背景・目的
以前、下記の記事でTerraformや、GitHub Actionsについて知識の整理や、検証しました。
今回は、これらをつなげてGitHub ActionsからAWSのS3を作成してみます。
実践
今回、構築したい環境は下記のとおりです。
前提
- AWSアカウントを保持していること
- GitHubアカウントを保持していること
- VSCode
- MacOS
①.GitHubリポジトリ
リポジトリの作成とダウンロード
- プライベートリポジトリを用意します
- git cloneによりローカルにダウンロードします
$ git clone git@github.com:XXXX/XXXX.git
- VSCodeで「フォルダーをワークスペースに追加」をクリックし、ダウンロードしたフォルダを追加します
②.OIDCの設定(AWSとGithub Actionsと連携)
OIDC(Open ID Connect)により、GitHub Actions ワークフローから、AWS 内のリソースにアクセスします。
AWSの作業
- AWSにサインインします
IDプロバイダの追加
-
IAMに移動します
-
ナビゲーションペインのIDプロバイダーをクリックします
-
「プロバイダを追加」をクリックします
-
下記を入力し、「プロバイダを追加」をクリックします
- プロバイダのタイプ:OpenID Connect
- プロバイダのURL:https://token.actions.githubusercontent.com
- 対象者:sts.amazonaws.com
ロールと信頼ポリシーの構成
-
IAMのナビゲーションペインで、「ロール」をクリックします
-
「ロールを作成」をクリックします
-
下記を指定し、「次へ」をクリックします
-
ロール名を指定して、「ロールの作成」をクリックします
GitHubの作業
Secretsの設定
- GitHubにサインインし、対象リポジトリを選択します
- ①「Settings」>②「Secrets and variables > Actions」>③「Secrets」>④「New repository secrets」をクリックします
- 下記の2つのシークレットを追加します
GitHub Actionsによる疎通
GitHub Actionsでは、.github/workflowディレクトリ直下へyml(yaml)ファイルを配置することで動作します。
-
.github/workflows
ディレクトリを作成します -
oidc-ymlファイルを作成します
-
下記のコードを書きます
name: OpenID Connect on: push env: ROLE_ARN: arn:aws:iam::${{secrets.AWS_ID}}:role/${{secrets.ROLE_NAME}} SESSION_NAME: gh-oidc-${{github.run_id}}-${{github.run_attempt}} jobs: connect: runs-on: ubuntu-latest permissions: id-token: write steps: - uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: ${{env.ROLE_ARN}} role-session-name: ${{env.SESSION_NAME}} aws-region: ap-northeast-1 - run: aws iam list-users - run: aws iam create-user --user-name invalid || true
-
Commitし、Pushします
$ git commit -m "oidc test connection" .github/workflows/oidc-test.yml $ git push origin main
③.ワークフローの作成
GitHubの作業
- GitHub Actionsで「New workflow」をクリックします
- terraformのworkflowテンプレートを選択します(Configureをクリックします)
- 「Commit changes」をクリックします
ローカルの作業
- ローカルでgit pullします
- テンプレートに対して、下記のようにOIDCのロールが使えるように設定します
- envの追加
- AWS configureの追加
- permissionの追加
name: 'Terraform' on: push: branches: [ "main" ] pull_request: env: ROLE_ARN: arn:aws:iam::${{secrets.AWS_ID}}:role/${{secrets.ROLE_NAME}} SESSION_NAME: gh-oidc-${{github.run_id}}-${{github.run_attempt}} REIGION_NAME: ap-northeast-1 permissions: contents: read jobs: terraform: name: 'Terraform' runs-on: ubuntu-latest environment: production permissions: id-token: write contents: read # Use the Bash shell regardless whether the GitHub Actions runner is ubuntu-latest, macos-latest, or windows-latest defaults: run: shell: bash steps: # Checkout the repository to the GitHub Actions runner - name: Checkout uses: actions/checkout@v4 - name: AWS configure uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: ${{env.ROLE_ARN}} role-session-name: ${{env.SESSION_NAME}} aws-region: ${{env.REIGION_NAME}} # Initialize a new or existing Terraform working directory by creating initial files, loading any remote state, downloading modules, etc. - name: Terraform Init run: terraform init --backend-config=backend.hcl # Checks that all Terraform configuration files adhere to a canonical format - name: Terraform Format run: terraform fmt -check # Generates an execution plan for Terraform - name: Terraform Plan run: terraform plan -input=false # On push to "main", build or change infrastructure according to Terraform configuration files # Note: It is recommended to set up a required "strict" status check in your repository for "Terraform Cloud". See the documentation on "strict" required status checks for more information: https://help.github.com/en/github/administering-a-repository/types-of-required-status-checks - name: Terraform Apply if: github.ref == 'refs/heads/main' && github.event_name == 'push' run: terraform apply -auto-approve -input=false
④.ステートファイル格納用のバックエンドを作成
S3バケット
terraform
-
backend.tfとbackend.hclファイルを用意します
$ ls -ltr total 24 -rw-r--r-- 1 XXXX YYYY 11 7 21 14:52 README.md -rw-r--r-- 1 XXXX YYYY 65 7 21 17:42 backend.tf -rw-r--r-- 1 XXXX YYYY 132 7 21 17:42 backend.hcl -rw-r--r-- 1 XXXX YYYY 230 7 21 17:46 provider.tf $ cat backend.* bucket = "XXXXXX" region = "ap-northeast-1" encrypt = true profile = "XXXX" terraform { backend "s3" { key = "terraform.tfstate" } } $
-
provider.tfファイルを用意します
$ cat provider.tf terraform { required_version = "~> 1.8.0" required_providers { aws = { source = "hashicorp/aws" version = "~> 5.44.0" } } } provider "aws" { region = "ap-northeast-1" profile = "XXXXX" } $
-
main.tfファイルを用意します
data "aws_caller_identity" "this" {} # S3 Bucket # https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket resource "aws_s3_bucket" "terraform_demo" { bucket = "terraform-demo-${data.aws_caller_identity.this.account_id}" } resource "aws_s3_bucket_policy" "terraform_demo" { bucket = aws_s3_bucket.terraform_demo.id policy = jsonencode({ Version = "2012-10-17" Statement = [ { Sid = "AllowSSLRequestsOnly" Effect = "Deny" Principal = "*" Action = "s3:*" Resource = [ aws_s3_bucket.terraform_demo.arn, "${aws_s3_bucket.terraform_demo.arn}/*", ] Condition = { Bool = { "aws:SecureTransport" = "false" } } } ] }) }
-
AWS SSOでログインします
$ aws sso login --sso-session XXX
-
terraform initを実行します
$ terraform init --backend-config=backend.hcl
-
terraform planを実行します
$ terraform plan
-
問題なければそのまま
terraform apply
を実行します$ terraform apply
⑤.GitHubActionでTerraformを実行する
IAMロールの修正
作成したIAMロールに、ポリシーをアタッチします
-
AWSにサインインします
-
IAMに移動し、作成したIAMロールをクリックします
-
インラインポリシーを追加をクリックします
-
下記のポリシーを追加します
{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": [ "s3:PutObject", "s3:GetObjectAcl", "s3:GetObject", "s3:ListBucket" ], "Resource": [ "arn:aws:s3:::{バックエンドのS3バケット}", "arn:aws:s3:::{バックエンドのS3バケット}/*" ] }, { "Sid": "VisualEditor1", "Effect": "Allow", "Action": "s3:*", "Resource": [ "arn:aws:s3:::{テスト用のバケット}", "arn:aws:s3:::{テスト用のバケット}/*" ] } ] }
-
ポリシー名を設定し、「ポリシーの作成」をクリックします
provider.tf
- ロールを使って作成するので、profileを削除します。また、バージョンは1.8.0は使えなかったので、1.9.0に変更しています
terraform { required_version = "~> 1.9.0" required_providers { aws = { source = "hashicorp/aws" version = "~> 5.44.0" } } } provider "aws" { region = "ap-northeast-1" }
backend.hcl
- backend.hclから、profileを削除します
bucket = "ステートファイルが格納されているバケット" region = "ap-northeast-1" encrypt = true
GitHub
考察
今回、GitHub Actionsから、Terraformを利用してS3バケットを作成してみました。
次回は、AWSネットワークを作成します
参考