serverless deploy On GitHub Actions
記事の内容
GitHub Actionsでserverless frameworkをAWSへデプロイする手順をまとめてみました。
AWSへデプロイする場合、ローカル端末からだとIAMユーザーのクレデンシャルをよく使いますが、
GitHub ActionsのようなCI/CDツールだと、IAMユーザーを使わなくても、OpenIDConnectを使えば
一時的なクレデンシャルでデプロイできます。管理面、セキュリティ面もこちらの方がグッドです。
その方法を整理してみました。
関係する技術・ツール
- serverless framework
- AWS CDK(TypeScript)
- Linux(Ubuntu)
- GitHub
- OpenIDConnect(OIDC)
作業の流れ
- デプロイするAWSアカウントへOIDCProvider作成
- OIDCで許可するIAM RoleとIAM Policy作成
- GitHub Actionsで実施するworkflow作成
- GitHubで、workflowで使用するシークレットを設定する
1 ~ 2. デプロイするAWSアカウントへOIDCProvider作成・OIDCで許可するIAM RoleとIAM Policy作成
OIDCProvider
OIDCを使用するにはデプロイするAWSアカウントにOIDCProviderが必要になります。
GitHubのた めの場合は、https://token.actions.githubusercontent.com
のurlを指定します。
IAM RoleとIAM Policy
OIDCProviderでどんな権限を使いたいか、あらかじめ用意しておく必要があります。
したがってOIDCProviderで許可するIAM Roleを作成します。
併せて、IAM Policyも作成してIAM Roleにアタッチします。
上記、コード化したいためaws-cdk(TypeScript)で作成してみました。
import { Construct } from "constructs";
import { StackProps, Stack, aws_iam } from "aws-cdk-lib";
export class cdkStack extends Stack {
constructor(
scope: Construct,
id: string,
props?: StackProps,
) {
super(scope, id, props);
const gitHubIdProvider = new aws_iam.CfnOIDCProvider(
this,
"GitHubIdProvider",
{
url: "https://token.actions.githubusercontent.com",
clientIdList: ["sts.amazonaws.com"],
thumbprintList: ["6938fd4d98bab03faadb97b34396831e3780aea1"],
}
);
const oidcDeployRole = new aws_iam.Role(this, "GitHubOidcRole", {
roleName: "github-oidc-role",
assumedBy: new aws_iam.FederatedPrincipal(
gitHubIdProvider.attrArn,
{
StringEquals: {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
},
StringLike: {
"token.actions.githubusercontent.com:sub":
"repo:<GitHubアカウント名>/<リポジトリ名>:*",
},
},
"sts:AssumeRoleWithWebIdentity"
),
});
const deployPolicy = new aws_iam.Policy(this, "deployPolicy", {
policyName: "serverlessDeployPolicy",
statements: [
new aws_iam.PolicyStatement({
effect: aws_iam.Effect.ALLOW,
actions: [
"cloudformation:*",
"iam:*",
"cognito-idp:*",
"s3:*",
"appsync:*",
"logs:*",
"lambda:*",
],
resources: ["*"],
}),
],
});
oidcDeployRole.node.addDependency(gitHubIdProvider);
oidcDeployRole.attachInlinePolicy(deployPolicy);
}
}
ちなみに、thumbprintList
ですが、6938fd4d98bab03faadb97b34396831e3780aea1
となっているのは、環境固有ではないようです。
下記のAWSコンソールのOIDCプロバイダ作成画面に「プロバイダURL」を入力すると、簡単に確認できます。
こちらに取得方法など詳しいことが記載されています。
試しに、取得してみたらアルファベットは大文字ではありますが確かに同じ値でした。
$ openssl x509 -in certificate.crt -fingerprint -sha1 -noout
SHA1 Fingerprint=69:38:FD:4D:98:BA:B0:3F:AA:DB:97:B3:43:96:83:1E:37:80:AE:A1
$ echo "69:38:FD:4D:98:BA:B0:3F:AA:DB:97:B3:43:96:83:1E:37:80:AE:A1" | sed s/://g
6938FD4D98BAB03FAADB97B34396831E3780AEA1
3. GitHub Actionsで実施するworkflow作成
.github/workflow/sls-deploy.yml
として作成します。
大きく、
- セットアップ(checkout → runtimeの設定 → package類のインストール)
- 単体テスト
- デプロイ
のフローで作成しようと思います。
今回はモノレポ構成でdevがデフォルトブランチ。slsというディレクトリのソースの変更をdevにマージされたらデプロイする条件をイベントにします。
また3のデプロイについては、2までのstepが成功した場合に実施するようにします。
name: serverless Deploy
on:
push:
branches:
- dev
paths:
- sls/**
permissions:
id-token: write
contents: read
jobs:
deploy:
name: deploy
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16.x]
steps:
# setup phase
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- name: setup ubuntu
run: sudo apt-get update && sudo apt-get install -y ghostscript
- name: install package
run: yarn --cwd sls install
# test phase
- name: execute test
run: yarn --cwd sls test
env:
ENV1_FOR_TEST: ${{ secrets.ENV1_FOR_TEST }}
ENV2_FOR_TEST: ${{ secrets.ENV2_FOR_TEST }}
# deploy phase
- if: ${{ success() }}
uses: aws-actions/configure-aws-credentials@v2
with:
aws-region: ap-northeast-1
role-to-assume: ${{ secrets.OIDC_ROLE }}
- name: serverless deploy
uses: serverless/github-action@v3.1
with:
args: -c "cd ./sls && serverless deploy --verbose"
entrypoint: /bin/sh
env:
ENV1_FOR_DEPLOY: ${{ secrets.ENV1_FOR_DEPLOY }}
ENV2FOR_DEPLOY: ${{ secrets.ENV2_FOR_DEPLOY }}
こちらのGitHub公式のリファレンスを元に作成しました。上記1,2のIAM RoleとPolicyの作成についても記載されています。aws-actions/configure-aws-credentialsというアクションを使います。
- aws-region: デプロイするリージョン
- role-to-assume: 1~2で作成したIAM RoleのArn
注意点としては、
permissions:
id-token: write
contents: read
リファレンスにもありますが、こちらはほぼ必須になるかと思います。
contentsはcheckoutするために必要です。
余談ですが、単体テストにあたりghostscript
が必要なためインストールしています。
こちらOSに依存するソフトウェアなのですが、このようにセットアップしておくことで、GitHub上のUbuntuでもテストを実行できます。
4. GitHubで、workflowで使用するシークレットを設定する
GitHubでIAM RoleのArnを設定します。
暗号化してくれる分には構わないので、シークレットで設定しました。
「OIDC_ROLE」という名前で設定します。
ちなみに、ENV1_FOR_TEST、ENV1_FOR_DEPLOYなどのようにテストや、デプロイに使用する環境変数も設定するとworkflowで使用できます。
実行してみる
実行されるには、作成したsls-deploy.yml
が、デフォルトブランチ(dev)にあれば実行されます。したがって、ymlをfeatureブランチで作成していれば、devにマージしたタイミングで実行されます。
下記はマージ前なので、workflowは表示されていませんが、マージされると、サイドメニューにserverless Deploy
が表示されると思います。
無事実行されてデプロイまで完了すれば、下記のようにworkflow成功になります。
OIDCProviderを作成しないと、エラーとなり失敗するため、下記のようにデプロイが中断されます。
Error: No OpenIDConnect provider found in your account for https://token.actions.githubusercontent.com
エラーメッセージは詳細に出力されました。もし失敗してしまう場合はメッセージ頼りに原因探ることになるでしょう。
以上になります。
これで無事、GitHub ActionsでAWSへのデプロイをCI/CDできるようになりました!
NCDC株式会社( ncdc.co.jp/ )のエンジニアチームです。 募集中のエンジニアのポジションや、採用している技術スタックの紹介などはこちら( github.com/ncdcdev/recruitment )をご覧ください! ※エンジニア以外も記事を投稿することがあります
Discussion