UNPKG

mira

Version:

NearForm Accelerator for Cloud Native Serverless AWS

104 lines (93 loc) 4.24 kB
import { CfnOutput, Construct, Duration } from '@aws-cdk/core' import { Topic } from '@aws-cdk/aws-sns' import { SingletonFunction, Runtime, AssetCode } from '@aws-cdk/aws-lambda' import { FollowMode } from '@aws-cdk/assets' import { SnsEventSource } from '@aws-cdk/aws-lambda-event-sources' import { AccountPrincipal, CompositePrincipal, Effect, ManagedPolicy, PolicyStatement, Role, ServicePrincipal } from '@aws-cdk/aws-iam' import { MiraConfig } from '../../../../config/mira-config' import path from 'path' import { MiraStack } from '../../../stack' export class Route53Manager extends MiraStack { constructor (parent: Construct) { const id = MiraConfig.getBaseStackName('Route53Manager') super(parent, id) const account = MiraConfig.getEnvironment() const { hostedZoneId } = MiraConfig.getDomainConfig() if (!hostedZoneId) { throw new Error('Cannot find hostedZoneId in config.') } const allowedPrincipals = MiraConfig.getDomainAllowedPrincipals().map(account => new AccountPrincipal(account.env.account)) const domainSubscriptionTopic = new Topic(this, 'DomainSubscriptionTopic', { displayName: 'Domain Subscription Topic', topicName: MiraConfig.getBaseStackName(`${account.name}-DomainSubscriptionTopic`) }) domainSubscriptionTopic.addToResourcePolicy(new PolicyStatement({ principals: allowedPrincipals, effect: Effect.ALLOW, resources: [domainSubscriptionTopic.topicArn], actions: ['sns:Publish'] })) const code = new AssetCode(path.join(__dirname, '..', '..', '..', '..', 'lambdas'), { follow: FollowMode.ALWAYS }) const permissionsBoundary = ManagedPolicy.fromManagedPolicyName(this, 'Route53PermissionsBoundary', MiraConfig.calculateSharedResourceName('Route53ManagerPolicyBoundary')) const DomainManagerRole = new Role(this, 'Route53ManagerRole', { assumedBy: new ServicePrincipal('lambda.amazonaws.com'), permissionsBoundary }) DomainManagerRole.addToPolicy(new PolicyStatement({ effect: Effect.ALLOW, resources: [`arn:aws:route53:::hostedzone/${hostedZoneId}`], actions: ['route53:ChangeResourceRecordSets'] })) DomainManagerRole.addToPolicy(new PolicyStatement({ effect: Effect.ALLOW, resources: ['*'], actions: ['acm:RequestCertificate', 'acm:DescribeCertificate', 'acm:DeleteCertificate', 'acm:ListCertificates'] })) DomainManagerRole.addToPolicy(new PolicyStatement({ effect: Effect.ALLOW, resources: ['*'], actions: ['route53:GetChange', 'route53:ListResourceRecordSets'] })) DomainManagerRole.addManagedPolicy(ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSLambdaBasicExecutionRole')) const Route53ManagerLambda = new SingletonFunction(this, 'Route53ManagerLambda', { code, handler: 'route53-manager.handler', runtime: Runtime.NODEJS_10_X, timeout: Duration.minutes(5), uuid: '934dd096-1586-46c4-92a0-0dd1239e993f', environment: { HOSTED_ZONE: hostedZoneId }, role: DomainManagerRole }) Route53ManagerLambda.addEventSource(new SnsEventSource(domainSubscriptionTopic)) new CfnOutput(this, 'domainSubscriptionTopicArn', { value: domainSubscriptionTopic.topicArn }) const allowedCompositePrincipals = new CompositePrincipal( ...MiraConfig .getDomainAllowedPrincipals() .map(account => new AccountPrincipal(account.env.account)) ) const CrossAccountDomainManagerRole = new Role(this, 'CrossAccountDomainManagerRole', { assumedBy: allowedCompositePrincipals, roleName: MiraConfig.getBaseStackName('DomainManager-Role'), permissionsBoundary }) CrossAccountDomainManagerRole.addToPolicy(new PolicyStatement({ effect: Effect.ALLOW, resources: [`arn:aws:route53:::hostedzone/${hostedZoneId}`], actions: ['route53:ChangeResourceRecordSets'] })) CrossAccountDomainManagerRole.addToPolicy(new PolicyStatement({ effect: Effect.ALLOW, resources: ['*'], actions: ['route53:GetChange'] })) new CfnOutput(this, 'CrossAccountDomainManagerRoleArn', { value: CrossAccountDomainManagerRole.roleArn }) } }