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 をセットアップする方法を説明します。

環境

Keycloakのインストール

Keycloak は Helm チャートを使ってインストールします (ArtifactHUB)。

codecentric/helm-chartsvalues.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 に戻ってクライアントを追加します。

レルム LocalConfigure - Clients を選択し Create ボタンをクリックします。

Client IDurn:amazon:cognito:sp:<プールID> の形式で入力します。

Client Protocolsaml を選択し、Save ボタンをクリックします。

Settings をデフォルトから変更する項目は次のとおりです。

  • Sign DocumentsOFF
  • Sign AssertionsON
  • Client Signature RequiredOFF
  • Force Name ID FormatON
  • Name ID Formatpersistent に設定
  • Valid Redirect URIshttps://<Cognito user pools に設定したドメイン名>/saml2/idpresponse を設定

Save ボタンをクリックします。

Mappers タブを選択し、Create ボタンをクリックします。

次のように入力し、Save ボタンをクリックします。

  • Nameemail を設定
  • Mapper TypeUser Attribute
  • User Attributeemail を設定
  • SAML Attribute Nameemail を設定

ユーザの追加

左側の Manage - Users を選択し、Add user ボタンをクリックします。

UsernameEmail 等を入力し Save ボタンをクリックします。

追加したユーザの Credentials タブを選択し、パスワードを設定して Set Password ボタンをクリックします。

Cognito User poolsのアプリクライアントの設定

AWS 管理コンソールの Cognito サービスの左側にある アプリの統合 - アプリクライアントの設定 をクリックします。

有効な ID プロバイダkeycloak を選択します。

コールバック URL は OIDC のフローのコールバック URL を設定しますが、テストのために http://localhost:8080/callback と入力します。

許可されている OAuth フロー は、これもテストのために Implicit grant をチェックします。

許可されている OAuth スコープ は、emailopenid をチェックし、変更の保存 ボタンをクリックします。

ホストされた UI を起動 リンクをクリックし、keycloak ボタンをクリックします。

Keycloak の認証画面が表示されるので、Username or emailPassword を入力して Sign In ボタンをクリックします。

サインインに成功しても、コールバック URL を処理するアプリケーションがありませんが、ブラウザの URL にはコールバック URL とフラグメント (#) の後に access_tokenid_token 等が表示されます。id_token の値を jwt.io にペーストして JWT を確認できます。

なお、コールバック URL を envoyproxy で処理することも可能です。「Envoy OAuth2 Filter を使ったログイン」の記事で説明しています。また、この記事で紹介している GitHub リポジトリ には Kubernetes 環境にデプロイするための Helm チャートも用意しています。

まとめ

SAMLOpenID Connect のような業界標準を採用することで、認証基盤に採用するプロダクトの幅が広がります。この記事では Keycloak を SAML IdP として使用する例を紹介しました。

Keycloak を SAML IdP として使用することで、WebAuthn のような新しい認証方式への対応も可能になります。

Keycloak を使用する WebAuthn のようなパスワードレスな認証方式の対応は次の記事を参照してください。

Active Directory と AD FS を使用する例は検索すると数多く見つかるでしょう。次の記事も参照してください。

OpenID Connect のトークンを処理するアプリケーション構築の記事は次のとおりです。

SAML のコールバックを Spring Boot などの Java フレームワークでハンドルできます。かなり古いリポジトリですが GitHub リポジトリ を参照してください。

参考