My service sits behind Traefik. Traefik protects the service during development using BasicAuth.
Everything works well in the browser. When accessing the service Rest-API I need a POST request header Authorization: ... with a token to authorize the user. I tried:
curl -u "user:pass" http://service.tld/api -H "Authorization: <token>"
But I get a 401 Unauthorized response from Traefik. The traefik logs say:
[...] msg="Authentication failed" middlewareName=...#docker middlewareType=BasicAuth
I suppose the -H header overwrites Traefik's BasicAuth -u "user:pass".
My question: How to make BasicAuth with Traefik and pass the Authorization header to the service?
Related
I have the following use case:
An http backend application running behind an oauth proxy
An OAuth proxy that authenticates users before authorizing access to the backend application
In some cases the application behind the proxy has another authorization method that also needs to be verified.
Accessing through a browser seems to work fine as soon as I'm logged in into the oauth proxy... however, using CLI (i.e: curl) it doesn't work because I need somehow to pass 2 different authorization headers
After some reading I thought about sending 2 headers:
Proxy-Authorization
Authorization
The proxy-authorization needs to be sent to the oauth proxy, and the authorization is sent to the application.
For that I would add an auth-snippet setting the Authorization for the auth-url authentication and set the Authorization with the value of Proxy-Authorization
Something like that:
nginx.ingress.kubernetes.io/auth-signin: https://oauth.mydomain.net/oauth2/start?rd=https://myapplication.mydomain.net
nginx.ingress.kubernetes.io/auth-url: https://oauth.mydomain.net/oauth2/auth
nginx.ingress.kubernetes.io/auth-snippet: |
proxy_set_header Authorization $http_proxy_authorization;
And then set the Authorization to the Authorization header on the configuration-snippet
nginx.ingress.kubernetes.io/configuration-snippet: |
proxy_set_header Authorization "$http_authorization";
Well, it doesn't work, I'm still redirected to the oauth page to login with a 302
I also tried using $proxy_authorization instead of $http_proxy_authorization and tried setting proxy_pass_request_headers on.
Any clue on what I can do to achieve that?
This can be achieved using cookies instead of a dual header:
curl -v -H "Authorization: FOOBAR" -b "_oauth2_proxy=<MYCOOKIE>" https://myapplication.mydomain.net/
I am running Grafana v6.2.4 in kubernetes, using basic auth. I want to use the k8s proxy for testing (i.e. kubectl proxy --port=8080). I have changed the GF_SERVER_ROOT_URL environment variable to:
{
"name": "GF_SERVER_ROOT_URL",
"value": "http://localhost:8080/api/v1/namespaces/my-namespace/services/grafana-prom:80/proxy/"
}
This allows me to log in and use Grafana through my browser at http://localhost:8080/api/v1/namespaces/my-namespace/services/grafana-prom:80/proxy/.
However, I want to use it via the API. If I send a request to http://localhost:8080/api/v1/namespaces/my-namespace/services/grafana-prom:80/proxy/api/dashboards/db I get back
{
"message": "Unauthorized"
}
However, if I set up a kubernetes port forward and send the identical request to http://localhost:30099/api/dashboards/db, then it succeeds.
Is there a different environment variable aside from GF_SERVER_ROOT_URL that I should be changing so that the API server root goes through the k8s proxy, i.e. http://localhost:8080/api/v1/namespaces/my-namespace/services/grafana-prom:80/proxy/api/dashboards/db? I have looked here but couldn't find it.
Otherwise what is the correct way to access the API through the k8s proxy?
I should add that I am specifically trying to use kubetctl proxy as an alternative to kubectl port-forward so I'm hoping to find an alternative to the suggestion here https://stackoverflow.com/a/45189081/1011724
I tried to replicate this in minikube and i might have found the reason for your requests through the API server proxy (using kubectl proxy) not getting authorized correctly.
Running the following curl-command:
curl -H "Authorization: Bearer <TOKEN>" http://localhost:8080/api/v1/namespaces/my-namespace/services/grafana-prom:80/proxy/api/dashboards/home
and using tcpdump to capture the requests in the Pod with tcpdump -vvvs 0 -l -A -i any yielded the following result(s):
GET /api/dashboards/home HTTP/1.1
Host: localhost:8080
User-Agent: curl/7.58.0
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 127.0.0.1, 192.168.99.1
X-Forwarded-Uri: /api/v1/namespaces/my-namespace/services/grafana-prom:80/proxy/api/dashboards/home
This GET request doesn't have the Authorization header (resulting in a 401 Unauthorized) so basically the API server seem to strip this HTTP header as it passes the request down to the Pod.
If i instead use kubectl port-forward -n my-namespace svc/grafana-prom 8080:80 the GET request now looks like this:
GET /api/dashboards/home HTTP/1.1
Host: localhost:8080
User-Agent: curl/7.58.0
Accept: */*
Authorization: Bearer <TOKEN>
When writing this answer i found this issue in the k/k repo #38775, to qoute one of the comments:
this is working as expected. "proxying" through the apiserver will not get you standard proxy behavior (preserving Authorization headers end-to-end), because the API is not being used as a standard proxy
This basically means that kubectl proxy will not work when trying to authorize through it, it's not a "regular" reverse proxy and probably for a good reason won't preserve Authorization headers.
Note that i tested both token and basic authorization using curl although token based auth is used above.
Hopefully this clear things up a bit!
I am currently developing a Mule 4 cloudhub interface that need to consume data coming from a Kerberos Secured API. I am having problems using the HTTP connector to use my keytab to authenticate
I can successfully issue a CURL command to the API but I can't
I have issued this from my machine with the provided keytab
curl -i -v -X GET -H "Accept: application/json" --negotiate -u: http://hdp-master-db.test.edu.au:8080/test_rest/AU
Can you advise on how to go about this?
Thanks
According to the HTTP Connector documentation the HTTP Request supports these four authentication methods:
Basic
OAuth
NT LAN Manager (NTLM)
Digest
It seems that it doesn't support Kerberos.
Problem
I am trying to enable authentication on my kubelet servers using Bearer Tokens (not X.509 client certificate authentication), and fail to understand the workflow.
What I tried
According to the documentation page Kubelet authentication/authorization, starting the kubelet with the --authentication-token-webhook flag enables the Bearer Token authentication. I could confirm that by sending a request to the kubelet REST API using one of the default secrets created by the Controller Manager:
$ MY_TOKEN="$(kubectl get secret default-token-kw7mk \
-o jsonpath='{$.data.token}' | base64 -d)"
$ curl -sS -o /dev/null -D - \
--cacert /var/run/kubernetes/kubelet.crt \
-H "Authorization : Bearer $MY_TOKEN" \
https://host-192-168-0-10:10250/pods/
HTTP/1.1 200 OK
Content-Type: application/json
Date: Fri, 30 Jun 2017 22:12:29 GMT
Transfer-Encoding: chunked
However any communication with the kubelet via the API server (typically using the kubectl logs or exec commands) using the same Bearer Token as above fails with:
$ kubectl --token="$MY_TOKEN" -n kube-system logs \
kube-dns-2272871451-sc02r -c kubedns
error: You must be logged in to the server (the server has asked for the client to provide credentials ( pods/log kube-dns-2272871451-sc02r))
Where I need clarification
My initial assumption was that the API server just passed the Bearer Token it received from the client directly to the kubelet, but my little experiment above proved me otherwise.
I see that the kube-apiserver documentation mentions a flag called --authentication-token-webhook-config-file but I'm unsure how to use it, or if it's even relevant for authenticating the API server against a kubelet.
Current configuration
My kubelet(s) run with:
--anonymous-auth=false
--authorization-mode=Webhook
--authentication-token-webhook
--cadvisor-port=0
--cluster-dns=10.0.0.10
--cluster-domain=cluster.local
--read-only-port=0
--kubeconfig=/etc/kubernetes/kubeconfig-kubelet
--pod-manifest-path=/etc/kubernetes/manifests
--require-kubeconfig
My API server runs with:
--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota,DefaultTolerationSeconds
--anonymous-auth=false
--authorization-mode=AlwaysAllow
(+ tls flags)
When making calls to the API server that require communication from the API server to the kubelet, that communication is done using the API server's client credentials, which only support x509 authentication to the kubelet.
The flags used to give the API server the credentials to use to contact the kubelet are listed in the "X509 client certificate authentication" section of https://kubernetes.io/docs/admin/kubelet-authentication-authorization/
API server webhook authentication options are unrelated to kubelet auth.
I'm trying to download the bits of a Cloud Foundry app using the Cloud Foundry API.
https://apidocs.cloudfoundry.org/236/apps/downloads_the_bits_for_an_app.html
When using a remote blobstore, such as AWS, the response is a redirect to the actual location of the bits. If the client is automatically following redirects, then the OAuth token that was used to communicate with Cloud Controller will be replayed on the new redirect request. Some blobstores may reject the request in that case. Clients may need to follow the redirect without including the OAuth token.
Here is my cURL command I'm attempting to use:
$ curl -L "https://api.my.host.net/v2/apps/my_app_guid/download" -X GET -H "Authorization: bearer myauthtoken"
curl: (7) Failed to connect to dal05.objectstorage.service.networklayer.com port 443: Operation timed out
I'm assuming my issue is that my Auth header bearer token is being sent on the redirect based on the quote from the Cloud Foundry API docs. How can I follow the redirect without the OAuth token? I'm using the default cURL command line utility on Mac OS X 10.11.
While #DanielStenberg's comment appears to be correct that the header wasn't my issue, I'll go ahead and provide an answer to my original question.
It appears the only way to follow the redirect without headers would be to NOT immediately follow the redirect, but print the response headers with the curl -D - command option. Once you get the 301/302 response from the original request, check the location header value that came in the response headers, then execute another curl to that location.