Skip to content
This repository has been archived by the owner on Jun 29, 2022. It is now read-only.

Commit

Permalink
Removes cdk-iam-floyd as ddependecy (#31)
Browse files Browse the repository at this point in the history
* removes cdk-iam-floyd from dependencies

* limit jsii version to last compatible

* update versiopn for next release

* normalize imports

* combine test steps: deploy & destroy

* ignore tsconfig.tsbuildinfo
  • Loading branch information
udondan authored Apr 20, 2022
1 parent 76837f9 commit d71298d
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 102 deletions.
8 changes: 1 addition & 7 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,7 @@ jobs:
chmod 777 $GITHUB_WORKSPACE/lambda --recursive
- name: Deploy
run: cd test && make deploy
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

- name: Destroy
run: cd test && make DESTROY
run: cd test && make deploy DESTROY
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ lambda/*
**/*.d.ts
**/cdk.out
**/package-lock.json
tsconfig.tsbuildinfo
46 changes: 22 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ For TypeScript/NodeJS, add these to your `dependencies` in `package.json`. For P

- cdk-ssm-document
- aws-cdk-lib (^2.0.0)
- cdk-iam-floyd (^0.300.0)
- constructs (^10.0.0)

## CDK compatibility
Expand Down Expand Up @@ -140,41 +139,39 @@ export class TestStack extends cdk.Stack {
### Creating a distributor package

```typescript
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { aws_iam, aws_s3, aws_s3_deployment, Stack, StackProps } from 'aws-cdk-lib';
import { Document } from 'cdk-ssm-document';
import * as s3deploy from 'aws-cdk-lib/aws-s3-deployment';
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as statement from 'cdk-iam-floyd';
import { Construct } from 'constructs';
import fs = require('fs');
import path = require('path');


export class TestStack extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props: cdk.StackProps) {
export class TestStack extends Stack {
constructor(scope: Construct, id: string, props: StackProps) {
super(scope, id, props);

const bucketName = `${cdk.Stack.of(this).account}-cdk-ssm-document-storage`;
const bucket = new s3.Bucket(this, 'DistributorPackages', {
const bucketName = `${Stack.of(this).account}-cdk-ssm-document-storage`;
const bucket = new aws_s3.Bucket(this, 'DistributorPackages', {
bucketName: bucketName,
});
const packageDeploy = new s3deploy.BucketDeployment(this, 'distribution-packages', {
sources: [s3deploy.Source.asset('../location/to/distributor/packages')],
destinationBucket: bucket
});
const packageDeploy = new aws_s3_deployment.BucketDeployment(
this,
'distribution-packages',
{
sources: [aws_s3_deployment.Source.asset('../location/to/distributor/packages')],
destinationBucket: bucket,
}
);

file = path.join(
const file = path.join(
__dirname,
'../location/to/distributor/packages/v1/manifest.json'
);
const docE = new Document(this, `SSM-Distribution-Package`, {
const doc = new Document(this, `SSM-Distribution-Package`, {
documentType: 'Package',
name: 'Test-Distribution-Package',
content: fs.readFileSync(file).toString(),
versionName: '1.0-Custom-Name',
attachments: [
{ key: "SourceUrl", values: [`s3://${bucketName}/v1`] }
]
attachments: [{ key: 'SourceUrl', values: [`s3://${bucketName}/v1`] }],
});

/**
Expand All @@ -193,14 +190,15 @@ export class TestStack extends cdk.Stack {
* ```
*/
doc.lambda.role?.addToPrincipalPolicy(
new statement.S3() //
.allow()
.toGetObject()
.onObject(bucket.bucketName, '*')
new aws_iam.PolicyStatement({
actions: ['s3:GetObject'],
resources: [`${bucket.arnForObjects('*')}`],
})
);
doc.node.addDependency(packageDeploy);
}
}

```

## Deploying many documents in a single stack
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.1.0
3.1.1
125 changes: 77 additions & 48 deletions lib/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
import cdk = require('aws-cdk-lib');
import iam = require('aws-cdk-lib/aws-iam');
import lambda = require('aws-cdk-lib/aws-lambda');
import * as statement from 'cdk-iam-floyd';
import {
Annotations,
aws_iam,
aws_lambda,
CustomResource,
Duration,
ITaggable,
Lazy,
Stack,
StackProps,
TagManager,
TagType,
} from 'aws-cdk-lib';
import { Construct } from 'constructs';
import yaml = require('js-yaml');
import path = require('path');
Expand Down Expand Up @@ -143,7 +152,7 @@ export interface DocumentContent {
/**
* Definition of the SSM document
*/
export interface DocumentProps extends cdk.StackProps {
export interface DocumentProps extends StackProps {
/**
* Defines if the default version should be updated to the latest version on document updates
*
Expand Down Expand Up @@ -191,7 +200,7 @@ export interface DocumentProps extends cdk.StackProps {
/**
* An SSM document
*/
export class Document extends Construct implements cdk.ITaggable {
export class Document extends Construct implements ITaggable {
/**
* Name of the document
*/
Expand All @@ -200,28 +209,28 @@ export class Document extends Construct implements cdk.ITaggable {
/**
* Resource tags
*/
public readonly tags: cdk.TagManager;
public readonly tags: TagManager;

/**
* The lambda function that is created
*/
public readonly lambda: lambda.IFunction;
public readonly lambda: aws_lambda.IFunction;

/**
* Defines a new SSM document
*/
constructor(scope: Construct, id: string, props: DocumentProps) {
super(scope, id);

this.tags = new cdk.TagManager(cdk.TagType.MAP, 'Custom::SSM-Document');
this.tags = new TagManager(TagType.MAP, 'Custom::SSM-Document');
this.tags.setTag(createdByTag, ID);

const stack = cdk.Stack.of(this).stackName;
const stack = Stack.of(this).stackName;
this.lambda = this.ensureLambda();
const name = this.fixDocumentName(props.name);

if (name.length < 3 || name.length > 128) {
cdk.Annotations.of(this).addError(
Annotations.of(this).addError(
`SSM Document name ${name} is invalid. The name must be between 3 and 128 characters.`
);
return;
Expand All @@ -233,7 +242,7 @@ export class Document extends Construct implements cdk.ITaggable {
content = yaml.safeLoad(content) as DocumentContent;
}

const document = new cdk.CustomResource(this, `SSM-Document-${name}`, {
const document = new CustomResource(this, `SSM-Document-${name}`, {
serviceToken: this.lambda.functionArn,
resourceType: resourceType,
properties: {
Expand All @@ -245,7 +254,7 @@ export class Document extends Construct implements cdk.ITaggable {
attachments: props.attachments,
versionName: props.versionName,
StackName: stack,
tags: cdk.Lazy.any({
tags: Lazy.any({
produce: () => this.tags.renderTags(),
}),
},
Expand All @@ -255,59 +264,79 @@ export class Document extends Construct implements cdk.ITaggable {
this.name = document.getAttString('Name');
}

private ensureLambda(): lambda.Function {
const stack = cdk.Stack.of(this);
private ensureLambda(): aws_lambda.Function {
const stack = Stack.of(this);
const constructName = 'SSM-Document-Manager-Lambda';
const existing = stack.node.tryFindChild(constructName);
if (existing) {
return existing as lambda.Function;
return existing as aws_lambda.Function;
}

const policy = new iam.ManagedPolicy(stack, 'SSM-Document-Manager-Policy', {
managedPolicyName: `${stack.stackName}-${cleanID}`,
description: `Used by Lambda ${cleanID}, which is a custom CFN resource, managing SSM documents`,
statements: [
new statement.Ssm().allow().toListDocuments().toListTagsForResource(),
new statement.Ssm()
.allow()
.toCreateDocument()
.toAddTagsToResource()
.ifAwsRequestTag(createdByTag, ID),
new statement.Ssm()
.allow()
.toDeleteDocument()
.toDescribeDocument()
.toGetDocument()
.toListDocumentVersions()
.toModifyDocumentPermission()
.toUpdateDocument()
.toUpdateDocumentDefaultVersion()
.toAddTagsToResource()
.toRemoveTagsFromResource()
.ifResourceTag(createdByTag, ID),
],
});

const role = new iam.Role(stack, 'SSM-Document-Manager-Role', {
const policy = new aws_iam.ManagedPolicy(
stack,
'SSM-Document-Manager-Policy',
{
managedPolicyName: `${stack.stackName}-${cleanID}`,
description: `Used by Lambda ${cleanID}, which is a custom CFN resource, managing SSM documents`,
statements: [
new aws_iam.PolicyStatement({
actions: ['ssm:ListDocuments', 'ssm:ListTagsForResource'],
resources: ['*'],
}),
new aws_iam.PolicyStatement({
actions: ['ssm:AddTagsToResource', 'ssm:CreateDocument'],
resources: ['*'],
conditions: {
StringLike: {
'aws:RequestTag/CreatedByCfnCustomResource': ID,
},
},
}),
new aws_iam.PolicyStatement({
actions: [
'ssm:AddTagsToResource',
'ssm:DeleteDocument',
'ssm:DescribeDocument',
'ssm:GetDocument',
'ssm:ListDocumentVersions',
'ssm:ModifyDocumentPermission',
'ssm:RemoveTagsFromResource',
'ssm:UpdateDocument',
'ssm:UpdateDocumentDefaultVersion',
],
resources: ['*'],
conditions: {
StringLike: {
'ssm:ResourceTag/CreatedByCfnCustomResource': ID,
},
},
}),
],
}
);

const role = new aws_iam.Role(stack, 'SSM-Document-Manager-Role', {
roleName: `${stack.stackName}-${cleanID}`,
description: `Used by Lambda ${cleanID}, which is a custom CFN resource, managing SSM documents`,
assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),
assumedBy: new aws_iam.ServicePrincipal('lambda.amazonaws.com'),
managedPolicies: [
policy,
iam.ManagedPolicy.fromAwsManagedPolicyName(
aws_iam.ManagedPolicy.fromAwsManagedPolicyName(
'service-role/AWSLambdaBasicExecutionRole'
),
],
});

const fn = new lambda.Function(stack, constructName, {
const fn = new aws_lambda.Function(stack, constructName, {
functionName: `${stack.stackName}-${cleanID}`,
role: role,
description: 'Custom CFN resource: Manage SSM Documents',
runtime: lambda.Runtime.NODEJS_14_X,
runtime: aws_lambda.Runtime.NODEJS_14_X,
handler: 'index.handler',
code: lambda.Code.fromAsset(path.join(__dirname, '../lambda/code.zip')),
timeout: cdk.Duration.minutes(lambdaTimeout),
code: aws_lambda.Code.fromAsset(
path.join(__dirname, '../lambda/code.zip')
),
timeout: Duration.minutes(lambdaTimeout),
});

return fn;
Expand Down
6 changes: 2 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,19 +60,17 @@
"aws-lambda": "^1.0.7",
"aws-sdk": "^2.1069.0",
"constructs": "^10.0.0",
"jsii": "^1.52.1",
"jsii-pacmak": "^1.52.1",
"jsii": "1.55.1",
"jsii-pacmak": "1.55.1",
"ts-node": "^10.4.0",
"typescript": "^4.5.5",
"cdk-iam-floyd": "^0.300.0",
"aws-cloudformation-custom-resource": "^2.0.1"
},
"dependencies": {
"js-yaml": "^3.14.1"
},
"peerDependencies": {
"aws-cdk-lib": "^2.0.0",
"cdk-iam-floyd": "^0.300.0",
"constructs": "^10.0.0"
},
"bundleDependencies": [
Expand Down
Loading

0 comments on commit d71298d

Please sign in to comment.