Last active
September 13, 2024 15:28
-
-
Save kmott/035931f0bb0503942a6691b6c90c74d6 to your computer and use it in GitHub Desktop.
Terraform - JWT Auth for GitLab using Vault
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// This enabled the JWT Auth backend in Vault for GitLab to authenticate with (obtains a Vault token based on $CI_JOB_JWT | |
// in pipeline jobs) | |
// | |
resource "vault_jwt_auth_backend" "gitlab" { | |
type = "jwt" | |
path = var.gitlab.jwt_auth_path | |
jwks_url = format("https://%s/-/jwks", var.gitlab.hostname) | |
bound_issuer = var.gitlab.hostname | |
} | |
resource "vault_policy" "policy" { | |
count = length(var.gitlab.projects) | |
name = format("gitlab-%s", replace(var.gitlab.projects[count.index].name, "/", "-")) | |
policy = <<EOT | |
%{ for _, policy in var.gitlab.projects[count.index].policies ~} | |
path "${policy.path}" { | |
capabilities = ["${join("\",\"", policy.capabilities)}"] | |
} | |
%{ endfor ~} | |
EOT | |
} | |
resource "vault_jwt_auth_backend_role" "role" { | |
count = length(var.gitlab.projects) | |
backend = vault_jwt_auth_backend.gitlab.path | |
role_type = "jwt" | |
token_policies = [format("gitlab-%s", replace(var.gitlab.projects[count.index].name, "/", "-"))] | |
role_name = format("gitlab-%s-readonly", replace(var.gitlab.projects[count.index].name, "/", "-")) | |
user_claim = "user_email" | |
token_explicit_max_ttl = 300 | |
bound_claims = { | |
project_id = var.gitlab.projects[count.index].id | |
} | |
} | |
variable "gitlab" { | |
type = object({ | |
hostname = string | |
jwt_auth_path = string | |
projects = list(object({ | |
name = string | |
id = number | |
token_max_ttl = number | |
policies = list(object({ | |
path = string | |
capabilities = list(string) | |
})) | |
})) | |
}) | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module "vault-gitlab" { | |
source = "./modules/vault-gitlab" | |
gitlab = { | |
hostname = "gitlab.example.org" | |
jwt_auth_path = "path/to/gitlab-jwt-auth" | |
// | |
// For each project, the user can specify a role when they log in to vault from their CI/CD pipeline | |
// to obtain their token: | |
// - vault write -namespace="" -field="token" ${VAULT_AUTH_JWT_PATH} role=${VAULT_AUTH_JWT_ROLE} jwt=${CI_JOB_JWT} | |
// | |
// The var 'VAULT_AUTH_JWT_PATH' is a globally set var in GitLab that defaults to the `jwt_auth_path` value | |
// from above. | |
// | |
// The var 'VAULT_AUTH_JWT_ROLE' is a globally set var in GitLab that defaults to | |
// 'gitlab-${CI_PROJECT_PATH_SLUG}-readonly', matching what Terraform is applying to Vault in the module above. | |
// | |
projects = [ | |
{ | |
name = "group1/proj1" | |
id = 999 | |
token_max_ttl = 300 | |
policies = [ | |
{ | |
path = "path/to/data/my/foo/*" | |
capabilities = ["read"] | |
}, | |
{ | |
path = "path/to/data/my/other/foo/specialSecrets" | |
capabilities = ["read"] | |
} | |
] | |
}, | |
{ | |
name = "group2/subgroup2/project1" | |
id = 1024 | |
token_max_ttl = 300 | |
policies = [ | |
{ | |
path = "some/other/data/for/different/group/secret" | |
capabilities = ["read"] | |
} | |
] | |
} | |
] | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# This is the .gitlab-ci.yml for a given repo that can obtain a VAULT_TOKEN using the `vault` CLI, and then use that | |
# token to obtain secrets from various paths in Vault as a part of the CI/CD pipeline steps. | |
# | |
# Setting `-namespace=""` is required if you are using Enterprise Vault with namespaces and the JWT auth method is in | |
# the root namespace. If that is not the case, set the namespace accordingly (or leave out entirely if not uisng | |
# Enterprise Vault). | |
# | |
deploy: | |
image: vault:1.7.6 | |
stage: deploy | |
tags: | |
- default | |
variables: | |
VAULT_ADDR: https://vault.example.org | |
VAULT_AUTH_JWT_PATH: path/to/gitlab-jwt-auth | |
VAULT_AUTH_JWT_ROLE: gitlab-${CI_PROJECT_PATH_SLUG}-readonly | |
VAULT_SECRETS_BASE_PATH: secrets/path/to/${CI_PROJECT_PATH} # For project specific secrets, not required | |
before_script: | |
- export VAULT_TOKEN="$(vault write -namespace="" -field="token" ${VAULT_AUTH_JWT_PATH} role=${VAULT_AUTH_JWT_ROLE} jwt=$CI_JOB_JWT)" | |
- export MY_SECRET="$(vault kv get -field="data" -format="json" ${VAULT_SECRETS_BASE_PATH}/test | jq -r '.secret')" | |
script: | |
- 'echo "MY_SECRET: ${MY_SECRET}"' # DO NOT DO THIS, FOR TESTING ONLY!! |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
We could add this as an import.