Keycloak:輕鬆實現開放式身份驗證和授權

作者:王金鑫,中國移動磐基 PaaS 平臺中間件專業服務項目組成員

Keycloak[1] 核心概念和術語

Keycloak 是 Web 應用程序和 RESTful Web 服務的單點登錄解決方案。Keycloak 的目標是使安全變得簡單,從而使應用程序開發人員能夠輕鬆地保護他們的應用程序和服務。開發人員通常要求編寫的安全功能是開箱即用的,並且很容易根據組織的要求進行定製化。Keycloak 爲登錄、註冊、管理和帳戶管理提供可定製的用戶界面。你也可以把 Keycloak 作爲一個集成平臺,將其連接到現有的 LDAP 和 Active Directory 服務器。您還可以將身份驗證委託給第三方身份提供商,例如 Github 和 Google。

在嘗試使用 Keycloak 來保護您的 Web 應用程序和 REST 服務之前,請考慮這些核心概念和術語。

部署和配置 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)和兩個用戶:

在 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 驗證登錄

作爲 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