このトピックでは、Container Service for Kubernetes (ACK) クラスターに Keycloak サービスをデプロイし、Keycloak を Kubernetes OpenID Connect (OIDC) 認証サーバーとして使用して ID を検証する方法について説明します。
前提条件
ACK マネージドクラスターが作成されていること、およびクラスターのバージョンが 1.22 以降であること。
(オプション) jwt-cli がインストールされていること。これは JSON Web トークン (JWT) の解析に使用されます。
環境のセットアップ
Keycloak サービス用のドメイン名を準備します。
証明書
本番環境で Keycloak のセキュリティを確保するには、次のコマンドを実行してルート証明書とサーバー証明書を生成します。サーバー証明書のサブジェクト代替名 (SAN) には、Keycloak サービス用に準備したドメイン名が含まれている必要があります。
openssl genrsa -out rootCA.key 2048 # CA キーを生成します。 openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 3650 -out rootCA.crt # CA 証明書を生成します。 openssl genrsa -out server.key 2048 # サーバーキーを生成します。 openssl req -new -key server.key -out server.csr openssl x509 -req -in server.csr -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -out server.crt -days 3650 -sha256 -extensions v3_req -extfile <(echo '[v3_req]'; echo 'subjectAltName = DNS:${Service domain name}')データベース
デフォルトでは、Keycloak のデータはローカルファイルに永続化されます。本番環境では、データをデータベースに永続化する必要があります。次の表に、Keycloak でサポートされているデータベースエンジンとバージョンを示します。
データベース
オプション値
バージョン
MariaDB Server
mariadb
10.11
Microsoft SQL Server
mssql
2022
MySQL
mysql
8.0
Oracle Database
oracle
19.3
PostgreSQL
postgres
15
この例では、ApsaraDB RDS for MySQL を使用して Keycloak データを永続化します。Keycloak という名前のデータベースが作成されます。データベースインスタンスの作成と使用方法の詳細については、「ApsaraDB RDS for MySQL インスタンスの作成と設定」をご参照ください。
ステップ 1: ACK マネージドクラスターに Keycloak をデプロイする
ACK マネージドクラスターに Keycloak サービスをデプロイします。
keycloak.yaml という名前のファイルを作成し、次の内容をファイルに追加します。
apiVersion: v1 kind: Service metadata: labels: app: keycloak name: keycloak namespace: default spec: ports: - name: http port: 80 protocol: TCP targetPort: 8080 selector: app: keycloak type: ClusterIP次のコマンドを実行して、ACK マネージドクラスターに Keycloak サービスをデプロイし、サービスを内部アクセスに公開します。
kubectl apply -f keycloak.yaml
関連する構成をデプロイします。
keycloak-secret.yaml という名前のファイルを作成し、次の内容をファイルに追加します。
次のデータベース構成は、Keycloak という名前のデータベースに接続するために使用されます。管理者構成は、初めて Keycloak にログインするために使用されます。
apiVersion: v1 data: db_passwd: ${Base64 でエンコードされたデータベースパスワード} db_username: ${Base64 でエンコードされたデータベースユーザー名} db_url: ${Base64 でエンコードされたデータベース URL/ホスト} keycloak_admin: ${Base64 でエンコードされた Keycloak 管理者ユーザー名} keycloak_admin_password: ${Base64 でエンコードされた Keycloak 管理者パスワード} kind: Secret metadata: name: keycloak-secret namespace: default type: Opaque次のコマンドを実行して構成をデプロイします。
kubectl apply -f keycloak-secret.yamlkeylock-pki.yaml という名前のファイルを作成し、次の内容をファイルに追加します。
apiVersion: v1 data: tls.crt: ${Base64 でエンコードされたサーバー証明書} tls.key: ${Base64 でエンコードされたサーバー秘密鍵} kind: Secret metadata: name: keycloak-pki namespace: default type: IngressTLS次のコマンドを実行してサーバー証明書をデプロイします。
kubectl apply -f keycloak-pki.yaml
Ingress を作成します。
keycloak-ingress.yaml という名前のファイルを作成し、次の内容をファイルに追加します。
次のコードブロックのサービスドメイン名を、Keycloak サービス用に準備したドメイン名に置き換えます。
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: labels: ingress-controller: nginx name: keycloak namespace: default spec: ingressClassName: nginx rules: - host: ${サービスドメイン名} http: paths: - backend: service: name: keycloak port: number: 80 path: / pathType: ImplementationSpecific tls: - hosts: - ${サービスドメイン名} secretName: keycloak-pki次のコマンドを実行して Ingress をデプロイします。
kubectl apply -f keycloak-ingress.yamlIngress がデプロイされると、パブリックにアクセス可能な IP アドレスが生成されます。サービスドメイン名はこの IP アドレスに解決されます。
Keycloak Deployment をデプロイします。
keycloak-deploy.yaml という名前のファイルを作成し、次の内容をファイルに追加します。
次のコマンドを実行して Keycloak Deployment をデプロイします。
kubectl apply -f keycloak-deploy.yaml
ブラウザで
https://${Keycloak Service domain name}を入力して Keycloak サービスにアクセスします。次のページが表示された場合、サービスは正常にデプロイされています。
ステップ 2: Keycloak をデプロイする
ユーザー設定
Keycloak サービスページで、[Administration Console] をクリックし、ユーザー名とパスワードを入力して管理コンソールにログインします。
ユーザー名とパスワードは、ステップ 2.a の keycloak-secret.yaml ファイルで設定した管理者ログイン情報です。
ページの左上隅で、ドロップダウンリストから master を選択し、[Create Realm] をクリックします。

[Create Realm] ページで、[Realm Name] を [myrealm] に設定し、[Create] をクリックして myrealm という名前の新しいレルムを作成します。Keycloak では、レルムはテナントを表します。
ページの左上隅にあるドロップダウンリストで myrealm を選択します。左側のナビゲーションウィンドウで [Users] を選択し、[Add User] をクリックします。

[Create User] ページで、[Username] を [myuser] に設定し、[Create] をクリックして myuser という名前のユーザーを作成します。他のパラメーターはオプションです。
[myuser] ページで [Attributes] をクリックし、[Key] を [name] に、[Value] を [ack] に設定してから、[Save] をクリックします。この属性は ID トークンに挿入できます。

[myuser] ページで [Credentials] をクリックし、[Set Password] をクリックします。
[Temporary] を On に設定し、[Save] をクリックします。初回ログイン後にパスワードを変更する必要があります。

Keycloak のログイン URL は
https://${Keycloak Service domain name}/realms/${your realm}/accountです。
クライアント設定
クライアントは、Keycloak にユーザー ID の検証を要求するエンティティです。ユーザー設定を構成した後、クライアント設定を構成する必要があります。
[myrealm] ページの左側のナビゲーションウィンドウで [Clients] を選択し、[Clients] ページで [Create Client] をクリックします。
[Create Client] ページで、[General Settings]、[Capability Config]、[Login Settings] を設定します。
[General Settings] ページで、[Client ID] と [Name] の両方を ack に設定し、[Next] をクリックします。

[Capability Config] ページで、[Client Authentication] を on に設定してクライアントアクセスタイプを confidential に設定し、他のパラメーターはデフォルト設定のままにして、[Next] をクリックします。

[Login Settings] ページで、[Valid Redirect URIs] を [http://*] に設定します。この設定は、ログイン成功後に使用する有効なリダイレクト URI を指定します。この例では、http://* はすべての HTTP リダイレクト URI に一致します。次に、[Save] をクリックします。

クライアントスコープ設定
クライアントスコープは、レルム内の複数のクライアント間で共通のプロトコルとロールのマッピングを共有するために使用できます。
[myrealm] ページの左側のナビゲーションウィンドウで [Client Scopes] を選択し、[Client Scopes] ページで [Create Client] [scope] をクリックします。
[Create Client] [scope] ページで、[Name] を [ack-kubernetes] に設定し、他のパラメーターはデフォルト設定のままにして、[Save] をクリックします。

[ack-kubernetes] ページで [Mappers] をクリックし、[Configure A New Mapper] をクリックします。
[Configure A New Mapper] ページで、User Attribute を作成します。この属性は、ステップ 6 で追加した [name] フィールドと [ack] フィールドを ID トークンに挿入するために使用されます。

[Add Mapper] ページで、[Name] を [name] に、[User Attribute] を [name] (前のステップで設定した name: ack 属性) に、[Token Claim Name] を [name] (ID トークン内の属性の名前) に設定します。他のパラメーターはデフォルト設定のままにします。次に、[Save] をクリックします。

左側のナビゲーションウィンドウで [Clients] をクリックして Clients ページに戻り、ack という名前のクライアントを選択します。
ack クライアントの [client] ページで [Client Scopes] をクリックし、[Add Client Scope] をクリックします。表示されるダイアログボックスで、追加するクライアントスコープを選択し、[Add] をクリックします。

ステップ 3: Kube API Server パラメーターを設定する
Kubernetes は OIDC プロトコルをサポートしており、外部 ID プロバイダー (IdP) と連携して ID を検証できます。ID 検証を有効にするには、ACK マネージドクラスターの Kube API Server コンポーネントに関連する OIDC パラメーターを設定する必要があります。
ACK コンソールにログインします。左側のナビゲーションウィンドウで、[クラスター] をクリックします。
クラスター ページで、管理するクラスターを見つけてその名前をクリックします。左側のナビゲーションウィンドウで、[アドオン] をクリックします。
[コンポーネント管理] ページの [コアコンポーネント] タブで Kube API Server コンポーネントを見つけ、カードの右下隅にある [設定] をクリックします。
[Kube API Server パラメーター] ページで、次のパラメーターを設定し、他のパラメーターはデフォルト設定のままにして、[確認] をクリックします。

パラメーター
説明
oidcIssuerURLOIDC
プロバイダー URL
https://${Keycloak Service domain name}/realms/myrealm/.well-known/openid-configurationにアクセスし、issuer に対応する値を oidcIssuerURL に入力します。この例では、https://${Keycloak Service domain name}/realms/myrealmです。重要クラスター内の API Server は、oidcIssuerURL 設定項目で指定されたアドレスにアクセスします。サービスドメイン名がパブリックドメイン名の場合は、クラスターでインターネットアクセスが有効になっていることを確認してください。詳細については、「クラスターのインターネットアクセスを有効にする」をご参照ください。
クラスターでインターネットアクセスを有効にしても API Server が oidcIssuerURL 設定項目で指定されたアドレスにアクセスできない場合は、
kubectl get endpointsを使用して Kubernetes バックエンドの IP アドレスの数を確認できます。IP アドレスが複数ある場合は、Worker ノードにログインして oidcIssuerURL へのアクセスを試み、インターネット設定、セキュリティグループルール、その他の設定を確認してください。
IP アドレスが 1 つしかない場合は、チケットを送信してサポートを依頼してください。
OidcClientIdOIDC トークン
クライアント ID
クライアント設定セクションの ステップ 2 で指定したクライアント ID を入力します。この例では、ack と入力します。
oidcUsernameClaim
ユーザー名 JWT Claim
クライアントスコープ設定セクションの ステップ 5 で指定した Token Claim Name パラメーターの値を入力します。この例では、name と入力します。これはクラスター内のユーザーの ID です。
oidcUsernamePrefix
ユーザー名プレフィックス
ハイフン (-) を入力します。これは、プレフィックスが指定されていないことを意味します。
oidcCAContent
OIDC プロバイダーの URL にリクエストを送信するために必要な Base64 でエンコードされた CA 証明書
環境のセットアップセクションの 証明書 で生成された Base64 でエンコードされたルート証明書を入力します。
ステップ 4: ID を検証する
次のコマンドを実行して ID トークンを要求します。次に、リクエストボディから ID トークンを取得します。
curl -ks -X POST https://${Keycloak Service domain name}/realms/myrealm/protocol/openid-connect/token \ -d grant_type=password -d client_id=ack \ -d username=myuser -d password=${Password used to log on to Keycloak} -d scope=openid \ -d client_secret=${クライアントクレデンシャル}次の変数を置き換える必要があります。
置き換える変数
説明
Keycloak サービスドメイン名
Keycloak サービス用に準備したドメイン名に置き換えます。
password
ステップ 1 の ステップ 2.a で指定したパスワードに置き換えます。
client_secret
Keycloak コンソールにログインします。[Clients] ページで ack という名前のクライアントを選択し、[Credentials] をクリックして、[Client Secret] パラメーターの値をコピーします。

オプション: jwt-cli を使用してトークンを解析すると、出力には
issが API サーバー用に設定された oidcIssuerURL であり、nameフィールドが前のクライアントスコープセクションの ステップ 5 で設定された User Attribute であることが示されます。次の YAML コンテンツを使用して ClusterRole を作成します。
kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: name: keycloak-example rules: - apiGroups: [""] resources: ["namespaces"] verbs: ["get","list"] # ロールに名前空間情報の読み取りを許可します。 --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: ack-crb roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: keycloak-example subjects: - kind: User name: ack apiGroup: rbac.authorization.k8s.io次のコマンドを実行して API サーバーにリクエストを送信します。
curl -k https://${API server address}/api/v1/namespaces -H "Authorization: Bearer ${id トークン}"API サーバーアドレス: クラスターがデプロイされているネットワークに基づいて API サーバーアドレスを入力します。コンテナサービス管理コンソールの[クラスター情報] ページの[基本情報] タブに移動し、ネットワークセクションで[API サーバーパブリックエンドポイント]と[API サーバー内部エンドポイント]を確認します。id token: ステップ 1 で取得した ID トークンを指定します。
リクエストが送信されると、次の名前空間情報が返されます。

現在のユーザーがアクセスを許可されていないリソースを要求するために別のリクエストを送信します。出力は、Kubernetes が ack ユーザーを識別し、ユーザーの権限を検証することを示しています。
