Keycloak:輕鬆實現開放式身份驗證和授權
作者:王金鑫,中國移動磐基 PaaS 平臺中間件專業服務項目組成員
Keycloak[1] 核心概念和術語
Keycloak 是 Web 應用程序和 RESTful Web 服務的單點登錄解決方案。Keycloak 的目標是使安全變得簡單,從而使應用程序開發人員能夠輕鬆地保護他們的應用程序和服務。開發人員通常要求編寫的安全功能是開箱即用的,並且很容易根據組織的要求進行定製化。Keycloak 爲登錄、註冊、管理和帳戶管理提供可定製的用戶界面。你也可以把 Keycloak 作爲一個集成平臺,將其連接到現有的 LDAP 和 Active Directory 服務器。您還可以將身份驗證委託給第三方身份提供商,例如 Github 和 Google。
在嘗試使用 Keycloak 來保護您的 Web 應用程序和 REST 服務之前,請考慮這些核心概念和術語。
-
realms 是指認證和授權的子域,用於管理和驗證用戶身份。每個 realm 都有自己的身份驗證和授權配置。
-
clients 是指使用 Keycloak 作爲 API 客戶端的程序或服務。Keycloak 提供了多種 API(例如 HTTP API、JSON API 和 Websocket API) 供客戶端使用。客戶端可以使用 Keycloak 提供的 API 訪問 Keycloak 後端服務,以獲得訪問令牌 (access tokens) 或其他授權資源所需的權限。
-
groups 是指一組具有相同權限的用戶或客戶端。用戶可以加入多個 group,每個 group 都具有特定的權限範圍。group 可以是基於用戶的,也可以是基於客戶端的。例如,在一個企業中,可以創建一個名爲 “admin” 的 group,並將所有管理員添加到這個 group 中,以便他們訪問系統中的所有權限。
-
users 是指使用 Keycloak 的用戶。Keycloak 提供了多種方式來驗證用戶的身份,例如密碼、社會安全號碼、護照等。用戶可以在 Keycloak 中創建、修改或刪除,並且可以使用 Keycloak 提供的 API 進行身份驗證和授權。
-
Client Scopes 是指用於授權客戶端訪問 Keycloak 後端服務的權限。client scope 可以定義一組權限,這些權限可以授予客戶端,以便它們可以訪問 Keycloak 後端服務。例如,可以創建一個名爲 “read” 的 client scope,並將其授予可以讀取特定資源的客戶端。這樣可以確保只有具有足夠權限的客戶端可以訪問系統中的資源。
部署和配置 Keycloak
首先,我們將使用 Helm 快速部署 Keycloak ,最後使用 terraform 配置它。
部署 Keycloak Helm chart
helm repo add bitnami https://charts.bitnami.com/bitnami
helm upgrade --install --namespace keycloak --create-namespace \
keycloak bitnami/keycloak --version 14.1.0 \
--reuse-values --values - <<EOF
auth:
createAdminUser: true
adminUser: admin
adminPassword: admin
managementUser: manager
managementPassword: manager
tls:
enabled: true
autoGenerated: true
service:
type: NodePort
EOF
在 values 中,我們定義了自動創建管理用戶和賬戶密碼,並配置了 autoGenerated 自動生成私有證書的功能。
我們將自動生成的 CA 證書保存下來,以便在未來的章節中用於關鍵數據的安全傳輸和驗證。
kubectl exec -n keycloak keycloak-0 \
-- cat /opt/bitnami/keycloak/certs/ca.crt > /tmp/keycloakca.crt
使用 terraform 配置 Keycloak
我們將使用 terraform[2] 在 Keycloak 中創建 clients、用戶和組,以便更好地瞭解 Keycloak 的字段信息。通過使用 API,我們可以更直觀地瞭解 Keycloak 的配置細節。
cat <<'EOF' > keycloak.tf
terraform {
required_providers {
keycloak = {
source = "mrparkers/keycloak"
version = "4.2.0"
}
}
}
# configure keycloak provider
provider "keycloak" {
client_id = "admin-cli"
username = "admin"
password = "admin"
url = "https://keycloak.keycloak.svc.cluster.local:20443"
tls_insecure_skip_verify = true
}
locals {
groups = ["harbor-dev", "harbor-admin"]
user_groups = {
user-dev = ["harbor-dev"]
user-admin = ["harbor-admin"]
}
}
resource "keycloak_realm" "realm" {
realm = "harbor"
enabled = true
}
# create groups
resource "keycloak_group" "groups" {
realm_id = keycloak_realm.realm.id
for_each = toset(local.groups)
name = each.key
}
# create users
resource "keycloak_user" "users" {
for_each = local.user_groups
realm_id = keycloak_realm.realm.id
username = each.key
enabled = true
email = "${each.key}@domain.com"
email_verified = true
first_name = each.key
last_name = each.key
initial_password {
value = each.key
}
}
# configure use groups membership
resource "keycloak_user_groups" "user_groups" {
for_each = local.user_groups
realm_id = keycloak_realm.realm.id
user_id = keycloak_user.users[each.key].id
group_ids = [for g in each.value : keycloak_group.groups[g].id]
}
# create groups openid client scope
resource "keycloak_openid_client_scope" "groups" {
realm_id = keycloak_realm.realm.id
name = "groups"
include_in_token_scope = true
gui_order = 1
}
resource "keycloak_openid_group_membership_protocol_mapper" "groups" {
realm_id = keycloak_realm.realm.id
client_scope_id = keycloak_openid_client_scope.groups.id
name = "groups"
claim_name = "groups"
full_path = false
}
# create harbor openid client
resource "keycloak_openid_client" "harbor" {
realm_id = keycloak_realm.realm.id
client_id = "harbor" #定義的client id
name = "harbor"
enabled = true
access_type = "CONFIDENTIAL"
client_secret = "harbor-client-secret" #此id的密碼
standard_flow_enabled = true
implicit_flow_enabled = false
login_theme = "keycloak"
direct_access_grants_enabled = false
oauth2_device_authorization_grant_enabled = true
valid_redirect_uris = [
"http://harbor.10086cloud.com/c/oidc/callback"
]
valid_post_logout_redirect_uris = [
"http://harbor.10086cloud.com"
]
web_origins = [
"http://harbor.10086cloud.com"
]
admin_url = "http://harbor.10086cloud.com"
root_url = "http://harbor.10086cloud.com"
base_url = "http://harbor.10086cloud.com"
}
# configure harbor openid client default scopes
resource "keycloak_openid_client_default_scopes" "harbor" {
realm_id = keycloak_realm.realm.id
client_id = keycloak_openid_client.harbor.id
default_scopes = [
"profile",
"email",
"roles",
keycloak_openid_client_scope.groups.name,
]
}
EOF
terraform init && terraform apply -auto-approve
運行上述腳本將創建一個 harbor realm、harbor clients、兩個組(harbor-dev、harbor-admin)和兩個用戶:
-
user-dev 是 harbor-dev 組的成員
-
user-admin 是 harbor-admin 組的成員
在 harbor 中配置 Keycloak
Harbor OIDC 認證流程
Harbor 可以與支持 OIDC 的 OAuth 服務提供商集成來進行用戶認證,並通過授權碼方式獲取令牌
(1)用戶通過瀏覽器訪問 Harbor 的登錄頁面,並單擊 “通過 OIDC 提供商登錄” 按鈕,該按鈕在 Harbor 使用 OIDC 認證時纔會顯示。
(2)用戶被重定向到 OIDC 提供商的身份驗證頁面。(本文爲公衆號亨利筆記原創文章)
(3)在用戶經過身份驗證後,OIDC 提供商將使用授權代碼重定向至 Harbor。
(4)Harbor 將與 OIDC 提供商交換此授權代碼以獲得訪問令牌。
(5)Harbor 使用訪問令牌請求 UserInfo 接口獲取用戶信息。
(6)Harbor 在系統中創建或更新用戶賬戶並將用戶重定向到 Harbor 的門戶首頁
快速部署 Harbor 演示集羣
首先使用 Kubernetes 和 Helm,快速輕鬆地搭建一個 Harbor 集羣。
helm repo add harbor https://helm.goharbor.io
helm upgrade --install --namespace harbor --create-namespace \
harbor harbor/harbor --version 1.12.0 \
--reuse-values --values - <<EOF
expose:
type: nodePort
tls:
enabled: false
nodePort:
ports:
http:
nodePort: 80
externalURL: http://harbor.10086cloud.com
EOF
配置 OIDC 提供身份驗證 [3]
如果您選擇 OpenID Connect (OIDC) 認證,用戶將通過 OIDC 單點登錄 (SSO) 提供商 KeyCloak 登錄到 Harbor 界面。在這種情況下,你不能在 Harbor 中創建用戶賬戶。
開始配置 harbor oidc
1、用管理用戶 admin 和默認管理員密碼 Harbor12345 登錄到 Keycloak 控制檯。
2、系統管理——> 配置管理——> 安全認證——> 認證模式下拉改爲 OIDC
3、輸入您的 KeyCloak 配置信息。
-
OIDC Provider Name:OIDC 提供程序的名稱
-
OIDC Provider Endpoint:OIDC 提供程序的 URL 連接地址
-
OIDC Client ID:harbor 向 OIDC 提供程序註冊的客戶端 ID
-
OIDC Client Secret:客戶端 ID 的密鑰
-
OIDC Scope:一個逗號分割的字符串,列出身份驗證期間要使用的作用域
通過 OIDC 驗證登錄
作爲 Harbor 用戶,請單擊通過 OIDC 提供商登錄按鈕。
這會將您重定向到 OIDC 提供程序進行身份驗證。輸入提前在 Keycloak 中創建的用戶:user-dev 密碼:user-dev
如果這是您第一次使用 OIDC 登錄 Harbor,請指定 Harbor 與您的 OIDC 用戶名關聯的用戶名。
也可以在最開始的時候配置 ” 自動登錄 “(Automatic onboarding), 跳過創建 Harbor 用戶名
使用 shell 腳本自動配置 harbor oidc
創建自定義 habor2.8_config.json 配置文件
{
"auth_mode": "oidc_auth",
"oidc_name": "Keycloak",
"oidc_endpoint": "https://192.168.123.50:20443/realms/harbor",
"oidc_client_id": "harbor",
"oidc_client_secret": "harbor-client-secret",
"oidc_scope": "openid,profile,email",
"oidc_groups_claim": "groups",
"oidc_auto_onboard": true,
"oidc_user_claim": "preferred_username"
}
curl -X PUT -u "admin:Harbor12345" \
-H "Content-Type: application/json" -ki 192.168.123.50/api/v2.0/configurations \
-d @habor2.8_config.json
從 docker 或 Helm CLI 使用 OIDC
Docker 和 Helm CLI 由於無法處理 OIDC 的重定向,因此 Harbor 提供了一個 CLI 密鑰,以便在從 Docker 或 Helm 登錄時使用。這僅在 Harbor 使用 OIDC 身份驗證時可用。
1、使用 OIDC 用戶帳戶登錄 Harbor。
2、點擊屏幕右上角頂部的用戶名,選擇用用戶設置
3、點擊 CLI 密碼可複製,... 圖標以顯示用於自動生成或手動創建新 CLI 密鑰的按鈕。一個用戶只能有一個 CLI 密鑰,因此當生成或創建新密鑰時,舊密鑰將變爲無效。
4、使用 docker 或 Helm CLI 登錄 Harbor 時使用您的 CLI 密鑰作爲密碼。
docker login -u **** -p ***** http://harbor.10086cloud.com
參考資料
[1]
Keycloak: https://www.keycloak.org/documentation
[2]
terraform: https://developer.hashicorp.com/terraform/downloads
[3]
配置 OIDC 提供身份驗證: https://goharbor.io/docs/1.10/administration/configure-authentication/oidc-auth/
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/wTYLuuTr7ezx4ObNHZ2_uw