Automagically deploying Architect Framework applications to AWS uisng GitLab CI

Featured image for sharing metadata for article

I have a number of services that I use the Architect Framework, as it's really handy for creating an event-based, multi-Lambda (HTTP) application.

Up until today, I've been manually deploying these from my local machine, which isn't ideal, as it means contributions from external contributors, or when I'm only able to access my phone, I can't get deployments released.

I'm a heavy user of GitLab and GitLab CI, and so I wanted to set up deployments as part of this.

One option is to add long-lived AWS access keys to GitLab CI, and regularly rotate them, but that's a bit of a pain.

With GitLab's recent support for OpenID Connect Authentication for cloud services, we can avoid the need for long-lived credentials, and instead use the OpenID Connect support in AWS to allow us to grant limited access to jobs using an ID Token for a specific job.

This ID Token is stored in the CI_JOB_JWT_V2 environment variable, and unpacks to the following sample payload:

{
  "alg": "RS256",
  "kid": "4i3sFE7sxqNPOT7FdvcGA1ZVGGI_r-tsDXnEuYT4ZqE",
  "typ": "JWT"
}
{
  "namespace_id": "305304",
  "namespace_path": "jamietanna",
  "project_id": "34472568",
  "project_path": "jamietanna/opengraph-mf2",
  "user_id": "259647",
  "user_login": "jamietanna",
  "user_email": "gitlab@jamietanna.co.uk",
  "pipeline_id": "504771836",
  "pipeline_source": "push",
  "job_id": "2269345391",
  "ref": "feature/deploy",
  "ref_type": "branch",
  "ref_protected": "false",
  "jti": "e4e29fdd-0dee-4c9b-86c7-31eadcc28f72",
  "iss": "https://gitlab.com",
  "iat": 1648637774,
  "nbf": 1648637769,
  "exp": 1648641374,
  "sub": "project_path:jamietanna/opengraph-mf2:ref_type:branch:ref:feature/deploy",
  "aud": "https://gitlab.com"
}

Alongside GitLab's documentation for AWS setup as well as the section on conditional role setup, we can produce the following IAM role Trust Policy:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "arn:aws:iam::<redacted>:oidc-provider/gitlab.com"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "gitlab.com:aud": "https://gitlab.com",
          "gitlab.com:sub": "project_path:jamietanna/opengraph-mf2:ref_type:branch:ref:main"
        }
      }
    }
  ]
}

As noted in the Architect docs, the role needs the AdministratorAccess managed policy associated with it.

This then allows the role to be assumed using the following GitLab CI snippet:

- >
  STS=($(aws sts assume-role-with-web-identity
  --role-arn ${ARC_ROLE_ARN}
  --role-session-name "GitLabRunner-${CI_PROJECT_ID}-${CI_PIPELINE_ID}"
  --web-identity-token $CI_JOB_JWT_V2
  --duration-seconds 3600
  --query 'Credentials.[AccessKeyId,SecretAccessKey,SessionToken]'
  --output text))  
- export AWS_ACCESS_KEY_ID="${STS[0]}"
- export AWS_SECRET_ACCESS_KEY="${STS[1]}"
- export AWS_SESSION_TOKEN="${STS[2]}"
# then, for example
- aws sts get-caller-identity

Note that ARC_ROLE_ARN is a protected and masked Variable in GitLab CI, for the role that has the Trust Policy noted above.

This allows us to then have the following GitLab CI setup:

image: node:16

stages:
  - deploy

deploy:
  stage: deploy
  only:
    refs:
    - main
  before_script:
    # as it's not available in the Node image
    - apt update && apt install -y awscli
    # prepare for future steps
    - >
      STS=($(aws sts assume-role-with-web-identity
      --role-arn ${ARC_ROLE_ARN}
      --role-session-name "GitLabRunner-${CI_PROJECT_ID}-${CI_PIPELINE_ID}"
      --web-identity-token $CI_JOB_JWT_V2
      --duration-seconds 3600
      --query 'Credentials.[AccessKeyId,SecretAccessKey,SessionToken]'
      --output text))      
    - export AWS_ACCESS_KEY_ID="${STS[0]}"
    - export AWS_SECRET_ACCESS_KEY="${STS[1]}"
    - export AWS_SESSION_TOKEN="${STS[2]}"
  script:
    - npm install
    - npm exec arc deploy production

Written by Jamie Tanna's profile image Jamie Tanna on , and last updated on .

Content for this article is shared under the terms of the Creative Commons Attribution Non Commercial Share Alike 4.0 International, and code is shared under the Apache License 2.0.

#blogumentation #oidc #architect-framework #aws #gitlab #gitlab-ci.

Also on:

This post was filed under articles.

Interactions with this post

Interactions with this post

Below you can find the interactions that this page has had using WebMention.

Have you written a response to this post? Let me know the URL:

Do you not have a website set up with WebMention capabilities? You can use Comment Parade.