AWS SSM Send-Command を使用して GitHub Actions から EC2 インスタンスを操作する方法
最初に
GitHub Actions から EC2 インスタンスを操作したかったので、Send-Command を試しに使ってみました。
AWS SSM Send-Command とは
AWS Systems Manager の Send-Command 機能は、EC2 インスタンスにリモートでコマンドを実行するためのサービスです。
これにより、SSH 接続をせずにインスタンスを管理・操作することができます。
例えば、システムのアップデートやログの収集、アプリケーションのデプロイなどが可能です。
CloudFormation でロールを作成する
AWS CloudFormation を使用して、必要な IAM ロールを作成します。
このロールには AssumeRoleWithWebIdentity と SendCommand のポリシーと、
AWS リソースにアクセスするために必要な OIDC プロバイダーを設定します。
以下は、CloudFormation テンプレートの例です。
AWSTemplateFormatVersion: 2010-09-09
Parameters:
Thumbprint1:
Type: String
Default: '6938fd4d98bab03faadb97b34396831e3780aea1'
Thumbprint2:
Type: String
Default: '1c58a3a8518e8759bf075b76b750d4f2df264fcd'
Resources:
GitHubActionsOidcProvider:
Type: AWS::IAM::OIDCProvider
Properties:
Url: https://token.actions.githubusercontent.com
ClientIdList:
- sts.amazonaws.com
ThumbprintList:
- !Ref Thumbprint1
- !Ref Thumbprint2
RoleGitHubActions:
Type: AWS::IAM::Role
Properties:
RoleName: github-actions-role
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Federated: !Sub arn:aws:iam::${AWS::AccountId}: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:xxx:*"
Policies:
- PolicyName: ssm-send-command
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- ssm:SendCommand
Resource:
- arn:aws:ssm:ap-northeast-1:*:document/AWS-RunShellScript
- !Sub arn:aws:ec2:ap-northeast-1:${AWS::AccountId}:instance/*
GitHubActionsOidcProvider
GitHub Actions が AWS リソースにアクセスするために必要な OIDC プロバイダーを定義しています。
このリソースは、GitHub Actions が発行する OIDC トークンを使用して AWS に認証するために使用されます。
RoleGitHubActions
GitHub Actions が特定の AWS リソースに対して操作を行うための IAM ロールを定義しています。
このロールには、GitHub Actions がこのロールを引き受けるためのポリシーと、特定のアクションを許可するポリシーが含まれています。
このテンプレートを CloudFormation にデプロイすることで、GitHub Actions が使用できる IAM ロールを作成します。
GitHub Actions で実行
次に、GitHub Actions を使用して、実際に EC2 インスタンスにコマンドを送信します。
以下は、そのための GitHub Actions ワークフローファイルの例です
name: ssm-send-command-test
on:
workflow_dispatch:
push:
branches:
- main
paths:
- .github/workflows/actions.yaml
- 'send-command-test/**'
permissions:
id-token: write
contents: read
jobs:
send-command-test:
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v4
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v2
with:
role-to-assume: "arn:aws:iam::MY_ACCOUNT_ID:role/github-actions-role"
aws-region: ap-northeast-1
- name: AWS Systems Manager Run Command
run: |
aws ssm send-command \
--document-name 'AWS-RunShellScript' \
--instance-ids 'i-XXXXXXX' \
--parameters 'commands=[
"bash -c \"touch ssm-send-command-test.txt\""
]' \
--timeout-seconds 60 \
--region ap-northeast-1
このワークフローは、以下のステップを実行します:
- リポジトリをチェックアウトします。
- aws-actions/configure-aws-credentials を使用して AWS 認証情報を設定します。
- aws ssm send-command を使用して、指定された EC2 インスタンスにコマンドを送信します。
※MY_ACCOUNT_ID は自身の AWS アカウント ID を入れてください
※instance-ids は EC2 インタスタンス ID を入れてください
結果
EC2 インスタンスに Session Manager で接続し、ファイルが生成されていることを確認します。
$ ls -la
total 8
drwxr-xr-x 2 root root 4096 Aug 5 00:21 .
drwxr-xr-x 5 root root 4096 Jul 31 10:03 ..
-rw-r--r-- 1 root root 0 Aug 5 00:26 ssm-send-command-test.txt
成功です🙌
最後に
今回はファイルを PUSH した後に GitHub Actions で EC2 インスタンスへ PUSH したファイルを配置したかったので、Send-Command を試しに使ってみました。
これを活用することで、手動で配置したりする手間を省略できたり、複数のインスタンスへ同時へ操作するということも可能で、運用の効率化に繋がると思います😀
Discussion