Connecting to Kubernetes API from pod - api

I'm trying to use Kubernetes API from inside a pod. Going to list/watch pods and custom defined resources.
Construct url as "https://KUBERNETES_SERVICE_HOST:KUBERNETES_SERVICE_PORT_HTTPS"
Authorization header = "Bearer /var/run/secrets/kubernetes.io/serviceaccount/token"
CaCert = /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
When running inside minikube, the request fails with "Error: connect ETIMEDOUT 10.96.0.1:443"
Same code running in GCP fails with: "Error: unable to verify the first certificate"

If you are using curl, you can skip certificate checks with the -k flag.
Try
curl -k https://10.96.0.1:443/api/v1/namespaces -H "Authorization: Bearer <content of /var/run/secrets/kubernetes.io/serviceaccount/token here>"

Related

Keycloak X.509 authentication using proxy

I am trying to configure X.509 client authentication on the Keycloak 17.0.0 (Quarkus). I am using the quay.io/keycloak/keycloak:17.0.0 to deploy it in my Kubernetes environment.
I am running the Keycloak according the https://github.com/keycloak/keycloak/blob/main/docs/guides/src/main/server/reverseproxy.adoc:
/opt/keycloak/bin/kc.sh build --spi-x509cert-lookup-provider=nginx
/opt/keycloak/bin/kc.sh start-dev --spi-x509cert-lookup-nginx-ssl-client-cert=SSL_CLIENT_CERT
And I have the configuration of the X.509 client certificate authentication in the Browser and Direct Grant authentication flows, enabled in the authentication bindings, according the https://www.keycloak.org/docs/latest/server_admin/#_x509.
So expecting that the Keycloak will take the client certificate from SSL_CLIENT_CERT header and authenticate based on that.
However, trying to use the certificate to authenticate, I receive:
{
"error_description": "X509 client certificate is missing.",
"error": "invalid_request"
}
This is my curl:
curl http://localhost:8080/auth/realms/TEST/protocol/openid-connect/token \
-H "SSL_CLIENT_CERT: <cert_content>" \
-d "grant_type=password&username=&password=&client_id=CLIENT_ID&client_secret=CLIENT_SECRET"
There is a little documentation about how to do it behind the proxy in the Keycloak Quarkus version.
Anyone able to make it work?
1.) You need to use TLS, so you can't use http protocol for that - https is required. Ideal TLS config will have proper cert setup, otherwise curl will need --insecure.
2.) -H "SSL_CLIENT_CERT: <cert_content>" \ adds HTTP header, so that's is level 7 (OSI model), but TLS connection is level 4. So this is wrong.
Curl has another parameters --cert, --key for mutual (X.509) TLS. You should to have also proper data encoding, so in theory correct curl:
curl -s -X POST \
--cert /<path>/client-pem.crt \
--key /<path>/client-pem.key \
--data-urlencode "client_id=CLIENT_ID" \
--data-urlencode "client_secret=CLIENT_SECRET" \
--data-urlencode "grant_type=password" \
--data-urlencode "username=" \
--data-urlencode "password=" \
https://<keycloak-host>/auth/realms/TEST/protocol/openid-connect/token

Keycloak invalid_grant with Authorization Grant flow

So this is what I did,
I have a Keycloak server running on localhost:8080 and I have configured a public client called myclient inside a realm myrealm.
I have added a response_url address as http://localhost:3000/*
I invoke a code request using this URL
http://localhost:8080/auth/realms/myrealm/protocol/openid-connect/auth?client_id=myclient&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2F&response_type=code
I am challenged for a login and then after successful login I login get a callback something like this. which obviously gives me a Not found as I don't have anything running on 3000 Port.
http://localhost:3000/?session_state=6af80f75-19b0-4c65-8d8b-89ca1cf5fd0d&code=e2082b9d-4199-4f0e-a3de-d9216ab70ac5.6af80f75-19b0-4c65-8d8b-89ca1cf5fd0d.8fa6724d-ffd2-4bb4-9ed9-7302acb432e8
I pick the code from above and then make a curl call below
curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d "grant_type=authorization_code&code=e2082b9d-4199-4f0e-a3de-d9216ab70ac5.6af80f75-19b0-4c65-8d8b-89ca1cf5fd0d.8fa6724d-ffd2-4bb4-9ed9-7302acb432e8&redirect_uri=http://localhost:3000/&client_id=myclient" http://localhost:8080/auth/realms/myrealm/protocol/openid-connect/token
I get an error saying
{"error":"invalid_grant","error_description":"Code not valid"}
when I try the same thing with https://www.keycloak.org/app/ it works. What am I missing here?

How to get Bearer access token in Jmeter

I have problems to get Bearer access token in Jmeter. Problem's cause most probably is in
server authentication - do not really understand how to properly setup this in Jmeter.
curl consist of several parts:
curl -X POST -v https://xxxx.xxx.xx.lv/token -u
"d123c9e3-4e91-46db-931e-37e8a52b8c8d:0e7cb8ad50fe3686de05fcf46815abc0a9d7cd095c23f75446d933ccxyxy"
-d "grant_type=password" -d "username=xxxxxxx" -d "password=xxxxxx" -d "scope=scop"
I have tried to use HTTP AuthorizationManager, HTTP Request and HTTP Header Manager without any successful results. Any advices?
Thanks!
Tatjana
I think you should do something like:
HTTP Request sampler:
these protocol and Server Name bits can be moved to HTTP Request Defaults so you won't have to specify them for each and every HTTP Request sampler
HTTP Authorization Manager:
In general since JMeter 5.1 it's possible to create a test plan from curl command line, the option lives under "Tools -> Import from cURL" main menu entry:

cURL authentication with mod_auth_openidc and keycloak

I have an authentication server running Keycloak, and a Apache2 webserver with mod_auth_openidc to do OAuth2 authorization.
With browsers, I can successfully intercept access to protected resource to redirect user to Keycloak login page. After successful login, user will be redirected to the resource link.
With Postman, I can also retrieve access token JWT with password grant flow, then use the access token to access protected resource. The cURL code provided by postman indicates that the mod_auth_openidc_session cookie is also required.
Next, I try to do 2-stage cURL command in Linux CLI.
First I retrieve the access token using password grant flow as below. I initiated the cookie engine to capture session cookies given by mod_auth_openidc.
# RETRIEVE ACCESS TOKEN JSON
curl -L -b ./cookie.jar -c ./cookie.jar -d 'client_id=CLIENT_ID' -d 'client_secret=368127b1-1ee0-4f3f-8429-29e9a93daf9a' -d 'username=USERNAME' -d 'password=PASSWORD' -d 'grant_type=password' 'https://AUTH_SERVER:PORT/auth/realms/REALM/protocol/openid-connect/token
# PARSE ACCESS TOKEN
access_token=`echo $response|jq '.access_token'|cut -d\" -f2`
Next, with the access token bearer in header and cookie jar file, I try to access to the protected resource.
curl -b ./cookie.jar -c ./cookie.jar --insecure -L -X GET 'https://RESOURCE_SERVER:PORT/protected_content' --header "'Authorization: Bearer "$access_token"'"
However, I still got redirected to the Keycloak login page, and the session cookie is not recorded in the cookie jar file.
Here is the recorded cookie jar file with sensitive info redacted/replaced.
# Netscape HTTP Cookie File
# https://curl.haxx.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
#HttpOnly_[AUTH_SERVER] FALSE /auth/realms/master/ TRUE 0 KC_RESTART eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI2Y2ZiNjYwOC1kMTlhLTQwZGUtOWJiYS04NzcxOTkzZTIwMWUifQ.eyJjaWQi[REDACTED]4aHhkVDBGZmhBZEVTSm8iLCJub25jZSI6IndTYXNYOWhGeGIxd1hKakNrS2FLMXVadVRGX3ZOZzRGVUZnMTJyYXFWbVkifX0.53645krpwlFnJ09cHAcZhNCci-DhGigu4soN5CVsZQ0
#HttpOnly_[AUTH_SERVER] FALSE /auth/realms/master/ TRUE 0 AUTH_SESSION_ID_LEGACY 6a23b139-05ba-4d22-b9e3-9ae857074814.[AUTH_SERVER]
#HttpOnly_[AUTH_SERVER] FALSE /auth/realms/master/ TRUE 0 AUTH_SESSION_ID 6a23b139-05ba-4d22-b9e3-9ae857074814.[AUTH_SERVER]
#HttpOnly_[RESOURCE_SERVER] FALSE / TRUE 0 mod_auth_openidc_state_XGEq0YKJAwSt8hxdT0FfhAdESJo NVc9Mk1FmN[REDACTED]lydKVtOw0iL-Y9iZMjzcUinutFPn74rmVvI_ERV3C8Wn1Euio8pID0jEAmu9NEfY_MEeuzOzqe6w7I20HZUNQHX0uh_vXR8
Can anyone tell me what I did wrong in the 2-stage cURL authentication/authorization process?
You have single quotes inside double quotes when setting Authorization header. This means instead of expect Authorization: Bearer token server is getting 'Authorization: Bearer token'. You can check the contents of your headers by using verbose -v option.
Following command should work as expected:
curl --header "Authorization: Bearer $access_token" -b ./cookie.jar -c ./cookie.jar --insecure -L -X GET https://RESOURCE_SERVER:PORT/protected_content'
Optionally, if you need double qoutes around token use following:
--header "Authorization: Bearer \"$access_token\""
Side note: In order not to overwrite existing cookies in cookie.jar, use different file name to store cookies from the request to authorized file.

Keycloak - invalid token when using nginx proxy

I’m trying to set up Keycloak using nginx as proxy.
The idea is to log in to web app using javascript adapter and then for each API request, nginx should ask Keycloak if token is valid (session could be revoked, etc.).
I’ve set it up without nginx locally - I have keycloak on my VM and I used Keycloak Gatekeeper to proxy API requests. It worked with no issues whatsoever.
Then, I deployed Keycloak and web app that uses js adapter on cluster and in nginx I proxied URLs required for login. Next, I configured auth module to call /auth/realms/cerulean-magnolia/protocol/openid-connect/token with grant_type=urn:ietf:params:oauth:grant-type:uma-ticket. There could be better endpoint to call but I’m always getting invalid_grant Invalid bearer token anyway.
Login works but when I try to use generated token, it becomes invalid and I can’t use it anymore.
I’ve set PROXY_ADDRESS_FORWARDING to true.
Any attempt of using this token ends up in getting:
{
"error": "invalid_grant",
"error_description": "Invalid bearer token"
}
If I would generate this token manually (via forwarded port) using password:
curl -L -X POST 'https://localhost:8141/auth/realms/cerulean-magnolia/protocol/openid-connect/token' \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=lei' \
--data-urlencode 'grant_type=password' \
--data-urlencode 'scope=openid' \
--data-urlencode 'username=...' \
--data-urlencode 'password=...' --insecure | jq
and then use this token to do:
http --verify=no -f https://localhost:8141/auth/realms/cerulean-magnolia/protocol/openid-connect/token grant_type=urn:ietf:params:oauth:grant-type:uma-ticket audience=lei-api response_mode=decision authorization:"Bearer ..."
It works fine. But if I use token generated via web app, I always get 401.
I’d be grateful for any help or hints.
Thanks in advance,
Patryk