0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Amazon Cognito × Google Workspace SAMLで認証基盤を作り、CloudFront/ALBでアクセス制御する

0
Posted at

はじめに

Google Workspace(以下GWS)をIdPとしたSAML認証で、Amazon Cognitoの認証基盤を構築し、さらにDev環境へのアクセス制御を「ALB認証アクション」と「CloudFront + Lambda@Edge」の2方式で実装・比較した記録です。

インフラ初心者が実際に手を動かしながら詰まったポイントも含めて残しているので、同じ構成を組む方の参考になれば幸いです。

この記事で扱うこと

  • Amazon Cognito User Poolの作成
  • GWSをIdPとしたSAML 2.0連携
  • ALB認証アクションによるインフラレイヤのアクセス制御
  • CloudFront + Lambda@Edge(cognito-at-edge)によるアクセス制御
  • 2方式のメリット・デメリット比較

想定構成

ユーザー → CloudFront → ALB(internal) → ECS(Frontend / Backend)

用語整理

最初に登場人物を整理しておきます。

用語 役割 例え
Google Workspace (IdP) 「この人は本人です」と証明する側 パスポート発行所
Amazon Cognito (SP) 証明を受け取りトークンを発行する側 入国審査
SAML 2.0 IdPとSPの間の通信ルール パスポートの規格

Part 1. Amazon Cognito User Poolの作成

1-1. User Poolを作成する

AWSマネジメントコンソールからCognitoを開き、User Poolを作成します。新しいUIではウィザードではなく1画面に統合されています。

項目 設定値
アプリケーションタイプ 従来のウェブアプリケーション
サインイン識別子 メールアドレス
自己登録 無効(チェックを外す)
必須属性 メールアドレス

ポイント
認証はGWSに委譲するため、Cognito側で自己登録を有効にする必要はありません。「従来のウェブアプリケーション」を選ぶと、バックエンドでの認可コードフローに適した設定になります。

1-2. ドメインを確認する

作成後、アプリケーションの統合 > ドメイン でCognitoドメイン(またはカスタムドメイン)を確認します。このドメインがSAMLのACS URLのベースになります。

例: https://xxxxx.auth.ap-northeast-1.amazoncognito.com

この時点で、SAML連携に必要な以下2つの値が決まります。

値 形式
Entity ID urn:amazon:cognito:sp:<User Pool ID>
ACS URL https://<ドメイン>/saml2/idpresponse

Part 2. Google WorkspaceでSAMLアプリを作成する

2-1. カスタムSAMLアプリを追加

Google Admin Console(admin.google.com)に特権管理者でログインし、以下の手順で進めます。

  1. アプリ > ウェブアプリとモバイルアプリ
  2. アプリを追加 > カスタムSAMLアプリを追加
  3. アプリ名を入力

2-2. GoogleのIdP情報をダウンロード

「Google IdP情報」画面で メタデータ(GoogleIDPMetadata.xml)をダウンロード します。このXMLにEntity ID・SSO URL・X.509証明書がすべて含まれています。

<md:EntityDescriptor entityID="https://accounts.google.com/o/saml2?idpid=XXXX" validUntil="2031-02-07T...">
  ...
  <md:SingleSignOnService Location="https://accounts.google.com/o/saml2/idp?idpid=XXXX"/>
</md:EntityDescriptor>
項目 XML内の場所
Entity ID entityID 属性
SSO URL SingleSignOnService の Location
X.509証明書 X509Certificate 要素
証明書有効期限 validUntil 属性

運用メモ
validUntil の値は証明書の有効期限です。運用ドキュメントに記録しておき、期限前に更新できるようにしておきましょう。

2-3. サービスプロバイダの詳細を入力

Cognito側の値を入力します。

項目 値
ACS URL https://<ドメイン>/saml2/idpresponse
Entity ID urn:amazon:cognito:sp:<User Pool ID>
Name IDフォーマット EMAIL
Name ID Primary email

ハマりどころ
ACS URLとEntity IDは完全一致が必要です。スペルミスや末尾スラッシュの有無で認証が失敗します。

2-4. 属性マッピング

Google Directory属性 アプリ属性
Primary email email
First name firstName
Last name lastName

2-5. アプリを有効化

作成したアプリはデフォルトで無効です。ユーザーアクセス > 全員に対してオン に変更しないとログインテストができません。


Part 3. CognitoにSAML IdPを登録する

3-1. IDプロバイダーを追加

サインインエクスペリエンス > フェデレーテッドIDプロバイダー > IDプロバイダーを追加 でSAMLを選択し、2-2でダウンロードした GoogleIDPMetadata.xml をアップロードします。

3-2. 属性マッピング

Cognito側は「ユーザープール属性(左)」と「SAML属性(右)」の対応を設定します。SAML属性側はGWSで設定した属性名を手入力します。

ユーザープール属性 SAML属性
email email
given_name firstName
family_name lastName

3-3. アプリクライアントへ紐付け

アプリクライアントの「ログインページ」設定で、IDプロバイダーに先ほど登録したSAML IdPを指定します。

項目 値
IDプロバイダー GoogleWorkspace
OAuth 2.0許可タイプ 認証コード付与
OpenID Connectスコープ openid, email, profile

3-4. 動作確認

Hosted UI(マネージドログイン)からテストし、Googleログイン画面 → ログイン → コールバックURLに ?code=xxxx が返ればSAML連携は成功です。


Part 4. ALB認証アクションでアクセス制御する

ここからはインフラレイヤでのアクセス制御です。アプリのコードを変更せず、ALBの機能だけでCognito認証を強制します。

4-1. ALB用アプリクライアントを作成

重要
ALBのCognito認証は クライアントシークレットが必須 です。シークレットなしのクライアントを指定すると以下のエラーになります。

InvalidLoadBalancerActionException: The user pool client must have a client secret

シークレットありのアプリクライアントを新規作成し、コールバックURLに以下を追加します。

https://<ALBドメイン>/oauth2/idpresponse

4-2. リスナールールに認証アクションを追加

HTTPS:443のリスナールールに「ユーザーの認証」アクションを追加します。アクションの順番が重要です。

順番 アクション
1番目 ユーザーの認証(Cognito)
2番目 ターゲットグループへ転送

ヘルスチェックの注意
/health などのヘルスチェックパスに認証をかけるとヘルスチェックが失敗します。優先度の高いルールで /health を認証なしに分離しておきましょう。

最終的なルール構成例:

優先度 条件 認証 転送先
50 /health なし backend
100 /api/* あり backend
デフォルト 上記以外 あり frontend

4-3. CloudFront経由でのハマりどころ

CloudFront → ALB構成の場合、いくつか追加対応が必要でした。

リダイレクトループ

CloudFrontのオリジンリクエストポリシーが AllViewerExceptHostHeader だと、Hostヘッダーが転送されずリダイレクトループになります。AllViewer に変更し、CloudFrontドメインのコールバックURL(https://<CloudFrontドメイン>/oauth2/idpresponse)もCognitoに追加します。

500 Internal Server Error

ALBが認証コードをトークンに交換する際、Cognitoのトークンエンドポイントへ通信します。ALBのセキュリティグループのアウトバウンドでHTTPS(443)が許可されていないと、この通信が失敗して500エラーになります。アウトバウンドルールを確認しましょう。


Part 5. CloudFront + Lambda@Edgeでアクセス制御する

もう一つの方式として、CloudFrontのエッジで認証する方法を試します。cognito-at-edge というライブラリを使います。

5-1. クライアントシークレットの考え方

cognito-at-edge は クライアントシークレットなし で動作させられます。

方式 シークレット 理由
ALB認証 必須 AWSの仕様。ALBがマネージドで安全に保持できる前提
Lambda@Edge 不要にできる Lambda@Edgeは環境変数が使えずコード直書きになるため、シークレットを含めない方がむしろ安全

5-2. Lambda関数のコード

const { Authenticator } = require('cognito-at-edge');

const authenticator = new Authenticator({
  region: 'ap-northeast-1',
  userPoolId: 'ap-northeast-1_xxxxxxxxx',
  userPoolAppId: 'xxxxxxxxxxxxxxxxxxxxxxxxxx',
  userPoolDomain: 'auth.dev.example.net',
});

exports.handler = async (request) => authenticator.handle(request);

依存パッケージを含めてzip化し、Lambdaにアップロードします。

npm install cognito-at-edge
zip -r function.zip index.js node_modules/

5-3. Lambda@Edgeデプロイの注意点

us-east-1で作成する

Lambda@Edge関数は 必ず us-east-1(バージニア北部) で作成する必要があります。

信頼ポリシーの修正

実行ロールの信頼ポリシーに edgelambda.amazonaws.com を追加します。

"Service": [
  "lambda.amazonaws.com",
  "edgelambda.amazonaws.com"
]

バージョン発行が必須

Lambda@Edgeは $LATEST を使えません。バージョンを発行し、発行済みバージョンをCloudFrontに関連付けます。これはエッジロケーションにコードを配置する都合上、コードを確定させる必要があるためです。

VPCオリジンの制約

CloudFrontがVPCオリジン(内部ALBへ直接接続する構成)を使っている場合、オリジンリクエストではLambda@Edgeを関連付けられません。

trigger の作成中にエラーが発生しました:
VPC origin with an origin Lambda@Edge association is not supported.

cognito-at-edge はビューワーリクエストで認証する設計なので、ビューワーリクエストで関連付ければ問題ありません。

CloudFrontイベント 設定
ビューワーリクエスト ◯(これを使う)
オリジンリクエスト ✕(VPCオリジンでは不可)

Part 6. ALB認証 vs Lambda@Edge 比較

観点 ALB認証アクション CloudFront + Lambda@Edge
実装の手間 少ない(GUI設定のみ、コード不要) 多い(Lambda保守が必要)
認証を止める位置 ALB(リージョン) エッジ(CloudFront)
クライアントシークレット 必須 不要にできる
CloudFrontキャッシュ 効きにくい(毎回ALBへ) 効かせられる(エッジで認証完結)
デプロイの制約 通常のALB設定 us-east-1・バージョン発行・反映に数分
デバッグ リージョンにログ集約で見やすい エッジに分散して見づらい

キャッシュについての補足

「ALB認証だとCloudFrontのオリジンキャッシュが効かない」という指摘はその通りですが、キャッシュポリシーが CachingDisabled の場合はそもそもキャッシュしていないため、この差は問題になりません。将来的にキャッシュを積極利用する予定があるかどうかが判断の分かれ目です。

どちらを選ぶか

  • シンプルさ重視・キャッシュ予定なし → ALB認証アクション
  • 将来的にCloudFrontキャッシュを活用したい → Lambda@Edge

Dev環境であれば、まずはシンプルなALB認証アクションで十分なケースが多いと考えます。


まとめ

  • GWSをIdPとしたSAML連携は、GoogleIDPMetadata.xml をCognitoにアップロードするだけで証明書・SSO URL・Entity IDがまとめて登録できる
  • インフラレイヤのアクセス制御は「ALB認証アクション」と「Lambda@Edge」の2方式がある
  • ALB認証はシンプルだがキャッシュが効きにくく、シークレット必須
  • Lambda@Edgeはキャッシュを活かせるが、us-east-1・バージョン発行・VPCオリジン制約などの考慮が必要

同じ構成で詰まった方の助けになれば幸いです。

参考リンク

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?