OIDC
gitlabにはOIDCの機能がある. CI/CDからAWSなどのcloudのリソースにアクセスする時当然認証情報が必要なのだ. 簡単なやり方だとgitlab用のAccess key IDとSecret access keyを用意してrepositoryの環境変数に設定するが鍵の更新が面倒だし, そのrepositoryにアクセスできる人全員が鍵を見られるのはセキュリティ上も好ましくない. OIDCはgitlabとcloudの間で適切な制限の範囲で一時認証を発行可能にする仕組みである. 例えば特定のrepositoryの特定のブランチからのCI/CDのjobには一時認証が発行できる, というような設定ができる. ドキュメントに従って設定すれば良いだけであるが, thumbprintを調べてべた書きするのも面倒なのでちょっと工夫してべた書きしない方法をまとめておく.
example
identityproviders.tf
# these resources are following the docs https://docs.gitlab.com/ee/ci/cloud_services/aws/
resource "aws_iam_openid_connect_provider" "default" {
url = "https://gitlab.hoge.com"
client_id_list = [
"https://gitlab.hoge.com",
]
thumbprint_list = ["${data.tls_certificate.gitlab.certificates.0.sha1_fingerprint}",
]
}
data "http" "gitlab_openid_configuration" {
url = "https://gitlab.hoge.com/.well-known/openid-configuration"
}
data "tls_certificate" "gitlab" {
url = jsondecode(data.http.gitlab_openid_configuration.response_body).jwks_uri
}
補足
- hogeは自分の使っているgitlabに合わせて変更する. 以下のhogehoge, fooなども同様.
gitlabrole.tf
以下は2つのrepository用にroleを作る例:
# these resources are following the docs https://docs.gitlab.com/ee/ci/cloud_services/aws/
# common part
data "aws_iam_policy_document" "oidc_principal" {
statement {
actions = ["sts:AssumeRoleWithWebIdentity"]
principals {
type = "Federated"
identifiers = [aws_iam_openid_connect_provider.default.arn]
}
effect = "Allow"
condition {
test = "StringLike"
variable = "gitlab.hoge.com:sub"
values = [
# 全てのブランチのコミットに対するジョブを対象にするための設定
"project_path:foo/*:ref_type:branch:ref:*",
# 全てのタグに対するジョブを対象にするための設定
"project_path:foo/*:ref_type:tag:ref:*"
]
}
}
}
# define hoge role and attach policy
# we should define custom policy and attach it
resource "aws_iam_role" "hoge_gitlab_role" {
name = "hoge_gitlab_cicd_role"
assume_role_policy = data.aws_iam_policy_document.oidc_principal.json
}
locals {
iam_role_policies = {
AdministratorAccess = "arn:aws:iam::aws:policy/AdministratorAccess"
}
}
resource "aws_iam_role_policy_attachment" "hoge_attach_policy" {
for_each = { for k, v in local.iam_role_policies : k => v }
policy_arn = each.value
role = aws_iam_role.hoge_gitlab_role.name
}
# define hogehoge role and attach policy
# we should define custom policy and attach it
resource "aws_iam_role" "hogehoge_gitlab_cicd_role" {
name = "hogehoge_gitlab_cicd_role"
assume_role_policy = data.aws_iam_policy_document.oidc_principal.json
}
resource "aws_iam_role_policy" "hogehoge_ci_cd_policy" {
name = "hogehoge_ci_cd_policy"
role = aws_iam_role.hogehoge_gitlab_cicd_role.id
policy = data.aws_iam_policy_document.hogehoge_cicd_policy_doc.json
}
data "aws_iam_policy_document" "hogehoge_cicd_policy_doc" {
statement {
actions = [
"s3:*",
"route53:*",
"elasticfilesystem:*",
"elasticloadbalancing:*",
"logs:*",
"ecs:*",
"iam:*",
"SNS:*",
"lambda:*",
"ec2:*",
"autoscaling:*",
"application-autoscaling:*",
"acm:*",
"ecr:*"
]
effect = "Allow"
resources = ["*"]
}
}
補足
- "arn:aws:iam::aws:policy/AdministratorAccess"は過剰なので使わない方が良い.
- これはAWSアカウント全体を管理するリポジトリのtf file. hoge=全体, hogehoge=個別のプロジェクト, のつもり.
- "s3:*"などもっと制限できる箇所はあるが制限しすぎると変更が面倒なので良い塩梅でやりたい. たとえばhogehogeでRDBを使いたくなったらhogeの方で権限を変更しなければならず制限しすぎると面倒.
一時認証の取得スクリプト
#!/bin/bash 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 $OIDC_TOKEN \ --duration-seconds 3600 \ --query 'Credentials.[AccessKeyId,SecretAccessKey,SessionToken]' \ --output text)) aws sts get-caller-identity
これをAWSに接続したいCI/CDのjobで実行するとAWSACCESSKEYIDなどが埋まる. gitlab-ci.yamlに
id_tokens: OIDC_TOKEN: aud: https://gitlab.hoge.com before_script: - source ci/get_tmp_aws_seacrets.sh
などとする.
gitlabのtemplate jobs
gitlabには備え付けのセキュリティ機能が用意されている. シークレットがハードコードされていないかなどをチェックしてくれる. settingsからチェックボックスで有効にすることもできるが.gitlab-ci.yamlに以下の様に書くだけで良い. jobの結果はbuild > artifactsからjsonをダウンロードして確認できる.
include:
- template: Code-Quality.gitlab-ci.yml
- template: Jobs/Secret-Detection.gitlab-ci.yml
- template: Security/SAST.gitlab-ci.yml
- template: Security/Dependency-Scanning.gitlab-ci.yml
- template: Security/SAST-IaC.gitlab-ci.yml
auto devops
auto devopsも備え付けの機能で, 例えばECSへ継続的デプロイする機能を用意してくれている. 試してみたみた結果CDの雛形を学ぶのには良いがこれに頼り切るには簡素すぎるという感想だった. 例えば先のOIDCで一時認証を使うとなると結局自分で.gitlab-ci.yamlを書く必要がある.