何故俺のCodePipelineはGithub認証を取れないのか AWS CDK
事の発端
AWS CDKの中でCDK Pipelinesを使用したCI/CD環境の構築を学ぶためにAWSのハンズオンを実施していた時の事。
GithubをパイプラインソースとするCI/CDパイプラインをデプロイしようとした時にエラーが発生しました。
ハンズオンでいうとココ(超序盤)
エラーの内容は以下の通り
MyPipelineStack | 14/16 | 21:49:08 | CREATE_FAILED |
AWS::CodePipeline::Webhook |
Pipeline/Pipeline/Source/XXXXXXXXXXXX/WebhookResource
(PipelineSourceXXXXXXXXXXcdkpipelineWebhookResource384A8AF7)
Webhook could not be registered with GitHub. Error cause: Invalid credentials
[StatusCode: 401, Body: {"message":"Bad credentials","documentation_url":"https://docs.github.com/rest","status":"401"}]
(Service: AWSCodePipeline; Status Code: 400; Error Code: ValidationException;
Request ID: 16cc77d5-eb51-4655-8bb7-0ed34b729467; Proxy: null)
エラーの内容としてはGithubの認証時に認証情報が無効であることをしめしています。
今回はこのエラーを解決するまでの私の遠回りの過程をお伝えします。
トラブルシューティング
今回私が疑ったのは以下のミス
・コードの記述ミス
・IAM権限まわりのミス
コードが間違ってる説
このチェックは簡単でしてた。
自分でタイピングしていたコードをハンズオン資料からのコピペに変えて変数を私の環境に合わせて修正。
しかし、エラーが無くなりません。
コードレビューを実施しても文法的なエラーは見当たらずこの説ではありませんでした。
IAM権限周りのミス
このチェックが終わりの始まりでした。多分10時間は溶かしたと思います。
まずはGitHubトークンを格納しているSecretsManagerのポリシーを確認しますがこれはデフォルトなので設定されておらずアクセス制限がされていない状態です。
Admin権限のユーザーでシークレットを取得できるのを確認できました。
次に怪しまれたのがCDKで構築されるリソースがSecretsManagerシークレットの取得権限を持っていないのではないかという事。
CloudTrailログでイベント名「GetSecretValue」で検索するとCloudFormationがシークレットを取得しようとしていました。
そのログを確認すると 「"responseElements": null,」の文字。
生成AIにこれがエラーの可能性があると言われた私はCloudFormationの権限をチェックすることに
これが間違いだった
AWS CDKはbootstrapを行ったときにリソースのデプロイに必要なIAMロールを作成します。
このロールは主にリソースを実際にデプロイするCloudFormationのロールとして使用されます。
今回CloudTrailログで使用されていたのはcdk-hnb659fds-cfn-exec-roleというロール
どうやらこのロールに権限が足りてないらしいと考えた私はウキウキでポリシーを確認。
Admin権限がついてるやんけ!!
CloudFormationにAdmin権限がついているのにシークレットを取得できない。
これはおかしいです。何故ならこの前に同じくAdmin権限をもつIAMユーザーでシークレットを取得できることを確認しているからです。
この矛盾により完全にドツボにハマった私は生成AIと壁打ちを繰り返しながらCDKのエラーを垂れ流していったのでした……。
解決
そうして2週間以上エラーを格闘し続けた私。
ある日一発目のエラーを食らった後にCloudTrailログを確認するとCloudFormation以外にAdmin権限を持ったIAMユーザーがシークレットを取得しようとしたログが見つかります。
そのログの中にはCloudFormationの時と同じく「"responseElements": null,」の文字。
あれ?これってシークレットを取得できなかった時に出るログでは?
この日の私は予めCLIからIAMユーザーとしてシークレットを取得できることを確認していました。
IAMユーザーでシークレットを取得できた
→でもログには「"responseElements": null,」と表示されている
→もしかしてこのログって取得エラーとは限らない?
→てことはCloudFormationもシークレットを取得できてる?
であれば、CloudFormationはシークレットを取得できたのにGithubの認証に失敗していることになります。
ということは……
Github認証情報(トークン)の権限ミス!?
急いで生成AIにGithubの認証情報の検証方法をききSecretsManagerに保存したGitHubトークンを確認。
するとこれがエラー。
トークンを作り直して再試行すると認証に成功。
そして新しいトークンで認証するようにコードを修正してcdk deploy
✅ MyPipelineStack
✨ Deployment time: 80.1s
Stack ARN:
arn:aws:cloudformation:ap-northeast-1:XXXXXXXXXXXXXX:stack/MyPipelineStack/9e2b6db0-ea0f-11ef-a5c5-0a5b5e5f7215
✨ Total time: 86.31s
デプロイ成功。
まとめ
今回のハマり要因は認証情報エラーを認証情報の権限ミスではなく、AWS側で認証情報を取得できていないという勘違いでした。
CloudTrailログの「"responseElements": null,」は正常な動作の場合も表示されるらしいので決してエラーログと決めつけないようにしないといけませんね。
あと、CDKのコードやCloudFormationのIAMロールはハンズオン通りに実施した時に生成されるものなのでこれを疑うよりもGitHubトークンのような自分の判断で作成されるリソースの設定ミスを疑うべきでした。
自分の力を過信するなリファレンスに従え自我を出すな
なにはともあれエラーの原因を調査し解決する経験ができたのでこの経験を糧にしていたいと思います。
ちなみに
Githubとの連携にトークンを使用する方法は現在のAWSでは推奨されていません。
現在はGithubコネクションを使用した認証が推奨されています。
今回しようしたコンストラクトでもこの形をデフォルトとしています。
実は私も途中でこのやり方を試して問題なくデプロイに成功していました。
でも、推奨ではないものの「このやり方は何か知らないけどできません」とは言いたくなかったので原因調査することにしました。
今後ハンズオンは推奨のバージョン2で進める予定です。
Discussion