GitHub Actionsで使用するAWSクレデンシャルをより安全なOIDC方式(AWS IDプロバイダ)に切り替えた
はじめに
レスキューナウでは、Cloud環境へのデプロイにおいてGitHub Actionsを活用しています。
パイプラインの構築にはGitHubのSecretsにAWSのクレデンシャルとしてAWS_ACCESS_KEY
とAWS_SECRET_KEY
を登録して使用するケースは実装も簡単でよく使われていると思います。
しかし、この方法には長期間有効なAWSのクレデンシャル情報を保有し続けるという、セキュリティ上の懸念が存在するため、より安全な状態にするため、OIDC(OpenID Connect)を使用する方法に切り替えました。
OIDCを使うメリットはこちらが参考になりました
AWS IDプロバイダの作成
AWSコンソール画面を開き、左側のメニューから IDプロバイダを選択します
プロバイダを追加
ボタンを押して プロバイダ設定画面を開きます
GitHubのドキュメントを参考にプロバイダのURL
と対象者
情報を入力します
プロバイダー URL の場合: https://token.actions.githubusercontent.com を使います
"Audience" の場合: 公式のアクションを使っている場合は、sts.amazonaws.com を使います。
ロールを作成する
AWSコンソール画面を開き、左側のメニューから ロールを選択します
ロールを作成
を選択して カスタム信頼ポリシー
を選択します
カスタム信頼ポリシーには以下のような情報を入力します
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::アカウントID:oidc-provider/token.actions.githubusercontent.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringLike": {
"token.actions.githubusercontent.com:sub": "repo:octo-org/octo-repo:*"
},
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
}
}
}
]
}
Federated
フィールドには、先ほど作成したOIDCプロバイダのARN(Amazon Resource Name)を指定します。
Condition
フィールドでは、OIDCで検証する条件を指定します。GitHub公式の例では、2つの条件が指定されています。
token.actions.githubusercontent.com:sub
は、GitHubのリポジトリを特定するための条件です。GitHubActionsを実行するRepositoryを指定します
"octo-org/octo-repo"という名前のGitHubリポジトリに対してのみ認証を許可設定していて、この条件に一致しない場合は認証は拒否されます。
token.actions.githubusercontent.com:aud
は、トークンの発行先を検証するための条件です。ここでは、sts.amazonaws.comという値が指定されており、トークンがAWS Security Token Service (STS)
によって発行されたものであることを確認しています。
この条件に一致しない場合は認証されません
このカスタム信頼ポリシーの設定により、GitHub Actionsからのリクエストが特定のGitHubリポジトリに関連付けられ、かつAWS STSによって発行されたトークンである場合にのみ、IAMロールへのアクセスが許可されます。
許可ポリシーの作成
今回は動作確認用にGetCallerIdentity
を設定します
左側のメニューから ポリシーを選択します
sts
を選択して読み取り項目にあるGetCallerIdentity
を選択してください
許可を追加
作成したロールに許可ポリシーをアタッチします
GetCallerIdentity
は呼出し元のIAMユーザーまたはロールの情報を返却します
作成
ロール名を設定してIAMロールを作成します
カスタム信頼ポリシーと許可ポリシーが正しいことを確認してください
作成されたロール情報を確認します
ここで確認できるARN
情報をGitHubのSecret情報に登録してGitHubActionsから呼出します。
これでGetCallerIdentity
の権限を持ったID プロバイダが作成できました
上記の手順をCloudFormationで実行する
本番/開発など色々な環境で用意する可能性があるので
上記のAWSコンソールで行った手順をCloudFormation
で構築できるようにします
AWSTemplateFormatVersion: 2010-09-09
Parameters:
Thumbprint:
Type: String
Default: '6938fd4d98bab03faadb97b34396831e3780aea1'
Resources:
GitHubActionsOidcProvider:
Type: AWS::IAM::OIDCProvider
Properties:
Url: https://token.actions.githubusercontent.com
ClientIdList:
- sts.amazonaws.com
ThumbprintList:
- !Ref Thumbprint
RoleGitHubActions:
Type: AWS::IAM::Role
Properties:
RoleName: oidc-get-caller-Identity
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Action: sts:AssumeRoleWithWebIdentity
Principal:
Federated: !Sub arn:aws:iam::${AWS::AccountId}:oidc-provider/token.actions.githubusercontent.com
Condition:
StringEquals:
token.actions.githubusercontent.com:aud: sts.amazonaws.com
StringLike:
token.actions.githubusercontent.com:sub: repo:octo-org/octo-repo:*
Policies:
- PolicyName: GetCallerIdentity
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- sts:GetCallerIdentity
Resource: '*'
Outputs:
Role:
Value: !GetAtt RoleGitHubActions.Arn
GitHubActionsに登録する
GitHubActionsのワークフローを設定します
GitHubActionsを実行したいRepositoryのSeacret情報に
secrets.AWS_ROLE_ARN
として、作成したロールのARNを登録します.
作成したAWSのIDプロバイダをconfigure-aws-credentialsを使用して認証情報を取得します
name: sts:GetCallerIdentity
on: workflow_dispatch
permissions:
id-token: write
contents: read
jobs:
get-caller-identity:
runs-on: ubuntu-latest
steps:
- uses: aws-actions/configure-aws-credentials@v2
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
aws-region: ap-northeast-1
- run: aws sts get-caller-identity
configure-aws-credentials
からAssumeRoleWithWebIdentity
を呼出すことで
AWSから一時的な認証情報を取得しています、この機能により有効期限が長いAWS_ACCESS_KEY
とAWS_SECRET_KEY
を使用することなくAWSのAPIを呼び出すことができます。
実行結果
ワークフローを実行するとget-caller-identity
から実行したロール情報が取得されていることが確認できました
まとめ
AWSのクレデンシャル情報の利用をやめて、OIDCを経由して一時的に認証することができました
実装としてはconfigure-aws-credentials
のrole-to-assume
にロールのARNを設定するだけで
OIDC の概要にに記載されている流れを実現できるのは非常に便利だと思います。
Discussion