Zabbix HTTP authentication with Keycloak-proxy - authentication

I'm try to integrate Zabbix UI with Keycloak SSO, using keycloak-proxy.
My setup is the following:
Nginx is the entry point: it handles the "virtual host", forwarding the requests to keycloak-proxy.
Keyclock-proxy is configured with client_id, client_secret, etc. to authenticate the users to Keycloak;
Zabbix dashboard on Apache, default setup: I enable the HTTP authentication.
I've created a test user both in Keycloak and Zabbix.
The authentication flow is ok: I'm redirected to KeyCloak, I do the authentication, but I always get "Login name or password is incorrect." from Zabbix UI.
What am I doing wrong?
Has anyone tried to use OIDC authentication with Zabbix?
I'm using Zabbix 4.0, KeyCloak 4.4, Keycloak-proxy 2.3.0.
keycloak-proxy configuration:
client-id: zabbix-client
client-secret: <secret>
discovery-url: http://keycloak.my.domain:8080/auth/realms/myrealm
enable-default-deny: true
enable-logout-redirect: true
enable-logging: true
encryption_key: <secret>
listen: 127.0.0.1:10080
redirection-url: http://testbed-zabbix.my.domain
upstream-url: http://a.b.c.d:80/zabbix
secure-cookie: false
enable-authorization-header: true
resources:
- uri: /*
roles:
- zabbix

Zabbix expects PHP_AUTH_USER (or REMOTE_USER or AUTH_USER) header with the username, but keycloak-proxy doesn't provide it. Let's use email as a username (you can use any claim from the access token in theory). Add email to the request header in the keycloak-proxy config:
add-claims:
- email
And create PHP_AUTH_USER variable from email header in the Zabbix Apache config:
SetEnvIfNoCase X-Auth-Email "(.*)" PHP_AUTH_USER=$1
Note: Conf syntax can be incorrect because it is off the top of my head - it may need some tweaks.
BTW: there is a (hackish) user patch available - https://support.zabbix.com/browse/ZBXNEXT-4640, but keycloak-gatekeeper is a better solution
For the record: keycloak-proxy = keycloak-gatekeeper (the project was renamed and migrated to keycloak org recently)

Related

Mlflow authorization with spnego

I saw this topic about Kerberos authntication - https://github.com/mlflow/mlflow/issues/2678 . It was in 2020 . Our team trying to do authentication with kerberos by spnego. We did spnego on nginx server and it is fine - and get code 200 when we do curl to mlflow http uri . BUT we can't do it with mlflow environment variable .
The question is - Does mlflow has some feature to make authentication with spnego or not? Or it has just these environment variables for authentication and such methods :
MLFLOW_TRACKING_USERNAME and MLFLOW_TRACKING_PASSWORD - username and password to use with HTTP Basic authentication. To use Basic authentication, you must set both environment variables .
MLFLOW_TRACKING_TOKEN - token to use with HTTP Bearer authentication. Basic authentication takes precedence if set.
MLFLOW_TRACKING_INSECURE_TLS - If set to the literal true, MLflow does not verify the TLS connection, meaning it does not validate certificates or hostnames for https:// tracking URIs. This flag is not recommended for production environments. If this is set to true then MLFLOW_TRACKING_SERVER_CERT_PATH must not be set.
MLFLOW_TRACKING_SERVER_CERT_PATH - Path to a CA bundle to use. Sets the verify param of the requests.request function (see https://requests.readthedocs.io/en/master/api/). When you use a self-signed server certificate you can use this to verify it on client side. If this is set MLFLOW_TRACKING_INSECURE_TLS must not be set (false).
MLFLOW_TRACKING_CLIENT_CERT_PATH - Path to ssl client cert file (.pem). Sets the cert param of the requests.request function (see https://requests.readthedocs.io/en/master/api/). This can be used to use a (self-signed) client certificate.
I looked at the source code. No, the mlflow.utils.rest_utils.http_request function doesn't support SPNEGO in any way – it can only send HTTP 'Basic' or 'Bearer' authorization headers.
However, it should be relatively easy to change it to generate a 'Negotiate' header using pyspnego, or even to use requests-gssapi given that it already uses Requests internally:
# For Linux:
import requests_gssapi
# For Windows:
#import requests_negotiate_sspi
def http_request(...):
...
if not auth_str:
# For Linux:
kwargs["auth"] = requests_gssapi.HTTPSPNEGOAuth()
# For Windows:
#kwargs["auth"] = requests_negotiate_sspi.HttpNegotiateAuth()
...

Keycloak Gatekeeper Configuration Error "unable to exchange code for access token"

I have a problem using keycloak gatekeeper for authorizing requests in a kubernetes cluster. A resource request is forwarded to login via keycloak, after login it is shown that access is forbidden using the gatekeepers forbidden page. The gatekeeper log looks like this:
{"level":"info","ts":1608128659.3984604,"msg":"keycloak proxy service starting","interface":":3000"}
{"level":"error","ts":1608128667.3914142,"msg":"no session found in request, redirecting for authorization","error":"authentication session not found"}
{"level":"info","ts":1608128667.3915262,"msg":"client request","latency":0.002089839,"status":307,"bytes":95,"client_ip":"192.168.42.129:48724","method":"GET","path":"/auth/"}
{"level":"info","ts":1608128667.4082289,"msg":"client request","latency":0.000065187,"status":307,"bytes":317,"client_ip":"192.168.42.129:48724","method":"GET","path":"/oauth/authorize"}
{"level":"error","ts":1608128671.970435,"msg":"unable to exchange code for access token","error":"unknown_error"}
{"level":"info","ts":1608128671.9705727,"msg":"client request","latency":0.203322612,"status":403,"bytes":2174,"client_ip":"192.168.42.129:48724","method":"GET","path":"/oauth/callback"}
I used a configuration similar to https://gist.github.com/carlosedp/80ea54104cc6303f04b3755033f9c4fe.
Is my redirect address maybe wrong, or is about the resource part in the configuration file?
The config file looks like this:
discovery-url: http://keycloak.192.168.42.129.nip.io/auth/realms/local/.well-known/openid-configuration
skip-openid-provider-tls-verify: true
client-id: gatekeeper
client-secret: XXX
listen: :3000
enable-refresh-tokens: true
tls-cert:
tls-private-key:
redirection-url: http://sb.192.168.42.129.nip.io
secure-cookie: false
encryption-key: XXX
upstream-url: http://127.0.0.1:5000/
forbidden-page: /html/access-forbidden.html
upstream-keepalives: true
skip-upstream-tls-verify: true
enable-logging: true
enable-json-logging: true
enable-encrypted-token: false
resources:
- uri: /*

How to set custom headers with Keycloak Gatekeeper?

I have Keycloak and Keycloak-Gatekeeper set up in OpenShift and it's acting as a proxy for an application that is running.
The application that Keycloak Gatekeeper is proxying requires a custom cookie to be set so I figured I could use the Gatekeeper's custom header configuration to set this however I'm running into issues.
Configuration looks like:
discovery-url: https://keycloak-url.com/auth/realms/MyRealm
client-id: MyClient
client-secret: MyClientSecret
cookie-access-name: my.token
encryption_key: MY_KEY
listen: :3000
redirection-url: https://gatekeeper-url.com
upstream-url: https://app-url.com
verbose: true
resources:
- uri: /home/*
roles:
- MyClient:general-access
headers:
Set-Cookie: isLoggedIn=true
After re-deploying and running through the auth flow, the upstream URL/application is not receiving the custom header. I tried with multiple headers (key/value) but can't seem to get it working or find where that header is being injected in the flow.
I've also checked logs and haven't been able to find anything super useful.
Sample Gatekeeper Config
Gatekeeper Custom Headers Docs
Any suggestions/ideas on how to get this working?
remove Set-Cookie.
Simply add
headers:
isLoggedIn: true

Devise ldap authenticatable returns 401 error

I am making some application in rails in which user needs to be log-in first to see the content. I used devise and ldap_devise_authenticatable to make user log-in through existing LDAP account.
However, when I tried to log in with my account into my application then log-in failure occurs(401 error unauthorized) even though I already have account on ldap.
I am following this tutorial
And following is the screenshot of my ldap server page:
I know the problem is in my ldap configuration file. How can i configure it properly so that my application send correct string to ldap server like in above screenshot
Code of my ldap.yml is as follows:
authorizations: &AUTHORIZATIONS
group_base: ou=groups,dc=test,dc=com
required_groups:
- cn=admins,ou=groups,dc=test,dc=com
- cn=users,ou=groups,dc=test,dc=com
- ["moreMembers", "cn=users,ou=groups,dc=test,dc=com"]
require_attribute:
objectClass: inetOrgPerson
authorizationRole: postsAdmin
## Environment
development:
host: 172.16.100.6
port: 389
attribute: cn
base: ou=People,dc=iitj,dc=ac,dc=in
#admin_user: cn=admin,dc=test,dc=com
#admin_password: admin_password
ssl: false
Have you tried setting attribute: sAMAccountName?
Also you need to set admin_ser and admin_password to match the credentials of the account you have in LDAP.

Spring security ldap authenticate first

I have set up an ldap authentication using the following configuration. I just need to user to authenticate to the LDAP data store, then have their session get an authentication token. From reading the docs, this is what I am thinking is supposed to happen:
Authenticate as the manager, find the users full dn based on search criteria
Attempt to bind as the user (using their full dn) and the provided password
The logs dont seem to give enough information as to why this is failing. It just says invalid credentials - when I know they are valid. My thoughts are one of the following is happening:
The users full DN is not being found, and they are just being authenticated with the username
It is trying to do a password compare, vs actually trying to bind to the directory
Configuration:
<ldap-server
url="ldap://adapps.company.com:389/dc=company,dc=com"
manager-dn="cn=fulluserdn,dc=company,dc=com"
manager-password="password"/>
<ldap-user-service user-search-base="" user-search-filter="(samaccountname={0})"/>
<authentication-manager>
<ldap-authentication-provider user-search-filter="(samaccountname={0})" user-search-base="dc=company,dc=com"/>
</authentication-manager>
Error logs:
[DEBUG,FilterBasedLdapUserSearch] Searching for user 'test', with user search [ searchFilter: '(samaccountname={0})', searchBase: 'dc=company,dc=com', scope: subtree, searchTimeLimit: 0, derefLinkFlag: false ]
[DEBUG,AbstractContextSource] Got Ldap context on server 'ldap://adapps.company.com:389/dc=company,dc=com'
[INFO,SpringSecurityLdapTemplate] Ignoring PartialResultException
[DEBUG,XmlWebApplicationContext] Publishing event in Root WebApplicationContext: org.springframework.security.authentication.event.AuthenticationFailureBadCredentialsEvent[source=org.springframework.security.authentication.UsernamePasswordAuthenticationToken#488b5f0b: Principal: test; Password: [PROTECTED]; Authenticated: false; Details: org.springframework.security.web.authentication.WebAuthenticationDetails#fffd148a: RemoteIpAddress: 127.0.0.1; SessionId: 0718B7EED3F930C63C03DA97C4344CBD; Not granted any authorities]
[DEBUG,UsernamePasswordAuthenticationFilter] Authentication request failed: org.springframework.security.authentication.BadCredentialsException: Bad credentials
[DEBUG,UsernamePasswordAuthenticationFilter] Updated SecurityContextHolder to contain null Authentication
[DEBUG,UsernamePasswordAuthenticationFilter] Delegating to authentication failure handlerorg.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler#395158
[DEBUG,TokenBasedRememberMeServices] Interactive login attempt was unsuccessful.
[DEBUG,TokenBasedRememberMeServices] Cancelling cookie
The problem was teat the LDAP server was running on a different port, but the normal port was still open.