diff --git a/prerequisites.sh b/prerequisites.sh new file mode 100755 index 0000000..a082fe2 --- /dev/null +++ b/prerequisites.sh @@ -0,0 +1,319 @@ +#!/bin/bash +set -euo pipefail + +RED='\033[0;31m' +YELLOW='\033[1;33m' +NC='\033[0m' + +function _logger() { + echo -e "$(date) ${YELLOW}[*] $@ ${NC}" +} + +######################################################### +######################################################### +######################################################### + +function prerequisites_with_brew() { + echo "[BEGIN][MacOS] prerequisites_with_brew() ..." + + brew install jq git wget unzip bash-completion gettext moreutils + + curl "https://awscli.amazonaws.com/AWSCLIV2.pkg" -o "AWSCLIV2.pkg" + sudo installer -pkg AWSCLIV2.pkg -target / + rm ./AWSCLIV2.pkg + + brew install node@14 + sudo npm install -g aws-cdk + + ### TODO Installing Python3 & Pip3 + + # _logger "[+] Upgrade Python 3.8" + # brew install python@3.8 + # echo 'export PATH="/usr/local/opt/python@3.8/bin:$PATH"' >> ~/.bash_profile + # echo 'export PATH="/usr/local/opt/python@3.8/bin/pip3:$PATH"' >> ~/.bash_profile + # echo 'alias python="python3.8"' >> ~/.bash_profile + # echo 'alias python3="python3.8"' >> ~/.bash_profile + # echo 'alias pip="pip3"' >> ~/.bash_profile + # source ~/.bash_profile + ## echo 'export PATH="/usr/local/opt/python@3.8/bin:$PATH"' >> ~/.zshrc + ## echo 'export PATH="/usr/local/opt/python@3.8/bin/pip3:$PATH"' >> ~/.zshrc + ## echo 'alias python="python3.8"' >> ~/.zshrc + ## echo 'alias python3="python3.8"' >> ~/.zshrc + ## echo 'alias pip="pip3"' >> ~/.zshrc + ## source ~/.zshrc + ## _logger "[+] Upgrading Python pip and setuptools" + ## python3 -m pip install --upgrade pip setuptools --user + + ### TODO Installing EKS tools + # brew install kubectl + # brew tap weaveworks/tap + # brew install weaveworks/tap/eksctl + ## brew upgrade eksctl && brew link --overwrite eksctl + + # curl -sSL https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash + # brew install fluxctl + ## brew link --overwrite fluxctl + + ## Install k9s + # brew install k9s + + echo "[END][MacOS] prerequisites_with_brew() !!!" +} + +function prerequisites_with_apt() { + echo "[BEGIN][Ubuntu] prerequisites_with_apt() ..." + + sudo apt update && sudo apt upgrade + sudo apt install -y jq git wget unzip bash-completion gettext moreutils + + curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" + unzip awscliv2.zip + sudo ./aws/install + rm ./awscliv2.zip + + sudo apt install python3.8 + echo 'alias python="python3.8"' >> ~/.bash_profile + echo 'alias python3="python3.8"' >> ~/.bash_profile + echo 'alias pip="pip3.8"' >> ~/.bash_profile + echo 'alias pip3="pip3.8"' >> ~/.bash_profile + source ~/.bash_profile + _logger "[+] Upgrading Python pip and setuptools" + python3 -m pip install --upgrade pip setuptools --user + + curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash - + sudo apt install -y nodejs --force + npm i -g aws-cdk --force + + sudo curl --silent --location -o /usr/local/bin/kubectl \ + https://amazon-eks.s3.us-west-2.amazonaws.com/1.17.7/2020-07-08/bin/linux/amd64/kubectl + sudo chmod +x /usr/local/bin/kubectl + + curl --silent --location "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp + sudo mv -v /tmp/eksctl /usr/local/bin + + curl -sSL https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash + + sudo curl --silent --location -o /usr/local/bin/fluxctl "https://github.com/fluxcd/flux/releases/download/1.20.2/fluxctl_linux_amd64" + sudo chmod +x /usr/local/bin/fluxctl + + ## Install k9s + installing_k9s + + # upgrade_ebs_storage_Ubuntu + + echo "[END][Ubuntu] prerequisites_with_apt() !!!" +} + +function prerequisites_with_yum() { + echo "[BEGIN][CenOS/RedHat/AmazonLinux] prerequisites_with_yum() ..." + + sudo yum -y update + sudo yum install -y jq git wget unzip bash-completion gettext moreutils + sudo yum groupinstall "Development Tools" -y + sudo yum install openssl-devel bzip2-devel libffi-devel -y + + # AWS CLI + CHECKER_AWS=$(aws --version) + if [[ $CHECKER_AWS != *"aws-cli/2"* ]]; + then + curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" + unzip -d /opt/ -o awscliv2.zip + cd /opt && sudo ./aws/install + else _logger "[+] Aws CLI installed" + fi + + curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash - + sudo yum install -y nodejs + npm i -g aws-cdk + + sudo curl --silent --location -o /usr/local/bin/kubectl \ + https://amazon-eks.s3.us-west-2.amazonaws.com/1.17.7/2020-07-08/bin/linux/amd64/kubectl + sudo chmod +x /usr/local/bin/kubectl + + curl --silent --location "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp + sudo mv -v /tmp/eksctl /usr/local/bin + + sudo curl --silent --location -o /usr/local/bin/fluxctl "https://github.com/fluxcd/flux/releases/download/1.20.2/fluxctl_linux_amd64" + sudo chmod +x /usr/local/bin/fluxctl + + curl -sSL https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash + + ## Install k9s + installing_k9s + + # upgrade_ebs_storage_AmazonLinux + + echo "[END][CenOS/RedHat/AmazonLinux] prerequisites_with_yum() ..." +} + +function prerequisites_with_windows() { + echo "[BEGIN] prerequisites_with_windows() ..." + + ## TODO Installing Windows + + echo "[END] prerequisites_with_windows() !!!" +} + +function upgrade_ebs_storage_AmazonLinux() { + _logger "[+] AMZ-Linux2/CenOS EBS Extending a Partition on a T2/T3 Instance" + sudo file -s /dev/nvme?n* + sudo growpart /dev/nvme0n1 1 + lsblk + echo "Extend an ext2/ext3/ext4 file system" + sudo yum install xfsprogs + sudo resize2fs /dev/nvme0n1p1 + df -h +} + +function upgrade_ebs_storage_Ubuntu() { + _logger "[+] Ubuntu EBS Extending a Partition on an EC2 Instance" + sudo growpart /dev/xvda 1 + lsblk + echo "Extend an EBS Volumne size" + sudo resize2fs /dev/xvda1 + df -hT +} + +function installing_k9s() { + ## Install k9s + K9S_VERSION=0.23.1 + K9S_TAR_FILENAME=k9s_$(uname -s)_$(uname -m).tar.gz + curl -o /tmp/$K9S_TAR_FILENAME -L -k https://github.com/derailed/k9s/releases/download/v${K9S_VERSION}/$K9S_TAR_FILENAME + tar -xvf /tmp/$K9S_TAR_FILENAME -C /tmp/ + sudo mv /tmp/k9s /usr/local/bin/k9s + sudo chmod +x /usr/local/bin/k9s +} + +function prerequisites() { + ## DEBUG purpose + # processor=$(uname -m) + # if [ "$processor" == "x86_64" ]; then + # arch="amd64" + # else + # arch="386" + # fi + # case "$(uname -s)" in + # Darwin*) + # os="darwin_${arch}" + # ;; + # MINGW64*) + # os="windows_${arch}" + # ;; + # MSYS_NT*) + # os="windows_${arch}" + # ;; + # *) + # os="linux_${arch}" + # ;; + # esac + # echo "os=$os" + # echo -e "\n====================================================\n" + + ## FIXME: Prerequisites >> Windows + + echo "OSTYPE=$OSTYPE" + KERNEL_TYPE=linux + if [[ "$OSTYPE" == "linux-gnu"* ]]; then + echo "Linux OS" + + ## TODO: https://github.com/saltstack/salt-bootstrap/blob/develop/bootstrap-salt.sh + # # Let's test if the lsb_release binary is available + # rv=$(lsb_release >/dev/null 2>&1) + + # # shellcheck disable=SC2181 + # if [ $? -eq 0 ]; then + DISTRO_ID=$(lsb_release -si) + echo "DISTRO_ID=$DISTRO_ID" + if [[ "$DISTRO_ID" == "Ubuntu" ]]; then + _logger "[+] Install with apt" + prerequisites_with_apt + # sudo apt-get install -y apache2-utils jq gettext bash-completion + elif [ "$DISTRO_ID" = "AmazonAMI" ] || [ "$DISTRO_ID" = "Amazon" ]; then + ## FIXME CenOS / RedHat + _logger "[+] Install with yum" + prerequisites_with_yum + # sudo yum install -y jq gettext bash-completion + else + echo -e "${RED} ERROR: can't install package" + exit 1; + fi + # rv=$(lsb_release -sr) + # [ "${rv}" != "" ] && DISTRO_VERSION=$(__parse_version_string "$rv") + # elif [ -f /etc/lsb-release ]; then + # # We don't have the lsb_release binary, though, we do have the file it parses + # DISTRO_NAME=$(grep DISTRIB_ID /etc/lsb-release | sed -e 's/.*=//') + # rv=$(grep DISTRIB_RELEASE /etc/lsb-release | sed -e 's/.*=//') + # [ "${rv}" != "" ] && DISTRO_VERSION=$(__parse_version_string "$rv") + # fi + elif [[ "$OSTYPE" == "darwin"* ]]; then + KERNEL_TYPE=darwin + _logger "[+] Install with brew" + prerequisites_with_brew + # brew install jq wget + else + echo -e "${RED}Unsupport platform: $OSTYPE" + exit 1 + fi + # echo "kernel=$KERNEL_TYPE" +} + +function prerequisites_docker() { + echo "[BEGIN][Docker] prerequisites_with_docker ..." + + ## TODO + + echo "[END][Docker] prerequisites_with_docker !!!" +} + +function verify_prerequisites() { + echo "[BEGIN] verify_prerequisites() ..." + + echo "[x] Verify Git client": $(git --version) + echo "[x] Verify AWS CLI version 2": $(aws --version) + echo "[x] Verify Node.js": $(node --version) + echo "[x] Verify CDK": $(cdk --version) + # echo "[x] Verify Python": $(python -V) + # echo "[x] Verify Python3": $(python3 -V) + # echo "[x] Verify Pip": $(pip -V) + # echo "[x] Verify Pip3": $(pip3 -V) + # echo "[x] Verify kubectl": $(kubectl version --client) + # echo "[x] Verify eksctl": $(eksctl version) + # echo "[x] Verify helm3": $(helm version --short) + # echo "[x] Verify k9s": $(k9s version --short) + # echo "[x] Verify fluxctl": $(fluxctl version) + echo "[END] verify_prerequisites() !!!" +} + + +function main() { + started_time=$(date '+%d/%m/%Y %H:%M:%S') + echo + echo "#########################################################" + echo "[START] Environment Prerequisites - starting at ${started_time}" + echo "#########################################################" + echo + + # _logger "[+] Prerequisites & Getting Started" + prerequisites + + # _logger "[+] Prerequisites >> Docker" + # prerequisites_docker + + _logger "[+] Verify Prerequisites" + ### Installing AWS CDK tools: https://docs.aws.amazon.com/cdk/latest/guide/tools.html + verify_prerequisites + + # upgrade_ebs_storage_AmazonLinux + + ## FIXME + # aws eks update-kubeconfig --name eks-cluster + + ended_time=$(date '+%d/%m/%Y %H:%M:%S') + echo + echo "#########################################################" + echo -e "${RED} [FINISH] Environment Prerequisites - finished at ${ended_time} - ${started_time} ${NC}" + echo "#########################################################" + echo +} + +main diff --git a/s3-website/README.S3WebsiteConstruct.md b/s3-website/README.S3WebsiteConstruct.md new file mode 100644 index 0000000..30ff9d7 --- /dev/null +++ b/s3-website/README.S3WebsiteConstruct.md @@ -0,0 +1,137 @@ +# S3Website CDK Construct >> Omni-Channel + +This is an AWS CDK Construct to make deploying a single page website (React/Vue/Angular SPA) to AWS S3 behind SSL/Cloudfront as easy as 5 lines of code. + +## Installation and Usage + +```typescript +import cdk = require('@aws-cdk/core'); +import { S3WebsiteConstruct } from './s3-website-construct'; + +export class CdkStack extends cdk.Stack { + constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { + super(scope, id, props); + + new S3WebsiteConstruct(this, 'spaDeploy') + .createBasicSite({ + indexDoc: 'index.html', + websiteFolder: '../blog/dist/blog' + }); + + new S3WebsiteConstruct(this, 'cfDeploy') + .createSiteWithCloudfront({ + indexDoc: 'index.html', + websiteFolder: '../blog/dist/blog' + }); + } +} +``` + +## Advanced Usage + +### Auto Deploy From Hosted Zone Name + +If you purchased your domain through route 53 and already have a hosted zone then just use the name to deploy your site behind cloudfront. This handles the SSL cert and everything for you. + +```typescript +new S3WebsiteConstruct(this, 'spaDeploy', { encryptBucket: true }) + .createSiteFromHostedZone({ + zoneName: 'cdkpatterns.com', + indexDoc: 'index.html', + websiteFolder: '../website/dist/website' + }); + +``` + +### Custom Domain and SSL Certificates + +You can also pass the ARN for an SSL certification and your alias routes to cloudfront + +```typescript +import cdk = require('@aws-cdk/core'); +import { S3WebsiteConstruct } from './s3-website-construct'; + +export class CdkStack extends cdk.Stack { + constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { + super(scope, id, props); + + new SPADeploy(this, 'cfDeploy') + .createSiteWithCloudfront({ + indexDoc: '../blog/dist/blog', + certificateARN: 'arn:...', + cfAliases: ['www.alias.com'] + }); + } +} + +``` + +### Encrypted S3 Bucket + +Pass in one boolean to tell SPA Deploy to encrypt your website bucket + +```typescript +new S3WebsiteConstruct(this, 'cfDeploy', {encryptBucket: true}).createBasicSite({ + indexDoc: 'index.html', + websiteFolder: 'website' +}); + +``` + +### Custom Origin Behaviors + +Pass in an array of CloudFront Behaviors + +```typescript +new S3WebsiteConstruct(this, 'cfDeploy').createSiteWithCloudfront({ + indexDoc: 'index.html', + websiteFolder: 'website', + cfBehaviors: [ + { + isDefaultBehavior: true, + allowedMethods: cf.CloudFrontAllowedMethods.ALL, + forwardedValues: { + queryString: true, + cookies: { forward: 'all' }, + headers: ['*'], + }, + }, + { + pathPattern: '/virtual-path', + allowedMethods: cf.CloudFrontAllowedMethods.GET_HEAD, + cachedMethods: cf.CloudFrontAllowedCachedMethods.GET_HEAD, + }, + ], +}); +``` + +### Restrict Access to Known IPs + +Pass in a boolean and an array of IP addresses and your site is locked down! + +```typescript +new S3WebsiteConstruct(stack, 'spaDeploy', { + encryptBucket: true, + ipFilter: true, + ipList: ['1.1.1.1'] +}).createBasicSite({ + indexDoc: 'index.html', + websiteFolder: 'website' + }) +``` + +### Modifying S3 Bucket Created in Construct + +An object is now returned containing relevant artifacts created if you need to make any further modifications: + * The S3 bucket is present for all of the methods + * When a CloudFront Web distribution is created it will be present in the return object + +```typescript +export interface SPADeployment { + readonly websiteBucket: s3.Bucket, +} + +export interface SPADeploymentWithCloudFront extends SPADeployment { + readonly distribution: CloudFrontWebDistribution, +} +``` \ No newline at end of file diff --git a/s3-website/lib/acm-construct.ts b/s3-website/lib/acm-construct.ts new file mode 100644 index 0000000..5a7d39f --- /dev/null +++ b/s3-website/lib/acm-construct.ts @@ -0,0 +1,16 @@ +import { Construct } from '@aws-cdk/core'; +import { PolicyStatement, Effect, AnyPrincipal } from '@aws-cdk/aws-iam'; + +export class AcmConstruct extends Construct { + + /** Define new bucket variables here: */ + + constructor( scope: Construct, id: string) { + super(scope, id) + + /** + * FIXME + */ + + } +} \ No newline at end of file diff --git a/s3-website/lib/cloudfront-construct.ts b/s3-website/lib/cloudfront-construct.ts new file mode 100644 index 0000000..cc27e37 --- /dev/null +++ b/s3-website/lib/cloudfront-construct.ts @@ -0,0 +1,16 @@ +import { Construct } from '@aws-cdk/core'; +import { PolicyStatement, Effect, AnyPrincipal } from '@aws-cdk/aws-iam'; + +export class CloudfrontConstruct extends Construct { + + /** Define new bucket variables here: */ + + constructor( scope: Construct, id: string) { + super(scope, id) + + /** + * FIXME + */ + + } +} \ No newline at end of file diff --git a/s3-website/lib/route53-construct.ts b/s3-website/lib/route53-construct.ts new file mode 100644 index 0000000..dae8402 --- /dev/null +++ b/s3-website/lib/route53-construct.ts @@ -0,0 +1,16 @@ +import { Construct } from '@aws-cdk/core'; +import { PolicyStatement, Effect, AnyPrincipal } from '@aws-cdk/aws-iam'; + +export class Route53Construct extends Construct { + + /** Define new bucket variables here: */ + + constructor( scope: Construct, id: string) { + super(scope, id) + + /** + * FIXME + */ + + } +} \ No newline at end of file diff --git a/s3-website/lib/s3-website-construct.ts b/s3-website/lib/s3-website-construct.ts new file mode 100644 index 0000000..82c3c53 --- /dev/null +++ b/s3-website/lib/s3-website-construct.ts @@ -0,0 +1,257 @@ +import { + CloudFrontWebDistribution, + ViewerCertificate, + OriginAccessIdentity, + Behavior, + SSLMethod, + SecurityPolicyProtocol, + } from '@aws-cdk/aws-cloudfront'; + import { PolicyStatement } from '@aws-cdk/aws-iam'; + import { HostedZone, ARecord, RecordTarget } from '@aws-cdk/aws-route53'; + import { DnsValidatedCertificate } from '@aws-cdk/aws-certificatemanager'; + import { HttpsRedirect } from '@aws-cdk/aws-route53-patterns'; + import { CloudFrontTarget } from '@aws-cdk/aws-route53-targets'; + import cdk = require('@aws-cdk/core'); + import s3deploy= require('@aws-cdk/aws-s3-deployment'); + import s3 = require('@aws-cdk/aws-s3'); + + export interface SPADeployConfig { + readonly indexDoc:string, + readonly errorDoc?:string, + readonly websiteFolder: string, + readonly certificateARN?: string, + readonly cfBehaviors?: Behavior[], + readonly cfAliases?: string[], + readonly exportWebsiteUrlOutput?:boolean, + readonly exportWebsiteUrlName?: string, + readonly blockPublicAccess?:s3.BlockPublicAccess + readonly sslMethod?: SSLMethod, + readonly securityPolicy?: SecurityPolicyProtocol, + } + + export interface HostedZoneConfig { + readonly indexDoc:string, + readonly errorDoc?:string, + readonly cfBehaviors?: Behavior[], + readonly websiteFolder: string, + readonly zoneName: string, + readonly subdomain?: string, + } + + export interface SPAGlobalConfig { + readonly encryptBucket?:boolean, + readonly ipFilter?:boolean, + readonly ipList?:string[] + } + + export interface SPADeployment { + readonly websiteBucket: s3.Bucket, + } + + export interface SPADeploymentWithCloudFront extends SPADeployment { + readonly distribution: CloudFrontWebDistribution, + } + + export class S3WebsiteConstruct extends cdk.Construct { + globalConfig: SPAGlobalConfig; + + constructor(scope: cdk.Construct, id:string, config?:SPAGlobalConfig) { + super(scope, id); + + if (typeof config !== 'undefined') { + this.globalConfig = config; + } else { + this.globalConfig = { + encryptBucket: false, + ipFilter: false, + }; + } + } + + /** + * Helper method to provide a configured s3 bucket + */ + private getS3Bucket(config:SPADeployConfig, isForCloudFront: boolean) { + const bucketConfig:any = { + websiteIndexDocument: config.indexDoc, + websiteErrorDocument: config.errorDoc, + publicReadAccess: true, + }; + + if (this.globalConfig.encryptBucket === true) { + bucketConfig.encryption = s3.BucketEncryption.S3_MANAGED; + } + + if (this.globalConfig.ipFilter === true || isForCloudFront === true) { + bucketConfig.publicReadAccess = false; + if (typeof config.blockPublicAccess !== 'undefined') { + bucketConfig.blockPublicAccess = config.blockPublicAccess; + } + } + + const bucket = new s3.Bucket(this, 'WebsiteBucket', bucketConfig); + + if (this.globalConfig.ipFilter === true && isForCloudFront === false) { + if (typeof this.globalConfig.ipList === 'undefined') { + this.node.addError('When IP Filter is true then the IP List is required'); + } + + const bucketPolicy = new PolicyStatement(); + bucketPolicy.addAnyPrincipal(); + bucketPolicy.addActions('s3:GetObject'); + bucketPolicy.addResources(`${bucket.bucketArn}/*`); + bucketPolicy.addCondition('IpAddress', { + 'aws:SourceIp': this.globalConfig.ipList, + }); + + bucket.addToResourcePolicy(bucketPolicy); + } + + return bucket; + } + + /** + * Helper method to provide configuration for cloudfront + */ + private getCFConfig(websiteBucket:s3.Bucket, config:any, accessIdentity: OriginAccessIdentity, cert?:DnsValidatedCertificate) { + const cfConfig:any = { + originConfigs: [ + { + s3OriginSource: { + s3BucketSource: websiteBucket, + originAccessIdentity: accessIdentity, + }, + behaviors: config.cfBehaviors ? config.cfBehaviors : [{ isDefaultBehavior: true }], + }, + ], + // We need to redirect all unknown routes back to index.html for angular routing to work + errorConfigurations: [{ + errorCode: 403, + responsePagePath: (config.errorDoc ? `/${config.errorDoc}` : `/${config.indexDoc}`), + responseCode: 200, + }, + { + errorCode: 404, + responsePagePath: (config.errorDoc ? `/${config.errorDoc}` : `/${config.indexDoc}`), + responseCode: 200, + }], + }; + + if (typeof config.certificateARN !== 'undefined' && typeof config.cfAliases !== 'undefined') { + cfConfig.aliasConfiguration = { + acmCertRef: config.certificateARN, + names: config.cfAliases, + }; + } + if (typeof config.sslMethod !== 'undefined') { + cfConfig.aliasConfiguration.sslMethod = config.sslMethod; + } + + if (typeof config.securityPolicy !== 'undefined') { + cfConfig.aliasConfiguration.securityPolicy = config.securityPolicy; + } + + if (typeof config.zoneName !== 'undefined' && typeof cert !== 'undefined') { + cfConfig.viewerCertificate = ViewerCertificate.fromAcmCertificate(cert, { + aliases: [config.subdomain ? `${config.subdomain}.${config.zoneName}` : config.zoneName], + }); + } + + return cfConfig; + } + + /** + * Basic setup needed for a non-ssl, non vanity url, non cached s3 website + */ + public createBasicSite(config:SPADeployConfig): SPADeployment { + const websiteBucket = this.getS3Bucket(config, false); + + new s3deploy.BucketDeployment(this, 'BucketDeployment', { + sources: [s3deploy.Source.asset(config.websiteFolder)], + destinationBucket: websiteBucket, + }); + + const cfnOutputConfig:any = { + description: 'The url of the website', + value: websiteBucket.bucketWebsiteUrl, + }; + + if (config.exportWebsiteUrlOutput === true) { + if (typeof config.exportWebsiteUrlName === 'undefined' || config.exportWebsiteUrlName === '') { + this.node.addError('When Output URL as AWS Export property is true then the output name is required'); + } + cfnOutputConfig.exportName = config.exportWebsiteUrlName; + } + + new cdk.CfnOutput(this, 'URL', cfnOutputConfig); + + return { websiteBucket }; + } + + /** + * This will create an s3 deployment fronted by a cloudfront distribution + * It will also setup error forwarding and unauth forwarding back to indexDoc + */ + public createSiteWithCloudfront(config:SPADeployConfig): SPADeploymentWithCloudFront { + const websiteBucket = this.getS3Bucket(config, true); + const accessIdentity = new OriginAccessIdentity(this, 'OriginAccessIdentity', { comment: `${websiteBucket.bucketName}-access-identity` }); + const distribution = new CloudFrontWebDistribution(this, 'cloudfrontDistribution', this.getCFConfig(websiteBucket, config, accessIdentity)); + + new s3deploy.BucketDeployment(this, 'BucketDeployment', { + sources: [s3deploy.Source.asset(config.websiteFolder)], + destinationBucket: websiteBucket, + // Invalidate the cache for / and index.html when we deploy so that cloudfront serves latest site + distribution, + distributionPaths: ['/', `/${config.indexDoc}`], + }); + + new cdk.CfnOutput(this, 'cloudfront domain', { + description: 'The domain of the website', + value: distribution.distributionDomainName, + }); + + return { websiteBucket, distribution }; + } + + /** + * S3 Deployment, cloudfront distribution, ssl cert and error forwarding auto + * configured by using the details in the hosted zone provided + */ + public createSiteFromHostedZone(config:HostedZoneConfig): SPADeploymentWithCloudFront { + const websiteBucket = this.getS3Bucket(config, true); + const zone = HostedZone.fromLookup(this, 'HostedZone', { domainName: config.zoneName }); + const domainName = config.subdomain ? `${config.subdomain}.${config.zoneName}` : config.zoneName; + const cert = new DnsValidatedCertificate(this, 'Certificate', { + hostedZone: zone, + domainName, + region: 'us-east-1', + }); + + const accessIdentity = new OriginAccessIdentity(this, 'OriginAccessIdentity', { comment: `${websiteBucket.bucketName}-access-identity` }); + const distribution = new CloudFrontWebDistribution(this, 'cloudfrontDistribution', this.getCFConfig(websiteBucket, config, accessIdentity, cert)); + + new s3deploy.BucketDeployment(this, 'BucketDeployment', { + sources: [s3deploy.Source.asset(config.websiteFolder)], + destinationBucket: websiteBucket, + // Invalidate the cache for / and index.html when we deploy so that cloudfront serves latest site + distribution, + distributionPaths: ['/', `/${config.indexDoc}`], + }); + + new ARecord(this, 'Alias', { + zone, + recordName: domainName, + target: RecordTarget.fromAlias(new CloudFrontTarget(distribution)), + }); + + if (!config.subdomain) { + new HttpsRedirect(this, 'Redirect', { + zone, + recordNames: [`www.${config.zoneName}`], + targetDomain: config.zoneName, + }); + } + + return { websiteBucket, distribution }; + } + } \ No newline at end of file diff --git a/s3-website/lib/s3-website-stack.ts b/s3-website/lib/s3-website-stack.ts index 62f9aed..9d447c1 100644 --- a/s3-website/lib/s3-website-stack.ts +++ b/s3-website/lib/s3-website-stack.ts @@ -1,9 +1,25 @@ import * as cdk from '@aws-cdk/core'; +import { S3WebsiteConstruct } from './s3-website-construct'; export class S3WebsiteStack extends cdk.Stack { constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); // The code that defines your stack goes here + + /** Create Basic Site */ + new S3WebsiteConstruct(this, 'spaDeploy') + .createBasicSite({ + indexDoc: 'index.html', + websiteFolder: '../blog/dist/blog' + }); + + /** Create Site with Cloudfront */ + new S3WebsiteConstruct(this, 'cfDeploy') + .createSiteWithCloudfront({ + indexDoc: 'index.html', + websiteFolder: '../blog/dist/blog' + }); + } } diff --git a/s3-website/package-lock.json b/s3-website/package-lock.json index 000adb6..7960b76 100644 --- a/s3-website/package-lock.json +++ b/s3-website/package-lock.json @@ -17,6 +17,464 @@ "constructs": "^3.2.0" } }, + "@aws-cdk/assets": { + "version": "1.90.1", + "resolved": "https://registry.npmjs.org/@aws-cdk/assets/-/assets-1.90.1.tgz", + "integrity": "sha512-CTsoRD4dugJiXhYbBRFqYFNwVsKDEfZLSJbAAuGq79EhIIsJ2QOk/9XdOBWjkEMXi4ynhDoGFV5C8AqONHZgxQ==", + "requires": { + "@aws-cdk/core": "1.90.1", + "@aws-cdk/cx-api": "1.90.1", + "constructs": "^3.2.0" + } + }, + "@aws-cdk/aws-apigateway": { + "version": "1.90.1", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-apigateway/-/aws-apigateway-1.90.1.tgz", + "integrity": "sha512-GIJa3eNN5rhnNCCxpWDLx7n1Cz3gYAse+SBJ69Hd3sEntDHLRew9QFhixdnpdaDOFMeVYWdeeDxO+Pggp/d3tA==", + "requires": { + "@aws-cdk/aws-certificatemanager": "1.90.1", + "@aws-cdk/aws-cloudwatch": "1.90.1", + "@aws-cdk/aws-cognito": "1.90.1", + "@aws-cdk/aws-ec2": "1.90.1", + "@aws-cdk/aws-elasticloadbalancingv2": "1.90.1", + "@aws-cdk/aws-iam": "1.90.1", + "@aws-cdk/aws-lambda": "1.90.1", + "@aws-cdk/aws-logs": "1.90.1", + "@aws-cdk/aws-s3": "1.90.1", + "@aws-cdk/aws-s3-assets": "1.90.1", + "@aws-cdk/core": "1.90.1", + "@aws-cdk/cx-api": "1.90.1", + "constructs": "^3.2.0" + } + }, + "@aws-cdk/aws-apigatewayv2": { + "version": "1.90.1", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-apigatewayv2/-/aws-apigatewayv2-1.90.1.tgz", + "integrity": "sha512-KmLQXKPg9QjkHH4mTAotLcCdlCiWMZfsArTUQ56Stc8NvtNV4iagXLWyAyiTzaXpPBwIFsiDC5dhG7BBOgDymw==", + "requires": { + "@aws-cdk/aws-certificatemanager": "1.90.1", + "@aws-cdk/aws-cloudwatch": "1.90.1", + "@aws-cdk/aws-ec2": "1.90.1", + "@aws-cdk/aws-iam": "1.90.1", + "@aws-cdk/core": "1.90.1", + "constructs": "^3.2.0" + } + }, + "@aws-cdk/aws-applicationautoscaling": { + "version": "1.90.1", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-applicationautoscaling/-/aws-applicationautoscaling-1.90.1.tgz", + "integrity": "sha512-GvTlGn7iNLhvZMySqD8/z4fkClDIHJ3duPNJMT5SfKvo6XBkadyU5Eji4/uBicNT1PejdA+jXZoLxfsw+FArMw==", + "requires": { + "@aws-cdk/aws-autoscaling-common": "1.90.1", + "@aws-cdk/aws-cloudwatch": "1.90.1", + "@aws-cdk/aws-iam": "1.90.1", + "@aws-cdk/core": "1.90.1", + "constructs": "^3.2.0" + } + }, + "@aws-cdk/aws-autoscaling-common": { + "version": "1.90.1", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-autoscaling-common/-/aws-autoscaling-common-1.90.1.tgz", + "integrity": "sha512-PxOjJX2ipQiot8tq0DoFGEeVirjS7FNzDPpS5AETL3Ri1O3Qtp7JhBKgCJE4BcEov/B0eW10SRa4A4NOOznv0A==", + "requires": { + "@aws-cdk/aws-iam": "1.90.1", + "@aws-cdk/core": "1.90.1", + "constructs": "^3.2.0" + } + }, + "@aws-cdk/aws-certificatemanager": { + "version": "1.90.1", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-certificatemanager/-/aws-certificatemanager-1.90.1.tgz", + "integrity": "sha512-UdxY+OIynbLWu2OIqqOlQdSM8GIUTPLBqNGG6GDLy5FjdRWc+ZPp0agS0DfUqwS4eme+E8S5Wi1htYKQnQQ2JA==", + "requires": { + "@aws-cdk/aws-iam": "1.90.1", + "@aws-cdk/aws-lambda": "1.90.1", + "@aws-cdk/aws-route53": "1.90.1", + "@aws-cdk/core": "1.90.1", + "constructs": "^3.2.0" + } + }, + "@aws-cdk/aws-cloudformation": { + "version": "1.90.1", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-cloudformation/-/aws-cloudformation-1.90.1.tgz", + "integrity": "sha512-v0I9lC4blfQMbzPqBy2ilYyd6//IUWdCh7MuzJDBqINgIe9/oIatoTPlf4ADaw1fyoE+wzTrerd7Ze+Ynl0ulg==", + "requires": { + "@aws-cdk/aws-iam": "1.90.1", + "@aws-cdk/aws-lambda": "1.90.1", + "@aws-cdk/aws-s3": "1.90.1", + "@aws-cdk/aws-sns": "1.90.1", + "@aws-cdk/core": "1.90.1", + "@aws-cdk/cx-api": "1.90.1", + "constructs": "^3.2.0" + } + }, + "@aws-cdk/aws-cloudfront": { + "version": "1.90.1", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-cloudfront/-/aws-cloudfront-1.90.1.tgz", + "integrity": "sha512-+UjHmolYff27qw2EFIiQtoKKtMg5MtGU3COy2WPAiYrcPfHbpU7YcSbNzoussYnRU3TNBN0RJ6AIsiKIx29FzQ==", + "requires": { + "@aws-cdk/aws-certificatemanager": "1.90.1", + "@aws-cdk/aws-cloudwatch": "1.90.1", + "@aws-cdk/aws-ec2": "1.90.1", + "@aws-cdk/aws-iam": "1.90.1", + "@aws-cdk/aws-kms": "1.90.1", + "@aws-cdk/aws-lambda": "1.90.1", + "@aws-cdk/aws-s3": "1.90.1", + "@aws-cdk/aws-ssm": "1.90.1", + "@aws-cdk/core": "1.90.1", + "constructs": "^3.2.0" + } + }, + "@aws-cdk/aws-cloudwatch": { + "version": "1.90.1", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-cloudwatch/-/aws-cloudwatch-1.90.1.tgz", + "integrity": "sha512-H0/2ZBFzDT/SUBnH8wVgWVgPpzKI2s0Prv3b8blXfnqF8kfoVMtOiqAqSt8TVHwWdAvkDk2ktWknlkfI4s5RHA==", + "requires": { + "@aws-cdk/aws-iam": "1.90.1", + "@aws-cdk/core": "1.90.1", + "constructs": "^3.2.0" + } + }, + "@aws-cdk/aws-codeguruprofiler": { + "version": "1.90.1", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-codeguruprofiler/-/aws-codeguruprofiler-1.90.1.tgz", + "integrity": "sha512-kvHM23kW19TUINQ+DUvsvE5ANGCsquPVE8qi7+5BR1R89Ij4SeGfPzyti9XQx/v/njf+D+f+bWq3uInkJVD4hg==", + "requires": { + "@aws-cdk/aws-iam": "1.90.1", + "@aws-cdk/core": "1.90.1", + "constructs": "^3.2.0" + } + }, + "@aws-cdk/aws-cognito": { + "version": "1.90.1", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-cognito/-/aws-cognito-1.90.1.tgz", + "integrity": "sha512-U3FERDRbYbqCN9BI/8MzdXxtx3OCV9mfE+DzuO6dCT7dsf0t7OiDoNkczTg5xKOz+rM05C4Yms0+UkEKel7wJA==", + "requires": { + "@aws-cdk/aws-certificatemanager": "1.90.1", + "@aws-cdk/aws-iam": "1.90.1", + "@aws-cdk/aws-lambda": "1.90.1", + "@aws-cdk/core": "1.90.1", + "@aws-cdk/custom-resources": "1.90.1", + "constructs": "^3.2.0", + "punycode": "^2.1.1" + }, + "dependencies": { + "punycode": { + "version": "2.1.1", + "bundled": true + } + } + }, + "@aws-cdk/aws-ec2": { + "version": "1.90.1", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-ec2/-/aws-ec2-1.90.1.tgz", + "integrity": "sha512-qFefip/yW1zfM6sA5AXFjddBPoLVh5zPtxaYbxxav+e1NDdXrdlT79Z7IqfapmR/ZSFWW3LY7KuFF82dizzECg==", + "requires": { + "@aws-cdk/aws-cloudwatch": "1.90.1", + "@aws-cdk/aws-iam": "1.90.1", + "@aws-cdk/aws-kms": "1.90.1", + "@aws-cdk/aws-logs": "1.90.1", + "@aws-cdk/aws-s3": "1.90.1", + "@aws-cdk/aws-s3-assets": "1.90.1", + "@aws-cdk/aws-ssm": "1.90.1", + "@aws-cdk/cloud-assembly-schema": "1.90.1", + "@aws-cdk/core": "1.90.1", + "@aws-cdk/cx-api": "1.90.1", + "@aws-cdk/region-info": "1.90.1", + "constructs": "^3.2.0" + } + }, + "@aws-cdk/aws-ecr": { + "version": "1.90.1", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-ecr/-/aws-ecr-1.90.1.tgz", + "integrity": "sha512-QtYETqI8Ts2bbhAgwYmQ+40bmOqZd0fZ+8LW+VRLv3uA/9FukY2EufMqXTyjwfzlHlTpYo+9mm38JndT/T903g==", + "requires": { + "@aws-cdk/aws-events": "1.90.1", + "@aws-cdk/aws-iam": "1.90.1", + "@aws-cdk/core": "1.90.1", + "constructs": "^3.2.0" + } + }, + "@aws-cdk/aws-ecr-assets": { + "version": "1.90.1", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-ecr-assets/-/aws-ecr-assets-1.90.1.tgz", + "integrity": "sha512-AThpqVAuZjzMd1MLtF0sTXe+APmWDIKWcLu1gne/Mxv3tEaJ2MQaPWB/ljcKAERuhbKKNxg1R1BjKZuPsVZRwQ==", + "requires": { + "@aws-cdk/assets": "1.90.1", + "@aws-cdk/aws-ecr": "1.90.1", + "@aws-cdk/aws-iam": "1.90.1", + "@aws-cdk/aws-s3": "1.90.1", + "@aws-cdk/core": "1.90.1", + "@aws-cdk/cx-api": "1.90.1", + "constructs": "^3.2.0", + "minimatch": "^3.0.4" + }, + "dependencies": { + "balanced-match": { + "version": "1.0.0", + "bundled": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } + } + }, + "@aws-cdk/aws-efs": { + "version": "1.90.1", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-efs/-/aws-efs-1.90.1.tgz", + "integrity": "sha512-7eX0uHQ3kQG/GDdDmKkZKx+TlWxMx8A9zF6NR2gezaYMlEHZZmKhIz51DC6wmN+C0odWWX+OTK+X0Uhsnc20Kw==", + "requires": { + "@aws-cdk/aws-ec2": "1.90.1", + "@aws-cdk/aws-kms": "1.90.1", + "@aws-cdk/cloud-assembly-schema": "1.90.1", + "@aws-cdk/core": "1.90.1", + "@aws-cdk/cx-api": "1.90.1", + "constructs": "^3.2.0" + } + }, + "@aws-cdk/aws-elasticloadbalancing": { + "version": "1.90.1", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-elasticloadbalancing/-/aws-elasticloadbalancing-1.90.1.tgz", + "integrity": "sha512-k5YyX8riukwGdwxwvkhFCXgvWU2MobfGpGQ9qXM8xKGG+zO64Zg4TRh9vGWzXO8HovQNgjvjcgyLR1woiJkGqQ==", + "requires": { + "@aws-cdk/aws-ec2": "1.90.1", + "@aws-cdk/core": "1.90.1", + "constructs": "^3.2.0" + } + }, + "@aws-cdk/aws-elasticloadbalancingv2": { + "version": "1.90.1", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-elasticloadbalancingv2/-/aws-elasticloadbalancingv2-1.90.1.tgz", + "integrity": "sha512-LN4DIIam6REfZu58L08kJv5BCJvN0fdx5kUaEVYPJIXZPDDQGNKNuDUOsMUeHMaWIN0NuMILhDdTS3T7Y8o3tw==", + "requires": { + "@aws-cdk/aws-certificatemanager": "1.90.1", + "@aws-cdk/aws-cloudwatch": "1.90.1", + "@aws-cdk/aws-ec2": "1.90.1", + "@aws-cdk/aws-iam": "1.90.1", + "@aws-cdk/aws-lambda": "1.90.1", + "@aws-cdk/aws-s3": "1.90.1", + "@aws-cdk/cloud-assembly-schema": "1.90.1", + "@aws-cdk/core": "1.90.1", + "@aws-cdk/cx-api": "1.90.1", + "@aws-cdk/region-info": "1.90.1", + "constructs": "^3.2.0" + } + }, + "@aws-cdk/aws-events": { + "version": "1.90.1", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-events/-/aws-events-1.90.1.tgz", + "integrity": "sha512-wysfuLyL+L45XqR6Fnb0Jih3YktXs7fo0QYp/bNEMIBG3gXaK2k1mVceMWFxG/NGBwf+lD4rD5t3E3G8C1DVbQ==", + "requires": { + "@aws-cdk/aws-iam": "1.90.1", + "@aws-cdk/core": "1.90.1", + "constructs": "^3.2.0" + } + }, + "@aws-cdk/aws-iam": { + "version": "1.90.1", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-iam/-/aws-iam-1.90.1.tgz", + "integrity": "sha512-oRsDKe54v1a3R8BdAV2KpxdgnDlCoiRhfoCG3ujwOWfHBl/IgzgqHzab4hlMU1T67km8DAY833DVwKx9kkunVg==", + "requires": { + "@aws-cdk/core": "1.90.1", + "@aws-cdk/region-info": "1.90.1", + "constructs": "^3.2.0" + } + }, + "@aws-cdk/aws-kms": { + "version": "1.90.1", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-kms/-/aws-kms-1.90.1.tgz", + "integrity": "sha512-i0IZGbvT5WMwU3Q2DbUrHm9iNil0G6regfotCLhGqZxhy/+DbPu9Ilix2nU5yWBOMNGhlMQtgDhXM3s2siqoAg==", + "requires": { + "@aws-cdk/aws-iam": "1.90.1", + "@aws-cdk/core": "1.90.1", + "@aws-cdk/cx-api": "1.90.1", + "constructs": "^3.2.0" + } + }, + "@aws-cdk/aws-lambda": { + "version": "1.90.1", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-lambda/-/aws-lambda-1.90.1.tgz", + "integrity": "sha512-l2vvKPv4dYHUGov/wErR4DfYFjc8n2MIAyoCpZ3TnIaaAKGmISrAVgh8ya/VS0t/nRXM4pIvqK/vkOFlK2TEKQ==", + "requires": { + "@aws-cdk/aws-applicationautoscaling": "1.90.1", + "@aws-cdk/aws-cloudwatch": "1.90.1", + "@aws-cdk/aws-codeguruprofiler": "1.90.1", + "@aws-cdk/aws-ec2": "1.90.1", + "@aws-cdk/aws-ecr": "1.90.1", + "@aws-cdk/aws-ecr-assets": "1.90.1", + "@aws-cdk/aws-efs": "1.90.1", + "@aws-cdk/aws-events": "1.90.1", + "@aws-cdk/aws-iam": "1.90.1", + "@aws-cdk/aws-kms": "1.90.1", + "@aws-cdk/aws-logs": "1.90.1", + "@aws-cdk/aws-s3": "1.90.1", + "@aws-cdk/aws-s3-assets": "1.90.1", + "@aws-cdk/aws-sqs": "1.90.1", + "@aws-cdk/core": "1.90.1", + "@aws-cdk/cx-api": "1.90.1", + "constructs": "^3.2.0" + } + }, + "@aws-cdk/aws-logs": { + "version": "1.90.1", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-logs/-/aws-logs-1.90.1.tgz", + "integrity": "sha512-6BMk6JE6aN9+7Rqo0yk9pZC53y+c8MtoVUbc6AMlwKf6AsuN7AZVVGlRZiZBWUNCS+5BklW8WQCXnrxZeSCAGg==", + "requires": { + "@aws-cdk/aws-cloudwatch": "1.90.1", + "@aws-cdk/aws-iam": "1.90.1", + "@aws-cdk/aws-kms": "1.90.1", + "@aws-cdk/aws-s3-assets": "1.90.1", + "@aws-cdk/core": "1.90.1", + "constructs": "^3.2.0" + } + }, + "@aws-cdk/aws-route53": { + "version": "1.90.1", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-route53/-/aws-route53-1.90.1.tgz", + "integrity": "sha512-fHe8wSf9zwjyPU48SLNUdGwt6ic1qlWb9IinsxNYMZGh3JeKylN+/uetDm97yGnI9dvewwTD0J4yH0oUjyGOZQ==", + "requires": { + "@aws-cdk/aws-ec2": "1.90.1", + "@aws-cdk/aws-iam": "1.90.1", + "@aws-cdk/aws-logs": "1.90.1", + "@aws-cdk/cloud-assembly-schema": "1.90.1", + "@aws-cdk/core": "1.90.1", + "@aws-cdk/custom-resources": "1.90.1", + "constructs": "^3.2.0" + } + }, + "@aws-cdk/aws-route53-patterns": { + "version": "1.90.1", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-route53-patterns/-/aws-route53-patterns-1.90.1.tgz", + "integrity": "sha512-U4fZTGwJmm4cOySm3jJYv+RsEU2o6VS+rOyzyYp8n7MaTVg/xP60zhAymySFJYo8I/BkBPdbJuwMog28V5G9ZA==", + "requires": { + "@aws-cdk/aws-certificatemanager": "1.90.1", + "@aws-cdk/aws-cloudfront": "1.90.1", + "@aws-cdk/aws-iam": "1.90.1", + "@aws-cdk/aws-route53": "1.90.1", + "@aws-cdk/aws-route53-targets": "1.90.1", + "@aws-cdk/aws-s3": "1.90.1", + "@aws-cdk/core": "1.90.1", + "@aws-cdk/region-info": "1.90.1", + "constructs": "^3.2.0" + } + }, + "@aws-cdk/aws-route53-targets": { + "version": "1.90.1", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-route53-targets/-/aws-route53-targets-1.90.1.tgz", + "integrity": "sha512-xw5p02G7T8CILE/cJhDRBVsH6bgqU6tCL+a7q8h2NgLaWJwHSwto3gH7r9CUk9Ude4BBTzuVncye93wFdtB3aQ==", + "requires": { + "@aws-cdk/aws-apigateway": "1.90.1", + "@aws-cdk/aws-apigatewayv2": "1.90.1", + "@aws-cdk/aws-cloudfront": "1.90.1", + "@aws-cdk/aws-cognito": "1.90.1", + "@aws-cdk/aws-ec2": "1.90.1", + "@aws-cdk/aws-elasticloadbalancing": "1.90.1", + "@aws-cdk/aws-elasticloadbalancingv2": "1.90.1", + "@aws-cdk/aws-iam": "1.90.1", + "@aws-cdk/aws-route53": "1.90.1", + "@aws-cdk/aws-s3": "1.90.1", + "@aws-cdk/core": "1.90.1", + "@aws-cdk/region-info": "1.90.1", + "constructs": "^3.2.0" + } + }, + "@aws-cdk/aws-s3": { + "version": "1.90.1", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-s3/-/aws-s3-1.90.1.tgz", + "integrity": "sha512-mLDbgeOlzPkQshaAlK9cvhXLUNvQhVCjZ+bGtSviAibvnKMpodlvMfRSVUazd/zTIGwrfxZWhQLwF6YHEhW0iw==", + "requires": { + "@aws-cdk/aws-events": "1.90.1", + "@aws-cdk/aws-iam": "1.90.1", + "@aws-cdk/aws-kms": "1.90.1", + "@aws-cdk/core": "1.90.1", + "@aws-cdk/cx-api": "1.90.1", + "constructs": "^3.2.0" + } + }, + "@aws-cdk/aws-s3-assets": { + "version": "1.90.1", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-s3-assets/-/aws-s3-assets-1.90.1.tgz", + "integrity": "sha512-mb+zTPc79oitO80Mu/oThGYoHfRHqt94OBEmc/qZuW1F4haBkhBuPK1tfSd89pJmbjVJACf9p0ulRYO0gy+J1w==", + "requires": { + "@aws-cdk/assets": "1.90.1", + "@aws-cdk/aws-iam": "1.90.1", + "@aws-cdk/aws-kms": "1.90.1", + "@aws-cdk/aws-s3": "1.90.1", + "@aws-cdk/core": "1.90.1", + "@aws-cdk/cx-api": "1.90.1", + "constructs": "^3.2.0" + } + }, + "@aws-cdk/aws-s3-deployment": { + "version": "1.90.1", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-s3-deployment/-/aws-s3-deployment-1.90.1.tgz", + "integrity": "sha512-4ZNSaE1V58yZywE7eRHXMxA+iJjcVHKThpfz7IRf28y+dFqkHmtkrR2B+ZOXpNWGBVb+LY2Jz6nHVpd4Azsvcw==", + "requires": { + "@aws-cdk/aws-cloudfront": "1.90.1", + "@aws-cdk/aws-ec2": "1.90.1", + "@aws-cdk/aws-iam": "1.90.1", + "@aws-cdk/aws-lambda": "1.90.1", + "@aws-cdk/aws-s3": "1.90.1", + "@aws-cdk/aws-s3-assets": "1.90.1", + "@aws-cdk/core": "1.90.1", + "@aws-cdk/lambda-layer-awscli": "1.90.1", + "constructs": "^3.2.0" + } + }, + "@aws-cdk/aws-sns": { + "version": "1.90.1", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-sns/-/aws-sns-1.90.1.tgz", + "integrity": "sha512-MsjI84W6jecNmDt6HVXKI2/IuCFrM/9iX6S+pMxmyDyUSXGOCDbNk7qE0+IJ1H7fnLa+gGeQr1TOdCFczm0h+g==", + "requires": { + "@aws-cdk/aws-cloudwatch": "1.90.1", + "@aws-cdk/aws-events": "1.90.1", + "@aws-cdk/aws-iam": "1.90.1", + "@aws-cdk/aws-kms": "1.90.1", + "@aws-cdk/aws-sqs": "1.90.1", + "@aws-cdk/core": "1.90.1", + "constructs": "^3.2.0" + } + }, + "@aws-cdk/aws-sqs": { + "version": "1.90.1", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-sqs/-/aws-sqs-1.90.1.tgz", + "integrity": "sha512-P2G73h27IM9Blr5uVQFCV5FYfv5Su9uKYqNE4tvc586pm8mOqEsRKavISkLXz7ojSn9RDLBpvGdWN4BAHCoQsQ==", + "requires": { + "@aws-cdk/aws-cloudwatch": "1.90.1", + "@aws-cdk/aws-iam": "1.90.1", + "@aws-cdk/aws-kms": "1.90.1", + "@aws-cdk/core": "1.90.1", + "constructs": "^3.2.0" + } + }, + "@aws-cdk/aws-ssm": { + "version": "1.90.1", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-ssm/-/aws-ssm-1.90.1.tgz", + "integrity": "sha512-2FrFeRxnimob57PhyDq0yQ5Y+7J+NprXX2xbekNHeAHq4NQCp3RwUrDtOWseDnXLNC/jwI+DtvQa/PbkYQF2wA==", + "requires": { + "@aws-cdk/aws-iam": "1.90.1", + "@aws-cdk/aws-kms": "1.90.1", + "@aws-cdk/cloud-assembly-schema": "1.90.1", + "@aws-cdk/core": "1.90.1", + "constructs": "^3.2.0" + } + }, "@aws-cdk/cfnspec": { "version": "1.90.1", "resolved": "https://registry.npmjs.org/@aws-cdk/cfnspec/-/cfnspec-1.90.1.tgz", @@ -151,6 +609,21 @@ } } }, + "@aws-cdk/custom-resources": { + "version": "1.90.1", + "resolved": "https://registry.npmjs.org/@aws-cdk/custom-resources/-/custom-resources-1.90.1.tgz", + "integrity": "sha512-Y/sD6EeRudh3y3f0ClPQZARclUv70MD4em/pkgi615YQxNq2V8Emb+pGR8+pBK9GzAT2m4R4ueKORuHF4jRWEw==", + "requires": { + "@aws-cdk/aws-cloudformation": "1.90.1", + "@aws-cdk/aws-ec2": "1.90.1", + "@aws-cdk/aws-iam": "1.90.1", + "@aws-cdk/aws-lambda": "1.90.1", + "@aws-cdk/aws-logs": "1.90.1", + "@aws-cdk/aws-sns": "1.90.1", + "@aws-cdk/core": "1.90.1", + "constructs": "^3.2.0" + } + }, "@aws-cdk/cx-api": { "version": "1.90.1", "resolved": "https://registry.npmjs.org/@aws-cdk/cx-api/-/cx-api-1.90.1.tgz", @@ -180,6 +653,16 @@ } } }, + "@aws-cdk/lambda-layer-awscli": { + "version": "1.90.1", + "resolved": "https://registry.npmjs.org/@aws-cdk/lambda-layer-awscli/-/lambda-layer-awscli-1.90.1.tgz", + "integrity": "sha512-V/Bt7m25gq5NfguyR0DQ4k0p6LTzbRUMPEOE+HPoTc9MIpVdvJhbMuftyF6dxtj+BbagL2wmchp/Rq3/hSyiPA==", + "requires": { + "@aws-cdk/aws-lambda": "1.90.1", + "@aws-cdk/core": "1.90.1", + "constructs": "^3.2.0" + } + }, "@aws-cdk/region-info": { "version": "1.90.1", "resolved": "https://registry.npmjs.org/@aws-cdk/region-info/-/region-info-1.90.1.tgz", diff --git a/s3-website/package.json b/s3-website/package.json index 6778cc0..1555364 100644 --- a/s3-website/package.json +++ b/s3-website/package.json @@ -25,6 +25,14 @@ "typescript": "~3.9.7" }, "dependencies": { + "@aws-cdk/aws-certificatemanager": "^1.90.1", + "@aws-cdk/aws-cloudfront": "^1.90.1", + "@aws-cdk/aws-iam": "^1.90.1", + "@aws-cdk/aws-route53": "^1.90.1", + "@aws-cdk/aws-route53-patterns": "^1.90.1", + "@aws-cdk/aws-route53-targets": "^1.90.1", + "@aws-cdk/aws-s3": "^1.90.1", + "@aws-cdk/aws-s3-deployment": "^1.90.1", "@aws-cdk/core": "1.90.1", "source-map-support": "^0.5.16" },