夜鶯 v8 版本的單點登入 SSO 介紹,包含 SSO 的設定、使用方法等內容。

夜鶯監控(Nightingale)支援單點登入(SSO)功能,支援 LDAP、CAS、OAuth2、OIDC 等多種協定。SSO 功能可以讓使用者透過統一的身分認證系統登入夜鶯監控,簡化使用者管理和登入流程,也降低了安全風險。

對於 CAS、OAuth2、OIDC 三種方式,使用者透過 SSO 登入夜鶯之後,夜鶯會判斷當前登入的使用者是否存在於夜鶯的使用者表中,如果不存在,則會自動建立一個使用者,如果存在,夜鶯會用 SSO 中的使用者資訊覆蓋夜鶯中已有使用者的資訊(前提是設定項 CoverAttributes = true,後文會介紹),這樣的好處是使用者只需要在 SSO 那裡維護手機號、電子郵件即可,夜鶯會在使用者登入時自動同步(當然,僅是在登入時同步,所以使用者至少要透過 SSO 登入過一次夜鶯,否則夜鶯中沒有這個使用者的資訊)。

設定 OIDC

這是最推薦的方式,如果你的 SSO 同時支援 OIDC 和 OAuth2,建議使用 OIDC。

設定項說明

下面是 OIDC 各個設定項的說明:

# 是否開啟 OIDC 單點登入,夜鶯可以同時開啟多個 SSO 方式
Enable = false

# 登入頁面會展示 SSO 登入位址的超連結,DisplayName 用於設定超連結的文字內容
DisplayName = 'OIDC'

# IDC 登入驗證通過後,需要跳轉到夜鶯,下面是設定夜鶯用於 OIDC 的回呼位址
# 您需要把 n9e.com 替換為您的夜鶯位址,/callback 是固定的路徑
RedirectURL = 'http://n9e.com/callback'

# OIDC SSO 伺服器根位址,換成您的 OIDC 伺服器位址
SsoAddr = 'http://sso.example.org'

# OIDC SSO 伺服器的登出位址,使用者在夜鶯中點擊登出時會跳轉到這個位址,即可完成夜鶯和 SSO 的同步登出
SsoLogoutAddr = 'http://sso.example.org/session/end'

# OIDC 給夜鶯分配的 ClientId 和 ClientSecret,必須要設定,一般是在 SSO 伺服器上註冊應用時取得的
ClientId = ''
ClientSecret = ''

# 使用者透過 SSO 登入夜鶯,夜鶯發現使用者在夜鶯的使用者表中不存在時,會自動建立一個使用者
# 建立使用者的時候,需要給這個使用者一個角色,下面是設定預設角色的列表
DefaultRoles = ['Standard']

# 使用者透過 SSO 登入夜鶯時,夜鶯會向 SSO 伺服器請求使用者資訊,並將使用者資訊寫入夜鶯的使用者表中
# 如果 CoverAttributes = true 則會覆蓋夜鶯中已有的使用者資訊,比如手機號、電子郵件等。通常這裡就是設定為 true 即可
CoverAttributes = true

# Scope 是 OIDC 協定中的一個概念,表示請求取得的使用者資訊欄位列表,通常就是下面的這些欄位
Scopes = ['openid', 'profile', 'email', 'phone']

# 使用者在 OIDC 中資訊欄位和夜鶯中的使用者資訊欄位不是 100% 一一對應的
# 所以在下面設定:夜鶯的各個欄位對應 OIDC 中的哪些欄位
# Username、Nickname、Phone、Email 就是夜鶯中的使用者資訊欄位
# 後面的 sub、nickname、phone_number、email 就是 OIDC 中的使用者欄位名
# 請根據您的 OIDC 伺服器的使用者資訊欄位進行調整
[Attributes]
Username = 'sub'
Nickname = 'nickname'
Phone = 'phone_number'
Email = 'email'

設定項 FAQ

1. 使用者使用 OIDC 可以登入成功,但是使用者名稱、手機號等取得不到

可以調整夜鶯的日誌級別為 DEBUG(在 config.toml 中調整),然後重啟夜鶯,過濾日誌關鍵字:sso_exchange_user: oidc info,再測試一遍登入,可以查看從單點登入系統取得到的使用者資訊有哪些,然後根據實際情況調整 Attributes 中的欄位對應。

對接 Authing 演示

下面使用 Authing 作為 OIDC 的 SSO 伺服器進行演示。首先,要在 Authing 上建立一個應用,取得 ClientId 和 ClientSecret。

Authing OIDC

然後在夜鶯中設定 OIDC 的相關資訊:

Enable = true
DisplayName = 'OIDC'
RedirectURL = 'http://192.168.127.151:17000/callback'
SsoAddr = 'https://n9e.authing.cn/oidc'
SsoLoginOutAddr = 'https://n9e.authing.cn/oidc/session/end'
ClientId = '65befb5b452d4854f9731b9b'
ClientSecret = '0af4...'
CoverAttributes = true
DefaultRoles = ['Standard']
Scopes = ['openid', 'profile', 'username', 'email', 'phone']

[Attributes]
Username = 'username'
Nickname = 'nickname'
Phone = 'phone_number'
Email = 'email'

上面的 192.168.127.151:17000 是我這個測試環境的夜鶯位址,您需要替換為自己的夜鶯位址。

對接飛書演示

飛書也支援 OIDC 協定,我們對這種方式也做一個說明。參考飛書的官方文件建立應用:設定應用單點登入,相關設定:

  • 授權模式:可以把 authorization_code 和 refresh_token 都選上
  • Scope:可以把 openid profile email phone offline_access 都選上
  • 回呼位址:填寫 http://n9e.com/callback,注意把 n9e.com 替換為您的夜鶯位址,需要公網可達,除非您的飛書也是私有化內網部署的

設定完成之後即可拿到 Issuer(即 SSO Server 位址)、ClientId 和 ClientSecret,設定到夜鶯中。另外,也可以拿到 SSO Logout 位址,是一個類似這樣的位址:

https://anycross.feishu.cn/sso/....../oidc/revoke

這個位址也設定到夜鶯的 SsoLogoutAddr 中,雖然設定了這個位址,但是無法聯動登出,下面是飛書文件的 官方解釋說明

由於 SSO 應用的登入態是從飛書登入態派生出的,因此不支援單點登出,即在 SSO 應用登出的時候,不能同時登出飛書。雖然平台提供了單點登出的位址,但這個位址是為了防止三方系統將其設定為必填項,位址本身並不生效。

最終夜鶯中的設定如下:

Enable = true
DisplayName = 'OIDC'
RedirectURL = 'http://n9e.com/callback'
SsoAddr = 'https://anycross.feishu.cn/sso/XXXXX'
SsoLoginOutAddr = 'https://anycross.feishu.cn/sso/XXXXX/oidc/revoke'
ClientId = 'xxx'
ClientSecret = 'xxx'
CoverAttributes = true
DefaultRoles = ['Standard']
Scopes = ['openid', 'profile', 'email', 'phone']

[Attributes]
Username = 'name'
Nickname = 'name'
Phone = 'phone_number'
Email = 'email'

上面的 n9e.com 需要替換為您自己的夜鶯位址,需要公網可達,除非您的飛書也是私有化內網部署的。

對接 Keycloak 演示

之前有網友寫過一篇文章,講解 Grafana 和夜鶯一起對接 Keycloak,大家可以參考:Grafana 和夜鶯透過 Keycloak 深度對接整合

設定 OAuth2

如果您的 SSO 既支援 OIDC 又支援 OAuth2,建議使用 OIDC,實在沒辦法再使用 OAuth2,OAuth2 坑多。

設定項說明

# 是否開啟 OAuth2 單點登入,夜鶯可以同時開啟多個 SSO 方式
Enable = false

# 登入頁面會展示 SSO 登入位址的超連結,DisplayName 用於設定超連結的文字內容
DisplayName = 'OAuth2'

# SSO 登入驗證通過後,需要跳轉到夜鶯,下面是設定夜鶯用於 OAuth2 的回呼位址
# 您需要把 n9e.com 替換為您的夜鶯位址,/callback/oauth 是固定的路徑
RedirectURL = 'http://n9e.com/callback/oauth'

# OAuth2 SSO 伺服器根位址,換成您的 OAuth2 伺服器位址
SsoAddr = 'https://sso.example.com/oauth2/authorize'

# OAuth2 SSO 伺服器的登出位址,使用者在夜鶯中點擊登出時會跳轉到這個位址,即可完成夜鶯和 SSO 的同步登出
SsoLogoutAddr = 'https://sso.example.com/oauth2/authorize/session/end'

#  取得 OAuth2 token 的位址
TokenAddr = 'https://sso.example.com/oauth2/token'

# OAuth2 提供的使用者資訊位址,夜鶯會透過這個位址取得使用者資訊
UserInfoAddr = 'https://sso.example.com/api/v1/user/info'

# 從 OAuth2 或許使用者資訊時,需要把上一步取得到的 token 放到請求頭中
# token 可以放在 header 中,也可以放在 formdata 或 querystring 中,需要根據您的 OAuth2 伺服器的要求進行設定
TranTokenMethod = 'header'

# OAuth2 給夜鶯分配的 ClientId 和 ClientSecret,必須要設定,一般是在 SSO 伺服器上註冊應用時取得的
ClientId = ''
ClientSecret = ''

# 使用者透過 SSO 登入夜鶯,夜鶯發現使用者在夜鶯的使用者表中不存在時,會自動建立一個使用者
# 建立使用者的時候,需要給這個使用者一個角色,下面是設定預設角色的列表
DefaultRoles = ['Standard']

# 使用者透過 SSO 登入夜鶯時,夜鶯會向 SSO 伺服器請求使用者資訊,並將使用者資訊寫入夜鶯的使用者表中
# 如果 CoverAttributes = true 則會覆蓋夜鶯中已有的使用者資訊,比如手機號、電子郵件等。通常這裡就是設定為 true 即可
CoverAttributes = true

# 從 OAuth2 中取得使用者資料時,回傳的 JSON 格式資料是否為陣列,根據你們的 OAuth2 伺服器的回傳格式進行設定
# 如果是陣列,夜鶯會取第一個元素作為使用者資訊
UserinfoIsArray = false

# OAuth2 使用者資訊的前綴,通常是 'data',即回傳的 JSON 資料中會有一個 'data' 欄位,裡面是使用者資訊
UserinfoPrefix = 'data'

# Scope 是 OAuth2 協定中的一個概念,表示請求取得的使用者資訊欄位列表,通常就是下面的這些欄位
Scopes = ['profile', 'email', 'phone']

# 使用者在 OAuth2 中資訊欄位和夜鶯中的使用者資訊欄位不是 100% 一一對應的
# 所以在下面設定:夜鶯的各個欄位對應 OAuth2 中的哪些欄位
# Username、Nickname、Phone、Email 就是夜鶯中的使用者資訊欄位
# 後面的 sub、nickname、phone_number、email 就是 OAuth2 中的使用者欄位名
# 請根據您的 OAuth2 伺服器的使用者資訊欄位進行調整
[Attributes]
Username = 'sub'
Nickname = 'nickname'
Phone = 'phone_number'
Email = 'email'

對接 Authing 演示

使用 Authing 作為 OAuth2 的 SSO 伺服器進行演示。首先,要在 Authing 上啟用 OAuth2。設定範例如下:

Authing OAuth2

然後在夜鶯中設定 OAuth2 的相關資訊:

Enable = true
DisplayName = 'OAuth2'
RedirectURL = 'http://192.168.127.151:17000/callback/oauth'
SsoAddr = 'https://n9e.authing.cn/oauth/auth'
SsoLogoutAddr = 'https://n9e.authing.cn/oauth/session/end'
TokenAddr = 'https://n9e.authing.cn/oauth/token'
UserInfoAddr = 'https://n9e.authing.cn/oauth/me'
TranTokenMethod = 'header'
ClientId = '65befb5b452d4854f9731b9b'
ClientSecret = '0af4...'
CoverAttributes = true
DefaultRoles = ['Standard']
UserinfoIsArray = false
UserinfoPrefix = ''
Scopes = ['profile', 'username', 'email', 'phone']

[Attributes]
Username = 'username'
Nickname = 'nickname'
Phone = 'phone'
Email = 'email'

上面的 192.168.127.151:17000 是我這個測試環境的夜鶯位址,您需要替換為自己的夜鶯位址。

設定 CAS

夜鶯監控(Nightingale)也支援 CAS 協定的單點登入。相比 OIDC,坑更多,慎用。

設定項說明

# 是否開啟 CAS 單點登入,夜鶯可以同時開啟多個 SSO 方式
Enable = false

# 登入頁面會展示 SSO 登入位址的超連結,DisplayName 用於設定超連結的文字內容
DisplayName = 'CAS'

# CAS 登入驗證通過後,需要跳轉到夜鶯,下面是設定夜鶯用於 CAS 的回呼位址
# 您需要把 n9e.com 替換為您的夜鶯位址,/callback/cas 是固定的路徑
RedirectURL = 'http://n9e.com/callback/cas'

# CAS SSO 伺服器根位址,換成您的 CAS 伺服器位址
SsoAddr = 'https://cas.example.com/cas'

# CAS SSO 伺服器的登出位址,使用者在夜鶯中點擊登出時會跳轉到這個位址,即可完成夜鶯和 SSO 的同步登出
SsoLogoutAddr = 'https://cas.example.com/cas/session/end'

# LoginPath 這個設定項,是為了相容不同的 CAS 版本,因為不同的 CAS 版本登入位址可能不同
# 如果您設定了 LoginPath,則夜鶯會在 SsoAddr 的基礎上拼接 LoginPath 作為登入位址
# 如果您沒有設定 LoginPath,夜鶯的邏輯是:
# 1. 如果發現 SsoAddr 中包含 p3 關鍵字,就設定 LoginPath = '/login'
# 2. 如果沒有包含 p3 關鍵字,就設定 LoginPath = '/cas/login'
LoginPath = ''

# 使用者透過 SSO 登入夜鶯,夜鶯發現使用者在夜鶯的使用者表中不存在時,會自動建立一個使用者
# 建立使用者的時候,需要給這個使用者一個角色,下面是設定預設角色的列表
DefaultRoles = ['Standard']

# 使用者透過 SSO 登入夜鶯時,夜鶯會向 SSO 伺服器請求使用者資訊,並將使用者資訊寫入夜鶯的使用者表中
# 如果 CoverAttributes = true 則會覆蓋夜鶯中已有的使用者資訊,比如手機號、電子郵件等。通常這裡就是設定為 true 即可
CoverAttributes = true

# 使用者在 CAS 中資訊欄位和夜鶯中的使用者資訊欄位不是 100% 一一對應的
# 所以在下面設定:夜鶯的各個欄位對應 CAS 中的哪些欄位
# Username、Nickname、Phone、Email 就是夜鶯中的使用者資訊欄位
# 後面的 sub、nickname、phone_number、email 就是 CAS 中的使用者欄位名
# 請根據您的 CAS 伺服器的使用者資訊欄位進行調整
[Attributes]
Username = 'sub'
Nickname = 'nickname'
Phone = 'phone_number'
Email = 'email'

對接 Authing 演示

使用 Authing 作為 CAS 的 SSO 伺服器進行演示。首先,要在 Authing 上啟用 CAS。設定範例如下:

Authing CAS

然後在夜鶯中設定 CAS 的相關資訊:

Enable = true
DisplayName = 'CAS'
RedirectURL = 'http://192.168.127.151:17000/callback/cas'
SsoAddr = 'https://n9e.authing.cn/cas-idp/65befb5b452d4854f9731b9b'
SsoLogoutAddr = 'https://n9e.authing.cn/cas-idp/65befb5b452d4854f9731b9b/logout'
LoginPath = '/login'
CoverAttributes = true
DefaultRoles = ['Standard']

[Attributes]
Username = 'username'
Nickname = 'nickname'
Phone = 'phone_number'
Email = 'email'

上面的 192.168.127.151:17000 是我這個測試環境的夜鶯位址,您需要替換為自己的夜鶯位址。

設定 LDAP

夜鶯監控(Nightingale)也支援 LDAP 協定的認證登入。LDAP 是一種輕量級目錄存取協定,通常用於企業內部的使用者認證和授權。前面講到的 SSO 機制(OIDC、OAuth2、CAS)都沒法把使用者資訊週期性全量同步到夜鶯中,而 LDAP 則可以做到這一點。

LDAP 在頁面上也沒有單獨的登入超連結入口,使用者在輸入使用者名稱和密碼登入夜鶯時,夜鶯首先去 DB 中查詢使用者資訊,如果沒有找到,則自動檢查 LDAP 是否啟用,如果啟用了,就直接使用 LDAP 進行認證登入。

設定項說明

# 是否開啟 LDAP 單點登入,夜鶯可以同時開啟多個 SSO 方式
Enable = false

# LDAP 伺服器位址和連接埠、TLS、StartTLS 等設定
# 請根據您自己的環境進行設定
Host = 'ldap.example.org'
Port = 389
TLS = false
StartTLS = true

# LDAP 伺服器的根 DN,可以 Google、GPT 取得更多資訊
BaseDn = 'dc=example,dc=org'

# 管理員資訊,這個帳號需要具備查詢所有使用者資訊的權限
BindUser = 'cn=manager,dc=example,dc=org'
BindPass = '*******'

# 是否同步 LDAP 中的建立使用者至夜鶯
SyncAddUsers = false

# 是否同步 LDAP 中的刪除使用者操作至夜鶯
SyncDelUsers = false

# 同步頻率,單位:秒
SyncInterval = 86400

# 使用者登入時,檢查使用者是否存在於 LDAp 中的篩選條件
# openldap 和 AD 通常有不同的篩選格式
# openldap 的格式可能為: (&(uid=%s))
# AD 的格式可能為 (&(sAMAccountName=%s))
# 您需要根據您的 LDAP 伺服器類型進行調整
AuthFilter = '(&(uid=%s))'

# 查詢 LDAP 中全量使用者的篩選條件
# 根據您的 LDAP 伺服器類型進行調整
UserFilter = '(&(uid=*))'

# 使用者透過 LDAP 登入夜鶯,夜鶯發現使用者在夜鶯的使用者表中不存在時,會自動建立一個使用者
# 建立使用者的時候,需要給這個使用者一個角色,下面是設定預設角色的列表
DefaultRoles = ['Standard']

# 使用者透過 LDAP 登入夜鶯時,夜鶯會向 LDAP 伺服器請求使用者資訊,並將使用者資訊寫入夜鶯的使用者表中
# 如果 CoverAttributes = true 則會覆蓋夜鶯中已有的使用者資訊,比如手機號、電子郵件等。通常這裡就是設定為 true 即可
CoverAttributes = true

# 使用者在 LDAP 中資訊欄位和夜鶯中的使用者資訊欄位不是 100% 一一對應的
# 所以在下面設定:夜鶯的各個欄位對應 LDAP 中的哪些欄位
# Username、Nickname、Phone、Email 就是夜鶯中的使用者資訊欄位
# 後面的 uid、cn、mobile、mail 就是 LDAP 中的使用者欄位名
# 請根據您的 LDAP 伺服器的使用者資訊欄位進行調整
[Attributes]
Username = 'uid'
Nickname = 'cn'
Phone = 'mobile'
Email = 'mail'

上面的設定資訊如果您看完註解還是不清楚如何設定,可以諮詢貴司的 LDAP 管理員,他大概率是比較清楚的。

常見問題

Q1:選哪個 SSO 協定?

A:

  • Keycloak / Auth0 / Okta 等現代 IDP → 用 OIDC
  • 公司自建 AD / LDAP → 用 LDAP
  • 老系統 / 政務 SSO → 用 CAS
  • 釘釘 / 飛書企業 → 用各自專用 SSO;
  • GitHub / Google / 自研 OAuth2 服務 → 用 OAuth2

Q2:能同時啟用多個 SSO 嗎?

A:可以。n9e 的登入頁會顯示所有啟用的 SSO 入口,使用者選自己習慣的登入方式。但建議只啟用 1-2 個避免使用者困惑。

參考資料

快猫星云 联系方式 快猫星云 联系方式
快猫星云 联系方式
快猫星云 联系方式
快猫星云 联系方式
快猫星云