uaa
uaa copied to clipboard
Allow creating a trust relationship with Github Actions OIDC provider to retrieve an uaa access token using a Github id_token
What version of UAA are you running?
-
76.26.0
-
77.1.0
How are you deploying the UAA?
I am deploying the UAA
- as part of a commercial Cloud Foundry distribution
What did you do?
JWT Bearer Token Grant
by adding the Github OIDC Provider:
I added the Github OIDC provider using non existing credentials and used the repository_owner
claim as the user_name
:
uaa curl /identity-providers -X POST -H "Content-Type: application/json" -d '{"type": "oidc1.0", "name": "Github", "originKey": "github", "config": {"discoveryUrl": "https://token.actions.githubusercontent.com/.well-known/openid-configuration", "scopes": ["read:user", "user:email"], "linkText": "Login with Github", "showLinkText": false, "addShadowUserOnLogin": true, "clientAuthInBody": true, "relyingPartyId": "uaa", "relyingPartySecret": "uaa", "addShadowUserOnLogin": true, "attributeMappings" : {"given_name": "repository_owner", "family_name": "repository_owner_id", "user_name": "repository_owner"}}}'
The sub
can't be used for the user_name
, as it includes unsupported characters like /
and :
. I used the repository_owner
claim for the user_name
.
UAA client required for authentication:
uaa curl /oauth/clients -X POST -H "Content-Type: application/json" -d '{"client_id" : "jwt-bearer-client", "client_secret" : "secret", "access_token_validity": 1800, "authorities" : [ "uaa.resource" ], "authorized_grant_types" : [ "urn:ietf:params:oauth:grant-type:jwt-bearer" ], "scope": ["openid", "cloud_controller.read"], "allowedproviders" : [ "github" ], "name" : "JWT Bearer Client"}'
Finally the request to get an access_token
(uaa
has to be used for requesting the id_token
)
curl -u 'jwt-bearer-client:secret' -d 'grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=<github id token>' https://uaa.sys.domain.com/oauth/token
The resulting access_token
:
{
"jti": "a6bfcbc1e851444196ce76779567cbed",
"sub": "c8068c6a-8e21-408f-9532-0f3a413f988e",
"scope": [
"openid",
"cloud_controller.read"
],
"client_id": "jwt-bearer-client",
"cid": "jwt-bearer-client",
"azp": "jwt-bearer-client",
"grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
"user_id": "c8068c6a-8e21-408f-9532-0f3a413f988e",
"origin": "github",
"user_name": "vchrisb",
"email": "[email protected]",
"rev_sig": "7ec0c4f2",
"iat": 1713450185,
"exp": 1713493385,
"iss": "https://uaa.sys.domain.com/oauth/token",
"zid": "uaa",
"aud": [
"cloud_controller",
"openid",
"jwt-bearer-client"
]
}
Example Github workflow to retrieve the id_token
using a custom github action vchrisb/setup-cf:
name: CI
permissions:
id-token: write # This is required for requesting the JWT
contents: read # This is required for actions/checkout
on:
push:
jobs:
deploy:
name: password
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: setup cf cli
uses: vchrisb/[email protected]
with:
api: ${{ secrets.CF_API }}
client_id: ${{ secrets.CF_CLIENT_ID }}
client_secret: ${{ secrets.CF_CLIENT_SECRET }}
grant_type: jwt-bearer
org: test
space: dev
- name: access cloud foundry api
run: cf push --strategy rolling
It is possible to get an uaa access_token
using the JWT Bearer Token Grant
, but this has limitations:
- adding the identity provider requires fake credentials
- the
sub
, or combination of claims, can't be used for theuser_name
- a
client_secret
is required
client_credentials Grant
:
I also tried using the client_credentials Grant
with private_key_jwt
to retrieve an UAA access_token by providing a Github id_token
.
For that I created a UAA client, which name matched the sub
claim of the id_token
. I configured the client's jwks_uri with the one of Github. An authentication does fail, because the iss
claim does not include the client_id
, which is required by the specs for this flow.
Conversation on that in UAA Slack.
What did you expect to see? What goal are you trying to achieve with the UAA?
I would like to be able to access the cloud foundry api from a Github workflow using temporary credentials.
Background
From Github Security hardening with OpenID Connect:
GitHub Actions workflows are often designed to access a cloud provider (such as AWS, Azure, GCP, or HashiCorp Vault) in order to deploy software or use the cloud's services. Before the workflow can access these resources, it will supply credentials, such as a password or token, to the cloud provider. These credentials are usually stored as a secret in GitHub, and the workflow presents this secret to the cloud provider every time it runs.
However, using hardcoded secrets requires you to create credentials in the cloud provider and then duplicate them in GitHub as a secret.
With OpenID Connect (OIDC), you can take a different approach by configuring your workflow to request a short-lived access token directly from the cloud provider. Your cloud provider also needs to support OIDC on their end, and you must configure a trust relationship that controls which workflows are able to request the access tokens. Providers that currently support OIDC include Amazon Web Services, Azure, Google Cloud Platform, and HashiCorp Vault, among others.
Github Actions does provide an id_token
to workflows with following relevant claims from Understanding the OIDC token:
-
sub
, e.g.repo:octo-org/octo-repo:environment:prod
, the template used to generate thesub
value can be configured -
iss
is alwayshttps://token.actions.githubusercontent.com
-
aud
can be configured when requesting theid_token
in the workflow
Example Job to retrieve the id_token
:
job:
environment: Production
runs-on: ubuntu-latest
steps:
- name: Install OIDC Client from Core Package
run: npm install @actions/[email protected] @actions/http-client
- name: Get Id Token
uses: actions/github-script@v7
id: idtoken
with:
script: |
const coredemo = require('@actions/core')
let id_token = await coredemo.getIDToken('https://uaa.sys.domain.com/oauth/token')
coredemo.setOutput('id_token', id_token)
The Github OIDC provider is solely exposing the JSON web key (JWK) endpoint: https://token.actions.githubusercontent.com/.well-known/jwks
to be used to validate the Github id_token
.
Github OIDC openid-configuration
The Github documentation does have examples how to create a trust relation with AWS, Azure, GCP and Vault.
(The Github actions OIDC provider is not the same as the Oauth2 provider for Github Oauth2 Apps.)
Ask
I want to use a short live token to interact with the cloud foundry api.
For that, I would like to be able to create a trust relation from UAA to Github, (and other CI systems like GitLab) to use the id_token
provided in the workflow to retrieve an UAA client access_token
.
The UAA client might be created using the sub
claim of the id_token
or a pre created client might be pattern matched against the sub
.
The client will be used to assign a cloud foundry space role to it.
We have created an issue in Pivotal Tracker to manage this:
https://www.pivotaltracker.com/story/show/187454040
The labels on this github issue will be updated when the story is started.
Ok, thank you. I know understand what you want and I have a plan in my mind howto solve it... the Prio is currently so that I want solve PR 2813 and then I can start to create some PRs for this fix. I think I will solve this issue with more than one PR, because the issue now exists in some parts, but finally the client credential flow should work and JWT bearer as well
@peterhaochen47 , FYI
- [ ] Allow OIDC setup with github, e.g. https://token.actions.githubusercontent.com/.well-known/openid-configuration
- [ ] Allow setup of CLIENT JWT Trust based on an OIDC IdP , https://docs.cloudfoundry.org/api/uaa/version/77.5.0/index.html#change-client-jwt
- [ ] .... JWT bearer maybe needs some additional fix
thank you @strehle I did some more testing and had success with jwt bearer grant.
I updated the initial issue with the findings
Ok cool, seems like there's at least a workaround / a hack.
We'll keep the issue open and in mind but likely won't pursue a fix immediately, because being compatible with a non-standard OIDC is not on our current roadmap. Nevertheless, your issue will help others & help us gather data point about the demand for this.
My last comment might have been misleading.
For the jwt bearer token grant that is probably right, but the original ask is to support a trust relation. To use the jwt bearer token grant for this problem, is already a workaround by itself.
AWS, Azure, GCP and Vault do support a trust with amongst others GitHub and Gitlab. From a bit more research, I think they actually use OIDC Token Exchange RFC 8693?
Here is the original github roadmap issue: https://github.com/github/roadmap/issues/376
Hi @vchrisb great stuff! I did not fully get it yet but it seems this requirement matches very much with one of our own: We have Azure Entra as Identity provider and would like to enable API developers to take an Azure Entra Bearer token from there clients and then use this token to execute API calls to a Cloudfoundry instance using UAA (knowing the same identities) on behalf the identy from the Azure token.
Hi @vchrisb , I have been able to use this pattern to create a web app offering SSO with Microsoft Entra which exchanges the Azure id-token to a UAA issued access-token and uses it to call the CF Api with it.
In this scenario it is actually ok to have a uaa client that is used be the server side part of the app to do the token exchange. It is a security gain in any case.
Now in your case I was wondering: Wouldn't it make sense to put a reverse proxy between your github runner and the cf api that actually does the token exchange using a uaa client?