问题
I would like to be able to disable external authorization for a specific path of my App.
Similiar to this SO: Kubernetes NGINX Ingress: Disable Basic Auth for specific path
Only difference is using an external Auth provider (OAuth via Microsoft Azure) and there is a
This is the path that should be reachable by the public
/MyPublicPath
My ingress.yaml:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: myIngressName
annotations:
nginx.ingress.kubernetes.io/auth-signin: https://externalprovider/oauth2/sign_in
nginx.ingress.kubernetes.io/auth-url: https://externalprovider/oauth2/auth
nginx.ingress.kubernetes.io/auth-request-redirect: https://myapp/context_root/
nginx.ingress.kubernetes.io/auth-response-headers: X-Auth-Request-User, X-Auth-Request-Email, X-Auth-Request-Access-Token, Set-Cookie, Authorization
spec:
rules:
- host: myHostName
http:
paths:
- backend:
serviceName: myServiceName
servicePort: 9080
path: /
Can I have it not hit the https://externalprovider/oauth2/auth url for just that path?
I've tried using ingress.kubernetes.io/configuration-snippet to set auth_basic to value "off" but that appears to be tied to the basic auth directives not the external ones.
回答1:
Because you have already ingress
in place and path is /
there will be no way of disabling the basic auth on your https://externalprovider/oauth2/auth
.
To do that you would need to setup another ingress controller
and configure it to disable basic auth. You can read about Multiple Ingress controllers, and Running Multiple Ingress Controllers.
You can also check this question on Stack Two ingress controller on same K8S cluster
回答2:
My experiment showed that it's not required to have two ingress-controllers
like Crow mentioned in the previous answer, (which would also work perfectly, but requires specification of different ingress-classes
for ingress-controllers
and in the annotations for each Ingress object
).
One Nginx ingress-controller
and two Ingress objects
are just enough to do the trick.
The experiment didn't cover the whole solution: the auth provider wasn't deployed so we'll see auth request only, but for checking Ingress part it's not really necessary.
Here are the details [TL;DR]:
Ingress-controller
was deployed according to the official manual.
Both my1service
and my2service
are forwarding the traffic to the same Nginx Pod.
I also added rewrite-target
annotation because my the destination Pod is serving content on path /
only.
Ingress1:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: myingress1
annotations:
nginx.ingress.kubernetes.io/auth-signin: https://externalprovider/oauth2/sign_in
nginx.ingress.kubernetes.io/auth-url: https://externalprovider/oauth2/auth
nginx.ingress.kubernetes.io/auth-request-redirect: https://myapp/context_root/
nginx.ingress.kubernetes.io/auth-response-headers: X-Auth-Request-User, X-Auth-Request-Email, X-Auth-Request-Access-Token, Set-Cookie, Authorization
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: myhost.com
http:
paths:
- backend:
serviceName: my1service
servicePort: 80
path: /
Ingress2:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: myingress2
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: myhost.com
http:
paths:
- backend:
serviceName: my2service
servicePort: 80
path: /somepath
Applying them to the cluster gives us the following configuration of ingress-controller: (I skipped not important lines from the nginx.conf content)
As we can see here, different set of rules is used for each location, so it's possible to have an auth for some path and skip the auth for another, or even have different auth providers for different locations on the same HTTP host.
ingress-controller's nginx.conf:
$ kubectl exec -n ingress-nginx ingress-nginx-controller-7fd7d8df56-xx987 -- cat /etc/nginx/nginx.conf > nginx.conf
$ less nginx.conf
http {
## start server myhost.com
server {
server_name myhost.com ;
location /somepath {
# this location doesn't use authentication and responds with the backend content page.
set $namespace "default";
set $ingress_name "myingress2";
set $service_name "my2service";
set $service_port "80";
set $location_path "/somepath";
set $proxy_upstream_name "default-my2service-80";
set $proxy_host $proxy_upstream_name;
set $pass_access_scheme $scheme;
}
location = /_external-auth-Lw {
internal;
# this location is used for executing authentication requests
set $proxy_upstream_name "default-my1service-80";
proxy_set_header Host externalprovider;
proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
proxy_set_header X-Original-Method $request_method;
proxy_set_header X-Sent-From "nginx-ingress-controller";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Auth-Request-Redirect https://myapp/context_root/;
set $target https://externalprovider/oauth2/auth;
proxy_pass $target;
}
location @64e7eef73f135f7a304693e85336f805005c5bc2 {
internal;
# this location suppose to return authentication error page
add_header Set-Cookie $auth_cookie;
return 302 https://externalprovider/oauth2/sign_in?rd=$pass_access_scheme://$http_host$escaped_request_uri;
}
location / {
# this location requests for authentication from external source before returning the backend content
set $namespace "default";
set $ingress_name "myingress1";
set $service_name "my1service";
set $service_port "80";
set $location_path "/";
set $balancer_ewma_score -1;
set $proxy_upstream_name "default-my1service-80";
set $proxy_host $proxy_upstream_name;
set $pass_access_scheme $scheme;
set $pass_server_port $server_port;
set $best_http_host $http_host;
set $pass_port $pass_server_port;
set $proxy_alternative_upstream_name "";
# this location requires authentication
auth_request /_external-auth-Lw;
auth_request_set $auth_cookie $upstream_http_set_cookie;
add_header Set-Cookie $auth_cookie;
auth_request_set $authHeader0 $upstream_http_x_auth_request_user;
proxy_set_header 'X-Auth-Request-User' $authHeader0;
auth_request_set $authHeader1 $upstream_http_x_auth_request_email;
proxy_set_header 'X-Auth-Request-Email' $authHeader1;
auth_request_set $authHeader2 $upstream_http_x_auth_request_access_token;
proxy_set_header 'X-Auth-Request-Access-Token' $authHeader2;
auth_request_set $authHeader3 $upstream_http_set_cookie;
proxy_set_header 'Set-Cookie' $authHeader3;
auth_request_set $authHeader4 $upstream_http_authorization;
proxy_set_header 'Authorization' $authHeader4;
set_escape_uri $escaped_request_uri $request_uri;
error_page 401 = @64e7eef73f135f7a304693e85336f805005c5bc2;
}
}
## end server myhost.com
}
Let's test how it all works:
# ingress-controller IP address is 10.68.0.8
# here I requested / path and internal error and 'externalprovider could not be resolved (3: Host not found)'
# error tells us that authentication was required, but auth backend is not available.
# It's expected.
master-node$ curl http://10.68.0.8/ -H "Host: myhost.com"
<html>
<head><title>500 Internal Server Error</title></head>
<body>
<center><h1>500 Internal Server Error</h1></center>
<hr><center>nginx/1.19.1</center>
</body>
</html>
#controller logs:
$ kubectl logs -n ingress-nginx ingress-nginx-controller-7fd7d8df56-xx987
10.68.0.1 - - [21/Jul/2020:13:17:06 +0000] "GET / HTTP/1.1" 502 0 "-" "curl/7.47.0" 0 0.072 [default-my1service-80] [] - - - - 158e2f959af845b216c399b939d7c2b6
2020/07/21 13:17:06 [error] 689#689: *119718 externalprovider could not be resolved (3: Host not found), client: 10.68.0.1, server: myhost.com, request: "GET / HTTP/1.1", subrequest: "/_external-auth-Lw", host: "myhost.com"
2020/07/21 13:17:06 [error] 689#689: *119718 auth request unexpected status: 502 while sending to client, client: 10.68.0.1, server: myhost.com, request: "GET / HTTP/1.1", host: "myhost.com"
10.68.0.1 - - [21/Jul/2020:13:17:06 +0000] "GET / HTTP/1.1" 500 177 "-" "curl/7.47.0" 74 0.072 [default-my1service-80] [] - - - - 158e2f959af845b216c399b939d7c2b6
# Then I sent a request to /somepath and got a reply without necessity
# to provide any auth headers.
$ curl http://10.68.0.8/somepath -H "Host: myhost.com"
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
</body>
</html>
#controller logs show the successful reply:
10.68.0.1 - - [21/Jul/2020:13:18:29 +0000] "GET /somepath HTTP/1.1" 200 612 "-" "curl/7.47.0" 82 0.002 [default-my2service-80] [] 10.68.1.3:80 612 0.004 200 3af1d3d48c045be160e2cee8313ebf42
来源:https://stackoverflow.com/questions/62438259/kubernetes-nginx-ingress-disable-external-auth-for-specific-path