GitHub Actions から EC2 へ Session Manager を使用してなるべくセキュアにファイルをアップロードする
概要
とある案件で GitHub Actions から EC2 へファイルをアップロードしたい、ということがありました。
該当の EC2 は、普段は AWS Session Manager を使用してサーバーにアクセスしており、 SSH/SFTP の穴を開けていないサーバーでした。
そのため、 Session Manager 経由でファイルをアップロードできないか試してみたところ、うまくいったという感じです。
要件
今回やりたかったことは以下のような感じです。
- GitHub Actions から rsync でファイルをアップロード
- EC2 の SSH ポートは開けたくない
- SSH でログインする Linux のユーザーはアップロード用に作成したもの
これを受けて、以下のようにしました。
- AWS Session Manager を使用して、rsync over ssh でファイルをアップロードする
- GitHub Actions の AWS Session Manager を実行する権限の設定は、 OIDC Provider による IAM Role の委譲で行う
- Session Manager が使用する SSM Document は、デフォルトのものだと ssm-user 固定なので、新しく作成
これであれば、EC2 に SSH ポートの穴を開けずに、かつ GitHub 常に固定の AWS のクレデンシャルを残さないので、セキュアにできて良いかなーという気持ちです。
実装
というわけで実装していきます。
AWS の設定は terraform を使って構築していきます。
まずは、使いたい Linux ユーザーでログインできるように、新しく SSM Document を作成します。
resource "aws_ssm_document" "github_actions" {
name = "SSM-SessionManagerRunShell-Deploy"
document_type = "Session"
content = jsonencode({
schemaVersion = "1.0"
sessionType = "Port"
inputs = {
runAsEnabled = true
runAsDefaultUser = "hoge-user"
}
properties = {
portNumber = "22"
}
})
}
hoge-user
はアップロードしたい Linux のユーザー名を入れてください。
次に GitHub Actions で AWS の IAM Role を使用できるようにします。
// OIDC provider を作成
resource "aws_iam_openid_connect_provider" "github_actions_oidc_provider" {
url = "https://token.actions.githubusercontent.com"
client_id_list = ["sts.amazonaws.com"]
thumbprint_list = [
"6938fd4d98bab03faadb97b34396831e3780aea1",
"1c58a3a8518e8759bf075b76b750d4f2df264fcd"
]
}
// GitHub Actions で使用する Role を作成
data "aws_iam_policy_document" "github_actions_assume_role" {
statement {
effect = "Allow"
actions = ["sts:AssumeRoleWithWebIdentity"]
principals {
identifiers = [aws_iam_openid_connect_provider.github_actions_oidc_provider.arn]
type = "Federated"
}
condition {
test = "StringEquals"
variable = "token.actions.githubusercontent.com:sub"
values = ["repo:${local.repo_name}:ref:refs/heads/main"]
}
condition {
test = "StringEquals"
variable = "token.actions.githubusercontent.com:aud"
values = ["sts.amazonaws.com"]
}
}
}
resource "aws_iam_role" "role" {
name = "oidc-role"
assume_role_policy = data.aws_iam_policy_document.github_actions_assume_role.json
}
data "aws_iam_policy_document" "policy_document" {
statement {
effect = "Allow"
actions = ["ssm:StartSession"]
resources = [
"arn:aws:ec2:ap-northeast-1:${data.aws_caller_identity.self.account_id}:instance/${module.instance_web.instance_id}",
aws_ssm_document.github_actions.arn,
]
}
statement {
effect = "Allow"
actions = ["ssm:TerminateSession"],
resources = ["arn:aws:ssm:*:*:session/*"]
]
}
}
resource "aws_iam_role_policy" "role_policy" {
role = aws_iam_role.role.id
policy = data.aws_iam_policy_document.policy_document.json
}
local.repo_name
には実行したい GitHub Actions があるリポジトリ名が入ります。org-name/repo-name
みたいなやつ。
ここで、作成した SSM Document を使って、ログインできるか確認します。
事前にインスタンスには SSH の公開鍵を登録しておいてください。
ssh hoge-user@ -oProxyCommand='sh -c "aws ssm start-session --target i-1234567880abcdefg --document-name SSM-SessionManagerRunShell-Deploy"'
問題なくログインできれば 🆗
次に、GitHub Actions を設定します。
今回は、 easingthemes/ssh-deploy
という Action を使ってみました。
name: deploy
on:
push:
branches:
- main
jobs:
deploy:
name: 🚀 deploy
runs-on: ubuntu-latest
permissions:
contents: write
id-token: write
steps:
- name: 🔑 Setup AWS Credentials
uses: aws-actions/configure-aws-credentials@v1
with:
role-to-assume: arn:aws:iam::1234567890:role/hoge-role
role-session-name: deploy
aws-region: ap-northeast-1
- name: 🚀 Deploy to EC2
uses: easingthemes/ssh-deploy@main
env:
SSH_PRIVATE_KEY: ${{ secrets.EC2_SSH_KEY }}
REMOTE_USER: ${{ secrets.DEPLOY_USER }}
REMOTE_HOST: "i-1234567880abcdefg"
SSH_CMD_ARGS: "-o StrictHostKeyChecking=no, -o ProxyCommand='aws ssm start-session --target %h --document-name SSM-SessionManagerRunShell-Deploy'"
SOURCE: "dist/"
TARGET: "/home/${{ secrets.DEPLOY_USER }}/dist"
これで無事に GitHub Actions からセキュアにファイルをアップロードできるようになりました。
便利み🎉
Discussion