日々のいろいろ

GitHubActionsでAWSのセキュリティグループのルールを一時的に変更する

投稿日: 5/7/2025

経緯

GitHubActionsのワーカーから、AWSのEC2にSSHで接続したい!

GitHubActionsのワーカーのグローバルIPアドレスでのSSH接続をEC2のセキュリティグループで許可しよう

GitHub無料利用だと、クラウド上のワーカー(AzureのVMらしい)となり、ワーカーが作成されるたびに異なるIPアドレスが割り当てられることを知る

セキュリティグループの設定に必要な固定のIPアドレスがわからない!

割り当てられるIPアドレスのリストは公開されているが、実際に使用するIPアドレスだけ許可したい...

今に至る

解決策

下記の3点で、対応可能
詳細を事項で解説

① 作成されたワーカー内で、現在のグローバルIPアドレスを取得する

② AWS CLIでセキュリティグループにポート22, 取得したIPアドレスでルールを追加

③ ジョブの最後でルールを削除

必要作業

大まかに必要な作業を列挙する

① GitHubとAWSをOIDCで認証するように設定 (GitHubドキュメント)

アクセスキー・シークレットキーでも可能だが、キーの運用の手間やセキュリティの観点からOIDCを使うことにする

AWSのIAMコンソールからIDプロバイダを設定する

下記項目を選択・入力してプロバイダを追加
プロパティのタイプ:OpenID Connect
プロバイダのURL:https://token.actions.githubusercontent.com
対象者:sts.amazonaws.com

画像

② OIDC用のIAMロール作成とポリシーの追加

OIDC用のロールを作成し、ワーカーが実際にセキュリティグループに対してアクションが可能なポリシーを追加する

ロールの作成

AWSアカウントID、GitHubのユーザ名、リポジトリ名を適宜設定
ちなみに、今回はリポジトリ名の後はワイルドカードで指定しているがブランチも指定が可能

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "",
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam::<AWSアカウントID>:oidc-provider/token.actions.githubusercontent.com"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringEquals": {
                    "token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
                },
                "StringLike": {
                    "token.actions.githubusercontent.com:sub": "repo:<GitHubユーザ名>/<リポジトリ名>:*"
                }
            }
        }
    ]
}

ポリシーの作成・アタッチ

※ロールの詳細画面からインラインポリシーを作成してもよし、作成したポリシーをロールにアタッチするもよし

ルールの作成、削除とルール一覧を表示するポリシーを付与
リージョン、AWSアカウントID、セキュリティグループIDを適宜入力

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "ec2:RevokeSecurityGroupIngress",
                "ec2:AuthorizeSecurityGroupIngress"
            ],
            "Resource": "arn:aws:ec2:<リージョン>:<AWSアカウントID>:security-group/<セキュリティグループID>"
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": "ec2:DescribeSecurityGroupRules",
            "Resource": "*"
        }
    ]
}

③ ジョブ内容(ymlファイル)作成

今回はSSH接続方法までは解説せず、あくまでセキュリティグループへのルールの追加・削除方法を記載する
ちなみに今回はAWS CLIを使うが、SDKを利用したプログラミング言語でも可能

最終的なコードは最後に表示するとして、要点の部分を記載していく

アクセス許可設定

permissions:
  id-token: write   # id-tokenは「write」を指定(これ絶対)
  contents: read    

アクセストークンの要求

 - name: AWS CLI set up
        uses: actions/checkout@v4
 - name: configure aws credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-session-name: Hoge
          role-to-assume: ${{ secrets.AWS_IAM_ROLE_ARN }} # ②で作成したロールのARNを指定
          aws-region: <リージョン>

IPアドレスを取得してセキュリティグループにルールを追加

 - name: add tempolary securitygroup rule
   run: | 
          WORKER_IP=$(curl -s https://checkip.amazonaws.com/)  # グローバルIPアドレスを返すAPIエンドポイント
          aws ec2 authorize-security-group-ingress --group-id ${{ secrets.AWS_SECURITY_GROUP_ID }} --protocol tcp --port 22 --cidr $WORKER_IP/32

追加したルールの削除

ルール追加時に取得したWORKER_IPのスコープは狭いため、削除時には再度取得する必要アリ

 - name: revoke tempolary securitygroup rule
        run: |
          WORKER_IP=$(curl -s https://checkip.amazonaws.com/)
          aws ec2 revoke-security-group-ingress --group-id ${{ secrets.AWS_SECURITY_GROUP_ID }} --protocol tcp --port 22 --cidr $WORKER_IP/32

全体のコード

※一部マスクしてます

name: Build Test

on:
  push:
    branches:
      - deploy  # 実行対象のブランチを指定
  workflow_dispatch:
  
permissions:
  id-token: write   
  contents: read    
  
jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      # コードのチェックアウト
      - name: Checkout Code
        uses: actions/checkout@v4

      - name: AWS CLI set up
        uses: actions/checkout@v4
      - name: configure aws credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-session-name: ******
          role-to-assume: ${{ secrets.AWS_IAM_ROLE_ARN }}
          aws-region: *******
      

      - name: update tempolary securitygroup rule
        run: | 
          WORKER_IP=$(curl -s https://checkip.amazonaws.com/)
          aws ec2 authorize-security-group-ingress --group-id ${{ secrets.AWS_SECURITY_GROUP_ID }} --protocol tcp --port 22 --cidr $WORKER_IP/32

      - name: SSH and clone app on EC2
        run: |
          sudo apt update -y && sudo apt install -y openssh-client
          sudo mkdir -p /home/runner/.ssh
          sudo chmod 700 /home/runner/.ssh
          sudo echo "${{ secrets.AWS_EC2_PRIVATE_KEY }}" | sudo tee /home/runner/.ssh/id_rsa > /dev/null
          sudo chmod 600 /home/runner/.ssh/id_rsa
          sudo ssh -i /home/runner/.ssh/id_rsa -o StrictHostKeyChecking=no ubuntu@****** "sudo rm -rf /var/next-arc"
          sudo ssh -i /home/runner/.ssh/id_rsa -o StrictHostKeyChecking=no ubuntu@****** 'sudo GIT_SSH_COMMAND="ssh -i /root/.ssh/id_rsa" git clone git@github.com:******/******.git /var/next-arc'
          sudo ssh -i /home/runner/.ssh/id_rsa -o StrictHostKeyChecking=no ubuntu@****** 'sudo touch /var/next-arc/.env && sudo chmod 666 /var/next-arc/.env && \
          sudo echo "${{ secrets.NEXT_PUBLIC_BACKEND_URL }}" >> /var/next-arc/.env && \
          sudo echo "${{ secrets.THUMBNAIL_IMAGE_PATH }}" >> /var/next-arc/.env && \
          sudo echo "${{ secrets.BACKEND_APP_PATH }}" >> /var/next-arc/.env'
          
      - name: build and start app
        run: |
          sudo ssh -i /home/runner/.ssh/id_rsa -o StrictHostKeyChecking=no ubuntu@****** "cd /var/next-arc"
          sudo ssh -i /home/runner/.ssh/id_rsa -o StrictHostKeyChecking=no ubuntu@****** 'sudo bash -c "cd /var/next-arc && \
          npm install && \
          npm run build && \
          pm2 delete all && \
          pm2 start npm --name \"next\" -- start && \
          pm2 save"'
          
      - name: revoke tempolary securitygroup rule
        run: |
          WORKER_IP=$(curl -s https://checkip.amazonaws.com/)
          aws ec2 revoke-security-group-ingress --group-id ${{ secrets.AWS_SECURITY_GROUP_ID }} --protocol tcp --port 22 --cidr $WORKER_IP/32

コメント

まだコメントがありません

コメントする
0 / 1500 文字