GitHub Actions内からEC2で作成したサーバにおいてあるシェルを実行できるのだけれども、WEB情報をみてみるとアクセスキーとシークレットアクセスキーをシークレットに設定してからEC2内のコマンドを実行する例がよく顕在される。
例えば以下のような情報
https://take-engineer.com/aws-ssm_ec2_github-actions/
name: AWS SSM Send-Command Example
on:
push:
branches: main
jobs:
start:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: AWS SSM Send-Command
uses: peterkimzz/aws-ssm-send-command@master
id: ssm
with:
aws-region: ${{ secrets.AWS_REGION }}
ここ ==> aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
ここ ==> aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
instance-ids: ${{ secrets.INSTANCE_ID }}
working-directory: /home/ubuntu
command: hogehoge.sh
もっとよい方法があるはずだ!
GitHubActions内には(正確には runs-on: ubuntu-latest で構築されるコンテナ内)AWS CLIがすでにインストールされているので、aws ssm send-command で セッションマネージャー経由にてEC2内のコマンドが実行できるはず。
つまり以下が発行できればよいということではないか?
EC2内で初期化などの実行したいシェルを作成しておき (例) 「setup.sh」
[setup.sh]を実行するAWS CLIコマンド
aws ssm send-command \
--document-name "AWS-RunShellScript" \
--document-version "1" \
--targets "Key=instanceids,Values=xxxxxxxxxxxxx" \
--parameters "commands='setup.sh'" \
--timeout-seconds 180 \
--max-concurrency "50" \
--max-errors "0" \
--region ap-northeast-1
事前準備
以下の2点のみで準備OK
- セッションマネージャーからアクセスできるようにEC2をセッティングする。
- GitHubActions内から ssm send-command を実行できるようにするため、
IAMロールを作成する。
セッションマネージャーからアクセスできるようにEC2をセッティングする。
// セッションマネージャーから接続できるようにポリシーを設定
const role = new iam.Role(this, 'ec2Role', {
assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com')
})
role.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonSSMManagedInstanceCore'))
//このあたりはいろいろ省略
//EC2インスタンスの作成
const ec2Instance = new ec2.Instance(this, 'ec2Instance', {
vpc,
instanceType: ec2.InstanceType.of(ec2.InstanceClass.T2, ec2.InstanceSize.NANO),
machineImage: ami,
securityGroup: securityGroup,
role: role, <====== ロールを設定
});
GitHubActions内から ssm send-command を実行できるようにするため、IAMロールを作成する。
-- IAMロールの作成 arn:aws:iam::xxxxxxxxxxxx:role/deploy-role --
信頼ポリシー
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::xxxxxxxxxxxx: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:XXXXX/xxxxxxxx:ref:refs/heads/*"
}
}
}
]
}
許可ポリシー インライン
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:ListBucket", <== これらはおまけ、GithubActions内からS3へリソースをsyncするのに必要
"s3:GetObject", <== 今回はなくてもOK
"s3:PutObject", <==
"ssm:SendCommand" <== これが必要
],
"Resource": "*",
"Effect": "Allow"
}
]
}
GitHubActionsの書き方
事前に変更されるであろうパラメータを GitHub Actions 構成変数(環境変数) に設定しておく
- AWS_ROLE
- (arn:aws:iam::xxxxxxxxxxxx:role/deploy-role)
- AWS_EC2_INSTANCEIDS
- (i-abcdefg)
- AWS_SSM_SEND_COMMAND
- (setup.sh)
Actions(実際)の書き方 (actions.yml)
jobs:
deploy:
name: sample
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- uses: actions/checkout@v3
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v2
with:
role-to-assume: ${{ vars.AWS_ROLE }}
aws-region: ap-northeast-1
- name: ec2 shell run
run: |
aws ssm send-command \
--document-name "AWS-RunShellScript" \
--document-version "1" \
--targets "Key=instanceids,Values=${{ vars.AWS_EC2_INSTANCEIDS }}" \
--parameters "commands='${{ vars.AWS_SSM_SEND_COMMAND }}'" \
--timeout-seconds 180 \
--max-concurrency "50" \
--max-errors "0" \
--region ap-northeast-1
ここで注意点
警告
aws ssm send-command で実行されるユーザーは 「ssm-user」になるので、他(たとえばubuntu)ユーザでシェル内コマンドを実行する場合 su コマンドでユーザを変更する記述を書く必要がある。
記述例
#!/bin/bash
cd /home/ubuntu
sudo su - ubuntu <<EOF
echo hogehoge
EOF
補足
aws s3 sync コマンドを実行できるので、リポジトリ内に setup.sh を配置しておき
S3にアップロード後にダウンロードしてその内容を実行するようにシェルを書いておけば
プルリクエストで初期設定などの内容が変更されてるのでこの方法も有用。