diff --git a/aws-eb-bluegreen/README.md b/aws-eb-bluegreen/README.md new file mode 100644 index 0000000..6bedf7e --- /dev/null +++ b/aws-eb-bluegreen/README.md @@ -0,0 +1,46 @@ +# Testing the code + +## Requirements + +- [An AWS Account](https://aws.amazon.com/account/) +- An IAM user with [programmatic access](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html) +- The AWS CLI with a [profile](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html) configured +- [Ansible](https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html) (on Windows you will need [Windows Subsystem for Linux](https://docs.microsoft.com/en-us/windows/wsl/install-win10)) + +## Configuration + + cd eb-bluegreen-infra + # Update the file `vars/common-vars.asb.yml` with appropriate values + ansible-playbook init/main.asb.yml --check -v + ansible-playbook init/main.asb.yml + + ansible-playbook infra/main.asb.yml --check -v + ansible-playbook infra/main.asb.yml + + # Insert secrets into SSM Parameter Store + # Create a Python script from .vault/ssm-parameters/parameters.py.template (change the profile and the values) named ssm-labs.py + cd .vault/ssm-parameters + python ssm-labs.py + python ssm-labs.py --nodryrun + + cd ../../../eb-bluegreen-app + git init + git remote add origin codecommit::us-east-1://spikeseed-labs@eb-bluegreen-app + git add -A + git commit -m "Demo application" + git push origin master + + cd ../eb-bluegreen-infra + ansible-playbook cicd/main.asb.yml --check -v + ansible-playbook cicd/main.asb.yml + + # Wait for the Elastic BeanStalk to be created, then: + + curl -i -H "x-com-token: 0123456789" https:///api/v1/hello # FQDN configured in common-vars.asb.yml + +### Cleanup + +1. Remove the S3 Buckets +1. Remove the stacks +1. Remove the CodeCommit repositories +1. Remove SSM Parameters diff --git a/aws-eb-bluegreen/eb-bluegreen-infra/.gitignore b/aws-eb-bluegreen/eb-bluegreen-infra/.gitignore new file mode 100644 index 0000000..1e03ff1 --- /dev/null +++ b/aws-eb-bluegreen/eb-bluegreen-infra/.gitignore @@ -0,0 +1,2 @@ +__pycache__ +ssm-*.py \ No newline at end of file diff --git a/aws-eb-bluegreen/eb-bluegreen-infra/.vault/ssm-parameters/download.sh b/aws-eb-bluegreen/eb-bluegreen-infra/.vault/ssm-parameters/download.sh new file mode 100644 index 0000000..48f18a7 --- /dev/null +++ b/aws-eb-bluegreen/eb-bluegreen-infra/.vault/ssm-parameters/download.sh @@ -0,0 +1,5 @@ +#!/bin/sh +PROFILE_NAME=spikeseed-labs +AWS_REGION=us-east-1 +BUCKET_NAME=$(aws ssm get-parameter --name /eb-bluegreen/cfn/bucket/vault --output text --query Parameter.Value --profile $PROFILE_NAME --region $AWS_REGION) +aws s3 sync --profile $PROFILE_NAME s3://$BUCKET_NAME/ssm-parameters . --include "*.py" diff --git a/aws-eb-bluegreen/eb-bluegreen-infra/.vault/ssm-parameters/parameters.py.template b/aws-eb-bluegreen/eb-bluegreen-infra/.vault/ssm-parameters/parameters.py.template new file mode 100644 index 0000000..0a6d424 --- /dev/null +++ b/aws-eb-bluegreen/eb-bluegreen-infra/.vault/ssm-parameters/parameters.py.template @@ -0,0 +1,7 @@ +from .ssm_utils import SsmParameterUpdater + +ssm = SsmParameterUpdater('spikeseed-labs', 'us-east-1') + +ssm.put_ssm_parameter('/cicd/deploy/color' , 'blue', value_type='String') # should only be executed the first time +ssm.put_ssm_parameter('/eb-bluegreen/database/password/1', 'TODO value') +ssm.put_ssm_parameter('/eb-bluegreen/database/password/2', 'TODO value') diff --git a/aws-eb-bluegreen/eb-bluegreen-infra/.vault/ssm-parameters/ssm_utils.py b/aws-eb-bluegreen/eb-bluegreen-infra/.vault/ssm-parameters/ssm_utils.py new file mode 100644 index 0000000..2d78adf --- /dev/null +++ b/aws-eb-bluegreen/eb-bluegreen-infra/.vault/ssm-parameters/ssm_utils.py @@ -0,0 +1,45 @@ +import sys +import boto3 + +class SsmParameterUpdater: + + def __init__(self, profile_name, region_name): + if len(sys.argv) == 2 and sys.argv[1] == '--nodryrun': + self._dry_run = False + print('==================') + print('Update Mode') + print('==================') + else: + self._dry_run = True + print('==================') + print('Dry Run Mode') + print('==================') + session = boto3.Session(profile_name=profile_name, region_name=region_name) + self._ssm_client = session.client('ssm') + + def get_ssm_parameter(self, name: str): + try: + return self._ssm_client.get_parameter(Name=name, WithDecryption=True)['Parameter'] + except: + return None + + def put_ssm_parameter(self, name: str, value: str, value_type: str = 'SecureString'): + param = self.get_ssm_parameter(name) + if not param or param['Value'] != value or param['Type'] != value_type: + if not self._dry_run: + + self._ssm_client.put_parameter( + Name=name, + Value=value, + Type=value_type, + Overwrite=True + ) + + print(f'[modified] {name}') + + else: + print(f'DR - [modified] {name}') + elif not self._dry_run: + print(f'[no change] {name}') + else: + print(f'DR - [no change] {name}') diff --git a/aws-eb-bluegreen/eb-bluegreen-infra/.vault/ssm-parameters/upload.sh b/aws-eb-bluegreen/eb-bluegreen-infra/.vault/ssm-parameters/upload.sh new file mode 100644 index 0000000..a010bda --- /dev/null +++ b/aws-eb-bluegreen/eb-bluegreen-infra/.vault/ssm-parameters/upload.sh @@ -0,0 +1,5 @@ +#!/bin/sh +PROFILE_NAME=spikeseed-labs +AWS_REGION=us-east-1 +BUCKET_NAME=$(aws ssm get-parameter --name /eb-bluegreen/cfn/bucket/vault --output text --query Parameter.Value --profile $PROFILE_NAME --region $AWS_REGION) +aws s3 sync --profile $PROFILE_NAME . s3://$BUCKET_NAME/ssm-parameters --exclude "*" --include "ssm-*.py" diff --git a/aws-eb-bluegreen/eb-bluegreen-infra/cicd/main.asb.yml b/aws-eb-bluegreen/eb-bluegreen-infra/cicd/main.asb.yml new file mode 100644 index 0000000..0a50e4c --- /dev/null +++ b/aws-eb-bluegreen/eb-bluegreen-infra/cicd/main.asb.yml @@ -0,0 +1,34 @@ +--- +- hosts: localhost + connection: local + gather_facts: false + + vars_files: + - ../vars/common-vars.asb.yml + + tasks: + + - name: "Deploy CloudFormation stack {{ local_stack_name }}" + amazon.aws.cloudformation: + stack_name: "{{ local_stack_name }}" + state: present + region: "{{ local_region_name }}" + profile: "{{ local_account_name }}" + template: "templates/cicd-app.cfn.yml" + tags: "{{ local_aws_tags }}" + template_parameters: + CodeCommitRepoName: "{{ repo_app }}" + SsmAssetsBucketNameKey: "{{ ssm_assets_bucket_name_key }}" + vars: + local_account: "{{ aws_accounts.labs }}" + local_account_name: "{{ local_account.account_name }}" + local_account_code: "{{ local_account.account_code }}" + local_region_name: "{{ default_aws_region }}" + local_region_code: "{{ default_aws_region_code }}" + local_stack_name: "{{ local_account_code }}-{{ local_region_code }}-{{ application }}-cicd-app" + local_aws_tags: + Application: "{{ application }}" + Environment: "{{ local_account.environment }}" + Name: "{{ local_stack_name }}" + tags: + - app diff --git a/aws-eb-bluegreen/eb-bluegreen-infra/cicd/templates/cicd-app.cfn.yml b/aws-eb-bluegreen/eb-bluegreen-infra/cicd/templates/cicd-app.cfn.yml new file mode 100644 index 0000000..9a59b6d --- /dev/null +++ b/aws-eb-bluegreen/eb-bluegreen-infra/cicd/templates/cicd-app.cfn.yml @@ -0,0 +1,210 @@ +Parameters: + + CodeCommitRepoName: + Type: String + SsmAssetsBucketNameKey: + Type: AWS::SSM::Parameter::Value + +Resources: + + CodeBuildDeployRole: + Type: AWS::IAM::Role + Properties: + RoleName: eb-bluegreen-codebuild-deploy-assumable-role + Path: / + AssumeRolePolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Principal: + AWS: !Sub arn:aws:iam::${AWS::AccountId}:root + Action: sts:AssumeRole + ManagedPolicyArns: + - arn:aws:iam::aws:policy/AWSElasticBeanstalkFullAccess + Policies: + - PolicyName: eb-bluegreen-codebuild-deploy-assumable-role-policy + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: + - iam:* + - lambda:GetFunction + - lambda:CreateFunction + - lambda:DeleteFunction + - lambda:UpdateFunction* + - lambda:InvokeFunction + - ssm:AddTagsToResource + - ssm:GetParameters + - ssm:PutParameter + - ssm:DeleteParameter + - route53:GetHostedZone + - route53:GetChange + - route53:ChangeResourceRecordSets + Resource: '*' + + #================ + # CodePipeline S3 Bucket + #================ + + CicdAppArtifactsBucket: + Type: AWS::S3::Bucket + DeletionPolicy: Retain + Properties: + AccessControl: Private + PublicAccessBlockConfiguration: + BlockPublicAcls: true + BlockPublicPolicy: true + IgnorePublicAcls: true + RestrictPublicBuckets: true + BucketEncryption: + ServerSideEncryptionConfiguration: + - ServerSideEncryptionByDefault: + SSEAlgorithm: AES256 + + #================ + # IAM Permissions + #================ + + CodeBuildServiceRole: + Type: AWS::IAM::Role + Properties: + RoleName: eb-bluegreen-codebuild-app-role + Path: / + AssumeRolePolicyDocument: + Statement: + - Effect: Allow + Principal: + Service: + - codebuild.amazonaws.com + Action: sts:AssumeRole + Policies: + - PolicyName: eb-bluegreen-codebuild-app-role-policy + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: sts:AssumeRole + Resource: !GetAtt CodeBuildDeployRole.Arn + - Effect: Allow + Action: + - logs:CreateLogGroup + - logs:CreateLogStream + - logs:PutLogEvents + Resource: '*' + - Effect: Allow + Action: + - s3:GetObject + - s3:PutObject + - s3:GetObjectVersion + Resource: + - !Sub arn:aws:s3:::${CicdAppArtifactsBucket}/* + - !Sub arn:aws:s3:::${SsmAssetsBucketNameKey}/* + + CodePipelineServiceRole: + Type: AWS::IAM::Role + Properties: + RoleName: eb-bluegreen-codepipeline-app-role + Path: / + AssumeRolePolicyDocument: + Statement: + - Effect: Allow + Principal: + Service: + - codepipeline.amazonaws.com + Action: sts:AssumeRole + Policies: + - PolicyName: eb-bluegreen-codepipeline-app-role-policy + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: + - s3:PutObject + - s3:GetObject + - s3:GetObjectVersion + - s3:GetBucketVersioning + Resource: + - !Sub arn:aws:s3:::${CicdAppArtifactsBucket}/* + - Effect: Allow + Action: + - codebuild:StartBuild + - codebuild:BatchGetBuilds + Resource: '*' + - Action: + - codecommit:GetBranch + - codecommit:GetCommit + - codecommit:UploadArchive + - codecommit:GetUploadArchiveStatus + - codecommit:CancelUploadArchive + Effect: Allow + Resource: !Sub arn:aws:codecommit:${AWS::Region}:${AWS::AccountId}:${CodeCommitRepoName} + + #================ + # CodeBuild + #================ + + CodeBuildProject: + Type: AWS::CodeBuild::Project + Properties: + Name: eb-bluegreen-app + ServiceRole: !Ref CodeBuildServiceRole + Artifacts: + Type: CODEPIPELINE + Source: + Type: CODEPIPELINE + Environment: + Type: LINUX_CONTAINER + ComputeType: BUILD_GENERAL1_MEDIUM + Image: aws/codebuild/amazonlinux2-x86_64-standard:3.0 + EnvironmentVariables: + - Type: PLAINTEXT + Name: ASSETS_BUCKET_NAME + Value: !Ref SsmAssetsBucketNameKey + - Type: PLAINTEXT + Name: ROLE_ARN + Value: !GetAtt CodeBuildDeployRole.Arn + + #================ + # CodePipeline + #================ + + Pipeline: + Type: AWS::CodePipeline::Pipeline + Properties: + RoleArn: !GetAtt CodePipelineServiceRole.Arn + RestartExecutionOnUpdate: False + ArtifactStore: + Type: S3 + Location: !Ref CicdAppArtifactsBucket + Name: eb-bluegreen-app + Stages: + - Name: Source + Actions: + - Name: App + ActionTypeId: + Category: Source + Owner: AWS + Version: 1 + Provider: CodeCommit + Configuration: + RepositoryName: !Ref CodeCommitRepoName + BranchName: master + OutputArtifacts: + - Name: App + RunOrder: 1 + - Name: Build + Actions: + - Name: Build + ActionTypeId: + Category: Build + Owner: AWS + Provider: CodeBuild + Version: 1 + Configuration: + ProjectName: !Ref CodeBuildProject + InputArtifacts: + - Name: App + OutputArtifacts: + - Name: BuildOutput + RunOrder: 1 diff --git a/aws-eb-bluegreen/eb-bluegreen-infra/infra/main.asb.yml b/aws-eb-bluegreen/eb-bluegreen-infra/infra/main.asb.yml new file mode 100644 index 0000000..fd666df --- /dev/null +++ b/aws-eb-bluegreen/eb-bluegreen-infra/infra/main.asb.yml @@ -0,0 +1,51 @@ +--- +- hosts: localhost + connection: local + gather_facts: false + + vars: + pbk_account: "{{ aws_accounts.labs }}" + pbk_account_name: "{{ pbk_account.account_name }}" + pbk_account_code: "{{ pbk_account.account_code }}" + pbk_account_env: "{{ pbk_account.environment }}" + + vars_files: + - ../vars/common-vars.asb.yml + + tasks: + + # ====================================================================================================================== + # VPC + # ====================================================================================================================== + + - name: "Deploy CloudFormation stack {{ local_stack_name }}" + amazon.aws.cloudformation: + stack_name: "{{ local_stack_name }}" + state: present + region: "{{ local_region_name }}" + profile: "{{ pbk_account_name }}" + template: "templates/vpc.cfn.yml" + tags: "{{ local_aws_tags }}" + template_parameters: + AccountName: "{{ pbk_account_name }}" + AccountCode: "{{ pbk_account_code }}" + RegionCode: "{{ local_region_code }}" + Application: "{{ application }}" + VpcCidr: "{{ pbk_account.vpc_cidr }}" + PublicSubnetCidrAz1: "{{ pbk_account.web_public_subnet_az1_cidr }}" + PublicSubnetCidrAz2: "{{ pbk_account.web_public_subnet_az2_cidr }}" + AppPrivateSubnetCidrAz1: "{{ pbk_account.app_private_subnet_az1_cidr }}" + AppPrivateSubnetCidrAz2: "{{ pbk_account.app_private_subnet_az2_cidr }}" + SsmVpcIdKey: "{{ ssm_vpc_id_key }}" + SsmPublicSubnetsKey: "{{ ssm_web_public_subnets_id_key }}" + SsmAppPrivateSubnetsKey: "{{ ssm_app_private_subnets_id_key }}" + vars: + local_region_name: "{{ default_aws_region }}" + local_region_code: "{{ default_aws_region_code }}" + local_stack_name: "{{ pbk_account_code }}-{{ local_region_code }}-{{ application }}-vpc" + local_aws_tags: + Application: "{{ application }}" + Environment: "{{ pbk_account_env }}" + Name: "{{ local_stack_name }}" + tags: + - vpc diff --git a/aws-eb-bluegreen/eb-bluegreen-infra/infra/templates/vpc.cfn.yml b/aws-eb-bluegreen/eb-bluegreen-infra/infra/templates/vpc.cfn.yml new file mode 100644 index 0000000..b94f6f2 --- /dev/null +++ b/aws-eb-bluegreen/eb-bluegreen-infra/infra/templates/vpc.cfn.yml @@ -0,0 +1,232 @@ +Parameters: + + AccountName: + Type: String + AccountCode: + Type: String + RegionCode: + Type: String + Application: + Type: String + VpcCidr: + Type: String + PublicSubnetCidrAz1: + Type: String + PublicSubnetCidrAz2: + Type: String + AppPrivateSubnetCidrAz1: + Type: String + AppPrivateSubnetCidrAz2: + Type: String + SsmVpcIdKey: + Type: String + SsmPublicSubnetsKey: + Type: String + SsmAppPrivateSubnetsKey: + Type: String + +Resources: + + #================ + # VPC + #================ + + Vpc: + Type: AWS::EC2::VPC + Properties: + CidrBlock: !Ref VpcCidr + EnableDnsSupport: true + EnableDnsHostnames: true + Tags: + - Key: Name + Value: !Sub ${AccountCode}-${RegionCode}-${Application} + + #================ + # Subnets + #================ + + PublicSubnetAz1: + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref Vpc + CidrBlock: !Ref PublicSubnetCidrAz1 + AvailabilityZone: !Select [ 0, !GetAZs ] + Tags: + - Key: Name + Value: !Sub ${AccountCode}-${RegionCode}-${Application}-public-1a + + PublicSubnetAz2: + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref Vpc + CidrBlock: !Ref PublicSubnetCidrAz2 + AvailabilityZone: !Select [ 1, !GetAZs ] + Tags: + - Key: Name + Value: !Sub ${AccountCode}-${RegionCode}-${Application}-public-1b + + AppPrivateSubnetAz1: + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref Vpc + CidrBlock: !Ref AppPrivateSubnetCidrAz1 + AvailabilityZone: !Select [ 0, !GetAZs ] + Tags: + - Key: Name + Value: !Sub ${AccountCode}-${RegionCode}-${Application}-app-private-1a + + AppPrivateSubnetAz2: + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref Vpc + CidrBlock: !Ref AppPrivateSubnetCidrAz2 + AvailabilityZone: !Select [ 1, !GetAZs ] + Tags: + - Key: Name + Value: !Sub ${AccountCode}-${RegionCode}-${Application}-app-private-1b + + #================= + # Internet Gateway + #================= + + InternetGateway: + Type: AWS::EC2::InternetGateway + Properties: + Tags: + - Key: Name + Value: !Sub ${AccountCode}-${RegionCode}-${Application}-igw + + VPCGatewayAttachment: + Type: AWS::EC2::VPCGatewayAttachment + Properties: + InternetGatewayId: !Ref InternetGateway + VpcId: !Ref Vpc + + PublicRouteTable: + Type: AWS::EC2::RouteTable + Properties: + VpcId: !Ref Vpc + Tags: + - Key: Name + Value: !Sub ${AccountCode}-${RegionCode}-${Application}-public-az + + RouteInternetGateway: + Type: AWS::EC2::Route + DependsOn: + - PublicRouteTable + Properties: + DestinationCidrBlock: 0.0.0.0/0 + GatewayId: !Ref InternetGateway + RouteTableId: !Ref PublicRouteTable + + # SubnetRouteTableAssociation (public only here) + + PublicSubnetAz1RouteTableAssociation: + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + RouteTableId: !Ref PublicRouteTable + SubnetId: !Ref PublicSubnetAz1 + + PublicSubnetAz2RouteTableAssociation: + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + RouteTableId: !Ref PublicRouteTable + SubnetId: !Ref PublicSubnetAz2 + + #================ + # NAT Gateway + #================ + + PublicSubnetAz1NATGatewayEIP: + Type: AWS::EC2::EIP + Properties: + Domain: vpc + Tags: + - Key: Name + Value: !Sub ${AccountCode}-${RegionCode}-${Application}-nat-az1-eip + +# -- NAT in public subnets + + PublicSubnetAz1NatGateway: + Type: AWS::EC2::NatGateway + Properties: + AllocationId: !GetAtt PublicSubnetAz1NATGatewayEIP.AllocationId + SubnetId: !Ref PublicSubnetAz1 + Tags: + - Key: Name + Value: !Sub ${AccountCode}-${RegionCode}-${Application}-public-1a + +# RouteTable + +# -- private-rt + + AppPrivateSubnetAz1RouteTable: + Type: AWS::EC2::RouteTable + Properties: + VpcId: !Ref Vpc + Tags: + - Key: Name + Value: !Sub ${AccountCode}-${RegionCode}-${Application}-app-private-1a + + AppPrivateSubnetAz2RouteTable: + Type: AWS::EC2::RouteTable + Properties: + VpcId: !Ref Vpc + Tags: + - Key: Name + Value: !Sub ${AccountCode}-${RegionCode}-${Application}-app-private-1b + + # SubnetRouteTableAssociation (private only here) + + AppPrivateSubnetAz1RouteTableAssociation: + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + RouteTableId: !Ref AppPrivateSubnetAz1RouteTable + SubnetId: !Ref AppPrivateSubnetAz1 + + AppPrivateSubnetAz2RouteTableAssociation: + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + RouteTableId: !Ref AppPrivateSubnetAz2RouteTable + SubnetId: !Ref AppPrivateSubnetAz2 + +# Route to NAT + + AppPrivateSubnetAz1Route: + Type: AWS::EC2::Route + Properties: + DestinationCidrBlock: 0.0.0.0/0 + RouteTableId: !Ref AppPrivateSubnetAz1RouteTable + NatGatewayId: !Ref PublicSubnetAz1NatGateway + + AppPrivateSubnetAz2Route: + Type: AWS::EC2::Route + Properties: + DestinationCidrBlock: 0.0.0.0/0 + RouteTableId: !Ref AppPrivateSubnetAz2RouteTable + NatGatewayId: !Ref PublicSubnetAz1NatGateway + + #================ + # SSM Parameters + #================ + + SsmVpcId: + Type: AWS::SSM::Parameter + Properties: + Type: String + Name: !Ref SsmVpcIdKey + Value: !Ref Vpc + + SsmPublicSubnetsId: + Type: AWS::SSM::Parameter + Properties: + Type: StringList + Name: !Ref SsmPublicSubnetsKey + Value: !Join [ ',', [ !Ref PublicSubnetAz1, !Ref PublicSubnetAz2 ] ] + + SsmAppPrivateSubnetsId: + Type: AWS::SSM::Parameter + Properties: + Type: StringList + Name: !Ref SsmAppPrivateSubnetsKey + Value: !Join [ ',', [ !Ref AppPrivateSubnetAz1, !Ref AppPrivateSubnetAz2 ] ] diff --git a/aws-eb-bluegreen/eb-bluegreen-infra/init/main.asb.yml b/aws-eb-bluegreen/eb-bluegreen-infra/init/main.asb.yml new file mode 100644 index 0000000..ade266c --- /dev/null +++ b/aws-eb-bluegreen/eb-bluegreen-infra/init/main.asb.yml @@ -0,0 +1,57 @@ +--- +- hosts: localhost + connection: local + gather_facts: false + + vars_files: + - ../vars/common-vars.asb.yml + + tasks: + + - name: "Deploy CloudFormation stack {{ local_stack_name }}" + amazon.aws.cloudformation: + stack_name: "{{ local_stack_name }}" + state: present + region: "{{ local_region_name }}" + profile: "{{ local_account_name }}" + template: "templates/buckets-use1.cfn.yml" + tags: "{{ local_aws_tags }}" + template_parameters: + SsmAssetsBucketNameKey: "{{ ssm_assets_bucket_name_key }}" + SsmLogsBucketNameKey: "{{ ssm_logs_bucket_name_key }}" + SsmVaultBucketNameKey: "{{ ssm_vault_bucket_name_key }}" + AwsElbAccountId: "{{ aws_config[local_region_name].elb_account_id }}" + vars: + local_account: "{{ aws_accounts.labs }}" + local_account_name: "{{ local_account.account_name }}" + local_account_code: "{{ local_account.account_code }}" + local_region_name: "{{ default_aws_region }}" + local_region_code: "{{ default_aws_region_code }}" + local_stack_name: "{{ local_account_code }}-{{ local_region_code }}-{{ application }}-buckets" + local_aws_tags: + Application: "{{ application }}" + Environment: "{{ local_account.environment }}" + Name: "{{ local_stack_name }}" + + - name: "Deploy CloudFormation stack {{ local_stack_name }}" + amazon.aws.cloudformation: + stack_name: "{{ local_stack_name }}" + state: present + region: "{{ local_region_name }}" + profile: "{{ local_account_name }}" + template: "templates/codecommit.cfn.yml" + tags: "{{ local_aws_tags }}" + template_parameters: + AppRepoName: "{{ repo_app }}" + InfraRepoName: "{{ repo_infra }}" + vars: + local_account: "{{ aws_accounts.labs }}" + local_account_name: "{{ local_account.account_name }}" + local_account_code: "{{ local_account.account_code }}" + local_region_name: "{{ default_aws_region }}" + local_region_code: "{{ default_aws_region_code }}" + local_stack_name: "{{ local_account_code }}-{{ local_region_code }}-{{ application }}-codecommit" + local_aws_tags: + Application: "{{ application }}" + Environment: "{{ local_account.environment }}" + Name: "{{ local_stack_name }}" diff --git a/aws-eb-bluegreen/eb-bluegreen-infra/init/templates/buckets-use1.cfn.yml b/aws-eb-bluegreen/eb-bluegreen-infra/init/templates/buckets-use1.cfn.yml new file mode 100644 index 0000000..f78348b --- /dev/null +++ b/aws-eb-bluegreen/eb-bluegreen-infra/init/templates/buckets-use1.cfn.yml @@ -0,0 +1,119 @@ +Parameters: + + SsmAssetsBucketNameKey: + Type: String + SsmLogsBucketNameKey: + Type: String + SsmVaultBucketNameKey: + Type: String + AwsElbAccountId: + Type: String + +Resources: + + AssetsBucket: + Type: AWS::S3::Bucket + Properties: + AccessControl: Private + PublicAccessBlockConfiguration: + BlockPublicAcls: true + BlockPublicPolicy: true + IgnorePublicAcls: true + RestrictPublicBuckets: true + BucketEncryption: + ServerSideEncryptionConfiguration: + - ServerSideEncryptionByDefault: + SSEAlgorithm: AES256 + + SsmAssetsBuckets: + Type: AWS::SSM::Parameter + Properties: + Type: String + Name: !Ref SsmAssetsBucketNameKey + Value: !Ref AssetsBucket + + LogsBucket: + Type: AWS::S3::Bucket + Properties: + AccessControl: Private + PublicAccessBlockConfiguration: + BlockPublicAcls: true + BlockPublicPolicy: true + IgnorePublicAcls: true + RestrictPublicBuckets: true + BucketEncryption: + ServerSideEncryptionConfiguration: + - ServerSideEncryptionByDefault: + SSEAlgorithm: AES256 + + LogsBucketPolicy: + Type: AWS::S3::BucketPolicy + Properties: + Bucket: !Ref LogsBucket + PolicyDocument: + Version: 2012-10-17 + Statement: + - Sid: AllowSSLRequestsOnly + Effect: Deny + Principal: '*' + Action: s3:* + Resource: + - !Sub arn:aws:s3:::${LogsBucket} + - !Sub arn:aws:s3:::${LogsBucket}/* + Condition: + Bool: + 'aws:SecureTransport': false + - Sid: DenyDeleteObjectVersion + Effect: Deny + Principal: '*' + Action: s3:DeleteObjectVersion + Resource: !Sub arn:aws:s3:::${LogsBucket}/* + - Sid: AWSLogDeliveryRead + Effect: Allow + Principal: + Service: delivery.logs.amazonaws.com + Action: s3:GetBucketAcl + Resource: !Sub arn:aws:s3:::${LogsBucket} + - Sid: AWSLogDeliveryWrite + Effect: Allow + Principal: + Service: delivery.logs.amazonaws.com + Action: s3:PutObject + Resource: !Sub arn:aws:s3:::${LogsBucket}/* + Condition: + StringEquals: + s3:x-amz-acl: bucket-owner-full-control + - Sid: AWSELBWrite + Effect: Allow + Principal: + AWS: !Sub arn:aws:iam::${AwsElbAccountId}:root # AWS account + Action: s3:PutObject + Resource: !Sub arn:aws:s3:::${LogsBucket}/* + + SsmLogsBucketName: + Type: AWS::SSM::Parameter + Properties: + Type: String + Name: !Ref SsmLogsBucketNameKey + Value: !Ref LogsBucket + + VaultBucket: + Type: AWS::S3::Bucket + Properties: + AccessControl: Private + PublicAccessBlockConfiguration: + BlockPublicAcls: true + BlockPublicPolicy: true + IgnorePublicAcls: true + RestrictPublicBuckets: true + BucketEncryption: + ServerSideEncryptionConfiguration: + - ServerSideEncryptionByDefault: + SSEAlgorithm: AES256 + + SsmVaultBuckets: + Type: AWS::SSM::Parameter + Properties: + Type: String + Name: !Ref SsmVaultBucketNameKey + Value: !Ref VaultBucket diff --git a/aws-eb-bluegreen/eb-bluegreen-infra/init/templates/codecommit.cfn.yml b/aws-eb-bluegreen/eb-bluegreen-infra/init/templates/codecommit.cfn.yml new file mode 100644 index 0000000..1b138f1 --- /dev/null +++ b/aws-eb-bluegreen/eb-bluegreen-infra/init/templates/codecommit.cfn.yml @@ -0,0 +1,19 @@ +Parameters: + + AppRepoName: + Type: String + InfraRepoName: + Type: String + +Resources: + + AppRepository: + Type: AWS::CodeCommit::Repository + Properties: + RepositoryName: !Ref AppRepoName + + InfraRepository: + Type: AWS::CodeCommit::Repository + Properties: + RepositoryName: !Ref InfraRepoName + diff --git a/aws-eb-bluegreen/eb-bluegreen-infra/vars/common-vars.asb.yml b/aws-eb-bluegreen/eb-bluegreen-infra/vars/common-vars.asb.yml new file mode 100644 index 0000000..e2eb1cf --- /dev/null +++ b/aws-eb-bluegreen/eb-bluegreen-infra/vars/common-vars.asb.yml @@ -0,0 +1,82 @@ +# https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-access-logs.html#access-logging-bucket-permissions +aws_config: + 'us-east-2': + elb_account_id: '033677994240' + 'us-east-1': + elb_account_id: '127311923021' + 'us-west-1': + elb_account_id: '027434742980' + 'us-west-2': + elb_account_id: '797873946194' + 'af-south-1': + elb_account_id: '098369216593' + 'ap-east-1': + elb_account_id: '754344448648' + 'ap-south-1': + elb_account_id: '718504428378' + 'ap-northeast-3': + elb_account_id: '383597477331' + 'ap-northeast-2': + elb_account_id: '600734575887' + 'ap-southeast-1': + elb_account_id: '114774131450' + 'ap-southeast-2': + elb_account_id: '783225319266' + 'ap-northeast-1': + elb_account_id: '582318560864' + 'ca-central-1': + elb_account_id: '985666609251' + 'cn-north-1': + elb_account_id: '638102146993' + 'cn-northwest-1': + elb_account_id: '037604701340' + 'eu-central-1': + elb_account_id: '054676820928' + 'eu-west-1': + elb_account_id: '156460612806' + 'eu-west-2': + elb_account_id: '652711504416' + 'eu-south-1': + elb_account_id: '635631232127' + 'eu-west-3': + elb_account_id: '009996457667' + 'eu-north-1': + elb_account_id: '897822967062' + 'me-south-1': + elb_account_id: '076674570225' + 'sa-east-1': + elb_account_id: '507241528517' + 'us-gov-east-1': + elb_account_id: '190560391635' + 'us-gov-west-1': + elb_account_id: '048591011584' + +application: eb-bluegreen + +default_aws_region: us-east-1 +default_aws_region_code: use1 + +# S3 +ssm_assets_bucket_name_key: /eb-bluegreen/cfn/bucket/assets +ssm_logs_bucket_name_key: /eb-bluegreen/cfn/bucket/logs +ssm_vault_bucket_name_key: /eb-bluegreen/cfn/bucket/vault + +# CodeCommit +repo_app: eb-bluegreen-app +repo_infra: eb-bluegreen-infra + +# VPC +ssm_vpc_id_key: /eb-bluegreen/cfn/vpc/id +ssm_web_public_subnets_id_key: /eb-bluegreen/cfn/vpc/subnet/web/public/ids +ssm_app_private_subnets_id_key: /eb-bluegreen/cfn/vpc/subnet/app/private/ids + +aws_accounts: + labs: + account_name: spikeseed-labs + account_code: l + environment: lab + vpc_cidr: 10.68.102.0/23 + web_public_subnet_az1_cidr: 10.68.102.0/26 + web_public_subnet_az2_cidr: 10.68.102.64/26 + app_private_subnet_az1_cidr: 10.68.103.0/26 + app_private_subnet_az2_cidr: 10.68.103.64/26