How to set custom headers with Keycloak Gatekeeper? - http-headers

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

Related

Kubernetes ingress custom JWT authentication cache key

We are leveraging Kubernetes ingress with external service JWT authentication using auth-url as a part of the ingress.
Now we want to use the auth-cache-key annotation to control the caching of JWT token. At current our external auth service just respond with 200/401 by looking at the token. All our components are backend micro-services with rest api. Incoming request may not be the UI request. How do we fill in the `auth-cache-key' for a JWT token coming in.
annotations:
nginx.ingress.kubernetes.io/auth-url: http://auth-service/validate
nginx.ingress.kubernetes.io/auth-response-headers: "authorization"
nginx.ingress.kubernetes.io/auth-cache-key: '$remote_user$http_authorization'
nginx.ingress.kubernetes.io/auth-cache-duration: '1m'
kubernetes.io/ingress.class: "nginx"
Looking at the example, $remote_user$http_authorization is specified as an example in K8s documentation. However not sure if $remote_user will be set in our case. Because this is not external basic auth. How do we decide on the auth cache key in case of this?
Not enough example/documentations exists around this.
Posting general answer as no further details and explanation provided.
It's true that there is not so much documentation around, so I decided to dig into NGINX Ingress source code.
The value set in annotation nginx.ingress.kubernetes.io/auth-cache-key is a variable $externalAuth.AuthCacheKey in code:
{{ if $externalAuth.AuthCacheKey }}
set $tmp_cache_key '{{ $server.Hostname }}{{ $authPath }}{{ $externalAuth.AuthCacheKey }}';
set $cache_key '';
As can see, $externalAuth.AuthCacheKey is used by variable $tmp_cache_key, which is encoded to base64 format and set as variable $cache_key using lua NGINX module:
rewrite_by_lua_block {
ngx.var.cache_key = ngx.encode_base64(ngx.sha1_bin(ngx.var.tmp_cache_key))
}
Then $cache_key is used to set variable $proxy_cache_key which defines a key for caching:
proxy_cache_key "$cache_key";
Based on the above code, we can assume that we can use any NGINX variable to set nginx.ingress.kubernetes.io/auth-cache-key annotation. Please note that some variables are only available if the corresponding module is loaded.
Example - I set following auth-cache-key annotation:
nginx.ingress.kubernetes.io/auth-cache-key: '$proxy_host$request_uri'
Then, on the NGINX Ingress controller pod, in the file /etc/nginx/nginx.conf there is following line:
set $tmp_cache_key '{my-host}/_external-auth-Lw-Prefix$proxy_host$request_uri';
If you will set auth-cache-key annotation to nonexistent NGINX variable, the NGINX will throw following error:
nginx: [emerg] unknown "nonexistent_variable" variable
It's up to you which variables you need.
Please check also following articles and topics:
A Guide to Caching with NGINX and NGINX Plus
external auth provider results in a lot of external auth requests

I am getting CORS error when calling grail api from angular front end

I am having a grails api which is hosted in azure. Below is the configuration of application in application.yml
grails:
cors:
enabled: true
allowedHeader: ["Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"]
allowedMethods: [GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS]
maxAge: 3600
allowedOrigins: "*"
When running locally it is working just fine but when i deploy it to azure and call any api ,it gives me CORS error.
Any help/suggestion is welcome.
Thanks
I think you add the config in the wrong format. You can try this:
grails:
cors:
enabled: true

Setting an Authorization header after a ForwardAuth in Traefik

I'm moving from Nginx to Traefik as the reverse-proxy of a Docker Swarm.
Currently, each request coming with a Bearer Token is sent to an authentication service (microservice running in the Swarm) which sends back a JWT when auth is correct. I then need to use this JWT in the Authorization header to the request can be sent to the service it targets.
The current setup with Nginx:
auth_request /auth;
auth_request_set $jwt $upstream_http_jwt;
proxy_set_header "Authorization" "jwt $jwt";
Can this approach be done with Traefik ForwardAuth directly or do I have to add a middleware to create this header once the request has been authenticated ?
This is possible if your authentication service can return the JWT in the Authorization header of its response. Set the authResponseHeaders option of the ForwardAuth middleware to Authorization.
The authResponseHeaders option is the list of headers to copy from the authentication server response and set on forwarded request, replacing any existing conflicting headers.
E.g.
http:
middlewares:
auth:
forwardAuth:
address: "http://your_auth_server/auth"
authResponseHeaders:
- "Authorization"

Spring cloud config git refreshRate behaviour

I am trying to setup Spring Cloud Config Server and want to enable auto refresh of properties based on changes to the backing git repository.
Below is the bootstrap.yml of the server.
server:
port: 8080
spring:
application:
name: my-configserver
cloud:
config:
server:
bootstrap: true
git:
uri: /Users/anoop/Documents/centralconfig
refreshRate: 15
searchPaths: {application}/properties
bus:
enabled: true
As per the documentation spring.cloud.config.server.git.refreshRate determines
how often the config server will fetch updated configuration data from
your Git backend
I see that the config clients are not notified of changes, when the configuration changes. I have not configured a git hook for this and was hoping that just setting the property would do the job.
Anoop
Since you have configured the refreshRate property, whenever config client (other applications) call config server to fetch properties (this happens when either the application starts or application calls /actuator/refresh endpoint), they will get properties which were fetched 15 seconds (your refreshRate) old.
By default the refreshRate property is set to 0, meaning any time client applications ask for property config server will fetch latest from GIT.
I don't think there is any property which lets your client apps get notified in case of change/commits in the GIT. This is something your app needs to do by calling actuator/refresh endpoint. This can be done programmatically using some scheduler (though I wouldn't recommend that).
By default, the config client just reads the properties in git repo at startup and not again.
You can actually have a way to workaround by force bean to refresh its configuration from the config server.
First, you need to add #RefreshScope annotation in the bean where config needs to be reloaded.
Second, enable spring boot actuator in application.yml of config client.
# enable dynamic configuration changes using spring boot actuator
management:
endpoints:
web:
exposure:
include: '*'
And then config a scheduled job (by using #Scheduled annotation with fixedRate,...). Of course, fixedRate should conform with refreshRate from config server.
And inside that job, it will execute the request as below:
curl -X POST http://username:password#localhost:8888/refresh
Then your config client will be notified changes in config repo every fixRate interval.
The property spring.cloud.config.server.git.refreshRate is configured in the Config Server and controls how frequently it is going to pull updates, if any, from Git. Otherwise, the Config Server's default behaviour is to connect to the Git repo only when some client requests its configuration.
Git Repo -> Config Server
It has no effect in the communication between the Config Server and its clients.
Config Server -> Spring Boot app (Config Server clients)
Spring Boot apps built with Config Server clients pull all configuration from the Config Server during their startup. To enable them to dynamically change the initially loaded configuration, you need to perform the following steps in your Spring Boot apps aka Config Server clients:
Include Spring Boot Actuator in the classpath, for example using Gradle:
implementation 'org.springframework.boot:spring-boot-starter-actuator'
Enable the actuator refresh endpoint via the management.endpoints.web.exposure.include=refresh property
Annotate the Beans holding the properties in your code with #RefreshScope, for example:
#RefreshScope
#Service
public class BookService {
#Value("${book.default-page-size:20}")
private int DEFAULT_PAGE_SIZE;
//...
}
With the application running, commit some property change into the repo:
git commit -am "Testing property changes"
Trigger the updating process by sending a HTTP POST request to the refresh endpoint, for example (using httpie and assuming your app is running locally at the port 8080:
http post :8080/actuator/refresh
and the response should be something like below indicating which properties, if any, have changed
HTTP/1.1 200
Connection: keep-alive
Content-Type: application/vnd.spring-boot.actuator.v3+json
Date: Wed, 30 Jun 2021 10:18:48 GMT
Keep-Alive: timeout=60
Transfer-Encoding: chunked
[
"config.client.version",
"book.default-page-size"
]

Zabbix HTTP authentication with Keycloak-proxy

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)