kubeconfig - oidc based authentication - kubernetes

Below is my kubeconfig file for accessing kubernetes clusters:
kind: ClientConfig
apiVersion: authentication.gke.io/v2alpha1
spec:
name: dev-corp
server: https://10.x.x.x:443
certificateAuthorityData: ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
authentication:
- name: oidc
oidc:
clientID: aaaaad3-9aa1-33c8-dd0-ddddd6b5bf5
clientSecret: ccccccccccccccccc-
issuerURI: https://login.microsoftonline.com/aaaa92-aab7-bbfa-cccf-ddaaaaaaaa/v2.0
kubectlRedirectURI: http://localhost:12345/callback
cloudConsoleRedirectURI: http://console.cloud.google.com/kubernetes/oidc
scopes: offline_access,profile
userClaim: upn
userPrefix: '-'
groupsClaim: groups
preferredAuthentication: oidc
There are different OAuth grant types.
My understanding is, above OAuth grant type is client credential grant type, that requires client_id, client_secret, token URL(issuerURI), scope
What is the significance of fields kubectlRedirectURI, cloudConsoleRedirectURI, userClaim, userPrefix?
How OIDC different from OAuth2?
oauth2.Config does not store userClaim & userPrefix, groupsClaim information
, as shown here.... https://github.com/golang/oauth2/blob/master/oauth2.go#L41
How to store kind:ClientConfig with oidc based authentication into cache? for example api.Config can be stored with an API from client-go to write api.Config as shown here.

KUBECTL_REDIRECT_URL: the redirect URL that kubectl oidc login uses for authorization. This is typically of the format http://localhost:PORT/callback, where PORT is any port above 1024 that will be available on developer workstations, for example http://localhost:10000/callback. You must register the URL with your OIDC provider as an authorized redirect URL for the client application.
USER_PREFIX: prefix prepended to user claims to prevent conflicts with existing names. By default, an issuer prefix is appended to the userID given to the Kubernetes API server (unless the user claim is email). The resulting user identifier is ISSUER_URI#USER. We recommend using a prefix, but you can disable the prefix by setting USER_PREFIX to -.
userClaim: the user identifier in the token under the claim name configured in spec.authentication.oidc.userClaim in the client configuration file.
cloudConsoleRedirectURI the name tell the story, the cloud redirect URL for OIDC, for example in case of google https://console.cloud.google.com/kubernetes/oidc
OIDC vs OAuth2
What's the difference between OpenID and OAuth?
The file in the question from OIDC and you are comparing the value with Oauth, both handling at different way, better to update the question again with Oauth config file.
api-server-authentication
you can check kubeconfig builder
kubernetes-engine-oidc
How to store kind:ClientConfig with oidc based authentication into cache?
you can write to a file and then read, or somewhere in the cloud storage as well

Related

keycloak-js How to authenticate AND authorize users

I'm having a bit of trouble understanding how to link together authenticating and authorizing users in my frontend using Keycloak and the keycloak-js adapter.
To preface this: I know that the keycloak-js adapter requires the client to have public as the Access Type.
My main question is how can I use Keycloak authentication AND authorization via the same client. If the Access Type MUST be set to public for the keycloak-js adapter to work, then how can I restrict access to my API depending on the users permissions?
Will I need two clients for this? One for authentication and one for authorization? If so, how can I use the access token from the authentication client in the authorization client?
My current setup in Keycloak is as follows:
Realm: admin-service
Client: admin-service-api
Access Type: confidential (because I want to use authorization to restrict api requests according to permission levels)
Root URL: http://localhost:8080/
Valid Redirect URIs: http://localhost:8080/*
Roles:
admin
Users:
test-user
My authorization setup for admin-service-api is as follows:
Resources: Books Resource
Uri (these are my API endpoints):
/v1/books
/v1/books/{id}
Scopes:
books:delete
books:create
books:update
books:read
Policies:
Default Policy
Books Policy:
Realm roles:
admin (the required checkbox is not checked)
Permissions:
Default Permission
Books Resource Permission:
Resources: Books Resource
Apply Policy: Books Policy
So with this setup, I have restricted my API (which is written in GoLang) to only allow requests if the requesting user has the appropriate permissions by making a request to the Keycloak API via https://my.auth.server/auth/realms/{{realm_name}}/protocol/openid-connect/token to retrieve the users access token and a list of the users permissions.
From there I can use this access token to make requests to my API to create/read/update/delete books so long as my test-user has the admin role. If my user does not have the admin role, the user is presented with an unauthorized message (401).

Grafana : How to use JWT authentication?

I want to use JWT for Grafana login authentication, Grafana docs dictate some steps for the same but [auth.jwt] default is not provided in sample.ini, and can you clarify what it means by header name that contains a token in the step mentioned for enabling JWT ?
This is the header providing a jwt payload from the proxy in front of grafana - in the case of IAP(https://cloud.google.com/iap/docs/signed-headers-howto) for example: x-goog-iap-jwt-assertion. The contents of this header is validated by the use of either source speficied i jwk_set_url, jwk_set_file or key_file, after which the claims for example for username and email can be fetched. Examples on IAP for this also available in the url above:
auth.jwt:
enabled: true
header_name: x-goog-iap-jwt-assertion
username_claim: sub
email_claim: email
jwk_set_url: https://www.gstatic.com/iap/verify/public_key-jwk
Note however - auth.jwt currently "broken by design" as mentioned in:
Authentication Grafana via JWT

Multiple authentications (Basic Auth + Keycloak)

I have 2 different rest endpoints in my Quarkus project:
/api/ws/...
/api/web/...
according to my understanding, it is so with Keycloak that I get a bearer token before and with this token I can access the endpoints.
But how do I do that if I want to secure the "ws" endpoint only with basic auth (Username + Password)?
So that I have then also the user in the SecurityIdentity (Principal) contained ?
the current "application.properties" looks like this:
# AUTH
quarkus.http.auth.basic=true
quarkus.http.auth.permission.authenticated.paths=/*
quarkus.http.auth.permission.authenticated.policy=authenticated
quarkus.http.auth.permission.web.paths=/*
quarkus.http.auth.permission.web.policy=authenticated
quarkus.oidc.tenant-id=RealmResolver
quarkus.oidc.enabled=true
quarkus.oidc.auth-server-url=${keycloak.url}/auth/realms/${keycloak.realm}
quarkus.oidc.client-id=${keycloak.client_id}
quarkus.oidc.token-path=${keycloak.url}/auth/realms/${keycloak.realm}/protocol/openid-connect/token
quarkus.oidc.token.refresh-expired=true
quarkus.oidc.application-type=WEB_APP
## WS
quarkus.http.auth.ws.basic=true
quarkus.oidc.ws.auth-server-url=${keycloak.url}/auth/realms/${keycloak.realm}
quarkus.oidc.ws.client-id=${keycloak.client_id}
quarkus.oidc.ws.application-type=hybrid
quarkus.http.auth.permission.ws.paths=/api/ws/*
quarkus.http.auth.permission.ws.policy=authenticated
Quarkus can support several authentication mechanisms at the same time - but at the moment it can not apply only one mechanism for a specific request path. Please watch https://github.com/quarkusio/quarkus/issues/11886
thanks

sign request to AWS API gateway with Signature v4 from using AWS Cognito token

I created a AWS API Gateway set with authentication = AWS_IAM to call a Lambda function. Now, to call this API I understand that I need to sign the request and as stated in the AWS documentation the correct way is to add the Authorization header calculated using AWS Signature V4 which need an access_key and a secret_key.
On my client side the user authenticate with AWS Cognito first and receive the JWT tokens (id token access token and refresh token) but I cannot find the access_key/secret
_key in them. How can I calculate the AWS Signature V4 from the tokens received from AWS Cognito?
I believe you can't (with 99,99999 of certainty)!
Please confirm that you are authenticating your users with AWS Cognito User Pool. You probably are because Cognito User Pool is the service that provides JWT. In this case, the token will assure the service that receives it (API Gateway) that your user is registered in a specific identity directory (User Pool). Your service should evaluate if it will provide access or not to its resources for users registered in this specific directory with the provided claims (groups, roles, etc).
When you secure your API Gateway endpoints with AWS_IAM you are saying that only identities that AWS can recognize inside its own identity directory (Users or Roles) are allowed to perform actions on the resource. In general, users registered in Cognito User Pools are not considered by AWS as valid identities.
For a Cognito User Pool user to be considered a valid AWS identity, you have two options:
1 - Configure your AWS account to use external Identity Providers and Federation. Not a simple thing and a solution to a different use case. In summary, don't choose this one.
2 - Use another AWS product (with a name that creates a lot of confusion) called Cognito Identity Pool. This service evaluates if the JWT token is allowed in that context (you configure it inside the Identity Pool). If is a valid token from a registered identity directory, Cognito Identity Pool will exchange your JWT token for a AWS Access Key, AWS Secret Key and AWS Session Token associated with a specific IAM Role. You can then use these keys to sign your request. But keep in mind that with this change you will lose your capacity to identity the specific user in API Gateway and in the downstream services called by API Gateway.
If you need to have the JWT token in your downstream services, you can do it with a little bit of additional effort. You can't find a way here: https://stackoverflow.com/a/57961207/6471284

How to create base authentication in kubernetes?

I want to create base authentication in kubernetes. every document say that I should create CSV or file then enter the username and password in it. but I do not want to use file I want to some database or kubernetes handle it.
what can I do for base authentication?
You can based your authentication on tokens if you don't want to use static pasword file.
First option:
Service Account Tokens
A service account is an automatically enabled authenticator that uses signed bearer tokens to verify requests.
The plugin uses two flags(which are optional):
Service accounts are usually created automatically by the API server and associated with pods running in the cluster through the ServiceAccount Admission Controller. Bearer tokens are mounted into pods at well-known locations, and allow in-cluster processes to talk to the API server. Accounts may be explicitly associated with pods using the serviceAccountName field of a PodSpec.
Service account bearer tokens are perfectly valid to use outside the cluster and can be used to create identities for long standing jobs that wish to talk to the Kubernetes API. To manually create a service account, simply use the kubectl create serviceaccount (NAME) command. This creates a service account in the current namespace and an associated secret.
The created secret holds the public CA of the API server and a signed JSON Web Token (JWT).
The signed JWT can be used as a bearer token to authenticate as the given service account. See above for how the token is included in a request. Normally these secrets are mounted into pods for in-cluster access to the API server, but can be used from outside the cluster as well.
There is some drawbacks because service account tokens are stored in secrets, any user with read access to those secrets can authenticate as the service account. Be careful when granting permissions to service accounts and read capabilities for secrets.
Second:
Install OpenID Connect (full documentation you can find here: oidc).
OpenID Connect (OIDC) is a superset of OAuth2 supported by some service providers, notably Azure Active Directory, Salesforce, and Google. The protocol’s main addition on top of OAuth2 is a field returned with the access token called an ID Token. This token is a JSON Web Token (JWT) with well known fields, such as a user’s email, signed by the server.
To identify the user, the authenticator uses the id_token (not the access_token) from the OAuth2 token response as a bearer token.
Since all of the data needed to validate who you are is in the id_token, Kubernetes doesn’t need to “phone home” to the identity provider. In a model where every request is stateless this provides a very scalable solution for authentication.
Kubernetes has no “web interface” to trigger the authentication process. There is no browser or interface to collect credentials which is why you need to authenticate to your identity provider first.
There’s no easy way to authenticate to the Kubernetes dashboard without using the kubectl proxy command or a reverse proxy that injects the id_token.
More information you can find here: kubernetes-authentication.