2

I have two services in Kubernetes which are exposed through nginx controller. Service a wants to invoke content on domain b but at the same time both services need to be authenticated through Google using the oauth-proxy service.

So I have managed to enable CORS and a can invoke b without any issues. But the problem is when I include the authentication as well, I am constantly getting:

Access to manifest at 'https://accounts.google.com/o/oauth2/auth?access_type=offline&approval_prompt=force&client_id=<obscured>.apps.googleusercontent.com&redirect_uri=https%3A%2F%2Fa.example.com%2Foauth2%2Fcallback&response_type=code&scope=profile+email&state=<obscured>manifest.json' (redirected from 'https://a.example.com/manifest.json') from origin 'https://a.example.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Here are the ingresses:

Service a

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
    kubernetes.io/tls-acme: "true"
    nginx.ingress.kubernetes.io/auth-url: "https://$host/oauth2/auth"
    nginx.ingress.kubernetes.io/auth-signin: "https://$host/oauth2/start?rd=$escaped_request_uri"
    nginx.ingress.kubernetes.io/whitelist-source-range: 0.0.0.0/0
  name: a
spec:
  rules:
  - host: a.example.com
    http:
      paths:
      - backend:
          service:
            name: a-svc
            port:
              number: 8080
        path: /
        pathType: Prefix
  tls:
  - hosts:
    - a.example.com
    secretName: a-tls

---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/whitelist-source-range: 0.0.0.0/0
  labels:
    k8s-app: oauth2-proxy
  name: a-oauth
spec:
  rules:
  - host: a.example.com
    http:
      paths:
      - backend:
          service:
            name: oauth2-proxy
            port:
              number: 4180
        path: /oauth2
        pathType: Prefix
  tls:
  - hosts:
      - a.example.com
    secretName: a-oauth-tls

Service b

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
    kubernetes.io/tls-acme: "true"
    nginx.ingress.kubernetes.io/auth-url: "https://$host/oauth2/auth"
    nginx.ingress.kubernetes.io/auth-signin: "https://$host/oauth2/start?rd=$escaped_request_uri"
    nginx.ingress.kubernetes.io/enable-cors: "true"
    nginx.ingress.kubernetes.io/whitelist-source-range: 0.0.0.0/0
  name: b
spec:
  rules:
  - host: b.example.com
    http:
      paths:
      - backend:
          service:
            name: b-svc
            port:
              number: 8080
        path: /
        pathType: Prefix
  tls:
  - hosts:
    - b.example.com
    secretName: b-tls

---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/enable-cors: "true"
    nginx.ingress.kubernetes.io/auth-url: "https://$host/oauth2/auth"
    nginx.ingress.kubernetes.io/auth-signin: "https://$host/oauth2/start?rd=$escaped_request_uri"
    nginx.ingress.kubernetes.io/whitelist-source-range: 0.0.0.0/0
  labels:
    k8s-app: oauth2-proxy
  name: b-oauth
spec:
  rules:
  - host: b.example.com
    http:
      paths:
      - backend:
          service:
            name: oauth2-proxy
            port:
              number: 4180
        path: /oauth2
        pathType: Prefix
  tls:
  - hosts:
      - b.example.com
    secretName: b-oauth-tls

Obviously, there is only one difference between these two and that is the cors annotations nginx.ingress.kubernetes.io/enable-cors: "true" in the service b ingresses.

I am not sure of what is causing the issue but I am guessing that the authentication done against Google in service a is not being passed to the CORS request so that the service b can also be authenticate with the same token/credentials.

What am I doing wrong and how can I resolve this?

sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
Luminance
  • 820
  • 1
  • 10
  • 24

2 Answers2

0

Based on the documentation, it looks like you lack of annotations for using HTTP.

Try to add fragment like this in service configuration file:

nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-methods: "PUT, GET, POST, OPTIONS"
nginx.ingress.kubernetes.io/cors-allow-credentials: "true"
nginx.ingress.kubernetes.io/configuration-snippet: |
   more_set_headers "Access-Control-Allow-Origin: $http_origin";

But it can be a problem with CORS. In such case you should add the following line:

--cors-allowed-origins=["http://*"]

to /etc/default/kube-apiserver or /etc/kubernetes/manifests/kube-apiserver.yaml file (depending on the location your kube-apiserver configuration file).

After that restart kube-apiserver.

See also this similar question.

kkopczak
  • 742
  • 2
  • 8
0

So, it turns out that the whole Kubernetes and Nginx config was correct, so the solution was implementing the usage of the saved cookie on client side when invoking a CORS request to the second service.

Essentially, this was already answered here: Set cookies for cross origin requests

Excerpt from the answer:

Front-end (client): Set the XMLHttpRequest.withCredentials flag to true, this can be achieved in different ways depending on the request-response library used:

  • jQuery 1.5.1 xhrFields: {withCredentials: true}
  • ES6 fetch() credentials: 'include'
  • axios: withCredentials: true
Luminance
  • 820
  • 1
  • 10
  • 24