Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor templates to have fewer imported values #37

Draft
wants to merge 20 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions cicd/1-setup/cicd-dependencies.template.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ Resources:
- codepipeline.amazonaws.com
Version: '2012-10-17'
Path: /service-role/
PermissionsBoundary: !ImportValue IAM-DevPermissions
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a tentative removal. I don't think we need it here. This stack is being deployed by an Admin anyway. I might be overlooking something though.

Policies:
- PolicyName: AiProxyPassRole
PolicyDocument:
Expand All @@ -43,7 +42,7 @@ Resources:
- "cloudformation:DescribeStacks"
- "cloudformation:CreateStack"
- "cloudformation:UpdateStack"
Resource: "*"
Resource: "*" # TODO scope to specific stacks
- PolicyName: CodeBuildResourcesAccess
PolicyDocument:
Statement:
Expand All @@ -68,11 +67,10 @@ Resources:
- s3:GetObjectVersion
Resource:
- !Sub ${ArtifactStore.Arn}/*
# TODO: Scope to specific ECR Repos?
- Effect: Allow
Action:
- ecr:GetAuthorizationToken
Resource: '*'
Resource: '*' # TODO scope to specific ECR repos
- Effect: Allow
Action: codestar-connections:UseConnection
Resource:
Expand Down Expand Up @@ -103,7 +101,6 @@ Resources:
- codebuild.amazonaws.com
Version: '2012-10-17'
Path: /service-role/
PermissionsBoundary: !ImportValue IAM-DevPermissions
Policies:
- PolicyName: PublicCodeBuildSecretsAccess
PolicyDocument:
Expand Down
31 changes: 23 additions & 8 deletions cicd/1-setup/deploy-cicd-dependencies.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,38 @@ TEMPLATE_FILE=cicd/1-setup/cicd-dependencies.template.yml
echo Validating cloudformation template...
aws cloudformation validate-template \
--template-body file://${TEMPLATE_FILE} \
| cat
> /dev/null

ACCOUNT=$(aws sts get-caller-identity --query "Account" --output text)
REGION=$(aws configure get region)

read -r -p "Would you like to deploy this template to AWS account $ACCOUNT? [y/N] " response
read -r -p "Would you like to create a change set for this template in AWS account $ACCOUNT? [y/N] " response
if [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]]
then
echo Updating cloudformation stack...
echo "Follow along at https://console.aws.amazon.com/cloudformation/home?region=us-east-1#/stacks?filteringText=aiproxy-cicd-deps&filteringStatus=active&viewNested=true&hideStacks=false"
aws cloudformation deploy \
echo Creating change set...
CHANGE_SET_NAME="aiproxy-cicd-deps-changeset-$(date +%s)"
aws cloudformation create-change-set \
--stack-name aiproxy-cicd-deps \
--template-file ${TEMPLATE_FILE} \
--change-set-name $CHANGE_SET_NAME \
--template-body file://${TEMPLATE_FILE} \
--capabilities CAPABILITY_IAM \
--tags EnvType=infrastructure \
"$@"

echo Complete!
echo "Change set created. You can review it at:"
echo "https://console.aws.amazon.com/cloudformation/home?region=$REGION#/stacks/changesets/changes?stackId=arn:aws:cloudformation:$REGION:$ACCOUNT:stack/aiproxy-cicd-deps/*&changeSetId=arn:aws:cloudformation:$REGION:$ACCOUNT:changeSet/$CHANGE_SET_NAME"

read -r -p "Would you like to execute the change set? [y/N] " response
if [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]]
then
echo Executing change set...
aws cloudformation execute-change-set \
--stack-name aiproxy-cicd-deps \
--change-set-name $CHANGE_SET_NAME
echo Complete!
else
echo Exiting...
fi
else
echo Exiting...
fi
fi
142 changes: 104 additions & 38 deletions cicd/2-cicd/cicd.template.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,11 @@ Conditions:

Resources:

# The Elastic Container Registry Repository will store our built docker
# images.
#-------------------------------------
# Elastic Container Registry (ECR)
# - Store built docker images
#-------------------------------------

EcrRepository:
Type: AWS::ECR::Repository
Properties:
Expand Down Expand Up @@ -113,6 +116,10 @@ Resources:
- 'kms:GenerateDataKeyWithoutPlaintext'
Resource: '*'

#-------------------------------------
# CodeBuild Projects
#-------------------------------------

# The CodeBuild Project is triggered by pull requests targeting $GitHubBranch
# It will perform any steps defined in the pr-buildspec.yml file.
PullRequestBuildProject:
Expand Down Expand Up @@ -191,32 +198,9 @@ Resources:
Artifacts:
Type: CODEPIPELINE

# Grant the AiProxy CodeBuild Role additional permissions for resources in
# this template. This allows us to avoid granting permission to * resources.
AiProxyRolePolicy:
Type: 'AWS::IAM::Policy'
Properties:
PolicyName: !Sub "${AWS::StackName}-codebuild-policy"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- codebuild:*
Resource:
- !GetAtt AppBuildProject.Arn
- !GetAtt IntegrationTestBuildProject.Arn
- Effect: Allow
Action:
- codebuild:CreateReportGroup
- codebuild:CreateReport
- codebuild:UpdateReport
- codebuild:BatchPutTestCases
- codebuild:BatchPutCodeCoverage
Resource:
- !Sub arn:aws:codebuild:us-east-1:165336972514:report-group/${AWS::StackName}-${GitHubBranch}-pr-build
Roles:
- !ImportValue AiProxyCodeBuildRoleName
#-------------------------------------
# Pipeline
#-------------------------------------

Pipeline:
Type: AWS::CodePipeline::Pipeline
Expand Down Expand Up @@ -278,11 +262,25 @@ Resources:
ActionMode: CREATE_UPDATE
TemplatePath: appBuildResults::packaged-app-template.yml
TemplateConfiguration: appBuildResults::cicd/3-app/aiproxy/dev.config.json
# ParameterOverrides must be a JSON string, not an object
ParameterOverrides: !Join
- ''
- - '{ "SubdomainName": "'
- !Sub "aiproxy-dev-${GitHubBranch}"
- '" }'
- ''
- - '{'
- !Sub '"SubdomainName": "aiproxy-dev-${GitHubBranch}",'
- !Sub '"ECRRepositoryArn": "${EcrRepository.Arn}",'
- !Sub
- '"VPC": "${VPCValue}",'
- { VPCValue: !ImportValue VPC }
- !Sub
- '"SecurityGroup": "${SecurityGroupValue}",'
- { SecurityGroupValue: !ImportValue VPC-ELBSecurityGroup }
- !Sub
- '"PublicSubnets": ${PublicSubnetsValue},'
- { PublicSubnetsValue: [!ImportValue VPC-PublicSubnetB, !ImportValue VPC-PublicSubnetC, !ImportValue VPC-PublicSubnetD, !ImportValue VPC-PublicSubnetE] }
- !Sub
- '"PrivateSubnets": ${PrivateSubnetsValue},'
- { PrivateSubnetsValue: [!ImportValue VPC-SubnetB, !ImportValue VPC-SubnetC, !ImportValue VPC-SubnetD, !ImportValue VPC-SubnetE] }
- '}'
Capabilities: CAPABILITY_AUTO_EXPAND,CAPABILITY_IAM
RoleArn: !Sub arn:aws:iam::${AWS::AccountId}:role/admin/CloudFormationService
- !Ref AWS::NoValue
Expand All @@ -304,11 +302,27 @@ Resources:
ActionMode: CREATE_UPDATE
TemplatePath: appBuildResults::packaged-app-template.yml
TemplateConfiguration: appBuildResults::cicd/3-app/aiproxy/test.config.json
# ParameterOverrides must be a JSON string, not an object
ParameterOverrides: !Join
- ''
- - '{ "SubdomainName": "'
- !If [ TargetsMainBranch, 'aiproxy-test', !Sub 'aiproxy-test-${GitHubBranch}' ]
- '" }'
- - '{'
- !Sub
- '"SubdomainName": "${SubdomainName}",'
- { SubdomainName: !If [ TargetsMainBranch, 'aiproxy-test', !Sub 'aiproxy-test-${GitHubBranch}' ] }
- !Sub '"ECRRepositoryArn": "${EcrRepository.Arn}",'
- !Sub
- '"VPC": "${VPCValue}",'
- { VPCValue: !ImportValue VPC }
- !Sub
- '"SecurityGroup": "${SecurityGroupValue}",'
- { SecurityGroupValue: !ImportValue VPC-ELBSecurityGroup }
- !Sub
- '"PublicSubnets": ${PublicSubnetsValue},'
- { PublicSubnetsValue: [!ImportValue VPC-PublicSubnetB, !ImportValue VPC-PublicSubnetC, !ImportValue VPC-PublicSubnetD, !ImportValue VPC-PublicSubnetE] }
- !Sub
- '"PrivateSubnets": ${PrivateSubnetsValue},'
- { PrivateSubnetsValue: [!ImportValue VPC-SubnetB, !ImportValue VPC-SubnetC, !ImportValue VPC-SubnetD, !ImportValue VPC-SubnetE] }
- '}'
Capabilities: CAPABILITY_AUTO_EXPAND,CAPABILITY_IAM
RoleArn: !Sub arn:aws:iam::${AWS::AccountId}:role/admin/CloudFormationService
- !Ref AWS::NoValue
Expand Down Expand Up @@ -353,11 +367,27 @@ Resources:
ActionMode: CREATE_UPDATE
TemplatePath: appBuildResults::packaged-app-template.yml
TemplateConfiguration: appBuildResults::cicd/3-app/aiproxy/production.config.json
# ParameterOverrides must be a JSON string, not an object
ParameterOverrides: !Join
- ''
- - '{ "SubdomainName": "'
- !If [ TargetsMainBranch, 'aiproxy', !Sub 'aiproxy-${GitHubBranch}' ]
- '" }'
- - '{'
- !Sub
- '"SubdomainName": "${SubdomainName}",'
- { SubdomainName: !If [ TargetsMainBranch, 'aiproxy', !Sub 'aiproxy-${GitHubBranch}' ] }
- !Sub '"ECRRepositoryArn": "${EcrRepository.Arn}",'
- !Sub
- '"VPC": "${VPCValue}",'
- { VPCValue: !ImportValue VPC }
- !Sub
- '"SecurityGroup": "${SecurityGroupValue}",'
- { SecurityGroupValue: !ImportValue VPC-ELBSecurityGroup }
- !Sub
- '"PublicSubnets": ${PublicSubnetsValue},'
- { PublicSubnetsValue: [!ImportValue VPC-PublicSubnetB, !ImportValue VPC-PublicSubnetC, !ImportValue VPC-PublicSubnetD, !ImportValue VPC-PublicSubnetE] }
- !Sub
- '"PrivateSubnets": ${PrivateSubnetsValue},'
- { PrivateSubnetsValue: [!ImportValue VPC-SubnetB, !ImportValue VPC-SubnetC, !ImportValue VPC-SubnetD, !ImportValue VPC-SubnetE] }
- '}'
Capabilities: CAPABILITY_AUTO_EXPAND,CAPABILITY_IAM
RoleArn: !Sub arn:aws:iam::${AWS::AccountId}:role/admin/CloudFormationService
- !Ref AWS::NoValue
Expand All @@ -384,6 +414,42 @@ Resources:
- Name: smokeTestResults
- !Ref AWS::NoValue


#-------------------------------------
# IAM Roles & Policies
#-------------------------------------

# Grant the AiProxy CodeBuild Role additional permissions for resources in
# this template. This allows us to avoid granting permission to * resources.
AiProxyRolePolicy:
Type: 'AWS::IAM::Policy'
Properties:
PolicyName: !Sub "${AWS::StackName}-codebuild-policy"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- codebuild:*
Resource:
- !GetAtt AppBuildProject.Arn
- !GetAtt IntegrationTestBuildProject.Arn
- Effect: Allow
Action:
- codebuild:CreateReportGroup
- codebuild:CreateReport
- codebuild:UpdateReport
- codebuild:BatchPutTestCases
- codebuild:BatchPutCodeCoverage
Resource:
- !Sub arn:aws:codebuild:us-east-1:165336972514:report-group/${AWS::StackName}-${GitHubBranch}-pr-build
Roles:
- !ImportValue AiProxyCodeBuildRoleName

#-------------------------------------
# Metrics & Notifications
#-------------------------------------

# Send pipeline events to an SNS topic.
# Note:
# Integration with Slack via AWS ChatBot is configured manually via AWS
Expand Down
59 changes: 38 additions & 21 deletions cicd/2-cicd/deploy-cicd.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,54 +8,71 @@ echo Deploying AiProxy CICD Pipeline
# - ENVIRONMENT_TYPE: Can be 'production' (default) or 'development', passed as a Parameter for "cicd/2-cicd/cicd.template.yml"
# - GITHUB_BADGE_ENABLED: defaults to true, passed as a Parameter for "cicd/2-cicd/cicd.template.yml"

# The branch name may become part of a domain name, so we need to validate it.
validate_branch_name() {
local branch_name=$1
if [[ ! $branch_name =~ ^[a-z0-9]([-a-z0-9]*[a-z0-9])$ ]]; then
echo "Invalid branch name '${branch_name}', branches must be alphanumeric and may contain hyphens."
exit 1
fi
}

# 'Developer' role requires a specific service role for all CloudFormation operations.
if [[ $(aws sts get-caller-identity --query Arn --output text) =~ "assumed-role/Developer/" ]]; then
# Append the role-arn option to the positional parameters $@ passed to cloudformation deploy.
set -- "$@" --role-arn "arn:aws:iam::$(aws sts get-caller-identity --query Account --output text):role/admin/CloudFormationService"
fi

# Default to main branch, but support pipelines using other branches
TARGET_BRANCH=${TARGET_BRANCH-'main'}
ENVIRONMENT_TYPE=${ENVIRONMENT_TYPE:-'production'}
GITHUB_BADGE_ENABLED=${GITHUB_BADGE_ENABLED:-'true'}
TARGET_BRANCH=${TARGET_BRANCH:-'main'}

if [ "$TARGET_BRANCH" == "main" ]
then
STACK_NAME="aiproxy-cicd"
else
# only allow alphanumeric branch names that may contain an internal hyphen.
# to avoid complicated logic elsewhere, we're constraining it here.
if [[ "$TARGET_BRANCH" =~ ^[a-z0-9]([-a-z0-9]*[a-z0-9])$ ]]; then
STACK_NAME="aiproxy-${TARGET_BRANCH}-cicd"
else
echo "Invalid branch name '${TARGET_BRANCH}', branches must be alphanumeric and may contain hyphens."
exit
fi
validate_branch_name "$TARGET_BRANCH"
STACK_NAME="aiproxy-${TARGET_BRANCH}-cicd"
fi

ENVIRONMENT_TYPE=${ENVIRONMENT_TYPE-'production'}
GITHUB_BADGE_ENABLED=${GITHUB_BADGE_ENABLED-'true'}

TEMPLATE_FILE=cicd/2-cicd/cicd.template.yml

echo Validating cloudformation template...
aws cloudformation validate-template \
--template-body file://${TEMPLATE_FILE} \
| cat
> /dev/null

ACCOUNT=$(aws sts get-caller-identity --query "Account" --output text)
REGION=$(aws configure get region)

read -r -p "Would you like to deploy this template to AWS account $ACCOUNT? [y/N] " response
read -r -p "Would you like to create a change set for this template in AWS account $ACCOUNT? [y/N] " response
if [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]]
then
echo Updating cloudformation stack...
aws cloudformation deploy \
echo Creating change set...
CHANGE_SET_NAME="${STACK_NAME}-changeset-$(date +%s)"
aws cloudformation create-change-set \
--stack-name $STACK_NAME \
--template-file $TEMPLATE_FILE \
--parameter-overrides GitHubBranch=$TARGET_BRANCH GitHubBadgeEnabled=$GITHUB_BADGE_ENABLED EnvironmentType=$ENVIRONMENT_TYPE \
--change-set-name $CHANGE_SET_NAME \
--template-body file://${TEMPLATE_FILE} \
--parameters ParameterKey=GitHubBranch,ParameterValue=$TARGET_BRANCH ParameterKey=GitHubBadgeEnabled,ParameterValue=$GITHUB_BADGE_ENABLED ParameterKey=EnvironmentType,ParameterValue=$ENVIRONMENT_TYPE \
--capabilities CAPABILITY_IAM \
--tags EnvType=${ENVIRONMENT_TYPE} \
--tags Key=EnvType,Value=${ENVIRONMENT_TYPE} \
"$@"

echo Complete!
echo "Change set created. You can review it at:"
echo "https://console.aws.amazon.com/cloudformation/home?region=$REGION#/stacks/changesets/changes?stackId=arn:aws:cloudformation:$REGION:$ACCOUNT:stack/$STACK_NAME/*&changeSetId=arn:aws:cloudformation:$REGION:$ACCOUNT:changeSet/$CHANGE_SET_NAME"

read -r -p "Would you like to execute the change set? [y/N] " response
if [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]]
then
echo Executing change set...
aws cloudformation execute-change-set \
--stack-name $STACK_NAME \
--change-set-name $CHANGE_SET_NAME
echo Complete!
else
echo Exiting...
fi
else
echo Exiting...
fi
Loading