Accessing the Grafana API through k8s proxy - kubernetes

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!

Related

Traefik: How to pass authorization header to service API?

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?

Kubernetes Ingress controller dual authorization header for oauth proxy

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/

Request to containerized OpenSearch without curl flags

I can interact with my open search docker container via curl -XGET https://localhost:9200 -u 'admin:admin' --insecure but no use when I want to automate requests to it... I need to be able to access it, even via HTTP is fine (not secure meaning not HTTPS).
command:
curl -XGET https://localhost:9200
error:
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: https://curl.se/docs/sslcerts.html
curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
I did go into that link, not a solution, just an explanation that threw me into a rabbit hole I was able to get out just now.
The awful thing is that this happened to me before and I fixed it, but it was not on a docker container and I don't remember how I fixed it.
You can disable security in your Dockerfile then:
RUN echo "plugins.security.disabled: true" >> /usr/share/opensearch/config/opensearch.yml
Your OpenSearch will be accessible via http://localhost:9200 after. I do this to setup my data, and then load /usr/share/opensearch/data in an other container set up with security.

kubeadm dind won't pull from insecure registry on http

I'm trying to use kubeadm dind, but I'm having trouble with private registries. I created a docker private registry, which is running on http, but kubernetes running in dind refuses to use http, and keeps trying to download using https.
The error I'm receiving is this...
Failed to pull image "192.168.2.5:5000/inotes-init-db:1.0.18": rpc
error: code = Unknown desc = Error response from daemon: Get
https://192.168.2.5:5000/v2/: http: server gave HTTP response to HTTPS
client
But the registry is running on http...
$ curl -X GET http://192.168.2.5:5000/v2/_catalog 2> /dev/null| jq
{
"repositories": [
"inotes-init-db",
"intelli-notes"
]
}
As you can see above, it works fine on http, but if I try https, it fails...
$ curl -X GET https://192.168.2.5:5000/v2/_catalog
curl: (35) gnutls_handshake() failed: An unexpected TLS packet was received
I also thought I could maybe access the kubernetes nodes to update their /etc/default/docker.json file, but I can't shell into them.
So, how do I get kubeadm to use http?

cURL follow redirect without headers from original request

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.