Automate AWS Account Creation with GitLab
This guide provides a step-by-step process to automate the creation of a new AWS account and associated resources using GitLab and Port.
This guide assumes you have:
- A Port account and that you have completed the onboarding process.
- A GitLab account with a repository set up for CI/CD.
Step 1: Copy Configuration Filesโ
First, copy the following files into your GitLab repository:
.gitlab-ci.yml
Click to expand
stages:
- prerequisites
- terraform
- port-update
image:
name: hashicorp/terraform:light
entrypoint:
- '/usr/bin/env'
- 'PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'
variables:
AWS_ACCESS_KEY_ID: ${TF_USER_AWS_KEY}
AWS_SECRET_ACCESS_KEY : ${TF_USER_AWS_SECRET}
AWS_DEFAULT_REGION: ${TF_USER_AWS_REGION}
PORT_CLIENT_ID: ${PORT_CLIENT_ID}
PORT_CLIENT_SECRET: ${PORT_CLIENT_SECRET}
before_script:
- rm -rf .terraform
- export AWS_ACCESS_KEY=${AWS_ACCESS_KEY_ID}
- export AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
- export AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION}
- apk update
- apk add --upgrade curl jq -q
fetch-port-access-token:
stage: prerequisites
except:
- pushes
script:
- |
echo "Getting access token from Port API"
accessToken=$(curl -X POST \
-H 'Content-Type: application/json' \
-d '{"clientId": "'"$PORT_CLIENT_ID"'", "clientSecret": "'"$PORT_CLIENT_SECRET"'"}' \
-s 'https://api.getport.io/v1/auth/access_token' | jq -r '.accessToken')
echo "ACCESS_TOKEN=$accessToken" >> data.env
cat $TRIGGER_PAYLOAD
runId=$(cat $TRIGGER_PAYLOAD | jq -r '.RUN_ID')
ACCOUNT_NAME=$(cat $TRIGGER_PAYLOAD | jq -r '.account_name')
EMAIL=$(cat $TRIGGER_PAYLOAD | jq -r '.email')
IAM_ROLE_NAME=$(cat $TRIGGER_PAYLOAD | jq -r '.role_name')
echo "RUN_ID=$runId" >> data.env
echo "ACCOUNT_NAME=$ACCOUNT_NAME" >> data.env
echo "EMAIL=$EMAIL" >> data.env
echo "IAM_ROLE_NAME=$IAM_ROLE_NAME" >> data.env
curl -X POST \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $accessToken" \
-d '{"message":"๐โโ๏ธ Starting action to create an AWS account"}' \
"https://api.getport.io/v1/actions/runs/$runId/logs"
curl -X PATCH \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $accessToken" \
-d '{"link":"'"$CI_PIPELINE_URL"'"}' \
"https://api.getport.io/v1/actions/runs/$runId"
artifacts:
reports:
dotenv: data.env
create-aws-account:
stage: terraform
needs:
- job: fetch-port-access-token
artifacts: true
script:
- echo "Creating AWS account and IAM role..."
- terraform init
- terraform apply -auto-approve -var "account_name=${ACCOUNT_NAME}" -var "email=${EMAIL}" -var "iam_role_name=${IAM_ROLE_NAME}"
send-data-to-port:
stage: port-update
dependencies:
- fetch-port-access-token
script:
- |
curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d "{\"identifier\": \"${EMAIL}\", \
\"title\": \"${ACCOUNT_NAME}\", \
\"properties\": { \
\"account_name\": \"${ACCOUNT_NAME}\", \
\"email\": \"${EMAIL}\", \
\"iam_role_name\": \"${IAM_ROLE_NAME}\", \
\"additional_data\": \"Your additional data here\" \
}, \
\"relations\": {}}" \
"https://api.getport.io/v1/blueprints/awsAccountBlueprint/entities?run_id=$RUN_ID"
curl -X PATCH \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d '{"status": "SUCCESS", "message": {"run_status": "Run completed successfully!"}}' \
"https://api.getport.io/v1/actions/runs/$RUN_ID"
main.tf
Click to expand
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.0"
}
}
}
provider "aws" {
region = var.region
}
resource "aws_organizations_account" "account" {
name = var.name
email = var.email
role_name = var.role_name
close_on_deletion = true
lifecycle {
ignore_changes = [role_name]
}
}
variables.tf
Click to expand
variable "region" {
description = "AWS region where resources will be created"
type = string
default = "us-east-1"
}
variable "name" {
description = "Name of the AWS account to be created"
type = string
default = "newAccount"
}
variable "email" {
description = "Email to attach to the AWS account"
type = string
default = "example@example.com"
}
variable "role_name" {
description = "Name of the IAM role to attach"
type = string
default = "IAMRole"
}
outputs.tf
Click to expand
output "account_name" {
value = aws_organizations_account.account.name
}
output "email" {
value = aws_organizations_account.account.email
}
output "role_name" {
value = aws_organizations_account.account.role_name
}
These files contain the necessary Terraform and GitLab CI configurations to automate AWS account creation.
Step 2: Configure GitLab Secretsโ
In GitLab, navigate to your project's Settings > CI / CD > Variables and add the required secrets.
- PORT_CLIENT_ID
- PORT_CLIENT_SECRET
- TF_USER_AWS_KEY
- TF_USER_AWS_REGION
- TF_USER_AWS_SECRET
These secrets are necessary for the Terraform scripts to execute correctly.
Step 3: Configure GitLab Webhookโ
In GitLab, navigate to your project's Settings > CI / CD > Pipeline trigger tokens and add new token. Then in View trigger token usage examples you can find the Webhook URL address ander Use webhook
This URL is necessary for triggering the Pipeline from the Self Service Action.
Step 4: Add AWS Account Blueprint in Portโ
Next, create a new blueprint in Port using the aws_account.json
file. This blueprint represents an AWS account in your software catalog.
Example Blueprint: aws_account.json
โ
Click to expand
{
"identifier": "awsAccountBlueprint",
"description": "This blueprint represents an AWS account in our software catalog.",
"title": "AWS account",
"icon": "AWS",
"schema": {
"properties": {
"role_name": {
"type": "string",
"title": "Role Name",
"description": "The name of the IAM role."
},
"account_name": {
"type": "string",
"title": "Account Name",
"description": "The name for the account."
},
"email": {
"type": "string",
"title": "Email",
"description": "The email for the account."
}
},
"required": [
"email",
"account_name"
]
},
"relations": {}
}
Step 5: Create Self-Service Action in Portโ
Create a new self-service action using the self-service-action.json
file. This action will trigger the AWS account creation process.
Example Self-Service Action: self-service-action.json
โ
Click to expand
Make sure to change 'WEBHOOK-URL-FROM-GITLAB' into your webhook URL from gitlab.
{
"identifier": "gitlabAwsAccountBlueprint_create_an_aws_account",
"title": "Create An AWS Account with GitLab",
"icon": "AWS",
"description": "Automate the creation of a new AWS account and associated resources.",
"trigger": {
"type": "self-service",
"operation": "CREATE",
"userInputs": {
"properties": {
"account_name": {
"icon": "AWS",
"title": "Account Name",
"description": "The desired name for the new AWS account",
"type": "string"
},
"email": {
"icon": "DefaultProperty",
"title": "Email",
"description": "The email address associated with the new AWS account",
"type": "string",
"pattern": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
},
"iam_role_name": {
"title": "IAM Role Name",
"description": "The name of the IAM role to be created for management purposes",
"type": "string"
}
},
"required": [
"account_name",
"email"
],
"order": [
"account_name",
"email",
"iam_role_name"
]
},
"blueprintIdentifier": "awsAccountBlueprint"
},
"invocationMethod": {
"type": "WEBHOOK",
"url": "WEBHOOK-URL-FROM-GITLAB",
"method": "POST",
"headers": {
"RUN_ID": "{{ .run.id }}"
},
"body": {
"RUN_ID": "{{ .run.id }}",
"account_name": "{{ .inputs."account_name" }}",
"email": "{{ .inputs."email" }}",
"iam_role_name": "{{ .inputs."iam_role_name" }}"
}
},
"requiredApproval": false,
"publish": true
}
Include the Run IDโ
Ensure that you include the RUN_ID in the body of the webhook, as illustrated in the example above. This ID is crucial for tracking the execution of the self-service action.
Conclusionโ
By following these steps, you can automate the creation of new AWS accounts using GitLab CI/CD and Port self-service actions.