Istio Oauth2 using GitHub - kubernetes

Hello with Nginx you are able to set the following with annotations:
nginx.ingress.kubernetes.io/auth-url: https://$host/oauth2/auth nginx.ingress.kubernetes.io/auth-signin: https://$host/oauth2/start?rd=https://$host$request_uri
What would be the equivalent of this but for istio?
I'm expecting the logs of OAuth to look like this
GET - "/oauth2/auth" HTTP/1.1
and not this
GET - "/"
I'm getting a 404 on my pages when using Oauth2 GitHub.

Related

How to reflect http method to keycloak resource when using ambassador filter

I'm trying to integrate the ambassador and keycloak, so all my microservices behind the ambassador could be protected by keycloak.
Now I can implement an easy case, by setting the filter + filter policy, say my resource: GET /products/:productId , if the user want to visit this page, ambassador will intercept it and redirect to keycloak login page, the filter policy settings look like:
apiVersion: getambassador.io/v2
kind: FilterPolicy
metadata:
name: keycloak-filter-policy
namespace: ambassador
spec:
rules:
- host: "*"
path: /product/:productId
filters:
- name: keycloak-filter
namespace: ambassador
arguments:
scopes:
My question is, how could I define policy like: POST /product/:productId ? On Keycloak, I have resource + policies such as: product:view product:edit how can I translate these resources to Ambassador's filter policies?
To directly answer your question, currently, you cannot add the HTTP method to the FilterPolicy. There is a workaround if you need to define more granular access control based on what you are trying to do with the resource.
For example, if you are using HTTP2 or HTTP3 you can get the method from the request headers. There is a pseudo-header called :method
Link for HTTP spec: https://httpwg.org/specs/rfc7540.html#HttpRequest
Link for Ambassador's Filters Doc: https://www.getambassador.io/docs/edge-stack/latest/topics/using/filters/

Kubernetes Nest CORS Issue

I am running a react project on Kubernetes and I am having both frontend and backend as services in Kubernetes. The backend is running nestjs and graphql.
When I tried to spin it up online by using the following url https://my_backend.mydomain everything went as expected, though I realized that with this architecture the backend will be publicly available.
So I decided to use the internal url of Kubernetes such as http://my_service:my_port, and I got an error: Blocked loading mixed active content. I realized it was for http instead of https, re-configured the url and set up the connection for https://my-service:my_port. Though now I get a: Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource.
My ingress file looks like the following:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-methods: "PUT, GET, POST, OPTIONS"
nginx.ingress.kubernetes.io/cors-allow-headers: "DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization"
nginx.ingress.kubernetes.io/cors-allow-origin: "$http_origin"
nginx.ingress.kubernetes.io/configuration-snippet: |
more_set_headers "Content-Security-Policy: https://cdn.jsdelivr.net:* https://*.rsms.me:* https://rsms.me:* always";
more_set_headers "Access-Control-Allow-Origin: *";
spec:
...
Am I mistaken somewhere? I could not find that much regarding Kubernets+NestJs+CORS. I keep ending up in documentation that says to add "Access-Control-Allow-Origin: *". But apparently that does not much with my configuration.

Is having an HTTP service as an external authorization service supported in istio?

I have seen example for EnvoyFilter in ISTIO where grpc_service is supported as filterconfig for external service call out.
kind: EnvoyFilter
metadata:
name: ext-authz
namespace: istio-system
spec:
filters:
- insertPosition:
index: FIRST
listenerMatch:
listenerType: SIDECAR_INBOUND
listenerProtocol: HTTP
filterType: HTTP
filterName: "envoy.ext_authz"
filterConfig:
grpc_service:
google_grpc:
target_uri: 127.0.0.1:9191
stat_prefix: "ext_authz"
But I want to use my external service as filterconfig using http_service instead of grpc_service but everytime I get 404 not found error.
Is http_service supported as filterConfig in Istio's envoyFilter?
version info : GKE is 14 and istio is 1.1.17
Update: modified entire answer.
After further verification it appears that Istio had http_service authorization service in the past it was not fully functional.
There were attempts to implement external HTTP service authorization for older versions of Istio, however it did work and the only workaround solutions were to use http lua filter or Nginx-Ingress Controller as Ingress Gateway that delegates the authentication part.
All of above cases can be found in this github issue. The HTTP call was successful but the headers were not being passed.
Here is another attempt in running http_service as authorization service.
As You noticed the Envoy documentation for Envoy 1.11.0 http_service filterConfig has different syntax. Therefore I suggest trying the configuration for filter from the github issue. And if It doesnt't work, try the http lua filter as a workaround.
The HTTP service as an external authorization service its not mentioned in Istio documentation so, I think its safe to say its not fully supported.

How do I forward headers to different services in Kubernetes (Istio)

I have a sample application (web-app, backend-1, backend-2) deployed on minikube all under a JWT policy, and they all have proper destination rules, Istio sidecar and MTLS enabled in order to secure the east-west traffic.
apiVersion: authentication.istio.io/v1alpha1
kind: Policy
metadata:
name: oidc
spec:
targets:
- name: web-app
- name: backend-1
- name: backend-2
peers:
- mtls: {}
origins:
- jwt:
issuer: "http://myurl/auth/realms/test"
jwksUri: "http://myurl/auth/realms/test/protocol/openid-connect/certs"
principalBinding: USE_ORIGIN
When I run the following command I receive a 401 unauthorized response when requesting the data from the backend, which is due to $TOKEN not being forwarded to backend-1 and backend-2 headers during the http request.
$> curl http://minikubeip/api "Authorization: Bearer $TOKEN"
Is there a way to forward http headers to backend-1 and backend-2 using native kubernetes/istio? Am I forced to make application code changes to accomplish this?
Edit:
This is the error I get after applying my oidc policy. When I curl web-app with the auth token I get
{"errors":[{"code":"APP_ERROR_CODE","message":"401 Unauthorized"}
Note that when I curl backend-1 or backend-2 with the same auth-token I get the appropriate data. Also, there is no other destination rule/policy applied to these services currently, policy enforcement is on, and my istio version is 1.1.15.
This is the policy I am applying:
apiVersion: authentication.istio.io/v1alpha1
kind: Policy
metadata:
name: default
namespace: default
spec:
# peers:
# - mtls: {}
origins:
- jwt:
issuer: "http://10.148.199.140:8080/auth/realms/test"
jwksUri: "http://10.148.199.140:8080/auth/realms/test/protocol/openid-connect/certs"
principalBinding: USE_ORIGIN
should the token be propagated to backend-1 and backend-2 without any other changes?
Yes, policy should transfer token to both backend-1 and backend-2
There is a github issue , where users had same issue like You
A few informations from there:
The JWT is verified by an Envoy filter, so you'll have to check the Envoy logs. For the code, see https://github.com/istio/proxy/tree/master/src/envoy/http/jwt_auth
Pilot retrieves the JWKS to be used by the filter (it is inlined into the Envoy config), you can find the code for that in pilot/pkg/security
And another problem with that in stackoverflow
where accepted answer is:
The problem was resolved with two options: 1. Replace Service Name and port by external server ip and external port (for issuer and jwksUri) 2. Disable the usage of mTLS and its policy (Known issue: https://github.com/istio/istio/issues/10062).
From istio documentation
For each service, Istio applies the narrowest matching policy. The order is: service-specific > namespace-wide > mesh-wide. If more than one service-specific policy matches a service, Istio selects one of them at random. Operators must avoid such conflicts when configuring their policies.
To enforce uniqueness for mesh-wide and namespace-wide policies, Istio accepts only one authentication policy per mesh and one authentication policy per namespace. Istio also requires mesh-wide and namespace-wide policies to have the specific name default.
If a service has no matching policies, both transport authentication and origin authentication are disabled.
Istio supports header propagation. Probably didn't support when this thread was created.
You can allow the original header to be forwarded by using forwardOriginalToken: true in JWTRules or forward a valid JWT payload using outputPayloadToHeader in JWTRules.
Reference: ISTIO JWTRule documentation

NGINX ingress auth-url returning 404 but the endpoint exists

Adding the annotation:
annotations:
nginx.ingress.kubernetes.io/auth-url: http://my-auth-service.my-api.svc.cluster.local:8080
...to my ingress rule causes a 500 response from the ingress controller (the ingress works without it).
The service exists and I can ssh into the ingress controller and CURL it, getting a response:
curl http://my-auth-service.my-api.svc.cluster.local:8080 Produces a 200 response.
I checked the ingress controller logs but it says that the service returned a 404. If I can CURL to the same URL why would it return a 404?
2019/07/01 20:26:11 [error] 558#558: *443367 auth request unexpected status: 404 while sending to client, client: 192.168.65.3, server: localhost, request: "GET /mocks HTTP/1.1", host: "localhost"
I'm not sure what to check to deterine the problem.
FWIW, for future readers - I ran into the same problem, and after looking at my auth service logs, noticed nginx ingress' requests were appending a /_external-auth-xxxxxx path to the request url.
Here's where the ingress controller does it, in the source:
https://github.com/kubernetes/ingress-nginx/blob/master/internal/ingress/controller/template/template.go#L428
And how I'm handling it in my own auth service (a Elixir/Phoenix route):
get "/_external-auth*encoded_nginx_auth_url", TokenController, :index
Here are the options you should check:
Global External Authentication
According to this documentation:
By default the controller redirects all requests to an existing
service that provides authentication if global-auth-url is set in the
NGINX ConfigMap. If you want to disable this behavior for that
ingress, you can use enable-global-auth: "false" in the NGINX
ConfigMap. nginx.ingress.kubernetes.io/enable-global-auth: indicates
if GlobalExternalAuth configuration should be applied or not to this
Ingress rule. Default values is set to "true".
Server Name Indication
Check your proxy_ssl_server_name setting in nginx. It indicates if HTTPS uses SNI or not and it is set to false by default.
Please let me know if that helped.