Skip to content

Commit

Permalink
Merge pull request #68 from adamwolfe-tc/docs/verbiage_and_examples_u…
Browse files Browse the repository at this point in the history
…pdate

docs: verbiage and examples update
  • Loading branch information
ivankatliarchuk authored Jul 26, 2024
2 parents 6cae72f + f17a98e commit ad489a3
Show file tree
Hide file tree
Showing 8 changed files with 128 additions and 53 deletions.
66 changes: 48 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
# AWS GitLab OIDC Provider Terraform Module

This module allows you to create a GitHub OIDC provider and the associated IAM roles, that will help Github Actions to securely authenticate against the AWS API using an IAM role.
This module allows you to create an AWS IAM OIDC provider that trusts GitLab and the associated IAM roles, that will help GitLab Pipelines to securely authenticate against the AWS API using an IAM role.

We recommend using GitHub's OIDC provider to get short-lived credentials needed for your actions. Specifying role-to-assume without providing an aws-access-key-id or a web-identity-token-file will signal to the action that you wish to use the OIDC provider. The default session duration is 1 hour when using the OIDC provider to directly assume an IAM Role. The default session duration is 6 hours when using an IAM User to assume an IAM Role (by providing an aws-access-key-id, aws-secret-access-key, and a role-to-assume) . If you would like to adjust this you can pass a duration to role-duration-seconds, but the duration cannot exceed the maximum that was defined when the IAM Role was created. The default session name is GitHubActions, and you can modify it by specifying the desired name in role-session-name.
We recommend using GitLab's OIDC issuer to get short-lived credentials needed for your pipelines. Specifying role-to-assume without providing an aws-access-key-id or a web-identity-token-file will signal to the pipeline that you wish to use the OIDC provider. The default session duration is 1 hour when using the OIDC provider to directly assume an IAM Role. The default session duration is 6 hours when using an IAM User to assume an IAM Role (by providing an aws-access-key-id, aws-secret-access-key, and a role-to-assume) . If you would like to adjust this you can pass a duration to role-duration-seconds, but the duration cannot exceed the maximum that was defined when the IAM Role was created. The default session name is `GitLabRunner-${CI_PROJECT_ID}-${CI_PIPELINE_ID}`, and you can modify it by specifying the desired name in role-session-name.

## Use-Cases

1. Retrieve temporary credentials from AWS to access cloud services
1. Use credentials to retrieve secrets or deploy to an environment
1. Scope role to branch or project
1. Create an AWS OIDC provider for GitHub Actions
1. Create an AWS OIDC provider for GitLab Pipelines

## Features

2. Create one or more IAM role that can be assumed by GitHub Actions
2. Create one or more IAM role that can be assumed by GitLab Pipelines
3. IAM roles can be scoped to :
* One or more GitHub organisations
* One or more GitHub repository
* One or more branches in a repository
* One or more GitLab namespaces
* One or more GitLab project
* One or more branches in a project

| Feature | Status |
|--------------------------------------------------------------------------------------------------------|--------|
| Create a role for all repositories in a specific Github organisation ||
| Create a role specific to a repository for a specific organisation ||
| Create a role specific to a branch in a repository ||
| Create a role for multiple organisations/repositories/branches ||
| Create a role for organisations/repositories/branches selected by wildcard (e.g. `feature/*` branches) ||
| Create a role for all projects in a specific GitLab namespace ||
| Create a role specific to a project for a specific namespace ||
| Create a role specific to a branch in a project ||
| Create a role for multiple namespaces/projects/branches ||
| Create a role for namesapces/projectss/branches selected by wildcard (e.g. `feature/*` branches) ||

---

Expand Down Expand Up @@ -57,14 +57,14 @@ We recommend using GitHub's OIDC provider to get short-lived credentials needed
IMPORTANT: The master branch is used in source just as an example. In your code, do not pin to master because there may be breaking changes between releases. Instead pin to the release tag (e.g. ?ref=tags/x.y.z) of one of our [latest releases](https://github.com/terraform-module/terraform-aws-gitlab-oidc-provider/releases).

```hcl
module "gitlab-oidc" {
module "gitlab_oidc" {
source = "terraform-module/gitlab-oidc-provider/aws"
version = "~> 1"
create_oidc_provider = true
create_oidc_role = true
repositories = ["terraform-module/module-blueprint"]
project_paths = ["project_path:terraform-module/module-blueprint", "project_path:foo/bar"]
oidc_role_attach_policies = ["arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"]
}
```
Expand All @@ -81,35 +81,65 @@ See `examples` directory for working examples to reference
## Available features

<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
# AWS Gitlab OIDC Provider Terraform Module

## Purpose
This module allows you to create a Gitlab OIDC provider for your AWS account, that will allow Gitlab pipelines to securely authenticate against the AWS API using an IAM role

## Requirements

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.40 |
| <a name="requirement_tls"></a> [tls](#requirement\_tls) | >= 3.0 |

## Providers

No providers.
| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.40 |
| <a name="provider_tls"></a> [tls](#provider\_tls) | >= 3.0 |

## Modules

No modules.

## Resources

No resources.
| Name | Type |
|------|------|
| [aws_iam_openid_connect_provider.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_openid_connect_provider) | resource |
| [aws_iam_role.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
| [aws_iam_role_policy_attachment.attach](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
| [aws_iam_policy_document.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [tls_certificate.gitlab](https://registry.terraform.io/providers/hashicorp/tls/latest/docs/data-sources/certificate) | data source |

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_variable"></a> [variable](#input\_variable) | defaul,description,type | `string` | `"variable"` | no |
| <a name="input_aud_value"></a> [aud\_value](#input\_aud\_value) | (Required) A list of client IDs (also known as audiences). When a mobile or web app registers with an OpenID Connect provider, they establish a value that identifies the application. (This is the value that's sent as the client\_id parameter on OAuth requests.) | `list(string)` | <pre>[<br> "https://gitlab.com"<br>]</pre> | no |
| <a name="input_create_oidc_provider"></a> [create\_oidc\_provider](#input\_create\_oidc\_provider) | Whether or not to create the associated oidc provider. If false, variable 'oidc\_provider\_arn' is required | `bool` | `true` | no |
| <a name="input_create_oidc_role"></a> [create\_oidc\_role](#input\_create\_oidc\_role) | Whether or not to create the OIDC attached role | `bool` | `true` | no |
| <a name="input_gitlab_tls_url"></a> [gitlab\_tls\_url](#input\_gitlab\_tls\_url) | the Hashicorp TLS provider has started following redirects starting v4. so we use tls:// | `string` | `"tls://gitlab.com:443"` | no |
| <a name="input_match_field"></a> [match\_field](#input\_match\_field) | the token field the OIDC provider filter on | `string` | `"sub"` | no |
| <a name="input_max_session_duration"></a> [max\_session\_duration](#input\_max\_session\_duration) | Maximum session duration in seconds. | `number` | `3600` | no |
| <a name="input_oidc_role_attach_policies"></a> [oidc\_role\_attach\_policies](#input\_oidc\_role\_attach\_policies) | Attach policies to OIDC role. | `list(string)` | `[]` | no |
| <a name="input_projects"></a> [projects](#input\_projects) | List of GitLab namesapce/project names authorized to assume the role. | `list(string)` | `[]` | no |
| <a name="input_role_description"></a> [role\_description](#input\_role\_description) | (Optional) Description of the role. | `string` | `"Role assumed by the Gitlab OIDC provider."` | no |
| <a name="input_role_name"></a> [role\_name](#input\_role\_name) | (Optional, Forces new resource) Friendly name of the role. | `string` | `"gitlab-oidc-provider-aws"` | no |
| <a name="input_tags"></a> [tags](#input\_tags) | A mapping of tags to assign to all resources | `map(string)` | `{}` | no |
| <a name="input_url"></a> [url](#input\_url) | GitLab OpenID TLS certificate URL. The address of your GitLab instance, such as https://gitlab.com or http://gitlab.example.com. | `string` | `"https://gitlab.com"` | no |

## Outputs

| Name | Description |
|------|-------------|
| <a name="output_used"></a> [used](#output\_used) | used value |
| <a name="output_oidc_provider_arn"></a> [oidc\_provider\_arn](#output\_oidc\_provider\_arn) | OIDC provider ARN |
| <a name="output_oidc_role"></a> [oidc\_role](#output\_oidc\_role) | CICD GitHub role. |
| <a name="output_policy_document"></a> [policy\_document](#output\_policy\_document) | joined IAM policy documents |
| <a name="output_thumbprint"></a> [thumbprint](#output\_thumbprint) | TLS endpoint certificate SHA1 Fingerprint |
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->


Expand Down
31 changes: 30 additions & 1 deletion examples/basic/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Example

Configuration in this directory creates a MySQL Aurora cluster.
Configuration in this directory creates an AWS IAM OpenID Connect Provider, IAM Role and IAM Role Policy for trusing the OIDC provider.

## Usage

Expand All @@ -15,5 +15,34 @@ $ terraform apply
Note that this example may create resources which cost money. Run `terraform destroy` when you don't need these resources.

<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
## Requirements

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.0 |

## Providers

No providers.

## Modules

| Name | Source | Version |
|------|--------|---------|
| <a name="module_gitlab_oidc"></a> [gitlab\_oidc](#module\_gitlab\_oidc) | ../.. | n/a |

## Resources

No resources.

## Inputs

No inputs.

## Outputs

| Name | Description |
|------|-------------|
| <a name="output_oidc_provider_arn"></a> [oidc\_provider\_arn](#output\_oidc\_provider\_arn) | OIDC provider ARN |
| <a name="output_oidc_role"></a> [oidc\_role](#output\_oidc\_role) | CICD GiLab role. |
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
8 changes: 6 additions & 2 deletions examples/basic/main.tf
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
terraform {
required_version = ">= 1.0"
}

################################################################################
# Resources
################################################################################

module "gitlab-oidc" {
module "gitlab_oidc" {
source = "../.."

create_oidc_provider = true
create_oidc_role = true

repositories = ["terraform-module/terraform-aws-github-oidc-provider"]
project_paths = ["project_path:terraform-module/terraform-aws-gitlab-oidc-provider"]
oidc_role_attach_policies = ["arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"]
}

Expand Down
5 changes: 4 additions & 1 deletion gitlab/.gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,17 @@ authenticate:
entrypoint: [""]
variables:
ROLE_ARN: arn:aws:iam::XXXXXXXXXXX:role/gitlab-oidc-provider-aws
id_tokens:
GITLAB_OIDC_TOKEN:
aud: https://gitlab.com
script:
- aws --version
- >
export $(printf "AWS_ACCESS_KEY_ID=%s AWS_SECRET_ACCESS_KEY=%s AWS_SESSION_TOKEN=%s"
$(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
--web-identity-token $GITLAB_OIDC_TOKEN
--duration-seconds 3600
--query 'Credentials.[AccessKeyId,SecretAccessKey,SessionToken]'
--output text))
Expand Down
21 changes: 11 additions & 10 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
* # AWS Gitlab OIDC Provider Terraform Module
*
* ## Purpose
* This module allows you to create a Gitlab OIDC provider for your AWS account, that will help Gitlab Actions to securely authenticate against the AWS API using an IAM role
* This module allows you to create a Gitlab OIDC provider for your AWS account, that will allow Gitlab pipelines to securely authenticate against the AWS API using an IAM role
*
*/

data "tls_certificate" "gitlab" {
url = var.gitlab_tls_url
}
Expand All @@ -13,7 +14,7 @@ resource "aws_iam_openid_connect_provider" "this" {
count = var.create_oidc_provider ? 1 : 0

client_id_list = var.aud_value
thumbprint_list = ["${data.tls_certificate.gitlab.certificates.0.sha1_fingerprint}"]
thumbprint_list = [data.tls_certificate.gitlab.certificates[0].sha1_fingerprint]
url = var.url
}

Expand All @@ -22,19 +23,19 @@ resource "aws_iam_role" "this" {
name = var.role_name
description = var.role_description
max_session_duration = var.max_session_duration
assume_role_policy = join("", data.aws_iam_policy_document.this.*.json)
assume_role_policy = join("", data.aws_iam_policy_document.this[*].json)
tags = var.tags

depends_on = [ aws_iam_openid_connect_provider.this ]
depends_on = [aws_iam_openid_connect_provider.this]
}

resource "aws_iam_role_policy_attachment" "attach" {
count = var.create_oidc_role ? length(var.oidc_role_attach_policies) : 0

policy_arn = var.oidc_role_attach_policies[count.index]
role = join("", aws_iam_role.this.*.name)
role = join("", aws_iam_role.this[*].name)

depends_on = [ aws_iam_role.this ]
depends_on = [aws_iam_role.this]
}

data "aws_iam_policy_document" "this" {
Expand All @@ -47,13 +48,13 @@ data "aws_iam_policy_document" "this" {
effect = "Allow"

condition {
test = "StringLike"
values = var.repositories
variable = "${join("", aws_iam_openid_connect_provider.this.*.url)}:${var.match_field}"
test = "StringLike"
values = var.project_paths
variable = "${join("", aws_iam_openid_connect_provider.this[*].url)}:${var.match_field}"
}

principals {
identifiers = [ statement.value.arn ]
identifiers = [statement.value.arn]
type = "Federated"
}
}
Expand Down
5 changes: 3 additions & 2 deletions outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ output "oidc_role" {

output "thumbprint" {
description = "TLS endpoint certificate SHA1 Fingerprint"
value = [data.tls_certificate.gitlab.certificates[0].sha1_fingerprint]
value = [data.tls_certificate.gitlab.certificates[0].sha1_fingerprint]
}

output "policy_document" {
value = join("", data.aws_iam_policy_document.this.*.json)
description = "joined IAM policy documents"
value = join("", data.aws_iam_policy_document.this[*].json)
}
34 changes: 15 additions & 19 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,19 @@ variable "role_description" {
default = "Role assumed by the Gitlab OIDC provider."
}

variable "repositories" {
description = "List of GitLab organization/repository names authorized to assume the role."
variable "project_paths" {
description = "List of GitLab namesapce/project names authorized to assume the role."
type = list(string)
default = []

validation {
# Ensures each element of github_repositories list matches the
# organization/repository format used by GitHub.
# Ensures each element of gitlab_projects list matches the
# namespace/project format used by GitLab.
condition = length([
for repo in var.repositories : 1
if length(regexall("^project_path:[A-Za-z0-9_.-]+?/([A-Za-z0-9_.:/-]+|\\*)$", repo)) > 0
]) == length(var.repositories)
error_message = "Repositories must be specified in the organization/repository format."
for path in var.project_paths : 1
if length(regexall("project_path:[A-Za-z0-9_.-]+?/([A-Za-z0-9_.:/-]+|\\*)$", path)) > 0
]) == length(var.project_paths)
error_message = "Projects must be specified in the "project_path:namespace/project" format."
}
}

Expand All @@ -68,24 +68,20 @@ variable "oidc_role_attach_policies" {
}

variable "match_field" {
type = string
default = "sub"
}

variable "gitlab_url" {
type = string
default = "https://gitlab.com"
description = "the token field the OIDC provider filter on"
type = string
default = "sub"
}

variable "gitlab_tls_url" {
type = string
# Avoid using https scheme because the Hashicorp TLS provider has started following redirects starting v4.
type = string
description = "the Hashicorp TLS provider has started following redirects starting v4. so we use tls://"
# See https://github.com/hashicorp/terraform-provider-tls/issues/249
default = "tls://gitlab.com:443"
}

variable "aud_value" {
description = "(Required) A list of client IDs (also known as audiences). When a mobile or web app registers with an OpenID Connect provider, they establish a value that identifies the application. (This is the value that's sent as the client_id parameter on OAuth requests.)"
type = list(string)
default = ["https://gitlab.com"]
type = list(string)
default = ["https://gitlab.com"]
}
11 changes: 11 additions & 0 deletions versions.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
terraform {
required_version = ">= 1"

required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.0"
}
tls = {
source = "hashicorp/tls"
version = ">= 3.0"
}
}
}

0 comments on commit ad489a3

Please sign in to comment.