OIDC
Keycloak などの OpenID Connect プロバイダーによるシングルサインオン。ロールはグループクレームから決まります
仕組み
OIDC プロバイダーが有効な場合、ログインページの サインイン の下に OpenID のボタンが表示されます。ログインは次のように進みます。
- ボタンを押すとブラウザーは
/api/v2/auth/oidcに送られ、そこからプロバイダーにリダイレクトされます(PKCE を使った 認可コードフロー)。 - ユーザーがプロバイダーでサインインすると、 リダイレクト URL に戻されます。
- サーバーはコードをトークンと交換し、ID トークンのクレームを読み込みます。
- ユーザー名は
preferred_usernameクレームで、groupsクレームの値のうち グループフィルター を 通過したものがそれぞれoidc/<value>グループになります。
AnsibleForms はスコープ openid profile email を要求します。スコープは設定できません。AnsibleForms からサインアウトすると、 プロバイダーが公開している場合は、ブラウザーがプロバイダーのセッション終了エンドポイントにも送られます。
OIDC は Keycloak でテストされています。ほかのプロバイダーも、以下の要件を満たせば動作します。
プロバイダーの要件
プロバイダーは OpenID Connect ディスカバリーと、AnsibleForms 用のコンフィデンシャルクライアントを提供する必要があります。
- ディスカバリー :AnsibleForms は
<issuer>/.well-known/openid-configurationを読み込むので、発行者には AnsibleForms サーバーから HTTPS で到達できる必要があります。 - 認可コードフロー、クライアント ID、クライアントシークレットを持つ コンフィデンシャルクライアント 。
- リダイレクト URI
https://af.example.com/api/v2/auth/oidc/callback。つまり、ユーザーが AnsibleForms にアクセスするアドレスの 後に/api/v2/auth/oidc/callbackを付けたものです。BASE_URLが/formsの場合はhttps://af.example.com/forms/api/v2/auth/oidc/callbackになります。 - グループ名のリストを保持する ID トークンの
groupsクレーム 。これがないと、ユーザーには OIDC グループが付与されません。 - ユーザー名になる
preferred_usernameクレーム 。
Keycloak の例
この例では、 https://keycloak.example.com 上のレルム example を使います。発行者は https://keycloak.example.com/realms/example になります。そのレルムで次の操作を行います。
- Clients で、クライアント ID
ansibleformsの OpenID Connect クライアントを作成します。 Client authentication をオンにし、 Standard flow はそのままにして、 Valid redirect URIs をhttps://af.example.com/api/v2/auth/oidc/callbackに設定します。 - クライアントの Credentials タブで Client secret をコピーします。
- Client scopes タブで
ansibleforms-dedicatedを開き、 By configuration > Group Membership のマッパーを追加します。 Token Claim Name はgroups、 Full group path はオフ、 Add to ID token はオンにします。
Full group path がオンの場合、クレームには /af-admins のようなパスが入るので、ロールでは oidc//af-admins と指定する必要があります。
プロバイダーの追加
アクセス > SSO でプロバイダーを追加します。ウィザードが 4 つのステップでフィールドを尋ね、 種類 のステップでは Open ID を選びます。
| ステップ | フィールド | 意味 |
|---|---|---|
| 詳細 | 名前、説明 | プロバイダーの一意の名前と、任意の説明 |
| 種類 | プロバイダー | Open ID 。作成時に設定し、変更できません |
| 認証情報 | 認証情報 | 接続 > 認証情報 の Open ID 認証情報。下記を参照 |
| グループ | グループフィルター | 正規表現。 groups クレームの値のうち一致するものだけが残ります。空の場合はすべてのグループが残ります |
認証情報はクライアントを保持するので、追加、変更できるのは管理者だけです。
| フィールド | 意味 |
|---|---|
| 発行者 (Issuer) | 必須。発行者の URL。例: https://keycloak.example.com/realms/example |
| クライアント ID | プロバイダーでのクライアント ID。例: ansibleforms |
| クライアントシークレット | クライアントシークレット。暗号化して保存するか、 シークレットストア から読み込みます |
| リダイレクト URI | 登録したとおりの値。例: https://af.example.com/api/v2/auth/oidc/callback 。空の場合はアプリの URL とコールバックのパス |
7.2.0 までは、発行者、クライアント ID、シークレット、リダイレクト URL はプロバイダーのフィールドでした。7.3.0 へのアップグレードでこれらは <provider>-sso という名前の認証情報に移されます。 認証情報内のアドレス を参照してください。 新しいプロバイダーには必ず認証情報を選んでください。サーバーは 7.3.0 より前の、独自のクライアント ID とシークレットを持つプロバイダーも 引き続き受け付け、認証情報が選ばれるまではそれらでサインインします。
同時に有効にできる OIDC プロバイダーは一つだけで、OpenID のボタンはそのプロバイダーでサインインします。別のプロバイダーの行メニューの 有効にする 、 またはその 有効 スイッチを使うと、同じ種類のほかのプロバイダーはオフになります。リストの 有効 列で、どれが使われているかがわかります。 プロバイダーはログインページをスキップすることもできます。 シングルサインオンの切り替え を参照してください。
プロバイダーを保存するとすぐに反映されます。発行者に到達できない場合、サーバーは Failed to initialize OIDC strategy をログに記録し、プロバイダーを再度保存するかサーバーを再起動するまで OIDC ログインは失敗します。
ロールへの対応付け
config.yaml では、OIDC のグループは oidc/<group> 、ユーザーは oidc/<preferred_username> と書きます。
roles:
- name: admin
groups:
- local/admins
- oidc/af-admins
- name: operator
groups:
- oidc/af-operators
users:
- oidc/jdoe
値は大文字と小文字も含めて完全一致で照合されます。ロールオプションについては ロール を参照してください。
制限事項
OIDC のユーザーはプロバイダーでサインインするため、ローカルアカウントや LDAP アカウントとはいくつかの点で動作が異なります。
- AnsibleForms にはパスワードがないので、そこでパスワードを変更することはできません。7.2.0 からは API トークン がセッションから作成されます。
groupsクレームは短く保ってください。プロバイダー側で専用のクライアントスコープやグループ構成を使うなどして AnsibleForms に関係のあるグループだけを送るか、 グループフィルター で絞り込みます。7.1.0 からは AnsibleForms のサインイン トークンにグループが含まれなくなりました。それ以前は、100 以上のグループに所属するユーザーはフォームを表示できないことがありました。 シングルサインオン後にフォームとジョブが空になる を参照してください。