Keycloak redirection issue behind proxy (Kong) - nginx

I'm trying to setup a Keycloak instance to handle the users of my webapp. This instance would be, like all others microservices, hidden behind a reverse proxy (Kong, it's a nginx-based proxy).
On my local setup, Kong listens to https://localhost, and keycloak listens to http://localhost:8082/auth.
To achieve that, I used several environment variables on my Keycloak container :
ENV KC_HOSTNAME=localhost
ENV KC_HOSTNAME_PORT=8082
ENV KC_HOSTNAME_STRICT_HTTPS=false
ENV KC_PROXY=edge
ENV PROXY_ADDRESS_FORWARDING=true
ENV KC_HTTP_ENABLED=true
ENV KC_HTTP_PORT=8082
KC_HTTP_RELATIVE_PATH=/auth
The setup of Kong configuration looks fine, and the keycloak endpoints that I need are exposed correctly through Kong (/realms, /js, /resources, /robots.txt, like the doc said). Kong handles the TLS connection, and then speaks to all microservices with HTTP only, thus KC_PROXY=edge. /admin is not exposed, I though I could access this locally using localhost:8082 on the right machine.
If I go to https://localhost/auth/realms/master/.well-known/openid-configuration, I get the configuration. However, Keycloak does not know it's behind Kong, so all endpoints contains localhost:8082. That seems normal, since it's how I set it up in the first place.
I tried to add a new realm with a different Frontend URL, calling it https://myapp.com
Now, my openid configuration contains https://myapp.com:8082/... everywhere. All the workflows get wrongs URLs.
What did I miss ? I cannot remove this port that I put in the first place, otherwise I will not be able to access the admin console.
I thought I could do something with KC_HOSTNAME_ADMIN, but unfortunately there is no KC_HOSTNAME_ADMIN_PORT.. or is there ?
Thank you for reading :)

In case it's of interest to someone, the solution was actually quite simple. I should not have set the HOSTNAME and HOSTNAME_PORT in the first place.
ENV KC_HOSTNAME_STRICT_HTTPS=false is mandatory, and also I needed to add a plugin to Kong to tweak the headers :
plugins
- name: post-function
service: keycloak
config:
functions:
- return function()
if ngx.var.upstream_x_forwarded_port == "8000" then
ngx.var.upstream_x_forwarded_port = 80
elseif ngx.var.upstream_x_forwarded_port == "8443" then
ngx.var.upstream_x_forwarded_port = 443
end
end
Otherwise, keycloak would have the wrong redirect uri in some cases.

Related

Yaws basic auth letsencrypt

I have a domain in stealth mode, protected by basic auth. Basic auth is not supported by Letsencrypt and probably never will (https://github.com/certbot/certbot/issues/1744#issuecomment-162038303).
After moving from Nginx to Yaws, the next Letsencrypt renewal is scheduled. So here is a problem. I could disable basic auth in Yaws, do the renewal and then enable again, but that is no real solution.
There are easy workarounds for Apache and Nginx, i.e. define an exception to basic auth for the directory /.well-known/acme-challenge.
How to do that in Yaws? The basic auth definition for my domain in yaws.conf is now
<auth>
realm = "some realm"
user = "some_user:some_pw"
</auth>
The only reference within this context with respect to Yaws I found is from 2010 and refers to Yaws 1.81 (https://uu.diva-portal.org/smash/get/diva2:344199/FULLTEXT01.pdf). Letsencrypt started 2015. I use Yaws 2.0.9.
There seems to be a solution for FreeDNS with shell variables (https://gist.github.com/ammgws/381b4d9104c4e2b43b9210f33f03a15a). Similar hacks are given at https://github.com/acmesh-official/acme.sh/blob/master/dnsapi/, but I have no idea how to use such an approach.
For each subdirectory you want to exclude, add a .yaws_auth file to that subdirectory with the contents
{allow, all}.
and be sure to include the trailing period/full stop. Also make sure that auth_skip_docroot is either set to false or not set at all in your yaws.conf file.

Stuck with woocommerce_rest_authentication_error: Invalid signature - provided signature does not match

Below issue was posted by me on https://github.com/XiaoFaye/WooCommerce.NET/issues/414 but since this may not be related at all to WooCommerce.Net but on a lowerlevel to Apache/Word/WooCommerc itself I am posting the same question here
I am really stuck with the famous error:
WebException: {"code":"woocommerce_rest_authentication_error","message":"Invalid signature - provided signature does not match.","data":{"status":401}}
FYI:
I have two wordpress instance running. One on my local machine and one on a remote server. The remote server is, as my local machine, in our company's LAN
I am running WAMP on both machines to run Apache and host Wordpress on port 80
The error ONLY occurs when trying to call the Rest api on the remote server. Connecting to the local rest api, the Rest Api/WooCommerceNet is working like a charm :-)
From my local browser I can login to the remote WooCommerce instance without any problem
On the remote server I have defined WP_SITEURL as 'http://[ip address]/webshop/ and WP_HOME as 'http://[ip address]/webshopin wp-config.php
Calling the api url (http://[ip address]/webshop/wp-json/wc/v3/) from my local browser works OK. I get the normal JSON response
Authentication is done through the WooCommerce.Net wrapper which only requires a consumer key, consumer secret and the api url. I am sure I am using the right consumer key and secret and the proper api url http://[ip address]/webshop/wp-json/wc/v3/ (see previous bullet)
I already played around with the authorizedHeader variable (true/false) when instantiating a WooCommerce RestApi but this has no effect
Is there anybody that can point me into the direction of a solution?
Your help will be much appreciated!
In my case, the problem was in my url adress. The URL Adress had two // begin wp-json
Url Before the solution: http://localhost:8080/wordpress//wp-json/wc/v3/
URL Now, and works ok: http://localhost:8080/wordpress/wp-json/wc/v3/
I use with this sentence.
RestAPI rest = new RestAPI(cUrlApi, Funciones.CK, Funciones.CS,false);
WCObject wc = new WCObject(rest);
var lstWooCategorias = await wc.Category.GetAll();
I hope my answer helps you.
Had the same issue. My fault was to define my url incorrect: http:// instead of https://.

OpenShift route accessible from outside the PAAS but not from a client inside the PAAS

Inside the same openshift project, I have an application1 (APP1) in POD1 and another application (APP2) in POD2.
Both these applications are offering REST API services. These 2 applications are accesible using 2 differents openshift route.
Acessing the two applications from outside the PAAS (openshift) is working fine: meaning doing a CURL to APP1/APP2 using openhsift route from a client outside the PAAS is working.
But when APP1 in POD1 is targeeting the REST service offered by APP2 in POD2 using APP2's openshift route. It is failing.
Similarly doing a CURL from APP1's container (using oc rsh) to APP2 using openshift route is failing.
However if APP1 is deployed outside this PAAS, the client call to APP2 using open shift route is working.
Similarly doing a CURL to APP2 using openshift route is working fine from outside the PAAS.
Also if I use service PAAS internal IP/PORT (10.224.x.y), this will solve the issue. But implies to use two different adresses depending if we target APP2 from inside or outside the PAAS.
So the question is how to make an openshift route visible from inside and outside the PAAS?
Or is is there an alternative way to share same hostname/port to access APP2 from inside and outside the PAAS?
You may want to have a look at:
https://docs.openshift.com/container-platform/3.7/architecture/networking/networking.html
For internal communication it is sufficient to use the name of the service (in your case use app1-svc in app2 to communicate with app1).
You can find the name of your service when you visit the routes view - the column "Routes To" shows you the service name.
How services work and how they are configured is explained here in detail:
https://docs.openshift.com/container-platform/3.7/architecture/core_concepts/pods_and_services.html#services

how-to create an insecure jupyter server

Jupyter only allows access from localhost unless I do a bunch of extra security stuff. I am running my server so that it is only accessible on a local network where anyone with access is equal in trustworthiness to localhost. How do I set up a jupyter notebook server with no extra security features?
Based on your question, I expect you want this configuration (in ~/.jupyter/jupyter_notebook_config.py):
c.NotebookApp.ip = '0.0.0.0' # listen on all IPs
c.NotebookApp.token = '' # disable authentication
There are a few security features in Jupyter (as of 4.3.1). I'll go over how to disable each one, and whether/when it makes sense to disable it:
It listens only on localhost. This can be changed to all public IP addresses:
c.NotebookApp.ip = '0.0.0.0'
Listening on public IPs should generally come with enabling HTTPS and/or password or token authentication (docs). If it's all internal on a trusted network where nothing bad ever happens, you can proceed to disable other security features:
Token authentication is enabled by default. To disable it:
c.NotebookApp.token = ''
Disabling authentication means that anyone with access to the host can run code. It seems like this is what you want. You can also enable a password:
In [1]: from notebook.auth import passwd
In [2]: passwd()
Enter password:
Verify password:
Out[2]: 'sha1:67c9e60bb8b6:9ffede0825894254b2e042ea597d771089e11aed'
You can store this in c.NotebookApp.password.
You can also store this password in (~/.jupyter/jupyter_notebook_config.json):
{
"NotebookApp": {
"password": "sha1:67c9e60bb8b6:9ffede0825894254b2e042ea597d771089e11aed"
}
}
Jupyter also has CORS protections, to avoid other websites from being able to access this server. This means that when a user on your network visits example.com, javascript on that page cannot execute code on your notebook server. It sounds like you don't want to touch this, but if you are running a service that should be able to access the notebook server, you can add it to:
c.NotebookApp.allow_origin = 'https://your.other.host'
Finally, Jupyter 4.3.1 introduces an xsrf token, which is part of dealing with the same category of cross-site execution above. You don't need to touch this if users are only accessing the server directly, rather than through javascript on additional websites.
c.NotebookApp.disable_check_xsrf = True
A completely insecure notebook server, which is to say one where any website can run code on it, as long as a browser can connect to its host (this would include localhost or LAN if the browser is running from inside the LAN):
c.NotebookApp.ip = '0.0.0.0' # listen on all IPs
c.NotebookApp.token = '' # disable authentication
c.NotebookApp.allow_origin = '*' # allow access from anywhere
c.NotebookApp.disable_check_xsrf = True # allow cross-site requests
This might be desirable if you are aiming to make compute resources free for the world to use however they want via the notebook API.

Grails - SSL and Spring security core

I would like to have my application running exclusively with SSL turned on.
I am using the Spring Security core plugin.
This is how I attempt to do it in Config.groovy:
grails.plugins.springsecurity.portMapper.httpPort = 8080
grails.plugins.springsecurity.portMapper.httpsPort = 8443
grails.plugins.springsecurity.secureChannel.definition = [ '/**' : 'REQUIRES_SECURE_CHANNEL']
I was expecting this to cause redirects every time I would try to access a Url using HTTP.
However, I am never redirected, and can navigate through both HTTP and HTTPS. I may add I am starting my application using grails run-app -https
Am I getting this all wrong ?
Any suggestion is most welcome.
Do you have a custom filterchain declared in your config?
you might need to add 'channelProcessingFilter' to your chain in that case
http://static.springsource.org/spring-security/site/docs/3.0.x/reference/security-filter-chain.html
You can also try using the forceHttps option
grails.plugins.springsecurity.auth.forceHttps = true
You don't have any wildcards, so the definition is literally matching the root URL (/), but nothing below it (/foo). What you want is:
grails.plugins.springsecurity.secureChannel.definition = [ '/**' : 'REQUIRES_SECURE_CHANNEL']
^^
(You can clearly see the wildcards in the documentation :-)
Finally, if your server is behind a load balancer or other firewall that hides the protocol, check that same page for instructions on checking the header.

Resources