import { CfnOutput, Stack, StackProps } from "aws-cdk-lib"; import { Construct } from "constructs"; // import * as sqs from 'aws-cdk-lib/aws-sqs'; // import * as route53 from 'aws-cdk-lib/aws-route53'; import * as cloudfront from "aws-cdk-lib/aws-cloudfront"; import * as s3 from "aws-cdk-lib/aws-s3"; import * as iam from "aws-cdk-lib/aws-iam"; import * as acm from "aws-cdk-lib/aws-certificatemanager"; import * as cloudfront_origins from "aws-cdk-lib/aws-cloudfront-origins"; // import * as targets from 'aws-cdk-lib/aws-route53-targets'; import * as s3deploy from "aws-cdk-lib/aws-s3-deployment"; import { Effect } from "aws-cdk-lib/aws-iam"; // import * as lambda from "aws-cdk-lib/aws-lambda"; // import { AssetCode, Function } from "aws-cdk-lib/aws-lambda"; // import { // LambdaIntegration, // MethodLoggingLevel, // RestApi, // } from "aws-cdk-lib/aws-apigateway"; export class DevConsoleStack extends Stack { constructor(scope: Construct, id: string, props?: StackProps) { super(scope, id, props); const siteDomain = "dev.assets.developer.tech.gov.sg"; const siteDomainAlt = "dev.assets.developer.gov.sg"; // const zone = route53.HostedZone.fromLookup(this, 'HostedZone', { domainName: "developer.tech.gov.sg" }); const cloudfrontOAI = new cloudfront.OriginAccessIdentity( this, "cloudfront-OAI", { comment: `OAI for ${id}`, } ); new CfnOutput(this, "Site", { value: "https://" + siteDomain }); const siteBucket = new s3.Bucket(this, "dev-console-systems-dev-bucket", { bucketName: siteDomain, publicReadAccess: false, blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL, cors: [ { allowedMethods: [ s3.HttpMethods.GET, s3.HttpMethods.POST, s3.HttpMethods.PUT, s3.HttpMethods.DELETE, ], allowedOrigins: ["*"], allowedHeaders: ["*"], }, ], }); // Grant access to cloudfront siteBucket.addToResourcePolicy( new iam.PolicyStatement({ effect: Effect.ALLOW, actions: ["s3:*Object"], resources: [siteBucket.arnForObjects("*")], principals: [ new iam.CanonicalUserPrincipal( cloudfrontOAI.cloudFrontOriginAccessIdentityS3CanonicalUserId ), ], }) ); new CfnOutput(this, "Bucket", { value: siteBucket.bucketName }); // Arn of certificate is hard coded here. DNS is registered in GSIB and is pointing to cloudfront. const certificate = acm.Certificate.fromCertificateArn( this, "1ee92b31-738a-4564-b4bb-b0edbf278dc4", "arn:aws:acm:us-east-1:781908166519:certificate/1ee92b31-738a-4564-b4bb-b0edbf278dc4" ); new CfnOutput(this, "Certificate", { value: certificate.certificateArn }); // CloudFront distribution const distribution = new cloudfront.Distribution( this, "dev-console-systems-cf-dev-dist", { certificate: certificate, domainNames: [siteDomain, siteDomainAlt], minimumProtocolVersion: cloudfront.SecurityPolicyProtocol.TLS_V1_2_2021, defaultBehavior: { origin: new cloudfront_origins.S3Origin(siteBucket, { originAccessIdentity: cloudfrontOAI, }), compress: true, allowedMethods: cloudfront.AllowedMethods.ALLOW_GET_HEAD_OPTIONS, viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS, }, } ); new CfnOutput(this, "DistributionId", { value: distribution.distributionId, }); // Deploy site contents to S3 bucket new s3deploy.BucketDeployment(this, "DeployWithInvalidation", { sources: [s3deploy.Source.asset("./s3-asset-source")], destinationBucket: siteBucket, // Invalidation distribution, distributionPaths: ["/*"], }); // Portion to get json files from github and inject into s3 below is commented out first // // Lambda Policy // const lambdaPolicyStatements = [ // new iam.PolicyStatement({ // effect: Effect.ALLOW, // actions: [ // "s3:ListBucket", // "s3:DeleteObject", // "s3:PutObject", // "s3:GetObject", // ], // resources: [siteBucket.bucketArn, siteBucket.bucketArn + "/*"], // }), // new iam.PolicyStatement({ // effect: Effect.ALLOW, // actions: [ // "cloudfront:CreateInvalidation", // "cloudfront:GetInvalidation", // "cloudfront:ListInvalidations", // ], // resources: [ // `arn:aws:cloudfront::${distribution.env.account}:distribution/${distribution.distributionId}`, // ], // }), // ]; // // Lambda Function // const lambdaFunction = new Function( // this, // "dev-console-products-info-handler", // { // runtime: lambda.Runtime.NODEJS_14_X, // initialPolicy: lambdaPolicyStatements, // handler: "products-info-handler.handler", // code: new AssetCode(`./infra/lambda`), // memorySize: 128, // timeout: Duration.seconds(10), // environment: { // BUCKET: siteBucket.bucketName, // }, // } // ); // // lambdaFunction.role?.attachInlinePolicy( // // new iam.Policy(this, 'products-info-handler-policy', { // // document: lambdaPolicy // // }) // // ) // // Api Gateway // const restApi = new RestApi(this, this.stackName + "RestApi", { // deployOptions: { // stageName: "dev", // metricsEnabled: true, // loggingLevel: MethodLoggingLevel.INFO, // dataTraceEnabled: true, // }, // }); // restApi.root.addMethod("GET", new LambdaIntegration(lambdaFunction, {})); } }