Open acudovs opened 8 years ago
I had similar problem (but I'm using squid for kerberos auth) And my solution was to not authorize with kerberos requests containing session auth (authorization header contains session id as login and "session" as password)
Also be sure that XHR requests generated for server name (not ip). For this web_endpoint_uri should be set to relative (empty string) or http://servername
Could you share your Squid configuration?
The key part is that:
acl with_session_or_token req_header Authorization ^Basic\s.+(OnNlc3Npb24=|p0b2tlbg==)$
acl authenticated proxy_auth REQUIRED
http_access allow with_session_or_token
http_access deny !authenticated
http_access allow all
I'm not sure how to mimic this in the Apache configuration.
For Single Sign-On to works properly user session needs to be authenticated using X-Remote-User header. But if I disable Kerberos for some requests to /api/system/sessions the Apache doesn't add X-Remote-User header, authentication fails and Graylog shows standard login form.
graylog will work with session auth header only
check order of auth providers:
It's true only if you already got the session somehow. I've spent hours trying different configurations. But maybe I just can't catch your point. Do you have spare Apache server to test the above configuration yourself? And don't forget to open a browser in incognito mode or you may share some previous session.
Actualy I don't want to run Apache :) But my point is that you need to pass X-Remote-User header only until session will be created. After that you will have session auth and you no longer need Kerberos auth. Also it is important to have graylog WEB and graylog REST on same address.
You are just right! I need to create initial session by passing the X-Remote-User header with correct Kerberos user principal in this header but I can't because only Kerberos knows the principal name and it needs to be disabled for the same request. The "chicken or the egg" :) Maybe I should try Squid if it works for you...
But the main problem is that Graylog breaks standard proxy authentication algorithm (including but not limited to Kerberos) by its own unexpected Authorization header.
Yep. Sure graylog auth header is a root problem. But I still can't get a problem. Send X-Remote-User header using Kerberos until graylog will generate auth header. After that X-Remote-User is not needed anymore.
This is what I did with squid config. It checks auth header with session and passes request if header found. Otherwise it makes Kerberos auth and sends X-Remote-User
Myabe the problem is that you sending auth header as undefined:session
?
The undefined:session
is from the Graylog frontend code, when it tries to find out whether it has a valid session or not.
I'm not sure what you mean by the auth header being the root problem, Graylog is using Basic auth, and has always done that. The SSO plugin only creates a Graylog session based on the externally set trusted headers and does not change anything else about the authentication mechanism.
From my limited Kerberos knowledge, the client needs to follow a few steps to get a valid Kerberos ticket, in which case the client is the Graylog web interface code running in the browser. We assume Basic auth and this is unlikely to change, to be honest.
Kerberos works as expected, there is no problem with tickets. But Graylog's Basic auth breaks Kerberos auth as both rely on Authorization header. So, technically SSO plugin can't be used for SSO with Apache + Kerberos. At least, until some workaround is found.
Ah, then I misunderstood. So Kerberos is relying on being able to use the Authentication
header for itself?
Sure! But not only Kerberos. As soon as "Require valid-user" added to Apache
Ok, I see. As this is something that needs to changed in Graylog server, I don't think we will be able to do anything about it before 3.0.
Squid could be used as workaround. At least it works for me :)
Full working squid3 config:
http_port pub_ip:80 accel
cache_peer 127.0.0.1 parent 80 0 no-query proxy-only
auth_param negotiate program /usr/lib/squid3/negotiate_kerberos_auth -r -s GSS_C_NO_NAME #-d
auth_param negotiate children 10
auth_param negotiate keep_alive on
acl with_session_or_token req_header Authorization ^Basic\s.+(OnNlc3Npb24=|p0b2tlbg==)$
acl authenticated proxy_auth REQUIRED
http_access allow with_session_or_token
http_access deny !authenticated
http_access allow all
request_header_access X-Remote-User deny all
request_header_add X-Remote-User "%ul" authenticated
request_header_add X-Graylog-Server-URL "http://%{Host}>h" all
@kroepke, I see you have added this to the 2.2.0 milestone. How do you plan to cope with this issue? Are you changing the process of session creation, e.g. by stopping to use the Authorization header?
It is possible to use Kerberos SSO with nginx with some trickery in the config file, and the same may be possible with Apache. This snippet of nginx config works for me:
# Set a variable $passthru_authorization to the original value of any Basic Authorization
# header. We do this because the ngx_http_auth_spnego_module may later overwrite the value!
map $http_authorization $passthru_authorization {
default "";
"~(?<auth_header_capture>Basic .*)" $auth_header_capture;
}
server {
# put your server directives here
# ...
location / {
# a trick using fake error codes above 418 to perform internal redirects
# to named locations
error_page 463 = @graylog_no_auth;
error_page 464 = @graylog_with_auth;
# Check if the request has Basic auth with username="undefined",
# password="session". this is the first auth-related request from a
# logged-out client, with an undefined session token
if ($http_authorization = "Basic dW5kZWZpbmVkOnNlc3Npb24=") {
# We want to apply Kerberos authentication to this request,
# so that the request that reaches Graylog has the Remote-User
# header and the client obtains a proper session token to use
# in future requests
return 464;
}
# Check if the client sent a session or API token using Basic auth.
# If they have, we should pass it to Graylog without triggering
# Kerberos auth, as Graylog should accept it.
# These possible matches are the different possible base64
# representations of ":session" or ":token" at the end of the
# Authorization header
if ($http_authorization ~ ".+(6c2Vzc2lvbg==|OnNlc3Npb24=|pzZXNzaW9u|p0b2tlbg==|6dG9rZW4=|OnRva2Vu)$") {
return 463;
}
# If there is no session or API token, trigger Kerberos auth.
if ($http_authorization !~ ".+(6c2Vzc2lvbg==|OnNlc3Npb24=|pzZXNzaW9u|p0b2tlbg==|6dG9rZW4=|OnRva2Vu)$") {
return 464;
}
}
location @graylog_with_auth {
# These are the directives which require Kerberos authentication
auth_gss on;
auth_gss_keytab /etc/nginx/krb5.keytab;
# Don't try and use Basic auth credentials to log in to Kerberos
auth_gss_allow_basic_fallback off;
# Pass the real IP to Graylog server
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Since in this location we require Kerberos auth, we should have
# a valid remote user to pass to the Graylog server, which should
# trust it implicitly and log the user in.
proxy_set_header Remote-User $remote_user;
# The ngx_http_auth_spnego_module sets a fake Authorization header,
# remove it as it'll probably confuse the Graylog server
proxy_set_header Authorization "";
# Proxy to Graylog server, assuming it's running on localhost port 9000
proxy_pass http://127.0.0.1:9000;
}
location @graylog_no_auth {
# Pass the real IP to Graylog server
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Clear the Remote-User header; we aren't doing any SSO in this location
proxy_set_header Remote-User "";
# Pass through Basic Authorization header from the client,
# as it contains Graylog session or API token
proxy_set_header Authorization $passthru_authorization;
# Proxy to Graylog server, assuming it's running on localhost port 9000
proxy_pass http://127.0.0.1:9000;
}
}
The key thing is to enable or disable Kerberos auth based on the type of Basic auth presented by the client. If the client presents Basic auth with a password of "session" or "token", that means the client is trying to use Graylog session or token-based authentication, with the token in the username, and Kerberos authentication shouldn't be enabled/required. However an exception to that rule is if the username is "undefined" - that's a sign that the client is logged out and so Kerberos authentication should be enabled for that request, to sign them in. After that request, the client should obtain a valid session token, use that for future requests, and no longer require Kerberos auth until their session expires.
This is still a bug. Any chance graylog can move away from misusing the Authorization header?
We will deprecate and remove this plugin in the near future, it was never a good idea in the first place, and as you note its implementation is flawed. For a replacement we need to rework some intervals though and that process is not finished yet. Sorry for the inconvenience.
The idea was good, and with the workarounds it works great. I hope it returns without the need for workarounds.
@kroepke I'm not sure you are understanding the issue. There is nothing inherently wrong with the graylog-plugin-auth-sso plugin.
The issue is that Graylog itself (even when the graylog-plugin-auth-sso plugin is disabled) is mis-using the Authorization header for its own session management. If that internal session handling was moved to a header such as "AuthorizationGraylogSession" instead of "Authorization" there would be no issue.
This misuse of the Authorization header interferes with Kerberos implementations that are outside of both graylog and the graylog-plugin-auth-sso plugin.
Kerberos Single Sign-On does not work
I've tried to setup Kerberos Single Sign-On to Graylog 2.1 on my Apache HTTP Server proxy.
My current Apache HTTP Server proxy configuration:
First of all I've created user admin@EXAMPLE.COM via Graylog WEB UI /system/authentication/users and configured SSO Plugin /system/authentication/config/sso to trust X-Remote-User HTTP header.
To test SSO plugin works as expected I've added static header to my configuration:
With the above configuration I always login as admin@EXAMPLE.COM without prompting for password.
So, the Kerberos part uses mod_auth_gssapi https://github.com/modauthgssapi/mod_auth_gssapi
With the above configuration Apache HTTP Server authenticates me as admin@EXAMPLE.COM but Graylog API session is not authorized
Request headers:
Response headers:
Seems like request to /api/system/sessions breaks Kerberos auth (header WWW-Authenticate: Negotiate) by adding HTTP header "Authorization: Basic dW5kZWZpbmVkOnNlc3Npb24=".
Environment