Keycloak で Argo CD の SSO を構築する方法
クラウドエース 北野です。
Argo CD の SSO を Keycloak のアカウントで実現する方法を紹介します。
概要
Keycloak と Argo CD を次の様に設定して、Keycloak を外部 ID プロバイダとして構築し、Keycloak のアカウントで Argo CD でログインします。
- Keycloak での設定
- OpenID Connect のクライアント作成
- クライアントスコープ group の作成
- Argo CD で OIDC プロバイダの設定
Keycloak での認証は次の2つの方法があります。
- クライアント認証
- PKCE
クライアント認証で SSO するための Keycloak の設定は次の通りです。
resource "keycloak_openid_client" "main" {
client_id = "argocd"
realm_id = keycloak_realm.main.id
name = "ArgoCD"
access_type = "CONFIDENTIAL"
service_accounts_enabled = false
valid_redirect_uris = [
"https://<ARGOCD HOSTNAME>/auth/callback",
]
valid_post_logout_redirect_uris = [
"https://<ARGOCD HOSTNAME>/applications"
]
web_origins = [
"https://<ARGOCD HOSTNAME>"
]
root_url = "https://<ARGOCD HOSTNAME>"
admin_url = "https://<ARGOCD HOSTNAME>"
base_url = "/applications"
standard_flow_enabled = true
implicit_flow_enabled = false
direct_access_grants_enabled = true
client_session_max_lifespan = 604800
access_token_lifespan = 180
}
resource "keycloak_openid_client_optional_scopes" "main" {
client_id = keycloak_openid_client.main.id
realm_id = keycloak_realm.main.id
optional_scopes = [
keycloak_openid_client_scope.main["groups"].name
]
}
resource "keycloak_openid_client_scope" "main" {
name = "groups"
realm_id = keycloak_realm.main.id
include_in_token_scope = true
}
resource "keycloak_openid_group_membership_protocol_mapper" "main" {
name = "groups"
realm_id = keycloak_realm.main.id
client_scope_id = keycloak_openid_client_scope.main.id
claim_name = "groups"
full_path = false
add_to_id_token = true
add_to_access_token = true
add_to_userinfo = true
}
Argo CD の設定は次の通りです。
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-cm
data:
url: https://<ARGOCD HOSTNAME>
oidc.config: |
name: Keycloak
issuer: https://<KEYCLOAK HOSTNAME>/realms/<REALM>
clientID: argocd
clientSecret: <CLIENT SECRET>
requestedScopes: ["openid", "profile", "email", "groups"]
次に PKCE による SSO の Keycloak の設定は次の通りです。
resource "keycloak_openid_client" "main" {
client_id = "argocd"
realm_id = keycloak_realm.main.id
name = "ArgoCD"
access_type = "PUBLIC"
service_accounts_enabled = false
valid_redirect_uris = [
"http://localhost:8085/auth/callback",
"https://<ARGOCD HOSTNAME>/auth/callback",
"https://<ARGOCD HOSTNAME>/pkce/verify"
]
valid_post_logout_redirect_uris = [
"https://<ARGOCD HOSTNAME>/applications"
]
web_origins = [
"https://<ARGOCD HOSTNAME>"
]
root_url = "https://<ARGOCD HOSTNAME>"
admin_url = "https://<ARGOCD HOSTNAME>"
base_url = "/applications"
standard_flow_enabled = true
implicit_flow_enabled = false
direct_access_grants_enabled = true
client_session_max_lifespan = 604800
access_token_lifespan = 180
pkce_code_challenge_method = "S256"
}
resource "keycloak_openid_client_optional_scopes" "main" {
client_id = keycloak_openid_client.main.id
realm_id = keycloak_realm.main.id
optional_scopes = [
keycloak_openid_client_scope.main.name
]
}
resource "keycloak_openid_client_scope" "main" {
name = "groups"
realm_id = keycloak_realm.main.id
include_in_token_scope = true
}
resource "keycloak_openid_group_membership_protocol_mapper" "main" {
name = "groups"
realm_id = keycloak_realm.main.id
client_scope_id = keycloak_openid_client_scope.main.id
claim_name = "groups"
full_path = false
add_to_id_token = true
add_to_access_token = true
add_to_userinfo = true
}
Argo CD の設定は次の通りです。
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-cm
labels:
app.kubernetes.io/name: argocd-cm
app.kubernetes.io/part-of: argocd
data:
admin.enabled: "false"
url: https://<ARGOCD HOSTNAME>
oidc.config: |
name: Keycloak
issuer: https://<KEYCLOAK HOSTNAME>/realms/<REALM>
clientID: argocd
enablePKCEAuthentication: true
requestedScopes: ["openid", "profile", "groups" ,"email"]
この記事では、上記の設定を以下の様な Google Kubernetes Engine 上に構築した Argo CD と Keycloak を使って説明します。
はじめに
以前、Google アカウントで Argo CD の SSO を実現する方法を紹介しました。しかし、企業のセキュリティ要件などにより、プライベート環境に構築した認証基盤で SSO させる必要があるかと思います。
そこで GKE 上に構築した Keycloak で Argo CD の SSO を実現する方法を紹介します。
Argo CD での SSO の実現方法
Argo CD では、次の2種類の SSO のプロバイダがあります。
- Argo CD にインストールされている Dex OIDC プロバイダ
- 既存の OIDC プロバイダ (Okta, OneLogin, Auth0, Microsoft, Keycloak)
SSO の設定は、Argo CD の Configmap argocd-cm
に設定します。
Dex と既存の OIDC プロバイダのそれぞれの設定は以下のようにします。
- Dex の SSO 設定
data:
dex.config: |
connectors:
- type: <TYPE>
id: <ID>
name: <NAME>
config: <CONECTION INFO>
- 既存のプロバイダの SSO 設定
data:
oidc.config: |
type: <TYPE>
id: <ID>
name: <NAME>
issuer: <IDP URL>
前回、Google アカウントで SSO を実現する方法の記事で Dex について簡単に説明しているので、Dex について気になる方は、そちらをご参照ください。
この記事では、既存プロバイダに分類される Keycloak を使って、SSO を実現する方法を紹介します。
Keycloak での SSO
Keycloak での SSO の実現は、次の2種類の認証方法があります。
- クライアント認証
- Proof Key for Code Exchange (以降 PKCE と呼びます)
この記事では、クライアント認証と PKCE によるそれぞれの SSO の実現方法を両方紹介します。
以下で説明しているコードの <>
で囲まれている箇所は、構築する環境に合わせて読みかえてください。
事前準備
Google Cloud 上に以下のようなシステムを構築します。
Argo CD と Keycloak を Google Cloud の Google Kubernetes Engine (以降 GKE と呼びます)上に構築します。
Keycloak のデータベースは Cloud SQL を使い、Argo CD のシークレット情報を Secret Manager に登録し、External Secret を使って参照します。Argo CD と Keycloak の インターネットへの公開には、Gateway を使い公開します。
それぞれの構築方法の詳細は以下の記事をご確認ください。
Keycloak の設定
今回、platform という realm に作り、以下の Keycloak のアカウントで SSO します。
このとき、権限はアカウントが所属する以下のグループに権限を付与します。
アカウントの設定 | 値 |
---|---|
ユーザー名 | sample |
sample@example.com | |
first name | sample |
last name | test |
所属グループ | administrators |
platform の realm を次の様に Terraform で作成します。
resource "keycloak_realm" "main" {
realm = "platform"
display_name = "platform"
registration_allowed = false
registration_email_as_username = true
login_with_email_allowed = true
verify_email = false
reset_password_allowed = true
sso_session_idle_timeout = "336h"
sso_session_max_lifespan = "720h"
}
ユーザーとグループの作成および、グループへのユーザーの追加を次の様に Terraform で作成します。
resource "keycloak_group" "main" {
name = "administrators"
realm_id = keycloak_realm.main.id
}
resource "keycloak_user" "main" {
username = "sample"
realm_id = keycloak_realm.main.id
enabled = true
email = "sample@example.com"
first_name = "sample"
last_name = "test"
initial_password {
value = "sample"
temporary = true
}
}
resource "keycloak_group_memberships" "main" {
group_id = keycloak_group.main.id
realm_id = keycloak_realm.main.id
members = [
keycloak_user.main.username
]
}
Argo CD 側には、作成したグループ (administrators) に admin 権限を設定します。
設定は次のように ConfigMap argocd-rbac-cm
に権限を定義します。
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-rbac-cm
data:
policy.csv: |
g, administrators, role:admin
Keycloak アカウントでの SSO
Keycloak クライアント認証と PKCE によって、Argo CD に SSO する方法を説明します。
今回、Keycloak のグループに権限を付与します。そのため、まず、グループに権限を付与するために必要な Keycloak のクライアントスコープの設定をします。
続いてクライアント認証と PKCE で Keycloak と Argo CD の設定を紹介して、Keycloak のアカウントログインできるかを確認します。
Keycloak のクライアントスコープの設定
Keycloak のグループで認証させるためにクライアントスコープ groups
を以下の設定で作成します。
設定項目 | 設定内容 |
---|---|
name | groups |
include in token scope | true |
またクライアントスコープ groups
の Mappers を次のように設定します。
設定項目 | 設定内容 |
---|---|
Mapper Type | Group Membership |
Name | groups |
Token Claim Name | groups |
Add to ID token | true |
Add to access token | true |
Add to userinfo | true |
Full group path | false |
これらを次の様に Terraform で設定します。
resource "keycloak_openid_client_scope" "main" {
name = "groups"
realm_id = keycloak_realm.main.id
include_in_token_scope = true
}
resource "keycloak_openid_group_membership_protocol_mapper" "main" {
name = "groups"
realm_id = keycloak_realm.main.id
client_scope_id = keycloak_openid_client_scope.main.id
claim_name = "groups"
full_path = false
add_to_id_token = true
add_to_access_token = true
add_to_userinfo = true
}
Keycloak のクライアント認証による SSO
Keycloak のクライアント認証による Argo CD の SSO では、以下を実施します。
- Keycloak: OpenID Connect のクライアントの作成
- Google Cloud: Keycloak のクライアントのシークレットを保存する Secret Manager の作成
- Kubernetes: Keycloak のクライアントシークレットの情報を Secret Manager から取得する External Secret の作成
- Argo CD: oidc の設定
まず、Keycloak 側で Open ID Connect のクライアントを以下の設定で作成します。
設定項目 | 値 |
---|---|
Client type | OpenID Connect |
Client ID | argocd |
Client authentication | true |
Authorization | false |
Standard flow | true |
Direct access grants | true |
Implicit flow | false |
Service accounts roles | false |
OAuth 2.0 Device Authorization Grant | false |
OIDC CIBA Grant | false |
Root URL | http://<ARGOCD HOSTNAME> |
Home URL | /Applications |
Valid redirect URIs | https://<ARGOCD HOSTNAME>/auth/callback |
Valid post logout redirect URIs | https://<ARGOCD HOSTNAME>/applications |
Web origins | http://<ARGOCD HOSTNAME> |
上記の Keycloak のクライアントを次の様に Terraform で作成します。
resource "keycloak_openid_client" "main" {
client_id = "argocd"
realm_id = keycloak_realm.main.id
name = "ArgoCD"
access_type = "CONFIDENTIAL"
service_accounts_enabled = false
valid_redirect_uris = [
"https://<ARGOCD HOSTNAME>/auth/callback",
]
valid_post_logout_redirect_uris = [
"https://<ARGOCD HOSTNAME>/applications"
]
web_origins = [
"https://<ARGOCD HOSTNAME>"
]
root_url = "https://<ARGOCD HOSTNAME>"
admin_url = "https://<ARGOCD HOSTNAME>"
base_url = "/applications"
standard_flow_enabled = true
implicit_flow_enabled = false
direct_access_grants_enabled = true
client_session_max_lifespan = 604800
access_token_lifespan = 180
}
resource "keycloak_openid_client_optional_scopes" "main" {
client_id = keycloak_openid_client.main.id
realm_id = keycloak_realm.main.id
optional_scopes = [
keycloak_openid_client_scope.main.name
]
}
作成したクライアント argocd
のクライアントシークレットを Google Cloud の Secret Manager に登録し、Kubernetes の External Secret を使って、Secret に連携します。
それぞれ、次のようにリソースを作成します。
リソースの種類 | リソース名 |
---|---|
Secret Manager | argocd-keycloak-oidc-client-secret |
Secret | argocd-oicd-client.keycloak-oidc-client-secret |
次の Terraform コードで Google Cloud 上に Secret Manager を作成して、Keycloak のクライアントシークレットを登録します。
resource "google_secret_manager_secret" "main" {
secret_id = "argocd-keycloak-oidc-client-secret"
project = var.project
replication {
user_managed {
replicas {
location = "asia-northeast1"
}
}
}
}
resource "google_secret_manager_secret_version" "main" {
secret = google_secret_manager_secret.main.id
secret_data = keycloak_openid_client.main.client_secret
}
Secret Manager の情報を次のマニフェストで作成される External Secret で Secret に連携します。
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: es-argocd-oicd-client
namespace: argocd
labels:
app.kubernetes.io/part-of: argocd
spec:
refreshInterval: 1h
secretStoreRef:
name: argocd-css
kind: ClusterSecretStore
target:
name: argocd-oicd-client
creationPolicy: Owner
data:
- secretKey: keycloak-oidc-client-secret
remoteRef:
key: argocd-keycloak-oidc-client-secret
version: latest
最後に argocd-cm
の ConfigMap に Keycloak の SSO を次の様に設定します。
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-cm
data:
url: https://<ARGOCD HOSTNAME>
oidc.config: |
name: Keycloak
issuer: https://<KEYCLOAK HOSTNAME>/realms/platform
clientID: argocd
clientSecret: $argocd-oicd-client:keycloak-oidc-client-secret
requestedScopes: ["openid", "profile", "email", "groups"]
Argo CD にアクセスすると、LOG IN VIA KEYCLOAK
のボタンが表示されます。
ボタンをクリックすると、Keycloak のログイン画面にリダイレクトされます。
作成したアカウントでログインすると、パスワードのアップデートを促されるので、アップデートします。
パスワードをアップデートすると、ログインに成功し Application の一覧画面が表示されます。
最後にログインしたユーザーの情報を確認すると、次のようになっています。
ユーザーは Keycloak で作成した sample@example.com
ユーザーでログインしており、administrators
のグループで権限を付与されていることが分かります。
Keycloak の PKCE よる SSO
PKCE は OAuth 2.0 の認可コードフローのセキュリティを強固にします。クライアントシークレットを安全に保存できない場合などに利用されています。PKCE は RFC7636 に定義されているので詳細はそちらをご確認ください。
Argo CD も Keycloak の PKCE を使った SSO に対応しているので、その方法を紹介します。Keycloak の PKCE による Argo CD の SSO は Keycloak と Argo CD にそれぞれ次の様な設定をします。
- Keycloak: OpenID Connect のクライアントの作成
- Argo CD: oidc の設定
Keycloak の OpenID Connect クライアントを以下の設定で作成します。
設定項目 | 値 |
---|---|
Client type | OpenID Connect |
Client ID | argocd |
Client authentication | false |
Authorization | false |
Standard flow | true |
Direct access grants | true |
Implicit flow | false |
Service accounts roles | false |
OAuth 2.0 Device Authorization Grant | false |
OIDC CIBA Grant | false |
Proof Key for Code Exchange Code Challenge Method | S256 |
Root URL | http://<ARGOCD HOSTNAME> |
Home URL | /applications |
Valid redirect URIs | https://<ARGOCD HOSTNAME>/auth/callback, http://localhost:8085/auth/callback, https://<ARGOCD HOSTNAME>/pkce/verify |
Valid post logout redirect URIs | https://<ARGOCD HOSTNAME>/applications |
Web origins | http://<ARGOCD HOSTNAME> |
上記の内容を次の様に Terraform で作成します。
resource "keycloak_openid_client" "main" {
client_id = "argocd"
realm_id = keycloak_realm.main.id
name = "ArgoCD"
access_type = "PUBLIC"
service_accounts_enabled = false
valid_redirect_uris = [
"http://localhost:8085/auth/callback",
"https://<ARGOCD HOSTNAME>/auth/callback",
"https://<ARGOCD HOSTNAME>/pkce/verify"
]
valid_post_logout_redirect_uris = [
"https://<ARGOCD HOSTNAME>/applications"
]
web_origins = [
"https://<ARGOCD HOSTNAME>"
]
root_url = "https://<ARGOCD HOSTNAME>"
admin_url = "https://<ARGOCD HOSTNAME>"
base_url = "/applications"
standard_flow_enabled = true
implicit_flow_enabled = false
direct_access_grants_enabled = true
client_session_max_lifespan = 604800
access_token_lifespan = 180
pkce_code_challenge_method = "S256"
}
resource "keycloak_openid_client_optional_scopes" "main" {
client_id = keycloak_openid_client.main.id
realm_id = keycloak_realm.main.id
optional_scopes = [
keycloak_openid_client_scope.main.name
]
}
次に argocd-cm
の ConfigMap に Keycloak の SSO を次の様に設定します。
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-cm
labels:
app.kubernetes.io/name: argocd-cm
app.kubernetes.io/part-of: argocd
data:
admin.enabled: "false"
url: https://<ARGOCD HOSTNAME>
oidc.config: |
name: Keycloak
issuer: https://<KEYCLOAK HOSTNAME>/realms/platform
clientID: argocd
enablePKCEAuthentication: true
requestedScopes: ["openid", "profile", "groups" ,"email"]
Argo CD にアクセスすると、LOG IN VIA KEYCLOAK
のボタンが表示されます。
ボタンをクリックすると、Keycloak のログイン画面にリダイレクトされます。
作成したアカウントでログインすると、パスワードのアップデートを促されるので、アップデートします。
パスワードをアップデートすると、ログインに成功し Application の一覧画面が表示されます。
最後にログインしたユーザーの情報を確認すると、次のようになっています。
ユーザーは Keycloak で作成した sample@example.com
ユーザーでログインしており、administrators
のグループで権限を付与されていることが分かります。
さいごに
Argo CD の SSO を Keycloak で実現する方法を紹介しました。
オンプレミスの環境で Argo CD を運用などされている場合、活用してみてください。
Discussion