GitHub Actions で Terraform を実行し、AWS にリソースをデプロイします。OIDC を利用することで、GitHub 内に AWS アカウントのシークレットなどを保存しなくて良いため、セキュリティが向上します。
公式ではこちらの手順が参考になります。
Configuring OpenID Connect in Amazon Web Services – GitHub Docs
AWS でプロバイダーとロールを設定
まずは AWS 側で認証用の ID プロバイダーとロールの設定を行います。AWS コンソールからでもできるのですが、設定用のテンプレートが公開されているのでそちらを利用しました。
こちらのテンプレートを利用すると、自動で ID プロバイダーとロールが作成されます。ロールに付与する権限は、ManagedPolicyArns
の部分で必要に応じて調整します。今回は VPC、S3、EC2 の権限を持つ例として記載しています。
Parameters:
GitHubOrg:
Type: String
RepositoryName:
Type: String
OIDCProviderArn:
Description: Arn for the GitHub OIDC Provider.
Default: ""
Type: String
Conditions:
CreateOIDCProvider: !Equals
- !Ref OIDCProviderArn
- ""
Resources:
Role:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Action: sts:AssumeRoleWithWebIdentity
Principal:
Federated: !If
- CreateOIDCProvider
- !Ref GithubOidc
- !Ref OIDCProviderArn
Condition:
StringLike:
token.actions.githubusercontent.com:sub: !Sub repo:${GitHubOrg}/${RepositoryName}:*
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonVPCFullAccess
- arn:aws:iam::aws:policy/AmazonS3FullAccess
- arn:aws:iam::aws:policy/AmazonEC2FullAccess
GithubOidc:
Type: AWS::IAM::OIDCProvider
Condition: CreateOIDCProvider
Properties:
Url: https://token.actions.githubusercontent.com
ClientIdList:
- sts.amazonaws.com
ThumbprintList:
- 6938fd4d98bab03faadb97b34396831e3780aea1
Outputs:
Role:
Value: !GetAtt Role.Arn
こちらのテンプレートを実行します。なお、パラメーターには次のように値を指定します。
- GitHubOrg: アクセス元 GitHub リポジトリーの組織名やアカウント名
- RepositoryName: アクセス元 GitHub リポジトリーのリポジトリー名
- OIDCProviderArn: 空欄のままで OK (既存のプロバイダーを利用する場合に ARN を指定)
作成されたロールの ARN は次の手順で使うので確認して控えておきます。
ロールの中で Condition
を指定する部分で、リクエスト元のリポジトリーを制限しています。この制限がないと、どこからのアクセスでも権限を取得されるため、絶対に指定しておくようにします。
GitHub Actions ワークフロー
AWS に OIDC 認証するための手順を GitHub Actions ワークフローに組み込みます。
シークレットの作成
まず、先ほど確認したロールの ARN を GitHub Actions シークレットとして登録しておきます。例として AWS_ROLE_TO_ASSUME
という名前で登録しておきます。
権限設定の追記
ワークフローから OIDC トークンのリクエストを行えるように権限の設定を追加します。次のような内容をワークフローに追記します。
permissions:
id-token: write
AWS アクセス トークンのリクエスト
AWS にアクセス トークンをリクエストするステップを追加します。role-to-assume
で、認証時に使うロールの ARN を指定します。aws-region
は利用するリージョンを指定します。
role-session-name
は必須ではないですが、ログなどに記録されるセッション名を指定できます。
steps:
- name: configure aws credentials
uses: aws-actions/configure-aws-credentials@v1
with:
role-to-assume: arn:aws:iam::1234567890:role/example-role
role-session-name: samplerolesession
aws-region: ${{ env.AWS_REGION }}
ワークフロー ファイルの例
上述の内容を踏まえ、次のような内容になります。
name: 'Terraform'
on:
push:
branches:
- main
pull_request:
jobs:
terraform:
name: 'Terraform'
runs-on: ubuntu-latest
environment: production
# 権限設定の追記
permissions:
id-token: write
defaults:
run:
shell: bash
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Terraform
uses: hashicorp/setup-terraform@v1
with:
cli_config_credentials_token: ${{ secrets.TF_API_TOKEN }}
# AWS での認証を行うステップ
- name: Authenticate to AWS
uses: aws-actions/configure-aws-credentials@v1
with:
role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
aws-region: ap-northeast-1
- name: Terraform Init
run: terraform init
- name: Terraform Format
run: terraform fmt -check
- name: Terraform Plan
run: terraform plan
- name: Terraform Apply
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
run: terraform apply -auto-approve
Terraform プロバイダーの指定
あとは Terraform ファイルを用意して AWS リソースを作成します。作成するリソースに応じてロールに必要な権限は調整してください。プロバイダーの指定は次のようになります。
provider "aws"{
region = var.aws_region
}
コメント