我正在嘗試使用 FreeIPA/Kerberos 在我們公司的一些 Intranet 網站上實現 SSO。但關於這個主題的資訊非常少。
我的測試網路中運行著三台機器:
Kinit、Unix 登入和 Apache Kerberos Auth 工作。用戶端系統上的Firefox瀏覽器無需密碼即可登入FreeIPA WebConfig(使用Kerberos Ticket)。我現在想將此功能轉移到我們的內部網路頁面。到目前為止,這些頁面的登入都是基於傳統的 LDAP 登入。透過登入腳本進行細微調整,使用者現在可以登入新的 FreeIPA 伺服器。但是,他仍然需要密碼,但由於 Kerberos 票證,實際上不再需要密碼。
問題是,無密碼登入是什麼樣的?
登入腳本的功能片段:
<?php $username = $_SERVER['PHP_AUTH_USER']; $password = 'password'; $ldap_rdn = 'uid='.$username.',cn=users,cn=accounts,dc=exampletest,dc=de'; $ldap_server = ldap_connect('ldap://ipa.exampletest.de:389'); ldap_set_option($ldap_server, LDAP_OPT_PROTOCOL_VERSION, 3); ldap_set_option($ldap_server, LDAP_OPT_REFERRALS, 0); if ($ldap_server) { $ldap_bind = @ldap_bind($ldap_server, $ldap_rdn, $password); if ($ldap_bind) { $search = array("uid","givenname","sn","mail","uidnumber","gidnumber"); $result = ldap_search($ldap_server, $ldap_rdn, "mail=$username*", $search); $info = ldap_get_entries($ldap_server, $result); print_r($info); } } ?>
現在我有兩個想法:
提前非常感謝。
編輯:
Web 伺服器 VM 和客戶端 VM 皆透過「ipa-client-install」初始化。另外,Web伺服器已經註冊了apache服務(ipa service-add HTTP/ebook.exampletest.de)。
apache 設定也反映了這一點:
<Directory /var/www/ebook/> AuthType GSSAPI AuthName "eBook Login" GssapiCredStore keytab:/etc/apache2/http.keytab GssapiAllowedMech krb5 GssapiBasicAuthMech krb5 GssapiImpersonate On GssapiDelegCcacheDir /run/apache2/clientcaches GssapiLocalName On # for production set to on: GssapiSSLonly Off GssapiNegotiateOnce Off GssapiUseSessions On Session On SessionCookieName gssapi_session path=/private;httponly;secure; Require valid-user </Directory>正如我已經提到的,用戶身份驗證似乎是這樣工作的(
client(自己的票)
> web 服務(自己的票) > ipa server
)。否則 apache 伺服器不會傳回我的 ldap/kerberos 使用者名稱。或者我在這裡遺漏了一些重要的東西?有其他方法可以強制執行這種身份驗證嗎?
輸出:<?php print_r($_SERVER) ?>
(已截取)
[GSS_MECH] => Negotiate/krb5 [GSS_NAME] => test@EXAMPLETEST.DE [REMOTE_USER] => test [AUTH_TYPE] => Negotiate [PHP_AUTH_USER] => test
確保您的 Web 伺服器具有正確 Kerberos 票證。
通常,Kerberos 驗證僅傳輸僅對該伺服器有效的票證,而不是一攬子「所有」票證。當用戶端對您的 web 應用程式進行身份驗證時,您獲得的只是
HTTP/webapp.example.tld
的票證,而且您無法真正使用它來代表使用者存取 LDAP。如果您需要代表使用者存取 LDAP,則有以下幾種選擇:
網路應用程式可以擁有自己的 LDAP 目錄憑證。這可能是最簡單的方法。 Web 應用程式可以使用標準密碼綁定,也可以使用從金鑰表取得的自己的票證進行 Kerberos (SASL) 綁定。
LDAP 還支援“模擬”,即Web 應用程式將使用自己的憑證進行身份驗證,但也指定一個“授權ID”(authzid) 來確定您將獲得哪個帳戶的權限。
例如,如果您以「webapp」身份進行驗證,但指定了authzid「myuser」(並且如果LDAP 伺服器允許),那麼您將獲得「myuser」通常所擁有的權限有– 而不是「webapp」的那些。
Web 應用程式的 HTTP 協商 (SPNEGO) 驗證可以啟用「委託」。委派確實將主
krbtgt
票證傳輸到Web伺服器,然後伺服器會將其放入臨時票證快取中並可供您的Web應用程式環境使用。但是,委託有一些問題:
這會使每個HTTP 請求變慢,因為客戶端必須要求帶有「轉發」標誌的新
krbtgt
票證(除非Web 伺服器可以使用例如cookie 來避免請求協商身份驗證)用於進一步的請求,例如帶有“會話”模式的mod_auth_gssapi)。它要求Web 應用程式高度可信,因為它將為每個存取它的使用者(包括管理員)儲存通配符票證- 即使Web 應用程式本身被信任不會濫用它們,它們仍然可能被竊取伺服器。
大多數使用 Kerberos 的 API(包括 ldap_sasl_bind())都期望
KRB5CCNAME
環境變數指向票證快取。但環境變數是進程範圍的,因此只要 PHP 重複使用相同進程,它們就可能會在不相關的請求中洩漏(或者更糟的是,如果您使用 mod_php 在 Apache 進程內執行 web 應用程式)。在 AD 中,這具體稱為“無約束委派”,因為 AD 引入了其他變體。
網路應用程式可以使用S4U2Proxy 又稱為「約束委派」來代表使用者建立票證,以取得某些有限的服務集(例如,FreeIPA 可以將其限制為僅存取
ldap/foo.example.com
)。這有點複雜(PHP 沒有這方面的 API - 您可能需要使用正確的標誌產生
kinit
),並且仍然存在與 KRB5CCNAME 跨請求洩漏相同的潛在問題。對於常規 Kerberos 驗證,用法如下所示:
僅此而已。 GSSAPI SASL 機制期望環境已經具有可用的 Kerberos 票證(例如透過 $KRB5CCNAME 或透過 gss-proxy),並且它將使用在那裡找到的任何票證進行身份驗證。
如果您想要使用模擬(假設在 LDAP 伺服器中設定),則必須指定 authz_id:
大多數
ldap_*()
PHP 函數都是 C libldap 函式庫的直接包裝器,因此其文件可作為部分參考。看來您的範例已經指定了使用者的確切DN,因此似乎不需要透過
mail
進行額外過濾- 只需在讀取郵件時使用objectClass=*
特定的DN。另外,當您想要讀取特定 DN 時,請使用 ldap_read() 進行「基本」搜尋而不是子樹搜尋。不,事情不是這樣的。您的使用者名稱(即用戶端 Kerberos 主體)儲存在用戶端票證中,因此 Web 伺服器在解密票證後立即知道它,而無需與 IPA 對話。