|
| 1 | +import { Construct } from 'constructs'; |
| 2 | +import { CfnResourceVersion } from './cloudformation.generated'; |
| 3 | +import { IRole, Role, CompositePrincipal, ServicePrincipal, PolicyDocument, PolicyStatement, Effect } from '../../aws-iam'; |
| 4 | +import { ILogGroup, LogGroup, RetentionDays } from '../../aws-logs'; |
| 5 | +import { Asset } from '../../aws-s3-assets'; |
| 6 | +/** |
| 7 | + * logging configuration for handler |
| 8 | + */ |
| 9 | +export interface ILogConfiguration { |
| 10 | + /** |
| 11 | + * The ARN of the role that CloudFormation should assume when sending log entries to CloudWatch logs. |
| 12 | + */ |
| 13 | + readonly logRole?: IRole; |
| 14 | + /** |
| 15 | + * The Amazon CloudWatch logs group to which CloudFormation sends error logging information when invoking the type's handlers. |
| 16 | + */ |
| 17 | + readonly logGroup?: ILogGroup; |
| 18 | +} |
| 19 | + |
| 20 | +/** |
| 21 | + * properties for ResourceVersion construct |
| 22 | + */ |
| 23 | +export interface ResourceVersionProps { |
| 24 | + /** |
| 25 | + * The name of the resource being registered. |
| 26 | + * We recommend that resource names adhere to the following pattern: company_or_organization::service::type. |
| 27 | + */ |
| 28 | + readonly typeName: string; |
| 29 | + /** |
| 30 | + * Logging configuration information for a resource. |
| 31 | + * @default if not provided, it will be auto generated |
| 32 | + */ |
| 33 | + readonly logging?: ILogConfiguration; |
| 34 | + /** |
| 35 | + * Contains the resource project package that contains the necessary files for the resource you want to register. |
| 36 | + */ |
| 37 | + readonly handler: Asset; |
| 38 | + /** |
| 39 | + * 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, |
| 40 | + * 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, |
| 41 | + * which it then passes to the resource type handler, thereby supplying your resource type with the appropriate credentials. |
| 42 | + * @default no role will be passed to the resourceVersion |
| 43 | + */ |
| 44 | + readonly executionRole?: IRole; |
| 45 | +} |
| 46 | + |
| 47 | +/** |
| 48 | + * L2 construct for https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudformation-resourceversion.html |
| 49 | + */ |
| 50 | +export class ResourceVersion extends Construct { |
| 51 | + |
| 52 | + /** |
| 53 | + * resourceVersion resource created by this construct |
| 54 | + */ |
| 55 | + public readonly resourceVersion: CfnResourceVersion; |
| 56 | + /** |
| 57 | + * logRole referenced by resourceVersion |
| 58 | + */ |
| 59 | + public readonly logRole: IRole; |
| 60 | + /** |
| 61 | + * logGroup referenced by resourceVersion |
| 62 | + */ |
| 63 | + public readonly logGroup: ILogGroup; |
| 64 | + |
| 65 | + constructor(scope: Construct, id: string, props: ResourceVersionProps) { |
| 66 | + super(scope, id); |
| 67 | + |
| 68 | + // default perms from https://github.com/aws-cloudformation/cloudformation-cli/blob/a73666d6b38099549c55f674748c095e0ef628ee/src/rpdk/core/data/managed-upload-infrastructure.yaml#L129 |
| 69 | + this.logRole = |
| 70 | + props.logging?.logRole ?? |
| 71 | + new Role(this, 'LogRole', { |
| 72 | + assumedBy: new CompositePrincipal( |
| 73 | + new ServicePrincipal('hooks.cloudformation.amazonaws.com'), |
| 74 | + new ServicePrincipal('resources.cloudformation.amazonaws.com'), |
| 75 | + ), |
| 76 | + description: 'Role for CloudFormation Resource Version logging', |
| 77 | + inlinePolicies: { |
| 78 | + LogAndMetricsDeliveryRolePolicy: |
| 79 | + new PolicyDocument({ |
| 80 | + statements: [ |
| 81 | + new PolicyStatement({ |
| 82 | + effect: Effect.ALLOW, |
| 83 | + actions: ['cloudwatch:PutMetricData', 'cloudwatch:ListMetrics', 'logs:DescribeLogGroups'], |
| 84 | + resources: ['*'], |
| 85 | + }), |
| 86 | + ], |
| 87 | + }), |
| 88 | + |
| 89 | + }, |
| 90 | + }); |
| 91 | + |
| 92 | + this.logGroup = |
| 93 | + props.logging?.logGroup ?? |
| 94 | + new LogGroup(this, 'LogGroup', { |
| 95 | + logGroupName: `/aws/cloudformation/${props.typeName.split('::').join('-')}`, |
| 96 | + retention: RetentionDays.TEN_YEARS, |
| 97 | + }); |
| 98 | + this.logGroup.grantWrite(this.logRole); |
| 99 | + |
| 100 | + this.resourceVersion = new CfnResourceVersion(this, 'CfnResourceVersion', { |
| 101 | + typeName: props.typeName, |
| 102 | + schemaHandlerPackage: props.handler.s3ObjectUrl, |
| 103 | + loggingConfig: { |
| 104 | + logRoleArn: this.logRole.roleArn, |
| 105 | + logGroupName: this.logGroup.logGroupName, |
| 106 | + }, |
| 107 | + executionRoleArn: props.executionRole?.roleArn, |
| 108 | + }); |
| 109 | + } |
| 110 | +} |
0 commit comments