-
Notifications
You must be signed in to change notification settings - Fork 66
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
docs: site: Add GitLab CI/CD example for JWT Auth #2146
Comments
Hi @Dentrax! Thanks for posting this suggestion. Pinniped abstracts its internal usage of various token types (e.g. JWTs) so that hopefully you don't need to worry about the level of detail shown in either of those GitLab docs. Here's an outline of the steps if you are using the Pinniped Supervisor:
Then it should "just work" for your users to be able to authenticate without requiring any interactive prompts by using that kubeconfig with the environment variables to hold their username and password (see https://pinniped.dev/docs/howto/cicd). Is that what you were asking about? Or maybe you meant something else? |
Thank you @cfryanr for your detailed explanations and links to useful resource!
After following the dos you shared, will I be able to obtain kubeconfigs for the cluster(s) in the GitLab CI/CD pipeline running with GitLab Runner? (non-TTY env) |
Hi @Dentrax, sorry, I'm not too familiar with the details of GitLab Runner. What I outlined above would give you a kubeconfig that you could use from anywhere. You'd have to figure out how to provide that kubeconfig file to your CI/CD scripts (e.g. pull it from a git repo), but that kubeconfig would not have any credentials or identity included inside it, so it can be shared among all users of that cluster. By setting the env vars |
Ah thanks for Is this possible to make whole process KEYLESS? Are those variables mandatory? Why should we export those? For example the Vault use-case, I don't export any I can generate a kubeconfig on the CI, no problem. In my GitLab CI/CD pipeline case, I was mostly asking for, what variable should I particularly pass to GitLab also exports ID_TOKENs, but I couldn't get which flag should I use to pass this variable. (I have read the doc above and there was no flag to pass id_token) |
Pinniped's primary use case is to provide authentication for human users, where those identities are sourced from external identity providers (e.g. GitLab, AD, GitHub, etc.). So you would typically only use Pinniped for non-human auth (e.g. CI bot accounts) when you prefer that those identities are also sourced from an external identity provider in a fashion similar to your human users. That's why you need to provide a username and password to auth in the typical flow. Some companies prefer this approach because then they can have a single, consistent point of control for all human and non-human actors. However, using Pinniped for human auth does not disable any other forms of auth that are supported by your clusters, so you can still use Pinniped for human auth while using other solutions for service-to-service auth (non-human auth) at the same time.
Maybe you're asking something else that I'm not understanding. Have you already acquired a JWT issued by GitLab somehow using some existing automation unrelated to Pinniped, and are you trying to use that JWT alone to authenticate to a cluster? Sorry, I'm not sure if I understand your use case. In the typical Pinniped use case, we do not assume that you start with a JWT. We assume that every user starts completely unauthenticated, with nothing but a Pinniped-generated kubeconfig (which contains no credentials and no identity), and then Pinniped helps you authenticate and get access to clusters. Could you describe more about what you are trying to accomplish, without assuming that the reader has any knowledge of your specific tools? |
Thank you @cfryanr! Really appreciate you trying to understand my use case and providing further details.
Happy to describe more! I've tried to draw some flow diagram here: (What I'm trying to accomplish)
GitLab already exports this with
Exactly! If pinniped supervisor verifies this using GitLab's JWKS, we should able to auth to cluster
Yeah actually, in this scenario, the flow starts with an ID token. Is this something that doesn't fit with the current design/architecture? I'm not so familiar end-to-end OIDC/JWT flow and terminology, sorry if I'm mixing things up here. Thanks in advance. |
Hi @Dentrax, thanks for the diagram. That helped me understand your use case. Here is what I think might work:
|
@cfryanr Just to clarify - it's possible to use a static token against a I'm guessing this kubeconfig would need to run command $ pinniped login oidc -h
Login using an OpenID Connect provider
Usage:
pinniped login oidc --issuer ISSUER [flags]
Flags:
--ca-bundle strings Path to TLS certificate authority bundle (PEM format, optional, can be repeated)
--ca-bundle-data strings Base64 encoded TLS certificate authority bundle (base64 encoded PEM format, optional, can be repeated)
--client-id string OpenID Connect client ID (default "pinniped-cli")
--concierge-api-group-suffix string Concierge API group suffix (default "pinniped.dev")
--concierge-authenticator-name string Concierge authenticator name
--concierge-authenticator-type string Concierge authenticator type (e.g., 'webhook', 'jwt')
--concierge-ca-bundle-data string CA bundle to use when connecting to the Concierge
--concierge-endpoint string API base for the Concierge endpoint
--credential-cache string Path to cluster-specific credentials cache ("" disables the cache) (default "/Users/caseyj/.config/pinniped/credentials.yaml")
--enable-concierge Use the Concierge to login
-h, --help help for oidc
--issuer string OpenID Connect issuer URL
--listen-port uint16 TCP port for localhost listener (authorization code flow only)
--request-audience string Request a token with an alternate audience using RFC8693 token exchange
--scopes strings OIDC scopes to request during login (default [offline_access,openid,pinniped:request-audience,username,groups])
--session-cache string Path to session cache file (default "/Users/caseyj/.config/pinniped/sessions.yaml")
--skip-browser Skip opening the browser (just print the URL)
--upstream-identity-provider-flow string The type of client flow to use with the upstream identity provider during login with a Supervisor (e.g. 'browser_authcode', 'cli_password')
--upstream-identity-provider-name string The name of the upstream identity provider used during login with a Supervisor
--upstream-identity-provider-type string The type of the upstream identity provider used during login with a Supervisor (e.g. 'oidc', 'ldap', 'activedirectory', 'github') (default "oidc")
$ pinniped login static -h
Login using a static token
Usage:
pinniped login static [--token TOKEN] [--token-env TOKEN_NAME] [flags]
Flags:
--concierge-api-group-suffix string Concierge API group suffix (default "pinniped.dev")
--concierge-authenticator-name string Concierge authenticator name
--concierge-authenticator-type string Concierge authenticator type (e.g., 'webhook', 'jwt')
--concierge-ca-bundle-data string CA bundle to use when connecting to the Concierge
--concierge-endpoint string API base for the Concierge endpoint
--credential-cache string Path to cluster-specific credentials cache ("" disables the cache) (default "/Users/caseyj/.config/pinniped/credentials.yaml")
--enable-concierge Use the Concierge to login
-h, --help help for static
--token string Static token to present during login
--token-env string Environment variable containing a static token
|
When you run This use case doesn't need |
I tried something like this. First I created a JWTAuthenticator like this: apiVersion: authentication.concierge.pinniped.dev/v1alpha1
kind: JWTAuthenticator
metadata:
name: demo-supervisor-jwt-authenticator-gitlab
spec: # This should be the issuer URL that was declared in the FederationDomain.
issuer: "https://gitlab.private.com"
audience: workload1-dd9de13c370982f61e9f # the id of the workload cluster
claims:
username: email Then I created a pipeline in GitLab like this: manual_authentication:
image: alpine:latest
id_tokens:
DEMO_ID_TOKEN:
aud: workload1-dd9de13c370982f61e9f # the same audiance
script:
- apk add curl jq
- |
mkdir -p $HOME/.kube
cat "$KUBECONFIG" > $HOME/.kube/config
export KUBECONFIG=$HOME/.kube/config
export PINNIPED_USERNAME=gitlab
export PINNIPED_PASSWORD=$CI_JOB_TOKEN
curl -Lso pinniped https://get.pinniped.dev/v0.36.0/pinniped-cli-linux-amd64 \
&& chmod +x pinniped \
&& mv pinniped /usr/local/bin/pinniped
echo "${DEMO_ID_TOKEN}" |base64 > /tmp/web_identity_token
cat /tmp/web_identity_token
DEMO_TOKEN=$(cat /tmp/web_identity_token |base64 -d)
pinniped get kubeconfig \
--static-token $(cat /tmp/web_identity_token |base64 -d) \
--concierge-api-group-suffix=pinniped.dev \
--concierge-endpoint=https://x.x.x.x:6443 \
--concierge-authenticator-name=demo-supervisor-jwt-authenticator-gitlab \
--concierge-authenticator-type=jwt \
--oidc-scopes openid,offline_access,email > /tmp/kubeconfig
cat /tmp/kubeconfig
KUBECONFIG=/tmp/kubeconfig pinniped whoami But the pipeline fails with the following error: Error: could not complete Concierge credential exchange: login failed: authentication failed
Error: could not complete WhoAmIRequest: Post "https://x.x.x.x:6443/apis/identity.concierge.pinniped.dev/v1alpha1/whoamirequests": getting credentials: exec: executable /usr/local/bin/pinniped failed with exit code 1 The ID_TOKEN includes these claims : https://docs.gitlab.com/ee/ci/secrets/id_token_authentication.html#token-payload I'm 100% sure I'm missing something due to lack of knowledge, would you mind helping us @cfryanr? Thank you! /cc @Dentrax btw Here is the generated kubeconfig maybe it could help: users:
- name: kubernetes-admin-pinniped
user:
exec:
apiVersion: client.authentication.k8s.io/v1beta1
args:
- login
- static
- --enable-concierge
- --concierge-api-group-suffix=pinniped.dev
- --concierge-authenticator-name=demo-supervisor-jwt-authenticator-gitlab
- --concierge-authenticator-type=jwt
- --concierge-endpoint=https://x.x.x.x:6443
- --concierge-ca-bundle-data=LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMvakNDQWVhZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFR...
- --token=[MASKED]
command: /usr/local/bin/pinniped
env: []
installHint: The pinniped CLI does not appear to be installed. See https://get.pinniped.dev/cli
for more details
provideClusterInfo: true |
@developer-guy I see a few problems with what you posted.
If it still doesn't work after making those changes, look at the pod logs for the Concierge pods at the same timestamp as the authentication failure. You should be able to get more information about why it failed. |
it worked, thank you very much!!! |
Fresh user here!
I was reading the Using Pinniped for CI/CD cluster operations doc. It'd be great to expand this doc by providing some demo instructions about how can we use JWT Auth with GitLab to access kubeconfig from the pipeline.
As a reference, I can drop GitLab's Use HashiCorp Vault secrets in GitLab CI/CD and OpenID Connect (OIDC) Authentication Using ID Tokens docs.
Thanks.
The text was updated successfully, but these errors were encountered: