SignalR connection via K8S Ingress - asp.net-core

I'm trying to expose a SignalR hub hosted in a Kubernetes (Azure) pod. Basically, the authentication and the handshake steps work fine, but when I trigger some action, all clients connected via the k8s Ingress doesn't receive the message. Has anybody experienced this issue or just have shared SignalR hubs through Kubernetes - Ingress?
ingress.yml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: endpoints
annotations:
kubernetes.io/ingress.class: addon-http-application-routing
ingress.kubernetes.io/ssl-redirect: "false"
nginx.ingress.kubernetes.io/ssl-redirect: "false"
nginx.org/websocket-services: "myservice"
spec:
rules:
- host: api.[MY-DOMAIN].com
http:
paths:
- backend:
serviceName: myservice
servicePort: 80
path: /myservice

Try:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/ssl-redirect: "false"
nginx.ingress.kubernetes.io/affinity: cookie
nginx.ingress.kubernetes.io/session-cookie-hash: sha1
nginx.ingress.kubernetes.io/session-cookie-name: REALTIMESERVERID
I wrote a sample project a while back, if you want a working example: DenisBiondic/RealTimeMicroservices
As a side note, consider using Azure SignalR Service, it should remove many headaches (also in the example above).

Not familiar with SignalR but there could be a couple of things.
The nginx Ingress might be stripping some http headers that SignalR needs. Are you familiar with the http headers that the SignalR is supposed to receive?
After authenticating, is it possible that SignalR hub is trying to speak TLS? I see that you have this running on port 80 with not TLS. You would have to configure something like this:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: endpoints
annotations:
kubernetes.io/ingress.class: addon-http-application-routing
ingress.kubernetes.io/ssl-redirect: "false" <== you may need to remove
nginx.ingress.kubernetes.io/ssl-redirect: "false" <== you may need to remove
nginx.org/websocket-services: "myservice"
spec:
rules:
- host: api.[MY-DOMAIN].com
http:
paths:
- backend:
serviceName: myservice
servicePort: 80
path: /myservice
tls:
- secretName: <your-tls-certs>
Hope it helps!

Related

How can I make one route public in kubernetes ingress with auth-url set?

I am playing a little bit with path-based routing via Kubernetes ingresses (we use Nginx ingress). We have one service up and running behind authentication via external service like the one in the first snippet. This service is already used by other services in our ecosystem, however, as the development progresses, the service now has management API and we need to turn off the authentication for specific paths. According to this answer, this is not possible for basic auth and, according to what I have tried (second snippet), it is not possible for authentication via external service either. Is there any other way to allow specific paths without authentication without completely rearchitecting ingresses and domains/paths?
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: path-based-routing-1
annotations:
kubernetes.io/tls-acme: "true"
kubernetes.io/ingress.class: nginx-external
nginx.ingress.kubernetes.io/auth-url: http://authorizer.dev.svc.cluster.local
spec:
tls:
- hosts:
- 'routing.example.com'
secretName: routing.example.com
rules:
- host: 'routing.example.com'
http:
paths:
- path: /
backend:
serviceName: path-based-routing-1
servicePort: 80
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: path-based-routing-2
annotations:
kubernetes.io/tls-acme: "true"
nginx.ingress.kubernetes.io/auth-type: ""
kubernetes.io/ingress.class: nginx-external
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
tls:
- hosts:
- 'routing.example.com'
secretName: routing.example.com
rules:
- host: 'routing.example.com'
http:
paths:
- path: /management-api
backend:
serviceName: path-based-routing-2
servicePort: 80

keycloak stops working when enabling tls behind nginx ingress controller

I need advice on how to configure nginx ingress controller and keycloak on eks kubernetes with TLS.
My first attempt was to get keycloak working without TLS. This works fine. But when I add TLS to the ingress definition, keycloak gives a Invalid parameter: redirect_uri error.
This is the working sample:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: keycloak-tls-test
namespace: keycloak-tls-test
spec:
rules:
- host: keycloak.test.myhops.com
http:
paths:
- backend:
serviceName: keycloak
servicePort: 80
When I add the tls part, I get the aforementioned error. See yaml file below.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: keycloak-tls-test
namespace: keycloak-tls-test
spec:
tls:
- hosts:
- keycloak.test.myhops.com
secretName: test-myhops-tls
rules:
- host: keycloak.test.myhops.com
http:
paths:
- backend:
serviceName: keycloak
servicePort: 80
Any suggestions on how to solve this? One online suggestion was to add https://keycloak.test.myhops.com/* to the Valid Redirect URL for the security-admin-console client in the master realm. This solved the invalid redirect_uri error, but then I only got blank pages. I could not find hints in the keycloak logging.
I figured out what caused the problem. It seems that when keycloak is used behind a reverse proxy that terminates the TLS, then keycloak needs proxy-address-forwarding to be set. For the docker container this means that the env var PROXY_ADDRESS_FORWARDING=true does the trick. So Ingress was correct and the keycloak deployment needed an extra environment variable.
Please not that ingress-nginx already set the correct headers for this to work:
X-Forwarded-For
X-Forwarded-Proto
Docker documentation
[keycloak documentation2

Paths are not working in Kubernetes NGINX Ingress Controller

I have a Spring Boot application responsible for getting citizens and a NGINX Ingress controller configured with ssl-passthrough to expose my cluster to outside.
When I do:
https://myhostname.com/citizens
It perfectly works. This is the configuration I am using:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nginx-ingress
namespace: default
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/ssl-passthrough: "true"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
rules:
- host: myhostname.com
http:
paths:
- path: /
backend:
serviceName: myservice
servicePort: 443
But I would like to have something like:
https://myhostname.com/myservice/citizens
It would be something similar to math Simple fanout approach that is described in the kubernetes docs:
https://kubernetes.io/docs/concepts/services-networking/ingress/#simple-fanout
Therefore, in my Spring application I have configured a contextPath so when locally I do:
https://localhost:8080/myservice/citizens
I get the desired result
For NGINX I have set up the following:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nginx-ingress
namespace: default
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/ssl-passthrough: "true"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: myhostname.com
http:
paths:
- path: /myservice
backend:
serviceName: myservice
servicePort: 443
What am I doing wrong?
Solution:
I've been researching a little and I've realized that the approach that I was trying to achieve is not possible with ssl-passthrough as the proxy is blind and it doesn't know the path to where route the traffic.
Therefore, the solution would be to use subdomains and not paths, because thanks to the SNI protocol, the NGINX controller will know to which hostname the client is trying to connect.
The final solution would be something similar to this
If your backend is expecting the whole path /myservice/citizens you can just use it to point it to the service without the rewrite-target directive, since it only dictates how URIs are going to be treated in the backend:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nginx-ingress
namespace: default
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/ssl-passthrough: "true"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
rules:
- host: myhostname.com
http:
paths:
- path: /myservice/citizens
backend:
serviceName: myservice
servicePort: 443
Be aware that this assumes that your service is able to redirect requests to 8080, which is your backend listening port, so it has to match it.

oauth2_proxy not asking for authentication

I am trying to setup oauth2_proxy on kubernetes to secure one of my single page application and I am using github as the authentication provider. I found this link useful and I followed this for doing my setup.
[https://alikhil.github.io/2018/05/oauth2-proxy-for-kubernetes-services/]
I have created an application on github and used my DNS Name in place of the HomePageURL and CallBackURL (https://auth.example.com replaced with https://example.com) because I do not have TLS secrets generated for auth.example.com. Rather I have TLS certificates generated for example.com because this domain belongs to me. I was getting error in nginx-controller that the certificate belongs to example.com and not to auth.example.com as these URLs have been used in defining the example Ingress and oauth proxy ingress and this was the basis for me to do the before mentioned chang.
My Ingresses looks like this
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: oauth2-proxy
annotations:
kubernetes.io/tls-acme: "true"
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: example.com
http:
paths:
- backend:
serviceName: oauth2-proxy
servicePort: 4180
path: /oauth2
tls:
- hosts:
- example.com
secretName: oauth-proxy-tls
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: oauth-main-ingress
annotations:
kubernetes.io/ingress.class: nginx
kubernetes.io/tls-acme: "true"
ingress.kubernetes.io/auth-url: https://example.com/oauth2/auth
ingress.kubernetes.io/auth-signin: https://example/oauth2/start?rd=https://$host$request_uri$is_args$args
spec:
rules:
- host: example.com
http:
paths:
- backend:
serviceName: example-service
servicePort: 80
path: /
tls:
- hosts:
- example.com
secretName: tls-secret
I want that whenever I click example.com it should display page for github authentication but in my case its directly giving the response which a service should give after successful authentication. I am not being asked to provide credentials. Also, I am getting error in my ingress controller logs as 7 controller.go:753] Error obtaining Endpoints for Service "default/oauth2-proxy": no object matching key "default/oauth2-proxy" in local store
Also, I tried replacing using nginx.ingress.kubernetes.io/auth-url: http://oauth2-proxy.oauth-proxy.svc.cluster.local:4180/oauth2/auth as mentioned in the link but it did not work for me. Can some one explain why is oauth2_proxy not asking for authentication and ingress is serving the requests directly without asking for authentication?
The annotation declared in the oauth-main-ingress yaml is incorrect.
As per the kubernetes/nginx-ingress documentation the annotation for external auth-url should be
nginx.ingress.kubernetes.io/auth-url: http://<oauth-service-url>
instead of
ingress.kubernetes.io/auth-url: http://<oauth-service-url>

Trouble configuring ssl-redirect on Kubernetes Ingress

I have configured an ingress on a kubernetes cluster from Google Cloud. I followed the instructions as is on this doc.
My manifest:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: web-proxy
annotations:
ingress.kubernetes.io/force-ssl-redirect: "true"
spec:
tls:
- hosts:
- foo.bar.com
secretName: foo-bar-secret
rules:
- host: foo.bar.com
http:
paths:
- backend:
serviceName: foo-bar-service
servicePort: 80
path: /*
From the documentation, it specifies that ssl-redirect
is by default true if tls is configured but it doesn't work. I've also tried to set force-ssl-redirect to true(default is false), still no luck.
I'm confused if there is actually a bug or I'm doing something wrong, because when I run kubectl describe ing web-proxy, it displays that annotations were set:
Annotations:
force-ssl-redirect: true
[...]
Any suggestions?
EDIT 1:
I was using the 1.8.3.gke.0 version but when I upgraded to 1.8.4.gke.0 this seems to have solved the problem.
I'll keep this post updated while I test more annotations(like: nginx.ingress.kubernetes.io/from-to-www-redirect)