Redmine 的 GSSAPI 身份验证失败
GSSAPI authentication fails for Redmine
我已经使用 Kerberos + GSSAPI 在 Apache 上为 Redmine 配置了 SSO。
它第一次工作正常。但是我推迟了这个配置,当我再次设置它时 SSO 身份验证失败,httpd 错误日志中出现以下错误:
[http:trace4] [pid 29360] http_request.c(316): [client 192.168.0.10:47380] Authorization: Negotiate TlRMTVNTUAABAAAAl4II4gAAAAAAAAAAAAAAAAAAAAAKADk4AAAADw==
[rewrite:trace2] [pid 29360] mod_rewrite.c(470): [client 192.168.0.10:47380] 192.168.0.10 - - [redmine.mydomain.com/sid#558a80593c58][rid#558a806408f0/initial] init rewrite engine with requested uri /
[rewrite:trace1] [pid 29360] mod_rewrite.c(470): [client 192.168.0.10:47380] 192.168.0.10 - - [redmine.mydomain.com/sid#558a80593c58][rid#558a806408f0/initial] pass through /
[authz_core:debug] [pid 29360] mod_authz_core.c(809): [client 192.168.0.10:47380] AH01626: authorization result of Require valid-user : denied (no authenticated user yet)
[authz_core:debug] [pid 29360] mod_authz_core.c(809): [client 192.168.0.10:47380] AH01626: authorization result of <RequireAny>: denied (no authenticated user yet)
[auth_gssapi:debug] [pid 29360] mod_auth_gssapi.c(900): [client 192.168.0.10:47380] URI: /, no main, no prev
[auth_gssapi:error] [pid 29360] [client 192.168.0.10:47380] GSS ERROR In Negotiate Auth: gss_accept_sec_context() failed: [An unsupported mechanism was requested (Unknown error)]
我还遇到了另一个错误:
[auth_gssapi:info] [pid 8012] [client 127.0.0.1:37910] NO AUTH DATA 客户端未发送任何身份验证 headers
我的krb5.conf
[logging]
default = FILE:/var/log/krb5libs.log
kdc = FILE:/var/log/krb5kdc.log
admin_server = FILE:/var/log/kadmind.log
[libdefaults]
default_realm = MYDOMAIN.COM
default_keytab_name = /etc/krb5.keytab
dns_lookup_realm = false
dns_lookup_kdc = false
ticket_lifetime = 24h
renew_lifetime = 24h
forwardable = true
default_tgs_enctypes = aes256-cts-hmac-sha1-96
default_tkt_enctypes = aes256-cts-hmac-sha1-96
[realms]
MYDOMAIN.COM = {
kdc = mydc.mydomain.com
admin_server = mydc.mydomain.com
default_domain = mydomain.com
kpasswd_server = mydc.mydomain.com
}
[domain_realm]
.mydomain.com = MYDOMAIN.COM
mydomain.com = MYDOMAIN.COM
我的密钥表
# klist -ek /etc/krb5.keytab
Keytab name: FILE:/etc/krb5.keytab
KVNO Principal
---- --------------------------------------------------------------------------
4 HTTPS/redmine.mydomain.com@MYDOMAIN.COM (aes256-cts-hmac-sha1-96)
Keytab 测试:
# kinit -V -kt /etc/krb5.keytab -p HTTPS/redmine.mydomain.com@MYDOMAIN.COM
Using default cache: /tmp/krb5cc_0
Using principal: HTTPS/redmine.mydomain.com@MYDOMAIN.COM
Using keytab: /etc/krb5.keytab
Authenticated to Kerberos v5
#
# klist -Af
Ticket cache: FILE:/tmp/krb5cc_0
Default principal: HTTPS/redmine.mydomain.com@MYDOMAIN.COM
Valid starting Expires Service principal
02/15/2019 16:31:47 02/16/2019 02:31:47 krbtgt/MYDOMAIN.COM@MYDOMAIN.COM
renew until 02/16/2019 16:31:47, Flags: FPRIA
我的密钥表是通过以下命令生成的:
ktpass -princ HTTPS/redmine.mydomain.com@MYDOMAIN.COM -mapuser serviceuser -pass my_password -ptype KRB5_NT_PRINCIPAL -crypto AES256-SHA1 -out redmine.keytab -mapOp set
SPN 信息
C:\>setspn -L serviceuser
Registered ServicePrincipalNames for CN=serviceuser,OU=Pseudo Accounts,OU=Managed Objects,DC=mydomain,DC=com:
HTTPS/redmine.mydomain.com
C:\>setspn -Q HTTPS/redmine.mydomain.com
Checking domain DC=mydomain,DC=com
CN=serviceuser,OU=Pseudo Accounts,OU=Managed Objects,DC=mydomain,DC=com
HTTPS/redmine.mydomain.com
Existing SPN found!
看起来我的密钥表没问题。
我的 redmine.conf for Apache
<VirtualHost *:80>
ServerAdmin admin@mydomain.com
ServerName redmine.mydomain.com
Redirect "/" "https://redmine.mydomain.com/"
</VirtualHost>
<VirtualHost *:443>
ServerAdmin admin@mydomain.com
ServerName redmine.mydomain.com
DocumentRoot /var/www/redmine/public/
# SSL
# Enable SSL with Perfect Forward Secrecy
SSLEngine on
SSLProtocol +TLSv1.2 +TLSv1.1 +TLSv1
SSLCompression off
SSLCertificateFile /etc/ssl/certs/mydomain.com.crt
SSLCertificateKeyFile /etc/ssl/private/mydomain.com.key
## Passenger Configuration
RailsBaseURI /
PassengerAppRoot /var/www/redmine
PassengerRuby /usr/local/rvm/gems/ruby-2.4.4/wrappers/ruby
PassengerFriendlyErrorPages on
RailsSpawnMethod smart
RailsAppSpawnerIdleTime 3600
PassengerMaxPreloaderIdleTime 0
PassengerMaxRequests 5000
PassengerUser apache
PassengerGroup apache
<Directory /var/www/redmine/public>
Options +Indexes +FollowSymLinks -MultiViews
AllowOverride All
<IfVersion < 2.3 >
Order allow,deny
Allow from all
</IfVersion>
<IfVersion >= 2.3>
Require all granted
</IfVersion>
</Directory>
# SSO start
<Location "/">
RewriteEngine On
RewriteCond %{IS_SUBREQ} ^false$
RewriteCond %{LA-U:REMOTE_USER} (.+)
RewriteRule . - [E=RU:%1]
RequestHeader add REMOTE_USER %{RU}e
SSLRequireSSL
AuthType GSSAPI
AuthName "login:"
GssapiSSLonly On
GssapiAllowedMech krb5
GssapiCredStore keytab:/etc/krb5.keytab
GssapiLocalName On
GssapiBasicAuth On
Require valid-user
</Location>
# SSO end
#AddOutputFilter DEFLATE text/html text/plain text/xml application/xml application/xhtml+xml text/javascript text/css
#BrowserMatch ^Mozilla/4 gzip-only-text/html
#BrowserMatch ^Mozilla/4.0[678] no-gzip
#BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
ErrorLog /var/log/httpd/redmine.error.log
LogLevel trace8
CustomLog /var/log/httpd/redmine.access.log combined
ServerSignature Off
</VirtualHost>
我也试过没有 GssapiAllowedMech krb5
选项,但我得到了同样的错误。
我修改了redmine app app/controllers/application_controller.rb
。将以下字符串添加到 find_current_user
函数:
elsif (forwarded_user = request.env["REMOTE_USER"])
# web server authentication
user = (User.find_by_login(forwarded_user) rescue nil)
结果:
def find_current_user
user = nil
unless api_request?
if session[:user_id]
# existing session
user = (User.active.find(session[:user_id]) rescue nil)
# Start custom settings
elsif (forwarded_user = request.env["REMOTE_USER"])
# web server authentication
user = (User.find_by_login(forwarded_user) rescue nil)
# End custom settings
elsif autologin_user = try_to_autologin
user = autologin_user
elsif params[:format] == 'atom' && params[:key] && request.get? && accept_rss_auth?
# RSS key authentication does not start a session
user = User.find_by_rss_key(params[:key])
end
end
浏览器配置。
对于 Google Chrome、Edge、Opera,我在 Internet 选项中设置了本地 Intranet 和受信任的站点区域,以使用当前用户名和密码自动登录。
对于 FF:
network.negotiate-auth.delegation-uris = mydomain.com
network.negotiate-auth.trusted-uris = mydomain.com
有什么想法吗?
我通过为我的服务用户添加 HTTP 主体并使用 HTTP 和 HTTPS 主体重新创建密钥表来解决我的问题。
C:\>setspn -L serviceuser
Registered ServicePrincipalNames for CN=serviceuser,OU=Pseudo Accounts,OU=Managed Objects,DC=mydomain,DC=com:
HTTP/redmine.mydomain.com
HTTPS/redmine.mydomain.com
C:\>setspn -Q HTTP/redmine.mydomain.com
Checking domain DC=mydomain,DC=com
CN=serviceuser,OU=Pseudo Accounts,OU=Managed Objects,DC=mydomain,DC=com
HTTP/redmine.mydomain.com
HTTPS/redmine.mydomain.com
Existing SPN found!
然后分两步创建密钥表:
ktpass -princ HTTP/redmine.mydomain.com@MYDOMAIN.COM -mapuser serviceuser -pass password -ptype KRB5_NT_PRINCIPAL -crypto All -out HTTP_redmine.keytab -mapOp set
ktpass -princ HTTPS/redmine.mydomain.com@MYDOMAIN.COM -mapuser serviceuser -pass password -ptype KRB5_NT_PRINCIPAL -crypto All -in HTTP_redmine.keytab -out HTTPS_redmine.keytab -mapOp set
在第二步中,我从第一步中导入了带有 HTTP SPN 的密钥选项卡。
我已经使用 Kerberos + GSSAPI 在 Apache 上为 Redmine 配置了 SSO。 它第一次工作正常。但是我推迟了这个配置,当我再次设置它时 SSO 身份验证失败,httpd 错误日志中出现以下错误:
[http:trace4] [pid 29360] http_request.c(316): [client 192.168.0.10:47380] Authorization: Negotiate TlRMTVNTUAABAAAAl4II4gAAAAAAAAAAAAAAAAAAAAAKADk4AAAADw==
[rewrite:trace2] [pid 29360] mod_rewrite.c(470): [client 192.168.0.10:47380] 192.168.0.10 - - [redmine.mydomain.com/sid#558a80593c58][rid#558a806408f0/initial] init rewrite engine with requested uri /
[rewrite:trace1] [pid 29360] mod_rewrite.c(470): [client 192.168.0.10:47380] 192.168.0.10 - - [redmine.mydomain.com/sid#558a80593c58][rid#558a806408f0/initial] pass through /
[authz_core:debug] [pid 29360] mod_authz_core.c(809): [client 192.168.0.10:47380] AH01626: authorization result of Require valid-user : denied (no authenticated user yet)
[authz_core:debug] [pid 29360] mod_authz_core.c(809): [client 192.168.0.10:47380] AH01626: authorization result of <RequireAny>: denied (no authenticated user yet)
[auth_gssapi:debug] [pid 29360] mod_auth_gssapi.c(900): [client 192.168.0.10:47380] URI: /, no main, no prev
[auth_gssapi:error] [pid 29360] [client 192.168.0.10:47380] GSS ERROR In Negotiate Auth: gss_accept_sec_context() failed: [An unsupported mechanism was requested (Unknown error)]
我还遇到了另一个错误: [auth_gssapi:info] [pid 8012] [client 127.0.0.1:37910] NO AUTH DATA 客户端未发送任何身份验证 headers
我的krb5.conf
[logging]
default = FILE:/var/log/krb5libs.log
kdc = FILE:/var/log/krb5kdc.log
admin_server = FILE:/var/log/kadmind.log
[libdefaults]
default_realm = MYDOMAIN.COM
default_keytab_name = /etc/krb5.keytab
dns_lookup_realm = false
dns_lookup_kdc = false
ticket_lifetime = 24h
renew_lifetime = 24h
forwardable = true
default_tgs_enctypes = aes256-cts-hmac-sha1-96
default_tkt_enctypes = aes256-cts-hmac-sha1-96
[realms]
MYDOMAIN.COM = {
kdc = mydc.mydomain.com
admin_server = mydc.mydomain.com
default_domain = mydomain.com
kpasswd_server = mydc.mydomain.com
}
[domain_realm]
.mydomain.com = MYDOMAIN.COM
mydomain.com = MYDOMAIN.COM
我的密钥表
# klist -ek /etc/krb5.keytab
Keytab name: FILE:/etc/krb5.keytab
KVNO Principal
---- --------------------------------------------------------------------------
4 HTTPS/redmine.mydomain.com@MYDOMAIN.COM (aes256-cts-hmac-sha1-96)
Keytab 测试:
# kinit -V -kt /etc/krb5.keytab -p HTTPS/redmine.mydomain.com@MYDOMAIN.COM
Using default cache: /tmp/krb5cc_0
Using principal: HTTPS/redmine.mydomain.com@MYDOMAIN.COM
Using keytab: /etc/krb5.keytab
Authenticated to Kerberos v5
#
# klist -Af
Ticket cache: FILE:/tmp/krb5cc_0
Default principal: HTTPS/redmine.mydomain.com@MYDOMAIN.COM
Valid starting Expires Service principal
02/15/2019 16:31:47 02/16/2019 02:31:47 krbtgt/MYDOMAIN.COM@MYDOMAIN.COM
renew until 02/16/2019 16:31:47, Flags: FPRIA
我的密钥表是通过以下命令生成的:
ktpass -princ HTTPS/redmine.mydomain.com@MYDOMAIN.COM -mapuser serviceuser -pass my_password -ptype KRB5_NT_PRINCIPAL -crypto AES256-SHA1 -out redmine.keytab -mapOp set
SPN 信息
C:\>setspn -L serviceuser
Registered ServicePrincipalNames for CN=serviceuser,OU=Pseudo Accounts,OU=Managed Objects,DC=mydomain,DC=com:
HTTPS/redmine.mydomain.com
C:\>setspn -Q HTTPS/redmine.mydomain.com
Checking domain DC=mydomain,DC=com
CN=serviceuser,OU=Pseudo Accounts,OU=Managed Objects,DC=mydomain,DC=com
HTTPS/redmine.mydomain.com
Existing SPN found!
看起来我的密钥表没问题。
我的 redmine.conf for Apache
<VirtualHost *:80>
ServerAdmin admin@mydomain.com
ServerName redmine.mydomain.com
Redirect "/" "https://redmine.mydomain.com/"
</VirtualHost>
<VirtualHost *:443>
ServerAdmin admin@mydomain.com
ServerName redmine.mydomain.com
DocumentRoot /var/www/redmine/public/
# SSL
# Enable SSL with Perfect Forward Secrecy
SSLEngine on
SSLProtocol +TLSv1.2 +TLSv1.1 +TLSv1
SSLCompression off
SSLCertificateFile /etc/ssl/certs/mydomain.com.crt
SSLCertificateKeyFile /etc/ssl/private/mydomain.com.key
## Passenger Configuration
RailsBaseURI /
PassengerAppRoot /var/www/redmine
PassengerRuby /usr/local/rvm/gems/ruby-2.4.4/wrappers/ruby
PassengerFriendlyErrorPages on
RailsSpawnMethod smart
RailsAppSpawnerIdleTime 3600
PassengerMaxPreloaderIdleTime 0
PassengerMaxRequests 5000
PassengerUser apache
PassengerGroup apache
<Directory /var/www/redmine/public>
Options +Indexes +FollowSymLinks -MultiViews
AllowOverride All
<IfVersion < 2.3 >
Order allow,deny
Allow from all
</IfVersion>
<IfVersion >= 2.3>
Require all granted
</IfVersion>
</Directory>
# SSO start
<Location "/">
RewriteEngine On
RewriteCond %{IS_SUBREQ} ^false$
RewriteCond %{LA-U:REMOTE_USER} (.+)
RewriteRule . - [E=RU:%1]
RequestHeader add REMOTE_USER %{RU}e
SSLRequireSSL
AuthType GSSAPI
AuthName "login:"
GssapiSSLonly On
GssapiAllowedMech krb5
GssapiCredStore keytab:/etc/krb5.keytab
GssapiLocalName On
GssapiBasicAuth On
Require valid-user
</Location>
# SSO end
#AddOutputFilter DEFLATE text/html text/plain text/xml application/xml application/xhtml+xml text/javascript text/css
#BrowserMatch ^Mozilla/4 gzip-only-text/html
#BrowserMatch ^Mozilla/4.0[678] no-gzip
#BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
ErrorLog /var/log/httpd/redmine.error.log
LogLevel trace8
CustomLog /var/log/httpd/redmine.access.log combined
ServerSignature Off
</VirtualHost>
我也试过没有 GssapiAllowedMech krb5
选项,但我得到了同样的错误。
我修改了redmine app app/controllers/application_controller.rb
。将以下字符串添加到 find_current_user
函数:
elsif (forwarded_user = request.env["REMOTE_USER"])
# web server authentication
user = (User.find_by_login(forwarded_user) rescue nil)
结果:
def find_current_user
user = nil
unless api_request?
if session[:user_id]
# existing session
user = (User.active.find(session[:user_id]) rescue nil)
# Start custom settings
elsif (forwarded_user = request.env["REMOTE_USER"])
# web server authentication
user = (User.find_by_login(forwarded_user) rescue nil)
# End custom settings
elsif autologin_user = try_to_autologin
user = autologin_user
elsif params[:format] == 'atom' && params[:key] && request.get? && accept_rss_auth?
# RSS key authentication does not start a session
user = User.find_by_rss_key(params[:key])
end
end
浏览器配置。
对于 Google Chrome、Edge、Opera,我在 Internet 选项中设置了本地 Intranet 和受信任的站点区域,以使用当前用户名和密码自动登录。
对于 FF:
network.negotiate-auth.delegation-uris = mydomain.com
network.negotiate-auth.trusted-uris = mydomain.com
有什么想法吗?
我通过为我的服务用户添加 HTTP 主体并使用 HTTP 和 HTTPS 主体重新创建密钥表来解决我的问题。
C:\>setspn -L serviceuser
Registered ServicePrincipalNames for CN=serviceuser,OU=Pseudo Accounts,OU=Managed Objects,DC=mydomain,DC=com:
HTTP/redmine.mydomain.com
HTTPS/redmine.mydomain.com
C:\>setspn -Q HTTP/redmine.mydomain.com
Checking domain DC=mydomain,DC=com
CN=serviceuser,OU=Pseudo Accounts,OU=Managed Objects,DC=mydomain,DC=com
HTTP/redmine.mydomain.com
HTTPS/redmine.mydomain.com
Existing SPN found!
然后分两步创建密钥表:
ktpass -princ HTTP/redmine.mydomain.com@MYDOMAIN.COM -mapuser serviceuser -pass password -ptype KRB5_NT_PRINCIPAL -crypto All -out HTTP_redmine.keytab -mapOp set
ktpass -princ HTTPS/redmine.mydomain.com@MYDOMAIN.COM -mapuser serviceuser -pass password -ptype KRB5_NT_PRINCIPAL -crypto All -in HTTP_redmine.keytab -out HTTPS_redmine.keytab -mapOp set
在第二步中,我从第一步中导入了带有 HTTP SPN 的密钥选项卡。