This is a Terraform module to configure GitLab as an IAM OIDC identity provider in AWS. It enables GitLab to access resources within an AWS account without requiring AWS credentials.
| Name | Version |
|---|---|
| terraform | ~> 1.0 |
| aws | ~> 4.0 |
| tls | 3.3.0 |
The following snippet shows the minimum required configuration to create a working OIDC connection between GitLab and AWS.
provider "aws" {
region = var.aws_region
}
module "aws_oidc_gitlab" {
for_each = var.gitlab
source = "../../"
iam_role_name = "gitlab_action_oidc_aws"
attach_admin_policy = true
create_oidc_provider = true
iam_policy_arns = []
gitlab_url = "https://gitlab.com"
audience = "https://gitlab.com"
match_field = each.value.match_field
match_value = each.value.match_value
}-
attach_admin_policyis the flag to enable or disable the attachment of the AdministratorAccess policy to the IAM role. aws_managed_policy_arnsis a list of AWS Managed IAM policy ARNs to attach to the IAM role such as S3FullAccessgitlab_urlis the address of your GitLab instance, such as https://gitlab.com or http://gitlab.example.com.audienceis the same asgitlab_urlmatch_valueIt should be your Gitlab Instance URl such as https://gitlab.example.com or a filter to a specific gitlab group, branch or tag such as project_path:mygroup/myproject:ref_type:branch:ref:main.match_fieldIf you use a filter to specific GitLab group, branch or tag asmatch_value, usesub. Useaudif you use GitLab instance url such as https://gitlab.com asmatch_value
By default, any GitLab user would be able to assume the role if he knows this IAM role's ARN. So, we need to lock it down by adding a condition in the assume-role policy document. Go to the tab Trust relationships and replace the existing condition with:
Here is how I declare the conditions in the module configuration.
condition {
test = "StringEquals"
values = var.match_value
variable = "${aws_iam_openid_connect_provider.gitlab[0].url}:${var.match_field}"
}Below condition allows any GitLab project to retrieve temporary credentials from AWS Security Token Service (STS). Use aud if you use GitLab instance url such as https://gitlab.com as match_value . aud means the URL of the GitLab instance. This is defined when the identity provider is first configured in your cloud provider.
condition {
test = "StringEquals"
values = var.match_value # https//gitlab.com
variable = "${aws_iam_openid_connect_provider.gitlab[0].url}:${var.match_field}" # gitlab.com:aud
}Trusted Entities look liks
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::585584209241:oidc-provider/gitlab.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"gitlab.com:aud": "https://gitlab.com"
}
}
}
]
}sub is a concatenation of metadata describing the GitLab CI/CD workflow including the group, project, branch, and tag. The sub field is in the following format:
project_path:{gitlab_group_id}/{project_name}:ref_type:{type}:ref:{branch_name}
| Filter | Example |
|---|---|
| Filter to main branch | project_path:mygroup/myproject:ref_type:branch:ref:main |
| Filter to any branch | Wildcard supported. project_path:mygroup/myproject:ref_type:branch:ref:* |
| Filter to specific project | project_path:mygroup/myproject:ref_type:branch:ref:main |
| Filter to all projects under a group | Wildcard supported. project_path:mygroup/*:ref_type:branch:ref:main |
| Filter to a Git tag | Wildcard supported. project_path:mygroup/*:ref_type:tag:ref:1.0 |
Trusted Entities look like
"Condition": {
"StringEquals": {
"gitlab.com:sub": "project_path:{group_id}/{project_name}:ref_type:branch:ref:main
}
}| Name | Description | Type | Default | Required |
|---|---|---|---|---|
| gitlab_url | The address of your GitLab instance, such as https://gitlab.com or http://gitlab.example.com. | string |
"https://gitlab.com" |
yes |
| audience | The address of your GitLab instance, such as https://gitlab.com or http://gitlab.example.com. | string |
"https://gitlab.com" |
yes |
| iam_role_policy_arns | List of IAM policy ARNs to attach to the IAM role. | list(string) |
[] |
optional |
| create_oidc_provider | Flag to enable/disable the creation of the GitHub OIDC provider. | bool |
true |
yes |
| match_field | Issuer, the domain of your GitLab instance. Change to sub if you want to use the filter to any project | string |
aud | yes |
| match_value | It should be your Gitab Instance URl by default. But if you want to use filer to a specific group, branch or tag, use this format project_path:mygroup/myproject:ref_type:branch:ref:main | list |
GitLab Instance URL | yes |
| Name | Description | Type | Default | Required |
|---|---|---|---|---|
| attach_admin_policy | Flag to enable/disable the attachment of the AdministratorAccess policy. | bool |
false |
no |
| iam_role_name | Name of the IAM role to be created. This will be assumable by GitLab. | string |
"gitlab_action_role" |
no |
| iam_role_path | Path under which to create IAM role. | string |
"/" |
no |
| max_session_duration | Maximum session duration in seconds. | number |
3600 |
no |
| Name | Description |
|---|---|
| iam_role_arn | ARN of the IAM role. |
variables:
REGION: us-east-1
ROLE_ARN: arn:aws:iam::${AWS_ACCOUNT_ID}:role/gitlab_action_role
image:
name: amazon/aws-cli:latest
entrypoint:
- '/usr/bin/env'
assume role:
script:
- >
STS=($(aws sts assume-role-with-web-identity
--role-arn ${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]}"
- export AWS_REGION="$REGION"
- aws sts get-caller-identity
- aws s3 ls
- aws iam list-users© 2021 Daniel Morris
Made available under the terms of the Apache License 2.0.
