Streamline AWS Deployments with GitLab CI and Terraform
A step-by-step guide for deploying infrastructure using CI/CD.
About | |
---|---|
✅ AWS Level | Intermediate - 200 |
⏱ Time to complete | 45 minutes |
💰 Cost to complete | Free Tier Eligible |
🧩 Prerequisites | AWS Account and GitLab Account |
📢 Feedback | Any feedback, issues, or just a 👍 / 👎 |
⏰ Last Updated | 2023-12-18 |
1
2
3
resource "aws_sqs_queue" "queue" {
name = "sample-queue"
}
https://gitlab.com
as well as the Audience. The provider URL is the URL from which the OpenID configuration is obtained. You can view the OpenID configuration for GitLab yourself by navigating to gitlab.com/.well-known/openid-configuration. Note that if you are using a self-managed instance of GitLab (that is publicly available on the internet) you would need to use the root URL of that instance instead of gitlab.com. In this case, check that your instance supports OpenID connect by navigating to the OpenID configuration URL using your instance's root domain.- AmazonS3FullAccess
- AmazonDynamoDBFullAccess
- AmazonSQSFullAccess
1
2
3
4
5
{
"StringLike": {
"gitlab.com:sub":"project_path:{GITLAB_GROUP}/{GITLAB_PROJECT}:ref_type:branch:ref:{GITLAB_BRANCH}"
}
}
{GITLAB_GROUP}
with your username (eg. kaizadwadia
), {GITLAB_PROJECT}
with your project slug (ie. my-terraform-queue
), and {GITLAB_BRANCH}
with main
. This will ensure that only pipelines running on the main branch of the specific repository has permissions to assume this role. Moreover, note that while the "StringEquals" condition would work here, we can also use wildcards like "*" within the condition statement using the "StringLike" condition. This allows for more complex permissions assignments such as allowing any repository under your username to assume this role. The trust policy should now look something like this:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::{AWS_ACCOUNT_ID}:oidc-provider/gitlab.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringLike": {
"gitlab.com:sub": "project_path:kaizadwadia/my-terraform-queue:ref_type:branch:ref:main"
}
}
}
]
}
.gitlab-ci.yml
file in the root of our repository. See the first section on how to create and edit files using the Web IDE in GitLab. Once we have created the .gitlab-ci.yml
file, we will add the following stage to it:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
stages:
- deploy
deploy:
stage: deploy
only:
- main
image:
name: hashicorp/terraform:light
entrypoint: [""]
id_tokens:
GITLAB_OIDC_TOKEN:
aud: https://gitlab.com
before_script:
- echo "${GITLAB_OIDC_TOKEN}" > /tmp/web_identity_token
- mkdir ~/.aws
- echo -e "[profile oidc]\nrole_arn=${ROLE_ARN}\nweb_identity_token_file=/tmp/web_identity_token" >> ~/.aws/config
script:
- terraform init
- terraform apply -auto-approve
GITLAB_OIDC_TOKEN
and available in the container to use. In the before_script
, we are performing the configuration used in the process that assumes the IAM role with the web identity token and saving it under the AWS CLI profile called "oidc". Profiles in the AWS CLI allow you to configure and store credentials and settings for different AWS accounts or IAM users, keeping them separate and switching between them easily. Save the YAML file, and in the next section, we will bring everything together and deploy the code to AWS.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Configure backend for state management
terraform {
backend "s3" {
bucket = "terraform-state-bucket-XXXX"
key = "statefile.tfstate"
dynamodb_table = "terraform-state-lock-table"
encrypt = true
profile = "oidc"
}
}
# Configure the AWS Provider
provider "aws" {
profile = "oidc"
}
- The SQS Queue created by Terraform
- The S3 bucket we created to store the Terraform state files
- The DynamoDB Table called "terraform-state-lock-table"
- The IAM Role, "GitLabRole" and Identity Provider, "gitlab.com"
Any opinions in this post are those of the individual author and may not reflect the opinions of AWS.