From da3438de4d455d8c46fd72016aba5bd335c9e6d8 Mon Sep 17 00:00:00 2001 From: Carlos Santos Date: Tue, 22 Mar 2022 13:06:48 -0700 Subject: [PATCH 01/20] feature: Initial check-in of .NET Fx template --- .../README.md | 351 +++++++++ .../microservices-env/v1/.compatible-envs | 2 + .../cloudformation.yaml | 284 +++++++ .../v1/instance_infrastructure/manifest.yaml | 5 + .../cloudformation.yaml | 718 ++++++++++++++++++ .../v1/pipeline_infrastructure/manifest.yaml | 5 + .../microservices-env/v1/schema/schema.yaml | 39 + .../v1/.compatible-envs | 1 + .../cloudformation.yaml | 346 +++++++++ .../v1/instance_infrastructure/manifest.yaml | 5 + .../cloudformation.yaml | 709 +++++++++++++++++ .../v1/pipeline_infrastructure/manifest.yaml | 5 + .../v1/schema/schema.yaml | 57 ++ .../private-fargate-svc/v1/.compatible-envs | 1 + .../cloudformation.yaml | 102 +++ .../v1/instance_infrastructure/manifest.yaml | 5 + .../cloudformation.yaml | 709 +++++++++++++++++ .../v1/pipeline_infrastructure/manifest.yaml | 5 + .../private-fargate-svc/v1/schema/schema.yaml | 57 ++ .../proton-service-assume-policy.json | 12 + .../specs/env-spec.yaml | 3 + .../specs/svc-private-spec.yaml | 13 + .../specs/svc-public-spec.yaml | 13 + 23 files changed, 3447 insertions(+) create mode 100644 public-private-fargate-microservices-dotnetfx/README.md create mode 100644 public-private-fargate-microservices-dotnetfx/microservices-env/v1/.compatible-envs create mode 100644 public-private-fargate-microservices-dotnetfx/microservices-env/v1/instance_infrastructure/cloudformation.yaml create mode 100644 public-private-fargate-microservices-dotnetfx/microservices-env/v1/instance_infrastructure/manifest.yaml create mode 100644 public-private-fargate-microservices-dotnetfx/microservices-env/v1/pipeline_infrastructure/cloudformation.yaml create mode 100644 public-private-fargate-microservices-dotnetfx/microservices-env/v1/pipeline_infrastructure/manifest.yaml create mode 100644 public-private-fargate-microservices-dotnetfx/microservices-env/v1/schema/schema.yaml create mode 100644 public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/.compatible-envs create mode 100644 public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/instance_infrastructure/cloudformation.yaml create mode 100644 public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/instance_infrastructure/manifest.yaml create mode 100644 public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/pipeline_infrastructure/cloudformation.yaml create mode 100644 public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/pipeline_infrastructure/manifest.yaml create mode 100644 public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/schema/schema.yaml create mode 100644 public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/.compatible-envs create mode 100644 public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/instance_infrastructure/cloudformation.yaml create mode 100644 public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/instance_infrastructure/manifest.yaml create mode 100644 public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/pipeline_infrastructure/cloudformation.yaml create mode 100644 public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/pipeline_infrastructure/manifest.yaml create mode 100644 public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/schema/schema.yaml create mode 100644 public-private-fargate-microservices-dotnetfx/policies/proton-service-assume-policy.json create mode 100644 public-private-fargate-microservices-dotnetfx/specs/env-spec.yaml create mode 100644 public-private-fargate-microservices-dotnetfx/specs/svc-private-spec.yaml create mode 100644 public-private-fargate-microservices-dotnetfx/specs/svc-public-spec.yaml diff --git a/public-private-fargate-microservices-dotnetfx/README.md b/public-private-fargate-microservices-dotnetfx/README.md new file mode 100644 index 0000000..d3c1129 --- /dev/null +++ b/public-private-fargate-microservices-dotnetfx/README.md @@ -0,0 +1,351 @@ +# AWS Proton Sample .NET Framework Microservices Using Amazon ECS and AWS Fargate + +This directory contains a sample AWS Proton Environment and Service templates for a set of .NET Framework 4.8 microservices deployed to Amazon ECS based using service discovery running on AWS Fargate and a CI/CD pipeline used to deploy updates, as well as sample specs for creating Proton Environments and Services using the templates. All resources deployed are tagged. + +The environment template deploys: + +- a VPC +- an Internet Gateway +- 2 Nat Gateways across 2 Availability Zones +- 2 private subnets across 2 Availability Zones +- 2 public subnets across 2 Availability Zones +- an ECS Cluster +- a private namespace for service discovery + +The service templates contains all the resources required to create a public ECS Fargate service behind a load balancer and a private ECS Fargate service in that environment. It also provides sample specs for creating Proton Environments and Services using the templates. + +Developers provisioning their services can configure the following properties through their service spec: + +- Fargate CPU size +- Fargate memory size +- Number of running containers +- Choose private or public subnets to run the loadbalanced service or the private service, accessed via service discovery +- Service name to register and use for service discovery + +If you need application code to run in the services: +* https://github.com/aws-quickstart/quickstart-dotnetfx-ecs-cicd + +# Registering and deploying these templates + +You can register and deploy these templates by using the AWS Proton console. To do this, you will need to compress the templates using the instructions below, upload them to an S3 bucket, and use the Proton console to register and test them. If you prefer to use the Command Line Interface, follow the instructions below: + +## Prerequisites + +First, make sure you have the AWS CLI installed, and configured. Run the following command to set the AWS region and an `account_id` environment variable: + +```bash +export AWS_DEFAULT_REGION=us-west-2 +account_id=`aws sts get-caller-identity --query Account --output text` +``` + +### Configure IAM Role, S3 Bucket, and CodeStar Connections Connection + +Before you register your templates and deploy your environments and services, you will need to create an Amazon IAM role so that AWS Proton can manage resources in your AWS account, an Amazon S3 bucket to store your templates, and a CodeStar Connections connection to pull and deploy your application code. + +Create the S3 bucket to store your templates: + +``` +aws s3api create-bucket \ + --bucket "proton-cli-templates-${account_id}" \ + --create-bucket-configuration LocationConstraint=us-west-2 +``` + +Create the IAM role that Proton will assume to provision resources and manage AWS CloudFormation stacks in your AWS account. + +``` +aws iam create-role \ + --role-name ProtonServiceRole \ + --assume-role-policy-document file://./policies/proton-service-assume-policy.json + +aws iam attach-role-policy \ + --role-name ProtonServiceRole \ + --policy-arn arn:aws:iam::aws:policy/AdministratorAccess +``` + +Then, allow Proton to use that role to provision resources for your services' continuous delivery pipelines: + +``` +aws proton update-account-settings \ + --pipeline-service-role-arn "arn:aws:iam::${account_id}:role/ProtonServiceRole" +``` + +Create an AWS CodeStar Connections connection to your application code stored in a GitHub or Bitbucket source code repository. This connection allows CodePipeline to pull your application source code before building and deploying the code to your Proton service. To use sample application code for the public service, first create a fork of the sample application repository here: +https://github.com/aws-quickstart/quickstart-dotnetfx-ecs-cicd + +Creating the source code connection must be completed in the CodeStar Connections console: +https://us-west-2.console.aws.amazon.com/codesuite/settings/connections?region=us-west-2 + +## Register an Environment Template + +Register the sample environment template, which contains an ECS Cluster and a VPC with two public subnets. + +First, create an environment template, which will contain all of the environment template's versions. + +``` +aws proton create-environment-template \ + --name "aws-proton-fargate-microservices-dotnetfx" \ + --display-name "aws proton fargate microservices-dotnetfx" \ + --description "Proton Example Dev VPC with Public facing services and with Private backend services on ECS cluster with Fargate compute" +``` + +Now create a version which contains the contents of the sample environment template. Compress the sample template files and register the version: + +``` +tar -zcvf env-template.tar.gz environment/ + +aws s3 cp env-template.tar.gz s3://proton-cli-templates-${account_id}/env-template.tar.gz + +rm env-template.tar.gz + +aws proton create-environment-template-version \ + --template-name "aws-proton-fargate-microservices-dotnetfx" \ + --description "Proton Example Dev Environment Version 1" \ + --source s3="{bucket=proton-cli-templates-${account_id},key=env-template.tar.gz}" +``` + +Wait for the environment template version to be successfully registered. + +``` +aws proton wait environment-template-version-registered \ + --template-name "aws-proton-fargate-microservices-dotnetfx" \ + --major-version "1" \ + --minor-version "0" +``` + +You can now publish the environment template version, making it available for users in your AWS account to create Proton environments. + +``` +aws proton update-environment-template-version \ + --template-name "aws-proton-fargate-microservices-dotnetfx" \ + --major-version "1" \ + --minor-version "0" \ + --status "PUBLISHED" +``` + +## Register the Service Templates + +Register the sample service template, which contains all the resources required to provision an ECS Fargate service behind a load balancer, the private services as well as a continuous delivery pipeline using AWS CodePipeline for each. + +First, create the service template. + +``` +aws proton create-service-template \ + --name "lb-public-fargate-svc-dotnetfx" \ + --display-name "PublicLoadbalancedDotNetFargateService" \ + --description ".NET Framework Windows Fargate Service with an Application Load Balancer" +``` + +Now create a version which contains the contents of the sample service template. Compress the sample template files and register the version: + +``` +tar -zcvf svc-public-template.tar.gz service/loadbalanced-public-svc/ + +aws s3 cp svc-public-template.tar.gz s3://proton-cli-templates-${account_id}/svc-public-template.tar.gz + +rm svc-public-template.tar.gz + +aws proton create-service-template-version \ + --template-name "lb-public-fargate-svc-dotnetfx" \ + --description "Version 1" \ + --source s3="{bucket=proton-cli-templates-${account_id},key=svc-public-template.tar.gz}" \ + --compatible-environment-templates '[{"templateName":"aws-proton-fargate-microservices-dotnetfx","majorVersion":"1"}]' +``` + +Wait for the service template version to be successfully registered. + +``` +aws proton wait service-template-version-registered \ + --template-name "lb-public-fargate-svc-dotnetfx" \ + --major-version "1" \ + --minor-version "0" +``` + +You can now publish the Public service template version, making it available for users in your AWS account to create Proton services. + +``` +aws proton update-service-template-version \ + --template-name "lb-public-fargate-svc-dotnetfx" \ + --major-version "1" \ + --minor-version "0" \ + --status "PUBLISHED" +``` + +### Second, create the Private service template. + +``` +aws proton create-service-template \ + --name "private-fargate-svc-dotnetfx" \ + --display-name "PrivateBackendDotNetFargateService" \ + --description ".NET Framework Windows Private Backend Fargate Service" +``` + +Now create a version which contains the contents of the sample service template. Compress the sample template files and register the version: + +``` +tar -zcvf svc-private-template.tar.gz service/private-fargate-svc-dotnetfx/ + +aws s3 cp svc-private-template.tar.gz s3://proton-cli-templates-${account_id}/svc-private-template.tar.gz + +rm svc-private-template.tar.gz + +aws proton create-service-template-version \ + --template-name "private-fargate-svc-dotnetfx" \ + --description "Version 1" \ + --source s3="{bucket=proton-cli-templates-${account_id},key=svc-private-template.tar.gz}" \ + --compatible-environment-templates '[{"templateName":"aws-proton-fargate-microservices-dotnetfx","majorVersion":"1"}]' +``` + +Wait for the service template version to be successfully registered. + +``` +aws proton wait service-template-version-registered \ + --template-name "private-fargate-svc-dotnetfx" \ + --major-version "1" \ + --minor-version "0" +``` + +You can now publish the Public service template version, making it available for users in your AWS account to create Proton services. + +``` +aws proton update-service-template-version \ + --template-name "private-fargate-svc-dotnetfx" \ + --major-version "1" \ + --minor-version "0" \ + --status "PUBLISHED" +``` + +## Deploy An Environment + +With the registered and published environment template, you can now instantiate a Proton environment from the template. + +You can use two different environment provisioning methods when you create environments. + +* Create, manage and provision an environment in a single account. + +* In a single management account create and manage an environment that is provisioned in another account with environment account connections. For more information, see [Create an environment in one account and provision in another account](https://docs.aws.amazon.com/proton/latest/adminguide/ag-create-env.html#ag-create-env-deploy-other) and [Environment account connections](https://docs.aws.amazon.com/proton/latest/adminguide/ag-env-account-connections.html). + +### Create and Provision Environment in a single account + +First, deploy a Proton environment. This command reads your environment spec at `specs/env-spec.yaml`, merges it with the environment template created above, and deploys the resources in a CloudFormation stack in your AWS account using the Proton service role. + +``` +aws proton create-environment \ + --name "Beta" \ + --template-name aws-proton-fargate-microservices-dotnetfx \ + --template-major-version 1 \ + --proton-service-role-arn arn:aws:iam::${account_id}:role/ProtonServiceRole \ + --spec file://specs/env-spec.yaml +``` + +Wait for the environment to successfully deploy. + +``` +aws proton wait environment-deployed --name Beta + +aws proton get-environment --name Beta +``` +### Create Environment in one account and Provision in another account + +First, log into the environment account where you want to provision the environment resources and create the IAM role that Proton will assume to provision resources and manage AWS CloudFormation stacks in your AWS account. +This can also be done from the console. https://docs.aws.amazon.com/proton/latest/adminguide/security_iam_service-role-policy-examples.html#proton-svc-role + +```bash +environment_account_id=`your_environment_account_id` + +aws iam create-role \ + --role-name ProtonServiceRole \ + --assume-role-policy-document file://./policies/proton-service-assume-policy.json + +aws iam attach-role-policy \ + --role-name ProtonServiceRole \ + --policy-arn arn:aws:iam::aws:policy/AdministratorAccess +``` + +Then, create and send an environment account connection request to your management account. When the request is accepted, AWS Proton can use the associated IAM role that permits environment resource provisioning in the associated environment account. +You need to specify the environment name that you will use for the environment. + +```bash +aws proton create-environment-account-connection \ + --management-account-id ${account_id} \ + --environment-name "Beta" \ + --role-arn arn:aws:iam::${environment_account_id}:role/ProtonServiceRole + +environment_account_connection_id=`replace_with_the_environment_account_connection_id_returned_above` +``` + +Log into the management account and accept the environment account connection request from your environment account. This can also be done from the console. + +```bash +aws proton accept-environment-account-connection --id ${environment_account_connection_id} +``` + +Then, create a Proton environment. This command reads your environment spec at `specs/env-spec.yaml`, merges it with the environment template created above, and deploys the resources in a CloudFormation stack in your environment AWS account using the Proton service role attached to the environment account connection. + +```bash +aws proton create-environment \ + --name "Beta" \ + --template-name aws-proton-fargate-microservices-dotnetfx \ + --template-major-version 1 \ + --environment-account-connection-id ${environment_account_connection_id} \ + --spec file://specs/env-spec.yaml +``` + +Wait for the environment to successfully deploy. Use the `get` call to check for deployment status: + +```bash +aws proton wait environment-deployed --name Beta + +aws proton get-environment --name Beta +``` + +## Deploy A Service + +With the registered and published service template and deployed environment, you can now create a Proton service and deploy it into your Proton environment. + +This command reads your service spec at `specs/svc-public--spec.yaml`, merges it with the service template created above, and deploys the resources in CloudFormation stacks in the AWS account of the environment. +The service will provision a Lambda-based CRUD API endpoint and a CodePipeline pipeline to deploy your application code. + +Fill in your CodeStar Connections connection ID and your source code repository details in this command. + +``` +aws proton create-service \ + --name "front-end" \ + --repository-connection-arn arn:aws:codestar-connections:us-west-2:${account_id}:connection/ \ + --repository-id "/" \ + --branch "main" \ + --template-major-version 1 \ + --template-name lb-public-fargate-svc-dotnetfx \ + --spec file://specs/svc-public-spec.yaml +``` + +Wait for the service to successfully deploy. + +``` +aws proton wait service-created --name front-end + +aws proton get-service --name front-end +``` + +And finally, create a Private Proton service and deploy it into your Proton environment. This command reads your service spec at `specs/svc-private-spec.yaml`, merges it with the service template created above, and deploys the resources in CloudFormation stacks in your AWS account using the Proton service role. The service will provision a private ECS service running on Fargate and a CodePipeline pipeline to deploy your application code. + + +Fill in your CodeStar Connections connection ID and your source code repository details in this command. + +``` +aws proton create-service \ + --name "back-end" \ + --repository-connection-arn arn:aws:codestar-connections:us-west-2:${account_id}:connection/ \ + --repository-id "/" \ + --branch "main" \ + --template-major-version 1 \ + --template-name private-fargate-svc-dotnetfx \ + --spec file://specs/svc-private-spec.yaml +``` + +Wait for the service to successfully deploy. + +``` +aws proton wait service-created --name back-end + +aws proton get-service --name back-end +``` \ No newline at end of file diff --git a/public-private-fargate-microservices-dotnetfx/microservices-env/v1/.compatible-envs b/public-private-fargate-microservices-dotnetfx/microservices-env/v1/.compatible-envs new file mode 100644 index 0000000..4efda05 --- /dev/null +++ b/public-private-fargate-microservices-dotnetfx/microservices-env/v1/.compatible-envs @@ -0,0 +1,2 @@ +microservices-env:1 + diff --git a/public-private-fargate-microservices-dotnetfx/microservices-env/v1/instance_infrastructure/cloudformation.yaml b/public-private-fargate-microservices-dotnetfx/microservices-env/v1/instance_infrastructure/cloudformation.yaml new file mode 100644 index 0000000..f523191 --- /dev/null +++ b/public-private-fargate-microservices-dotnetfx/microservices-env/v1/instance_infrastructure/cloudformation.yaml @@ -0,0 +1,284 @@ +AWSTemplateFormatVersion: '2010-09-09' +Description: AWS Fargate cluster running containers in public and private subnets. Supports + public facing microservices behind load balancer, private microservices, and private service discovery namespaces. Deployed resources are all tagged with defined environment name tag. +Mappings: + # The VPC and subnet configuration is passed in via the environment spec. + EnvironmentNameConfig: + Environment: + Name: '{{ environment.name}}' + SubnetConfig: + VPC: + CIDR: '{{ environment.inputs.vpc_cidr}}' + PublicOne: + CIDR: '{{ environment.inputs.public_subnet_one_cidr}}' + PublicTwo: + CIDR: '{{ environment.inputs.public_subnet_two_cidr}}' + PrivateOne: + CIDR: '{{ environment.inputs.private_subnet_one_cidr}}' + PrivateTwo: + CIDR: '{{ environment.inputs.private_subnet_two_cidr}}' + ServiceDiscoveryConfig: + PrivateNamespace: + Name: '{{ environment.inputs.service_discovery_namespace}}' + +Resources: + # Create the VPC with subnets across 2 Availability Zones, 2 Public subnets, 2 Private subnets, + # an Internet Gateway, 2 Nat Gateways and the required routetables and routes + VPC: + Type: AWS::EC2::VPC + Properties: + CidrBlock: !FindInMap ['SubnetConfig', 'VPC', 'CIDR'] + EnableDnsHostnames: true + EnableDnsSupport: true + Tags: + - Key: Name + Value: !FindInMap ['EnvironmentNameConfig', 'Environment', 'Name'] + + InternetGateway: + Type: AWS::EC2::InternetGateway + Properties: + Tags: + - Key: Name + Value: !FindInMap ['EnvironmentNameConfig', 'Environment', 'Name'] + + InternetGatewayAttachment: + Type: AWS::EC2::VPCGatewayAttachment + Properties: + InternetGatewayId: !Ref InternetGateway + VpcId: !Ref VPC + + PublicSubnetOne: + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref VPC + AvailabilityZone: + Fn::Select: + - 0 + - Fn::GetAZs: {Ref: 'AWS::Region'} + CidrBlock: !FindInMap ['SubnetConfig', 'PublicOne', 'CIDR'] + MapPublicIpOnLaunch: true + Tags: + - Key: Name + Value: !FindInMap ['EnvironmentNameConfig', 'Environment', 'Name'] + + PublicSubnetTwo: + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref VPC + AvailabilityZone: + Fn::Select: + - 1 + - Fn::GetAZs: {Ref: 'AWS::Region'} + CidrBlock: !FindInMap ['SubnetConfig', 'PublicTwo', 'CIDR'] + MapPublicIpOnLaunch: true + Tags: + - Key: Name + Value: !FindInMap ['EnvironmentNameConfig', 'Environment', 'Name'] + + PrivateSubnetOne: + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref VPC + AvailabilityZone: + Fn::Select: + - 0 + - Fn::GetAZs: {Ref: 'AWS::Region'} + CidrBlock: !FindInMap ['SubnetConfig', 'PrivateOne', 'CIDR'] + MapPublicIpOnLaunch: false + Tags: + - Key: Name + Value: !FindInMap ['EnvironmentNameConfig', 'Environment', 'Name'] + + PrivateSubnetTwo: + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref VPC + AvailabilityZone: + Fn::Select: + - 1 + - Fn::GetAZs: {Ref: 'AWS::Region'} + CidrBlock: !FindInMap ['SubnetConfig', 'PrivateTwo', 'CIDR'] + MapPublicIpOnLaunch: false + Tags: + - Key: Name + Value: !FindInMap ['EnvironmentNameConfig', 'Environment', 'Name'] + + NatGatewayOneEIP: + Type: AWS::EC2::EIP + DependsOn: InternetGatewayAttachment + Properties: + Domain: vpc + Tags: + - Key: Name + Value: !FindInMap ['EnvironmentNameConfig', 'Environment', 'Name'] + + NatGatewayTwoEIP: + Type: AWS::EC2::EIP + DependsOn: InternetGatewayAttachment + Properties: + Domain: vpc + Tags: + - Key: Name + Value: !FindInMap ['EnvironmentNameConfig', 'Environment', 'Name'] + + NatGatewayOne: + Type: AWS::EC2::NatGateway + Properties: + AllocationId: !GetAtt NatGatewayOneEIP.AllocationId + SubnetId: !Ref PublicSubnetOne + Tags: + - Key: Name + Value: !FindInMap ['EnvironmentNameConfig', 'Environment', 'Name'] + + NatGatewayTwo: + Type: AWS::EC2::NatGateway + Properties: + AllocationId: !GetAtt NatGatewayTwoEIP.AllocationId + SubnetId: !Ref PublicSubnetTwo + Tags: + - Key: Name + Value: !FindInMap ['EnvironmentNameConfig', 'Environment', 'Name'] + + PublicRouteTable: + Type: AWS::EC2::RouteTable + Properties: + VpcId: !Ref VPC + Tags: + - Key: Name + Value: !FindInMap ['EnvironmentNameConfig', 'Environment', 'Name'] + + DefaultPublicRoute: + Type: AWS::EC2::Route + DependsOn: InternetGatewayAttachment + Properties: + RouteTableId: !Ref PublicRouteTable + DestinationCidrBlock: 0.0.0.0/0 + GatewayId: !Ref InternetGateway + + PublicSubnetOneRouteTableAssociation: + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + RouteTableId: !Ref PublicRouteTable + SubnetId: !Ref PublicSubnetOne + + PublicSubnetTwoRouteTableAssociation: + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + RouteTableId: !Ref PublicRouteTable + SubnetId: !Ref PublicSubnetTwo + + PrivateRouteTableOne: + Type: AWS::EC2::RouteTable + Properties: + VpcId: !Ref VPC + Tags: + - Key: Name + Value: !FindInMap ['EnvironmentNameConfig', 'Environment', 'Name'] + + DefaultPrivateRouteOne: + Type: AWS::EC2::Route + Properties: + RouteTableId: !Ref PrivateRouteTableOne + DestinationCidrBlock: 0.0.0.0/0 + NatGatewayId: !Ref NatGatewayOne + + PrivateSubnetOneRouteTableAssociation: + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + RouteTableId: !Ref PrivateRouteTableOne + SubnetId: !Ref PrivateSubnetOne + + PrivateRouteTableTwo: + Type: AWS::EC2::RouteTable + Properties: + VpcId: !Ref VPC + Tags: + - Key: Name + Value: !FindInMap ['EnvironmentNameConfig', 'Environment', 'Name'] + + DefaultPrivateRouteTwo: + Type: AWS::EC2::Route + Properties: + RouteTableId: !Ref PrivateRouteTableTwo + DestinationCidrBlock: 0.0.0.0/0 + NatGatewayId: !Ref NatGatewayTwo + + PrivateSubnetTwoRouteTableAssociation: + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + RouteTableId: !Ref PrivateRouteTableTwo + SubnetId: !Ref PrivateSubnetTwo + + # Create a Private namespace for Service Discovery + PrivateNamespace: + Type: AWS::ServiceDiscovery::PrivateDnsNamespace + Properties: + Name: !FindInMap ['ServiceDiscoveryConfig', 'PrivateNamespace', 'Name'] + Vpc: !Ref 'VPC' + + # Create the ECS Cluster to schedule and orchestrate the Fargate containers + ECSCluster: + Type: AWS::ECS::Cluster + Properties: + Tags: + - Key: Name + Value: !FindInMap ['EnvironmentNameConfig', 'Environment', 'Name'] + + # A security group for the containers we will run in Fargate. + # Rules are added to this security group based on what ingress you + # add for the cluster. + ContainerSecurityGroup: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: Access to the Fargate containers + VpcId: !Ref 'VPC' + Tags: + - Key: Name + Value: !FindInMap ['EnvironmentNameConfig', 'Environment', 'Name'] + + # This is a role which is used by the ECS tasks themselves. + ECSTaskExecutionRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Statement: + - Effect: Allow + Principal: + Service: [ecs-tasks.amazonaws.com] + Action: ['sts:AssumeRole'] + Path: / + ManagedPolicyArns: + - 'arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy' + Tags: + - Key: Name + Value: !FindInMap ['EnvironmentNameConfig', 'Environment', 'Name'] + +# These output values will be available to service templates to use. +Outputs: + ClusterName: + Description: The name of the ECS cluster + Value: !Ref 'ECSCluster' + ECSTaskExecutionRole: + Description: The ARN of the ECS role + Value: !GetAtt 'ECSTaskExecutionRole.Arn' + VpcId: + Description: The ID of the VPC that this stack is deployed in + Value: !Ref 'VPC' + PublicSubnetOne: + Description: A reference to the public subnet in the 1st Availability Zone + Value: !Ref 'PublicSubnetOne' + PublicSubnetTwo: + Description: A reference to the public subnet in the 2nd Availability Zone + Value: !Ref 'PublicSubnetTwo' + PrivateSubnetOne: + Description: A reference to the private subnet in the 1st Availability Zone + Value: !Ref 'PrivateSubnetOne' + PrivateSubnetTwo: + Description: A reference to the private subnet in the 2nd Availability Zone + Value: !Ref 'PrivateSubnetTwo' + ContainerSecurityGroup: + Description: A security group used to allow Fargate containers to receive traffic + Value: !Ref 'ContainerSecurityGroup' + PrivateNamespace: + Description: The NamespaceId registered for Service Discovery + Value: !Ref 'PrivateNamespace' diff --git a/public-private-fargate-microservices-dotnetfx/microservices-env/v1/instance_infrastructure/manifest.yaml b/public-private-fargate-microservices-dotnetfx/microservices-env/v1/instance_infrastructure/manifest.yaml new file mode 100644 index 0000000..eed587b --- /dev/null +++ b/public-private-fargate-microservices-dotnetfx/microservices-env/v1/instance_infrastructure/manifest.yaml @@ -0,0 +1,5 @@ +infrastructure: + templates: + - file: "cloudformation.yaml" + rendering_engine: jinja + template_language: cloudformation diff --git a/public-private-fargate-microservices-dotnetfx/microservices-env/v1/pipeline_infrastructure/cloudformation.yaml b/public-private-fargate-microservices-dotnetfx/microservices-env/v1/pipeline_infrastructure/cloudformation.yaml new file mode 100644 index 0000000..aa0289a --- /dev/null +++ b/public-private-fargate-microservices-dotnetfx/microservices-env/v1/pipeline_infrastructure/cloudformation.yaml @@ -0,0 +1,718 @@ +Resources: + FunctionBucket: + Type: AWS::S3::Bucket + DeletionPolicy: Retain + Properties: + VersioningConfiguration: + Status: Enabled + BucketEncryption: + ServerSideEncryptionConfiguration: + - ServerSideEncryptionByDefault: + SSEAlgorithm: 'AES256' + # This policy allows environment accounts to get the build artifacts from FunctionBucket in the management account + FunctionBucketPolicy: + Type: AWS::S3::BucketPolicy + Properties: + Bucket: !Ref FunctionBucket + PolicyDocument: + Version: 2012-10-17 + Statement: + - Action: + - 's3:GetObject' + Effect: Allow + Resource: !Join + - '' + - - 'arn:aws:s3:::' + - !Ref FunctionBucket + - /* + Principal: + AWS: + {% for service_instance in service_instances %} + - "arn:aws:iam::{{service_instance.environment.account_id}}:root" + {% endfor %} + BuildProject: + Type: AWS::CodeBuild::Project + Properties: + Artifacts: + Type: CODEPIPELINE + Environment: + ComputeType: BUILD_GENERAL1_SMALL + Image: aws/codebuild/amazonlinux2-x86_64-standard:3.0 + PrivilegedMode: true + Type: LINUX_CONTAINER + EnvironmentVariables: + - Name: bucket_name + Type: PLAINTEXT + Value: !Ref FunctionBucket + - Name: service_name + Type: PLAINTEXT + Value: '{{service.name}}' + ServiceRole: + Fn::GetAtt: + - PublishRole + - Arn + Source: + BuildSpec: >- + { + "version": "0.2", + "phases": { + "install": { + "runtime-versions": {{ + {"ruby2.7": {"ruby": "2.7"}, + "go1.x": {"golang": "1.x"}, + "nodejs12.x": {"nodejs": "12.x"}, + "python3.8": {"python": "3.8"}, + "java11": {"java": "openjdk11.x"}, + "dotnetcore3.1": {"dotnet": "3.1"} + }[service_instances[0].outputs.LambdaRuntime] | tojson | safe }}, + "commands": [ + "pip3 install --upgrade --user awscli", + "echo 'f6bd1536a743ab170b35c94ed4c7c4479763356bd543af5d391122f4af852460 yq_linux_amd64' > yq_linux_amd64.sha", + "wget https://github.com/mikefarah/yq/releases/download/3.4.0/yq_linux_amd64", + "sha256sum -c yq_linux_amd64.sha", + "mv yq_linux_amd64 /usr/bin/yq", + "chmod +x /usr/bin/yq" + ] + }, + "pre_build": { + "commands": [ + "cd $CODEBUILD_SRC_DIR", + "{{ pipeline.inputs.unit_test_command }}" + ] + }, + "build": { + "commands": [ + "{{ pipeline.inputs.packaging_command }}", + "FUNCTION_URI=s3://$bucket_name/$CODEBUILD_BUILD_NUMBER/function.zip", + "aws s3 cp function.zip $FUNCTION_URI" + ] + }, + "post_build": { + "commands": [ + "aws proton --region $AWS_DEFAULT_REGION get-service --name $service_name | jq -r .service.spec > service.yaml", + "yq w service.yaml 'instances[*].spec.code_uri' \"$FUNCTION_URI\" > rendered_service.yaml" + ] + } + }, + "artifacts": { + "files": [ + "rendered_service.yaml" + ] + } + } + Type: CODEPIPELINE + EncryptionKey: + Fn::GetAtt: + - PipelineArtifactsBucketEncryptionKey + - Arn +{% for service_instance in service_instances %} + Deploy{{loop.index}}Project: + Type: AWS::CodeBuild::Project + Properties: + Artifacts: + Type: CODEPIPELINE + Environment: + ComputeType: BUILD_GENERAL1_SMALL + Image: aws/codebuild/amazonlinux2-x86_64-standard:3.0 + PrivilegedMode: false + Type: LINUX_CONTAINER + EnvironmentVariables: + - Name: service_name + Type: PLAINTEXT + Value: '{{service.name}}' + - Name: service_instance_name + Type: PLAINTEXT + Value: '{{service_instance.name}}' + ServiceRole: + Fn::GetAtt: + - DeploymentRole + - Arn + Source: + BuildSpec: >- + { + "version": "0.2", + "phases": { + "build": { + "commands": [ + "pip3 install --upgrade --user awscli", + "aws proton --region $AWS_DEFAULT_REGION update-service-instance --deployment-type CURRENT_VERSION --name $service_instance_name --service-name $service_name --spec file://rendered_service.yaml", + "aws proton --region $AWS_DEFAULT_REGION wait service-instance-deployed --name $service_instance_name --service-name $service_name" + ] + } + } + } + Type: CODEPIPELINE + EncryptionKey: + Fn::GetAtt: + - PipelineArtifactsBucketEncryptionKey + - Arn +{% endfor %} + # This role is used to build and publish the lambda function to S3 + PublishRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Statement: + - Action: sts:AssumeRole + Effect: Allow + Principal: + Service: codebuild.amazonaws.com + Version: "2012-10-17" + PublishRoleDefaultPolicy: + Type: AWS::IAM::Policy + Properties: + PolicyDocument: + Statement: + - Action: + - logs:CreateLogGroup + - logs:CreateLogStream + - logs:PutLogEvents + Effect: Allow + Resource: + - Fn::Join: + - "" + - - "arn:" + - Ref: AWS::Partition + - ":logs:" + - Ref: AWS::Region + - ":" + - Ref: AWS::AccountId + - :log-group:/aws/codebuild/ + - Ref: BuildProject + - Fn::Join: + - "" + - - "arn:" + - Ref: AWS::Partition + - ":logs:" + - Ref: AWS::Region + - ":" + - Ref: AWS::AccountId + - :log-group:/aws/codebuild/ + - Ref: BuildProject + - :* + - Action: + - codebuild:CreateReportGroup + - codebuild:CreateReport + - codebuild:UpdateReport + - codebuild:BatchPutTestCases + Effect: Allow + Resource: + Fn::Join: + - "" + - - "arn:" + - Ref: AWS::Partition + - ":codebuild:" + - Ref: AWS::Region + - ":" + - Ref: AWS::AccountId + - :report-group/ + - Ref: BuildProject + - -* + - Action: + - proton:GetService + Effect: Allow + Resource: "*" + - Action: + - s3:GetObject* + - s3:GetBucket* + - s3:List* + - s3:DeleteObject* + - s3:PutObject* + - s3:Abort* + - s3:CreateMultipartUpload + Effect: Allow + Resource: + - Fn::GetAtt: + - FunctionBucket + - Arn + - Fn::Join: + - "" + - - Fn::GetAtt: + - FunctionBucket + - Arn + - /* + - Action: + - s3:GetObject* + - s3:GetBucket* + - s3:List* + - s3:DeleteObject* + - s3:PutObject* + - s3:Abort* + Effect: Allow + Resource: + - Fn::GetAtt: + - PipelineArtifactsBucket + - Arn + - Fn::Join: + - "" + - - Fn::GetAtt: + - PipelineArtifactsBucket + - Arn + - /* + - Action: + - kms:Decrypt + - kms:DescribeKey + - kms:Encrypt + - kms:ReEncrypt* + - kms:GenerateDataKey* + Effect: Allow + Resource: + Fn::GetAtt: + - PipelineArtifactsBucketEncryptionKey + - Arn + - Action: + - kms:Decrypt + - kms:Encrypt + - kms:ReEncrypt* + - kms:GenerateDataKey* + Effect: Allow + Resource: + Fn::GetAtt: + - PipelineArtifactsBucketEncryptionKey + - Arn + Version: "2012-10-17" + PolicyName: PublishRoleDefaultPolicy + Roles: + - Ref: PublishRole + + DeploymentRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Statement: + - Action: sts:AssumeRole + Effect: Allow + Principal: + Service: codebuild.amazonaws.com + Version: "2012-10-17" + DeploymentRoleDefaultPolicy: + Type: AWS::IAM::Policy + Properties: + PolicyDocument: + Statement: + - Action: + - logs:CreateLogGroup + - logs:CreateLogStream + - logs:PutLogEvents + Effect: Allow + Resource: + - Fn::Join: + - "" + - - "arn:" + - Ref: AWS::Partition + - ":logs:" + - Ref: AWS::Region + - ":" + - Ref: AWS::AccountId + - :log-group:/aws/codebuild/Deploy*Project* + - Fn::Join: + - "" + - - "arn:" + - Ref: AWS::Partition + - ":logs:" + - Ref: AWS::Region + - ":" + - Ref: AWS::AccountId + - :log-group:/aws/codebuild/Deploy*Project:* + - Action: + - codebuild:CreateReportGroup + - codebuild:CreateReport + - codebuild:UpdateReport + - codebuild:BatchPutTestCases + Effect: Allow + Resource: + Fn::Join: + - "" + - - "arn:" + - Ref: AWS::Partition + - ":codebuild:" + - Ref: AWS::Region + - ":" + - Ref: AWS::AccountId + - :report-group/Deploy*Project + - -* + - Action: + - proton:UpdateServiceInstance + - proton:GetServiceInstance + Effect: Allow + Resource: "*" + - Action: + - s3:GetObject* + - s3:GetBucket* + - s3:List* + Effect: Allow + Resource: + - Fn::GetAtt: + - PipelineArtifactsBucket + - Arn + - Fn::Join: + - "" + - - Fn::GetAtt: + - PipelineArtifactsBucket + - Arn + - /* + - Action: + - kms:Decrypt + - kms:DescribeKey + Effect: Allow + Resource: + Fn::GetAtt: + - PipelineArtifactsBucketEncryptionKey + - Arn + - Action: + - kms:Decrypt + - kms:Encrypt + - kms:ReEncrypt* + - kms:GenerateDataKey* + Effect: Allow + Resource: + Fn::GetAtt: + - PipelineArtifactsBucketEncryptionKey + - Arn + Version: "2012-10-17" + PolicyName: DeploymentRoleDefaultPolicy + Roles: + - Ref: DeploymentRole + PipelineArtifactsBucketEncryptionKey: + Type: AWS::KMS::Key + Properties: + KeyPolicy: + Statement: + - Action: + - kms:Create* + - kms:Describe* + - kms:Enable* + - kms:List* + - kms:Put* + - kms:Update* + - kms:Revoke* + - kms:Disable* + - kms:Get* + - kms:Delete* + - kms:ScheduleKeyDeletion + - kms:CancelKeyDeletion + - kms:GenerateDataKey + - kms:TagResource + - kms:UntagResource + Effect: Allow + Principal: + AWS: + Fn::Join: + - "" + - - "arn:" + - Ref: AWS::Partition + - ":iam::" + - Ref: AWS::AccountId + - :root + Resource: "*" + - Action: + - kms:Decrypt + - kms:DescribeKey + - kms:Encrypt + - kms:ReEncrypt* + - kms:GenerateDataKey* + Effect: Allow + Principal: + AWS: + Fn::GetAtt: + - PipelineRole + - Arn + Resource: "*" + - Action: + - kms:Decrypt + - kms:DescribeKey + - kms:Encrypt + - kms:ReEncrypt* + - kms:GenerateDataKey* + Effect: Allow + Principal: + AWS: + Fn::GetAtt: + - PublishRole + - Arn + Resource: "*" + - Action: + - kms:Decrypt + - kms:Encrypt + - kms:ReEncrypt* + - kms:GenerateDataKey* + Effect: Allow + Principal: + AWS: + Fn::GetAtt: + - PublishRole + - Arn + Resource: "*" + - Action: + - kms:Decrypt + - kms:DescribeKey + Effect: Allow + Principal: + AWS: + Fn::GetAtt: + - DeploymentRole + - Arn + Resource: "*" + - Action: + - kms:Decrypt + - kms:Encrypt + - kms:ReEncrypt* + - kms:GenerateDataKey* + Effect: Allow + Principal: + AWS: + Fn::GetAtt: + - DeploymentRole + - Arn + Resource: "*" + Version: "2012-10-17" + UpdateReplacePolicy: Delete + DeletionPolicy: Delete + PipelineArtifactsBucket: + Type: AWS::S3::Bucket + Properties: + VersioningConfiguration: + Status: Enabled + BucketEncryption: + ServerSideEncryptionConfiguration: + - ServerSideEncryptionByDefault: + KMSMasterKeyID: + Fn::GetAtt: + - PipelineArtifactsBucketEncryptionKey + - Arn + SSEAlgorithm: aws:kms + PublicAccessBlockConfiguration: + BlockPublicAcls: true + BlockPublicPolicy: true + IgnorePublicAcls: true + RestrictPublicBuckets: true + UpdateReplacePolicy: Retain + DeletionPolicy: Retain + PipelineArtifactsBucketEncryptionKeyAlias: + Type: AWS::KMS::Alias + Properties: + AliasName: 'alias/codepipeline-encryption-key-{{ service.name }}' + TargetKeyId: + Fn::GetAtt: + - PipelineArtifactsBucketEncryptionKey + - Arn + UpdateReplacePolicy: Delete + DeletionPolicy: Delete + PipelineRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Statement: + - Action: sts:AssumeRole + Effect: Allow + Principal: + Service: codepipeline.amazonaws.com + Version: "2012-10-17" + PipelineRoleDefaultPolicy: + Type: AWS::IAM::Policy + Properties: + PolicyDocument: + Statement: + - Action: + - s3:GetObject* + - s3:GetBucket* + - s3:List* + - s3:DeleteObject* + - s3:PutObject* + - s3:Abort* + Effect: Allow + Resource: + - Fn::GetAtt: + - PipelineArtifactsBucket + - Arn + - Fn::Join: + - "" + - - Fn::GetAtt: + - PipelineArtifactsBucket + - Arn + - /* + - Action: + - kms:Decrypt + - kms:DescribeKey + - kms:Encrypt + - kms:ReEncrypt* + - kms:GenerateDataKey* + Effect: Allow + Resource: + Fn::GetAtt: + - PipelineArtifactsBucketEncryptionKey + - Arn + - Action: codestar-connections:* + Effect: Allow + Resource: "*" + - Action: sts:AssumeRole + Effect: Allow + Resource: + Fn::GetAtt: + - PipelineBuildCodePipelineActionRole + - Arn + - Action: sts:AssumeRole + Effect: Allow + Resource: + Fn::GetAtt: + - PipelineDeployCodePipelineActionRole + - Arn + Version: "2012-10-17" + PolicyName: PipelineRoleDefaultPolicy + Roles: + - Ref: PipelineRole + Pipeline: + Type: AWS::CodePipeline::Pipeline + Properties: + RoleArn: + Fn::GetAtt: + - PipelineRole + - Arn + Stages: + - Actions: + - ActionTypeId: + Category: Source + Owner: AWS + Provider: CodeStarSourceConnection + Version: "1" + Configuration: + ConnectionArn: '{{ service.repository_connection_arn }}' + FullRepositoryId: '{{ service.repository_id }}' + BranchName: '{{ service.branch_name }}' + Name: Checkout + OutputArtifacts: + - Name: Artifact_Source_Checkout + RunOrder: 1 + Name: Source + - Actions: + - ActionTypeId: + Category: Build + Owner: AWS + Provider: CodeBuild + Version: "1" + Configuration: + ProjectName: + Ref: BuildProject + InputArtifacts: + - Name: Artifact_Source_Checkout + Name: Build + OutputArtifacts: + - Name: BuildOutput + RoleArn: + Fn::GetAtt: + - PipelineBuildCodePipelineActionRole + - Arn + RunOrder: 1 + Name: Build {%- for service_instance in service_instances %} + - Actions: + - ActionTypeId: + Category: Build + Owner: AWS + Provider: CodeBuild + Version: "1" + Configuration: + ProjectName: + Ref: Deploy{{loop.index}}Project + InputArtifacts: + - Name: BuildOutput + Name: Deploy + RoleArn: + Fn::GetAtt: + - PipelineDeployCodePipelineActionRole + - Arn + RunOrder: 1 + Name: 'Deploy{{service_instance.name}}' +{%- endfor %} + ArtifactStore: + EncryptionKey: + Id: + Fn::GetAtt: + - PipelineArtifactsBucketEncryptionKey + - Arn + Type: KMS + Location: + Ref: PipelineArtifactsBucket + Type: S3 + DependsOn: + - PipelineRoleDefaultPolicy + - PipelineRole + PipelineBuildCodePipelineActionRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Statement: + - Action: sts:AssumeRole + Effect: Allow + Principal: + AWS: + Fn::Join: + - "" + - - "arn:" + - Ref: AWS::Partition + - ":iam::" + - Ref: AWS::AccountId + - :root + Version: "2012-10-17" + PipelineBuildCodePipelineActionRoleDefaultPolicy: + Type: AWS::IAM::Policy + Properties: + PolicyDocument: + Statement: + - Action: + - codebuild:BatchGetBuilds + - codebuild:StartBuild + - codebuild:StopBuild + Effect: Allow + Resource: + Fn::GetAtt: + - BuildProject + - Arn + Version: "2012-10-17" + PolicyName: PipelineBuildCodePipelineActionRoleDefaultPolicy + Roles: + - Ref: PipelineBuildCodePipelineActionRole + PipelineDeployCodePipelineActionRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Statement: + - Action: sts:AssumeRole + Effect: Allow + Principal: + AWS: + Fn::Join: + - "" + - - "arn:" + - Ref: AWS::Partition + - ":iam::" + - Ref: AWS::AccountId + - :root + Version: "2012-10-17" + PipelineDeployCodePipelineActionRoleDefaultPolicy: + Type: AWS::IAM::Policy + Properties: + PolicyDocument: + Statement: + - Action: + - codebuild:BatchGetBuilds + - codebuild:StartBuild + - codebuild:StopBuild + Effect: Allow + Resource: + Fn::Join: + - "" + - - "arn:" + - Ref: AWS::Partition + - ":codebuild:" + - Ref: AWS::Region + - ":" + - Ref: AWS::AccountId + - ":project/Deploy*" + Version: "2012-10-17" + PolicyName: PipelineDeployCodePipelineActionRoleDefaultPolicy + Roles: + - Ref: PipelineDeployCodePipelineActionRole +Outputs: + PipelineEndpoint: + Description: The URL to access the pipeline + Value: !Sub "https://${AWS::Region}.console.aws.amazon.com/codesuite/codepipeline/pipelines/${Pipeline}/view?region=${AWS::Region}" diff --git a/public-private-fargate-microservices-dotnetfx/microservices-env/v1/pipeline_infrastructure/manifest.yaml b/public-private-fargate-microservices-dotnetfx/microservices-env/v1/pipeline_infrastructure/manifest.yaml new file mode 100644 index 0000000..eed587b --- /dev/null +++ b/public-private-fargate-microservices-dotnetfx/microservices-env/v1/pipeline_infrastructure/manifest.yaml @@ -0,0 +1,5 @@ +infrastructure: + templates: + - file: "cloudformation.yaml" + rendering_engine: jinja + template_language: cloudformation diff --git a/public-private-fargate-microservices-dotnetfx/microservices-env/v1/schema/schema.yaml b/public-private-fargate-microservices-dotnetfx/microservices-env/v1/schema/schema.yaml new file mode 100644 index 0000000..59c4256 --- /dev/null +++ b/public-private-fargate-microservices-dotnetfx/microservices-env/v1/schema/schema.yaml @@ -0,0 +1,39 @@ +schema: + format: + openapi: "3.0.0" + environment_input_type: "PublicEnvironmentInput" + types: + PublicEnvironmentInput: + type: object + description: "Input properties for my environment" + properties: + vpc_cidr: + type: string + description: "This CIDR range for your VPC" + default: 10.0.0.0/16 + pattern: ([0-9]{1,3}\.){3}[0-9]{1,3}($|/(16|24)) + public_subnet_one_cidr: + type: string + description: "The CIDR range for public subnet one" + default: 10.0.1.0/24 + pattern: ([0-9]{1,3}\.){3}[0-9]{1,3}($|/(16|24)) + public_subnet_two_cidr: + type: string + description: "The CIDR range for public subnet one" + default: 10.0.2.0/24 + pattern: ([0-9]{1,3}\.){3}[0-9]{1,3}($|/(16|24)) + private_subnet_one_cidr: + type: string + description: "The CIDR range for private subnet one" + default: 10.0.3.0/24 + pattern: ([0-9]{1,3}\.){3}[0-9]{1,3}($|/(16|24)) + private_subnet_two_cidr: + type: string + description: "The CIDR range for private subnet two" + default: 10.0.4.0/24 + pattern: ([0-9]{1,3}\.){3}[0-9]{1,3}($|/(16|24)) + service_discovery_namespace: + type: string + description: "The name of the private namespace for service discovery" + default: example.local + diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/.compatible-envs b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/.compatible-envs new file mode 100644 index 0000000..4ef64cc --- /dev/null +++ b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/.compatible-envs @@ -0,0 +1 @@ +microservices-env:1 diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/instance_infrastructure/cloudformation.yaml b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/instance_infrastructure/cloudformation.yaml new file mode 100644 index 0000000..bee5b88 --- /dev/null +++ b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/instance_infrastructure/cloudformation.yaml @@ -0,0 +1,346 @@ +AWSTemplateFormatVersion: '2010-09-09' +Description: Deploy a service on AWS Fargate, hosted in a public subnet, and accessible via a public load balancer. +Mappings: + EnvironmentNameConfig: + Environment: + Name: '{{environment.name}}' + TaskSize: + x-small: + cpu: 256 + memory: 512 + small: + cpu: 512 + memory: 1024 + medium: + cpu: 1024 + memory: 2048 + large: + cpu: 2048 + memory: 4096 + x-large: + cpu: 4096 + memory: 8192 +Resources: + # Register service in ServiceDiscovery Service + DiscoveryService: + Type: AWS::ServiceDiscovery::Service + Properties: + Description: Discovery Service for the Demo Application + DnsConfig: + RoutingPolicy: MULTIVALUE + DnsRecords: + - TTL: 60 + Type: A + HealthCheckCustomConfig: + FailureThreshold: 1 + Name: '{{service_instance.inputs.service_discovery_name}}' + NamespaceId: '{{environment.outputs.PrivateNamespace}}' + + # A log group for storing the stdout logs from this service's containers + LogGroup: + Type: AWS::Logs::LogGroup + Properties: + LogGroupName: '{{service.name}}/{{service_instance.name}}' + + # The task definition. This is a simple metadata description of what + # container to run, and what resource requirements it has. + TaskDefinition: + Type: AWS::ECS::TaskDefinition + Properties: + Family: '{{service.name}}_{{service_instance.name}}' + Cpu: !FindInMap [TaskSize, {{service_instance.inputs.task_size}}, cpu] + Memory: !FindInMap [TaskSize, {{service_instance.inputs.task_size}}, memory] + NetworkMode: awsvpc + RequiresCompatibilities: + - FARGATE + ExecutionRoleArn: '{{environment.outputs.ECSTaskExecutionRole}}' + TaskRoleArn: !Ref "AWS::NoValue" + ContainerDefinitions: + - Name: '{{service_instance.name}}' + Cpu: !FindInMap [TaskSize, {{service_instance.inputs.task_size}}, cpu] + Memory: !FindInMap [TaskSize, {{service_instance.inputs.task_size}}, memory] + Image: '{{service_instance.inputs.image}}' + PortMappings: + - ContainerPort: '{{service_instance.inputs.port}}' + LogConfiguration: + LogDriver: 'awslogs' + Options: + awslogs-group: '{{service.name}}/{{service_instance.name}}' + awslogs-region: !Ref 'AWS::Region' + awslogs-stream-prefix: '{{service.name}}/{{service_instance.name}}' + Tags: + - Key: Name + Value: !FindInMap ['EnvironmentNameConfig', 'Environment', 'Name'] + + # The service_instance.inputs. The service is a resource which allows you to run multiple + # copies of a type of task, and gather up their logs and metrics, as well + # as monitor the number of running tasks and replace any that have crashed + Service: + Type: AWS::ECS::Service + DependsOn: LoadBalancerRule + Properties: + ServiceName: '{{service.name}}_{{service_instance.name}}' + Cluster: '{{environment.outputs.ClusterName}}' + LaunchType: FARGATE + DeploymentConfiguration: + MaximumPercent: 200 + MinimumHealthyPercent: 75 + DesiredCount: '{{service_instance.inputs.desired_count}}' + NetworkConfiguration: + AwsvpcConfiguration: + AssignPublicIp: ENABLED + SecurityGroups: + - '{{environment.outputs.ContainerSecurityGroup}}' + Subnets: + - '{{environment.outputs.PublicSubnetOne}}' + - '{{environment.outputs.PublicSubnetTwo}}' + TaskDefinition: !Ref 'TaskDefinition' + ServiceRegistries: + - RegistryArn: !GetAtt DiscoveryService.Arn + LoadBalancers: + - ContainerName: '{{service_instance.name}}' + ContainerPort: '{{service_instance.inputs.port}}' + TargetGroupArn: !Ref 'TargetGroup' + Tags: + - Key: Name + Value: !FindInMap ['EnvironmentNameConfig', 'Environment', 'Name'] + + # A target group. This is used for keeping track of all the tasks, and + # what IP addresses / port numbers they have. You can query it yourself, + # to use the addresses yourself, but most often this target group is just + # connected to an application load balancer, or network load balancer, so + # it can automatically distribute traffic across all the targets. + TargetGroup: + Type: AWS::ElasticLoadBalancingV2::TargetGroup + Properties: + HealthCheckIntervalSeconds: 6 + HealthCheckPath: / + HealthCheckProtocol: HTTP + HealthCheckTimeoutSeconds: 5 + HealthyThresholdCount: 2 + TargetType: ip + # Note that the Name property has a 32 character limit, which could be + # reached by using either {{service.name}}, {{service_instance.name}} + # or a combination of both as we're doing here, so we truncate the name to 29 characters + # plus an ellipsis different from '...' or '---' to avoid running into errors. + Name: '{{(service.name~"--"~service_instance.name)|truncate(29, true, 'zzz', 0)}}' + Port: '{{service_instance.inputs.port}}' + Protocol: HTTP + UnhealthyThresholdCount: 2 + VpcId: '{{environment.outputs.VpcId}}' + Tags: + - Key: Name + Value: !FindInMap ['EnvironmentNameConfig', 'Environment', 'Name'] + + # Create a rule on the load balancer for routing traffic to the target group + LoadBalancerRule: + Type: AWS::ElasticLoadBalancingV2::ListenerRule + Properties: + Actions: + - TargetGroupArn: !Ref 'TargetGroup' + Type: 'forward' + Conditions: + - Field: path-pattern + Values: + - '*' + ListenerArn: !Ref PublicLoadBalancerListener + Priority: 1 + + # Enable autoscaling for this service + ScalableTarget: + Type: AWS::ApplicationAutoScaling::ScalableTarget + DependsOn: Service + Properties: + ServiceNamespace: 'ecs' + ScalableDimension: 'ecs:service:DesiredCount' + ResourceId: + Fn::Join: + - '/' + - - service + - '{{environment.outputs.ClusterName}}' + - '{{service.name}}_{{service_instance.name}}' + MinCapacity: 1 + MaxCapacity: 10 + RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/ecs.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_ECSService + + # Create scaling policies for the service + ScaleDownPolicy: + Type: AWS::ApplicationAutoScaling::ScalingPolicy + DependsOn: ScalableTarget + Properties: + PolicyName: + Fn::Join: + - '/' + - - scale + - '{{service.name}}_{{service_instance.name}}' + - down + PolicyType: StepScaling + ResourceId: + Fn::Join: + - '/' + - - service + - '{{environment.outputs.ClusterName}}' + - '{{service.name}}_{{service_instance.name}}' + ScalableDimension: 'ecs:service:DesiredCount' + ServiceNamespace: 'ecs' + StepScalingPolicyConfiguration: + AdjustmentType: 'ChangeInCapacity' + StepAdjustments: + - MetricIntervalUpperBound: 0 + ScalingAdjustment: -1 + MetricAggregationType: 'Average' + Cooldown: 60 + + ScaleUpPolicy: + Type: AWS::ApplicationAutoScaling::ScalingPolicy + DependsOn: ScalableTarget + Properties: + PolicyName: + Fn::Join: + - '/' + - - scale + - '{{service.name}}_{{service_instance.name}}' + - up + PolicyType: StepScaling + ResourceId: + Fn::Join: + - '/' + - - service + - '{{environment.outputs.ClusterName}}' + - '{{service.name}}_{{service_instance.name}}' + ScalableDimension: 'ecs:service:DesiredCount' + ServiceNamespace: 'ecs' + StepScalingPolicyConfiguration: + AdjustmentType: 'ChangeInCapacity' + StepAdjustments: + - MetricIntervalLowerBound: 0 + MetricIntervalUpperBound: 15 + ScalingAdjustment: 1 + - MetricIntervalLowerBound: 15 + MetricIntervalUpperBound: 25 + ScalingAdjustment: 2 + - MetricIntervalLowerBound: 25 + ScalingAdjustment: 3 + MetricAggregationType: 'Average' + Cooldown: 60 + + # Create alarms to trigger these policies + LowCpuUsageAlarm: + Type: AWS::CloudWatch::Alarm + Properties: + AlarmName: + Fn::Join: + - '-' + - - low-cpu + - '{{service.name}}_{{service_instance.name}}' + AlarmDescription: + Fn::Join: + - ' ' + - - "Low CPU utilization for service" + - '{{service.name}}_{{service_instance.name}}' + MetricName: CPUUtilization + Namespace: AWS/ECS + Dimensions: + - Name: ServiceName + Value: '{{service.name}}_{{service_instance.name}}' + - Name: ClusterName + Value: + '{{environment.outputs.ClusterName}}' + Statistic: Average + Period: 60 + EvaluationPeriods: 1 + Threshold: 20 + ComparisonOperator: LessThanOrEqualToThreshold + AlarmActions: + - !Ref ScaleDownPolicy + + HighCpuUsageAlarm: + Type: AWS::CloudWatch::Alarm + Properties: + AlarmName: + Fn::Join: + - '-' + - - high-cpu + - '{{service.name}}_{{service_instance.name}}' + AlarmDescription: + Fn::Join: + - ' ' + - - "High CPU utilization for service" + - '{{service.name}}_{{service_instance.name}}' + MetricName: CPUUtilization + Namespace: AWS/ECS + Dimensions: + - Name: ServiceName + Value: '{{service.name}}_{{service_instance.name}}' + - Name: ClusterName + Value: + '{{environment.outputs.ClusterName}}' + Statistic: Average + Period: 60 + EvaluationPeriods: 1 + Threshold: 70 + ComparisonOperator: GreaterThanOrEqualToThreshold + AlarmActions: + - !Ref ScaleUpPolicy + + EcsSecurityGroupIngressFromPublicALB: + Type: AWS::EC2::SecurityGroupIngress + Properties: + Description: Ingress from the public ALB + GroupId: '{{environment.outputs.ContainerSecurityGroup}}' + IpProtocol: -1 + SourceSecurityGroupId: !Ref 'PublicLoadBalancerSG' + + # Public load balancer, hosted in public subnets that is accessible + # to the public, and is intended to route traffic to one or more public + # facing services. This is used for accepting traffic from the public + # internet and directing it to public facing microservices + PublicLoadBalancerSG: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: Access to the public facing load balancer + VpcId: '{{environment.outputs.VpcId}}' + SecurityGroupIngress: + # Allow access to ALB from anywhere on the internet + - CidrIp: 0.0.0.0/0 + IpProtocol: -1 + Tags: + - Key: Name + Value: !FindInMap ['EnvironmentNameConfig', 'Environment', 'Name'] + + PublicLoadBalancer: + Type: AWS::ElasticLoadBalancingV2::LoadBalancer + Properties: + Scheme: internet-facing + LoadBalancerAttributes: + - Key: idle_timeout.timeout_seconds + Value: '30' + Subnets: + # The load balancer is placed into the public subnets, so that traffic + # from the internet can reach the load balancer directly via the internet gateway + - '{{environment.outputs.PublicSubnetOne}}' + - '{{environment.outputs.PublicSubnetTwo}}' + SecurityGroups: [!Ref 'PublicLoadBalancerSG'] + Tags: + - Key: Name + Value: !FindInMap ['EnvironmentNameConfig', 'Environment', 'Name'] + + PublicLoadBalancerListener: + Type: AWS::ElasticLoadBalancingV2::Listener + DependsOn: + - PublicLoadBalancer + Properties: + DefaultActions: + - TargetGroupArn: !Ref 'TargetGroup' + Type: 'forward' + LoadBalancerArn: !Ref 'PublicLoadBalancer' + Port: 80 + Protocol: HTTP + +Outputs: + ServiceEndpoint: + Description: The URL to access the service + Value: !Sub "http://${PublicLoadBalancer.DNSName}" + ServiceDiscovery: + Description: The registered service discovery Service Id + Value: !Ref DiscoveryService diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/instance_infrastructure/manifest.yaml b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/instance_infrastructure/manifest.yaml new file mode 100644 index 0000000..eed587b --- /dev/null +++ b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/instance_infrastructure/manifest.yaml @@ -0,0 +1,5 @@ +infrastructure: + templates: + - file: "cloudformation.yaml" + rendering_engine: jinja + template_language: cloudformation diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/pipeline_infrastructure/cloudformation.yaml b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/pipeline_infrastructure/cloudformation.yaml new file mode 100644 index 0000000..a6a82d8 --- /dev/null +++ b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/pipeline_infrastructure/cloudformation.yaml @@ -0,0 +1,709 @@ +Resources: + ECRRepo: + Type: AWS::ECR::Repository + DeletionPolicy: Retain + Properties: + # This policy allows environment accounts to get the image from ECRRepo in the management account + RepositoryPolicyText: + Version: "2012-10-17" + Statement: + - Sid: AllowPull + Effect: Allow + Principal: + AWS: + {% for service_instance in service_instances %} + - "arn:aws:iam::{{service_instance.environment.account_id}}:root" + {% endfor %} + Action: + - ecr:GetAuthorizationToken + - ecr:BatchCheckLayerAvailability + - ecr:GetDownloadUrlForLayer + - ecr:BatchGetImage + BuildProject: + Type: AWS::CodeBuild::Project + Properties: + Artifacts: + Type: CODEPIPELINE + Environment: + ComputeType: BUILD_GENERAL1_SMALL + Image: aws/codebuild/amazonlinux2-x86_64-standard:3.0 + PrivilegedMode: true + Type: LINUX_CONTAINER + EnvironmentVariables: + - Name: repo_name + Type: PLAINTEXT + Value: !Ref ECRRepo + - Name: service_name + Type: PLAINTEXT + Value: '{{service.name}}' + ServiceRole: + Fn::GetAtt: + - PublishRole + - Arn + Source: + BuildSpec: + Fn::Join: + - "" + - - >- + { + "version": "0.2", + "phases": { + "install": { + "runtime-versions": { + "docker": 18 + }, + "commands": [ + "pip3 install --upgrade --user awscli", + "echo 'f6bd1536a743ab170b35c94ed4c7c4479763356bd543af5d391122f4af852460 yq_linux_amd64' > yq_linux_amd64.sha", + "wget https://github.com/mikefarah/yq/releases/download/3.4.0/yq_linux_amd64", + "sha256sum -c yq_linux_amd64.sha", + "mv yq_linux_amd64 /usr/bin/yq", + "chmod +x /usr/bin/yq" + ] + }, + "pre_build": { + "commands": [ + "cd $CODEBUILD_SRC_DIR", + "$(aws ecr get-login --no-include-email --region $AWS_DEFAULT_REGION)", + "{{ pipeline.inputs.unit_test_command }}", + ] + }, + "build": { + "commands": [ + "IMAGE_REPO_NAME=$repo_name", + "IMAGE_TAG=$CODEBUILD_BUILD_NUMBER", + "IMAGE_ID= + - Ref: AWS::AccountId + - >- + .dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG", + "docker build -t $IMAGE_REPO_NAME:$IMAGE_TAG -f {{ pipeline.inputs.dockerfile }} .", + "docker tag $IMAGE_REPO_NAME:$IMAGE_TAG $IMAGE_ID;", + "docker push $IMAGE_ID" + ] + }, + "post_build": { + "commands": [ + "aws proton --region $AWS_DEFAULT_REGION get-service --name $service_name | jq -r .service.spec > service.yaml", + "yq w service.yaml 'instances[*].spec.image' \"$IMAGE_ID\" > rendered_service.yaml" + ] + } + }, + "artifacts": { + "files": [ + "rendered_service.yaml" + ] + } + } + Type: CODEPIPELINE + EncryptionKey: + Fn::GetAtt: + - PipelineArtifactsBucketEncryptionKey + - Arn +{% for service_instance in service_instances %} + Deploy{{loop.index}}Project: + Type: AWS::CodeBuild::Project + Properties: + Artifacts: + Type: CODEPIPELINE + Environment: + ComputeType: BUILD_GENERAL1_SMALL + Image: aws/codebuild/amazonlinux2-x86_64-standard:3.0 + PrivilegedMode: false + Type: LINUX_CONTAINER + EnvironmentVariables: + - Name: service_name + Type: PLAINTEXT + Value: '{{service.name}}' + - Name: service_instance_name + Type: PLAINTEXT + Value: '{{service_instance.name}}' + ServiceRole: + Fn::GetAtt: + - DeploymentRole + - Arn + Source: + BuildSpec: >- + { + "version": "0.2", + "phases": { + "build": { + "commands": [ + "pip3 install --upgrade --user awscli", + "aws proton --region $AWS_DEFAULT_REGION update-service-instance --deployment-type CURRENT_VERSION --name $service_instance_name --service-name $service_name --spec file://rendered_service.yaml", + "aws proton --region $AWS_DEFAULT_REGION wait service-instance-deployed --name $service_instance_name --service-name $service_name" + ] + } + } + } + Type: CODEPIPELINE + EncryptionKey: + Fn::GetAtt: + - PipelineArtifactsBucketEncryptionKey + - Arn +{% endfor %} + # This role is used to build and publish an image to ECR + PublishRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Statement: + - Action: sts:AssumeRole + Effect: Allow + Principal: + Service: codebuild.amazonaws.com + Version: "2012-10-17" + PublishRoleDefaultPolicy: + Type: AWS::IAM::Policy + Properties: + PolicyDocument: + Statement: + - Action: + - logs:CreateLogGroup + - logs:CreateLogStream + - logs:PutLogEvents + Effect: Allow + Resource: + - Fn::Join: + - "" + - - "arn:" + - Ref: AWS::Partition + - ":logs:" + - Ref: AWS::Region + - ":" + - Ref: AWS::AccountId + - :log-group:/aws/codebuild/ + - Ref: BuildProject + - Fn::Join: + - "" + - - "arn:" + - Ref: AWS::Partition + - ":logs:" + - Ref: AWS::Region + - ":" + - Ref: AWS::AccountId + - :log-group:/aws/codebuild/ + - Ref: BuildProject + - :* + - Action: + - codebuild:CreateReportGroup + - codebuild:CreateReport + - codebuild:UpdateReport + - codebuild:BatchPutTestCases + Effect: Allow + Resource: + Fn::Join: + - "" + - - "arn:" + - Ref: AWS::Partition + - ":codebuild:" + - Ref: AWS::Region + - ":" + - Ref: AWS::AccountId + - :report-group/ + - Ref: BuildProject + - -* + - Action: + - ecr:GetAuthorizationToken + Effect: Allow + Resource: "*" + - Action: + - ecr:BatchCheckLayerAvailability + - ecr:CompleteLayerUpload + - ecr:GetAuthorizationToken + - ecr:InitiateLayerUpload + - ecr:PutImage + - ecr:UploadLayerPart + Effect: Allow + Resource: + Fn::GetAtt: + - ECRRepo + - Arn + - Action: + - proton:GetService + Effect: Allow + Resource: "*" + - Action: + - s3:GetObject* + - s3:GetBucket* + - s3:List* + - s3:DeleteObject* + - s3:PutObject* + - s3:Abort* + Effect: Allow + Resource: + - Fn::GetAtt: + - PipelineArtifactsBucket + - Arn + - Fn::Join: + - "" + - - Fn::GetAtt: + - PipelineArtifactsBucket + - Arn + - /* + - Action: + - kms:Decrypt + - kms:DescribeKey + - kms:Encrypt + - kms:ReEncrypt* + - kms:GenerateDataKey* + Effect: Allow + Resource: + Fn::GetAtt: + - PipelineArtifactsBucketEncryptionKey + - Arn + - Action: + - kms:Decrypt + - kms:Encrypt + - kms:ReEncrypt* + - kms:GenerateDataKey* + Effect: Allow + Resource: + Fn::GetAtt: + - PipelineArtifactsBucketEncryptionKey + - Arn + Version: "2012-10-17" + PolicyName: PublishRoleDefaultPolicy + Roles: + - Ref: PublishRole + + DeploymentRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Statement: + - Action: sts:AssumeRole + Effect: Allow + Principal: + Service: codebuild.amazonaws.com + Version: "2012-10-17" + DeploymentRoleDefaultPolicy: + Type: AWS::IAM::Policy + Properties: + PolicyDocument: + Statement: + - Action: + - logs:CreateLogGroup + - logs:CreateLogStream + - logs:PutLogEvents + Effect: Allow + Resource: + - Fn::Join: + - "" + - - "arn:" + - Ref: AWS::Partition + - ":logs:" + - Ref: AWS::Region + - ":" + - Ref: AWS::AccountId + - :log-group:/aws/codebuild/Deploy*Project* + - Fn::Join: + - "" + - - "arn:" + - Ref: AWS::Partition + - ":logs:" + - Ref: AWS::Region + - ":" + - Ref: AWS::AccountId + - :log-group:/aws/codebuild/Deploy*Project:* + - Action: + - codebuild:CreateReportGroup + - codebuild:CreateReport + - codebuild:UpdateReport + - codebuild:BatchPutTestCases + Effect: Allow + Resource: + Fn::Join: + - "" + - - "arn:" + - Ref: AWS::Partition + - ":codebuild:" + - Ref: AWS::Region + - ":" + - Ref: AWS::AccountId + - :report-group/Deploy*Project + - -* + - Action: + - proton:UpdateServiceInstance + - proton:GetServiceInstance + Effect: Allow + Resource: "*" + - Action: + - s3:GetObject* + - s3:GetBucket* + - s3:List* + Effect: Allow + Resource: + - Fn::GetAtt: + - PipelineArtifactsBucket + - Arn + - Fn::Join: + - "" + - - Fn::GetAtt: + - PipelineArtifactsBucket + - Arn + - /* + - Action: + - kms:Decrypt + - kms:DescribeKey + Effect: Allow + Resource: + Fn::GetAtt: + - PipelineArtifactsBucketEncryptionKey + - Arn + - Action: + - kms:Decrypt + - kms:Encrypt + - kms:ReEncrypt* + - kms:GenerateDataKey* + Effect: Allow + Resource: + Fn::GetAtt: + - PipelineArtifactsBucketEncryptionKey + - Arn + Version: "2012-10-17" + PolicyName: DeploymentRoleDefaultPolicy + Roles: + - Ref: DeploymentRole + PipelineArtifactsBucketEncryptionKey: + Type: AWS::KMS::Key + Properties: + KeyPolicy: + Statement: + - Action: + - kms:Create* + - kms:Describe* + - kms:Enable* + - kms:List* + - kms:Put* + - kms:Update* + - kms:Revoke* + - kms:Disable* + - kms:Get* + - kms:Delete* + - kms:ScheduleKeyDeletion + - kms:CancelKeyDeletion + - kms:GenerateDataKey + - kms:TagResource + - kms:UntagResource + Effect: Allow + Principal: + AWS: + Fn::Join: + - "" + - - "arn:" + - Ref: AWS::Partition + - ":iam::" + - Ref: AWS::AccountId + - :root + Resource: "*" + - Action: + - kms:Decrypt + - kms:DescribeKey + - kms:Encrypt + - kms:ReEncrypt* + - kms:GenerateDataKey* + Effect: Allow + Principal: + AWS: + Fn::GetAtt: + - PipelineRole + - Arn + Resource: "*" + - Action: + - kms:Decrypt + - kms:DescribeKey + - kms:Encrypt + - kms:ReEncrypt* + - kms:GenerateDataKey* + Effect: Allow + Principal: + AWS: + Fn::GetAtt: + - PublishRole + - Arn + Resource: "*" + - Action: + - kms:Decrypt + - kms:Encrypt + - kms:ReEncrypt* + - kms:GenerateDataKey* + Effect: Allow + Principal: + AWS: + Fn::GetAtt: + - PublishRole + - Arn + Resource: "*" + - Action: + - kms:Decrypt + - kms:DescribeKey + Effect: Allow + Principal: + AWS: + Fn::GetAtt: + - DeploymentRole + - Arn + Resource: "*" + - Action: + - kms:Decrypt + - kms:Encrypt + - kms:ReEncrypt* + - kms:GenerateDataKey* + Effect: Allow + Principal: + AWS: + Fn::GetAtt: + - DeploymentRole + - Arn + Resource: "*" + Version: "2012-10-17" + UpdateReplacePolicy: Delete + DeletionPolicy: Delete + PipelineArtifactsBucket: + Type: AWS::S3::Bucket + Properties: + VersioningConfiguration: + Status: Enabled + BucketEncryption: + ServerSideEncryptionConfiguration: + - ServerSideEncryptionByDefault: + KMSMasterKeyID: + Fn::GetAtt: + - PipelineArtifactsBucketEncryptionKey + - Arn + SSEAlgorithm: aws:kms + PublicAccessBlockConfiguration: + BlockPublicAcls: true + BlockPublicPolicy: true + IgnorePublicAcls: true + RestrictPublicBuckets: true + UpdateReplacePolicy: Retain + DeletionPolicy: Retain + PipelineArtifactsBucketEncryptionKeyAlias: + Type: AWS::KMS::Alias + Properties: + AliasName: 'alias/codepipeline-encryption-key-{{ service.name }}' + TargetKeyId: + Fn::GetAtt: + - PipelineArtifactsBucketEncryptionKey + - Arn + UpdateReplacePolicy: Delete + DeletionPolicy: Delete + PipelineRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Statement: + - Action: sts:AssumeRole + Effect: Allow + Principal: + Service: codepipeline.amazonaws.com + Version: "2012-10-17" + PipelineRoleDefaultPolicy: + Type: AWS::IAM::Policy + Properties: + PolicyDocument: + Statement: + - Action: + - s3:GetObject* + - s3:GetBucket* + - s3:List* + - s3:DeleteObject* + - s3:PutObject* + - s3:Abort* + Effect: Allow + Resource: + - Fn::GetAtt: + - PipelineArtifactsBucket + - Arn + - Fn::Join: + - "" + - - Fn::GetAtt: + - PipelineArtifactsBucket + - Arn + - /* + - Action: + - kms:Decrypt + - kms:DescribeKey + - kms:Encrypt + - kms:ReEncrypt* + - kms:GenerateDataKey* + Effect: Allow + Resource: + Fn::GetAtt: + - PipelineArtifactsBucketEncryptionKey + - Arn + - Action: codestar-connections:* + Effect: Allow + Resource: "*" + - Action: sts:AssumeRole + Effect: Allow + Resource: + Fn::GetAtt: + - PipelineBuildCodePipelineActionRole + - Arn + - Action: sts:AssumeRole + Effect: Allow + Resource: + Fn::GetAtt: + - PipelineDeployCodePipelineActionRole + - Arn + Version: "2012-10-17" + PolicyName: PipelineRoleDefaultPolicy + Roles: + - Ref: PipelineRole + Pipeline: + Type: AWS::CodePipeline::Pipeline + Properties: + RoleArn: + Fn::GetAtt: + - PipelineRole + - Arn + Stages: + - Actions: + - ActionTypeId: + Category: Source + Owner: AWS + Provider: CodeStarSourceConnection + Version: "1" + Configuration: + ConnectionArn: '{{ service.repository_connection_arn }}' + FullRepositoryId: '{{ service.repository_id }}' + BranchName: '{{ service.branch_name }}' + Name: Checkout + OutputArtifacts: + - Name: Artifact_Source_Checkout + RunOrder: 1 + Name: Source + - Actions: + - ActionTypeId: + Category: Build + Owner: AWS + Provider: CodeBuild + Version: "1" + Configuration: + ProjectName: + Ref: BuildProject + InputArtifacts: + - Name: Artifact_Source_Checkout + Name: Build + OutputArtifacts: + - Name: BuildOutput + RoleArn: + Fn::GetAtt: + - PipelineBuildCodePipelineActionRole + - Arn + RunOrder: 1 + Name: Build {%- for service_instance in service_instances %} + - Actions: + - ActionTypeId: + Category: Build + Owner: AWS + Provider: CodeBuild + Version: "1" + Configuration: + ProjectName: + Ref: Deploy{{loop.index}}Project + InputArtifacts: + - Name: BuildOutput + Name: Deploy + RoleArn: + Fn::GetAtt: + - PipelineDeployCodePipelineActionRole + - Arn + RunOrder: 1 + Name: 'Deploy{{service_instance.name}}' +{%- endfor %} + ArtifactStore: + EncryptionKey: + Id: + Fn::GetAtt: + - PipelineArtifactsBucketEncryptionKey + - Arn + Type: KMS + Location: + Ref: PipelineArtifactsBucket + Type: S3 + DependsOn: + - PipelineRoleDefaultPolicy + - PipelineRole + PipelineBuildCodePipelineActionRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Statement: + - Action: sts:AssumeRole + Effect: Allow + Principal: + AWS: + Fn::Join: + - "" + - - "arn:" + - Ref: AWS::Partition + - ":iam::" + - Ref: AWS::AccountId + - :root + Version: "2012-10-17" + PipelineBuildCodePipelineActionRoleDefaultPolicy: + Type: AWS::IAM::Policy + Properties: + PolicyDocument: + Statement: + - Action: + - codebuild:BatchGetBuilds + - codebuild:StartBuild + - codebuild:StopBuild + Effect: Allow + Resource: + Fn::GetAtt: + - BuildProject + - Arn + Version: "2012-10-17" + PolicyName: PipelineBuildCodePipelineActionRoleDefaultPolicy + Roles: + - Ref: PipelineBuildCodePipelineActionRole + PipelineDeployCodePipelineActionRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Statement: + - Action: sts:AssumeRole + Effect: Allow + Principal: + AWS: + Fn::Join: + - "" + - - "arn:" + - Ref: AWS::Partition + - ":iam::" + - Ref: AWS::AccountId + - :root + Version: "2012-10-17" + PipelineDeployCodePipelineActionRoleDefaultPolicy: + Type: AWS::IAM::Policy + Properties: + PolicyDocument: + Statement: + - Action: + - codebuild:BatchGetBuilds + - codebuild:StartBuild + - codebuild:StopBuild + Effect: Allow + Resource: + Fn::Join: + - "" + - - "arn:" + - Ref: AWS::Partition + - ":codebuild:" + - Ref: AWS::Region + - ":" + - Ref: AWS::AccountId + - ":project/Deploy*" + Version: "2012-10-17" + PolicyName: PipelineDeployCodePipelineActionRoleDefaultPolicy + Roles: + - Ref: PipelineDeployCodePipelineActionRole +Outputs: + PipelineEndpoint: + Description: The URL to access the pipeline + Value: !Sub "https://${AWS::Region}.console.aws.amazon.com/codesuite/codepipeline/pipelines/${Pipeline}/view?region=${AWS::Region}" diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/pipeline_infrastructure/manifest.yaml b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/pipeline_infrastructure/manifest.yaml new file mode 100644 index 0000000..eed587b --- /dev/null +++ b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/pipeline_infrastructure/manifest.yaml @@ -0,0 +1,5 @@ +infrastructure: + templates: + - file: "cloudformation.yaml" + rendering_engine: jinja + template_language: cloudformation diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/schema/schema.yaml b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/schema/schema.yaml new file mode 100644 index 0000000..b77cae8 --- /dev/null +++ b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/schema/schema.yaml @@ -0,0 +1,57 @@ +schema: + format: + openapi: "3.0.0" + service_input_type: "LoadBalancedServiceInput" + pipeline_input_type: "PipelineInputs" + + types: + LoadBalancedServiceInput: + type: object + description: "Input properties for a loadbalanced Fargate service" + properties: + port: + type: number + description: "The port to route traffic to" + default: 80 + minimum: 0 + maximum: 65535 + desired_count: + type: number + description: "The default number of Fargate tasks you want running" + default: 1 + minimum: 1 + task_size: + type: string + description: "The size of the task you want to run" + enum: ["x-small", "small", "medium", "large", "x-large"] + default: "x-small" + image: + type: string + description: "The name/url of the container image" + default: "public.ecr.aws/z9d2n7e1/nginx:1.21.0" + minLength: 1 + maxLength: 200 + service_discovery_name: + type: string + description: "The name of the service to register in service discovery" + minLength: 3 + maxLength: 24 + required: + - service_discovery_name + + PipelineInputs: + type: object + description: "Pipeline input properties" + properties: + dockerfile: + type: string + description: "The location of the Dockerfile to build" + default: "Dockerfile" + minLength: 1 + maxLength: 100 + unit_test_command: + type: string + description: "The command to run to unit test the application code" + default: "echo 'add your unit test command here'" + minLength: 1 + maxLength: 200 \ No newline at end of file diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/.compatible-envs b/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/.compatible-envs new file mode 100644 index 0000000..4ef64cc --- /dev/null +++ b/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/.compatible-envs @@ -0,0 +1 @@ +microservices-env:1 diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/instance_infrastructure/cloudformation.yaml b/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/instance_infrastructure/cloudformation.yaml new file mode 100644 index 0000000..0d76adb --- /dev/null +++ b/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/instance_infrastructure/cloudformation.yaml @@ -0,0 +1,102 @@ +AWSTemplateFormatVersion: '2010-09-09' +Description: Deploy a backend service on AWS Fargate, hosted in a private subnet, and accessible via Service Discovery. +Mappings: + EnvironmentNameConfig: + Environment: + Name: '{{ environment.name}}' + TaskSize: + x-small: + cpu: 256 + memory: 512 + small: + cpu: 512 + memory: 1024 + medium: + cpu: 1024 + memory: 2048 + large: + cpu: 2048 + memory: 4096 + x-large: + cpu: 4096 + memory: 8192 +Resources: + # Register service in ServiceDiscovery Service + DiscoveryService: + Type: AWS::ServiceDiscovery::Service + Properties: + Description: Discovery Service for the Demo Application + DnsConfig: + RoutingPolicy: MULTIVALUE + DnsRecords: + - TTL: 60 + Type: A + HealthCheckCustomConfig: + FailureThreshold: 1 + Name: '{{service_instance.inputs.service_discovery_name}}' + NamespaceId: '{{environment.outputs.PrivateNamespace}}' + # A log group for storing the stdout logs from this service's containers + LogGroup: + Type: AWS::Logs::LogGroup + Properties: + LogGroupName: '{{service.name}}/{{service_instance.name}}' + + # The task definition. This is a simple metadata description of what + # container to run, and what resource requirements it has. + TaskDefinition: + Type: AWS::ECS::TaskDefinition + Properties: + Family: '{{service.name}}_{{service_instance.name}}' + Cpu: !FindInMap [TaskSize, {{service_instance.inputs.task_size}}, cpu] + Memory: !FindInMap [TaskSize, {{service_instance.inputs.task_size}}, memory] + NetworkMode: awsvpc + RequiresCompatibilities: + - FARGATE + ExecutionRoleArn: '{{environment.outputs.ECSTaskExecutionRole}}' + TaskRoleArn: !Ref "AWS::NoValue" + ContainerDefinitions: + - Name: '{{service_instance.name}}' + Cpu: !FindInMap [TaskSize, {{service_instance.inputs.task_size}}, cpu] + Memory: !FindInMap [TaskSize, {{service_instance.inputs.task_size}}, memory] + Image: '{{service_instance.inputs.image}}' + PortMappings: + - ContainerPort: '{{service_instance.inputs.port}}' + LogConfiguration: + LogDriver: 'awslogs' + Options: + awslogs-group: '{{service.name}}/{{service_instance.name}}' + awslogs-region: !Ref 'AWS::Region' + awslogs-stream-prefix: '{{service.name}}/{{service_instance.name}}' + Tags: + - Key: Name + Value: !FindInMap ['EnvironmentNameConfig', 'Environment', 'Name'] + + # The service_instance.inputs. The service is a resource which allows you to run multiple + # copies of a type of task, and gather up their logs and metrics, as well + # as monitor the number of running tasks and replace any that have crashed + Service: + Type: AWS::ECS::Service + Properties: + ServiceName: '{{service.name}}_{{service_instance.name}}' + Cluster: '{{environment.outputs.ClusterName}}' + LaunchType: FARGATE + DesiredCount: '{{service_instance.inputs.desired_count}}' + NetworkConfiguration: + AwsvpcConfiguration: + AssignPublicIp: DISABLED + SecurityGroups: + - '{{environment.outputs.ContainerSecurityGroup}}' + Subnets: + - '{{environment.outputs.PrivateSubnetOne}}' + - '{{environment.outputs.PrivateSubnetTwo}}' + TaskDefinition: !Ref 'TaskDefinition' + ServiceRegistries: + - RegistryArn: !GetAtt DiscoveryService.Arn + Tags: + - Key: Name + Value: !FindInMap ['EnvironmentNameConfig', 'Environment', 'Name'] + +Outputs: + ServiceDiscovery: + Description: The registered service discovery Service Id + Value: !Ref DiscoveryService diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/instance_infrastructure/manifest.yaml b/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/instance_infrastructure/manifest.yaml new file mode 100644 index 0000000..eed587b --- /dev/null +++ b/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/instance_infrastructure/manifest.yaml @@ -0,0 +1,5 @@ +infrastructure: + templates: + - file: "cloudformation.yaml" + rendering_engine: jinja + template_language: cloudformation diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/pipeline_infrastructure/cloudformation.yaml b/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/pipeline_infrastructure/cloudformation.yaml new file mode 100644 index 0000000..a6a82d8 --- /dev/null +++ b/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/pipeline_infrastructure/cloudformation.yaml @@ -0,0 +1,709 @@ +Resources: + ECRRepo: + Type: AWS::ECR::Repository + DeletionPolicy: Retain + Properties: + # This policy allows environment accounts to get the image from ECRRepo in the management account + RepositoryPolicyText: + Version: "2012-10-17" + Statement: + - Sid: AllowPull + Effect: Allow + Principal: + AWS: + {% for service_instance in service_instances %} + - "arn:aws:iam::{{service_instance.environment.account_id}}:root" + {% endfor %} + Action: + - ecr:GetAuthorizationToken + - ecr:BatchCheckLayerAvailability + - ecr:GetDownloadUrlForLayer + - ecr:BatchGetImage + BuildProject: + Type: AWS::CodeBuild::Project + Properties: + Artifacts: + Type: CODEPIPELINE + Environment: + ComputeType: BUILD_GENERAL1_SMALL + Image: aws/codebuild/amazonlinux2-x86_64-standard:3.0 + PrivilegedMode: true + Type: LINUX_CONTAINER + EnvironmentVariables: + - Name: repo_name + Type: PLAINTEXT + Value: !Ref ECRRepo + - Name: service_name + Type: PLAINTEXT + Value: '{{service.name}}' + ServiceRole: + Fn::GetAtt: + - PublishRole + - Arn + Source: + BuildSpec: + Fn::Join: + - "" + - - >- + { + "version": "0.2", + "phases": { + "install": { + "runtime-versions": { + "docker": 18 + }, + "commands": [ + "pip3 install --upgrade --user awscli", + "echo 'f6bd1536a743ab170b35c94ed4c7c4479763356bd543af5d391122f4af852460 yq_linux_amd64' > yq_linux_amd64.sha", + "wget https://github.com/mikefarah/yq/releases/download/3.4.0/yq_linux_amd64", + "sha256sum -c yq_linux_amd64.sha", + "mv yq_linux_amd64 /usr/bin/yq", + "chmod +x /usr/bin/yq" + ] + }, + "pre_build": { + "commands": [ + "cd $CODEBUILD_SRC_DIR", + "$(aws ecr get-login --no-include-email --region $AWS_DEFAULT_REGION)", + "{{ pipeline.inputs.unit_test_command }}", + ] + }, + "build": { + "commands": [ + "IMAGE_REPO_NAME=$repo_name", + "IMAGE_TAG=$CODEBUILD_BUILD_NUMBER", + "IMAGE_ID= + - Ref: AWS::AccountId + - >- + .dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG", + "docker build -t $IMAGE_REPO_NAME:$IMAGE_TAG -f {{ pipeline.inputs.dockerfile }} .", + "docker tag $IMAGE_REPO_NAME:$IMAGE_TAG $IMAGE_ID;", + "docker push $IMAGE_ID" + ] + }, + "post_build": { + "commands": [ + "aws proton --region $AWS_DEFAULT_REGION get-service --name $service_name | jq -r .service.spec > service.yaml", + "yq w service.yaml 'instances[*].spec.image' \"$IMAGE_ID\" > rendered_service.yaml" + ] + } + }, + "artifacts": { + "files": [ + "rendered_service.yaml" + ] + } + } + Type: CODEPIPELINE + EncryptionKey: + Fn::GetAtt: + - PipelineArtifactsBucketEncryptionKey + - Arn +{% for service_instance in service_instances %} + Deploy{{loop.index}}Project: + Type: AWS::CodeBuild::Project + Properties: + Artifacts: + Type: CODEPIPELINE + Environment: + ComputeType: BUILD_GENERAL1_SMALL + Image: aws/codebuild/amazonlinux2-x86_64-standard:3.0 + PrivilegedMode: false + Type: LINUX_CONTAINER + EnvironmentVariables: + - Name: service_name + Type: PLAINTEXT + Value: '{{service.name}}' + - Name: service_instance_name + Type: PLAINTEXT + Value: '{{service_instance.name}}' + ServiceRole: + Fn::GetAtt: + - DeploymentRole + - Arn + Source: + BuildSpec: >- + { + "version": "0.2", + "phases": { + "build": { + "commands": [ + "pip3 install --upgrade --user awscli", + "aws proton --region $AWS_DEFAULT_REGION update-service-instance --deployment-type CURRENT_VERSION --name $service_instance_name --service-name $service_name --spec file://rendered_service.yaml", + "aws proton --region $AWS_DEFAULT_REGION wait service-instance-deployed --name $service_instance_name --service-name $service_name" + ] + } + } + } + Type: CODEPIPELINE + EncryptionKey: + Fn::GetAtt: + - PipelineArtifactsBucketEncryptionKey + - Arn +{% endfor %} + # This role is used to build and publish an image to ECR + PublishRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Statement: + - Action: sts:AssumeRole + Effect: Allow + Principal: + Service: codebuild.amazonaws.com + Version: "2012-10-17" + PublishRoleDefaultPolicy: + Type: AWS::IAM::Policy + Properties: + PolicyDocument: + Statement: + - Action: + - logs:CreateLogGroup + - logs:CreateLogStream + - logs:PutLogEvents + Effect: Allow + Resource: + - Fn::Join: + - "" + - - "arn:" + - Ref: AWS::Partition + - ":logs:" + - Ref: AWS::Region + - ":" + - Ref: AWS::AccountId + - :log-group:/aws/codebuild/ + - Ref: BuildProject + - Fn::Join: + - "" + - - "arn:" + - Ref: AWS::Partition + - ":logs:" + - Ref: AWS::Region + - ":" + - Ref: AWS::AccountId + - :log-group:/aws/codebuild/ + - Ref: BuildProject + - :* + - Action: + - codebuild:CreateReportGroup + - codebuild:CreateReport + - codebuild:UpdateReport + - codebuild:BatchPutTestCases + Effect: Allow + Resource: + Fn::Join: + - "" + - - "arn:" + - Ref: AWS::Partition + - ":codebuild:" + - Ref: AWS::Region + - ":" + - Ref: AWS::AccountId + - :report-group/ + - Ref: BuildProject + - -* + - Action: + - ecr:GetAuthorizationToken + Effect: Allow + Resource: "*" + - Action: + - ecr:BatchCheckLayerAvailability + - ecr:CompleteLayerUpload + - ecr:GetAuthorizationToken + - ecr:InitiateLayerUpload + - ecr:PutImage + - ecr:UploadLayerPart + Effect: Allow + Resource: + Fn::GetAtt: + - ECRRepo + - Arn + - Action: + - proton:GetService + Effect: Allow + Resource: "*" + - Action: + - s3:GetObject* + - s3:GetBucket* + - s3:List* + - s3:DeleteObject* + - s3:PutObject* + - s3:Abort* + Effect: Allow + Resource: + - Fn::GetAtt: + - PipelineArtifactsBucket + - Arn + - Fn::Join: + - "" + - - Fn::GetAtt: + - PipelineArtifactsBucket + - Arn + - /* + - Action: + - kms:Decrypt + - kms:DescribeKey + - kms:Encrypt + - kms:ReEncrypt* + - kms:GenerateDataKey* + Effect: Allow + Resource: + Fn::GetAtt: + - PipelineArtifactsBucketEncryptionKey + - Arn + - Action: + - kms:Decrypt + - kms:Encrypt + - kms:ReEncrypt* + - kms:GenerateDataKey* + Effect: Allow + Resource: + Fn::GetAtt: + - PipelineArtifactsBucketEncryptionKey + - Arn + Version: "2012-10-17" + PolicyName: PublishRoleDefaultPolicy + Roles: + - Ref: PublishRole + + DeploymentRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Statement: + - Action: sts:AssumeRole + Effect: Allow + Principal: + Service: codebuild.amazonaws.com + Version: "2012-10-17" + DeploymentRoleDefaultPolicy: + Type: AWS::IAM::Policy + Properties: + PolicyDocument: + Statement: + - Action: + - logs:CreateLogGroup + - logs:CreateLogStream + - logs:PutLogEvents + Effect: Allow + Resource: + - Fn::Join: + - "" + - - "arn:" + - Ref: AWS::Partition + - ":logs:" + - Ref: AWS::Region + - ":" + - Ref: AWS::AccountId + - :log-group:/aws/codebuild/Deploy*Project* + - Fn::Join: + - "" + - - "arn:" + - Ref: AWS::Partition + - ":logs:" + - Ref: AWS::Region + - ":" + - Ref: AWS::AccountId + - :log-group:/aws/codebuild/Deploy*Project:* + - Action: + - codebuild:CreateReportGroup + - codebuild:CreateReport + - codebuild:UpdateReport + - codebuild:BatchPutTestCases + Effect: Allow + Resource: + Fn::Join: + - "" + - - "arn:" + - Ref: AWS::Partition + - ":codebuild:" + - Ref: AWS::Region + - ":" + - Ref: AWS::AccountId + - :report-group/Deploy*Project + - -* + - Action: + - proton:UpdateServiceInstance + - proton:GetServiceInstance + Effect: Allow + Resource: "*" + - Action: + - s3:GetObject* + - s3:GetBucket* + - s3:List* + Effect: Allow + Resource: + - Fn::GetAtt: + - PipelineArtifactsBucket + - Arn + - Fn::Join: + - "" + - - Fn::GetAtt: + - PipelineArtifactsBucket + - Arn + - /* + - Action: + - kms:Decrypt + - kms:DescribeKey + Effect: Allow + Resource: + Fn::GetAtt: + - PipelineArtifactsBucketEncryptionKey + - Arn + - Action: + - kms:Decrypt + - kms:Encrypt + - kms:ReEncrypt* + - kms:GenerateDataKey* + Effect: Allow + Resource: + Fn::GetAtt: + - PipelineArtifactsBucketEncryptionKey + - Arn + Version: "2012-10-17" + PolicyName: DeploymentRoleDefaultPolicy + Roles: + - Ref: DeploymentRole + PipelineArtifactsBucketEncryptionKey: + Type: AWS::KMS::Key + Properties: + KeyPolicy: + Statement: + - Action: + - kms:Create* + - kms:Describe* + - kms:Enable* + - kms:List* + - kms:Put* + - kms:Update* + - kms:Revoke* + - kms:Disable* + - kms:Get* + - kms:Delete* + - kms:ScheduleKeyDeletion + - kms:CancelKeyDeletion + - kms:GenerateDataKey + - kms:TagResource + - kms:UntagResource + Effect: Allow + Principal: + AWS: + Fn::Join: + - "" + - - "arn:" + - Ref: AWS::Partition + - ":iam::" + - Ref: AWS::AccountId + - :root + Resource: "*" + - Action: + - kms:Decrypt + - kms:DescribeKey + - kms:Encrypt + - kms:ReEncrypt* + - kms:GenerateDataKey* + Effect: Allow + Principal: + AWS: + Fn::GetAtt: + - PipelineRole + - Arn + Resource: "*" + - Action: + - kms:Decrypt + - kms:DescribeKey + - kms:Encrypt + - kms:ReEncrypt* + - kms:GenerateDataKey* + Effect: Allow + Principal: + AWS: + Fn::GetAtt: + - PublishRole + - Arn + Resource: "*" + - Action: + - kms:Decrypt + - kms:Encrypt + - kms:ReEncrypt* + - kms:GenerateDataKey* + Effect: Allow + Principal: + AWS: + Fn::GetAtt: + - PublishRole + - Arn + Resource: "*" + - Action: + - kms:Decrypt + - kms:DescribeKey + Effect: Allow + Principal: + AWS: + Fn::GetAtt: + - DeploymentRole + - Arn + Resource: "*" + - Action: + - kms:Decrypt + - kms:Encrypt + - kms:ReEncrypt* + - kms:GenerateDataKey* + Effect: Allow + Principal: + AWS: + Fn::GetAtt: + - DeploymentRole + - Arn + Resource: "*" + Version: "2012-10-17" + UpdateReplacePolicy: Delete + DeletionPolicy: Delete + PipelineArtifactsBucket: + Type: AWS::S3::Bucket + Properties: + VersioningConfiguration: + Status: Enabled + BucketEncryption: + ServerSideEncryptionConfiguration: + - ServerSideEncryptionByDefault: + KMSMasterKeyID: + Fn::GetAtt: + - PipelineArtifactsBucketEncryptionKey + - Arn + SSEAlgorithm: aws:kms + PublicAccessBlockConfiguration: + BlockPublicAcls: true + BlockPublicPolicy: true + IgnorePublicAcls: true + RestrictPublicBuckets: true + UpdateReplacePolicy: Retain + DeletionPolicy: Retain + PipelineArtifactsBucketEncryptionKeyAlias: + Type: AWS::KMS::Alias + Properties: + AliasName: 'alias/codepipeline-encryption-key-{{ service.name }}' + TargetKeyId: + Fn::GetAtt: + - PipelineArtifactsBucketEncryptionKey + - Arn + UpdateReplacePolicy: Delete + DeletionPolicy: Delete + PipelineRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Statement: + - Action: sts:AssumeRole + Effect: Allow + Principal: + Service: codepipeline.amazonaws.com + Version: "2012-10-17" + PipelineRoleDefaultPolicy: + Type: AWS::IAM::Policy + Properties: + PolicyDocument: + Statement: + - Action: + - s3:GetObject* + - s3:GetBucket* + - s3:List* + - s3:DeleteObject* + - s3:PutObject* + - s3:Abort* + Effect: Allow + Resource: + - Fn::GetAtt: + - PipelineArtifactsBucket + - Arn + - Fn::Join: + - "" + - - Fn::GetAtt: + - PipelineArtifactsBucket + - Arn + - /* + - Action: + - kms:Decrypt + - kms:DescribeKey + - kms:Encrypt + - kms:ReEncrypt* + - kms:GenerateDataKey* + Effect: Allow + Resource: + Fn::GetAtt: + - PipelineArtifactsBucketEncryptionKey + - Arn + - Action: codestar-connections:* + Effect: Allow + Resource: "*" + - Action: sts:AssumeRole + Effect: Allow + Resource: + Fn::GetAtt: + - PipelineBuildCodePipelineActionRole + - Arn + - Action: sts:AssumeRole + Effect: Allow + Resource: + Fn::GetAtt: + - PipelineDeployCodePipelineActionRole + - Arn + Version: "2012-10-17" + PolicyName: PipelineRoleDefaultPolicy + Roles: + - Ref: PipelineRole + Pipeline: + Type: AWS::CodePipeline::Pipeline + Properties: + RoleArn: + Fn::GetAtt: + - PipelineRole + - Arn + Stages: + - Actions: + - ActionTypeId: + Category: Source + Owner: AWS + Provider: CodeStarSourceConnection + Version: "1" + Configuration: + ConnectionArn: '{{ service.repository_connection_arn }}' + FullRepositoryId: '{{ service.repository_id }}' + BranchName: '{{ service.branch_name }}' + Name: Checkout + OutputArtifacts: + - Name: Artifact_Source_Checkout + RunOrder: 1 + Name: Source + - Actions: + - ActionTypeId: + Category: Build + Owner: AWS + Provider: CodeBuild + Version: "1" + Configuration: + ProjectName: + Ref: BuildProject + InputArtifacts: + - Name: Artifact_Source_Checkout + Name: Build + OutputArtifacts: + - Name: BuildOutput + RoleArn: + Fn::GetAtt: + - PipelineBuildCodePipelineActionRole + - Arn + RunOrder: 1 + Name: Build {%- for service_instance in service_instances %} + - Actions: + - ActionTypeId: + Category: Build + Owner: AWS + Provider: CodeBuild + Version: "1" + Configuration: + ProjectName: + Ref: Deploy{{loop.index}}Project + InputArtifacts: + - Name: BuildOutput + Name: Deploy + RoleArn: + Fn::GetAtt: + - PipelineDeployCodePipelineActionRole + - Arn + RunOrder: 1 + Name: 'Deploy{{service_instance.name}}' +{%- endfor %} + ArtifactStore: + EncryptionKey: + Id: + Fn::GetAtt: + - PipelineArtifactsBucketEncryptionKey + - Arn + Type: KMS + Location: + Ref: PipelineArtifactsBucket + Type: S3 + DependsOn: + - PipelineRoleDefaultPolicy + - PipelineRole + PipelineBuildCodePipelineActionRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Statement: + - Action: sts:AssumeRole + Effect: Allow + Principal: + AWS: + Fn::Join: + - "" + - - "arn:" + - Ref: AWS::Partition + - ":iam::" + - Ref: AWS::AccountId + - :root + Version: "2012-10-17" + PipelineBuildCodePipelineActionRoleDefaultPolicy: + Type: AWS::IAM::Policy + Properties: + PolicyDocument: + Statement: + - Action: + - codebuild:BatchGetBuilds + - codebuild:StartBuild + - codebuild:StopBuild + Effect: Allow + Resource: + Fn::GetAtt: + - BuildProject + - Arn + Version: "2012-10-17" + PolicyName: PipelineBuildCodePipelineActionRoleDefaultPolicy + Roles: + - Ref: PipelineBuildCodePipelineActionRole + PipelineDeployCodePipelineActionRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Statement: + - Action: sts:AssumeRole + Effect: Allow + Principal: + AWS: + Fn::Join: + - "" + - - "arn:" + - Ref: AWS::Partition + - ":iam::" + - Ref: AWS::AccountId + - :root + Version: "2012-10-17" + PipelineDeployCodePipelineActionRoleDefaultPolicy: + Type: AWS::IAM::Policy + Properties: + PolicyDocument: + Statement: + - Action: + - codebuild:BatchGetBuilds + - codebuild:StartBuild + - codebuild:StopBuild + Effect: Allow + Resource: + Fn::Join: + - "" + - - "arn:" + - Ref: AWS::Partition + - ":codebuild:" + - Ref: AWS::Region + - ":" + - Ref: AWS::AccountId + - ":project/Deploy*" + Version: "2012-10-17" + PolicyName: PipelineDeployCodePipelineActionRoleDefaultPolicy + Roles: + - Ref: PipelineDeployCodePipelineActionRole +Outputs: + PipelineEndpoint: + Description: The URL to access the pipeline + Value: !Sub "https://${AWS::Region}.console.aws.amazon.com/codesuite/codepipeline/pipelines/${Pipeline}/view?region=${AWS::Region}" diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/pipeline_infrastructure/manifest.yaml b/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/pipeline_infrastructure/manifest.yaml new file mode 100644 index 0000000..eed587b --- /dev/null +++ b/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/pipeline_infrastructure/manifest.yaml @@ -0,0 +1,5 @@ +infrastructure: + templates: + - file: "cloudformation.yaml" + rendering_engine: jinja + template_language: cloudformation diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/schema/schema.yaml b/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/schema/schema.yaml new file mode 100644 index 0000000..f546157 --- /dev/null +++ b/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/schema/schema.yaml @@ -0,0 +1,57 @@ +schema: + format: + openapi: "3.0.0" + service_input_type: "PrivateServiceInput" + pipeline_input_type: "PipelineInputs" + + types: + PrivateServiceInput: + type: object + description: "Input properties for a Private Fargate service" + properties: + port: + type: number + description: "The port to route traffic to" + default: 8080 + minimum: 0 + maximum: 65535 + desired_count: + type: number + description: "The default number of Fargate tasks you want running" + default: 1 + minimum: 1 + task_size: + type: string + description: "The size of the task you want to run" + enum: ["x-small", "small", "medium", "large", "x-large"] + default: "x-small" + image: + type: string + description: "The name/url of the container image" + default: "public.ecr.aws/z9d2n7e1/nginx:1.21.0" + minLength: 1 + maxLength: 200 + service_discovery_name: + type: string + description: "The name of the service to register in service discovery" + minLength: 3 + maxLength: 24 + required: + - service_discovery_name + + PipelineInputs: + type: object + description: "Pipeline input properties" + properties: + dockerfile: + type: string + description: "The location of the Dockerfile to build" + default: "Dockerfile" + minLength: 1 + maxLength: 100 + unit_test_command: + type: string + description: "The command to run to unit test the application code" + default: "echo 'add your unit test command here'" + minLength: 1 + maxLength: 200 \ No newline at end of file diff --git a/public-private-fargate-microservices-dotnetfx/policies/proton-service-assume-policy.json b/public-private-fargate-microservices-dotnetfx/policies/proton-service-assume-policy.json new file mode 100644 index 0000000..a4c9f57 --- /dev/null +++ b/public-private-fargate-microservices-dotnetfx/policies/proton-service-assume-policy.json @@ -0,0 +1,12 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "Service": "proton.amazonaws.com" + }, + "Action": "sts:AssumeRole" + } + ] + } diff --git a/public-private-fargate-microservices-dotnetfx/specs/env-spec.yaml b/public-private-fargate-microservices-dotnetfx/specs/env-spec.yaml new file mode 100644 index 0000000..59834af --- /dev/null +++ b/public-private-fargate-microservices-dotnetfx/specs/env-spec.yaml @@ -0,0 +1,3 @@ +proton: EnvironmentSpec +spec: + vpc_cidr: "10.0.0.0/16" diff --git a/public-private-fargate-microservices-dotnetfx/specs/svc-private-spec.yaml b/public-private-fargate-microservices-dotnetfx/specs/svc-private-spec.yaml new file mode 100644 index 0000000..52ce57e --- /dev/null +++ b/public-private-fargate-microservices-dotnetfx/specs/svc-private-spec.yaml @@ -0,0 +1,13 @@ +proton: ServiceSpec + +pipeline: + unit_test_command: "ls" + +instances: + - name: "backend-dev" + environment: "Beta" + spec: + desired_count: 2 + port: 80 + task_size: "medium" + service_discovery_name: "backend-dev" diff --git a/public-private-fargate-microservices-dotnetfx/specs/svc-public-spec.yaml b/public-private-fargate-microservices-dotnetfx/specs/svc-public-spec.yaml new file mode 100644 index 0000000..dd6f2a8 --- /dev/null +++ b/public-private-fargate-microservices-dotnetfx/specs/svc-public-spec.yaml @@ -0,0 +1,13 @@ +proton: ServiceSpec + +pipeline: + unit_test_command: "ls" + +instances: + - name: "frontend-dev" + environment: "Beta" + spec: + desired_count: 2 + port: 80 + task_size: "medium" + service_discovery_name: "frontend-dev" From bda073aa418acd2aa72776dea13e30ccec9ec46a Mon Sep 17 00:00:00 2001 From: Carlos Santos Date: Wed, 23 Mar 2022 13:51:37 -0700 Subject: [PATCH 02/20] style: Formatting Cleanup - Consistent use of single quotes - Use of shorthand yaml syntax - Removed default image --- .../cloudformation.yaml | 72 +--- .../cloudformation.yaml | 336 ++++-------------- .../v1/schema/schema.yaml | 2 +- .../cloudformation.yaml | 5 +- .../cloudformation.yaml | 335 ++++------------- .../private-fargate-svc/v1/schema/schema.yaml | 2 +- 6 files changed, 172 insertions(+), 580 deletions(-) diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/instance_infrastructure/cloudformation.yaml b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/instance_infrastructure/cloudformation.yaml index bee5b88..f02c5f7 100644 --- a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/instance_infrastructure/cloudformation.yaml +++ b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/instance_infrastructure/cloudformation.yaml @@ -40,6 +40,7 @@ Resources: LogGroup: Type: AWS::Logs::LogGroup Properties: + #TODO: Should this include environment name? LogGroupName: '{{service.name}}/{{service_instance.name}}' # The task definition. This is a simple metadata description of what @@ -54,7 +55,7 @@ Resources: RequiresCompatibilities: - FARGATE ExecutionRoleArn: '{{environment.outputs.ECSTaskExecutionRole}}' - TaskRoleArn: !Ref "AWS::NoValue" + TaskRoleArn: !Ref 'AWS::NoValue' ContainerDefinitions: - Name: '{{service_instance.name}}' Cpu: !FindInMap [TaskSize, {{service_instance.inputs.task_size}}, cpu] @@ -75,6 +76,7 @@ Resources: # The service_instance.inputs. The service is a resource which allows you to run multiple # copies of a type of task, and gather up their logs and metrics, as well # as monitor the number of running tasks and replace any that have crashed + # TODO: Need to sepcify Windows constraint Service: Type: AWS::ECS::Service DependsOn: LoadBalancerRule @@ -153,34 +155,19 @@ Resources: Properties: ServiceNamespace: 'ecs' ScalableDimension: 'ecs:service:DesiredCount' - ResourceId: - Fn::Join: - - '/' - - - service - - '{{environment.outputs.ClusterName}}' - - '{{service.name}}_{{service_instance.name}}' + ResourceId: !Sub 'service/{{environment.outputs.ClusterName}}/{{service.name}}_{{service_instance.name}}' MinCapacity: 1 MaxCapacity: 10 - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/ecs.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_ECSService + RoleARN: !Sub 'arn:aws:iam::${AWS::AccountId}:role/aws-service-role/ecs.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_ECSService' # Create scaling policies for the service ScaleDownPolicy: Type: AWS::ApplicationAutoScaling::ScalingPolicy DependsOn: ScalableTarget Properties: - PolicyName: - Fn::Join: - - '/' - - - scale - - '{{service.name}}_{{service_instance.name}}' - - down + PolicyName: !Sub 'scale/{{service.name}}_{{service_instance.name}}/down' PolicyType: StepScaling - ResourceId: - Fn::Join: - - '/' - - - service - - '{{environment.outputs.ClusterName}}' - - '{{service.name}}_{{service_instance.name}}' + ResourceId: !Sub 'service/{{environment.outputs.ClusterName}}/{{service.name}}_{{service_instance.name}}' ScalableDimension: 'ecs:service:DesiredCount' ServiceNamespace: 'ecs' StepScalingPolicyConfiguration: @@ -195,19 +182,9 @@ Resources: Type: AWS::ApplicationAutoScaling::ScalingPolicy DependsOn: ScalableTarget Properties: - PolicyName: - Fn::Join: - - '/' - - - scale - - '{{service.name}}_{{service_instance.name}}' - - up + PolicyName: !Sub 'scale/{{service.name}}_{{service_instance.name}}/up' PolicyType: StepScaling - ResourceId: - Fn::Join: - - '/' - - - service - - '{{environment.outputs.ClusterName}}' - - '{{service.name}}_{{service_instance.name}}' + ResourceId: !Sub 'service/{{environment.outputs.ClusterName}}/{{service.name}}_{{service_instance.name}}' ScalableDimension: 'ecs:service:DesiredCount' ServiceNamespace: 'ecs' StepScalingPolicyConfiguration: @@ -228,16 +205,8 @@ Resources: LowCpuUsageAlarm: Type: AWS::CloudWatch::Alarm Properties: - AlarmName: - Fn::Join: - - '-' - - - low-cpu - - '{{service.name}}_{{service_instance.name}}' - AlarmDescription: - Fn::Join: - - ' ' - - - "Low CPU utilization for service" - - '{{service.name}}_{{service_instance.name}}' + AlarmName: !Sub 'low-cpu-{{service.name}}_{{service_instance.name}}' + AlarmDescription: !Sub 'Low CPU utilization for service {{service.name}}_{{service_instance.name}}' MetricName: CPUUtilization Namespace: AWS/ECS Dimensions: @@ -257,16 +226,8 @@ Resources: HighCpuUsageAlarm: Type: AWS::CloudWatch::Alarm Properties: - AlarmName: - Fn::Join: - - '-' - - - high-cpu - - '{{service.name}}_{{service_instance.name}}' - AlarmDescription: - Fn::Join: - - ' ' - - - "High CPU utilization for service" - - '{{service.name}}_{{service_instance.name}}' + AlarmName: !Sub 'high-cpu-{{service.name}}_{{service_instance.name}}' + AlarmDescription: !Sub 'High CPU utilization for service {{service.name}}_{{service_instance.name}}' MetricName: CPUUtilization Namespace: AWS/ECS Dimensions: @@ -288,7 +249,7 @@ Resources: Properties: Description: Ingress from the public ALB GroupId: '{{environment.outputs.ContainerSecurityGroup}}' - IpProtocol: -1 + IpProtocol: '-1' SourceSecurityGroupId: !Ref 'PublicLoadBalancerSG' # Public load balancer, hosted in public subnets that is accessible @@ -303,7 +264,8 @@ Resources: SecurityGroupIngress: # Allow access to ALB from anywhere on the internet - CidrIp: 0.0.0.0/0 - IpProtocol: -1 + #TODO: Should this be narrowed down? + IpProtocol: '-1' Tags: - Key: Name Value: !FindInMap ['EnvironmentNameConfig', 'Environment', 'Name'] @@ -340,7 +302,7 @@ Resources: Outputs: ServiceEndpoint: Description: The URL to access the service - Value: !Sub "http://${PublicLoadBalancer.DNSName}" + Value: !Sub 'http://${PublicLoadBalancer.DNSName}' ServiceDiscovery: Description: The registered service discovery Service Id Value: !Ref DiscoveryService diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/pipeline_infrastructure/cloudformation.yaml b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/pipeline_infrastructure/cloudformation.yaml index a6a82d8..3594f88 100644 --- a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/pipeline_infrastructure/cloudformation.yaml +++ b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/pipeline_infrastructure/cloudformation.yaml @@ -5,7 +5,7 @@ Resources: Properties: # This policy allows environment accounts to get the image from ECRRepo in the management account RepositoryPolicyText: - Version: "2012-10-17" + Version: '2012-10-17' Statement: - Sid: AllowPull Effect: Allow @@ -19,6 +19,7 @@ Resources: - ecr:BatchCheckLayerAvailability - ecr:GetDownloadUrlForLayer - ecr:BatchGetImage + # TODO: Need to change to support Windows BuildProject: Type: AWS::CodeBuild::Project Properties: @@ -36,10 +37,7 @@ Resources: - Name: service_name Type: PLAINTEXT Value: '{{service.name}}' - ServiceRole: - Fn::GetAtt: - - PublishRole - - Arn + ServiceRole: !GetAtt PublishRole.Arn Source: BuildSpec: Fn::Join: @@ -95,10 +93,7 @@ Resources: } } Type: CODEPIPELINE - EncryptionKey: - Fn::GetAtt: - - PipelineArtifactsBucketEncryptionKey - - Arn + EncryptionKey: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn {% for service_instance in service_instances %} Deploy{{loop.index}}Project: Type: AWS::CodeBuild::Project @@ -117,10 +112,7 @@ Resources: - Name: service_instance_name Type: PLAINTEXT Value: '{{service_instance.name}}' - ServiceRole: - Fn::GetAtt: - - DeploymentRole - - Arn + ServiceRole: !GetAtt DeploymentRole.Arn Source: BuildSpec: >- { @@ -136,10 +128,7 @@ Resources: } } Type: CODEPIPELINE - EncryptionKey: - Fn::GetAtt: - - PipelineArtifactsBucketEncryptionKey - - Arn + EncryptionKey: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn {% endfor %} # This role is used to build and publish an image to ECR PublishRole: @@ -151,7 +140,7 @@ Resources: Effect: Allow Principal: Service: codebuild.amazonaws.com - Version: "2012-10-17" + Version: '2012-10-17' PublishRoleDefaultPolicy: Type: AWS::IAM::Policy Properties: @@ -163,49 +152,19 @@ Resources: - logs:PutLogEvents Effect: Allow Resource: - - Fn::Join: - - "" - - - "arn:" - - Ref: AWS::Partition - - ":logs:" - - Ref: AWS::Region - - ":" - - Ref: AWS::AccountId - - :log-group:/aws/codebuild/ - - Ref: BuildProject - - Fn::Join: - - "" - - - "arn:" - - Ref: AWS::Partition - - ":logs:" - - Ref: AWS::Region - - ":" - - Ref: AWS::AccountId - - :log-group:/aws/codebuild/ - - Ref: BuildProject - - :* + - !Sub 'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/${BuildProject}' + - !Sub 'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/${BuildProject}:*' - Action: - codebuild:CreateReportGroup - codebuild:CreateReport - codebuild:UpdateReport - codebuild:BatchPutTestCases Effect: Allow - Resource: - Fn::Join: - - "" - - - "arn:" - - Ref: AWS::Partition - - ":codebuild:" - - Ref: AWS::Region - - ":" - - Ref: AWS::AccountId - - :report-group/ - - Ref: BuildProject - - -* + Resource: !Sub 'arn:${AWS::Partition}:codebuild:${AWS::Region}:${AWS::AccountId}:report-group/${BuildProject}-*' - Action: - ecr:GetAuthorizationToken Effect: Allow - Resource: "*" + Resource: '*' - Action: - ecr:BatchCheckLayerAvailability - ecr:CompleteLayerUpload @@ -214,14 +173,11 @@ Resources: - ecr:PutImage - ecr:UploadLayerPart Effect: Allow - Resource: - Fn::GetAtt: - - ECRRepo - - Arn + Resource: !GetAtt ECRRepo.Arn - Action: - proton:GetService Effect: Allow - Resource: "*" + Resource: '*' - Action: - s3:GetObject* - s3:GetBucket* @@ -231,15 +187,8 @@ Resources: - s3:Abort* Effect: Allow Resource: - - Fn::GetAtt: - - PipelineArtifactsBucket - - Arn - - Fn::Join: - - "" - - - Fn::GetAtt: - - PipelineArtifactsBucket - - Arn - - /* + - !GetAtt PipelineArtifactsBucket.Arn + - !Sub '${PipelineArtifactsBucket.Arn}/*' - Action: - kms:Decrypt - kms:DescribeKey @@ -247,24 +196,17 @@ Resources: - kms:ReEncrypt* - kms:GenerateDataKey* Effect: Allow - Resource: - Fn::GetAtt: - - PipelineArtifactsBucketEncryptionKey - - Arn + Resource: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn - Action: - kms:Decrypt - kms:Encrypt - kms:ReEncrypt* - kms:GenerateDataKey* Effect: Allow - Resource: - Fn::GetAtt: - - PipelineArtifactsBucketEncryptionKey - - Arn - Version: "2012-10-17" + Resource: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn + Version: '2012-10-17' PolicyName: PublishRoleDefaultPolicy - Roles: - - Ref: PublishRole + Roles: !Ref PublishRole DeploymentRole: Type: AWS::IAM::Role @@ -275,7 +217,7 @@ Resources: Effect: Allow Principal: Service: codebuild.amazonaws.com - Version: "2012-10-17" + Version: '2012-10-17' DeploymentRoleDefaultPolicy: Type: AWS::IAM::Policy Properties: @@ -287,83 +229,43 @@ Resources: - logs:PutLogEvents Effect: Allow Resource: - - Fn::Join: - - "" - - - "arn:" - - Ref: AWS::Partition - - ":logs:" - - Ref: AWS::Region - - ":" - - Ref: AWS::AccountId - - :log-group:/aws/codebuild/Deploy*Project* - - Fn::Join: - - "" - - - "arn:" - - Ref: AWS::Partition - - ":logs:" - - Ref: AWS::Region - - ":" - - Ref: AWS::AccountId - - :log-group:/aws/codebuild/Deploy*Project:* + - !Sub 'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/Deploy*Project*' + - !Sub 'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/Deploy*Project:*' - Action: - codebuild:CreateReportGroup - codebuild:CreateReport - codebuild:UpdateReport - codebuild:BatchPutTestCases Effect: Allow - Resource: - Fn::Join: - - "" - - - "arn:" - - Ref: AWS::Partition - - ":codebuild:" - - Ref: AWS::Region - - ":" - - Ref: AWS::AccountId - - :report-group/Deploy*Project - - -* + Resource: !Sub 'arn:${AWS::Partition}:codebuild:${AWS::Region}:${AWS::AccountId}:report-group/Deploy*Project-*' - Action: - proton:UpdateServiceInstance - proton:GetServiceInstance Effect: Allow - Resource: "*" + Resource: '*' - Action: - s3:GetObject* - s3:GetBucket* - s3:List* Effect: Allow Resource: - - Fn::GetAtt: - - PipelineArtifactsBucket - - Arn - - Fn::Join: - - "" - - - Fn::GetAtt: - - PipelineArtifactsBucket - - Arn - - /* + - !GetAtt PipelineArtifactsBucket.Arn + - !Sub '${PipelineArtifactsBucket.Arn}/*' - Action: - kms:Decrypt - kms:DescribeKey Effect: Allow - Resource: - Fn::GetAtt: - - PipelineArtifactsBucketEncryptionKey - - Arn + Resource: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn - Action: - kms:Decrypt - kms:Encrypt - kms:ReEncrypt* - kms:GenerateDataKey* Effect: Allow - Resource: - Fn::GetAtt: - - PipelineArtifactsBucketEncryptionKey - - Arn - Version: "2012-10-17" + Resource: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn + Version: '2012-10-17' PolicyName: DeploymentRoleDefaultPolicy - Roles: - - Ref: DeploymentRole + Roles: !Ref DeploymentRole PipelineArtifactsBucketEncryptionKey: Type: AWS::KMS::Key Properties: @@ -387,15 +289,8 @@ Resources: - kms:UntagResource Effect: Allow Principal: - AWS: - Fn::Join: - - "" - - - "arn:" - - Ref: AWS::Partition - - ":iam::" - - Ref: AWS::AccountId - - :root - Resource: "*" + AWS: !Sub 'arn:${AWS::Partition}:iam::${AWS::AccountId}:root' + Resource: '*' - Action: - kms:Decrypt - kms:DescribeKey @@ -404,11 +299,8 @@ Resources: - kms:GenerateDataKey* Effect: Allow Principal: - AWS: - Fn::GetAtt: - - PipelineRole - - Arn - Resource: "*" + AWS: !GetAtt PipelineRole.Arn + Resource: '*' - Action: - kms:Decrypt - kms:DescribeKey @@ -417,11 +309,8 @@ Resources: - kms:GenerateDataKey* Effect: Allow Principal: - AWS: - Fn::GetAtt: - - PublishRole - - Arn - Resource: "*" + AWS: !GetAtt PublishRole.Arn + Resource: '*' - Action: - kms:Decrypt - kms:Encrypt @@ -429,21 +318,15 @@ Resources: - kms:GenerateDataKey* Effect: Allow Principal: - AWS: - Fn::GetAtt: - - PublishRole - - Arn - Resource: "*" + AWS: !GetAtt: PublishRole.Arn + Resource: '*' - Action: - kms:Decrypt - kms:DescribeKey Effect: Allow Principal: - AWS: - Fn::GetAtt: - - DeploymentRole - - Arn - Resource: "*" + AWS: !GetAtt DeploymentRole.Arn + Resource: '*' - Action: - kms:Decrypt - kms:Encrypt @@ -451,12 +334,9 @@ Resources: - kms:GenerateDataKey* Effect: Allow Principal: - AWS: - Fn::GetAtt: - - DeploymentRole - - Arn - Resource: "*" - Version: "2012-10-17" + AWS: !GetAtt DeploymentRole.Arn + Resource: '*' + Version: '2012-10-17' UpdateReplacePolicy: Delete DeletionPolicy: Delete PipelineArtifactsBucket: @@ -467,10 +347,7 @@ Resources: BucketEncryption: ServerSideEncryptionConfiguration: - ServerSideEncryptionByDefault: - KMSMasterKeyID: - Fn::GetAtt: - - PipelineArtifactsBucketEncryptionKey - - Arn + KMSMasterKeyID: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn SSEAlgorithm: aws:kms PublicAccessBlockConfiguration: BlockPublicAcls: true @@ -483,10 +360,7 @@ Resources: Type: AWS::KMS::Alias Properties: AliasName: 'alias/codepipeline-encryption-key-{{ service.name }}' - TargetKeyId: - Fn::GetAtt: - - PipelineArtifactsBucketEncryptionKey - - Arn + TargetKeyId: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn UpdateReplacePolicy: Delete DeletionPolicy: Delete PipelineRole: @@ -498,7 +372,7 @@ Resources: Effect: Allow Principal: Service: codepipeline.amazonaws.com - Version: "2012-10-17" + Version: '2012-10-17' PipelineRoleDefaultPolicy: Type: AWS::IAM::Policy Properties: @@ -513,15 +387,8 @@ Resources: - s3:Abort* Effect: Allow Resource: - - Fn::GetAtt: - - PipelineArtifactsBucket - - Arn - - Fn::Join: - - "" - - - Fn::GetAtt: - - PipelineArtifactsBucket - - Arn - - /* + - !GetAtt PipelineArtifactsBucket.Arn + - !Sub '${PipelineArtifactsBucket.Arn}/*' - Action: - kms:Decrypt - kms:DescribeKey @@ -529,43 +396,30 @@ Resources: - kms:ReEncrypt* - kms:GenerateDataKey* Effect: Allow - Resource: - Fn::GetAtt: - - PipelineArtifactsBucketEncryptionKey - - Arn + Resource: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn - Action: codestar-connections:* Effect: Allow - Resource: "*" + Resource: '*' - Action: sts:AssumeRole Effect: Allow - Resource: - Fn::GetAtt: - - PipelineBuildCodePipelineActionRole - - Arn + Resource: !GetAtt PipelineBuildCodePipelineActionRole.Arn - Action: sts:AssumeRole Effect: Allow - Resource: - Fn::GetAtt: - - PipelineDeployCodePipelineActionRole - - Arn - Version: "2012-10-17" + Resource: !GetAtt PipelineDeployCodePipelineActionRole.Arn + Version: '2012-10-17' PolicyName: PipelineRoleDefaultPolicy - Roles: - - Ref: PipelineRole + Roles: !Ref PipelineRole Pipeline: Type: AWS::CodePipeline::Pipeline Properties: - RoleArn: - Fn::GetAtt: - - PipelineRole - - Arn + RoleArn: !GetAtt PipelineRole.Arn Stages: - Actions: - ActionTypeId: Category: Source Owner: AWS Provider: CodeStarSourceConnection - Version: "1" + Version: 1 Configuration: ConnectionArn: '{{ service.repository_connection_arn }}' FullRepositoryId: '{{ service.repository_id }}' @@ -580,19 +434,15 @@ Resources: Category: Build Owner: AWS Provider: CodeBuild - Version: "1" + Version: 1 Configuration: - ProjectName: - Ref: BuildProject + ProjectName: !Ref BuildProject InputArtifacts: - Name: Artifact_Source_Checkout Name: Build OutputArtifacts: - Name: BuildOutput - RoleArn: - Fn::GetAtt: - - PipelineBuildCodePipelineActionRole - - Arn + RoleArn: !GetAtt PipelineBuildCodePipelineActionRole.Arn RunOrder: 1 Name: Build {%- for service_instance in service_instances %} - Actions: @@ -600,29 +450,21 @@ Resources: Category: Build Owner: AWS Provider: CodeBuild - Version: "1" + Version: 1 Configuration: - ProjectName: - Ref: Deploy{{loop.index}}Project + ProjectName: !Ref Deploy{{loop.index}}Project InputArtifacts: - Name: BuildOutput Name: Deploy - RoleArn: - Fn::GetAtt: - - PipelineDeployCodePipelineActionRole - - Arn + RoleArn: !GetAtt PipelineDeployCodePipelineActionRole.Arn RunOrder: 1 Name: 'Deploy{{service_instance.name}}' {%- endfor %} ArtifactStore: EncryptionKey: - Id: - Fn::GetAtt: - - PipelineArtifactsBucketEncryptionKey - - Arn + Id: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn Type: KMS - Location: - Ref: PipelineArtifactsBucket + Location: !Ref PipelineArtifactsBucket Type: S3 DependsOn: - PipelineRoleDefaultPolicy @@ -635,15 +477,8 @@ Resources: - Action: sts:AssumeRole Effect: Allow Principal: - AWS: - Fn::Join: - - "" - - - "arn:" - - Ref: AWS::Partition - - ":iam::" - - Ref: AWS::AccountId - - :root - Version: "2012-10-17" + AWS: !Sub 'arn:${AWS::Partition}:iam::${AWS::AccountId}:root' + Version: '2012-10-17' PipelineBuildCodePipelineActionRoleDefaultPolicy: Type: AWS::IAM::Policy Properties: @@ -654,14 +489,10 @@ Resources: - codebuild:StartBuild - codebuild:StopBuild Effect: Allow - Resource: - Fn::GetAtt: - - BuildProject - - Arn - Version: "2012-10-17" + Resource: !GetAtt BuildProject.Arn + Version: '2012-10-17' PolicyName: PipelineBuildCodePipelineActionRoleDefaultPolicy - Roles: - - Ref: PipelineBuildCodePipelineActionRole + Roles: !Ref PipelineBuildCodePipelineActionRole PipelineDeployCodePipelineActionRole: Type: AWS::IAM::Role Properties: @@ -670,15 +501,8 @@ Resources: - Action: sts:AssumeRole Effect: Allow Principal: - AWS: - Fn::Join: - - "" - - - "arn:" - - Ref: AWS::Partition - - ":iam::" - - Ref: AWS::AccountId - - :root - Version: "2012-10-17" + AWS: !Sub 'arn:${AWS::Partition}:iam::${AWS::AccountId}:root' + Version: '2012-10-17' PipelineDeployCodePipelineActionRoleDefaultPolicy: Type: AWS::IAM::Policy Properties: @@ -689,21 +513,11 @@ Resources: - codebuild:StartBuild - codebuild:StopBuild Effect: Allow - Resource: - Fn::Join: - - "" - - - "arn:" - - Ref: AWS::Partition - - ":codebuild:" - - Ref: AWS::Region - - ":" - - Ref: AWS::AccountId - - ":project/Deploy*" - Version: "2012-10-17" + Resource: !Sub 'arn:${AWS::Partition}:codebuild:${AWS::Region}:${AWS::AccountId}:project/Deploy*' + Version: '2012-10-17' PolicyName: PipelineDeployCodePipelineActionRoleDefaultPolicy - Roles: - - Ref: PipelineDeployCodePipelineActionRole + Roles: !Ref PipelineDeployCodePipelineActionRole Outputs: PipelineEndpoint: Description: The URL to access the pipeline - Value: !Sub "https://${AWS::Region}.console.aws.amazon.com/codesuite/codepipeline/pipelines/${Pipeline}/view?region=${AWS::Region}" + Value: !Sub https://${AWS::Region}.console.aws.amazon.com/codesuite/codepipeline/pipelines/${Pipeline}/view?region=${AWS::Region}' diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/schema/schema.yaml b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/schema/schema.yaml index b77cae8..cdeb072 100644 --- a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/schema/schema.yaml +++ b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/schema/schema.yaml @@ -28,7 +28,6 @@ schema: image: type: string description: "The name/url of the container image" - default: "public.ecr.aws/z9d2n7e1/nginx:1.21.0" minLength: 1 maxLength: 200 service_discovery_name: @@ -37,6 +36,7 @@ schema: minLength: 3 maxLength: 24 required: + - image - service_discovery_name PipelineInputs: diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/instance_infrastructure/cloudformation.yaml b/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/instance_infrastructure/cloudformation.yaml index 0d76adb..a7afd5c 100644 --- a/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/instance_infrastructure/cloudformation.yaml +++ b/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/instance_infrastructure/cloudformation.yaml @@ -39,6 +39,7 @@ Resources: LogGroup: Type: AWS::Logs::LogGroup Properties: + #TODO: Should this include environment name? LogGroupName: '{{service.name}}/{{service_instance.name}}' # The task definition. This is a simple metadata description of what @@ -50,10 +51,11 @@ Resources: Cpu: !FindInMap [TaskSize, {{service_instance.inputs.task_size}}, cpu] Memory: !FindInMap [TaskSize, {{service_instance.inputs.task_size}}, memory] NetworkMode: awsvpc + # TODO: Add Windows Requirement RequiresCompatibilities: - FARGATE ExecutionRoleArn: '{{environment.outputs.ECSTaskExecutionRole}}' - TaskRoleArn: !Ref "AWS::NoValue" + TaskRoleArn: !Ref 'AWS::NoValue' ContainerDefinitions: - Name: '{{service_instance.name}}' Cpu: !FindInMap [TaskSize, {{service_instance.inputs.task_size}}, cpu] @@ -79,6 +81,7 @@ Resources: Properties: ServiceName: '{{service.name}}_{{service_instance.name}}' Cluster: '{{environment.outputs.ClusterName}}' + # TODO: Add Windows Requirement LaunchType: FARGATE DesiredCount: '{{service_instance.inputs.desired_count}}' NetworkConfiguration: diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/pipeline_infrastructure/cloudformation.yaml b/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/pipeline_infrastructure/cloudformation.yaml index a6a82d8..24e897e 100644 --- a/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/pipeline_infrastructure/cloudformation.yaml +++ b/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/pipeline_infrastructure/cloudformation.yaml @@ -5,7 +5,7 @@ Resources: Properties: # This policy allows environment accounts to get the image from ECRRepo in the management account RepositoryPolicyText: - Version: "2012-10-17" + Version: '2012-10-17' Statement: - Sid: AllowPull Effect: Allow @@ -36,10 +36,7 @@ Resources: - Name: service_name Type: PLAINTEXT Value: '{{service.name}}' - ServiceRole: - Fn::GetAtt: - - PublishRole - - Arn + ServiceRole: !GetAtt PublishRole.Arn Source: BuildSpec: Fn::Join: @@ -95,10 +92,7 @@ Resources: } } Type: CODEPIPELINE - EncryptionKey: - Fn::GetAtt: - - PipelineArtifactsBucketEncryptionKey - - Arn + EncryptionKey: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn {% for service_instance in service_instances %} Deploy{{loop.index}}Project: Type: AWS::CodeBuild::Project @@ -117,10 +111,7 @@ Resources: - Name: service_instance_name Type: PLAINTEXT Value: '{{service_instance.name}}' - ServiceRole: - Fn::GetAtt: - - DeploymentRole - - Arn + ServiceRole: !GetAtt DeploymentRole.Arn Source: BuildSpec: >- { @@ -136,10 +127,7 @@ Resources: } } Type: CODEPIPELINE - EncryptionKey: - Fn::GetAtt: - - PipelineArtifactsBucketEncryptionKey - - Arn + EncryptionKey: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn {% endfor %} # This role is used to build and publish an image to ECR PublishRole: @@ -151,7 +139,7 @@ Resources: Effect: Allow Principal: Service: codebuild.amazonaws.com - Version: "2012-10-17" + Version: '2012-10-17' PublishRoleDefaultPolicy: Type: AWS::IAM::Policy Properties: @@ -163,49 +151,19 @@ Resources: - logs:PutLogEvents Effect: Allow Resource: - - Fn::Join: - - "" - - - "arn:" - - Ref: AWS::Partition - - ":logs:" - - Ref: AWS::Region - - ":" - - Ref: AWS::AccountId - - :log-group:/aws/codebuild/ - - Ref: BuildProject - - Fn::Join: - - "" - - - "arn:" - - Ref: AWS::Partition - - ":logs:" - - Ref: AWS::Region - - ":" - - Ref: AWS::AccountId - - :log-group:/aws/codebuild/ - - Ref: BuildProject - - :* + - !Sub 'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/${BuildProject}' + - !Sub 'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/${BuildProject}:*' - Action: - codebuild:CreateReportGroup - codebuild:CreateReport - codebuild:UpdateReport - codebuild:BatchPutTestCases Effect: Allow - Resource: - Fn::Join: - - "" - - - "arn:" - - Ref: AWS::Partition - - ":codebuild:" - - Ref: AWS::Region - - ":" - - Ref: AWS::AccountId - - :report-group/ - - Ref: BuildProject - - -* + Resource: !Sub 'arn:${AWS::Partition}:codebuild:${AWS::Region}:${AWS::AccountId}:report-group/${BuildProject}-*' - Action: - ecr:GetAuthorizationToken Effect: Allow - Resource: "*" + Resource: '*' - Action: - ecr:BatchCheckLayerAvailability - ecr:CompleteLayerUpload @@ -214,14 +172,11 @@ Resources: - ecr:PutImage - ecr:UploadLayerPart Effect: Allow - Resource: - Fn::GetAtt: - - ECRRepo - - Arn + Resource: !GetAtt ECRRepo.Arn - Action: - proton:GetService Effect: Allow - Resource: "*" + Resource: '*' - Action: - s3:GetObject* - s3:GetBucket* @@ -231,15 +186,8 @@ Resources: - s3:Abort* Effect: Allow Resource: - - Fn::GetAtt: - - PipelineArtifactsBucket - - Arn - - Fn::Join: - - "" - - - Fn::GetAtt: - - PipelineArtifactsBucket - - Arn - - /* + - !GetAtt PipelineArtifactsBucket.Arn + - !Sub '${PipelineArtifactsBucket.Arn}/*' - Action: - kms:Decrypt - kms:DescribeKey @@ -247,24 +195,17 @@ Resources: - kms:ReEncrypt* - kms:GenerateDataKey* Effect: Allow - Resource: - Fn::GetAtt: - - PipelineArtifactsBucketEncryptionKey - - Arn + Resource: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn - Action: - kms:Decrypt - kms:Encrypt - kms:ReEncrypt* - kms:GenerateDataKey* Effect: Allow - Resource: - Fn::GetAtt: - - PipelineArtifactsBucketEncryptionKey - - Arn - Version: "2012-10-17" + Resource: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn + Version: '2012-10-17' PolicyName: PublishRoleDefaultPolicy - Roles: - - Ref: PublishRole + Roles: !Ref PublishRole DeploymentRole: Type: AWS::IAM::Role @@ -275,7 +216,7 @@ Resources: Effect: Allow Principal: Service: codebuild.amazonaws.com - Version: "2012-10-17" + Version: '2012-10-17' DeploymentRoleDefaultPolicy: Type: AWS::IAM::Policy Properties: @@ -287,83 +228,43 @@ Resources: - logs:PutLogEvents Effect: Allow Resource: - - Fn::Join: - - "" - - - "arn:" - - Ref: AWS::Partition - - ":logs:" - - Ref: AWS::Region - - ":" - - Ref: AWS::AccountId - - :log-group:/aws/codebuild/Deploy*Project* - - Fn::Join: - - "" - - - "arn:" - - Ref: AWS::Partition - - ":logs:" - - Ref: AWS::Region - - ":" - - Ref: AWS::AccountId - - :log-group:/aws/codebuild/Deploy*Project:* + - !Sub 'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/Deploy*Project*' + - !Sub 'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/Deploy*Project:*' - Action: - codebuild:CreateReportGroup - codebuild:CreateReport - codebuild:UpdateReport - codebuild:BatchPutTestCases Effect: Allow - Resource: - Fn::Join: - - "" - - - "arn:" - - Ref: AWS::Partition - - ":codebuild:" - - Ref: AWS::Region - - ":" - - Ref: AWS::AccountId - - :report-group/Deploy*Project - - -* + Resource: !Sub 'arn:${AWS::Partition}:codebuild:${AWS::Region}:${AWS::AccountId}:report-group/Deploy*Project-*' - Action: - proton:UpdateServiceInstance - proton:GetServiceInstance Effect: Allow - Resource: "*" + Resource: '*' - Action: - s3:GetObject* - s3:GetBucket* - s3:List* Effect: Allow Resource: - - Fn::GetAtt: - - PipelineArtifactsBucket - - Arn - - Fn::Join: - - "" - - - Fn::GetAtt: - - PipelineArtifactsBucket - - Arn - - /* + - !GetAtt PipelineArtifactsBucket.Arn + - !Sub '${PipelineArtifactsBucket.Arn}/*' - Action: - kms:Decrypt - kms:DescribeKey Effect: Allow - Resource: - Fn::GetAtt: - - PipelineArtifactsBucketEncryptionKey - - Arn + Resource: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn - Action: - kms:Decrypt - kms:Encrypt - kms:ReEncrypt* - kms:GenerateDataKey* Effect: Allow - Resource: - Fn::GetAtt: - - PipelineArtifactsBucketEncryptionKey - - Arn - Version: "2012-10-17" + Resource: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn + Version: '2012-10-17' PolicyName: DeploymentRoleDefaultPolicy - Roles: - - Ref: DeploymentRole + Roles: !Ref DeploymentRole PipelineArtifactsBucketEncryptionKey: Type: AWS::KMS::Key Properties: @@ -387,15 +288,8 @@ Resources: - kms:UntagResource Effect: Allow Principal: - AWS: - Fn::Join: - - "" - - - "arn:" - - Ref: AWS::Partition - - ":iam::" - - Ref: AWS::AccountId - - :root - Resource: "*" + AWS: !Sub 'arn:${AWS::Partition}:iam::${AWS::AccountId}:root' + Resource: '*' - Action: - kms:Decrypt - kms:DescribeKey @@ -404,11 +298,8 @@ Resources: - kms:GenerateDataKey* Effect: Allow Principal: - AWS: - Fn::GetAtt: - - PipelineRole - - Arn - Resource: "*" + AWS: !GetAtt PipelineRole.Arn + Resource: '*' - Action: - kms:Decrypt - kms:DescribeKey @@ -417,11 +308,8 @@ Resources: - kms:GenerateDataKey* Effect: Allow Principal: - AWS: - Fn::GetAtt: - - PublishRole - - Arn - Resource: "*" + AWS: !GetAtt PublishRole.Arn + Resource: '*' - Action: - kms:Decrypt - kms:Encrypt @@ -429,21 +317,15 @@ Resources: - kms:GenerateDataKey* Effect: Allow Principal: - AWS: - Fn::GetAtt: - - PublishRole - - Arn - Resource: "*" + AWS: !GetAtt PublishRole.Arn + Resource: '*' - Action: - kms:Decrypt - kms:DescribeKey Effect: Allow Principal: - AWS: - Fn::GetAtt: - - DeploymentRole - - Arn - Resource: "*" + AWS: !GetAtt DeploymentRole.Arn + Resource: '*' - Action: - kms:Decrypt - kms:Encrypt @@ -451,12 +333,9 @@ Resources: - kms:GenerateDataKey* Effect: Allow Principal: - AWS: - Fn::GetAtt: - - DeploymentRole - - Arn - Resource: "*" - Version: "2012-10-17" + AWS: !GetAtt DeploymentRole.Arn + Resource: '*' + Version: '2012-10-17' UpdateReplacePolicy: Delete DeletionPolicy: Delete PipelineArtifactsBucket: @@ -467,10 +346,7 @@ Resources: BucketEncryption: ServerSideEncryptionConfiguration: - ServerSideEncryptionByDefault: - KMSMasterKeyID: - Fn::GetAtt: - - PipelineArtifactsBucketEncryptionKey - - Arn + KMSMasterKeyID: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn SSEAlgorithm: aws:kms PublicAccessBlockConfiguration: BlockPublicAcls: true @@ -483,10 +359,7 @@ Resources: Type: AWS::KMS::Alias Properties: AliasName: 'alias/codepipeline-encryption-key-{{ service.name }}' - TargetKeyId: - Fn::GetAtt: - - PipelineArtifactsBucketEncryptionKey - - Arn + TargetKeyId: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn UpdateReplacePolicy: Delete DeletionPolicy: Delete PipelineRole: @@ -498,7 +371,7 @@ Resources: Effect: Allow Principal: Service: codepipeline.amazonaws.com - Version: "2012-10-17" + Version: '2012-10-17' PipelineRoleDefaultPolicy: Type: AWS::IAM::Policy Properties: @@ -513,15 +386,8 @@ Resources: - s3:Abort* Effect: Allow Resource: - - Fn::GetAtt: - - PipelineArtifactsBucket - - Arn - - Fn::Join: - - "" - - - Fn::GetAtt: - - PipelineArtifactsBucket - - Arn - - /* + - !GetAtt PipelineArtifactsBucket.Arn + - !Sub '${PipelineArtifactsBucket.Arn}/*' - Action: - kms:Decrypt - kms:DescribeKey @@ -529,43 +395,30 @@ Resources: - kms:ReEncrypt* - kms:GenerateDataKey* Effect: Allow - Resource: - Fn::GetAtt: - - PipelineArtifactsBucketEncryptionKey - - Arn + Resource: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn - Action: codestar-connections:* Effect: Allow - Resource: "*" + Resource: '*' - Action: sts:AssumeRole Effect: Allow - Resource: - Fn::GetAtt: - - PipelineBuildCodePipelineActionRole - - Arn + Resource: !GetAtt PipelineBuildCodePipelineActionRole.Arn - Action: sts:AssumeRole Effect: Allow - Resource: - Fn::GetAtt: - - PipelineDeployCodePipelineActionRole - - Arn - Version: "2012-10-17" + Resource: !GetAtt PipelineDeployCodePipelineActionRole.Arn + Version: '2012-10-17' PolicyName: PipelineRoleDefaultPolicy - Roles: - - Ref: PipelineRole + Roles: !Ref PipelineRole Pipeline: Type: AWS::CodePipeline::Pipeline Properties: - RoleArn: - Fn::GetAtt: - - PipelineRole - - Arn + RoleArn: !GetAtt PipelineRole.Arn Stages: - Actions: - ActionTypeId: Category: Source Owner: AWS Provider: CodeStarSourceConnection - Version: "1" + Version: 1 Configuration: ConnectionArn: '{{ service.repository_connection_arn }}' FullRepositoryId: '{{ service.repository_id }}' @@ -580,19 +433,15 @@ Resources: Category: Build Owner: AWS Provider: CodeBuild - Version: "1" + Version: 1 Configuration: - ProjectName: - Ref: BuildProject + ProjectName: !Ref BuildProject InputArtifacts: - Name: Artifact_Source_Checkout Name: Build OutputArtifacts: - Name: BuildOutput - RoleArn: - Fn::GetAtt: - - PipelineBuildCodePipelineActionRole - - Arn + RoleArn: !GetAtt PipelineBuildCodePipelineActionRole.Arn RunOrder: 1 Name: Build {%- for service_instance in service_instances %} - Actions: @@ -600,29 +449,21 @@ Resources: Category: Build Owner: AWS Provider: CodeBuild - Version: "1" + Version: 1 Configuration: - ProjectName: - Ref: Deploy{{loop.index}}Project + ProjectName: !Ref Deploy{{loop.index}}Project InputArtifacts: - Name: BuildOutput Name: Deploy - RoleArn: - Fn::GetAtt: - - PipelineDeployCodePipelineActionRole - - Arn + RoleArn: !GetAtt PipelineDeployCodePipelineActionRole.Arn RunOrder: 1 Name: 'Deploy{{service_instance.name}}' {%- endfor %} ArtifactStore: EncryptionKey: - Id: - Fn::GetAtt: - - PipelineArtifactsBucketEncryptionKey - - Arn + Id: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn Type: KMS - Location: - Ref: PipelineArtifactsBucket + Location: !Ref PipelineArtifactsBucket Type: S3 DependsOn: - PipelineRoleDefaultPolicy @@ -635,15 +476,8 @@ Resources: - Action: sts:AssumeRole Effect: Allow Principal: - AWS: - Fn::Join: - - "" - - - "arn:" - - Ref: AWS::Partition - - ":iam::" - - Ref: AWS::AccountId - - :root - Version: "2012-10-17" + AWS: !Sub 'arn:${AWS::Partition}:iam::${AWS::AccountId}:root' + Version: '2012-10-17' PipelineBuildCodePipelineActionRoleDefaultPolicy: Type: AWS::IAM::Policy Properties: @@ -654,14 +488,10 @@ Resources: - codebuild:StartBuild - codebuild:StopBuild Effect: Allow - Resource: - Fn::GetAtt: - - BuildProject - - Arn - Version: "2012-10-17" + Resource: !GetAtt BuildProject.Arn + Version: '2012-10-17' PolicyName: PipelineBuildCodePipelineActionRoleDefaultPolicy - Roles: - - Ref: PipelineBuildCodePipelineActionRole + Roles: !Ref PipelineBuildCodePipelineActionRole PipelineDeployCodePipelineActionRole: Type: AWS::IAM::Role Properties: @@ -670,15 +500,8 @@ Resources: - Action: sts:AssumeRole Effect: Allow Principal: - AWS: - Fn::Join: - - "" - - - "arn:" - - Ref: AWS::Partition - - ":iam::" - - Ref: AWS::AccountId - - :root - Version: "2012-10-17" + AWS: !Sub 'arn:${AWS::Partition}:iam::${AWS::AccountId}:root' + Version: '2012-10-17' PipelineDeployCodePipelineActionRoleDefaultPolicy: Type: AWS::IAM::Policy Properties: @@ -689,21 +512,11 @@ Resources: - codebuild:StartBuild - codebuild:StopBuild Effect: Allow - Resource: - Fn::Join: - - "" - - - "arn:" - - Ref: AWS::Partition - - ":codebuild:" - - Ref: AWS::Region - - ":" - - Ref: AWS::AccountId - - ":project/Deploy*" - Version: "2012-10-17" + Resource: !Sub 'arn:${AWS::Partition}:codebuild:${AWS::Region}:${AWS::AccountId}:project/Deploy*' + Version: '2012-10-17' PolicyName: PipelineDeployCodePipelineActionRoleDefaultPolicy - Roles: - - Ref: PipelineDeployCodePipelineActionRole + Roles: !Ref PipelineDeployCodePipelineActionRole Outputs: PipelineEndpoint: Description: The URL to access the pipeline - Value: !Sub "https://${AWS::Region}.console.aws.amazon.com/codesuite/codepipeline/pipelines/${Pipeline}/view?region=${AWS::Region}" + Value: !Sub 'https://${AWS::Region}.console.aws.amazon.com/codesuite/codepipeline/pipelines/${Pipeline}/view?region=${AWS::Region}' diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/schema/schema.yaml b/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/schema/schema.yaml index f546157..6b3f7a1 100644 --- a/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/schema/schema.yaml +++ b/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/schema/schema.yaml @@ -28,7 +28,6 @@ schema: image: type: string description: "The name/url of the container image" - default: "public.ecr.aws/z9d2n7e1/nginx:1.21.0" minLength: 1 maxLength: 200 service_discovery_name: @@ -37,6 +36,7 @@ schema: minLength: 3 maxLength: 24 required: + - image - service_discovery_name PipelineInputs: From b12038d64a6475d65095a42fa6db441018d712f1 Mon Sep 17 00:00:00 2001 From: Carlos Santos Date: Thu, 24 Mar 2022 12:45:20 -0700 Subject: [PATCH 03/20] style: Using yaml for build project specs --- .../cloudformation.yaml | 107 +++++++----------- .../cloudformation.yaml | 107 +++++++----------- 2 files changed, 82 insertions(+), 132 deletions(-) diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/pipeline_infrastructure/cloudformation.yaml b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/pipeline_infrastructure/cloudformation.yaml index 3594f88..1440052 100644 --- a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/pipeline_infrastructure/cloudformation.yaml +++ b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/pipeline_infrastructure/cloudformation.yaml @@ -39,59 +39,39 @@ Resources: Value: '{{service.name}}' ServiceRole: !GetAtt PublishRole.Arn Source: - BuildSpec: - Fn::Join: - - "" - - - >- - { - "version": "0.2", - "phases": { - "install": { - "runtime-versions": { - "docker": 18 - }, - "commands": [ - "pip3 install --upgrade --user awscli", - "echo 'f6bd1536a743ab170b35c94ed4c7c4479763356bd543af5d391122f4af852460 yq_linux_amd64' > yq_linux_amd64.sha", - "wget https://github.com/mikefarah/yq/releases/download/3.4.0/yq_linux_amd64", - "sha256sum -c yq_linux_amd64.sha", - "mv yq_linux_amd64 /usr/bin/yq", - "chmod +x /usr/bin/yq" - ] - }, - "pre_build": { - "commands": [ - "cd $CODEBUILD_SRC_DIR", - "$(aws ecr get-login --no-include-email --region $AWS_DEFAULT_REGION)", - "{{ pipeline.inputs.unit_test_command }}", - ] - }, - "build": { - "commands": [ - "IMAGE_REPO_NAME=$repo_name", - "IMAGE_TAG=$CODEBUILD_BUILD_NUMBER", - "IMAGE_ID= - - Ref: AWS::AccountId - - >- - .dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG", - "docker build -t $IMAGE_REPO_NAME:$IMAGE_TAG -f {{ pipeline.inputs.dockerfile }} .", - "docker tag $IMAGE_REPO_NAME:$IMAGE_TAG $IMAGE_ID;", - "docker push $IMAGE_ID" - ] - }, - "post_build": { - "commands": [ - "aws proton --region $AWS_DEFAULT_REGION get-service --name $service_name | jq -r .service.spec > service.yaml", - "yq w service.yaml 'instances[*].spec.image' \"$IMAGE_ID\" > rendered_service.yaml" - ] - } - }, - "artifacts": { - "files": [ - "rendered_service.yaml" - ] - } - } + BuildSpec: !Sub | + version: "0.2" + phases: + install: + runtime-versions: + docker: 18 + commands: + - pip3 install --upgrade --user awscli + - echo 'f6bd1536a743ab170b35c94ed4c7c4479763356bd543af5d391122f4af852460 yq_linux_amd64' > yq_linux_amd64.sha + - wget https://github.com/mikefarah/yq/releases/download/3.4.0/yq_linux_amd64 + - sha256sum -c yq_linux_amd64.sha + - mv yq_linux_amd64 /usr/bin/yq + - chmod +x /usr/bin/yq + pre_build: + commands: + - cd $CODEBUILD_SRC_DIR + - $(aws ecr get-login --no-include-email --region $AWS_DEFAULT_REGION) + - {{ pipeline.inputs.unit_test_command }} + build: + commands: + - IMAGE_REPO_NAME=$repo_name + - IMAGE_TAG=$CODEBUILD_BUILD_NUMBER + - IMAGE_ID=${AWS::AccountId}.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG + - docker build -t $IMAGE_REPO_NAME:$IMAGE_TAG -f {{ pipeline.inputs.dockerfile }} . + - docker tag $IMAGE_REPO_NAME:$IMAGE_TAG $IMAGE_ID; + - docker push $IMAGE_ID + post_build: + commands: + - aws proton --region $AWS_DEFAULT_REGION get-service --name $service_name | jq -r .service.spec > service.yaml + - yq w service.yaml 'instances[*].spec.image' "$IMAGE_ID" > rendered_service.yaml + artifacts: + files: + - rendered_service.yaml Type: CODEPIPELINE EncryptionKey: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn {% for service_instance in service_instances %} @@ -114,19 +94,14 @@ Resources: Value: '{{service_instance.name}}' ServiceRole: !GetAtt DeploymentRole.Arn Source: - BuildSpec: >- - { - "version": "0.2", - "phases": { - "build": { - "commands": [ - "pip3 install --upgrade --user awscli", - "aws proton --region $AWS_DEFAULT_REGION update-service-instance --deployment-type CURRENT_VERSION --name $service_instance_name --service-name $service_name --spec file://rendered_service.yaml", - "aws proton --region $AWS_DEFAULT_REGION wait service-instance-deployed --name $service_instance_name --service-name $service_name" - ] - } - } - } + BuildSpec: | + version: "0.2" + phases: + build: + commands: + - pip3 install --upgrade --user awscli + - aws proton --region $AWS_DEFAULT_REGION update-service-instance --deployment-type CURRENT_VERSION --name $service_instance_name --service-name $service_name --spec file://rendered_service.yaml + - aws proton --region $AWS_DEFAULT_REGION wait service-instance-deployed --name $service_instance_name --service-name $service_name Type: CODEPIPELINE EncryptionKey: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn {% endfor %} diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/pipeline_infrastructure/cloudformation.yaml b/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/pipeline_infrastructure/cloudformation.yaml index 24e897e..6fc6f5c 100644 --- a/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/pipeline_infrastructure/cloudformation.yaml +++ b/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/pipeline_infrastructure/cloudformation.yaml @@ -38,59 +38,39 @@ Resources: Value: '{{service.name}}' ServiceRole: !GetAtt PublishRole.Arn Source: - BuildSpec: - Fn::Join: - - "" - - - >- - { - "version": "0.2", - "phases": { - "install": { - "runtime-versions": { - "docker": 18 - }, - "commands": [ - "pip3 install --upgrade --user awscli", - "echo 'f6bd1536a743ab170b35c94ed4c7c4479763356bd543af5d391122f4af852460 yq_linux_amd64' > yq_linux_amd64.sha", - "wget https://github.com/mikefarah/yq/releases/download/3.4.0/yq_linux_amd64", - "sha256sum -c yq_linux_amd64.sha", - "mv yq_linux_amd64 /usr/bin/yq", - "chmod +x /usr/bin/yq" - ] - }, - "pre_build": { - "commands": [ - "cd $CODEBUILD_SRC_DIR", - "$(aws ecr get-login --no-include-email --region $AWS_DEFAULT_REGION)", - "{{ pipeline.inputs.unit_test_command }}", - ] - }, - "build": { - "commands": [ - "IMAGE_REPO_NAME=$repo_name", - "IMAGE_TAG=$CODEBUILD_BUILD_NUMBER", - "IMAGE_ID= - - Ref: AWS::AccountId - - >- - .dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG", - "docker build -t $IMAGE_REPO_NAME:$IMAGE_TAG -f {{ pipeline.inputs.dockerfile }} .", - "docker tag $IMAGE_REPO_NAME:$IMAGE_TAG $IMAGE_ID;", - "docker push $IMAGE_ID" - ] - }, - "post_build": { - "commands": [ - "aws proton --region $AWS_DEFAULT_REGION get-service --name $service_name | jq -r .service.spec > service.yaml", - "yq w service.yaml 'instances[*].spec.image' \"$IMAGE_ID\" > rendered_service.yaml" - ] - } - }, - "artifacts": { - "files": [ - "rendered_service.yaml" - ] - } - } + BuildSpec: !Sub | + version: "0.2" + phases: + install: + runtime-versions: + docker: 18 + commands: + - pip3 install --upgrade --user awscli + - echo 'f6bd1536a743ab170b35c94ed4c7c4479763356bd543af5d391122f4af852460 yq_linux_amd64' > yq_linux_amd64.sha + - wget https://github.com/mikefarah/yq/releases/download/3.4.0/yq_linux_amd64 + - sha256sum -c yq_linux_amd64.sha + - mv yq_linux_amd64 /usr/bin/yq + - chmod +x /usr/bin/yq + pre_build: + commands: + - cd $CODEBUILD_SRC_DIR + - $(aws ecr get-login --no-include-email --region $AWS_DEFAULT_REGION) + - {{ pipeline.inputs.unit_test_command }} + build: + commands: + - IMAGE_REPO_NAME=$repo_name + - IMAGE_TAG=$CODEBUILD_BUILD_NUMBER + - IMAGE_ID=${AWS::AccountId}.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG + - docker build -t $IMAGE_REPO_NAME:$IMAGE_TAG -f {{ pipeline.inputs.dockerfile }} . + - docker tag $IMAGE_REPO_NAME:$IMAGE_TAG $IMAGE_ID; + - docker push $IMAGE_ID + post_build: + commands: + - aws proton --region $AWS_DEFAULT_REGION get-service --name $service_name | jq -r .service.spec > service.yaml + - yq w service.yaml 'instances[*].spec.image' "$IMAGE_ID" > rendered_service.yaml + artifacts: + files: + - rendered_service.yaml Type: CODEPIPELINE EncryptionKey: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn {% for service_instance in service_instances %} @@ -113,19 +93,14 @@ Resources: Value: '{{service_instance.name}}' ServiceRole: !GetAtt DeploymentRole.Arn Source: - BuildSpec: >- - { - "version": "0.2", - "phases": { - "build": { - "commands": [ - "pip3 install --upgrade --user awscli", - "aws proton --region $AWS_DEFAULT_REGION update-service-instance --deployment-type CURRENT_VERSION --name $service_instance_name --service-name $service_name --spec file://rendered_service.yaml", - "aws proton --region $AWS_DEFAULT_REGION wait service-instance-deployed --name $service_instance_name --service-name $service_name" - ] - } - } - } + BuildSpec: | + version: "0.2" + phases: + build: + commands: + - pip3 install --upgrade --user awscli + - aws proton --region $AWS_DEFAULT_REGION update-service-instance --deployment-type CURRENT_VERSION --name $service_instance_name --service-name $service_name --spec file://rendered_service.yaml + - aws proton --region $AWS_DEFAULT_REGION wait service-instance-deployed --name $service_instance_name --service-name $service_name Type: CODEPIPELINE EncryptionKey: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn {% endfor %} From 65761f57321653d416fbcb2ce9e2cd9a6705c670 Mon Sep 17 00:00:00 2001 From: Carlos Santos Date: Mon, 28 Mar 2022 07:31:49 -0700 Subject: [PATCH 04/20] fix: Corrected env template folder structure --- .../cloudformation.yaml | 0 .../manifest.yaml | 0 .../cloudformation.yaml | 718 ------------------ .../v1/pipeline_infrastructure/manifest.yaml | 5 - 4 files changed, 723 deletions(-) rename public-private-fargate-microservices-dotnetfx/microservices-env/v1/{instance_infrastructure => infrastructure}/cloudformation.yaml (100%) rename public-private-fargate-microservices-dotnetfx/microservices-env/v1/{instance_infrastructure => infrastructure}/manifest.yaml (100%) delete mode 100644 public-private-fargate-microservices-dotnetfx/microservices-env/v1/pipeline_infrastructure/cloudformation.yaml delete mode 100644 public-private-fargate-microservices-dotnetfx/microservices-env/v1/pipeline_infrastructure/manifest.yaml diff --git a/public-private-fargate-microservices-dotnetfx/microservices-env/v1/instance_infrastructure/cloudformation.yaml b/public-private-fargate-microservices-dotnetfx/microservices-env/v1/infrastructure/cloudformation.yaml similarity index 100% rename from public-private-fargate-microservices-dotnetfx/microservices-env/v1/instance_infrastructure/cloudformation.yaml rename to public-private-fargate-microservices-dotnetfx/microservices-env/v1/infrastructure/cloudformation.yaml diff --git a/public-private-fargate-microservices-dotnetfx/microservices-env/v1/instance_infrastructure/manifest.yaml b/public-private-fargate-microservices-dotnetfx/microservices-env/v1/infrastructure/manifest.yaml similarity index 100% rename from public-private-fargate-microservices-dotnetfx/microservices-env/v1/instance_infrastructure/manifest.yaml rename to public-private-fargate-microservices-dotnetfx/microservices-env/v1/infrastructure/manifest.yaml diff --git a/public-private-fargate-microservices-dotnetfx/microservices-env/v1/pipeline_infrastructure/cloudformation.yaml b/public-private-fargate-microservices-dotnetfx/microservices-env/v1/pipeline_infrastructure/cloudformation.yaml deleted file mode 100644 index aa0289a..0000000 --- a/public-private-fargate-microservices-dotnetfx/microservices-env/v1/pipeline_infrastructure/cloudformation.yaml +++ /dev/null @@ -1,718 +0,0 @@ -Resources: - FunctionBucket: - Type: AWS::S3::Bucket - DeletionPolicy: Retain - Properties: - VersioningConfiguration: - Status: Enabled - BucketEncryption: - ServerSideEncryptionConfiguration: - - ServerSideEncryptionByDefault: - SSEAlgorithm: 'AES256' - # This policy allows environment accounts to get the build artifacts from FunctionBucket in the management account - FunctionBucketPolicy: - Type: AWS::S3::BucketPolicy - Properties: - Bucket: !Ref FunctionBucket - PolicyDocument: - Version: 2012-10-17 - Statement: - - Action: - - 's3:GetObject' - Effect: Allow - Resource: !Join - - '' - - - 'arn:aws:s3:::' - - !Ref FunctionBucket - - /* - Principal: - AWS: - {% for service_instance in service_instances %} - - "arn:aws:iam::{{service_instance.environment.account_id}}:root" - {% endfor %} - BuildProject: - Type: AWS::CodeBuild::Project - Properties: - Artifacts: - Type: CODEPIPELINE - Environment: - ComputeType: BUILD_GENERAL1_SMALL - Image: aws/codebuild/amazonlinux2-x86_64-standard:3.0 - PrivilegedMode: true - Type: LINUX_CONTAINER - EnvironmentVariables: - - Name: bucket_name - Type: PLAINTEXT - Value: !Ref FunctionBucket - - Name: service_name - Type: PLAINTEXT - Value: '{{service.name}}' - ServiceRole: - Fn::GetAtt: - - PublishRole - - Arn - Source: - BuildSpec: >- - { - "version": "0.2", - "phases": { - "install": { - "runtime-versions": {{ - {"ruby2.7": {"ruby": "2.7"}, - "go1.x": {"golang": "1.x"}, - "nodejs12.x": {"nodejs": "12.x"}, - "python3.8": {"python": "3.8"}, - "java11": {"java": "openjdk11.x"}, - "dotnetcore3.1": {"dotnet": "3.1"} - }[service_instances[0].outputs.LambdaRuntime] | tojson | safe }}, - "commands": [ - "pip3 install --upgrade --user awscli", - "echo 'f6bd1536a743ab170b35c94ed4c7c4479763356bd543af5d391122f4af852460 yq_linux_amd64' > yq_linux_amd64.sha", - "wget https://github.com/mikefarah/yq/releases/download/3.4.0/yq_linux_amd64", - "sha256sum -c yq_linux_amd64.sha", - "mv yq_linux_amd64 /usr/bin/yq", - "chmod +x /usr/bin/yq" - ] - }, - "pre_build": { - "commands": [ - "cd $CODEBUILD_SRC_DIR", - "{{ pipeline.inputs.unit_test_command }}" - ] - }, - "build": { - "commands": [ - "{{ pipeline.inputs.packaging_command }}", - "FUNCTION_URI=s3://$bucket_name/$CODEBUILD_BUILD_NUMBER/function.zip", - "aws s3 cp function.zip $FUNCTION_URI" - ] - }, - "post_build": { - "commands": [ - "aws proton --region $AWS_DEFAULT_REGION get-service --name $service_name | jq -r .service.spec > service.yaml", - "yq w service.yaml 'instances[*].spec.code_uri' \"$FUNCTION_URI\" > rendered_service.yaml" - ] - } - }, - "artifacts": { - "files": [ - "rendered_service.yaml" - ] - } - } - Type: CODEPIPELINE - EncryptionKey: - Fn::GetAtt: - - PipelineArtifactsBucketEncryptionKey - - Arn -{% for service_instance in service_instances %} - Deploy{{loop.index}}Project: - Type: AWS::CodeBuild::Project - Properties: - Artifacts: - Type: CODEPIPELINE - Environment: - ComputeType: BUILD_GENERAL1_SMALL - Image: aws/codebuild/amazonlinux2-x86_64-standard:3.0 - PrivilegedMode: false - Type: LINUX_CONTAINER - EnvironmentVariables: - - Name: service_name - Type: PLAINTEXT - Value: '{{service.name}}' - - Name: service_instance_name - Type: PLAINTEXT - Value: '{{service_instance.name}}' - ServiceRole: - Fn::GetAtt: - - DeploymentRole - - Arn - Source: - BuildSpec: >- - { - "version": "0.2", - "phases": { - "build": { - "commands": [ - "pip3 install --upgrade --user awscli", - "aws proton --region $AWS_DEFAULT_REGION update-service-instance --deployment-type CURRENT_VERSION --name $service_instance_name --service-name $service_name --spec file://rendered_service.yaml", - "aws proton --region $AWS_DEFAULT_REGION wait service-instance-deployed --name $service_instance_name --service-name $service_name" - ] - } - } - } - Type: CODEPIPELINE - EncryptionKey: - Fn::GetAtt: - - PipelineArtifactsBucketEncryptionKey - - Arn -{% endfor %} - # This role is used to build and publish the lambda function to S3 - PublishRole: - Type: AWS::IAM::Role - Properties: - AssumeRolePolicyDocument: - Statement: - - Action: sts:AssumeRole - Effect: Allow - Principal: - Service: codebuild.amazonaws.com - Version: "2012-10-17" - PublishRoleDefaultPolicy: - Type: AWS::IAM::Policy - Properties: - PolicyDocument: - Statement: - - Action: - - logs:CreateLogGroup - - logs:CreateLogStream - - logs:PutLogEvents - Effect: Allow - Resource: - - Fn::Join: - - "" - - - "arn:" - - Ref: AWS::Partition - - ":logs:" - - Ref: AWS::Region - - ":" - - Ref: AWS::AccountId - - :log-group:/aws/codebuild/ - - Ref: BuildProject - - Fn::Join: - - "" - - - "arn:" - - Ref: AWS::Partition - - ":logs:" - - Ref: AWS::Region - - ":" - - Ref: AWS::AccountId - - :log-group:/aws/codebuild/ - - Ref: BuildProject - - :* - - Action: - - codebuild:CreateReportGroup - - codebuild:CreateReport - - codebuild:UpdateReport - - codebuild:BatchPutTestCases - Effect: Allow - Resource: - Fn::Join: - - "" - - - "arn:" - - Ref: AWS::Partition - - ":codebuild:" - - Ref: AWS::Region - - ":" - - Ref: AWS::AccountId - - :report-group/ - - Ref: BuildProject - - -* - - Action: - - proton:GetService - Effect: Allow - Resource: "*" - - Action: - - s3:GetObject* - - s3:GetBucket* - - s3:List* - - s3:DeleteObject* - - s3:PutObject* - - s3:Abort* - - s3:CreateMultipartUpload - Effect: Allow - Resource: - - Fn::GetAtt: - - FunctionBucket - - Arn - - Fn::Join: - - "" - - - Fn::GetAtt: - - FunctionBucket - - Arn - - /* - - Action: - - s3:GetObject* - - s3:GetBucket* - - s3:List* - - s3:DeleteObject* - - s3:PutObject* - - s3:Abort* - Effect: Allow - Resource: - - Fn::GetAtt: - - PipelineArtifactsBucket - - Arn - - Fn::Join: - - "" - - - Fn::GetAtt: - - PipelineArtifactsBucket - - Arn - - /* - - Action: - - kms:Decrypt - - kms:DescribeKey - - kms:Encrypt - - kms:ReEncrypt* - - kms:GenerateDataKey* - Effect: Allow - Resource: - Fn::GetAtt: - - PipelineArtifactsBucketEncryptionKey - - Arn - - Action: - - kms:Decrypt - - kms:Encrypt - - kms:ReEncrypt* - - kms:GenerateDataKey* - Effect: Allow - Resource: - Fn::GetAtt: - - PipelineArtifactsBucketEncryptionKey - - Arn - Version: "2012-10-17" - PolicyName: PublishRoleDefaultPolicy - Roles: - - Ref: PublishRole - - DeploymentRole: - Type: AWS::IAM::Role - Properties: - AssumeRolePolicyDocument: - Statement: - - Action: sts:AssumeRole - Effect: Allow - Principal: - Service: codebuild.amazonaws.com - Version: "2012-10-17" - DeploymentRoleDefaultPolicy: - Type: AWS::IAM::Policy - Properties: - PolicyDocument: - Statement: - - Action: - - logs:CreateLogGroup - - logs:CreateLogStream - - logs:PutLogEvents - Effect: Allow - Resource: - - Fn::Join: - - "" - - - "arn:" - - Ref: AWS::Partition - - ":logs:" - - Ref: AWS::Region - - ":" - - Ref: AWS::AccountId - - :log-group:/aws/codebuild/Deploy*Project* - - Fn::Join: - - "" - - - "arn:" - - Ref: AWS::Partition - - ":logs:" - - Ref: AWS::Region - - ":" - - Ref: AWS::AccountId - - :log-group:/aws/codebuild/Deploy*Project:* - - Action: - - codebuild:CreateReportGroup - - codebuild:CreateReport - - codebuild:UpdateReport - - codebuild:BatchPutTestCases - Effect: Allow - Resource: - Fn::Join: - - "" - - - "arn:" - - Ref: AWS::Partition - - ":codebuild:" - - Ref: AWS::Region - - ":" - - Ref: AWS::AccountId - - :report-group/Deploy*Project - - -* - - Action: - - proton:UpdateServiceInstance - - proton:GetServiceInstance - Effect: Allow - Resource: "*" - - Action: - - s3:GetObject* - - s3:GetBucket* - - s3:List* - Effect: Allow - Resource: - - Fn::GetAtt: - - PipelineArtifactsBucket - - Arn - - Fn::Join: - - "" - - - Fn::GetAtt: - - PipelineArtifactsBucket - - Arn - - /* - - Action: - - kms:Decrypt - - kms:DescribeKey - Effect: Allow - Resource: - Fn::GetAtt: - - PipelineArtifactsBucketEncryptionKey - - Arn - - Action: - - kms:Decrypt - - kms:Encrypt - - kms:ReEncrypt* - - kms:GenerateDataKey* - Effect: Allow - Resource: - Fn::GetAtt: - - PipelineArtifactsBucketEncryptionKey - - Arn - Version: "2012-10-17" - PolicyName: DeploymentRoleDefaultPolicy - Roles: - - Ref: DeploymentRole - PipelineArtifactsBucketEncryptionKey: - Type: AWS::KMS::Key - Properties: - KeyPolicy: - Statement: - - Action: - - kms:Create* - - kms:Describe* - - kms:Enable* - - kms:List* - - kms:Put* - - kms:Update* - - kms:Revoke* - - kms:Disable* - - kms:Get* - - kms:Delete* - - kms:ScheduleKeyDeletion - - kms:CancelKeyDeletion - - kms:GenerateDataKey - - kms:TagResource - - kms:UntagResource - Effect: Allow - Principal: - AWS: - Fn::Join: - - "" - - - "arn:" - - Ref: AWS::Partition - - ":iam::" - - Ref: AWS::AccountId - - :root - Resource: "*" - - Action: - - kms:Decrypt - - kms:DescribeKey - - kms:Encrypt - - kms:ReEncrypt* - - kms:GenerateDataKey* - Effect: Allow - Principal: - AWS: - Fn::GetAtt: - - PipelineRole - - Arn - Resource: "*" - - Action: - - kms:Decrypt - - kms:DescribeKey - - kms:Encrypt - - kms:ReEncrypt* - - kms:GenerateDataKey* - Effect: Allow - Principal: - AWS: - Fn::GetAtt: - - PublishRole - - Arn - Resource: "*" - - Action: - - kms:Decrypt - - kms:Encrypt - - kms:ReEncrypt* - - kms:GenerateDataKey* - Effect: Allow - Principal: - AWS: - Fn::GetAtt: - - PublishRole - - Arn - Resource: "*" - - Action: - - kms:Decrypt - - kms:DescribeKey - Effect: Allow - Principal: - AWS: - Fn::GetAtt: - - DeploymentRole - - Arn - Resource: "*" - - Action: - - kms:Decrypt - - kms:Encrypt - - kms:ReEncrypt* - - kms:GenerateDataKey* - Effect: Allow - Principal: - AWS: - Fn::GetAtt: - - DeploymentRole - - Arn - Resource: "*" - Version: "2012-10-17" - UpdateReplacePolicy: Delete - DeletionPolicy: Delete - PipelineArtifactsBucket: - Type: AWS::S3::Bucket - Properties: - VersioningConfiguration: - Status: Enabled - BucketEncryption: - ServerSideEncryptionConfiguration: - - ServerSideEncryptionByDefault: - KMSMasterKeyID: - Fn::GetAtt: - - PipelineArtifactsBucketEncryptionKey - - Arn - SSEAlgorithm: aws:kms - PublicAccessBlockConfiguration: - BlockPublicAcls: true - BlockPublicPolicy: true - IgnorePublicAcls: true - RestrictPublicBuckets: true - UpdateReplacePolicy: Retain - DeletionPolicy: Retain - PipelineArtifactsBucketEncryptionKeyAlias: - Type: AWS::KMS::Alias - Properties: - AliasName: 'alias/codepipeline-encryption-key-{{ service.name }}' - TargetKeyId: - Fn::GetAtt: - - PipelineArtifactsBucketEncryptionKey - - Arn - UpdateReplacePolicy: Delete - DeletionPolicy: Delete - PipelineRole: - Type: AWS::IAM::Role - Properties: - AssumeRolePolicyDocument: - Statement: - - Action: sts:AssumeRole - Effect: Allow - Principal: - Service: codepipeline.amazonaws.com - Version: "2012-10-17" - PipelineRoleDefaultPolicy: - Type: AWS::IAM::Policy - Properties: - PolicyDocument: - Statement: - - Action: - - s3:GetObject* - - s3:GetBucket* - - s3:List* - - s3:DeleteObject* - - s3:PutObject* - - s3:Abort* - Effect: Allow - Resource: - - Fn::GetAtt: - - PipelineArtifactsBucket - - Arn - - Fn::Join: - - "" - - - Fn::GetAtt: - - PipelineArtifactsBucket - - Arn - - /* - - Action: - - kms:Decrypt - - kms:DescribeKey - - kms:Encrypt - - kms:ReEncrypt* - - kms:GenerateDataKey* - Effect: Allow - Resource: - Fn::GetAtt: - - PipelineArtifactsBucketEncryptionKey - - Arn - - Action: codestar-connections:* - Effect: Allow - Resource: "*" - - Action: sts:AssumeRole - Effect: Allow - Resource: - Fn::GetAtt: - - PipelineBuildCodePipelineActionRole - - Arn - - Action: sts:AssumeRole - Effect: Allow - Resource: - Fn::GetAtt: - - PipelineDeployCodePipelineActionRole - - Arn - Version: "2012-10-17" - PolicyName: PipelineRoleDefaultPolicy - Roles: - - Ref: PipelineRole - Pipeline: - Type: AWS::CodePipeline::Pipeline - Properties: - RoleArn: - Fn::GetAtt: - - PipelineRole - - Arn - Stages: - - Actions: - - ActionTypeId: - Category: Source - Owner: AWS - Provider: CodeStarSourceConnection - Version: "1" - Configuration: - ConnectionArn: '{{ service.repository_connection_arn }}' - FullRepositoryId: '{{ service.repository_id }}' - BranchName: '{{ service.branch_name }}' - Name: Checkout - OutputArtifacts: - - Name: Artifact_Source_Checkout - RunOrder: 1 - Name: Source - - Actions: - - ActionTypeId: - Category: Build - Owner: AWS - Provider: CodeBuild - Version: "1" - Configuration: - ProjectName: - Ref: BuildProject - InputArtifacts: - - Name: Artifact_Source_Checkout - Name: Build - OutputArtifacts: - - Name: BuildOutput - RoleArn: - Fn::GetAtt: - - PipelineBuildCodePipelineActionRole - - Arn - RunOrder: 1 - Name: Build {%- for service_instance in service_instances %} - - Actions: - - ActionTypeId: - Category: Build - Owner: AWS - Provider: CodeBuild - Version: "1" - Configuration: - ProjectName: - Ref: Deploy{{loop.index}}Project - InputArtifacts: - - Name: BuildOutput - Name: Deploy - RoleArn: - Fn::GetAtt: - - PipelineDeployCodePipelineActionRole - - Arn - RunOrder: 1 - Name: 'Deploy{{service_instance.name}}' -{%- endfor %} - ArtifactStore: - EncryptionKey: - Id: - Fn::GetAtt: - - PipelineArtifactsBucketEncryptionKey - - Arn - Type: KMS - Location: - Ref: PipelineArtifactsBucket - Type: S3 - DependsOn: - - PipelineRoleDefaultPolicy - - PipelineRole - PipelineBuildCodePipelineActionRole: - Type: AWS::IAM::Role - Properties: - AssumeRolePolicyDocument: - Statement: - - Action: sts:AssumeRole - Effect: Allow - Principal: - AWS: - Fn::Join: - - "" - - - "arn:" - - Ref: AWS::Partition - - ":iam::" - - Ref: AWS::AccountId - - :root - Version: "2012-10-17" - PipelineBuildCodePipelineActionRoleDefaultPolicy: - Type: AWS::IAM::Policy - Properties: - PolicyDocument: - Statement: - - Action: - - codebuild:BatchGetBuilds - - codebuild:StartBuild - - codebuild:StopBuild - Effect: Allow - Resource: - Fn::GetAtt: - - BuildProject - - Arn - Version: "2012-10-17" - PolicyName: PipelineBuildCodePipelineActionRoleDefaultPolicy - Roles: - - Ref: PipelineBuildCodePipelineActionRole - PipelineDeployCodePipelineActionRole: - Type: AWS::IAM::Role - Properties: - AssumeRolePolicyDocument: - Statement: - - Action: sts:AssumeRole - Effect: Allow - Principal: - AWS: - Fn::Join: - - "" - - - "arn:" - - Ref: AWS::Partition - - ":iam::" - - Ref: AWS::AccountId - - :root - Version: "2012-10-17" - PipelineDeployCodePipelineActionRoleDefaultPolicy: - Type: AWS::IAM::Policy - Properties: - PolicyDocument: - Statement: - - Action: - - codebuild:BatchGetBuilds - - codebuild:StartBuild - - codebuild:StopBuild - Effect: Allow - Resource: - Fn::Join: - - "" - - - "arn:" - - Ref: AWS::Partition - - ":codebuild:" - - Ref: AWS::Region - - ":" - - Ref: AWS::AccountId - - ":project/Deploy*" - Version: "2012-10-17" - PolicyName: PipelineDeployCodePipelineActionRoleDefaultPolicy - Roles: - - Ref: PipelineDeployCodePipelineActionRole -Outputs: - PipelineEndpoint: - Description: The URL to access the pipeline - Value: !Sub "https://${AWS::Region}.console.aws.amazon.com/codesuite/codepipeline/pipelines/${Pipeline}/view?region=${AWS::Region}" diff --git a/public-private-fargate-microservices-dotnetfx/microservices-env/v1/pipeline_infrastructure/manifest.yaml b/public-private-fargate-microservices-dotnetfx/microservices-env/v1/pipeline_infrastructure/manifest.yaml deleted file mode 100644 index eed587b..0000000 --- a/public-private-fargate-microservices-dotnetfx/microservices-env/v1/pipeline_infrastructure/manifest.yaml +++ /dev/null @@ -1,5 +0,0 @@ -infrastructure: - templates: - - file: "cloudformation.yaml" - rendering_engine: jinja - template_language: cloudformation From 9ec8456d45bd3af355c325f2f66d24aa221b9e60 Mon Sep 17 00:00:00 2001 From: Carlos Santos Date: Mon, 28 Mar 2022 11:57:33 -0700 Subject: [PATCH 05/20] feature: Initial Windows ECS Fargate Push --- .../microservices-env/v1/.compatible-envs | 2 - .../cloudformation.yaml | 16 +- .../cloudformation.yaml | 444 ++++++++++++++++-- .../v1/schema/schema.yaml | 22 +- 4 files changed, 417 insertions(+), 67 deletions(-) delete mode 100644 public-private-fargate-microservices-dotnetfx/microservices-env/v1/.compatible-envs diff --git a/public-private-fargate-microservices-dotnetfx/microservices-env/v1/.compatible-envs b/public-private-fargate-microservices-dotnetfx/microservices-env/v1/.compatible-envs deleted file mode 100644 index 4efda05..0000000 --- a/public-private-fargate-microservices-dotnetfx/microservices-env/v1/.compatible-envs +++ /dev/null @@ -1,2 +0,0 @@ -microservices-env:1 - diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/instance_infrastructure/cloudformation.yaml b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/instance_infrastructure/cloudformation.yaml index f02c5f7..f9e99db 100644 --- a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/instance_infrastructure/cloudformation.yaml +++ b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/instance_infrastructure/cloudformation.yaml @@ -40,8 +40,7 @@ Resources: LogGroup: Type: AWS::Logs::LogGroup Properties: - #TODO: Should this include environment name? - LogGroupName: '{{service.name}}/{{service_instance.name}}' + LogGroupName: '{{environment.name}}/{{service.name}}/{{service_instance.name}}' # The task definition. This is a simple metadata description of what # container to run, and what resource requirements it has. @@ -54,6 +53,9 @@ Resources: NetworkMode: awsvpc RequiresCompatibilities: - FARGATE + RuntimePlatform: + CpuArchitecture: 'X86_64' + OperatingSystemFamily: 'WINDOWS_SERVER_2019_CORE' ExecutionRoleArn: '{{environment.outputs.ECSTaskExecutionRole}}' TaskRoleArn: !Ref 'AWS::NoValue' ContainerDefinitions: @@ -76,7 +78,6 @@ Resources: # The service_instance.inputs. The service is a resource which allows you to run multiple # copies of a type of task, and gather up their logs and metrics, as well # as monitor the number of running tasks and replace any that have crashed - # TODO: Need to sepcify Windows constraint Service: Type: AWS::ECS::Service DependsOn: LoadBalancerRule @@ -87,7 +88,7 @@ Resources: DeploymentConfiguration: MaximumPercent: 200 MinimumHealthyPercent: 75 - DesiredCount: '{{service_instance.inputs.desired_count}}' + DesiredCount: {{service_instance.inputs.desired_count}} NetworkConfiguration: AwsvpcConfiguration: AssignPublicIp: ENABLED @@ -101,7 +102,7 @@ Resources: - RegistryArn: !GetAtt DiscoveryService.Arn LoadBalancers: - ContainerName: '{{service_instance.name}}' - ContainerPort: '{{service_instance.inputs.port}}' + ContainerPort: {{service_instance.inputs.port}} TargetGroupArn: !Ref 'TargetGroup' Tags: - Key: Name @@ -249,7 +250,7 @@ Resources: Properties: Description: Ingress from the public ALB GroupId: '{{environment.outputs.ContainerSecurityGroup}}' - IpProtocol: '-1' + IpProtocol: 'tcp' SourceSecurityGroupId: !Ref 'PublicLoadBalancerSG' # Public load balancer, hosted in public subnets that is accessible @@ -264,8 +265,7 @@ Resources: SecurityGroupIngress: # Allow access to ALB from anywhere on the internet - CidrIp: 0.0.0.0/0 - #TODO: Should this be narrowed down? - IpProtocol: '-1' + IpProtocol: 'tcp' Tags: - Key: Name Value: !FindInMap ['EnvironmentNameConfig', 'Environment', 'Name'] diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/pipeline_infrastructure/cloudformation.yaml b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/pipeline_infrastructure/cloudformation.yaml index 1440052..7e3e9ab 100644 --- a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/pipeline_infrastructure/cloudformation.yaml +++ b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/pipeline_infrastructure/cloudformation.yaml @@ -1,3 +1,15 @@ +Mappings: + BuildConfig: + BuildServer: + VolumeType: '{{pipeline.inputs.build_server_volume_type}}' + VolumeSize: '{{pipeline.inputs.build_server_volume_size}}' + ImageBuild: + Dockerfile: '{{pipeline.inputs.dockerfile}}' +Parameters: + BuildServerAmiId: + Type: AWS::SSM::Parameter::Value + Description: AMI ID or SSM Parameter expression to use to retrieve the AMI ID for the build server. Must be compatible with operating system version used by ECS cluster. + Default: '{{pipeline.inputs.build_server_ami_id}}' Resources: ECRRepo: Type: AWS::ECR::Repository @@ -19,16 +31,281 @@ Resources: - ecr:BatchCheckLayerAvailability - ecr:GetDownloadUrlForLayer - ecr:BatchGetImage - # TODO: Need to change to support Windows + ContainerImageBuildServerRole: + Type : AWS::IAM::Role + Properties: + Policies: + - PolicyDocument: + Version: '2012-10-17' + Statement: + - Action: s3:GetObject + Resource: !Sub arn:${AWS::Partition}:s3:::${PipelineArtifactsBucket}/* + Effect: Allow + - Action: + - kms:Decrypt + - kms:Encrypt + - kms:ReEncrypt* + - kms:GenerateDataKey* + Effect: Allow + Resource: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn + PolicyName: s3-instance-bucket-policy + - PolicyDocument: + Version: '2012-10-17' + Statement: + - Action: + - "ecr:GetAuthorizationToken" + Resource: "*" + Effect: Allow + PolicyName: ecr-instance-policy + - PolicyDocument: + Version: '2012-10-17' + Statement: + - Action: + - "ecr:BatchCheckLayerAvailability" + - "ecr:BatchGetImage" + - "ecr:CompleteLayerUpload" + - "ecr:DescribeImages" + - "ecr:DescribeImageScanFindings" + - "ecr:DescribeRepositories" + - "ecr:GetDownloadUrlForLayer" + - "ecr:GetLifecyclePolicy" + - "ecr:GetLifecyclePolicyPreview" + - "ecr:GetRepositoryPolicy" + - "ecr:InitiateLayerUpload" + - "ecr:ListImages" + - "ecr:ListTagsForResource" + - "ecr:PutImage" + - "ecr:UploadLayerPart" + Resource: !GetAtt ECRRepo.Arn + Effect: Allow + PolicyName: ecr-resource-instance-policy + Path: / + ManagedPolicyArns: + - !Sub 'arn:${AWS::Partition}:iam::aws:policy/AmazonSSMManagedInstanceCore' + - !Sub 'arn:${AWS::Partition}:iam::aws:policy/CloudWatchAgentServerPolicy' + AssumeRolePolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: "Allow" + Principal: + Service: + - "ec2.amazonaws.com" + - "ssm.amazonaws.com" + Action: "sts:AssumeRole" + ContainerImageBuildServerInstanceProfile: + Type: "AWS::IAM::InstanceProfile" + Properties: + Roles: + - !Ref ContainerImageBuildServerRole + BuildDotNetContainerDocument: + Type: AWS::SSM::Document + Properties: + DocumentType: Automation + Content: + schemaVersion: "0.3" + description: "Create a .NET Framework Container for CodeBuild" + parameters: + AmiId: + type: String + default: !Ref BuildServerAmiId + description: The Windows Server AMI to use for the build server must match version used by ECS cluster. + DockerFile: + type: String + default: !FindInMap ['BuildConfig', 'ImageBuild', 'Dockerfile'] + description: Location of the Dockerfile relative to repository's root folder + InstanceType: + type: String + description: (Optional) The instance type of the EC2 instance to be launched. + default: !Ref BuildServerInstanceType + IamInstanceProfileName: + type: String + description: (Required) The IAM instance profile to attach to the build instance. + default: !Ref ContainerImageBuildServerInstanceProfile + InstanceVolumeSize: + type: Integer + description: (Required) Desired volume size (GiB) of the build instance. + default: !FindInMap ['BuildConfig', 'BuildServer', 'VolumeSize'] + InstanceVolumeType: + type: String + description: (Required) Desired volume type of the build instance. + default: !FindInMap ['BuildConfig', 'BuildServer', 'VolumeType'] + PipelineBucketName: + type: String + description: (Required) Bucket that build artifact is stored in. + default: !Ref PipelineArtifactsBucket + SourceArtifactS3Path: + type: String + description: (Required) Build artifact key. + EcrRepoName: + default: !Ref ECRRepo + description: "ECR Repo Name" + type: "String" + ImageTag: + type: String + description: (Optional) Tag for container image. + default: latest + BuildLogGroupName: + type: String + description: (Optional) CloudWatch Log Group Name for build. + default: !Sub '/aws/codebuild/${BuildProject}' + mainSteps: + - name: createNewInstance + action: 'aws:runInstances' + maxAttempts: 3 + timeoutSeconds: 1200 + onFailure: Abort + inputs: + ImageId: '{{ AmiId }}' + InstanceType: '{{ InstanceType }}' + MinInstanceCount: 1 + MaxInstanceCount: 1 + IamInstanceProfileName: '{{ IamInstanceProfileName }}' + BlockDeviceMappings: + - DeviceName: /dev/xvdb + Ebs: + VolumeSize: '{{ InstanceVolumeSize }}' + VolumeType: '{{ InstanceVolumeType }}' + TagSpecifications: + - ResourceType: instance + Tags: + - Key: tag:aws:cloudformation:stack-id + Value: !Ref AWS::StackId + - Key: tag:aws:cloudformation:stack-name + Value: !Ref AWS::StackName + - Key: Name + Value: dotnetfx-container-build + nextStep: getInstance + - name: getInstance + action: 'aws:executeAwsApi' + maxAttempts: 2 + onFailure: Abort + inputs: + Service: ec2 + Api: DescribeInstances + InstanceIds: + - '{{ createNewInstance.InstanceIds }}' + outputs: + - Name: InstanceId + Selector: '$.Reservations[0].Instances[0].InstanceId' + Type: String + isCritical: 'true' + nextStep: waitForInstanceToBeReady + - name: waitForInstanceToBeReady + action: 'aws:waitForAwsResourceProperty' + onFailure: 'step:terminateInstance' + timeoutSeconds: 600 + maxAttempts: 2 + inputs: + Service: ec2 + Api: DescribeInstanceStatus + InstanceIds: + - '{{ getInstance.InstanceId }}' + PropertySelector: '$.InstanceStatuses[0].InstanceStatus.Details[0].Status' + DesiredValues: + - passed + isCritical: 'false' + nextStep: waitForSSMAgentOnline + - name: waitForSSMAgentOnline + action: 'aws:waitForAwsResourceProperty' + onFailure: 'step:terminateInstance' + timeoutSeconds: 600 + inputs: + Service: ssm + Api: DescribeInstanceInformation + InstanceInformationFilterList: + - key: InstanceIds + valueSet: + - '{{ getInstance.InstanceId }}' + PropertySelector: '$.InstanceInformationList[0].PingStatus' + DesiredValues: + - Online + isCritical: 'true' + nextStep: CreateDockerImage + - name: CreateDockerImage + action: 'aws:runCommand' + onFailure: 'step:terminateInstance' + timeoutSeconds: 7200 + inputs: + DocumentName: AWS-RunPowerShellScript + InstanceIds: + - '{{ getInstance.InstanceId }}' + Parameters: + commands: | + $ErrorActionPreference = "Stop" + + Write-Host "*****Downloading from S3...*****" + + New-Item -Name tmp -ItemType directory -Force | out-null + New-Item -Name tmp\src -ItemType directory -Force | out-null + + cd .\tmp + + $tmpFolder = $(Get-Location).Path + $srcFolder = "$tmpFolder\src" + $key = "{{SourceArtifactS3Path}}" + $srcFileName = "$(Split-Path $key -Leaf)" + + Read-S3Object -BucketName "{{PipelineBucketName}}" -Key $key -File $srcFileName + Expand-Archive -Path "$tmpFolder\$srcFileName" -DestinationPath "$srcFolder" -Force + + Write-Host "*****Building Docker image...*****" + + $instanceInfo = (Invoke-RestMethod -Method Get -Uri http://169.254.169.254/latest/dynamic/instance-identity/document) + $repoUri = $instanceInfo.accountId + '.dkr.ecr.' + $instanceInfo.region + '.amazonaws.com/{{EcrRepoName}}' + $latestUri = "$($repoUri):latest" + $hasCustomTag = $False + $buildArgs = @("-t", $latestUri) + $customTag = "{{ImageTag}}" + + if ($customTag -and $($customTag -ne "latest")) { + $hasCustomTag = $True + $uriWithTag = "$($repoUri):$customTag" + $buildArgs += @("-t", $uriWithTag) + } + + Write-Host "Docker Build Args are '$buildArgs'" + + cd $srcFolder + docker build $buildArgs $srcFolder\ + + if ($LASTEXITCODE -ne 0) { + throw ("'docker build $buildArgs $srcFolder\' execution failed with exit code $LASTEXITCODE.") + } + + Write-Host "*****Pushing Docker image to ECR...*****" + + Invoke-Expression –Command (Get-ECRLoginCommand –Region $region).Command + docker push $repoUri --all-tags + + if ($LASTEXITCODE -ne 0) { + throw "'docker push $repoUri --all-tags' execution failed with exit code $LASTEXITCODE." + } + executionTimeout: '7200' + CloudWatchOutputConfig: + CloudWatchLogGroupName: '{{ BuildLogGroupName }}' + CloudWatchOutputEnabled: true + isCritical: 'true' + nextStep: terminateInstance + - name: terminateInstance + action: 'aws:changeInstanceState' + maxAttempts: 3 + onFailure: Continue + inputs: + InstanceIds: + - '{{getInstance.InstanceId}}' + DesiredState: terminated + isCritical: 'true' + isEnd: 'true' BuildProject: Type: AWS::CodeBuild::Project Properties: Artifacts: Type: CODEPIPELINE + Packaging: NONE Environment: ComputeType: BUILD_GENERAL1_SMALL Image: aws/codebuild/amazonlinux2-x86_64-standard:3.0 - PrivilegedMode: true + PrivilegedMode: false Type: LINUX_CONTAINER EnvironmentVariables: - Name: repo_name @@ -39,8 +316,15 @@ Resources: Value: '{{service.name}}' ServiceRole: !GetAtt PublishRole.Arn Source: + InsecureSsl: false BuildSpec: !Sub | version: "0.2" + env: + variables: + CONTAINER_NAME: ${TaskContainerName} + DOCUMENT_NAME: ${BuildDotNetContainerDocument} + ECR_REPO_URI: ${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/${ECRRepo} + LOG_GROUP_NAME: ${CloudWatchLogGroupName} phases: install: runtime-versions: @@ -54,27 +338,52 @@ Resources: - chmod +x /usr/bin/yq pre_build: commands: - - cd $CODEBUILD_SRC_DIR - - $(aws ecr get-login --no-include-email --region $AWS_DEFAULT_REGION) - - {{ pipeline.inputs.unit_test_command }} + - BUILD_ID=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-8) + - IMAGE_TAG=build-$BUILD_ID + - SRC_ARTIFACT_FULL_S3_PATH=${!CODEBUILD_SOURCE_VERSION#*"s3:::"} + - SRC_ARTIFACT_S3_PATH=${!SRC_ARTIFACT_FULL_S3_PATH#*"/"} + - SRC_ARTIFACT_BUCKET_NAME=$(echo $SRC_ARTIFACT_FULL_S3_PATH | cut -c 1-$((${!#SRC_ARTIFACT_FULL_S3_PATH} - ${!#SRC_ARTIFACT_S3_PATH} - 1))) + - echo SRC_ARTIFACT_FULL_S3_PATH=$SRC_ARTIFACT_FULL_S3_PATH + - echo SRC_ARTIFACT_S3_PATH=$SRC_ARTIFACT_S3_PATH + - echo SRC_ARTIFACT_BUCKET_NAME=$SRC_ARTIFACT_BUCKET_NAME build: commands: - - IMAGE_REPO_NAME=$repo_name - - IMAGE_TAG=$CODEBUILD_BUILD_NUMBER - - IMAGE_ID=${AWS::AccountId}.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG - - docker build -t $IMAGE_REPO_NAME:$IMAGE_TAG -f {{ pipeline.inputs.dockerfile }} . - - docker tag $IMAGE_REPO_NAME:$IMAGE_TAG $IMAGE_ID; - - docker push $IMAGE_ID + - echo Starting automation execution using document $DOCUMENT_NAME... + - echo Logs are stored under CloudWatch Log Group $LOG_GROUP_NAME... + - EXECUTION_ID=$(aws ssm start-automation-execution --document-name $DOCUMENT_NAME --parameters DockerFile={{ pipeline.inputs.dockerfile }},ImageTag=$IMAGE_TAG,PipelineBucketName=$SRC_ARTIFACT_BUCKET_NAME,SourceArtifactS3Path=$SRC_ARTIFACT_S3_PATH --output text) + - echo Running execution $EXECUTION_ID... + - COMMAND="aws ssm describe-automation-executions --filters Key=ExecutionId,Values=$EXECUTION_ID" + - STATUS=$($COMMAND | jq -r ".AutomationExecutionMetadataList[0].AutomationExecutionStatus") + - | + while [ $STATUS = "InProgress" ]; + do sleep 3; + STATUS=$($COMMAND | jq -r ".AutomationExecutionMetadataList[0].AutomationExecutionStatus"); + done + - | + if [ $STATUS = "Success" ]; + then echo Automation execution succeeded.; + else echo Automation execution failed. Please check CloudWatch log for details.; + ERROR_MSG=$($COMMAND | jq -r ".AutomationExecutionMetadataList[0].FailureMessage"); + echo SSM Failure Message Follows.; + echo $ERROR_MSG; + exit 1; + fi post_build: commands: - - aws proton --region $AWS_DEFAULT_REGION get-service --name $service_name | jq -r .service.spec > service.yaml - - yq w service.yaml 'instances[*].spec.image' "$IMAGE_ID" > rendered_service.yaml + - if [ $CODEBUILD_BUILD_SUCCEEDING -eq 1 ]; + - then echo Writing updated service specification file...; + - aws proton --region $AWS_DEFAULT_REGION get-service --name $service_name | jq -r .service.spec > service.yaml; + - yq w service.yaml 'instances[*].spec.image' "$IMAGE_ID" > rendered_service.yaml; + - fi artifacts: files: - rendered_service.yaml Type: CODEPIPELINE EncryptionKey: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn -{% for service_instance in service_instances %} + TimeoutInMinutes: 60 + QueuedTimeoutInMinutes: 480 + + {% for service_instance in service_instances %} Deploy{{loop.index}}Project: Type: AWS::CodeBuild::Project Properties: @@ -104,8 +413,8 @@ Resources: - aws proton --region $AWS_DEFAULT_REGION wait service-instance-deployed --name $service_instance_name --service-name $service_name Type: CODEPIPELINE EncryptionKey: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn -{% endfor %} - # This role is used to build and publish an image to ECR + {% endfor %} + # This role is used to build container image PublishRole: Type: AWS::IAM::Role Properties: @@ -121,6 +430,64 @@ Resources: Properties: PolicyDocument: Statement: + - Effect: Allow + Resource: !Sub 'arn:${AWS::Partition}:ec2:${AWS::Region}:${AWS::AccountId}:instance/*' + Action: + - 'ec2:RunInstances' + Condition: + StringEquals: + "aws:RequestTag/tag:aws:cloudformation:stack-id": !Ref AWS::StackId + - Effect: Allow + Resource: !Sub 'arn:${AWS::Partition}:ec2:${AWS::Region}:${AWS::AccountId}:instance/*' + Action: + - 'ec2:TerminateInstances' + Condition: + StringEquals: + "aws:ResourceTag/tag:aws:cloudformation:stack-id": !Ref AWS::StackId + - Effect: Allow + Resource: '*' + Action: + - 'ec2:DescribeInstances' + - 'ec2:DescribeInstanceStatus' + - 'ec2:CreateTags' + - Effect: Allow + Resource: + - !Sub 'arn:${AWS::Partition}:ec2:${AWS::Region}:${AWS::AccountId}:instance/*' + Action: + - 'ssm:SendCommand' + Condition: + StringEquals: + "aws:ResourceTag/tag:aws:cloudformation:stack-id": !Ref AWS::StackId + - Effect: Allow + Resource: + - !Sub 'arn:${AWS::Partition}:ssm:${AWS::Region}::document/AWS-RunPowerShellScript' + Action: + - 'ssm:SendCommand' + - Effect: Allow + Resource: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/${ContainerImageBuildServerRole} + Action: + - 'iam:PassRole' + - Effect: Allow + Resource: '*' + Action: + - 'ssm:CancelCommand' + - 'ssm:DescribeAutomationExecutions' + - 'ssm:DescribeInstanceInformation' + - 'ssm:ListCommands' + - 'ssm:ListCommandInvocations' + - Effect: Allow + Resource: !Sub arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:automation-execution/ + Action: + - 'ssm:StopAutomationExecution' + - 'ssm:GetAutomationExecution' + - Effect: Allow + Resource: !Sub arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:automation-definition/${BuildDotNetContainerDocument}:$DEFAULT + Action: + - 'ssm:StartAutomationExecution' + - Effect: Allow + Resource: !Sub arn:${AWS::Partition}:ssm:${AWS::Region}::parameter/aws/service/ami-windows-latest/* + Action: + - 'ssm:GetParameters' - Action: - logs:CreateLogGroup - logs:CreateLogStream @@ -137,29 +504,11 @@ Resources: Effect: Allow Resource: !Sub 'arn:${AWS::Partition}:codebuild:${AWS::Region}:${AWS::AccountId}:report-group/${BuildProject}-*' - Action: - - ecr:GetAuthorizationToken - Effect: Allow - Resource: '*' - - Action: - - ecr:BatchCheckLayerAvailability - - ecr:CompleteLayerUpload - - ecr:GetAuthorizationToken - - ecr:InitiateLayerUpload - - ecr:PutImage - - ecr:UploadLayerPart - Effect: Allow - Resource: !GetAtt ECRRepo.Arn - - Action: - - proton:GetService - Effect: Allow - Resource: '*' - - Action: - - s3:GetObject* - - s3:GetBucket* - - s3:List* - - s3:DeleteObject* - - s3:PutObject* - - s3:Abort* + - 's3:PutObject' + - 's3:GetObject' + - 's3:GetObjectVersion' + - 's3:GetBucketAcl' + - 's3:GetBucketLocation' Effect: Allow Resource: - !GetAtt PipelineArtifactsBucket.Arn @@ -172,16 +521,8 @@ Resources: - kms:GenerateDataKey* Effect: Allow Resource: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn - - Action: - - kms:Decrypt - - kms:Encrypt - - kms:ReEncrypt* - - kms:GenerateDataKey* - Effect: Allow - Resource: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn Version: '2012-10-17' - PolicyName: PublishRoleDefaultPolicy - Roles: !Ref PublishRole + Roles: [ !Ref PublishRole ] DeploymentRole: Type: AWS::IAM::Role @@ -419,7 +760,8 @@ Resources: - Name: BuildOutput RoleArn: !GetAtt PipelineBuildCodePipelineActionRole.Arn RunOrder: 1 - Name: Build {%- for service_instance in service_instances %} + Name: Build + {%- for service_instance in service_instances %} - Actions: - ActionTypeId: Category: Build @@ -433,8 +775,8 @@ Resources: Name: Deploy RoleArn: !GetAtt PipelineDeployCodePipelineActionRole.Arn RunOrder: 1 - Name: 'Deploy{{service_instance.name}}' -{%- endfor %} + Name: 'Deploy-{{service_instance.name}}' + {%- endfor %} ArtifactStore: EncryptionKey: Id: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/schema/schema.yaml b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/schema/schema.yaml index cdeb072..b2a208b 100644 --- a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/schema/schema.yaml +++ b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/schema/schema.yaml @@ -43,15 +43,25 @@ schema: type: object description: "Pipeline input properties" properties: + build_server_ami_id: + type: string + description: AMI ID or SSM Parameter expression to use to retrieve the AMI ID for the build server. Must be compatible with operating system version used by ECS cluster. + default: /aws/service/ami-windows-latest/Windows_Server-2019-English-Core-ECS_Optimized/image_id + build_server_instance_type: + default: t2.medium + enum: [t2.small, t2.medium, t2.large, + t3.small, t3.medium, t3.large, + t3a.small, t3a.medium, t3a.large ] + build_server_volume_type: + default: 30 + minimum: 4 + maximum: 1024 + build_server_volume_size: + default: gp3 + enum: [ gp3, gp2 ] dockerfile: type: string description: "The location of the Dockerfile to build" default: "Dockerfile" minLength: 1 maxLength: 100 - unit_test_command: - type: string - description: "The command to run to unit test the application code" - default: "echo 'add your unit test command here'" - minLength: 1 - maxLength: 200 \ No newline at end of file From 5c1cd93a34ac5eab780a61c5a5ce4da78024293e Mon Sep 17 00:00:00 2001 From: Carlos Santos Date: Mon, 28 Mar 2022 12:14:31 -0700 Subject: [PATCH 06/20] fix: Corrected pipeline input parameter types --- .../loadbalanced-public-svc/v1/schema/schema.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/schema/schema.yaml b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/schema/schema.yaml index b2a208b..2bef221 100644 --- a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/schema/schema.yaml +++ b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/schema/schema.yaml @@ -53,10 +53,12 @@ schema: t3.small, t3.medium, t3.large, t3a.small, t3a.medium, t3a.large ] build_server_volume_type: + type: number default: 30 minimum: 4 maximum: 1024 build_server_volume_size: + type: string default: gp3 enum: [ gp3, gp2 ] dockerfile: From eda39a71eabc80a007f40129f621d03ed98b5680 Mon Sep 17 00:00:00 2001 From: Carlos Santos Date: Mon, 28 Mar 2022 12:34:17 -0700 Subject: [PATCH 07/20] fix: Added missing parameter type for pipeline inputs --- .../loadbalanced-public-svc/v1/schema/schema.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/schema/schema.yaml b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/schema/schema.yaml index 2bef221..bec28b9 100644 --- a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/schema/schema.yaml +++ b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/schema/schema.yaml @@ -48,6 +48,7 @@ schema: description: AMI ID or SSM Parameter expression to use to retrieve the AMI ID for the build server. Must be compatible with operating system version used by ECS cluster. default: /aws/service/ami-windows-latest/Windows_Server-2019-English-Core-ECS_Optimized/image_id build_server_instance_type: + type: string default: t2.medium enum: [t2.small, t2.medium, t2.large, t3.small, t3.medium, t3.large, From d2ee80cf30e46a369038abb5fcc7ab2486820ab7 Mon Sep 17 00:00:00 2001 From: Carlos Santos Date: Mon, 28 Mar 2022 16:48:34 -0700 Subject: [PATCH 08/20] fix: Initial working service template - Removed unsupported container configuraitons - Updated default container image (used for initial svc deployment) --- .../v1/instance_infrastructure/cloudformation.yaml | 14 ++++---------- .../loadbalanced-public-svc/v1/schema/schema.yaml | 5 +++-- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/instance_infrastructure/cloudformation.yaml b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/instance_infrastructure/cloudformation.yaml index f9e99db..9cb47aa 100644 --- a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/instance_infrastructure/cloudformation.yaml +++ b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/instance_infrastructure/cloudformation.yaml @@ -5,12 +5,6 @@ Mappings: Environment: Name: '{{environment.name}}' TaskSize: - x-small: - cpu: 256 - memory: 512 - small: - cpu: 512 - memory: 1024 medium: cpu: 1024 memory: 2048 @@ -68,9 +62,9 @@ Resources: LogConfiguration: LogDriver: 'awslogs' Options: - awslogs-group: '{{service.name}}/{{service_instance.name}}' + awslogs-group: '{{environment.name}}/{{service.name}}/{{service_instance.name}}' awslogs-region: !Ref 'AWS::Region' - awslogs-stream-prefix: '{{service.name}}/{{service_instance.name}}' + awslogs-stream-prefix: '{{environment.name}}/{{service.name}}/{{service_instance.name}}' Tags: - Key: Name Value: !FindInMap ['EnvironmentNameConfig', 'Environment', 'Name'] @@ -250,7 +244,7 @@ Resources: Properties: Description: Ingress from the public ALB GroupId: '{{environment.outputs.ContainerSecurityGroup}}' - IpProtocol: 'tcp' + IpProtocol: '-1' SourceSecurityGroupId: !Ref 'PublicLoadBalancerSG' # Public load balancer, hosted in public subnets that is accessible @@ -265,7 +259,7 @@ Resources: SecurityGroupIngress: # Allow access to ALB from anywhere on the internet - CidrIp: 0.0.0.0/0 - IpProtocol: 'tcp' + IpProtocol: '-1' Tags: - Key: Name Value: !FindInMap ['EnvironmentNameConfig', 'Environment', 'Name'] diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/schema/schema.yaml b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/schema/schema.yaml index bec28b9..47493e6 100644 --- a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/schema/schema.yaml +++ b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/schema/schema.yaml @@ -23,11 +23,12 @@ schema: task_size: type: string description: "The size of the task you want to run" - enum: ["x-small", "small", "medium", "large", "x-large"] - default: "x-small" + enum: [ "medium", "large", "x-large"] + default: "medium" image: type: string description: "The name/url of the container image" + default: "mcr.microsoft.com/dotnet/framework/samples:aspnetapp" minLength: 1 maxLength: 200 service_discovery_name: From b5e6333e7425109068e24a213df1dede8580d39a Mon Sep 17 00:00:00 2001 From: Carlos Santos Date: Thu, 31 Mar 2022 11:57:05 -0700 Subject: [PATCH 09/20] feature: Initial working .NET Fx templates - Corrected IAM permissions, param data types - Centralized CW logs to two log groups (service/service-name) and (service/pipeline) - Added validation of zip file extension - Removed duplicate IAM perms --- .../cloudformation.yaml | 6 +- .../cloudformation.yaml | 265 +++++++++--------- .../v1/schema/schema.yaml | 6 +- 3 files changed, 136 insertions(+), 141 deletions(-) diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/instance_infrastructure/cloudformation.yaml b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/instance_infrastructure/cloudformation.yaml index 9cb47aa..453d096 100644 --- a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/instance_infrastructure/cloudformation.yaml +++ b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/instance_infrastructure/cloudformation.yaml @@ -34,7 +34,7 @@ Resources: LogGroup: Type: AWS::Logs::LogGroup Properties: - LogGroupName: '{{environment.name}}/{{service.name}}/{{service_instance.name}}' + LogGroupName: '{{service.name}}/{{service_instance.name}}' # The task definition. This is a simple metadata description of what # container to run, and what resource requirements it has. @@ -62,9 +62,9 @@ Resources: LogConfiguration: LogDriver: 'awslogs' Options: - awslogs-group: '{{environment.name}}/{{service.name}}/{{service_instance.name}}' + awslogs-group: '{{service.name}}/{{service_instance.name}}' awslogs-region: !Ref 'AWS::Region' - awslogs-stream-prefix: '{{environment.name}}/{{service.name}}/{{service_instance.name}}' + awslogs-stream-prefix: '{{service.name}}/{{service_instance.name}}' Tags: - Key: Name Value: !FindInMap ['EnvironmentNameConfig', 'Environment', 'Name'] diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/pipeline_infrastructure/cloudformation.yaml b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/pipeline_infrastructure/cloudformation.yaml index 7e3e9ab..b1e6c47 100644 --- a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/pipeline_infrastructure/cloudformation.yaml +++ b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/pipeline_infrastructure/cloudformation.yaml @@ -1,8 +1,9 @@ Mappings: BuildConfig: BuildServer: + InstanceType: '{{pipeline.inputs.build_server_instance_type}}' VolumeType: '{{pipeline.inputs.build_server_volume_type}}' - VolumeSize: '{{pipeline.inputs.build_server_volume_size}}' + VolumeSize: {{pipeline.inputs.build_server_volume_size}} ImageBuild: Dockerfile: '{{pipeline.inputs.dockerfile}}' Parameters: @@ -14,6 +15,7 @@ Resources: ECRRepo: Type: AWS::ECR::Repository DeletionPolicy: Retain + UpdateReplacePolicy: Retain Properties: # This policy allows environment accounts to get the image from ECRRepo in the management account RepositoryPolicyText: @@ -34,51 +36,6 @@ Resources: ContainerImageBuildServerRole: Type : AWS::IAM::Role Properties: - Policies: - - PolicyDocument: - Version: '2012-10-17' - Statement: - - Action: s3:GetObject - Resource: !Sub arn:${AWS::Partition}:s3:::${PipelineArtifactsBucket}/* - Effect: Allow - - Action: - - kms:Decrypt - - kms:Encrypt - - kms:ReEncrypt* - - kms:GenerateDataKey* - Effect: Allow - Resource: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn - PolicyName: s3-instance-bucket-policy - - PolicyDocument: - Version: '2012-10-17' - Statement: - - Action: - - "ecr:GetAuthorizationToken" - Resource: "*" - Effect: Allow - PolicyName: ecr-instance-policy - - PolicyDocument: - Version: '2012-10-17' - Statement: - - Action: - - "ecr:BatchCheckLayerAvailability" - - "ecr:BatchGetImage" - - "ecr:CompleteLayerUpload" - - "ecr:DescribeImages" - - "ecr:DescribeImageScanFindings" - - "ecr:DescribeRepositories" - - "ecr:GetDownloadUrlForLayer" - - "ecr:GetLifecyclePolicy" - - "ecr:GetLifecyclePolicyPreview" - - "ecr:GetRepositoryPolicy" - - "ecr:InitiateLayerUpload" - - "ecr:ListImages" - - "ecr:ListTagsForResource" - - "ecr:PutImage" - - "ecr:UploadLayerPart" - Resource: !GetAtt ECRRepo.Arn - Effect: Allow - PolicyName: ecr-resource-instance-policy Path: / ManagedPolicyArns: - !Sub 'arn:${AWS::Partition}:iam::aws:policy/AmazonSSMManagedInstanceCore' @@ -92,6 +49,46 @@ Resources: - "ec2.amazonaws.com" - "ssm.amazonaws.com" Action: "sts:AssumeRole" + ContainerImageBuildServerRoleDefaultPolicy: + Type: AWS::IAM::Policy + Properties: + PolicyName: ContainerImageBuildServerRoleDefaultPolicy + Roles: [!Ref ContainerImageBuildServerRole ] + PolicyDocument: + Version: '2012-10-17' + Statement: + - Action: s3:GetObject + Resource: !Sub arn:${AWS::Partition}:s3:::${PipelineArtifactsBucket}/* + Effect: Allow + - Action: + - kms:Decrypt + - kms:Encrypt + - kms:ReEncrypt* + - kms:GenerateDataKey* + Effect: Allow + Resource: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn + - Action: + - "ecr:GetAuthorizationToken" + Resource: "*" + Effect: Allow + - Action: + - "ecr:BatchCheckLayerAvailability" + - "ecr:BatchGetImage" + - "ecr:CompleteLayerUpload" + - "ecr:DescribeImages" + - "ecr:DescribeImageScanFindings" + - "ecr:DescribeRepositories" + - "ecr:GetDownloadUrlForLayer" + - "ecr:GetLifecyclePolicy" + - "ecr:GetLifecyclePolicyPreview" + - "ecr:GetRepositoryPolicy" + - "ecr:InitiateLayerUpload" + - "ecr:ListImages" + - "ecr:ListTagsForResource" + - "ecr:PutImage" + - "ecr:UploadLayerPart" + Resource: !GetAtt ECRRepo.Arn + Effect: Allow ContainerImageBuildServerInstanceProfile: Type: "AWS::IAM::InstanceProfile" Properties: @@ -116,13 +113,13 @@ Resources: InstanceType: type: String description: (Optional) The instance type of the EC2 instance to be launched. - default: !Ref BuildServerInstanceType + default: !FindInMap ['BuildConfig', 'BuildServer', 'InstanceType'] IamInstanceProfileName: type: String description: (Required) The IAM instance profile to attach to the build instance. default: !Ref ContainerImageBuildServerInstanceProfile InstanceVolumeSize: - type: Integer + type: String description: (Required) Desired volume size (GiB) of the build instance. default: !FindInMap ['BuildConfig', 'BuildServer', 'VolumeSize'] InstanceVolumeType: @@ -147,8 +144,8 @@ Resources: BuildLogGroupName: type: String description: (Optional) CloudWatch Log Group Name for build. - default: !Sub '/aws/codebuild/${BuildProject}' mainSteps: + {% raw %} - name: createNewInstance action: 'aws:runInstances' maxAttempts: 3 @@ -245,6 +242,11 @@ Resources: $key = "{{SourceArtifactS3Path}}" $srcFileName = "$(Split-Path $key -Leaf)" + # Expand-Archive requires '.zip' file extension so add it if necessary + if ([System.IO.Path]::GetExtension($srcFileName) -ne ".zip") { + $srcFileName += ".zip" + } + Read-S3Object -BucketName "{{PipelineBucketName}}" -Key $key -File $srcFileName Expand-Archive -Path "$tmpFolder\$srcFileName" -DestinationPath "$srcFolder" -Force @@ -296,6 +298,7 @@ Resources: DesiredState: terminated isCritical: 'true' isEnd: 'true' + {% endraw %} BuildProject: Type: AWS::CodeBuild::Project Properties: @@ -315,16 +318,20 @@ Resources: Type: PLAINTEXT Value: '{{service.name}}' ServiceRole: !GetAtt PublishRole.Arn + LogsConfig: + CloudWatchLogs: + GroupName: '{{service.name}}/pipeline' + Status: 'ENABLED' + StreamName: 'build' Source: InsecureSsl: false BuildSpec: !Sub | version: "0.2" env: variables: - CONTAINER_NAME: ${TaskContainerName} DOCUMENT_NAME: ${BuildDotNetContainerDocument} ECR_REPO_URI: ${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/${ECRRepo} - LOG_GROUP_NAME: ${CloudWatchLogGroupName} + LOG_GROUP_NAME: {{service.name}}/pipeline phases: install: runtime-versions: @@ -350,7 +357,7 @@ Resources: commands: - echo Starting automation execution using document $DOCUMENT_NAME... - echo Logs are stored under CloudWatch Log Group $LOG_GROUP_NAME... - - EXECUTION_ID=$(aws ssm start-automation-execution --document-name $DOCUMENT_NAME --parameters DockerFile={{ pipeline.inputs.dockerfile }},ImageTag=$IMAGE_TAG,PipelineBucketName=$SRC_ARTIFACT_BUCKET_NAME,SourceArtifactS3Path=$SRC_ARTIFACT_S3_PATH --output text) + - EXECUTION_ID=$(aws ssm start-automation-execution --document-name $DOCUMENT_NAME --parameters BuildLogGroupName=$LOG_GROUP_NAME,DockerFile={{ pipeline.inputs.dockerfile }},ImageTag=$IMAGE_TAG,PipelineBucketName=$SRC_ARTIFACT_BUCKET_NAME,SourceArtifactS3Path=$SRC_ARTIFACT_S3_PATH --output text) - echo Running execution $EXECUTION_ID... - COMMAND="aws ssm describe-automation-executions --filters Key=ExecutionId,Values=$EXECUTION_ID" - STATUS=$($COMMAND | jq -r ".AutomationExecutionMetadataList[0].AutomationExecutionStatus") @@ -370,11 +377,14 @@ Resources: fi post_build: commands: - - if [ $CODEBUILD_BUILD_SUCCEEDING -eq 1 ]; - - then echo Writing updated service specification file...; - - aws proton --region $AWS_DEFAULT_REGION get-service --name $service_name | jq -r .service.spec > service.yaml; - - yq w service.yaml 'instances[*].spec.image' "$IMAGE_ID" > rendered_service.yaml; - - fi + - | + if [ $CODEBUILD_BUILD_SUCCEEDING -eq 1 ]; + then echo Writing updated service specification file...; + aws proton --region $AWS_DEFAULT_REGION get-service --name $service_name | jq -r .service.spec > service.yaml; + yq w service.yaml 'instances[*].spec.image' "$ECR_REPO_URI:$IMAGE_TAG" > rendered_service.yaml; + echo **** Updated service spec follows **** + cat rendered_service.yaml + fi artifacts: files: - rendered_service.yaml @@ -402,6 +412,11 @@ Resources: Type: PLAINTEXT Value: '{{service_instance.name}}' ServiceRole: !GetAtt DeploymentRole.Arn + LogsConfig: + CloudWatchLogs: + GroupName: '{{service.name}}/pipeline' + Status: 'ENABLED' + StreamName: 'deploy' Source: BuildSpec: | version: "0.2" @@ -428,33 +443,43 @@ Resources: PublishRoleDefaultPolicy: Type: AWS::IAM::Policy Properties: + PolicyName: PublishRoleDefaultPolicy PolicyDocument: Statement: - Effect: Allow - Resource: !Sub 'arn:${AWS::Partition}:ec2:${AWS::Region}:${AWS::AccountId}:instance/*' + Resource: + - !Sub 'arn:${AWS::Partition}:ec2:*::image/*' + - !Sub 'arn:${AWS::Partition}:ec2:*:*:network-interface/*' + - !Sub 'arn:${AWS::Partition}:ec2:*:*:security-group/*' + - !Sub 'arn:${AWS::Partition}:ec2:*:*:subnet/*' + - !Sub 'arn:${AWS::Partition}:ec2:*:*:volume/*' + Action: + - 'ec2:RunInstances' + - Effect: Allow + Resource: !Sub 'arn:${AWS::Partition}:ec2:*:*:instance/*' Action: - - 'ec2:RunInstances' + - 'ec2:RunInstances' Condition: StringEquals: "aws:RequestTag/tag:aws:cloudformation:stack-id": !Ref AWS::StackId - Effect: Allow Resource: !Sub 'arn:${AWS::Partition}:ec2:${AWS::Region}:${AWS::AccountId}:instance/*' Action: - - 'ec2:TerminateInstances' + - 'ec2:TerminateInstances' Condition: StringEquals: "aws:ResourceTag/tag:aws:cloudformation:stack-id": !Ref AWS::StackId - Effect: Allow Resource: '*' Action: - - 'ec2:DescribeInstances' - - 'ec2:DescribeInstanceStatus' - - 'ec2:CreateTags' + - 'ec2:DescribeInstances' + - 'ec2:DescribeInstanceStatus' + - 'ec2:CreateTags' - Effect: Allow Resource: - !Sub 'arn:${AWS::Partition}:ec2:${AWS::Region}:${AWS::AccountId}:instance/*' Action: - - 'ssm:SendCommand' + - 'ssm:SendCommand' Condition: StringEquals: "aws:ResourceTag/tag:aws:cloudformation:stack-id": !Ref AWS::StackId @@ -462,40 +487,40 @@ Resources: Resource: - !Sub 'arn:${AWS::Partition}:ssm:${AWS::Region}::document/AWS-RunPowerShellScript' Action: - - 'ssm:SendCommand' + - 'ssm:SendCommand' - Effect: Allow Resource: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/${ContainerImageBuildServerRole} Action: - - 'iam:PassRole' + - 'iam:PassRole' - Effect: Allow Resource: '*' Action: - - 'ssm:CancelCommand' - - 'ssm:DescribeAutomationExecutions' - - 'ssm:DescribeInstanceInformation' - - 'ssm:ListCommands' - - 'ssm:ListCommandInvocations' + - 'ssm:CancelCommand' + - 'ssm:DescribeAutomationExecutions' + - 'ssm:DescribeInstanceInformation' + - 'ssm:ListCommands' + - 'ssm:ListCommandInvocations' - Effect: Allow Resource: !Sub arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:automation-execution/ Action: - - 'ssm:StopAutomationExecution' - - 'ssm:GetAutomationExecution' + - 'ssm:StopAutomationExecution' + - 'ssm:GetAutomationExecution' - Effect: Allow Resource: !Sub arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:automation-definition/${BuildDotNetContainerDocument}:$DEFAULT Action: - - 'ssm:StartAutomationExecution' + - 'ssm:StartAutomationExecution' - Effect: Allow Resource: !Sub arn:${AWS::Partition}:ssm:${AWS::Region}::parameter/aws/service/ami-windows-latest/* Action: - - 'ssm:GetParameters' + - 'ssm:GetParameters' - Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents Effect: Allow Resource: - - !Sub 'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/${BuildProject}' - - !Sub 'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/${BuildProject}:*' + - !Sub 'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:{{service.name}}/pipeline' + - !Sub 'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:{{service.name}}/pipeline:*' - Action: - codebuild:CreateReportGroup - codebuild:CreateReport @@ -504,11 +529,15 @@ Resources: Effect: Allow Resource: !Sub 'arn:${AWS::Partition}:codebuild:${AWS::Region}:${AWS::AccountId}:report-group/${BuildProject}-*' - Action: - - 's3:PutObject' - - 's3:GetObject' - - 's3:GetObjectVersion' - - 's3:GetBucketAcl' - - 's3:GetBucketLocation' + - proton:GetService + Effect: Allow + Resource: "*" + - Action: + - 's3:PutObject' + - 's3:GetObject' + - 's3:GetObjectVersion' + - 's3:GetBucketAcl' + - 's3:GetBucketLocation' Effect: Allow Resource: - !GetAtt PipelineArtifactsBucket.Arn @@ -537,6 +566,7 @@ Resources: DeploymentRoleDefaultPolicy: Type: AWS::IAM::Policy Properties: + PolicyName: DeploymentRoleDefaultPolicy PolicyDocument: Statement: - Action: @@ -545,8 +575,8 @@ Resources: - logs:PutLogEvents Effect: Allow Resource: - - !Sub 'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/Deploy*Project*' - - !Sub 'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/Deploy*Project:*' + - !Sub 'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:{{service.name}}/pipeline' + - !Sub 'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:{{service.name}}/pipeline:*' - Action: - codebuild:CreateReportGroup - codebuild:CreateReport @@ -570,18 +600,13 @@ Resources: - Action: - kms:Decrypt - kms:DescribeKey - Effect: Allow - Resource: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn - - Action: - - kms:Decrypt - kms:Encrypt - kms:ReEncrypt* - kms:GenerateDataKey* Effect: Allow Resource: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn Version: '2012-10-17' - PolicyName: DeploymentRoleDefaultPolicy - Roles: !Ref DeploymentRole + Roles: [ !Ref DeploymentRole ] PipelineArtifactsBucketEncryptionKey: Type: AWS::KMS::Key Properties: @@ -615,42 +640,11 @@ Resources: - kms:GenerateDataKey* Effect: Allow Principal: - AWS: !GetAtt PipelineRole.Arn - Resource: '*' - - Action: - - kms:Decrypt - - kms:DescribeKey - - kms:Encrypt - - kms:ReEncrypt* - - kms:GenerateDataKey* - Effect: Allow - Principal: - AWS: !GetAtt PublishRole.Arn - Resource: '*' - - Action: - - kms:Decrypt - - kms:Encrypt - - kms:ReEncrypt* - - kms:GenerateDataKey* - Effect: Allow - Principal: - AWS: !GetAtt: PublishRole.Arn - Resource: '*' - - Action: - - kms:Decrypt - - kms:DescribeKey - Effect: Allow - Principal: - AWS: !GetAtt DeploymentRole.Arn - Resource: '*' - - Action: - - kms:Decrypt - - kms:Encrypt - - kms:ReEncrypt* - - kms:GenerateDataKey* - Effect: Allow - Principal: - AWS: !GetAtt DeploymentRole.Arn + AWS: + - !GetAtt PipelineRole.Arn + - !GetAtt PublishRole.Arn + - !GetAtt DeploymentRole.Arn + - !GetAtt ContainerImageBuildServerRole.Arn Resource: '*' Version: '2012-10-17' UpdateReplacePolicy: Delete @@ -692,6 +686,7 @@ Resources: PipelineRoleDefaultPolicy: Type: AWS::IAM::Policy Properties: + PolicyName: PipelineRoleDefaultPolicy PolicyDocument: Statement: - Action: @@ -723,8 +718,7 @@ Resources: Effect: Allow Resource: !GetAtt PipelineDeployCodePipelineActionRole.Arn Version: '2012-10-17' - PolicyName: PipelineRoleDefaultPolicy - Roles: !Ref PipelineRole + Roles: [ !Ref PipelineRole ] Pipeline: Type: AWS::CodePipeline::Pipeline Properties: @@ -735,7 +729,7 @@ Resources: Category: Source Owner: AWS Provider: CodeStarSourceConnection - Version: 1 + Version: '1' Configuration: ConnectionArn: '{{ service.repository_connection_arn }}' FullRepositoryId: '{{ service.repository_id }}' @@ -750,7 +744,7 @@ Resources: Category: Build Owner: AWS Provider: CodeBuild - Version: 1 + Version: '1' Configuration: ProjectName: !Ref BuildProject InputArtifacts: @@ -767,7 +761,7 @@ Resources: Category: Build Owner: AWS Provider: CodeBuild - Version: 1 + Version: '1' Configuration: ProjectName: !Ref Deploy{{loop.index}}Project InputArtifacts: @@ -785,7 +779,10 @@ Resources: Type: S3 DependsOn: - PipelineRoleDefaultPolicy - - PipelineRole + - PublishRoleDefaultPolicy + - PipelineBuildCodePipelineActionRoleDefaultPolicy + - PipelineDeployCodePipelineActionRoleDefaultPolicy + - ContainerImageBuildServerRoleDefaultPolicy PipelineBuildCodePipelineActionRole: Type: AWS::IAM::Role Properties: @@ -809,7 +806,7 @@ Resources: Resource: !GetAtt BuildProject.Arn Version: '2012-10-17' PolicyName: PipelineBuildCodePipelineActionRoleDefaultPolicy - Roles: !Ref PipelineBuildCodePipelineActionRole + Roles: [ !Ref PipelineBuildCodePipelineActionRole ] PipelineDeployCodePipelineActionRole: Type: AWS::IAM::Role Properties: @@ -833,7 +830,7 @@ Resources: Resource: !Sub 'arn:${AWS::Partition}:codebuild:${AWS::Region}:${AWS::AccountId}:project/Deploy*' Version: '2012-10-17' PolicyName: PipelineDeployCodePipelineActionRoleDefaultPolicy - Roles: !Ref PipelineDeployCodePipelineActionRole + Roles: [ !Ref PipelineDeployCodePipelineActionRole ] Outputs: PipelineEndpoint: Description: The URL to access the pipeline diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/schema/schema.yaml b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/schema/schema.yaml index 47493e6..dbe6026 100644 --- a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/schema/schema.yaml +++ b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/schema/schema.yaml @@ -37,7 +37,6 @@ schema: minLength: 3 maxLength: 24 required: - - image - service_discovery_name PipelineInputs: @@ -54,12 +53,12 @@ schema: enum: [t2.small, t2.medium, t2.large, t3.small, t3.medium, t3.large, t3a.small, t3a.medium, t3a.large ] - build_server_volume_type: + build_server_volume_size: type: number default: 30 minimum: 4 maximum: 1024 - build_server_volume_size: + build_server_volume_type: type: string default: gp3 enum: [ gp3, gp2 ] @@ -68,4 +67,3 @@ schema: description: "The location of the Dockerfile to build" default: "Dockerfile" minLength: 1 - maxLength: 100 From 09b91cf7c0ec605bbca038fe8e594dc1cfa4e164 Mon Sep 17 00:00:00 2001 From: Carlos Santos Date: Thu, 31 Mar 2022 13:04:58 -0700 Subject: [PATCH 10/20] fix: Changed SSM Doc Resolve AMI - ID at Execution Time Previously SSM param was resolved by using a CF parameter. This led to the SSM doc having the resolved AMI ID as the default value, not the SSM param name. This leads to essentially hard coding the AMI ID at the time that the CF stack is created. SSM doc should resolve the SSM param at time of execution. - Added Operating System Family parameter since the SSM parameter could point to an AMI ID for various OSs - Sync'd pipeline templates between public and private services --- .../cloudformation.yaml | 2 +- .../cloudformation.yaml | 7 +- .../v1/schema/schema.yaml | 10 +- .../cloudformation.yaml | 539 ++++++++++++++---- .../private-fargate-svc/v1/schema/schema.yaml | 48 +- 5 files changed, 482 insertions(+), 124 deletions(-) diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/instance_infrastructure/cloudformation.yaml b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/instance_infrastructure/cloudformation.yaml index 453d096..f3c5970 100644 --- a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/instance_infrastructure/cloudformation.yaml +++ b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/instance_infrastructure/cloudformation.yaml @@ -49,7 +49,7 @@ Resources: - FARGATE RuntimePlatform: CpuArchitecture: 'X86_64' - OperatingSystemFamily: 'WINDOWS_SERVER_2019_CORE' + OperatingSystemFamily: '{{service_instance.inputs.cluster_operating_system_family}}' ExecutionRoleArn: '{{environment.outputs.ECSTaskExecutionRole}}' TaskRoleArn: !Ref 'AWS::NoValue' ContainerDefinitions: diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/pipeline_infrastructure/cloudformation.yaml b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/pipeline_infrastructure/cloudformation.yaml index b1e6c47..80cad89 100644 --- a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/pipeline_infrastructure/cloudformation.yaml +++ b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/pipeline_infrastructure/cloudformation.yaml @@ -6,11 +6,6 @@ Mappings: VolumeSize: {{pipeline.inputs.build_server_volume_size}} ImageBuild: Dockerfile: '{{pipeline.inputs.dockerfile}}' -Parameters: - BuildServerAmiId: - Type: AWS::SSM::Parameter::Value - Description: AMI ID or SSM Parameter expression to use to retrieve the AMI ID for the build server. Must be compatible with operating system version used by ECS cluster. - Default: '{{pipeline.inputs.build_server_ami_id}}' Resources: ECRRepo: Type: AWS::ECR::Repository @@ -104,7 +99,7 @@ Resources: parameters: AmiId: type: String - default: !Ref BuildServerAmiId + default: "{{'{{'}}ssm:{{pipeline.inputs.build_server_ami_id}}{{'}}'}}" description: The Windows Server AMI to use for the build server must match version used by ECS cluster. DockerFile: type: String diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/schema/schema.yaml b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/schema/schema.yaml index dbe6026..c043ca7 100644 --- a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/schema/schema.yaml +++ b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/schema/schema.yaml @@ -43,23 +43,31 @@ schema: type: object description: "Pipeline input properties" properties: + cluster_operating_system_family: + type: string + description: "The operating system used for the ECS Task Definition" + default: WINDOWS_SERVER_2019_CORE + enum: ['WINDOWS_SERVER_2019_CORE', 'WINDOWS_SERVER_2019_FULL', 'WINDOWS_SERVER_2022_CORE', 'WINDOWS_SERVER_2022_FULL'] build_server_ami_id: type: string - description: AMI ID or SSM Parameter expression to use to retrieve the AMI ID for the build server. Must be compatible with operating system version used by ECS cluster. + description: SSM Parameter expression to use to retrieve the AMI ID for the build server. Must be compatible with operating system version used by ECS cluster. default: /aws/service/ami-windows-latest/Windows_Server-2019-English-Core-ECS_Optimized/image_id build_server_instance_type: type: string + description: "Instance type used for the EC2 Instance that serves as the build server." default: t2.medium enum: [t2.small, t2.medium, t2.large, t3.small, t3.medium, t3.large, t3a.small, t3a.medium, t3a.large ] build_server_volume_size: type: number + description: "Volume size in GiBs used when provisioning the build server." default: 30 minimum: 4 maximum: 1024 build_server_volume_type: type: string + description: "Volume type used when provisioning the build server." default: gp3 enum: [ gp3, gp2 ] dockerfile: diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/pipeline_infrastructure/cloudformation.yaml b/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/pipeline_infrastructure/cloudformation.yaml index 6fc6f5c..80cad89 100644 --- a/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/pipeline_infrastructure/cloudformation.yaml +++ b/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/pipeline_infrastructure/cloudformation.yaml @@ -1,7 +1,16 @@ +Mappings: + BuildConfig: + BuildServer: + InstanceType: '{{pipeline.inputs.build_server_instance_type}}' + VolumeType: '{{pipeline.inputs.build_server_volume_type}}' + VolumeSize: {{pipeline.inputs.build_server_volume_size}} + ImageBuild: + Dockerfile: '{{pipeline.inputs.dockerfile}}' Resources: ECRRepo: Type: AWS::ECR::Repository DeletionPolicy: Retain + UpdateReplacePolicy: Retain Properties: # This policy allows environment accounts to get the image from ECRRepo in the management account RepositoryPolicyText: @@ -19,15 +28,282 @@ Resources: - ecr:BatchCheckLayerAvailability - ecr:GetDownloadUrlForLayer - ecr:BatchGetImage + ContainerImageBuildServerRole: + Type : AWS::IAM::Role + Properties: + Path: / + ManagedPolicyArns: + - !Sub 'arn:${AWS::Partition}:iam::aws:policy/AmazonSSMManagedInstanceCore' + - !Sub 'arn:${AWS::Partition}:iam::aws:policy/CloudWatchAgentServerPolicy' + AssumeRolePolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: "Allow" + Principal: + Service: + - "ec2.amazonaws.com" + - "ssm.amazonaws.com" + Action: "sts:AssumeRole" + ContainerImageBuildServerRoleDefaultPolicy: + Type: AWS::IAM::Policy + Properties: + PolicyName: ContainerImageBuildServerRoleDefaultPolicy + Roles: [!Ref ContainerImageBuildServerRole ] + PolicyDocument: + Version: '2012-10-17' + Statement: + - Action: s3:GetObject + Resource: !Sub arn:${AWS::Partition}:s3:::${PipelineArtifactsBucket}/* + Effect: Allow + - Action: + - kms:Decrypt + - kms:Encrypt + - kms:ReEncrypt* + - kms:GenerateDataKey* + Effect: Allow + Resource: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn + - Action: + - "ecr:GetAuthorizationToken" + Resource: "*" + Effect: Allow + - Action: + - "ecr:BatchCheckLayerAvailability" + - "ecr:BatchGetImage" + - "ecr:CompleteLayerUpload" + - "ecr:DescribeImages" + - "ecr:DescribeImageScanFindings" + - "ecr:DescribeRepositories" + - "ecr:GetDownloadUrlForLayer" + - "ecr:GetLifecyclePolicy" + - "ecr:GetLifecyclePolicyPreview" + - "ecr:GetRepositoryPolicy" + - "ecr:InitiateLayerUpload" + - "ecr:ListImages" + - "ecr:ListTagsForResource" + - "ecr:PutImage" + - "ecr:UploadLayerPart" + Resource: !GetAtt ECRRepo.Arn + Effect: Allow + ContainerImageBuildServerInstanceProfile: + Type: "AWS::IAM::InstanceProfile" + Properties: + Roles: + - !Ref ContainerImageBuildServerRole + BuildDotNetContainerDocument: + Type: AWS::SSM::Document + Properties: + DocumentType: Automation + Content: + schemaVersion: "0.3" + description: "Create a .NET Framework Container for CodeBuild" + parameters: + AmiId: + type: String + default: "{{'{{'}}ssm:{{pipeline.inputs.build_server_ami_id}}{{'}}'}}" + description: The Windows Server AMI to use for the build server must match version used by ECS cluster. + DockerFile: + type: String + default: !FindInMap ['BuildConfig', 'ImageBuild', 'Dockerfile'] + description: Location of the Dockerfile relative to repository's root folder + InstanceType: + type: String + description: (Optional) The instance type of the EC2 instance to be launched. + default: !FindInMap ['BuildConfig', 'BuildServer', 'InstanceType'] + IamInstanceProfileName: + type: String + description: (Required) The IAM instance profile to attach to the build instance. + default: !Ref ContainerImageBuildServerInstanceProfile + InstanceVolumeSize: + type: String + description: (Required) Desired volume size (GiB) of the build instance. + default: !FindInMap ['BuildConfig', 'BuildServer', 'VolumeSize'] + InstanceVolumeType: + type: String + description: (Required) Desired volume type of the build instance. + default: !FindInMap ['BuildConfig', 'BuildServer', 'VolumeType'] + PipelineBucketName: + type: String + description: (Required) Bucket that build artifact is stored in. + default: !Ref PipelineArtifactsBucket + SourceArtifactS3Path: + type: String + description: (Required) Build artifact key. + EcrRepoName: + default: !Ref ECRRepo + description: "ECR Repo Name" + type: "String" + ImageTag: + type: String + description: (Optional) Tag for container image. + default: latest + BuildLogGroupName: + type: String + description: (Optional) CloudWatch Log Group Name for build. + mainSteps: + {% raw %} + - name: createNewInstance + action: 'aws:runInstances' + maxAttempts: 3 + timeoutSeconds: 1200 + onFailure: Abort + inputs: + ImageId: '{{ AmiId }}' + InstanceType: '{{ InstanceType }}' + MinInstanceCount: 1 + MaxInstanceCount: 1 + IamInstanceProfileName: '{{ IamInstanceProfileName }}' + BlockDeviceMappings: + - DeviceName: /dev/xvdb + Ebs: + VolumeSize: '{{ InstanceVolumeSize }}' + VolumeType: '{{ InstanceVolumeType }}' + TagSpecifications: + - ResourceType: instance + Tags: + - Key: tag:aws:cloudformation:stack-id + Value: !Ref AWS::StackId + - Key: tag:aws:cloudformation:stack-name + Value: !Ref AWS::StackName + - Key: Name + Value: dotnetfx-container-build + nextStep: getInstance + - name: getInstance + action: 'aws:executeAwsApi' + maxAttempts: 2 + onFailure: Abort + inputs: + Service: ec2 + Api: DescribeInstances + InstanceIds: + - '{{ createNewInstance.InstanceIds }}' + outputs: + - Name: InstanceId + Selector: '$.Reservations[0].Instances[0].InstanceId' + Type: String + isCritical: 'true' + nextStep: waitForInstanceToBeReady + - name: waitForInstanceToBeReady + action: 'aws:waitForAwsResourceProperty' + onFailure: 'step:terminateInstance' + timeoutSeconds: 600 + maxAttempts: 2 + inputs: + Service: ec2 + Api: DescribeInstanceStatus + InstanceIds: + - '{{ getInstance.InstanceId }}' + PropertySelector: '$.InstanceStatuses[0].InstanceStatus.Details[0].Status' + DesiredValues: + - passed + isCritical: 'false' + nextStep: waitForSSMAgentOnline + - name: waitForSSMAgentOnline + action: 'aws:waitForAwsResourceProperty' + onFailure: 'step:terminateInstance' + timeoutSeconds: 600 + inputs: + Service: ssm + Api: DescribeInstanceInformation + InstanceInformationFilterList: + - key: InstanceIds + valueSet: + - '{{ getInstance.InstanceId }}' + PropertySelector: '$.InstanceInformationList[0].PingStatus' + DesiredValues: + - Online + isCritical: 'true' + nextStep: CreateDockerImage + - name: CreateDockerImage + action: 'aws:runCommand' + onFailure: 'step:terminateInstance' + timeoutSeconds: 7200 + inputs: + DocumentName: AWS-RunPowerShellScript + InstanceIds: + - '{{ getInstance.InstanceId }}' + Parameters: + commands: | + $ErrorActionPreference = "Stop" + + Write-Host "*****Downloading from S3...*****" + + New-Item -Name tmp -ItemType directory -Force | out-null + New-Item -Name tmp\src -ItemType directory -Force | out-null + + cd .\tmp + + $tmpFolder = $(Get-Location).Path + $srcFolder = "$tmpFolder\src" + $key = "{{SourceArtifactS3Path}}" + $srcFileName = "$(Split-Path $key -Leaf)" + + # Expand-Archive requires '.zip' file extension so add it if necessary + if ([System.IO.Path]::GetExtension($srcFileName) -ne ".zip") { + $srcFileName += ".zip" + } + + Read-S3Object -BucketName "{{PipelineBucketName}}" -Key $key -File $srcFileName + Expand-Archive -Path "$tmpFolder\$srcFileName" -DestinationPath "$srcFolder" -Force + + Write-Host "*****Building Docker image...*****" + + $instanceInfo = (Invoke-RestMethod -Method Get -Uri http://169.254.169.254/latest/dynamic/instance-identity/document) + $repoUri = $instanceInfo.accountId + '.dkr.ecr.' + $instanceInfo.region + '.amazonaws.com/{{EcrRepoName}}' + $latestUri = "$($repoUri):latest" + $hasCustomTag = $False + $buildArgs = @("-t", $latestUri) + $customTag = "{{ImageTag}}" + + if ($customTag -and $($customTag -ne "latest")) { + $hasCustomTag = $True + $uriWithTag = "$($repoUri):$customTag" + $buildArgs += @("-t", $uriWithTag) + } + + Write-Host "Docker Build Args are '$buildArgs'" + + cd $srcFolder + docker build $buildArgs $srcFolder\ + + if ($LASTEXITCODE -ne 0) { + throw ("'docker build $buildArgs $srcFolder\' execution failed with exit code $LASTEXITCODE.") + } + + Write-Host "*****Pushing Docker image to ECR...*****" + + Invoke-Expression –Command (Get-ECRLoginCommand –Region $region).Command + docker push $repoUri --all-tags + + if ($LASTEXITCODE -ne 0) { + throw "'docker push $repoUri --all-tags' execution failed with exit code $LASTEXITCODE." + } + executionTimeout: '7200' + CloudWatchOutputConfig: + CloudWatchLogGroupName: '{{ BuildLogGroupName }}' + CloudWatchOutputEnabled: true + isCritical: 'true' + nextStep: terminateInstance + - name: terminateInstance + action: 'aws:changeInstanceState' + maxAttempts: 3 + onFailure: Continue + inputs: + InstanceIds: + - '{{getInstance.InstanceId}}' + DesiredState: terminated + isCritical: 'true' + isEnd: 'true' + {% endraw %} BuildProject: Type: AWS::CodeBuild::Project Properties: Artifacts: Type: CODEPIPELINE + Packaging: NONE Environment: ComputeType: BUILD_GENERAL1_SMALL Image: aws/codebuild/amazonlinux2-x86_64-standard:3.0 - PrivilegedMode: true + PrivilegedMode: false Type: LINUX_CONTAINER EnvironmentVariables: - Name: repo_name @@ -37,9 +313,20 @@ Resources: Type: PLAINTEXT Value: '{{service.name}}' ServiceRole: !GetAtt PublishRole.Arn + LogsConfig: + CloudWatchLogs: + GroupName: '{{service.name}}/pipeline' + Status: 'ENABLED' + StreamName: 'build' Source: + InsecureSsl: false BuildSpec: !Sub | version: "0.2" + env: + variables: + DOCUMENT_NAME: ${BuildDotNetContainerDocument} + ECR_REPO_URI: ${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/${ECRRepo} + LOG_GROUP_NAME: {{service.name}}/pipeline phases: install: runtime-versions: @@ -53,27 +340,55 @@ Resources: - chmod +x /usr/bin/yq pre_build: commands: - - cd $CODEBUILD_SRC_DIR - - $(aws ecr get-login --no-include-email --region $AWS_DEFAULT_REGION) - - {{ pipeline.inputs.unit_test_command }} + - BUILD_ID=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-8) + - IMAGE_TAG=build-$BUILD_ID + - SRC_ARTIFACT_FULL_S3_PATH=${!CODEBUILD_SOURCE_VERSION#*"s3:::"} + - SRC_ARTIFACT_S3_PATH=${!SRC_ARTIFACT_FULL_S3_PATH#*"/"} + - SRC_ARTIFACT_BUCKET_NAME=$(echo $SRC_ARTIFACT_FULL_S3_PATH | cut -c 1-$((${!#SRC_ARTIFACT_FULL_S3_PATH} - ${!#SRC_ARTIFACT_S3_PATH} - 1))) + - echo SRC_ARTIFACT_FULL_S3_PATH=$SRC_ARTIFACT_FULL_S3_PATH + - echo SRC_ARTIFACT_S3_PATH=$SRC_ARTIFACT_S3_PATH + - echo SRC_ARTIFACT_BUCKET_NAME=$SRC_ARTIFACT_BUCKET_NAME build: commands: - - IMAGE_REPO_NAME=$repo_name - - IMAGE_TAG=$CODEBUILD_BUILD_NUMBER - - IMAGE_ID=${AWS::AccountId}.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG - - docker build -t $IMAGE_REPO_NAME:$IMAGE_TAG -f {{ pipeline.inputs.dockerfile }} . - - docker tag $IMAGE_REPO_NAME:$IMAGE_TAG $IMAGE_ID; - - docker push $IMAGE_ID + - echo Starting automation execution using document $DOCUMENT_NAME... + - echo Logs are stored under CloudWatch Log Group $LOG_GROUP_NAME... + - EXECUTION_ID=$(aws ssm start-automation-execution --document-name $DOCUMENT_NAME --parameters BuildLogGroupName=$LOG_GROUP_NAME,DockerFile={{ pipeline.inputs.dockerfile }},ImageTag=$IMAGE_TAG,PipelineBucketName=$SRC_ARTIFACT_BUCKET_NAME,SourceArtifactS3Path=$SRC_ARTIFACT_S3_PATH --output text) + - echo Running execution $EXECUTION_ID... + - COMMAND="aws ssm describe-automation-executions --filters Key=ExecutionId,Values=$EXECUTION_ID" + - STATUS=$($COMMAND | jq -r ".AutomationExecutionMetadataList[0].AutomationExecutionStatus") + - | + while [ $STATUS = "InProgress" ]; + do sleep 3; + STATUS=$($COMMAND | jq -r ".AutomationExecutionMetadataList[0].AutomationExecutionStatus"); + done + - | + if [ $STATUS = "Success" ]; + then echo Automation execution succeeded.; + else echo Automation execution failed. Please check CloudWatch log for details.; + ERROR_MSG=$($COMMAND | jq -r ".AutomationExecutionMetadataList[0].FailureMessage"); + echo SSM Failure Message Follows.; + echo $ERROR_MSG; + exit 1; + fi post_build: commands: - - aws proton --region $AWS_DEFAULT_REGION get-service --name $service_name | jq -r .service.spec > service.yaml - - yq w service.yaml 'instances[*].spec.image' "$IMAGE_ID" > rendered_service.yaml + - | + if [ $CODEBUILD_BUILD_SUCCEEDING -eq 1 ]; + then echo Writing updated service specification file...; + aws proton --region $AWS_DEFAULT_REGION get-service --name $service_name | jq -r .service.spec > service.yaml; + yq w service.yaml 'instances[*].spec.image' "$ECR_REPO_URI:$IMAGE_TAG" > rendered_service.yaml; + echo **** Updated service spec follows **** + cat rendered_service.yaml + fi artifacts: files: - rendered_service.yaml Type: CODEPIPELINE EncryptionKey: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn -{% for service_instance in service_instances %} + TimeoutInMinutes: 60 + QueuedTimeoutInMinutes: 480 + + {% for service_instance in service_instances %} Deploy{{loop.index}}Project: Type: AWS::CodeBuild::Project Properties: @@ -92,6 +407,11 @@ Resources: Type: PLAINTEXT Value: '{{service_instance.name}}' ServiceRole: !GetAtt DeploymentRole.Arn + LogsConfig: + CloudWatchLogs: + GroupName: '{{service.name}}/pipeline' + Status: 'ENABLED' + StreamName: 'deploy' Source: BuildSpec: | version: "0.2" @@ -103,8 +423,8 @@ Resources: - aws proton --region $AWS_DEFAULT_REGION wait service-instance-deployed --name $service_instance_name --service-name $service_name Type: CODEPIPELINE EncryptionKey: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn -{% endfor %} - # This role is used to build and publish an image to ECR + {% endfor %} + # This role is used to build container image PublishRole: Type: AWS::IAM::Role Properties: @@ -118,16 +438,84 @@ Resources: PublishRoleDefaultPolicy: Type: AWS::IAM::Policy Properties: + PolicyName: PublishRoleDefaultPolicy PolicyDocument: Statement: + - Effect: Allow + Resource: + - !Sub 'arn:${AWS::Partition}:ec2:*::image/*' + - !Sub 'arn:${AWS::Partition}:ec2:*:*:network-interface/*' + - !Sub 'arn:${AWS::Partition}:ec2:*:*:security-group/*' + - !Sub 'arn:${AWS::Partition}:ec2:*:*:subnet/*' + - !Sub 'arn:${AWS::Partition}:ec2:*:*:volume/*' + Action: + - 'ec2:RunInstances' + - Effect: Allow + Resource: !Sub 'arn:${AWS::Partition}:ec2:*:*:instance/*' + Action: + - 'ec2:RunInstances' + Condition: + StringEquals: + "aws:RequestTag/tag:aws:cloudformation:stack-id": !Ref AWS::StackId + - Effect: Allow + Resource: !Sub 'arn:${AWS::Partition}:ec2:${AWS::Region}:${AWS::AccountId}:instance/*' + Action: + - 'ec2:TerminateInstances' + Condition: + StringEquals: + "aws:ResourceTag/tag:aws:cloudformation:stack-id": !Ref AWS::StackId + - Effect: Allow + Resource: '*' + Action: + - 'ec2:DescribeInstances' + - 'ec2:DescribeInstanceStatus' + - 'ec2:CreateTags' + - Effect: Allow + Resource: + - !Sub 'arn:${AWS::Partition}:ec2:${AWS::Region}:${AWS::AccountId}:instance/*' + Action: + - 'ssm:SendCommand' + Condition: + StringEquals: + "aws:ResourceTag/tag:aws:cloudformation:stack-id": !Ref AWS::StackId + - Effect: Allow + Resource: + - !Sub 'arn:${AWS::Partition}:ssm:${AWS::Region}::document/AWS-RunPowerShellScript' + Action: + - 'ssm:SendCommand' + - Effect: Allow + Resource: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/${ContainerImageBuildServerRole} + Action: + - 'iam:PassRole' + - Effect: Allow + Resource: '*' + Action: + - 'ssm:CancelCommand' + - 'ssm:DescribeAutomationExecutions' + - 'ssm:DescribeInstanceInformation' + - 'ssm:ListCommands' + - 'ssm:ListCommandInvocations' + - Effect: Allow + Resource: !Sub arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:automation-execution/ + Action: + - 'ssm:StopAutomationExecution' + - 'ssm:GetAutomationExecution' + - Effect: Allow + Resource: !Sub arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:automation-definition/${BuildDotNetContainerDocument}:$DEFAULT + Action: + - 'ssm:StartAutomationExecution' + - Effect: Allow + Resource: !Sub arn:${AWS::Partition}:ssm:${AWS::Region}::parameter/aws/service/ami-windows-latest/* + Action: + - 'ssm:GetParameters' - Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents Effect: Allow Resource: - - !Sub 'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/${BuildProject}' - - !Sub 'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/${BuildProject}:*' + - !Sub 'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:{{service.name}}/pipeline' + - !Sub 'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:{{service.name}}/pipeline:*' - Action: - codebuild:CreateReportGroup - codebuild:CreateReport @@ -135,30 +523,16 @@ Resources: - codebuild:BatchPutTestCases Effect: Allow Resource: !Sub 'arn:${AWS::Partition}:codebuild:${AWS::Region}:${AWS::AccountId}:report-group/${BuildProject}-*' - - Action: - - ecr:GetAuthorizationToken - Effect: Allow - Resource: '*' - - Action: - - ecr:BatchCheckLayerAvailability - - ecr:CompleteLayerUpload - - ecr:GetAuthorizationToken - - ecr:InitiateLayerUpload - - ecr:PutImage - - ecr:UploadLayerPart - Effect: Allow - Resource: !GetAtt ECRRepo.Arn - Action: - proton:GetService Effect: Allow - Resource: '*' + Resource: "*" - Action: - - s3:GetObject* - - s3:GetBucket* - - s3:List* - - s3:DeleteObject* - - s3:PutObject* - - s3:Abort* + - 's3:PutObject' + - 's3:GetObject' + - 's3:GetObjectVersion' + - 's3:GetBucketAcl' + - 's3:GetBucketLocation' Effect: Allow Resource: - !GetAtt PipelineArtifactsBucket.Arn @@ -171,16 +545,8 @@ Resources: - kms:GenerateDataKey* Effect: Allow Resource: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn - - Action: - - kms:Decrypt - - kms:Encrypt - - kms:ReEncrypt* - - kms:GenerateDataKey* - Effect: Allow - Resource: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn Version: '2012-10-17' - PolicyName: PublishRoleDefaultPolicy - Roles: !Ref PublishRole + Roles: [ !Ref PublishRole ] DeploymentRole: Type: AWS::IAM::Role @@ -195,6 +561,7 @@ Resources: DeploymentRoleDefaultPolicy: Type: AWS::IAM::Policy Properties: + PolicyName: DeploymentRoleDefaultPolicy PolicyDocument: Statement: - Action: @@ -203,8 +570,8 @@ Resources: - logs:PutLogEvents Effect: Allow Resource: - - !Sub 'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/Deploy*Project*' - - !Sub 'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/Deploy*Project:*' + - !Sub 'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:{{service.name}}/pipeline' + - !Sub 'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:{{service.name}}/pipeline:*' - Action: - codebuild:CreateReportGroup - codebuild:CreateReport @@ -228,18 +595,13 @@ Resources: - Action: - kms:Decrypt - kms:DescribeKey - Effect: Allow - Resource: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn - - Action: - - kms:Decrypt - kms:Encrypt - kms:ReEncrypt* - kms:GenerateDataKey* Effect: Allow Resource: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn Version: '2012-10-17' - PolicyName: DeploymentRoleDefaultPolicy - Roles: !Ref DeploymentRole + Roles: [ !Ref DeploymentRole ] PipelineArtifactsBucketEncryptionKey: Type: AWS::KMS::Key Properties: @@ -273,42 +635,11 @@ Resources: - kms:GenerateDataKey* Effect: Allow Principal: - AWS: !GetAtt PipelineRole.Arn - Resource: '*' - - Action: - - kms:Decrypt - - kms:DescribeKey - - kms:Encrypt - - kms:ReEncrypt* - - kms:GenerateDataKey* - Effect: Allow - Principal: - AWS: !GetAtt PublishRole.Arn - Resource: '*' - - Action: - - kms:Decrypt - - kms:Encrypt - - kms:ReEncrypt* - - kms:GenerateDataKey* - Effect: Allow - Principal: - AWS: !GetAtt PublishRole.Arn - Resource: '*' - - Action: - - kms:Decrypt - - kms:DescribeKey - Effect: Allow - Principal: - AWS: !GetAtt DeploymentRole.Arn - Resource: '*' - - Action: - - kms:Decrypt - - kms:Encrypt - - kms:ReEncrypt* - - kms:GenerateDataKey* - Effect: Allow - Principal: - AWS: !GetAtt DeploymentRole.Arn + AWS: + - !GetAtt PipelineRole.Arn + - !GetAtt PublishRole.Arn + - !GetAtt DeploymentRole.Arn + - !GetAtt ContainerImageBuildServerRole.Arn Resource: '*' Version: '2012-10-17' UpdateReplacePolicy: Delete @@ -350,6 +681,7 @@ Resources: PipelineRoleDefaultPolicy: Type: AWS::IAM::Policy Properties: + PolicyName: PipelineRoleDefaultPolicy PolicyDocument: Statement: - Action: @@ -381,8 +713,7 @@ Resources: Effect: Allow Resource: !GetAtt PipelineDeployCodePipelineActionRole.Arn Version: '2012-10-17' - PolicyName: PipelineRoleDefaultPolicy - Roles: !Ref PipelineRole + Roles: [ !Ref PipelineRole ] Pipeline: Type: AWS::CodePipeline::Pipeline Properties: @@ -393,7 +724,7 @@ Resources: Category: Source Owner: AWS Provider: CodeStarSourceConnection - Version: 1 + Version: '1' Configuration: ConnectionArn: '{{ service.repository_connection_arn }}' FullRepositoryId: '{{ service.repository_id }}' @@ -408,7 +739,7 @@ Resources: Category: Build Owner: AWS Provider: CodeBuild - Version: 1 + Version: '1' Configuration: ProjectName: !Ref BuildProject InputArtifacts: @@ -418,13 +749,14 @@ Resources: - Name: BuildOutput RoleArn: !GetAtt PipelineBuildCodePipelineActionRole.Arn RunOrder: 1 - Name: Build {%- for service_instance in service_instances %} + Name: Build + {%- for service_instance in service_instances %} - Actions: - ActionTypeId: Category: Build Owner: AWS Provider: CodeBuild - Version: 1 + Version: '1' Configuration: ProjectName: !Ref Deploy{{loop.index}}Project InputArtifacts: @@ -432,8 +764,8 @@ Resources: Name: Deploy RoleArn: !GetAtt PipelineDeployCodePipelineActionRole.Arn RunOrder: 1 - Name: 'Deploy{{service_instance.name}}' -{%- endfor %} + Name: 'Deploy-{{service_instance.name}}' + {%- endfor %} ArtifactStore: EncryptionKey: Id: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn @@ -442,7 +774,10 @@ Resources: Type: S3 DependsOn: - PipelineRoleDefaultPolicy - - PipelineRole + - PublishRoleDefaultPolicy + - PipelineBuildCodePipelineActionRoleDefaultPolicy + - PipelineDeployCodePipelineActionRoleDefaultPolicy + - ContainerImageBuildServerRoleDefaultPolicy PipelineBuildCodePipelineActionRole: Type: AWS::IAM::Role Properties: @@ -466,7 +801,7 @@ Resources: Resource: !GetAtt BuildProject.Arn Version: '2012-10-17' PolicyName: PipelineBuildCodePipelineActionRoleDefaultPolicy - Roles: !Ref PipelineBuildCodePipelineActionRole + Roles: [ !Ref PipelineBuildCodePipelineActionRole ] PipelineDeployCodePipelineActionRole: Type: AWS::IAM::Role Properties: @@ -490,8 +825,8 @@ Resources: Resource: !Sub 'arn:${AWS::Partition}:codebuild:${AWS::Region}:${AWS::AccountId}:project/Deploy*' Version: '2012-10-17' PolicyName: PipelineDeployCodePipelineActionRoleDefaultPolicy - Roles: !Ref PipelineDeployCodePipelineActionRole + Roles: [ !Ref PipelineDeployCodePipelineActionRole ] Outputs: PipelineEndpoint: Description: The URL to access the pipeline - Value: !Sub 'https://${AWS::Region}.console.aws.amazon.com/codesuite/codepipeline/pipelines/${Pipeline}/view?region=${AWS::Region}' + Value: !Sub https://${AWS::Region}.console.aws.amazon.com/codesuite/codepipeline/pipelines/${Pipeline}/view?region=${AWS::Region}' diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/schema/schema.yaml b/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/schema/schema.yaml index 6b3f7a1..c043ca7 100644 --- a/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/schema/schema.yaml +++ b/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/schema/schema.yaml @@ -1,18 +1,18 @@ schema: format: openapi: "3.0.0" - service_input_type: "PrivateServiceInput" + service_input_type: "LoadBalancedServiceInput" pipeline_input_type: "PipelineInputs" types: - PrivateServiceInput: + LoadBalancedServiceInput: type: object - description: "Input properties for a Private Fargate service" + description: "Input properties for a loadbalanced Fargate service" properties: port: type: number description: "The port to route traffic to" - default: 8080 + default: 80 minimum: 0 maximum: 65535 desired_count: @@ -23,11 +23,12 @@ schema: task_size: type: string description: "The size of the task you want to run" - enum: ["x-small", "small", "medium", "large", "x-large"] - default: "x-small" + enum: [ "medium", "large", "x-large"] + default: "medium" image: type: string description: "The name/url of the container image" + default: "mcr.microsoft.com/dotnet/framework/samples:aspnetapp" minLength: 1 maxLength: 200 service_discovery_name: @@ -36,22 +37,41 @@ schema: minLength: 3 maxLength: 24 required: - - image - service_discovery_name PipelineInputs: type: object description: "Pipeline input properties" properties: + cluster_operating_system_family: + type: string + description: "The operating system used for the ECS Task Definition" + default: WINDOWS_SERVER_2019_CORE + enum: ['WINDOWS_SERVER_2019_CORE', 'WINDOWS_SERVER_2019_FULL', 'WINDOWS_SERVER_2022_CORE', 'WINDOWS_SERVER_2022_FULL'] + build_server_ami_id: + type: string + description: SSM Parameter expression to use to retrieve the AMI ID for the build server. Must be compatible with operating system version used by ECS cluster. + default: /aws/service/ami-windows-latest/Windows_Server-2019-English-Core-ECS_Optimized/image_id + build_server_instance_type: + type: string + description: "Instance type used for the EC2 Instance that serves as the build server." + default: t2.medium + enum: [t2.small, t2.medium, t2.large, + t3.small, t3.medium, t3.large, + t3a.small, t3a.medium, t3a.large ] + build_server_volume_size: + type: number + description: "Volume size in GiBs used when provisioning the build server." + default: 30 + minimum: 4 + maximum: 1024 + build_server_volume_type: + type: string + description: "Volume type used when provisioning the build server." + default: gp3 + enum: [ gp3, gp2 ] dockerfile: type: string description: "The location of the Dockerfile to build" default: "Dockerfile" minLength: 1 - maxLength: 100 - unit_test_command: - type: string - description: "The command to run to unit test the application code" - default: "echo 'add your unit test command here'" - minLength: 1 - maxLength: 200 \ No newline at end of file From 5fd6f3c6a93cc0e43ee926f30f3cd213051b77ea Mon Sep 17 00:00:00 2001 From: Carlos Santos Date: Thu, 31 Mar 2022 13:31:21 -0700 Subject: [PATCH 11/20] feat: Private .NET Fx Fargate Svc - Sync'd private and lb service templates - Corrected private template's schema --- .../instance_infrastructure/cloudformation.yaml | 15 ++++++--------- .../private-fargate-svc/v1/schema/schema.yaml | 4 ++-- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/instance_infrastructure/cloudformation.yaml b/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/instance_infrastructure/cloudformation.yaml index a7afd5c..358c9a7 100644 --- a/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/instance_infrastructure/cloudformation.yaml +++ b/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/instance_infrastructure/cloudformation.yaml @@ -5,12 +5,6 @@ Mappings: Environment: Name: '{{ environment.name}}' TaskSize: - x-small: - cpu: 256 - memory: 512 - small: - cpu: 512 - memory: 1024 medium: cpu: 1024 memory: 2048 @@ -39,7 +33,6 @@ Resources: LogGroup: Type: AWS::Logs::LogGroup Properties: - #TODO: Should this include environment name? LogGroupName: '{{service.name}}/{{service_instance.name}}' # The task definition. This is a simple metadata description of what @@ -51,9 +44,11 @@ Resources: Cpu: !FindInMap [TaskSize, {{service_instance.inputs.task_size}}, cpu] Memory: !FindInMap [TaskSize, {{service_instance.inputs.task_size}}, memory] NetworkMode: awsvpc - # TODO: Add Windows Requirement RequiresCompatibilities: - FARGATE + RuntimePlatform: + CpuArchitecture: 'X86_64' + OperatingSystemFamily: '{{service_instance.inputs.cluster_operating_system_family}}' ExecutionRoleArn: '{{environment.outputs.ECSTaskExecutionRole}}' TaskRoleArn: !Ref 'AWS::NoValue' ContainerDefinitions: @@ -81,8 +76,10 @@ Resources: Properties: ServiceName: '{{service.name}}_{{service_instance.name}}' Cluster: '{{environment.outputs.ClusterName}}' - # TODO: Add Windows Requirement LaunchType: FARGATE + DeploymentConfiguration: + MaximumPercent: 200 + MinimumHealthyPercent: 75 DesiredCount: '{{service_instance.inputs.desired_count}}' NetworkConfiguration: AwsvpcConfiguration: diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/schema/schema.yaml b/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/schema/schema.yaml index c043ca7..bee4ef1 100644 --- a/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/schema/schema.yaml +++ b/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/schema/schema.yaml @@ -1,11 +1,11 @@ schema: format: openapi: "3.0.0" - service_input_type: "LoadBalancedServiceInput" + service_input_type: "PrivateServiceInput" pipeline_input_type: "PipelineInputs" types: - LoadBalancedServiceInput: + PrivateServiceInput: type: object description: "Input properties for a loadbalanced Fargate service" properties: From e1e2d7865c950574945779d5895338da7bafd846 Mon Sep 17 00:00:00 2001 From: Carlos Santos Date: Thu, 31 Mar 2022 13:33:40 -0700 Subject: [PATCH 12/20] doc: Corrected svc input parameter descn --- .../microservices-svc/private-fargate-svc/v1/schema/schema.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/schema/schema.yaml b/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/schema/schema.yaml index bee4ef1..e81149c 100644 --- a/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/schema/schema.yaml +++ b/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/schema/schema.yaml @@ -7,7 +7,7 @@ schema: types: PrivateServiceInput: type: object - description: "Input properties for a loadbalanced Fargate service" + description: "Input properties for a Private Fargate service" properties: port: type: number From e099e8195c3332724b7fde417b17d088152f0b76 Mon Sep 17 00:00:00 2001 From: Carlos Santos Date: Thu, 31 Mar 2022 13:55:43 -0700 Subject: [PATCH 13/20] fix: Corrected location of OS family param --- .../loadbalanced-public-svc/v1/schema/schema.yaml | 10 +++++----- .../private-fargate-svc/v1/schema/schema.yaml | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/schema/schema.yaml b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/schema/schema.yaml index c043ca7..526fa8d 100644 --- a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/schema/schema.yaml +++ b/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/schema/schema.yaml @@ -9,6 +9,11 @@ schema: type: object description: "Input properties for a loadbalanced Fargate service" properties: + cluster_operating_system_family: + type: string + description: "The operating system used for the ECS Task Definition" + default: WINDOWS_SERVER_2019_CORE + enum: ['WINDOWS_SERVER_2019_CORE', 'WINDOWS_SERVER_2019_FULL', 'WINDOWS_SERVER_2022_CORE', 'WINDOWS_SERVER_2022_FULL'] port: type: number description: "The port to route traffic to" @@ -43,11 +48,6 @@ schema: type: object description: "Pipeline input properties" properties: - cluster_operating_system_family: - type: string - description: "The operating system used for the ECS Task Definition" - default: WINDOWS_SERVER_2019_CORE - enum: ['WINDOWS_SERVER_2019_CORE', 'WINDOWS_SERVER_2019_FULL', 'WINDOWS_SERVER_2022_CORE', 'WINDOWS_SERVER_2022_FULL'] build_server_ami_id: type: string description: SSM Parameter expression to use to retrieve the AMI ID for the build server. Must be compatible with operating system version used by ECS cluster. diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/schema/schema.yaml b/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/schema/schema.yaml index e81149c..bcdbe01 100644 --- a/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/schema/schema.yaml +++ b/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/schema/schema.yaml @@ -9,6 +9,11 @@ schema: type: object description: "Input properties for a Private Fargate service" properties: + cluster_operating_system_family: + type: string + description: "The operating system used for the ECS Task Definition" + default: WINDOWS_SERVER_2019_CORE + enum: ['WINDOWS_SERVER_2019_CORE', 'WINDOWS_SERVER_2019_FULL', 'WINDOWS_SERVER_2022_CORE', 'WINDOWS_SERVER_2022_FULL'] port: type: number description: "The port to route traffic to" @@ -43,11 +48,6 @@ schema: type: object description: "Pipeline input properties" properties: - cluster_operating_system_family: - type: string - description: "The operating system used for the ECS Task Definition" - default: WINDOWS_SERVER_2019_CORE - enum: ['WINDOWS_SERVER_2019_CORE', 'WINDOWS_SERVER_2019_FULL', 'WINDOWS_SERVER_2022_CORE', 'WINDOWS_SERVER_2022_FULL'] build_server_ami_id: type: string description: SSM Parameter expression to use to retrieve the AMI ID for the build server. Must be compatible with operating system version used by ECS cluster. From 7af17735a70ddc1734470a06eec97b670bf3cb82 Mon Sep 17 00:00:00 2001 From: Carlos Santos Date: Fri, 1 Apr 2022 07:44:19 -0700 Subject: [PATCH 14/20] fix: Updated spec file to match templates --- .../specs/svc-private-spec.yaml | 2 +- .../specs/svc-public-spec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/public-private-fargate-microservices-dotnetfx/specs/svc-private-spec.yaml b/public-private-fargate-microservices-dotnetfx/specs/svc-private-spec.yaml index 52ce57e..0953fe0 100644 --- a/public-private-fargate-microservices-dotnetfx/specs/svc-private-spec.yaml +++ b/public-private-fargate-microservices-dotnetfx/specs/svc-private-spec.yaml @@ -1,7 +1,7 @@ proton: ServiceSpec pipeline: - unit_test_command: "ls" + build_server_instance_type: "t3.medium" instances: - name: "backend-dev" diff --git a/public-private-fargate-microservices-dotnetfx/specs/svc-public-spec.yaml b/public-private-fargate-microservices-dotnetfx/specs/svc-public-spec.yaml index dd6f2a8..28475da 100644 --- a/public-private-fargate-microservices-dotnetfx/specs/svc-public-spec.yaml +++ b/public-private-fargate-microservices-dotnetfx/specs/svc-public-spec.yaml @@ -1,7 +1,7 @@ proton: ServiceSpec pipeline: - unit_test_command: "ls" + build_server_instance_type: "t3.medium" instances: - name: "frontend-dev" From 338a8d6c13bec7a6caa46456cb2903a708fd2023 Mon Sep 17 00:00:00 2001 From: Carlos Santos Date: Fri, 1 Apr 2022 09:25:25 -0700 Subject: [PATCH 15/20] feat: Load Balanced Fargate .NET Fx Templates - Changed to use only the load balancer version for .NET Fx assuming that customers would move existing workloads to Windows containers as is, typically a three tier app. They wouldn't need the private version of a Fargate service since most .NET Fx workloads are monoliths and the private service implied a decomposition to microservices. We found it unlikely that customers would stick with .NET Fx if they were decomposing their application. --- .../README.md | 0 .../v1/infrastructure/cloudformation.yaml | 0 .../v1/infrastructure/manifest.yaml | 0 .../v1/schema/schema.yaml | 0 .../v1/.compatible-envs | 0 .../cloudformation.yaml | 21 +- .../v1/instance_infrastructure/manifest.yaml | 0 .../cloudformation.yaml | 0 .../v1/pipeline_infrastructure/manifest.yaml | 0 .../v1/schema/schema.yaml | 0 .../proton-service-assume-policy.json | 0 .../specs/env-spec.yaml | 0 .../specs/svc-spec.yaml | 0 .../private-fargate-svc/v1/.compatible-envs | 1 - .../cloudformation.yaml | 102 --- .../v1/instance_infrastructure/manifest.yaml | 5 - .../cloudformation.yaml | 832 ------------------ .../v1/pipeline_infrastructure/manifest.yaml | 5 - .../private-fargate-svc/v1/schema/schema.yaml | 77 -- .../specs/svc-private-spec.yaml | 13 - 20 files changed, 1 insertion(+), 1055 deletions(-) rename {public-private-fargate-microservices-dotnetfx => loadbalanced-fargate-dotnetfx-svc}/README.md (100%) rename {public-private-fargate-microservices-dotnetfx/microservices-env => loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-env}/v1/infrastructure/cloudformation.yaml (100%) rename {public-private-fargate-microservices-dotnetfx/microservices-env => loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-env}/v1/infrastructure/manifest.yaml (100%) rename {public-private-fargate-microservices-dotnetfx/microservices-env => loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-env}/v1/schema/schema.yaml (100%) rename {public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc => loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-svc}/v1/.compatible-envs (100%) rename {public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc => loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-svc}/v1/instance_infrastructure/cloudformation.yaml (94%) rename {public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc => loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-svc}/v1/instance_infrastructure/manifest.yaml (100%) rename {public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc => loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-svc}/v1/pipeline_infrastructure/cloudformation.yaml (100%) rename {public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc => loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-svc}/v1/pipeline_infrastructure/manifest.yaml (100%) rename {public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc => loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-svc}/v1/schema/schema.yaml (100%) rename {public-private-fargate-microservices-dotnetfx => loadbalanced-fargate-dotnetfx-svc}/policies/proton-service-assume-policy.json (100%) rename {public-private-fargate-microservices-dotnetfx => loadbalanced-fargate-dotnetfx-svc}/specs/env-spec.yaml (100%) rename public-private-fargate-microservices-dotnetfx/specs/svc-public-spec.yaml => loadbalanced-fargate-dotnetfx-svc/specs/svc-spec.yaml (100%) delete mode 100644 public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/.compatible-envs delete mode 100644 public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/instance_infrastructure/cloudformation.yaml delete mode 100644 public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/instance_infrastructure/manifest.yaml delete mode 100644 public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/pipeline_infrastructure/cloudformation.yaml delete mode 100644 public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/pipeline_infrastructure/manifest.yaml delete mode 100644 public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/schema/schema.yaml delete mode 100644 public-private-fargate-microservices-dotnetfx/specs/svc-private-spec.yaml diff --git a/public-private-fargate-microservices-dotnetfx/README.md b/loadbalanced-fargate-dotnetfx-svc/README.md similarity index 100% rename from public-private-fargate-microservices-dotnetfx/README.md rename to loadbalanced-fargate-dotnetfx-svc/README.md diff --git a/public-private-fargate-microservices-dotnetfx/microservices-env/v1/infrastructure/cloudformation.yaml b/loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-env/v1/infrastructure/cloudformation.yaml similarity index 100% rename from public-private-fargate-microservices-dotnetfx/microservices-env/v1/infrastructure/cloudformation.yaml rename to loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-env/v1/infrastructure/cloudformation.yaml diff --git a/public-private-fargate-microservices-dotnetfx/microservices-env/v1/infrastructure/manifest.yaml b/loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-env/v1/infrastructure/manifest.yaml similarity index 100% rename from public-private-fargate-microservices-dotnetfx/microservices-env/v1/infrastructure/manifest.yaml rename to loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-env/v1/infrastructure/manifest.yaml diff --git a/public-private-fargate-microservices-dotnetfx/microservices-env/v1/schema/schema.yaml b/loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-env/v1/schema/schema.yaml similarity index 100% rename from public-private-fargate-microservices-dotnetfx/microservices-env/v1/schema/schema.yaml rename to loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-env/v1/schema/schema.yaml diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/.compatible-envs b/loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-svc/v1/.compatible-envs similarity index 100% rename from public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/.compatible-envs rename to loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-svc/v1/.compatible-envs diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/instance_infrastructure/cloudformation.yaml b/loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-svc/v1/instance_infrastructure/cloudformation.yaml similarity index 94% rename from public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/instance_infrastructure/cloudformation.yaml rename to loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-svc/v1/instance_infrastructure/cloudformation.yaml index f3c5970..3622368 100644 --- a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/instance_infrastructure/cloudformation.yaml +++ b/loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-svc/v1/instance_infrastructure/cloudformation.yaml @@ -15,21 +15,6 @@ Mappings: cpu: 4096 memory: 8192 Resources: - # Register service in ServiceDiscovery Service - DiscoveryService: - Type: AWS::ServiceDiscovery::Service - Properties: - Description: Discovery Service for the Demo Application - DnsConfig: - RoutingPolicy: MULTIVALUE - DnsRecords: - - TTL: 60 - Type: A - HealthCheckCustomConfig: - FailureThreshold: 1 - Name: '{{service_instance.inputs.service_discovery_name}}' - NamespaceId: '{{environment.outputs.PrivateNamespace}}' - # A log group for storing the stdout logs from this service's containers LogGroup: Type: AWS::Logs::LogGroup @@ -92,8 +77,6 @@ Resources: - '{{environment.outputs.PublicSubnetOne}}' - '{{environment.outputs.PublicSubnetTwo}}' TaskDefinition: !Ref 'TaskDefinition' - ServiceRegistries: - - RegistryArn: !GetAtt DiscoveryService.Arn LoadBalancers: - ContainerName: '{{service_instance.name}}' ContainerPort: {{service_instance.inputs.port}} @@ -297,6 +280,4 @@ Outputs: ServiceEndpoint: Description: The URL to access the service Value: !Sub 'http://${PublicLoadBalancer.DNSName}' - ServiceDiscovery: - Description: The registered service discovery Service Id - Value: !Ref DiscoveryService + diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/instance_infrastructure/manifest.yaml b/loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-svc/v1/instance_infrastructure/manifest.yaml similarity index 100% rename from public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/instance_infrastructure/manifest.yaml rename to loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-svc/v1/instance_infrastructure/manifest.yaml diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/pipeline_infrastructure/cloudformation.yaml b/loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-svc/v1/pipeline_infrastructure/cloudformation.yaml similarity index 100% rename from public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/pipeline_infrastructure/cloudformation.yaml rename to loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-svc/v1/pipeline_infrastructure/cloudformation.yaml diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/pipeline_infrastructure/manifest.yaml b/loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-svc/v1/pipeline_infrastructure/manifest.yaml similarity index 100% rename from public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/pipeline_infrastructure/manifest.yaml rename to loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-svc/v1/pipeline_infrastructure/manifest.yaml diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/schema/schema.yaml b/loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-svc/v1/schema/schema.yaml similarity index 100% rename from public-private-fargate-microservices-dotnetfx/microservices-svc/loadbalanced-public-svc/v1/schema/schema.yaml rename to loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-svc/v1/schema/schema.yaml diff --git a/public-private-fargate-microservices-dotnetfx/policies/proton-service-assume-policy.json b/loadbalanced-fargate-dotnetfx-svc/policies/proton-service-assume-policy.json similarity index 100% rename from public-private-fargate-microservices-dotnetfx/policies/proton-service-assume-policy.json rename to loadbalanced-fargate-dotnetfx-svc/policies/proton-service-assume-policy.json diff --git a/public-private-fargate-microservices-dotnetfx/specs/env-spec.yaml b/loadbalanced-fargate-dotnetfx-svc/specs/env-spec.yaml similarity index 100% rename from public-private-fargate-microservices-dotnetfx/specs/env-spec.yaml rename to loadbalanced-fargate-dotnetfx-svc/specs/env-spec.yaml diff --git a/public-private-fargate-microservices-dotnetfx/specs/svc-public-spec.yaml b/loadbalanced-fargate-dotnetfx-svc/specs/svc-spec.yaml similarity index 100% rename from public-private-fargate-microservices-dotnetfx/specs/svc-public-spec.yaml rename to loadbalanced-fargate-dotnetfx-svc/specs/svc-spec.yaml diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/.compatible-envs b/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/.compatible-envs deleted file mode 100644 index 4ef64cc..0000000 --- a/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/.compatible-envs +++ /dev/null @@ -1 +0,0 @@ -microservices-env:1 diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/instance_infrastructure/cloudformation.yaml b/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/instance_infrastructure/cloudformation.yaml deleted file mode 100644 index 358c9a7..0000000 --- a/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/instance_infrastructure/cloudformation.yaml +++ /dev/null @@ -1,102 +0,0 @@ -AWSTemplateFormatVersion: '2010-09-09' -Description: Deploy a backend service on AWS Fargate, hosted in a private subnet, and accessible via Service Discovery. -Mappings: - EnvironmentNameConfig: - Environment: - Name: '{{ environment.name}}' - TaskSize: - medium: - cpu: 1024 - memory: 2048 - large: - cpu: 2048 - memory: 4096 - x-large: - cpu: 4096 - memory: 8192 -Resources: - # Register service in ServiceDiscovery Service - DiscoveryService: - Type: AWS::ServiceDiscovery::Service - Properties: - Description: Discovery Service for the Demo Application - DnsConfig: - RoutingPolicy: MULTIVALUE - DnsRecords: - - TTL: 60 - Type: A - HealthCheckCustomConfig: - FailureThreshold: 1 - Name: '{{service_instance.inputs.service_discovery_name}}' - NamespaceId: '{{environment.outputs.PrivateNamespace}}' - # A log group for storing the stdout logs from this service's containers - LogGroup: - Type: AWS::Logs::LogGroup - Properties: - LogGroupName: '{{service.name}}/{{service_instance.name}}' - - # The task definition. This is a simple metadata description of what - # container to run, and what resource requirements it has. - TaskDefinition: - Type: AWS::ECS::TaskDefinition - Properties: - Family: '{{service.name}}_{{service_instance.name}}' - Cpu: !FindInMap [TaskSize, {{service_instance.inputs.task_size}}, cpu] - Memory: !FindInMap [TaskSize, {{service_instance.inputs.task_size}}, memory] - NetworkMode: awsvpc - RequiresCompatibilities: - - FARGATE - RuntimePlatform: - CpuArchitecture: 'X86_64' - OperatingSystemFamily: '{{service_instance.inputs.cluster_operating_system_family}}' - ExecutionRoleArn: '{{environment.outputs.ECSTaskExecutionRole}}' - TaskRoleArn: !Ref 'AWS::NoValue' - ContainerDefinitions: - - Name: '{{service_instance.name}}' - Cpu: !FindInMap [TaskSize, {{service_instance.inputs.task_size}}, cpu] - Memory: !FindInMap [TaskSize, {{service_instance.inputs.task_size}}, memory] - Image: '{{service_instance.inputs.image}}' - PortMappings: - - ContainerPort: '{{service_instance.inputs.port}}' - LogConfiguration: - LogDriver: 'awslogs' - Options: - awslogs-group: '{{service.name}}/{{service_instance.name}}' - awslogs-region: !Ref 'AWS::Region' - awslogs-stream-prefix: '{{service.name}}/{{service_instance.name}}' - Tags: - - Key: Name - Value: !FindInMap ['EnvironmentNameConfig', 'Environment', 'Name'] - - # The service_instance.inputs. The service is a resource which allows you to run multiple - # copies of a type of task, and gather up their logs and metrics, as well - # as monitor the number of running tasks and replace any that have crashed - Service: - Type: AWS::ECS::Service - Properties: - ServiceName: '{{service.name}}_{{service_instance.name}}' - Cluster: '{{environment.outputs.ClusterName}}' - LaunchType: FARGATE - DeploymentConfiguration: - MaximumPercent: 200 - MinimumHealthyPercent: 75 - DesiredCount: '{{service_instance.inputs.desired_count}}' - NetworkConfiguration: - AwsvpcConfiguration: - AssignPublicIp: DISABLED - SecurityGroups: - - '{{environment.outputs.ContainerSecurityGroup}}' - Subnets: - - '{{environment.outputs.PrivateSubnetOne}}' - - '{{environment.outputs.PrivateSubnetTwo}}' - TaskDefinition: !Ref 'TaskDefinition' - ServiceRegistries: - - RegistryArn: !GetAtt DiscoveryService.Arn - Tags: - - Key: Name - Value: !FindInMap ['EnvironmentNameConfig', 'Environment', 'Name'] - -Outputs: - ServiceDiscovery: - Description: The registered service discovery Service Id - Value: !Ref DiscoveryService diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/instance_infrastructure/manifest.yaml b/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/instance_infrastructure/manifest.yaml deleted file mode 100644 index eed587b..0000000 --- a/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/instance_infrastructure/manifest.yaml +++ /dev/null @@ -1,5 +0,0 @@ -infrastructure: - templates: - - file: "cloudformation.yaml" - rendering_engine: jinja - template_language: cloudformation diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/pipeline_infrastructure/cloudformation.yaml b/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/pipeline_infrastructure/cloudformation.yaml deleted file mode 100644 index 80cad89..0000000 --- a/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/pipeline_infrastructure/cloudformation.yaml +++ /dev/null @@ -1,832 +0,0 @@ -Mappings: - BuildConfig: - BuildServer: - InstanceType: '{{pipeline.inputs.build_server_instance_type}}' - VolumeType: '{{pipeline.inputs.build_server_volume_type}}' - VolumeSize: {{pipeline.inputs.build_server_volume_size}} - ImageBuild: - Dockerfile: '{{pipeline.inputs.dockerfile}}' -Resources: - ECRRepo: - Type: AWS::ECR::Repository - DeletionPolicy: Retain - UpdateReplacePolicy: Retain - Properties: - # This policy allows environment accounts to get the image from ECRRepo in the management account - RepositoryPolicyText: - Version: '2012-10-17' - Statement: - - Sid: AllowPull - Effect: Allow - Principal: - AWS: - {% for service_instance in service_instances %} - - "arn:aws:iam::{{service_instance.environment.account_id}}:root" - {% endfor %} - Action: - - ecr:GetAuthorizationToken - - ecr:BatchCheckLayerAvailability - - ecr:GetDownloadUrlForLayer - - ecr:BatchGetImage - ContainerImageBuildServerRole: - Type : AWS::IAM::Role - Properties: - Path: / - ManagedPolicyArns: - - !Sub 'arn:${AWS::Partition}:iam::aws:policy/AmazonSSMManagedInstanceCore' - - !Sub 'arn:${AWS::Partition}:iam::aws:policy/CloudWatchAgentServerPolicy' - AssumeRolePolicyDocument: - Version: "2012-10-17" - Statement: - - Effect: "Allow" - Principal: - Service: - - "ec2.amazonaws.com" - - "ssm.amazonaws.com" - Action: "sts:AssumeRole" - ContainerImageBuildServerRoleDefaultPolicy: - Type: AWS::IAM::Policy - Properties: - PolicyName: ContainerImageBuildServerRoleDefaultPolicy - Roles: [!Ref ContainerImageBuildServerRole ] - PolicyDocument: - Version: '2012-10-17' - Statement: - - Action: s3:GetObject - Resource: !Sub arn:${AWS::Partition}:s3:::${PipelineArtifactsBucket}/* - Effect: Allow - - Action: - - kms:Decrypt - - kms:Encrypt - - kms:ReEncrypt* - - kms:GenerateDataKey* - Effect: Allow - Resource: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn - - Action: - - "ecr:GetAuthorizationToken" - Resource: "*" - Effect: Allow - - Action: - - "ecr:BatchCheckLayerAvailability" - - "ecr:BatchGetImage" - - "ecr:CompleteLayerUpload" - - "ecr:DescribeImages" - - "ecr:DescribeImageScanFindings" - - "ecr:DescribeRepositories" - - "ecr:GetDownloadUrlForLayer" - - "ecr:GetLifecyclePolicy" - - "ecr:GetLifecyclePolicyPreview" - - "ecr:GetRepositoryPolicy" - - "ecr:InitiateLayerUpload" - - "ecr:ListImages" - - "ecr:ListTagsForResource" - - "ecr:PutImage" - - "ecr:UploadLayerPart" - Resource: !GetAtt ECRRepo.Arn - Effect: Allow - ContainerImageBuildServerInstanceProfile: - Type: "AWS::IAM::InstanceProfile" - Properties: - Roles: - - !Ref ContainerImageBuildServerRole - BuildDotNetContainerDocument: - Type: AWS::SSM::Document - Properties: - DocumentType: Automation - Content: - schemaVersion: "0.3" - description: "Create a .NET Framework Container for CodeBuild" - parameters: - AmiId: - type: String - default: "{{'{{'}}ssm:{{pipeline.inputs.build_server_ami_id}}{{'}}'}}" - description: The Windows Server AMI to use for the build server must match version used by ECS cluster. - DockerFile: - type: String - default: !FindInMap ['BuildConfig', 'ImageBuild', 'Dockerfile'] - description: Location of the Dockerfile relative to repository's root folder - InstanceType: - type: String - description: (Optional) The instance type of the EC2 instance to be launched. - default: !FindInMap ['BuildConfig', 'BuildServer', 'InstanceType'] - IamInstanceProfileName: - type: String - description: (Required) The IAM instance profile to attach to the build instance. - default: !Ref ContainerImageBuildServerInstanceProfile - InstanceVolumeSize: - type: String - description: (Required) Desired volume size (GiB) of the build instance. - default: !FindInMap ['BuildConfig', 'BuildServer', 'VolumeSize'] - InstanceVolumeType: - type: String - description: (Required) Desired volume type of the build instance. - default: !FindInMap ['BuildConfig', 'BuildServer', 'VolumeType'] - PipelineBucketName: - type: String - description: (Required) Bucket that build artifact is stored in. - default: !Ref PipelineArtifactsBucket - SourceArtifactS3Path: - type: String - description: (Required) Build artifact key. - EcrRepoName: - default: !Ref ECRRepo - description: "ECR Repo Name" - type: "String" - ImageTag: - type: String - description: (Optional) Tag for container image. - default: latest - BuildLogGroupName: - type: String - description: (Optional) CloudWatch Log Group Name for build. - mainSteps: - {% raw %} - - name: createNewInstance - action: 'aws:runInstances' - maxAttempts: 3 - timeoutSeconds: 1200 - onFailure: Abort - inputs: - ImageId: '{{ AmiId }}' - InstanceType: '{{ InstanceType }}' - MinInstanceCount: 1 - MaxInstanceCount: 1 - IamInstanceProfileName: '{{ IamInstanceProfileName }}' - BlockDeviceMappings: - - DeviceName: /dev/xvdb - Ebs: - VolumeSize: '{{ InstanceVolumeSize }}' - VolumeType: '{{ InstanceVolumeType }}' - TagSpecifications: - - ResourceType: instance - Tags: - - Key: tag:aws:cloudformation:stack-id - Value: !Ref AWS::StackId - - Key: tag:aws:cloudformation:stack-name - Value: !Ref AWS::StackName - - Key: Name - Value: dotnetfx-container-build - nextStep: getInstance - - name: getInstance - action: 'aws:executeAwsApi' - maxAttempts: 2 - onFailure: Abort - inputs: - Service: ec2 - Api: DescribeInstances - InstanceIds: - - '{{ createNewInstance.InstanceIds }}' - outputs: - - Name: InstanceId - Selector: '$.Reservations[0].Instances[0].InstanceId' - Type: String - isCritical: 'true' - nextStep: waitForInstanceToBeReady - - name: waitForInstanceToBeReady - action: 'aws:waitForAwsResourceProperty' - onFailure: 'step:terminateInstance' - timeoutSeconds: 600 - maxAttempts: 2 - inputs: - Service: ec2 - Api: DescribeInstanceStatus - InstanceIds: - - '{{ getInstance.InstanceId }}' - PropertySelector: '$.InstanceStatuses[0].InstanceStatus.Details[0].Status' - DesiredValues: - - passed - isCritical: 'false' - nextStep: waitForSSMAgentOnline - - name: waitForSSMAgentOnline - action: 'aws:waitForAwsResourceProperty' - onFailure: 'step:terminateInstance' - timeoutSeconds: 600 - inputs: - Service: ssm - Api: DescribeInstanceInformation - InstanceInformationFilterList: - - key: InstanceIds - valueSet: - - '{{ getInstance.InstanceId }}' - PropertySelector: '$.InstanceInformationList[0].PingStatus' - DesiredValues: - - Online - isCritical: 'true' - nextStep: CreateDockerImage - - name: CreateDockerImage - action: 'aws:runCommand' - onFailure: 'step:terminateInstance' - timeoutSeconds: 7200 - inputs: - DocumentName: AWS-RunPowerShellScript - InstanceIds: - - '{{ getInstance.InstanceId }}' - Parameters: - commands: | - $ErrorActionPreference = "Stop" - - Write-Host "*****Downloading from S3...*****" - - New-Item -Name tmp -ItemType directory -Force | out-null - New-Item -Name tmp\src -ItemType directory -Force | out-null - - cd .\tmp - - $tmpFolder = $(Get-Location).Path - $srcFolder = "$tmpFolder\src" - $key = "{{SourceArtifactS3Path}}" - $srcFileName = "$(Split-Path $key -Leaf)" - - # Expand-Archive requires '.zip' file extension so add it if necessary - if ([System.IO.Path]::GetExtension($srcFileName) -ne ".zip") { - $srcFileName += ".zip" - } - - Read-S3Object -BucketName "{{PipelineBucketName}}" -Key $key -File $srcFileName - Expand-Archive -Path "$tmpFolder\$srcFileName" -DestinationPath "$srcFolder" -Force - - Write-Host "*****Building Docker image...*****" - - $instanceInfo = (Invoke-RestMethod -Method Get -Uri http://169.254.169.254/latest/dynamic/instance-identity/document) - $repoUri = $instanceInfo.accountId + '.dkr.ecr.' + $instanceInfo.region + '.amazonaws.com/{{EcrRepoName}}' - $latestUri = "$($repoUri):latest" - $hasCustomTag = $False - $buildArgs = @("-t", $latestUri) - $customTag = "{{ImageTag}}" - - if ($customTag -and $($customTag -ne "latest")) { - $hasCustomTag = $True - $uriWithTag = "$($repoUri):$customTag" - $buildArgs += @("-t", $uriWithTag) - } - - Write-Host "Docker Build Args are '$buildArgs'" - - cd $srcFolder - docker build $buildArgs $srcFolder\ - - if ($LASTEXITCODE -ne 0) { - throw ("'docker build $buildArgs $srcFolder\' execution failed with exit code $LASTEXITCODE.") - } - - Write-Host "*****Pushing Docker image to ECR...*****" - - Invoke-Expression –Command (Get-ECRLoginCommand –Region $region).Command - docker push $repoUri --all-tags - - if ($LASTEXITCODE -ne 0) { - throw "'docker push $repoUri --all-tags' execution failed with exit code $LASTEXITCODE." - } - executionTimeout: '7200' - CloudWatchOutputConfig: - CloudWatchLogGroupName: '{{ BuildLogGroupName }}' - CloudWatchOutputEnabled: true - isCritical: 'true' - nextStep: terminateInstance - - name: terminateInstance - action: 'aws:changeInstanceState' - maxAttempts: 3 - onFailure: Continue - inputs: - InstanceIds: - - '{{getInstance.InstanceId}}' - DesiredState: terminated - isCritical: 'true' - isEnd: 'true' - {% endraw %} - BuildProject: - Type: AWS::CodeBuild::Project - Properties: - Artifacts: - Type: CODEPIPELINE - Packaging: NONE - Environment: - ComputeType: BUILD_GENERAL1_SMALL - Image: aws/codebuild/amazonlinux2-x86_64-standard:3.0 - PrivilegedMode: false - Type: LINUX_CONTAINER - EnvironmentVariables: - - Name: repo_name - Type: PLAINTEXT - Value: !Ref ECRRepo - - Name: service_name - Type: PLAINTEXT - Value: '{{service.name}}' - ServiceRole: !GetAtt PublishRole.Arn - LogsConfig: - CloudWatchLogs: - GroupName: '{{service.name}}/pipeline' - Status: 'ENABLED' - StreamName: 'build' - Source: - InsecureSsl: false - BuildSpec: !Sub | - version: "0.2" - env: - variables: - DOCUMENT_NAME: ${BuildDotNetContainerDocument} - ECR_REPO_URI: ${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/${ECRRepo} - LOG_GROUP_NAME: {{service.name}}/pipeline - phases: - install: - runtime-versions: - docker: 18 - commands: - - pip3 install --upgrade --user awscli - - echo 'f6bd1536a743ab170b35c94ed4c7c4479763356bd543af5d391122f4af852460 yq_linux_amd64' > yq_linux_amd64.sha - - wget https://github.com/mikefarah/yq/releases/download/3.4.0/yq_linux_amd64 - - sha256sum -c yq_linux_amd64.sha - - mv yq_linux_amd64 /usr/bin/yq - - chmod +x /usr/bin/yq - pre_build: - commands: - - BUILD_ID=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-8) - - IMAGE_TAG=build-$BUILD_ID - - SRC_ARTIFACT_FULL_S3_PATH=${!CODEBUILD_SOURCE_VERSION#*"s3:::"} - - SRC_ARTIFACT_S3_PATH=${!SRC_ARTIFACT_FULL_S3_PATH#*"/"} - - SRC_ARTIFACT_BUCKET_NAME=$(echo $SRC_ARTIFACT_FULL_S3_PATH | cut -c 1-$((${!#SRC_ARTIFACT_FULL_S3_PATH} - ${!#SRC_ARTIFACT_S3_PATH} - 1))) - - echo SRC_ARTIFACT_FULL_S3_PATH=$SRC_ARTIFACT_FULL_S3_PATH - - echo SRC_ARTIFACT_S3_PATH=$SRC_ARTIFACT_S3_PATH - - echo SRC_ARTIFACT_BUCKET_NAME=$SRC_ARTIFACT_BUCKET_NAME - build: - commands: - - echo Starting automation execution using document $DOCUMENT_NAME... - - echo Logs are stored under CloudWatch Log Group $LOG_GROUP_NAME... - - EXECUTION_ID=$(aws ssm start-automation-execution --document-name $DOCUMENT_NAME --parameters BuildLogGroupName=$LOG_GROUP_NAME,DockerFile={{ pipeline.inputs.dockerfile }},ImageTag=$IMAGE_TAG,PipelineBucketName=$SRC_ARTIFACT_BUCKET_NAME,SourceArtifactS3Path=$SRC_ARTIFACT_S3_PATH --output text) - - echo Running execution $EXECUTION_ID... - - COMMAND="aws ssm describe-automation-executions --filters Key=ExecutionId,Values=$EXECUTION_ID" - - STATUS=$($COMMAND | jq -r ".AutomationExecutionMetadataList[0].AutomationExecutionStatus") - - | - while [ $STATUS = "InProgress" ]; - do sleep 3; - STATUS=$($COMMAND | jq -r ".AutomationExecutionMetadataList[0].AutomationExecutionStatus"); - done - - | - if [ $STATUS = "Success" ]; - then echo Automation execution succeeded.; - else echo Automation execution failed. Please check CloudWatch log for details.; - ERROR_MSG=$($COMMAND | jq -r ".AutomationExecutionMetadataList[0].FailureMessage"); - echo SSM Failure Message Follows.; - echo $ERROR_MSG; - exit 1; - fi - post_build: - commands: - - | - if [ $CODEBUILD_BUILD_SUCCEEDING -eq 1 ]; - then echo Writing updated service specification file...; - aws proton --region $AWS_DEFAULT_REGION get-service --name $service_name | jq -r .service.spec > service.yaml; - yq w service.yaml 'instances[*].spec.image' "$ECR_REPO_URI:$IMAGE_TAG" > rendered_service.yaml; - echo **** Updated service spec follows **** - cat rendered_service.yaml - fi - artifacts: - files: - - rendered_service.yaml - Type: CODEPIPELINE - EncryptionKey: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn - TimeoutInMinutes: 60 - QueuedTimeoutInMinutes: 480 - - {% for service_instance in service_instances %} - Deploy{{loop.index}}Project: - Type: AWS::CodeBuild::Project - Properties: - Artifacts: - Type: CODEPIPELINE - Environment: - ComputeType: BUILD_GENERAL1_SMALL - Image: aws/codebuild/amazonlinux2-x86_64-standard:3.0 - PrivilegedMode: false - Type: LINUX_CONTAINER - EnvironmentVariables: - - Name: service_name - Type: PLAINTEXT - Value: '{{service.name}}' - - Name: service_instance_name - Type: PLAINTEXT - Value: '{{service_instance.name}}' - ServiceRole: !GetAtt DeploymentRole.Arn - LogsConfig: - CloudWatchLogs: - GroupName: '{{service.name}}/pipeline' - Status: 'ENABLED' - StreamName: 'deploy' - Source: - BuildSpec: | - version: "0.2" - phases: - build: - commands: - - pip3 install --upgrade --user awscli - - aws proton --region $AWS_DEFAULT_REGION update-service-instance --deployment-type CURRENT_VERSION --name $service_instance_name --service-name $service_name --spec file://rendered_service.yaml - - aws proton --region $AWS_DEFAULT_REGION wait service-instance-deployed --name $service_instance_name --service-name $service_name - Type: CODEPIPELINE - EncryptionKey: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn - {% endfor %} - # This role is used to build container image - PublishRole: - Type: AWS::IAM::Role - Properties: - AssumeRolePolicyDocument: - Statement: - - Action: sts:AssumeRole - Effect: Allow - Principal: - Service: codebuild.amazonaws.com - Version: '2012-10-17' - PublishRoleDefaultPolicy: - Type: AWS::IAM::Policy - Properties: - PolicyName: PublishRoleDefaultPolicy - PolicyDocument: - Statement: - - Effect: Allow - Resource: - - !Sub 'arn:${AWS::Partition}:ec2:*::image/*' - - !Sub 'arn:${AWS::Partition}:ec2:*:*:network-interface/*' - - !Sub 'arn:${AWS::Partition}:ec2:*:*:security-group/*' - - !Sub 'arn:${AWS::Partition}:ec2:*:*:subnet/*' - - !Sub 'arn:${AWS::Partition}:ec2:*:*:volume/*' - Action: - - 'ec2:RunInstances' - - Effect: Allow - Resource: !Sub 'arn:${AWS::Partition}:ec2:*:*:instance/*' - Action: - - 'ec2:RunInstances' - Condition: - StringEquals: - "aws:RequestTag/tag:aws:cloudformation:stack-id": !Ref AWS::StackId - - Effect: Allow - Resource: !Sub 'arn:${AWS::Partition}:ec2:${AWS::Region}:${AWS::AccountId}:instance/*' - Action: - - 'ec2:TerminateInstances' - Condition: - StringEquals: - "aws:ResourceTag/tag:aws:cloudformation:stack-id": !Ref AWS::StackId - - Effect: Allow - Resource: '*' - Action: - - 'ec2:DescribeInstances' - - 'ec2:DescribeInstanceStatus' - - 'ec2:CreateTags' - - Effect: Allow - Resource: - - !Sub 'arn:${AWS::Partition}:ec2:${AWS::Region}:${AWS::AccountId}:instance/*' - Action: - - 'ssm:SendCommand' - Condition: - StringEquals: - "aws:ResourceTag/tag:aws:cloudformation:stack-id": !Ref AWS::StackId - - Effect: Allow - Resource: - - !Sub 'arn:${AWS::Partition}:ssm:${AWS::Region}::document/AWS-RunPowerShellScript' - Action: - - 'ssm:SendCommand' - - Effect: Allow - Resource: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/${ContainerImageBuildServerRole} - Action: - - 'iam:PassRole' - - Effect: Allow - Resource: '*' - Action: - - 'ssm:CancelCommand' - - 'ssm:DescribeAutomationExecutions' - - 'ssm:DescribeInstanceInformation' - - 'ssm:ListCommands' - - 'ssm:ListCommandInvocations' - - Effect: Allow - Resource: !Sub arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:automation-execution/ - Action: - - 'ssm:StopAutomationExecution' - - 'ssm:GetAutomationExecution' - - Effect: Allow - Resource: !Sub arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:automation-definition/${BuildDotNetContainerDocument}:$DEFAULT - Action: - - 'ssm:StartAutomationExecution' - - Effect: Allow - Resource: !Sub arn:${AWS::Partition}:ssm:${AWS::Region}::parameter/aws/service/ami-windows-latest/* - Action: - - 'ssm:GetParameters' - - Action: - - logs:CreateLogGroup - - logs:CreateLogStream - - logs:PutLogEvents - Effect: Allow - Resource: - - !Sub 'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:{{service.name}}/pipeline' - - !Sub 'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:{{service.name}}/pipeline:*' - - Action: - - codebuild:CreateReportGroup - - codebuild:CreateReport - - codebuild:UpdateReport - - codebuild:BatchPutTestCases - Effect: Allow - Resource: !Sub 'arn:${AWS::Partition}:codebuild:${AWS::Region}:${AWS::AccountId}:report-group/${BuildProject}-*' - - Action: - - proton:GetService - Effect: Allow - Resource: "*" - - Action: - - 's3:PutObject' - - 's3:GetObject' - - 's3:GetObjectVersion' - - 's3:GetBucketAcl' - - 's3:GetBucketLocation' - Effect: Allow - Resource: - - !GetAtt PipelineArtifactsBucket.Arn - - !Sub '${PipelineArtifactsBucket.Arn}/*' - - Action: - - kms:Decrypt - - kms:DescribeKey - - kms:Encrypt - - kms:ReEncrypt* - - kms:GenerateDataKey* - Effect: Allow - Resource: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn - Version: '2012-10-17' - Roles: [ !Ref PublishRole ] - - DeploymentRole: - Type: AWS::IAM::Role - Properties: - AssumeRolePolicyDocument: - Statement: - - Action: sts:AssumeRole - Effect: Allow - Principal: - Service: codebuild.amazonaws.com - Version: '2012-10-17' - DeploymentRoleDefaultPolicy: - Type: AWS::IAM::Policy - Properties: - PolicyName: DeploymentRoleDefaultPolicy - PolicyDocument: - Statement: - - Action: - - logs:CreateLogGroup - - logs:CreateLogStream - - logs:PutLogEvents - Effect: Allow - Resource: - - !Sub 'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:{{service.name}}/pipeline' - - !Sub 'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:{{service.name}}/pipeline:*' - - Action: - - codebuild:CreateReportGroup - - codebuild:CreateReport - - codebuild:UpdateReport - - codebuild:BatchPutTestCases - Effect: Allow - Resource: !Sub 'arn:${AWS::Partition}:codebuild:${AWS::Region}:${AWS::AccountId}:report-group/Deploy*Project-*' - - Action: - - proton:UpdateServiceInstance - - proton:GetServiceInstance - Effect: Allow - Resource: '*' - - Action: - - s3:GetObject* - - s3:GetBucket* - - s3:List* - Effect: Allow - Resource: - - !GetAtt PipelineArtifactsBucket.Arn - - !Sub '${PipelineArtifactsBucket.Arn}/*' - - Action: - - kms:Decrypt - - kms:DescribeKey - - kms:Encrypt - - kms:ReEncrypt* - - kms:GenerateDataKey* - Effect: Allow - Resource: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn - Version: '2012-10-17' - Roles: [ !Ref DeploymentRole ] - PipelineArtifactsBucketEncryptionKey: - Type: AWS::KMS::Key - Properties: - KeyPolicy: - Statement: - - Action: - - kms:Create* - - kms:Describe* - - kms:Enable* - - kms:List* - - kms:Put* - - kms:Update* - - kms:Revoke* - - kms:Disable* - - kms:Get* - - kms:Delete* - - kms:ScheduleKeyDeletion - - kms:CancelKeyDeletion - - kms:GenerateDataKey - - kms:TagResource - - kms:UntagResource - Effect: Allow - Principal: - AWS: !Sub 'arn:${AWS::Partition}:iam::${AWS::AccountId}:root' - Resource: '*' - - Action: - - kms:Decrypt - - kms:DescribeKey - - kms:Encrypt - - kms:ReEncrypt* - - kms:GenerateDataKey* - Effect: Allow - Principal: - AWS: - - !GetAtt PipelineRole.Arn - - !GetAtt PublishRole.Arn - - !GetAtt DeploymentRole.Arn - - !GetAtt ContainerImageBuildServerRole.Arn - Resource: '*' - Version: '2012-10-17' - UpdateReplacePolicy: Delete - DeletionPolicy: Delete - PipelineArtifactsBucket: - Type: AWS::S3::Bucket - Properties: - VersioningConfiguration: - Status: Enabled - BucketEncryption: - ServerSideEncryptionConfiguration: - - ServerSideEncryptionByDefault: - KMSMasterKeyID: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn - SSEAlgorithm: aws:kms - PublicAccessBlockConfiguration: - BlockPublicAcls: true - BlockPublicPolicy: true - IgnorePublicAcls: true - RestrictPublicBuckets: true - UpdateReplacePolicy: Retain - DeletionPolicy: Retain - PipelineArtifactsBucketEncryptionKeyAlias: - Type: AWS::KMS::Alias - Properties: - AliasName: 'alias/codepipeline-encryption-key-{{ service.name }}' - TargetKeyId: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn - UpdateReplacePolicy: Delete - DeletionPolicy: Delete - PipelineRole: - Type: AWS::IAM::Role - Properties: - AssumeRolePolicyDocument: - Statement: - - Action: sts:AssumeRole - Effect: Allow - Principal: - Service: codepipeline.amazonaws.com - Version: '2012-10-17' - PipelineRoleDefaultPolicy: - Type: AWS::IAM::Policy - Properties: - PolicyName: PipelineRoleDefaultPolicy - PolicyDocument: - Statement: - - Action: - - s3:GetObject* - - s3:GetBucket* - - s3:List* - - s3:DeleteObject* - - s3:PutObject* - - s3:Abort* - Effect: Allow - Resource: - - !GetAtt PipelineArtifactsBucket.Arn - - !Sub '${PipelineArtifactsBucket.Arn}/*' - - Action: - - kms:Decrypt - - kms:DescribeKey - - kms:Encrypt - - kms:ReEncrypt* - - kms:GenerateDataKey* - Effect: Allow - Resource: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn - - Action: codestar-connections:* - Effect: Allow - Resource: '*' - - Action: sts:AssumeRole - Effect: Allow - Resource: !GetAtt PipelineBuildCodePipelineActionRole.Arn - - Action: sts:AssumeRole - Effect: Allow - Resource: !GetAtt PipelineDeployCodePipelineActionRole.Arn - Version: '2012-10-17' - Roles: [ !Ref PipelineRole ] - Pipeline: - Type: AWS::CodePipeline::Pipeline - Properties: - RoleArn: !GetAtt PipelineRole.Arn - Stages: - - Actions: - - ActionTypeId: - Category: Source - Owner: AWS - Provider: CodeStarSourceConnection - Version: '1' - Configuration: - ConnectionArn: '{{ service.repository_connection_arn }}' - FullRepositoryId: '{{ service.repository_id }}' - BranchName: '{{ service.branch_name }}' - Name: Checkout - OutputArtifacts: - - Name: Artifact_Source_Checkout - RunOrder: 1 - Name: Source - - Actions: - - ActionTypeId: - Category: Build - Owner: AWS - Provider: CodeBuild - Version: '1' - Configuration: - ProjectName: !Ref BuildProject - InputArtifacts: - - Name: Artifact_Source_Checkout - Name: Build - OutputArtifacts: - - Name: BuildOutput - RoleArn: !GetAtt PipelineBuildCodePipelineActionRole.Arn - RunOrder: 1 - Name: Build - {%- for service_instance in service_instances %} - - Actions: - - ActionTypeId: - Category: Build - Owner: AWS - Provider: CodeBuild - Version: '1' - Configuration: - ProjectName: !Ref Deploy{{loop.index}}Project - InputArtifacts: - - Name: BuildOutput - Name: Deploy - RoleArn: !GetAtt PipelineDeployCodePipelineActionRole.Arn - RunOrder: 1 - Name: 'Deploy-{{service_instance.name}}' - {%- endfor %} - ArtifactStore: - EncryptionKey: - Id: !GetAtt PipelineArtifactsBucketEncryptionKey.Arn - Type: KMS - Location: !Ref PipelineArtifactsBucket - Type: S3 - DependsOn: - - PipelineRoleDefaultPolicy - - PublishRoleDefaultPolicy - - PipelineBuildCodePipelineActionRoleDefaultPolicy - - PipelineDeployCodePipelineActionRoleDefaultPolicy - - ContainerImageBuildServerRoleDefaultPolicy - PipelineBuildCodePipelineActionRole: - Type: AWS::IAM::Role - Properties: - AssumeRolePolicyDocument: - Statement: - - Action: sts:AssumeRole - Effect: Allow - Principal: - AWS: !Sub 'arn:${AWS::Partition}:iam::${AWS::AccountId}:root' - Version: '2012-10-17' - PipelineBuildCodePipelineActionRoleDefaultPolicy: - Type: AWS::IAM::Policy - Properties: - PolicyDocument: - Statement: - - Action: - - codebuild:BatchGetBuilds - - codebuild:StartBuild - - codebuild:StopBuild - Effect: Allow - Resource: !GetAtt BuildProject.Arn - Version: '2012-10-17' - PolicyName: PipelineBuildCodePipelineActionRoleDefaultPolicy - Roles: [ !Ref PipelineBuildCodePipelineActionRole ] - PipelineDeployCodePipelineActionRole: - Type: AWS::IAM::Role - Properties: - AssumeRolePolicyDocument: - Statement: - - Action: sts:AssumeRole - Effect: Allow - Principal: - AWS: !Sub 'arn:${AWS::Partition}:iam::${AWS::AccountId}:root' - Version: '2012-10-17' - PipelineDeployCodePipelineActionRoleDefaultPolicy: - Type: AWS::IAM::Policy - Properties: - PolicyDocument: - Statement: - - Action: - - codebuild:BatchGetBuilds - - codebuild:StartBuild - - codebuild:StopBuild - Effect: Allow - Resource: !Sub 'arn:${AWS::Partition}:codebuild:${AWS::Region}:${AWS::AccountId}:project/Deploy*' - Version: '2012-10-17' - PolicyName: PipelineDeployCodePipelineActionRoleDefaultPolicy - Roles: [ !Ref PipelineDeployCodePipelineActionRole ] -Outputs: - PipelineEndpoint: - Description: The URL to access the pipeline - Value: !Sub https://${AWS::Region}.console.aws.amazon.com/codesuite/codepipeline/pipelines/${Pipeline}/view?region=${AWS::Region}' diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/pipeline_infrastructure/manifest.yaml b/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/pipeline_infrastructure/manifest.yaml deleted file mode 100644 index eed587b..0000000 --- a/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/pipeline_infrastructure/manifest.yaml +++ /dev/null @@ -1,5 +0,0 @@ -infrastructure: - templates: - - file: "cloudformation.yaml" - rendering_engine: jinja - template_language: cloudformation diff --git a/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/schema/schema.yaml b/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/schema/schema.yaml deleted file mode 100644 index bcdbe01..0000000 --- a/public-private-fargate-microservices-dotnetfx/microservices-svc/private-fargate-svc/v1/schema/schema.yaml +++ /dev/null @@ -1,77 +0,0 @@ -schema: - format: - openapi: "3.0.0" - service_input_type: "PrivateServiceInput" - pipeline_input_type: "PipelineInputs" - - types: - PrivateServiceInput: - type: object - description: "Input properties for a Private Fargate service" - properties: - cluster_operating_system_family: - type: string - description: "The operating system used for the ECS Task Definition" - default: WINDOWS_SERVER_2019_CORE - enum: ['WINDOWS_SERVER_2019_CORE', 'WINDOWS_SERVER_2019_FULL', 'WINDOWS_SERVER_2022_CORE', 'WINDOWS_SERVER_2022_FULL'] - port: - type: number - description: "The port to route traffic to" - default: 80 - minimum: 0 - maximum: 65535 - desired_count: - type: number - description: "The default number of Fargate tasks you want running" - default: 1 - minimum: 1 - task_size: - type: string - description: "The size of the task you want to run" - enum: [ "medium", "large", "x-large"] - default: "medium" - image: - type: string - description: "The name/url of the container image" - default: "mcr.microsoft.com/dotnet/framework/samples:aspnetapp" - minLength: 1 - maxLength: 200 - service_discovery_name: - type: string - description: "The name of the service to register in service discovery" - minLength: 3 - maxLength: 24 - required: - - service_discovery_name - - PipelineInputs: - type: object - description: "Pipeline input properties" - properties: - build_server_ami_id: - type: string - description: SSM Parameter expression to use to retrieve the AMI ID for the build server. Must be compatible with operating system version used by ECS cluster. - default: /aws/service/ami-windows-latest/Windows_Server-2019-English-Core-ECS_Optimized/image_id - build_server_instance_type: - type: string - description: "Instance type used for the EC2 Instance that serves as the build server." - default: t2.medium - enum: [t2.small, t2.medium, t2.large, - t3.small, t3.medium, t3.large, - t3a.small, t3a.medium, t3a.large ] - build_server_volume_size: - type: number - description: "Volume size in GiBs used when provisioning the build server." - default: 30 - minimum: 4 - maximum: 1024 - build_server_volume_type: - type: string - description: "Volume type used when provisioning the build server." - default: gp3 - enum: [ gp3, gp2 ] - dockerfile: - type: string - description: "The location of the Dockerfile to build" - default: "Dockerfile" - minLength: 1 diff --git a/public-private-fargate-microservices-dotnetfx/specs/svc-private-spec.yaml b/public-private-fargate-microservices-dotnetfx/specs/svc-private-spec.yaml deleted file mode 100644 index 0953fe0..0000000 --- a/public-private-fargate-microservices-dotnetfx/specs/svc-private-spec.yaml +++ /dev/null @@ -1,13 +0,0 @@ -proton: ServiceSpec - -pipeline: - build_server_instance_type: "t3.medium" - -instances: - - name: "backend-dev" - environment: "Beta" - spec: - desired_count: 2 - port: 80 - task_size: "medium" - service_discovery_name: "backend-dev" From db91ab813593d565e33778d191be40054e7a5c7c Mon Sep 17 00:00:00 2001 From: Carlos Santos Date: Wed, 6 Apr 2022 07:35:54 -0700 Subject: [PATCH 16/20] fix: Corrected reference to environment in compatible-envs This is needed when using using the GitHub integration feature of Proton --- .../loadbalanced-fargate-dotnetfx-svc/v1/.compatible-envs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-svc/v1/.compatible-envs b/loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-svc/v1/.compatible-envs index 4ef64cc..0b7cd87 100644 --- a/loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-svc/v1/.compatible-envs +++ b/loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-svc/v1/.compatible-envs @@ -1 +1 @@ -microservices-env:1 +loadbalanced-fargate-dotnetfx-env:1 From 2702cd552abb1ecb6307e1f8de3d5bbbfe8a0842 Mon Sep 17 00:00:00 2001 From: Carlos Santos Date: Wed, 6 Apr 2022 13:27:09 -0700 Subject: [PATCH 17/20] fix: Correct rendered_service.yaml output echo *** was listing out the directory contents. --- .../v1/pipeline_infrastructure/cloudformation.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-svc/v1/pipeline_infrastructure/cloudformation.yaml b/loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-svc/v1/pipeline_infrastructure/cloudformation.yaml index 80cad89..dd62d21 100644 --- a/loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-svc/v1/pipeline_infrastructure/cloudformation.yaml +++ b/loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-svc/v1/pipeline_infrastructure/cloudformation.yaml @@ -377,7 +377,7 @@ Resources: then echo Writing updated service specification file...; aws proton --region $AWS_DEFAULT_REGION get-service --name $service_name | jq -r .service.spec > service.yaml; yq w service.yaml 'instances[*].spec.image' "$ECR_REPO_URI:$IMAGE_TAG" > rendered_service.yaml; - echo **** Updated service spec follows **** + echo === Updated service spec follows === cat rendered_service.yaml fi artifacts: From 156bb6cf52047946072acd8a9a1b4a15601a787e Mon Sep 17 00:00:00 2001 From: Carlos Santos Date: Fri, 15 Apr 2022 15:52:23 -0700 Subject: [PATCH 18/20] doc: Completed README.md updates --- loadbalanced-fargate-dotnetfx-svc/README.md | 134 ++++++-------------- 1 file changed, 39 insertions(+), 95 deletions(-) diff --git a/loadbalanced-fargate-dotnetfx-svc/README.md b/loadbalanced-fargate-dotnetfx-svc/README.md index d3c1129..ebbdf90 100644 --- a/loadbalanced-fargate-dotnetfx-svc/README.md +++ b/loadbalanced-fargate-dotnetfx-svc/README.md @@ -1,6 +1,6 @@ # AWS Proton Sample .NET Framework Microservices Using Amazon ECS and AWS Fargate -This directory contains a sample AWS Proton Environment and Service templates for a set of .NET Framework 4.8 microservices deployed to Amazon ECS based using service discovery running on AWS Fargate and a CI/CD pipeline used to deploy updates, as well as sample specs for creating Proton Environments and Services using the templates. All resources deployed are tagged. +This directory contains a sample AWS Proton Environment and Service templates for a set of .NET Framework 4.8 deployed to an Amazon ECS load-balanced service running on AWS Fargate, and a CI/CD pipeline used to deploy updates, as well as sample specs for creating Proton Environments and Services using the templates. All resources deployed are tagged. The environment template deploys: @@ -9,20 +9,22 @@ The environment template deploys: - 2 Nat Gateways across 2 Availability Zones - 2 private subnets across 2 Availability Zones - 2 public subnets across 2 Availability Zones -- an ECS Cluster - a private namespace for service discovery -The service templates contains all the resources required to create a public ECS Fargate service behind a load balancer and a private ECS Fargate service in that environment. It also provides sample specs for creating Proton Environments and Services using the templates. - Developers provisioning their services can configure the following properties through their service spec: -- Fargate CPU size -- Fargate memory size +- ECS Cluster OS family - Because Windows of the coupling in the User/Kernel boundary in Windows, customers must take care to [match the container host OS version with container image versions](https://docs.microsoft.com/en-us/virtualization/windowscontainers/deploy-containers/version-compatibility?tabs=windows-server-20H2%2Cwindows-10-20H2#windows-server-host-os-compatibility) +- ECS task size - Medium (cpu 1024, memory 2048), Large (cpu 2048, memory 4096), and X-Large (cpu 4096, memory 8192). See the [Task Size](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html#task_size) page for supported Windows options. - Number of running containers -- Choose private or public subnets to run the loadbalanced service or the private service, accessed via service discovery - Service name to register and use for service discovery -If you need application code to run in the services: +Developers provisioning their pipeline can configure the following properties through their pipeline spec: + +- AMI to use for Build Server - Priviledged modes is not supported on Windows so a Windows EC2 instance is used to create the container image. +- Build Server instance type, volume size, and volume type +- Dockerfile path + +If you need application code to run in the services, you can find a sample application here: * https://github.com/aws-quickstart/quickstart-dotnetfx-ecs-cicd # Registering and deploying these templates @@ -83,23 +85,23 @@ First, create an environment template, which will contain all of the environment ``` aws proton create-environment-template \ - --name "aws-proton-fargate-microservices-dotnetfx" \ - --display-name "aws proton fargate microservices-dotnetfx" \ - --description "Proton Example Dev VPC with Public facing services and with Private backend services on ECS cluster with Fargate compute" + --name "public-vpc" \ + --display-name "PublicVPC" \ + --description "VPC with Public Access and ECS Cluster" ``` Now create a version which contains the contents of the sample environment template. Compress the sample template files and register the version: ``` -tar -zcvf env-template.tar.gz environment/ +tar -zcvf env-template.tar.gz loadbalanced-fargate-dotnetfx-env/ aws s3 cp env-template.tar.gz s3://proton-cli-templates-${account_id}/env-template.tar.gz rm env-template.tar.gz aws proton create-environment-template-version \ - --template-name "aws-proton-fargate-microservices-dotnetfx" \ - --description "Proton Example Dev Environment Version 1" \ + --template-name "public-vpc" \ + --description "Version 1" \ --source s3="{bucket=proton-cli-templates-${account_id},key=env-template.tar.gz}" ``` @@ -107,7 +109,12 @@ Wait for the environment template version to be successfully registered. ``` aws proton wait environment-template-version-registered \ - --template-name "aws-proton-fargate-microservices-dotnetfx" \ + --template-name "public-vpc" \ + --major-version "1" \ + --minor-version "0" + +aws proton get-environment-template-version \ + --template-name "public-vpc" \ --major-version "1" \ --minor-version "0" ``` @@ -116,7 +123,7 @@ You can now publish the environment template version, making it available for us ``` aws proton update-environment-template-version \ - --template-name "aws-proton-fargate-microservices-dotnetfx" \ + --template-name "public-vpc" \ --major-version "1" \ --minor-version "0" \ --status "PUBLISHED" @@ -124,82 +131,43 @@ aws proton update-environment-template-version \ ## Register the Service Templates -Register the sample service template, which contains all the resources required to provision an ECS Fargate service behind a load balancer, the private services as well as a continuous delivery pipeline using AWS CodePipeline for each. +Register the sample service template, which contains all the resources required to provision an ECS Fargate service behind a load balancer as well as a continuous delivery pipeline using AWS CodePipeline. First, create the service template. ``` aws proton create-service-template \ - --name "lb-public-fargate-svc-dotnetfx" \ - --display-name "PublicLoadbalancedDotNetFargateService" \ + --name "lb-fargate-service-dotnetfx" \ + --display-name "PublicLoadbalancedDotNetFxFargateService" \ --description ".NET Framework Windows Fargate Service with an Application Load Balancer" ``` Now create a version which contains the contents of the sample service template. Compress the sample template files and register the version: ``` -tar -zcvf svc-public-template.tar.gz service/loadbalanced-public-svc/ +tar -zcvf lb-fargate-service-dotnetfx-template.tar.gz loadbalanced-fargate-dotnetfx-svc/ -aws s3 cp svc-public-template.tar.gz s3://proton-cli-templates-${account_id}/svc-public-template.tar.gz +aws s3 cp lb-fargate-service-dotnetfx-template.tar.gz s3://proton-cli-templates-${account_id}/lb-fargate-service-dotnetfx-template.tar.gz -rm svc-public-template.tar.gz +rm lb-fargate-service-dotnetfx-template.tar.gz aws proton create-service-template-version \ - --template-name "lb-public-fargate-svc-dotnetfx" \ + --template-name "lb-fargate-service-dotnetfx" \ --description "Version 1" \ - --source s3="{bucket=proton-cli-templates-${account_id},key=svc-public-template.tar.gz}" \ - --compatible-environment-templates '[{"templateName":"aws-proton-fargate-microservices-dotnetfx","majorVersion":"1"}]' + --source s3="{bucket=proton-cli-templates-${account_id},key=lb-fargate-service-dotnetfx-template.tar.gz}" \ + --compatible-environment-templates '[{"templateName":"lb-fargate-service-dotnetfx","majorVersion":"1"}]' ``` Wait for the service template version to be successfully registered. ``` aws proton wait service-template-version-registered \ - --template-name "lb-public-fargate-svc-dotnetfx" \ + --template-name "lb-fargate-service-dotnetfx" \ --major-version "1" \ --minor-version "0" -``` - -You can now publish the Public service template version, making it available for users in your AWS account to create Proton services. -``` -aws proton update-service-template-version \ - --template-name "lb-public-fargate-svc-dotnetfx" \ - --major-version "1" \ - --minor-version "0" \ - --status "PUBLISHED" -``` - -### Second, create the Private service template. - -``` -aws proton create-service-template \ - --name "private-fargate-svc-dotnetfx" \ - --display-name "PrivateBackendDotNetFargateService" \ - --description ".NET Framework Windows Private Backend Fargate Service" -``` - -Now create a version which contains the contents of the sample service template. Compress the sample template files and register the version: - -``` -tar -zcvf svc-private-template.tar.gz service/private-fargate-svc-dotnetfx/ - -aws s3 cp svc-private-template.tar.gz s3://proton-cli-templates-${account_id}/svc-private-template.tar.gz - -rm svc-private-template.tar.gz - -aws proton create-service-template-version \ - --template-name "private-fargate-svc-dotnetfx" \ - --description "Version 1" \ - --source s3="{bucket=proton-cli-templates-${account_id},key=svc-private-template.tar.gz}" \ - --compatible-environment-templates '[{"templateName":"aws-proton-fargate-microservices-dotnetfx","majorVersion":"1"}]' -``` - -Wait for the service template version to be successfully registered. - -``` -aws proton wait service-template-version-registered \ - --template-name "private-fargate-svc-dotnetfx" \ +aws proton get-service-template-version \ + --template-name "lb-fargate-service-dotnetfx" \ --major-version "1" \ --minor-version "0" ``` @@ -208,7 +176,7 @@ You can now publish the Public service template version, making it available for ``` aws proton update-service-template-version \ - --template-name "private-fargate-svc-dotnetfx" \ + --template-name "lb-fargate-service-dotnetfx" \ --major-version "1" \ --minor-version "0" \ --status "PUBLISHED" @@ -231,7 +199,7 @@ First, deploy a Proton environment. This command reads your environment spec at ``` aws proton create-environment \ --name "Beta" \ - --template-name aws-proton-fargate-microservices-dotnetfx \ + --template-name public-vpc \ --template-major-version 1 \ --proton-service-role-arn arn:aws:iam::${account_id}:role/ProtonServiceRole \ --spec file://specs/env-spec.yaml @@ -284,7 +252,7 @@ Then, create a Proton environment. This command reads your environment spec at ` ```bash aws proton create-environment \ --name "Beta" \ - --template-name aws-proton-fargate-microservices-dotnetfx \ + --template-name public-vpc \ --template-major-version 1 \ --environment-account-connection-id ${environment_account_connection_id} \ --spec file://specs/env-spec.yaml @@ -314,7 +282,7 @@ aws proton create-service \ --repository-id "/" \ --branch "main" \ --template-major-version 1 \ - --template-name lb-public-fargate-svc-dotnetfx \ + --template-name lb-fargate-service-dotnetfx \ --spec file://specs/svc-public-spec.yaml ``` @@ -325,27 +293,3 @@ aws proton wait service-created --name front-end aws proton get-service --name front-end ``` - -And finally, create a Private Proton service and deploy it into your Proton environment. This command reads your service spec at `specs/svc-private-spec.yaml`, merges it with the service template created above, and deploys the resources in CloudFormation stacks in your AWS account using the Proton service role. The service will provision a private ECS service running on Fargate and a CodePipeline pipeline to deploy your application code. - - -Fill in your CodeStar Connections connection ID and your source code repository details in this command. - -``` -aws proton create-service \ - --name "back-end" \ - --repository-connection-arn arn:aws:codestar-connections:us-west-2:${account_id}:connection/ \ - --repository-id "/" \ - --branch "main" \ - --template-major-version 1 \ - --template-name private-fargate-svc-dotnetfx \ - --spec file://specs/svc-private-spec.yaml -``` - -Wait for the service to successfully deploy. - -``` -aws proton wait service-created --name back-end - -aws proton get-service --name back-end -``` \ No newline at end of file From 0a45d27c96e348b9b61a3320e356e360aa7db49e Mon Sep 17 00:00:00 2001 From: Carlos Santos Date: Fri, 15 Apr 2022 16:01:07 -0700 Subject: [PATCH 19/20] doc: Typo corrections in spec and schema files --- .../loadbalanced-fargate-dotnetfx-env/v1/schema/schema.yaml | 2 +- loadbalanced-fargate-dotnetfx-svc/specs/svc-spec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-env/v1/schema/schema.yaml b/loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-env/v1/schema/schema.yaml index 59c4256..48d7516 100644 --- a/loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-env/v1/schema/schema.yaml +++ b/loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-env/v1/schema/schema.yaml @@ -9,7 +9,7 @@ schema: properties: vpc_cidr: type: string - description: "This CIDR range for your VPC" + description: "The CIDR range for your VPC" default: 10.0.0.0/16 pattern: ([0-9]{1,3}\.){3}[0-9]{1,3}($|/(16|24)) public_subnet_one_cidr: diff --git a/loadbalanced-fargate-dotnetfx-svc/specs/svc-spec.yaml b/loadbalanced-fargate-dotnetfx-svc/specs/svc-spec.yaml index 28475da..499689a 100644 --- a/loadbalanced-fargate-dotnetfx-svc/specs/svc-spec.yaml +++ b/loadbalanced-fargate-dotnetfx-svc/specs/svc-spec.yaml @@ -7,7 +7,7 @@ instances: - name: "frontend-dev" environment: "Beta" spec: - desired_count: 2 + desired_count: 1 port: 80 task_size: "medium" service_discovery_name: "frontend-dev" From 9e4b882ac578ed243b79fc630c0aa5f465ccc9d2 Mon Sep 17 00:00:00 2001 From: csantos Date: Tue, 11 Oct 2022 15:50:13 -0700 Subject: [PATCH 20/20] chore: rearranged files to match new folder structure --- .../fargate-dotnetfx-env}/README.md | 0 .../fargate-dotnetfx-env/spec/spec.yaml | 0 .../v1/infrastructure/cloudformation.yaml | 0 .../v1/infrastructure/manifest.yaml | 0 .../fargate-dotnetfx-env}/v1/schema/schema.yaml | 0 .../v1/.compatible-envs | 1 - .../policies/proton-service-assume-policy.json | 12 ------------ .../loadbalanced-fargate-dotnetfx-svc/spec/spec.yaml | 0 .../v1/.compatible-envs | 1 + .../v1/instance_infrastructure/cloudformation.yaml | 0 .../v1/instance_infrastructure/manifest.yaml | 0 .../v1/pipeline_infrastructure/cloudformation.yaml | 0 .../v1/pipeline_infrastructure/manifest.yaml | 0 .../v1/schema/schema.yaml | 0 14 files changed, 1 insertion(+), 13 deletions(-) rename {loadbalanced-fargate-dotnetfx-svc => environment-templates/fargate-dotnetfx-env}/README.md (100%) rename loadbalanced-fargate-dotnetfx-svc/specs/env-spec.yaml => environment-templates/fargate-dotnetfx-env/spec/spec.yaml (100%) rename {loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-env => environment-templates/fargate-dotnetfx-env}/v1/infrastructure/cloudformation.yaml (100%) rename {loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-env => environment-templates/fargate-dotnetfx-env}/v1/infrastructure/manifest.yaml (100%) rename {loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-env => environment-templates/fargate-dotnetfx-env}/v1/schema/schema.yaml (100%) delete mode 100644 loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-svc/v1/.compatible-envs delete mode 100644 loadbalanced-fargate-dotnetfx-svc/policies/proton-service-assume-policy.json rename loadbalanced-fargate-dotnetfx-svc/specs/svc-spec.yaml => service-templates/loadbalanced-fargate-dotnetfx-svc/spec/spec.yaml (100%) create mode 100644 service-templates/loadbalanced-fargate-dotnetfx-svc/v1/.compatible-envs rename {loadbalanced-fargate-dotnetfx-svc => service-templates}/loadbalanced-fargate-dotnetfx-svc/v1/instance_infrastructure/cloudformation.yaml (100%) rename {loadbalanced-fargate-dotnetfx-svc => service-templates}/loadbalanced-fargate-dotnetfx-svc/v1/instance_infrastructure/manifest.yaml (100%) rename {loadbalanced-fargate-dotnetfx-svc => service-templates}/loadbalanced-fargate-dotnetfx-svc/v1/pipeline_infrastructure/cloudformation.yaml (100%) rename {loadbalanced-fargate-dotnetfx-svc => service-templates}/loadbalanced-fargate-dotnetfx-svc/v1/pipeline_infrastructure/manifest.yaml (100%) rename {loadbalanced-fargate-dotnetfx-svc => service-templates}/loadbalanced-fargate-dotnetfx-svc/v1/schema/schema.yaml (100%) diff --git a/loadbalanced-fargate-dotnetfx-svc/README.md b/environment-templates/fargate-dotnetfx-env/README.md similarity index 100% rename from loadbalanced-fargate-dotnetfx-svc/README.md rename to environment-templates/fargate-dotnetfx-env/README.md diff --git a/loadbalanced-fargate-dotnetfx-svc/specs/env-spec.yaml b/environment-templates/fargate-dotnetfx-env/spec/spec.yaml similarity index 100% rename from loadbalanced-fargate-dotnetfx-svc/specs/env-spec.yaml rename to environment-templates/fargate-dotnetfx-env/spec/spec.yaml diff --git a/loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-env/v1/infrastructure/cloudformation.yaml b/environment-templates/fargate-dotnetfx-env/v1/infrastructure/cloudformation.yaml similarity index 100% rename from loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-env/v1/infrastructure/cloudformation.yaml rename to environment-templates/fargate-dotnetfx-env/v1/infrastructure/cloudformation.yaml diff --git a/loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-env/v1/infrastructure/manifest.yaml b/environment-templates/fargate-dotnetfx-env/v1/infrastructure/manifest.yaml similarity index 100% rename from loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-env/v1/infrastructure/manifest.yaml rename to environment-templates/fargate-dotnetfx-env/v1/infrastructure/manifest.yaml diff --git a/loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-env/v1/schema/schema.yaml b/environment-templates/fargate-dotnetfx-env/v1/schema/schema.yaml similarity index 100% rename from loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-env/v1/schema/schema.yaml rename to environment-templates/fargate-dotnetfx-env/v1/schema/schema.yaml diff --git a/loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-svc/v1/.compatible-envs b/loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-svc/v1/.compatible-envs deleted file mode 100644 index 0b7cd87..0000000 --- a/loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-svc/v1/.compatible-envs +++ /dev/null @@ -1 +0,0 @@ -loadbalanced-fargate-dotnetfx-env:1 diff --git a/loadbalanced-fargate-dotnetfx-svc/policies/proton-service-assume-policy.json b/loadbalanced-fargate-dotnetfx-svc/policies/proton-service-assume-policy.json deleted file mode 100644 index a4c9f57..0000000 --- a/loadbalanced-fargate-dotnetfx-svc/policies/proton-service-assume-policy.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Principal": { - "Service": "proton.amazonaws.com" - }, - "Action": "sts:AssumeRole" - } - ] - } diff --git a/loadbalanced-fargate-dotnetfx-svc/specs/svc-spec.yaml b/service-templates/loadbalanced-fargate-dotnetfx-svc/spec/spec.yaml similarity index 100% rename from loadbalanced-fargate-dotnetfx-svc/specs/svc-spec.yaml rename to service-templates/loadbalanced-fargate-dotnetfx-svc/spec/spec.yaml diff --git a/service-templates/loadbalanced-fargate-dotnetfx-svc/v1/.compatible-envs b/service-templates/loadbalanced-fargate-dotnetfx-svc/v1/.compatible-envs new file mode 100644 index 0000000..164e93a --- /dev/null +++ b/service-templates/loadbalanced-fargate-dotnetfx-svc/v1/.compatible-envs @@ -0,0 +1 @@ +fargate-dotnetfx-env:1 diff --git a/loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-svc/v1/instance_infrastructure/cloudformation.yaml b/service-templates/loadbalanced-fargate-dotnetfx-svc/v1/instance_infrastructure/cloudformation.yaml similarity index 100% rename from loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-svc/v1/instance_infrastructure/cloudformation.yaml rename to service-templates/loadbalanced-fargate-dotnetfx-svc/v1/instance_infrastructure/cloudformation.yaml diff --git a/loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-svc/v1/instance_infrastructure/manifest.yaml b/service-templates/loadbalanced-fargate-dotnetfx-svc/v1/instance_infrastructure/manifest.yaml similarity index 100% rename from loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-svc/v1/instance_infrastructure/manifest.yaml rename to service-templates/loadbalanced-fargate-dotnetfx-svc/v1/instance_infrastructure/manifest.yaml diff --git a/loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-svc/v1/pipeline_infrastructure/cloudformation.yaml b/service-templates/loadbalanced-fargate-dotnetfx-svc/v1/pipeline_infrastructure/cloudformation.yaml similarity index 100% rename from loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-svc/v1/pipeline_infrastructure/cloudformation.yaml rename to service-templates/loadbalanced-fargate-dotnetfx-svc/v1/pipeline_infrastructure/cloudformation.yaml diff --git a/loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-svc/v1/pipeline_infrastructure/manifest.yaml b/service-templates/loadbalanced-fargate-dotnetfx-svc/v1/pipeline_infrastructure/manifest.yaml similarity index 100% rename from loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-svc/v1/pipeline_infrastructure/manifest.yaml rename to service-templates/loadbalanced-fargate-dotnetfx-svc/v1/pipeline_infrastructure/manifest.yaml diff --git a/loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-svc/v1/schema/schema.yaml b/service-templates/loadbalanced-fargate-dotnetfx-svc/v1/schema/schema.yaml similarity index 100% rename from loadbalanced-fargate-dotnetfx-svc/loadbalanced-fargate-dotnetfx-svc/v1/schema/schema.yaml rename to service-templates/loadbalanced-fargate-dotnetfx-svc/v1/schema/schema.yaml