Secrets ManagerとGitHub Actionsを組み合わせて認証情報を管理する

Secrets ManagerとGitHub Actionsを組み合わせて認証情報を管理する

2025.12.06

こんにちは、データ事業本部のキタガワです。
最近GitHub Actionsに入門しました。

今回はSecrets ManagerとGitHub Actionsを組み合わせて認証情報を管理する方法を紹介します。

ここで作成したソースコードは以下のリポジトリにありますので、参考にしてみてください。

https://github.com/cm-kitagawa-zempei/secrets-manager-github-actions-terraform

背景

GitHub Actionsにはシークレット機能があり、これを利用して認証情報などの機微な情報を安全に管理できます。シークレットに登録した値はGitHub Actionsの環境変数としてアクセスでき、ログなどにも出力されないため、外部に漏洩することを防ぐことができます。

ただ、階層構造での管理やパスワードローテーションには対応していないため、運用面で物足りなさを感じることもあります。調べてみたところSecrets ManagerをGitHub Actionsから利用する方法があることがわかりました。

https://docs.aws.amazon.com/ja_jp/secretsmanager/latest/userguide/retrieving-secrets_github.html

環境変数にセットした値はマスクされるらしく、この部分に関しても安心して使用できます。
直近ではサードパーティSaaSシークレットの管理やローテーションができるアップデートも行われており、以下のブログではSnowflakeのKey Pairのローテーションが紹介されています。

https://dev.classmethod.jp/articles/update-aws-secrets-manager-managed-external-secrets/

GitHub ActionsのSecretsは追加の設定などが不要で手軽に使用することができますが、これらの利点があるSecrets Managerを採用することも大いに検討できるのではないでしょうか。

利用方法

使い方は簡単で、アクションが用意されているので、それを利用するだけです。

https://github.com/aws-actions/aws-secretsmanager-get-secrets

- name: Step name
  uses: aws-actions/aws-secretsmanager-get-secrets@v2
  with:
    secret-ids: |
      ENVVAR, secretId1

上記の例だと secretId1 の値が ENVVAR という環境変数にセットされます。また parse-json-secrets: true を指定すると、JSON形式で保存されたシークレットを環境変数に展開できます。

例えば上記の例で secretId1{"key1": "value1", "key2": "value2"} というJSON形式で保存されていた場合、ENVVAR_KEY1ENVVAR_KEY2 という環境変数にそれぞれ value1value2 がセットされます。

やってみる

前提として以下のリソース等が必要になります。

  • GitHubリポジトリ
  • AWS アカウントと適切な権限(IAM、Secrets Managerの操作権限)
  • AWS CLIがインストールされていること
  • Terraformがインストールされていること

AWS CLIとTerraformのバージョンは以下のとおりです。

❯ aws --version
aws-cli/2.17.23 Python/3.11.9 Darwin/25.1.0 exe/x86_64

❯ terraform --version
Terraform v1.14.1
on darwin_arm64

構成概要

今回は以下のような構成を想定しています。

Terraformで作成するリソースは以下の通りです。

リソース 用途
IAM OIDC Provider GitHub ActionsとのOIDC連携
IAM Role GitHub Actionsが引き受けるロール
IAM Policy Secrets Managerへのアクセス許可
Secrets Manager Secret 認証情報の保存

AWSリソースの作成(Terraform)

まずGitHub Actionsに必要なAWSリソースを作成します。

ファイル構成

作成するファイルは以下の通りです。

.
├── main.tf          # リソース定義
├── variables.tf     # 入力変数
├── outputs.tf       # 出力値
└── terraform.tfvars # 環境設定(要作成)

それぞれのファイルを前述の構成図に沿って見ていきましょう。

1. 変数の定義(variables.tf)

まず、環境ごとに異なる値を変数として定義します。

variable "github_org_or_user" {
  description = "GitHub organization name (for org repos) or username (for personal repos)"
  type        = string
}

variable "github_repo" {
  description = "GitHub repository name"
  type        = string
}

variable "aws_region" {
  description = "AWS region"
  type        = string
  default     = "ap-northeast-1"
}

terraform.tfvars を作成し、自身の環境に合わせてそれぞれの値を設定します。

github_org_or_user = "your-github-org-or-user-name"
github_repo = "your-github-repo-name"
aws_region = "ap-northeast-1"

2. OIDC Providerの作成(main.tf)

GitHub ActionsからAWSへの認証にはOIDCを使用します。まずOIDC Providerを作成します。

resource "aws_iam_openid_connect_provider" "github_actions" {
  url            = "https://token.actions.githubusercontent.com"
  client_id_list = ["sts.amazonaws.com"]
}

これにより、GitHubが発行するOIDCトークンをAWSで検証できるようになります。なお、thumbprint_list については現在指定不要のようです。

https://qiita.com/satooshi/items/0c2f5a0e2b64a1d9a4b3#1-oidcプロバイダー作成

2023年6月27日に GitHub Changelog でサムプリントを2種類設定するという記事が公開されていましたが、2023年7月6日からAWS側で証明書の検証が可能になったため、サムプリントの指定は不要のようです。

このブログにおいても指定を行わずともOIDCでの認証が成功していることを確認しています。

3. IAM Roleの作成(main.tf)

次に、GitHub Actionsが引き受けるロールを作成します。ここで重要なのが信頼ポリシーの condition の部分です。

data "aws_iam_policy_document" "github_actions_assume_role" {
  statement {
    effect  = "Allow"
    actions = ["sts:AssumeRoleWithWebIdentity"]

    principals {
      type        = "Federated"
      identifiers = [aws_iam_openid_connect_provider.github_actions.arn]
    }

    condition {
      test     = "StringEquals"
      variable = "token.actions.githubusercontent.com:aud"
      values   = ["sts.amazonaws.com"]
    }

    # 特定のリポジトリからのみアクセスを許可
    condition {
      test     = "StringLike"
      variable = "token.actions.githubusercontent.com:sub"
      values   = ["repo:${var.github_org_or_user}/${var.github_repo}:*"]
    }
  }
}

resource "aws_iam_role" "github_actions" {
  name               = "github-actions-secrets-manager-role"
  assume_role_policy = data.aws_iam_policy_document.github_actions_assume_role.json
}

token.actions.githubusercontent.com:sub の条件により、指定したリポジトリからのアクセスのみを許可しています。これがないと他のリポジトリからこのロールを引き受けられてしまうため、セキュリティ上非常に重要です。

4. Secrets Managerへのアクセス権限(main.tf)

IAM Roleに対して、Secrets Managerへのアクセス権限を付与します。

data "aws_iam_policy_document" "secrets_manager_access" {
  statement {
    effect    = "Allow"
    actions   = ["secretsmanager:GetSecretValue"]
    resources = [aws_secretsmanager_secret.db_credentials.arn]
  }
  statement {
    effect    = "Allow"
    actions   = ["secretsmanager:ListSecrets"]
    resources = ["*"]
  }
}

resource "aws_iam_role_policy" "secrets_manager_access" {
  name   = "secrets-manager-access"
  role   = aws_iam_role.github_actions.id
  policy = data.aws_iam_policy_document.secrets_manager_access.json
}

公式ドキュメント によるとGitHub Actionsが引き受けるロールに必要なのは以下のアクセス許可です。

  • 取得するシークレットに対する GetSecretValue
  • すべてのシークレットに対する ListSecrets
  • (オプション) シークレットが カスタマー管理キー で暗号化されている場合には、KMS key に対する Decrypt

今回シークレットはデフォルトのAWS管理キーで暗号化されているため、Decryptは不要です。また公式では ListSecrets も必要と記載されていますが、試したところ今回の構成では付与しなくても動作しました。

5. シークレットの作成(main.tf)

最後に、Secrets Managerにシークレットを作成します。

resource "aws_secretsmanager_secret" "db_credentials" {
  name        = "sample/db-credentials"
  description = "Database credentials for sample application"

  recovery_window_in_days = 7
}

resource "aws_secretsmanager_secret_version" "db_credentials" {
  secret_id = aws_secretsmanager_secret.db_credentials.id
  secret_string = jsonencode({
    host     = "db.example.com"
    port     = 5432
    username = "app_user"
    password = "initial-password-v1"
    database = "myapp"
  })
}

JSON形式で保存しておくと、GitHub Actions側で parse-json-secrets: true を指定することで各フィールドを個別の環境変数として展開できます。ここでは例としてDBの擬似的な接続情報を設定しています。

なお、この例ではTerraformのコードにパスワードなどをハードコーディングしていますが、実際にはAWS CLIなどを通してセキュアな方法で登録することを推奨します。

6. 出力値の定義(outputs.tf)

デプロイ後に必要な値を出力します。

output "iam_role_arn" {
  description = "IAM role ARN for GitHub Actions"
  value       = aws_iam_role.github_actions.arn
}

ファイル構成のおさらい

ファイル 内容
variables.tf GitHubリポジトリ情報とリージョンの変数定義
terraform.tfvars 自身の環境に合わせた変数値
main.tf OIDC Provider、IAM Role/Policy、Secrets Manager
outputs.tf GitHub Actionsで使用するIAM Role ARNの出力

準備ができたらデプロイします。

デプロイ

デプロイは以下のコマンドを実行します。

# Terraformの初期化
terraform init

# Terraformの実行
terraform apply

デプロイが完了すると iam_role_arn が出力されるので、これをGitHub Actionsのシークレットへ AWS_ROLE_ARN として登録します。
alt text

GitHub Actionsの設定

続いてGitHub Actionsの設定を行います。GitHub Actionsを利用するリポジトリのトップに .github/workflows/ というディレクトリを作成し、ここにYAMLファイルを配置します。ファイルの名前は任意ですが、今回は sample-github-actions.yml とします。

ファイルには次のような内容を記載します。

name: "Sample GitHub Actions"

on:
  push:
    branches: [main]
  workflow_dispatch:  # 手動実行用

env:
  AWS_REGION: ap-northeast-1

# OIDC 認証に必要な権限
permissions:
  id-token: write
  contents: read

jobs:
  sample-github-actions:
    name: Sample GitHub Actions
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
          aws-region: ${{ env.AWS_REGION }}

      - name: Get secrets from Secrets Manager
        uses: aws-actions/aws-secretsmanager-get-secrets@v2
        with:
          secret-ids: |
            DB_SECRETS, sample/db-credentials
          parse-json-secrets: true

      - name: Use secrets (demo)
        run: |
          echo "Database host: ${{ env.DB_SECRETS_HOST }}"
          echo "Database port: ${{ env.DB_SECRETS_PORT }}"
          echo "Database name: ${{ env.DB_SECRETS_DATABASE }}"
          echo "Database user: ${{ env.DB_SECRETS_USERNAME }}"
          echo "Database password: ${{ env.DB_SECRETS_PASSWORD }}"

設定ファイルの各項目について簡単に説明します。

実行条件(on)

on:
  push:
    branches: [main]
  workflow_dispatch:

実行条件には pushworkflow_dispatch を指定しています。push は通常のプッシュで実行され、workflow_dispatch は手動で実行されるようになっています。

権限の設定(permissions)

permissions:
  id-token: write
  contents: read

OIDC認証を使用するには id-token: write の権限が必要です。これによりGitHub ActionsがOIDCトークンを発行できるようになります。

AWS認証(configure-aws-credentials)

- name: Configure AWS Credentials
  uses: aws-actions/configure-aws-credentials@v4
  with:
    role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
    aws-region: ${{ env.AWS_REGION }}

先ほどGitHub Secretsに登録した AWS_ROLE_ARN を使用してAssumeRoleを行います。アクセスキーを使わずOIDC経由で安全に認証できます。

シークレットの取得(aws-secretsmanager-get-secrets)

- name: Get secrets from Secrets Manager
  uses: aws-actions/aws-secretsmanager-get-secrets@v2
  with:
    secret-ids: |
      DB_SECRETS, sample/db-credentials
    parse-json-secrets: true

Secrets Managerからシークレットを取得します。
secret-ids の形式は 環境変数名, シークレット名 です。parse-json-secrets: true を指定しているため、JSONの各キーが DB_SECRETS_HOSTDB_SECRETS_PORT などの環境変数に展開されます。

環境変数の利用

- name: Use secrets (demo)
  run: |
    echo "Database host: ${{ env.DB_SECRETS_HOST }}"
    echo "Database port: ${{ env.DB_SECRETS_PORT }}"
    ...

展開された環境変数は ${{ env.環境変数名 }} で参照できます。ここではデモとしてDBの接続情報をechoしています。値は自動的にマスクされるため、ログには出力されません。

動作確認

ここまで作成してきたファイルをGitHubにプッシュして動作確認を行います。

git add .
git commit -m "Add GitHub Actions"
git push

push後にGitHub Actionsが自動的に実行されます。

alt text

問題なく設定できていればSample GitHub Actionsに緑のチェックマークが表示されます。またここをクリックしUse secrets (demo)の実行ログを確認すると、Secrets Managerからシークレットを取得し、環境変数に展開されたことが確認できます。

alt text

出力した値はマスクされるため、ログに出力されていないことも確認できます。

まとめ

今回はSecrets ManagerとGitHub Actionsを組み合わせて認証情報を管理する方法を紹介しました。GitHub Actionsのシークレット機能で十分なケースも多いですが、より高度な管理が必要な場合はSecrets Managerも選択肢に入れてみてください。

参考

https://docs.aws.amazon.com/ja_jp/secretsmanager/latest/userguide/retrieving-secrets_github.html

https://dev.classmethod.jp/articles/update-aws-secrets-manager-managed-external-secrets/

https://zenn.dev/farstep/books/learn-github-actions

https://qiita.com/satooshi/items/0c2f5a0e2b64a1d9a4b3

https://github.com/aws-actions/aws-secretsmanager-get-secrets

この記事をシェアする

FacebookHatena blogX

関連記事