0
0

GitHubActionsとTerraformでS3バケットを作成してみた

Last updated at Posted at 2024-07-21

背景・目的

以前、下記の記事でTerraformや、GitHub Actionsについて知識の整理や、検証しました。
今回は、これらをつなげてGitHub ActionsからAWSのS3を作成してみます。

実践

今回、構築したい環境は下記のとおりです。

image.png

前提

  • AWSアカウントを保持していること
  • GitHubアカウントを保持していること
  • VSCode
  • MacOS

①.GitHubリポジトリ

リポジトリの作成とダウンロード

  1. プライベートリポジトリを用意します
  2. git cloneによりローカルにダウンロードします
    $ git clone git@github.com:XXXX/XXXX.git
    
  3. VSCodeで「フォルダーをワークスペースに追加」をクリックし、ダウンロードしたフォルダを追加します
    image.png

②.OIDCの設定(AWSとGithub Actionsと連携)

OIDC(Open ID Connect)により、GitHub Actions ワークフローから、AWS 内のリソースにアクセスします。

AWSの作業

  1. AWSにサインインします

IDプロバイダの追加

  1. IAMに移動します

  2. ナビゲーションペインのIDプロバイダーをクリックします

  3. 「プロバイダを追加」をクリックします

  4. 下記を入力し、「プロバイダを追加」をクリックします

  5. できました
    image.png

ロールと信頼ポリシーの構成

  1. IAMのナビゲーションペインで、「ロール」をクリックします

  2. 「ロールを作成」をクリックします

  3. 下記を指定し、「次へ」をクリックします

    • 信頼されたエンティティタイプ:ウェブアイデンティティ
    • アイデンティティプロバイダー:上記で追加した、IDプロバイダ
    • Audience:sts.amazonaws.com(IDプロバイダを選択するとデフォルトで設定)
    • GitHub 組織:Githubアカウント
    • GitHubリポジトリ:リポジトリを指定
      image.png
  4. とりあえず疎通のために、「IAMReadOnlyAccess」を追加します
    image.png

  5. ロール名を指定して、「ロールの作成」をクリックします

GitHubの作業

Secretsの設定

  1. GitHubにサインインし、対象リポジトリを選択します
  2. ①「Settings」>②「Secrets and variables > Actions」>③「Secrets」>④「New repository secrets」をクリックします
    image.png
  3. 下記の2つのシークレットを追加します
    • AWS_ID:AWSアカウントID
    • ROLE_NAME:作成したロール名
      image.png

GitHub Actionsによる疎通

GitHub Actionsでは、.github/workflowディレクトリ直下へyml(yaml)ファイルを配置することで動作します。

  1. .github/workflowsディレクトリを作成します

  2. oidc-ymlファイルを作成します

  3. 下記のコードを書きます

    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 
    
  4. Commitし、Pushします

    $ git commit -m "oidc test connection" .github/workflows/oidc-test.yml
    $ git push origin main
    
  5. 成功しました
    image.png

③.ワークフローの作成

GitHubの作業

  1. GitHub Actionsで「New workflow」をクリックします
  2. terraformのworkflowテンプレートを選択します(Configureをクリックします)
    image.png
  3. 「Commit changes」をクリックします
    image.png

ローカルの作業

  1. ローカルでgit pullします
  2. テンプレートに対して、下記のように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バケット

  1. AWSにサインインします
  2. S3に移動し、バケットを作成します
  3. ステートファイルが、誤って消えないようにバージョンニングを設定しておきます
    image.png

terraform

  1. 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"
      }
    }
    $
    
  2. 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"
    }
    $
    
  3. 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"
              }
            }
          }
        ]
      })
    }
    
  4. AWS SSOでログインします

    $ aws sso login --sso-session XXX
    
  5. terraform initを実行します

    $ terraform init --backend-config=backend.hcl
    
  6. terraform planを実行します

    $ terraform plan                             
    
  7. 問題なければそのままterraform applyを実行します

    $ terraform apply
    
  8. S3バケットは問題なくできていました
    image.png

  9. tfstateもバックエンドのS3にできていました
    image.png

⑤.GitHubActionでTerraformを実行する

IAMロールの修正

作成したIAMロールに、ポリシーをアタッチします

  1. AWSにサインインします

  2. IAMに移動し、作成したIAMロールをクリックします

  3. インラインポリシーを追加をクリックします

  4. 下記のポリシーを追加します

    {
        "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:::{テスト用のバケット}/*"
                ]
            }
        ]
    }
    
  5. ポリシー名を設定し、「ポリシーの作成」をクリックします

provider.tf

  1. ロールを使って作成するので、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

  1. backend.hclから、profileを削除します
    bucket  = "ステートファイルが格納されているバケット"
    region  = "ap-northeast-1"
    encrypt = true
    

GitHub

  1. 作成したファイルをcommitし、pushします
  2. 成功しました
    image.png

考察

今回、GitHub Actionsから、Terraformを利用してS3バケットを作成してみました。
次回は、AWSネットワークを作成します

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0