This is the last part of the series for Infrastructure as Code: Deploying a Demo App on EC2 with AWS Image Builder and Terraform. On this part, I will focus more on GitHub Actions and how to utilize this CI/CD platform to deploy updates to your Infrastructure code.
Start with a Pre-defined Workflow File
GitHub Actions already provides a sample template to start. Simply search for the sample template in Actions tab, and click on the Configure button.
This will create a terraform.yml file with all the required steps for a Terraform deployment.
Let's walk through each one.
1. The Trigger
This part indicates different GitHub actions to trigger the workflow. The default actions triggers it with a push and pull request action. Since I want to trigger the workflow manually, I added a workflow dispatch action.
name: 'Terraform'
on:
push:
branches: [ "main" ]
pull_request:
workflow_dispatch:
2. Jobs
The next part will be the actions that will run. Below is the initialization of the GitHub runner (ubuntu-latest image) that will be spun up as the workflow runs.
jobs:
terraform:
name: 'Terraform'
runs-on: ubuntu-latest
environment: production
The other parts below have definitions in the sample file on what their purpose is:
steps:
# Checkout the repository to the GitHub Actions runner
- name: Checkout
uses: actions/checkout@v3
# Install the latest version of Terraform CLI and configure the Terraform CLI configuration file with a Terraform Cloud user API token
- name: Setup Terraform
uses: hashicorp/setup-terraform@v1
with:
cli_config_credentials_token: ${{ secrets.TF_API_TOKEN }}
# Initialize a new or existing Terraform working directory by creating initial files, loading any remote state, downloading modules, etc.
- name: Terraform Init
run: terraform init
# Checks that all Terraform configuration files adhere to a canonical format
- name: Terraform Format
run: terraform fmt -check
# Generates an execution plan for Terraform
- name: Terraform Plan
run: terraform plan -input=false
One customization that needs to be done is to create the Terraform API token (TF_API_TOKEN) which will be saved in GitHub secrets as it is an authentication header that will be used. We can generate a token by following this Terraform documentation: https://developer.hashicorp.com/terraform/tutorials/cloud-get-started/cloud-login. Type terraform login
and type yes on the prompt.
$ terraform login
Terraform will request an API token for app.terraform.io using your browser.
If login is successful, Terraform will store the token in plain text in
the following file for use by subsequent commands:
C:\Users\kayea\AppData\Roaming\terraform.d\credentials.tfrc.json
Do you want to proceed?
Only 'yes' will be accepted to confirm.
Enter a value: yes
---------------------------------------------------------------------------------
Terraform must now open a web browser to the tokens page for app.terraform.io.
If a browser does not open this automatically, open the following URL to proceed:
https://app.terraform.io/app/settings/tokens?source=terraform-login
---------------------------------------------------------------------------------
Generate a token using your browser, and copy-paste it into this prompt.
Terraform will store the token in plain text in the following file
for use by subsequent commands:
C:\Users\kayea\AppData\Roaming\terraform.d\credentials.tfrc.json
Token for app.terraform.io:
Enter a value:
On the browser, login to Terraform cloud, and you will be redirected to this page. You can type a name to identify this token, and set various expiration dates.
You can now save this token under GitHub Secrets
Go back to the GitHub actions template and commit the change:
Since the push
action triggers the workflow, you would see that updating the code will trigger the action:
3. Create an AWS credential
You'll notice that on the initial run, this would immediately fail on Terraform initialize. This is because we haven't configured any AWS credentials on the workflow. We can follow this documentation, or follow along below:
Before this can be done, we need to create an IAM role. Go to the AWS management console and create a role for Web Identity, adding the fields.
AWS also made it available to pre-generate the trust policy to be added to the role
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRoleWithWebIdentity",
"Principal": {
"Federated": "arn:aws:iam::111111111111:oidc-provider/token.actions.githubusercontent.com"
},
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": [
"sts.amazonaws.com"
]
},
"StringLike": {
"token.actions.githubusercontent.com:sub": [
"repo:coderkaye/*"
]
}
}
}
]
}
Now add the GitHub action below and add the ARN of the role created.
- name: Configure AWS credentials from Test account
uses: aws-actions/configure-aws-credentials@v3
with:
role-to-assume: arn:aws:iam::11111111111:role/aws-githubactions
aws-region: us-east-1
You also need to update the permissions of id-token to write
permissions:
id-token: write
contents: read
On this run, it will not automatically apply the Terraform code, but show the plan.
4. Final Updates
You can now update your pipeline to add specific GitHub Actions triggers. Some best practices for Infrastructure pipeline are below:
- Set a manual trigger of the workflow. We do not ever want to accidentally deploy infrastructure without proper review.
- Add tests. One Terraform feature is to be able to test the linting of your terraform code. This is one good test to add on top of other tests.
- Add approval checks. You can add notifications to your CI/CD pipeline to ensure that someone in authority is able to review the infrastructure being deployed before the infrastructure is actually updated.
If you have any questions or if any part is unclear, feel free to shoot a comment below!
Top comments (1)
interesting use case! nicely explained!