Learn how to prepare your application to take it from your development environment into a deployment ready to receive users.
- Create new CloudCity accounts for staging and production
- Register for AWS VPN and AWS SSO
- Create root AWS
- Create two AWS accounts, for staging and production
- If desired, set up AWS Control Tower
-
Use terraform to deploy CRUD application infrastructure, with template provided in a separate repository. This includes:
- VPCs
- Subnets
- Security Groups
- ECS (preferred) or Elastic Beanstalk (legacy)
- RDS
-
Stash the following secrets for GitHub Actions:
- AWS access keys
- Elastic Container Registry details
- Environment Names
-
Stash secrets in AWS Systems Manager Parameter Store. The actual secrets to store are defined in ecs-task-definition.json
-
Use the following branch names for deploying:
staging
- deploys to stagingmaster
orrelease
- deploys to production
-
Wire the deploy GitHub Action to be invoked on push to the designated branch names
-
Obtain Amazon Certificate Manager (ACM) SSL certificates for the domain associated with the application
- Configure DNS entries in Cloudflare to facilitate this, following instructions from AWS
-
Create DNS entries on Cloudflare that point the root domain and www subdomain to the load balancer
-
Create DNS entries on Cloudflare so that Google Groups can be used for mail addresses with the domain name associated with the application
The GitHub Actions CI workflow (ci.yml
) uses GitHub OIDC to authenticate with AWS.
This has several benefits over using AWS access keys:
- The credentials are short-lived, and can be revoked at any time
- Fine grained access control for credentials
Read more on OIDC here.
The simplest way to set this up is using CloudFormation. In the root AWS account, create a CloudFormation stack:
Parameters:
GitHubOrg:
Type: String
RepositoryName:
Type: String
OIDCProviderArn:
Description: Arn for the GitHub OIDC Provider.
Default: ""
Type: String
Conditions:
CreateOIDCProvider: !Equals
- !Ref OIDCProviderArn
- ""
Resources:
Role:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Action: sts:AssumeRoleWithWebIdentity
Principal:
Federated: !If
- CreateOIDCProvider
- !Ref GithubOidc
- !Ref OIDCProviderArn
Condition:
StringLike:
token.actions.githubusercontent.com:aud: sts.amazonaws.com
token.actions.githubusercontent.com:sub: !Sub repo:${GitHubOrg}/${RepositoryName}:*
Policies: # TODO - Attach any other policies you need to deploy your app (ECR, EB)
- PolicyName: DeployToSomeS3Bucket
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- s3:DeleteObject
- s3:GetBucketLocation
- s3:GetObject
- s3:ListBucket
- s3:PutObject
- s3:ListObjectsV2
Resource: arn:aws:s3:::<s3-bucket-name>/*
GithubOidc:
Type: AWS::IAM::OIDCProvider
Condition: CreateOIDCProvider
Properties:
Url: https://token.actions.githubusercontent.com
ClientIdList:
- sts.amazonaws.com
ThumbprintList:
- 6938fd4d98bab03faadb97b34396831e3780aea1
- 1c58a3a8518e8759bf075b76b750d4f2df264fcd
Outputs:
Role:
Value: !GetAtt Role.Arn
The stack creates a role that is assumed by the GitHub Action. The stack provided allows the role to sync with an S3 bucket. You must add any policies required to deploy your application to that role.
The stack will prompt for a few inputs:
GitHubOrg
: This should be eitherdatagovsg
oropengovsg
RepositoryName
: The repository the GitHub Action will run onOIDCProviderARN
:- If a GitHub OIDC provider already exists in the account, use the ARN of the provider
- Else leave this field blank, and the stack will create a new provider
After creating the resources, navigate to the GitHub OIDC Provider created, and copy the ARN.
In the GitHub Action's env vars, set:
AWS_ROLE_ARN
: the copied ARNAWS_REGION
: the region of the AWS account
That's it!
Terraform version coming soon...