private CloudFrontWebDistribution generateCloudFront(RestApi api, string name)
        {
            var dist = new CloudFrontWebDistribution(this, name + "Distribution", new CloudFrontWebDistributionProps
            {
                PriceClass    = PriceClass.PRICE_CLASS_ALL,
                Comment       = name,
                OriginConfigs = new[] {
                    new SourceConfiguration {
                        Behaviors = new IBehavior[] {
                            new Behavior {
                                Compress          = true,
                                IsDefaultBehavior = true,
                                DefaultTtl        = Duration.Seconds(0)
                            }
                        },
                        CustomOriginSource = new CustomOriginConfig {
                            DomainName = api.RestApiId + ".execute-api.us-east-1.amazonaws.com", // lazy but quick
                            OriginPath = "/prod",
                        }
                    }
                }
            });

            new CfnOutput(this, name + "distId", new CfnOutputProps {
                Value = dist.DistributionDomainName
            });

            return(dist);
        }
        public StaticSiteOnS3WithCloudFront(Stack scope, string id, StaticSiteConstructProps props) : base(scope, id)
        {
            var fullDomain = $"{props.SiteSubDomain}.{props.DomainName}";

            var siteBucket = new Bucket(this, $"SiteBucket_{id}", new BucketProps
            {
                BucketName           = $"static-content-{fullDomain}",
                WebsiteIndexDocument = props.WebsiteIndexDocument,
                WebsiteErrorDocument = "error.html",
                PublicReadAccess     = true,
                RemovalPolicy        = RemovalPolicy.DESTROY
            });


            var distribution = new CloudFrontWebDistribution(this, $"SiteDistribution_{id}", new CloudFrontWebDistributionProps
            {
                AliasConfiguration = new AliasConfiguration()
                {
                    Names          = new string[] { fullDomain },
                    AcmCertRef     = props.CertificateArn,
                    SecurityPolicy = SecurityPolicyProtocol.TLS_V1_2_2019
                },

                //ViewerCertificate = ViewerCertificate.FromAcmCertificate(certificate), // this syntax doesn't seem to be quite ready for use yet
                OriginConfigs = new ISourceConfiguration[]
                {
                    new SourceConfiguration
                    {
                        S3OriginSource = new S3OriginConfig {
                            S3BucketSource = siteBucket
                        },
                        Behaviors = new Behavior[] { new Behavior()
                                                     {
                                                         IsDefaultBehavior = true
                                                     } }
                    }
                }
            });

            new ARecord(this, $"SiteAliasRecord_{id}", new ARecordProps
            {
                RecordName = fullDomain,
                Target     = RecordTarget.FromAlias(new CloudFrontTarget(distribution)),
                Zone       = props.Zone
            });

            new BucketDeployment(this, $"DeployWithInvalidation_{id}", new BucketDeploymentProps
            {
                Sources           = new ISource[] { Source.Asset(props.WebsiteFilesPath) },
                DestinationBucket = siteBucket,
                Distribution      = distribution,
                DistributionPaths = new string[] { "/*" }
            });

            scope.Log($"CloudFrontSite_{props.DomainName}", $"https://{fullDomain}");

            scope.Log($"StaticWebsiteBucket_{props.DomainName}", siteBucket.BucketName);
        }
        public WebApplicationStack(Construct parent, string id) : base(parent, id)
        {
            // Create a S3 bucket, with the given name and define the web index document as 'index.html'
            var bucket = new Bucket(this, "Bucket", new BucketProps
            {
                WebsiteIndexDocument = "index.html"
            });

            // Obtain the cloudfront origin access identity so that the s3 bucket may be restricted to it.
            var origin = new CfnCloudFrontOriginAccessIdentity(this, "BucketOrigin", new CfnCloudFrontOriginAccessIdentityProps {
                CloudFrontOriginAccessIdentityConfig = new {
                    comment = "mysfits-workshop"
                }
            });

            // Restrict the S3 bucket via a bucket policy that only allows our CloudFront distribution
            bucket.GrantRead(new CanonicalUserPrincipal(
                                 origin.AttrS3CanonicalUserId
                                 ));

            // Definition for a new CloudFront web distribution, which enforces traffic over HTTPS
            var cdn = new CloudFrontWebDistribution(this, "CloudFront", new CloudFrontWebDistributionProps
            {
                ViewerProtocolPolicy = ViewerProtocolPolicy.ALLOW_ALL,
                PriceClass           = PriceClass.PRICE_CLASS_ALL,
                OriginConfigs        = new SourceConfiguration[] {
                    new SourceConfiguration {
                        Behaviors = new Behavior[] {
                            new Behavior {
                                IsDefaultBehavior = true,
                                MaxTtl            = null,
                                AllowedMethods    = CloudFrontAllowedMethods.GET_HEAD_OPTIONS
                            }
                        },
                        OriginPath     = "/web",
                        S3OriginSource = new S3OriginConfig {
                            S3BucketSource         = bucket,
                            OriginAccessIdentityId = origin.Ref
                        }
                    }
                }
            }
                                                    );

            string currentPath = Directory.GetCurrentDirectory();

            // A CDK helper that takes the defined source directory, compresses it, and uploads it to the destination s3 bucket.
            new BucketDeployment(this, "DeployWebsite", new BucketDeploymentProps
            {
                Sources = new ISource[] {
                    Source.Asset(Path.Combine(currentPath, "../Web"))
                },
                DestinationBucket    = bucket,
                DestinationKeyPrefix = "web/",
                Distribution         = cdn,
                RetainOnDelete       = false,
            });

            // Create a CDK Output which details the URL for the CloudFront Distribtion URL.
            new CfnOutput(this, "CloudFrontURL", new CfnOutputProps
            {
                Description = "The CloudFront distribution URL",
                Value       = "http://" + cdn.DomainName
            });
        }
        // A simple construct that contains a collection of AWS S3 buckets.
        public StaticSiteConstruct(Construct scope, string id, StaticSiteConstructProps props) : base(scope, id)
        {
            var zone = HostedZone.FromLookup(this, "Zone", new HostedZoneProviderProps
            {
                DomainName = props.DomainName
            });

            var siteDomain = (string)($"{props.SiteSubDomain}.{props.DomainName}");

            new CfnOutput(this, "Site", new CfnOutputProps
            {
                Value = $"https://{siteDomain}"
            });

            var siteBucket = new Bucket(this, "SiteBucket", new BucketProps
            {
                BucketName           = siteDomain,
                WebsiteIndexDocument = "index.html",
                WebsiteErrorDocument = "error.html",
                PublicReadAccess     = true,

                // The default removal policy is RETAIN, which means that cdk destroy will not attempt to delete
                // the new bucket, and it will remain in your account until manually deleted. By setting the policy to
                // DESTROY, cdk destroy will attempt to delete the bucket, but will error if the bucket is not empty.
                RemovalPolicy = RemovalPolicy.DESTROY // NOT recommended for production code
            });

            new CfnOutput(this, "Bucket", new CfnOutputProps
            {
                Value = siteBucket.BucketName
            });

            var certificateArn = new DnsValidatedCertificate(this, "SiteCertificate", new DnsValidatedCertificateProps
            {
                DomainName = siteDomain,
                HostedZone = zone
            }).CertificateArn;

            new CfnOutput(this, "Certificate", new CfnOutputProps {
                Value = certificateArn
            });

            var behavior = new Behavior();

            behavior.IsDefaultBehavior = true;

            var distribution = new CloudFrontWebDistribution(this, "SiteDistribution", new CloudFrontWebDistributionProps
            {
                AliasConfiguration = new AliasConfiguration
                {
                    AcmCertRef     = certificateArn,
                    Names          = new string[] { siteDomain },
                    SslMethod      = SSLMethod.SNI,
                    SecurityPolicy = SecurityPolicyProtocol.TLS_V1_2016
                },
                OriginConfigs = new ISourceConfiguration[]
                {
                    new SourceConfiguration
                    {
                        S3OriginSource = new S3OriginConfig
                        {
                            S3BucketSource = siteBucket
                        },
                        Behaviors = new Behavior[] { behavior }
                    }
                }
            });

            new CfnOutput(this, "DistributionId", new CfnOutputProps
            {
                Value = distribution.DistributionId
            });

            new ARecord(this, "SiteAliasRecord", new ARecordProps
            {
                RecordName = siteDomain,
                Target     = RecordTarget.FromAlias(new CloudFrontTarget(distribution)),
                Zone       = zone
            });

            new BucketDeployment(this, "DeployWithInvalidation", new BucketDeploymentProps
            {
                Sources           = new ISource[] { Source.Asset("./site-contents") },
                DestinationBucket = siteBucket,
                Distribution      = distribution,
                DistributionPaths = new string[] { "/*" }
            });
        }
Beispiel #5
0
        public SpaStack(Construct scope, string id, SpaStackProps props) : base(scope, id, props)
        {
            //s3 bucket
            var bucket = new Bucket(this, $"{props.ServiceName}-bucket", new BucketProps
            {
                WebsiteIndexDocument = "index.html",
                Versioned            = true,
                BucketName           = props.ServiceName,
                RemovalPolicy        = RemovalPolicy.DESTROY
            });

            //cloudfront distribution
            var cloudFrontOai = new OriginAccessIdentity(this, $"{props.ServiceName}-oai", new OriginAccessIdentityProps
            {
                Comment = $"OAI for {props.ServiceName}."
            });

            var cloudfrontDist = new CloudFrontWebDistribution(this, $"{props.ServiceName}-cfd", new CloudFrontWebDistributionProps
            {
                ViewerCertificate = ViewerCertificate.FromAcmCertificate(
                    props.CloudFrontCert,
                    new ViewerCertificateOptions
                {
                    Aliases   = new [] { $"{props.SubDomain}.{props.HostedZoneName}" },
                    SslMethod = SSLMethod.SNI
                }),
                OriginConfigs = new ISourceConfiguration[]
                {
                    new SourceConfiguration
                    {
                        S3OriginSource = new S3OriginConfig
                        {
                            S3BucketSource       = bucket,
                            OriginAccessIdentity = cloudFrontOai
                        },
                        Behaviors = new IBehavior[]
                        {
                            new Behavior
                            {
                                IsDefaultBehavior = true,
                            }
                        }
                    }
                }
            });

            var cnameRecord = new CnameRecord(this, $"{props.ServiceName}CloudFrontCname", new CnameRecordProps
            {
                Zone = HostedZone.FromHostedZoneAttributes(this, "HostedZone", new HostedZoneAttributes
                {
                    ZoneName     = props.HostedZoneName,
                    HostedZoneId = props.HostedZoneId
                }),
                RecordName = props.SubDomain,
                DomainName = cloudfrontDist.DistributionDomainName
            });

            var cloudfrontS3Access = new PolicyStatement();

            cloudfrontS3Access.AddActions("s3:GetBucket*", "s3:GetObject*", "s3:List*");
            cloudfrontS3Access.AddResources(bucket.BucketArn);
            cloudfrontS3Access.AddResources($"{bucket.BucketArn}/*");
            cloudfrontS3Access.AddCanonicalUserPrincipal(cloudFrontOai.CloudFrontOriginAccessIdentityS3CanonicalUserId);

            bucket.AddToResourcePolicy(cloudfrontS3Access);

            //codebuild project

            var codeBuildProject = new Project(this, $"{props.ServiceName}-codeBuild-project", new ProjectProps
            {
                Vpc         = props.Vpc,
                ProjectName = props.ServiceName,
                Environment = new BuildEnvironment
                {
                    BuildImage = LinuxBuildImage.STANDARD_4_0,
                },
                Source               = Source.GitHub(props.GitHubSourceProps),
                BuildSpec            = BuildSpec.FromSourceFilename(props.BuildSpecFile),
                EnvironmentVariables = new Dictionary <string, IBuildEnvironmentVariable>
                {
                    { "SPA_DIRECTORY", new BuildEnvironmentVariable {
                          Value = props.SpaDirectory
                      } },
                    { "S3_BUCKET", new BuildEnvironmentVariable {
                          Value = bucket.BucketName
                      } },
                    { "CLOUDFRONT_ID", new BuildEnvironmentVariable {
                          Value = cloudfrontDist.DistributionId
                      } },
                    { "API_URL", new BuildEnvironmentVariable {
                          Value = props.ApiUrl
                      } }
                }
            });

            // iam policy to push your build to S3
            codeBuildProject.AddToRolePolicy(
                new PolicyStatement(new PolicyStatementProps
            {
                Effect    = Effect.ALLOW,
                Resources = new[] { bucket.BucketArn, $"{bucket.BucketArn}/*" },
                Actions   = new[]
                {
                    "s3:GetBucket*",
                    "s3:List*",
                    "s3:GetObject*",
                    "s3:DeleteObject",
                    "s3:PutObject"
                }
            }));

            codeBuildProject.AddToRolePolicy(
                new PolicyStatement(new PolicyStatementProps
            {
                Effect    = Effect.ALLOW,
                Resources = new [] { "*" },
                Actions   = new []
                {
                    "cloudfront:CreateInvalidation",
                    "cloudfront:GetDistribution*",
                    "cloudfront:GetInvalidation",
                    "cloudfront:ListInvalidations",
                    "cloudfront:ListDistributions"
                }
            }));

            //codepipeline?
        }