-
Notifications
You must be signed in to change notification settings - Fork 4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
l2 imp of AWS::CloudFormation::ResourceVersion
- CF type https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudformation-resourceversion.html - creates log group + log access role if not provided - param documentation taken from cloudformation docs
- Loading branch information
1 parent
a928748
commit d185888
Showing
3 changed files
with
182 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
export * from './cloud-formation-capabilities'; | ||
export * from './custom-resource'; | ||
export * from './nested-stack'; | ||
export * from './resource-version'; | ||
|
||
// AWS::CloudFormation CloudFormation Resources: | ||
export * from './cloudformation.generated'; |
110 changes: 110 additions & 0 deletions
110
packages/aws-cdk-lib/aws-cloudformation/lib/resource-version.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
import { Construct } from 'constructs'; | ||
import { CfnResourceVersion } from './cloudformation.generated'; | ||
import { IRole, Role, CompositePrincipal, ServicePrincipal, PolicyDocument, PolicyStatement, Effect } from '../../aws-iam'; | ||
import { ILogGroup, LogGroup, RetentionDays } from '../../aws-logs'; | ||
import { Asset } from '../../aws-s3-assets'; | ||
/** | ||
* logging configuration for handler | ||
*/ | ||
export interface ILogConfiguration { | ||
/** | ||
* The ARN of the role that CloudFormation should assume when sending log entries to CloudWatch logs. | ||
*/ | ||
readonly logRole?: IRole; | ||
/** | ||
* The Amazon CloudWatch logs group to which CloudFormation sends error logging information when invoking the type's handlers. | ||
*/ | ||
readonly logGroup?: ILogGroup; | ||
} | ||
|
||
/** | ||
* properties for ResourceVersion construct | ||
*/ | ||
export interface ResourceVersionProps { | ||
/** | ||
* The name of the resource being registered. | ||
* We recommend that resource names adhere to the following pattern: company_or_organization::service::type. | ||
*/ | ||
readonly typeName: string; | ||
/** | ||
* Logging configuration information for a resource. | ||
* @default if not provided, it will be auto generated | ||
*/ | ||
readonly logging?: ILogConfiguration; | ||
/** | ||
* Contains the resource project package that contains the necessary files for the resource you want to register. | ||
*/ | ||
readonly handler: Asset; | ||
/** | ||
* IAM role for CloudFormation to assume when invoking the resource. If your resource calls AWS APIs in any of its handlers, you must create an IAM execution role that includes the necessary permissions to call those AWS APIs, | ||
* and provision that execution role in your account. When CloudFormation needs to invoke the resource type handler, CloudFormation assumes this execution role to create a temporary session token, | ||
* which it then passes to the resource type handler, thereby supplying your resource type with the appropriate credentials. | ||
* @default no role will be passed to the resourceVersion | ||
*/ | ||
readonly executionRole?: IRole; | ||
} | ||
|
||
/** | ||
* L2 construct for https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudformation-resourceversion.html | ||
*/ | ||
export class ResourceVersion extends Construct { | ||
|
||
/** | ||
* resourceVersion resource created by this construct | ||
*/ | ||
public readonly resourceVersion: CfnResourceVersion; | ||
/** | ||
* logRole referenced by resourceVersion | ||
*/ | ||
public readonly logRole: IRole; | ||
/** | ||
* logGroup referenced by resourceVersion | ||
*/ | ||
public readonly logGroup: ILogGroup; | ||
|
||
constructor(scope: Construct, id: string, props: ResourceVersionProps) { | ||
super(scope, id); | ||
|
||
// default perms from https://github.com/aws-cloudformation/cloudformation-cli/blob/a73666d6b38099549c55f674748c095e0ef628ee/src/rpdk/core/data/managed-upload-infrastructure.yaml#L129 | ||
this.logRole = | ||
props.logging?.logRole ?? | ||
new Role(this, 'LogRole', { | ||
assumedBy: new CompositePrincipal( | ||
new ServicePrincipal('hooks.cloudformation.amazonaws.com'), | ||
new ServicePrincipal('resources.cloudformation.amazonaws.com'), | ||
), | ||
description: 'Role for CloudFormation Resource Version logging', | ||
inlinePolicies: { | ||
LogAndMetricsDeliveryRolePolicy: | ||
new PolicyDocument({ | ||
statements: [ | ||
new PolicyStatement({ | ||
effect: Effect.ALLOW, | ||
actions: ['cloudwatch:PutMetricData', 'cloudwatch:ListMetrics', 'logs:DescribeLogGroups'], | ||
resources: ['*'], | ||
}), | ||
], | ||
}), | ||
|
||
}, | ||
}); | ||
|
||
this.logGroup = | ||
props.logging?.logGroup ?? | ||
new LogGroup(this, 'LogGroup', { | ||
logGroupName: `/aws/cloudformation/${props.typeName.split('::').join('-')}`, | ||
retention: RetentionDays.TEN_YEARS, | ||
}); | ||
this.logGroup.grantWrite(this.logRole); | ||
|
||
this.resourceVersion = new CfnResourceVersion(this, 'CfnResourceVersion', { | ||
typeName: props.typeName, | ||
schemaHandlerPackage: props.handler.s3ObjectUrl, | ||
loggingConfig: { | ||
logRoleArn: this.logRole.roleArn, | ||
logGroupName: this.logGroup.logGroupName, | ||
}, | ||
executionRoleArn: props.executionRole?.roleArn, | ||
}); | ||
} | ||
} |
71 changes: 71 additions & 0 deletions
71
packages/aws-cdk-lib/aws-cloudformation/test/resource-version.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
import { join } from 'path'; | ||
import { Template } from '../../assertions'; | ||
import { Role, ServicePrincipal } from '../../aws-iam'; | ||
import { Asset } from '../../aws-s3-assets'; | ||
import { App, Stack } from '../../core'; | ||
import { ResourceVersion } from '../lib'; | ||
|
||
test('it creates the resource-version and its related resources', () => { | ||
const app = new App(); | ||
const stack = new Stack(app, 'Stack', { | ||
env: { account: '1234', region: 'testregion' }, | ||
}); | ||
const id = 'unittest'; | ||
const asset = new Asset(stack, 'SampleAsset', { | ||
path: join(__dirname, 'asset-directory-fixture'), | ||
}); | ||
const executionRole = new Role(stack, 'role', { | ||
assumedBy: new ServicePrincipal('unittest.amazonaws.com'), | ||
}); | ||
const typeName = 'UNIT::TEST::TEST'; | ||
const rv = new ResourceVersion(stack, id, { | ||
typeName, | ||
handler: asset, | ||
executionRole, | ||
}); | ||
|
||
// it should create the l1 resource | ||
Template.fromStack(stack).hasResourceProperties('AWS::CloudFormation::ResourceVersion', { | ||
TypeName: typeName, | ||
SchemaHandlerPackage: asset.s3ObjectUrl, | ||
LoggingConfig: { | ||
LogGroupName: { | ||
Ref: 'unittestLogGroup321F9C37', | ||
}, | ||
LogRoleArn: { | ||
'Fn::GetAtt': ['unittestLogRoleEC6FE6AD', 'Arn'], | ||
}, | ||
}, | ||
ExecutionRoleArn: { | ||
'Fn::GetAtt': ['roleC7B7E775', 'Arn'], | ||
}, | ||
}); | ||
|
||
// it should create the log group (if not provided) | ||
Template.fromStack(stack).hasResourceProperties('AWS::Logs::LogGroup', { | ||
LogGroupName: `/aws/cloudformation/${typeName.split('::').join('-')}`, | ||
}); | ||
|
||
// it should create the log delivery role (if not provided) | ||
Template.fromStack(stack).hasResourceProperties('AWS::IAM::Role', { | ||
AssumeRolePolicyDocument: { | ||
Statement: [ | ||
{ | ||
Action: 'sts:AssumeRole', | ||
Effect: 'Allow', | ||
Principal: { | ||
Service: 'hooks.cloudformation.amazonaws.com', | ||
}, | ||
}, | ||
{ | ||
Action: 'sts:AssumeRole', | ||
Effect: 'Allow', | ||
Principal: { | ||
Service: 'resources.cloudformation.amazonaws.com', | ||
}, | ||
}, | ||
], | ||
Version: '2012-10-17', | ||
}, | ||
}); | ||
}); |