KeycloakのSAML2 IdPをAmazon Cognito user poolsと連携する
Keycloak は SAML の Identity Provider (IdP) としてあるいは OpenID Connect (OIDC) の OpenID Provider (OP) として使用することができます。
2層アーキテクチャ (Two-tier Architecture) や 3層アーキテクチャ (Three-tier Architecture)、またはより多層 (Multi-tier) となるマイクロサービスアーキテクチャで構築されたアプリケーションに認証認可機能を提供する場合には持参人トークン (Bearer token) を使用する OIDC が適していますが、SAML フェデレーション機能を活用することで ID やパスワードを使用する認証フローをプライベートネットワーク内に閉じることができる利点も得られます。
この記事では、SAML IdP として Keycloak を Rancher Desktop の Kubernetes 環境にインストールし、OIDC の OP として Amazon Cognito user pools をセットアップする方法を説明します。
環境
- mac mini (Apple Silicon)
- Rancher Desktop 1.7.0
- Kubernetes 1.23.13
Keycloakのインストール
Keycloak は Helm チャートを使ってインストールします (ArtifactHUB)。
codecentric/helm-charts の values.yaml
を元にした takesection/keycloak-install を clone します。
git clone https://github.com/takesection/keycloak-install.git
この記事では Rancher Desktop に同梱されている Ingress、traefik を使用するため、TLS のための証明書を用意する必要があります。
証明書を Let's Encrypt で取得する例から説明します。
certbot
Homebrew を使って certbot をインストールします。
brew install certbot
証明書生成
次のコマンドを実行します。
sudo certbot certonly --manual --preferred-challenges dns
ドメイン名を入力します。所有するドメイン名が example.com
であれば、*.example.com
のように入力すると便利です。
Please enter in your domain name(s) (comma and/or space separated) (Enter 'c' to cancel):
ドメイン名の所有を確認するために、DNS に TXT レコードの追加が要求されます。
表示された指示に従って DNS (Route 53 等) に TXT レコードを追加します。
_acme-challenge.example.com TXT "<表示された値>"
DNS にレコードを追加してから、それがローカル環境で認識されるまで少し時間がかかるので、追加後しばらく待ってから Enter キーを押してください。
成功すると、この例であれば /etc/letsencrypt/live/example.com
ディレクトリに証明書ファイルが生成されます。
生成されたファイルを keycloak-install
にコピーします。
sudo cp /etc/letsencrypt/live/example.com/fullchain.pem /etc/letsencrypt/live/example.com/privkey.pem ./
tls-secret
を作成します。
kubectl create secret tls tls-secret --cert=fullchain.pem --key=privkey.pem
values.ymlの編集
values.yml
から local-values.yml
をコピーしてください。
cp values.yml local-values.yml
local-values.yml
の298行目、306行目にある ingress の設定を、証明書のドメイン名に合わせて編集します。例えば、使用するドメイン名が keycloak.example.com
であれば、以下のようになります。
# List of rules for the Ingress rules: - # Ingress host host: '{{ .Release.Name }}.example.com' # Paths for the host paths: - path: / pathType: Prefix # TLS configuration tls: - hosts: - keycloak.example.com secretName: "tls-secret"
Helm チャートのリポジトリを追加します。
helm repo add codecentric https://codecentric.github.io/helm-charts
keycloak をインストールします。
helm install keycloak --values=local-values.yml codecentric/keycloak
Keycloak の初期設定
port-forward で localhost でアクセスできるようにします。
kubectl port-forward svc/keycloak-http 8080:80
ブラウザを使って http://localhost:8080/auth/
にアクセスして、管理者のユーザ名とパスワードを設定します。
Create
ボタンをクリックします。
メタデータのダウンロード
kubectl get ingress
で表示されたホスト名とIPアドレスを、DNS (Route 53) または /etc/hosts
ファイルに設定します。
ブラウザを使って https://keycloak.example.com/auth/
にアクセスします。以降、example.com
の部分は所有しているドメイン名で読み替えてください。
Administration Console
をクリックして、設定したユーザ名、パスワードを入力して Sign In
ボタンをクリックします。
左上の Master
と表示されているところにマウスカーソルを移動して、Add realm
ボタンをクリックします。
任意の Name
を入力します。ここでは local
と入力して Create
ボタンをクリックします。
レルム Local
の Endpoints にある SAML 2.0 Identity Provider Metadata
のリンクをクリックして、ダウンロードします。
Cognito User pools
AWS の管理コンソールにログインして、東京 (ap-northeast-1) リージョンの Cognito サービスにアクセスし、ユーザープールの管理
ボタンをクリックします。
ユーザープールを作成する
ボタンをクリックし、プール名に keycloak
と入力します。そして デフォルトを確認する
ボタンをクリックします。
プールの作成
ボタンをクリックします。
プールID
の値をメモします。urn:amazon:cognito:sp:<プールID>
を Keycloak のクライアント名の設定に後で使用します。
左側にある アプリの統合
- ドメイン名
を選択して、ドメイン名を入力し、変更の保存
ボタンをクリックします。
ドメイン名が例えば https://example.auth.ap-northeast-1.amazoncognito.com
の場合、Keycloak のクライアントに設定する Endpoint は https://example.auth.ap-northeast-1.amazoncognito.com/saml2/idpresponse
になります。
左側にある 全般設定
- アプリクライアント
を選択し、アプリクライアントの追加
リンクをクリックします。
アプリクライアント名
に saml
と入力して アプリクライアントの作成
ボタンをクリックします。
左側にある フェデレーション
- ID プロバイダー
を選択し、SAML
を選択します。
メタデータドキュメント
の Select file
ボタンをクリックして、Keycloak の SAML 2.0 Identity Provider Metadata
リンクからダウンロードしたファイルを選択します。プロバイダ名には keycloak
と入力して プロバイダーの作成
ボタンをクリックします。
左側にある フェデレーション
- 属性マッピング
を選択し、SAML 属性の追加
リンクをクリックします。SAML 属性
に email
と入力し、ユーザープール属性
に Email
を選択して 変更の保存
ボタンをクリックします。Amazon Cognito user pools は email
属性が必須なためです。
Keycloak のクライアント
再び、Keycloak に戻ってクライアントを追加します。
レルム Local
の Configure
- Clients
を選択し Create
ボタンをクリックします。
Client ID
に urn:amazon:cognito:sp:<プールID>
の形式で入力します。
Client Protocol
は saml
を選択し、Save
ボタンをクリックします。
Settings
をデフォルトから変更する項目は次のとおりです。
Sign Documents
をOFF
Sign Assertions
をON
Client Signature Required
をOFF
Force Name ID Format
をON
Name ID Format
をpersistent
に設定Valid Redirect URIs
にhttps://<Cognito user pools に設定したドメイン名>/saml2/idpresponse
を設定
Save
ボタンをクリックします。
Mappers
タブを選択し、Create
ボタンをクリックします。
次のように入力し、Save
ボタンをクリックします。
Name
にemail
を設定Mapper Type
にUser Attribute
User Attribute
にemail
を設定SAML Attribute Name
にemail
を設定
ユーザの追加
左側の Manage
- Users
を選択し、Add user
ボタンをクリックします。
Username
、Email
等を入力し Save
ボタンをクリックします。
追加したユーザの Credentials
タブを選択し、パスワードを設定して Set Password
ボタンをクリックします。
Cognito User poolsのアプリクライアントの設定
AWS 管理コンソールの Cognito サービスの左側にある アプリの統合
- アプリクライアントの設定
をクリックします。
有効な ID プロバイダ
に keycloak
を選択します。
コールバック URL
は OIDC のフローのコールバック URL を設定しますが、テストのために http://localhost:8080/callback
と入力します。
許可されている OAuth フロー
は、これもテストのために Implicit grant
をチェックします。
許可されている OAuth スコープ
は、email
と openid
をチェックし、変更の保存
ボタンをクリックします。
ホストされた UI を起動
リンクをクリックし、keycloak
ボタンをクリックします。
Keycloak の認証画面が表示されるので、Username or email
と Password
を入力して Sign In
ボタンをクリックします。
サインインに成功しても、コールバック URL を処理するアプリケーションがありませんが、ブラウザの URL にはコールバック URL とフラグメント (#
) の後に access_token
や id_token
等が表示されます。id_token
の値を jwt.io にペーストして JWT を確認できます。
なお、コールバック URL を envoyproxy で処理することも可能です。「Envoy OAuth2 Filter を使ったログイン」の記事で説明しています。また、この記事で紹介している GitHub リポジトリ には Kubernetes 環境にデプロイするための Helm チャートも用意しています。
まとめ
SAML や OpenID Connect のような業界標準を採用することで、認証基盤に採用するプロダクトの幅が広がります。この記事では Keycloak を SAML IdP として使用する例を紹介しました。
Keycloak を SAML IdP として使用することで、WebAuthn のような新しい認証方式への対応も可能になります。
Keycloak を使用する WebAuthn のようなパスワードレスな認証方式の対応は次の記事を参照してください。
Active Directory と AD FS を使用する例は検索すると数多く見つかるでしょう。次の記事も参照してください。
OpenID Connect のトークンを処理するアプリケーション構築の記事は次のとおりです。
SAML のコールバックを Spring Boot などの Java フレームワークでハンドルできます。かなり古いリポジトリですが GitHub リポジトリ を参照してください。