{"id":22458378,"url":"https://github.com/xenitab/aad-oidc-identity","last_synced_at":"2026-04-19T14:01:50.121Z","repository":{"id":45184441,"uuid":"439969281","full_name":"XenitAB/aad-oidc-identity","owner":"XenitAB","description":"This proof of concept aims to showcase the new federated identity credentials in Azure AD working together with Service Account Token Volume Projection and Service Account Issuer Discovery in Kubernetes.","archived":false,"fork":false,"pushed_at":"2022-01-04T07:10:34.000Z","size":297,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":4,"default_branch":"main","last_synced_at":"2026-03-30T13:37:24.196Z","etag":null,"topics":["aks","azure","azuread","kubernetes","oidc"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/XenitAB.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-12-19T21:14:14.000Z","updated_at":"2023-03-12T07:37:47.000Z","dependencies_parsed_at":"2022-07-26T16:32:00.991Z","dependency_job_id":null,"html_url":"https://github.com/XenitAB/aad-oidc-identity","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/XenitAB/aad-oidc-identity","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/XenitAB%2Faad-oidc-identity","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/XenitAB%2Faad-oidc-identity/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/XenitAB%2Faad-oidc-identity/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/XenitAB%2Faad-oidc-identity/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/XenitAB","download_url":"https://codeload.github.com/XenitAB/aad-oidc-identity/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/XenitAB%2Faad-oidc-identity/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32009239,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-18T20:23:30.271Z","status":"online","status_checked_at":"2026-04-19T02:00:07.110Z","response_time":55,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aks","azure","azuread","kubernetes","oidc"],"created_at":"2024-12-06T08:12:24.273Z","updated_at":"2026-04-19T14:01:50.082Z","avatar_url":"https://github.com/XenitAB.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# aad-oidc-identity\n\n**PLEASE NOTE**: This is a pre-alpha proof of concept. The name is just a placeholder for something meaningful in the future and borrowed from [aad-pod-identity](https://github.com/Azure/aad-pod-identity).\n\nThis proof of concept aims to showcase the new federated identity credentials in Azure AD working together with Service Account Token Volume Projection and Service Account Issuer Discovery in Kubernetes to create a secure way for applications to get Azure AD tokens, kind of like [IRSA](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html).\n\n## POC TODO\n\n- [x] Initial project setup\n- [x] Service Account Issuer Discovery with go-oidc-middleware\n- [x] External endpoint for OIDC Metadata (`/.well-known/openid-configuration`)\n- [x] External endpoint for JWKs (`/jwks`)\n- [x] Request Azure AD access tokens using federated identity credentials with JWT created with JWK\n- [x] Internal endpoint for token switching from Kubernetes JWT to Azure AD JWT (`/token/azure`)\n- [x] Create a small overview diagram\n- [x] Document the flow to showcase the functionality\n- [x] Client ID discovery through annotation\n- [x] Tenant ID discovery through annotation\n- [x] Scope discovery through annotation\n- [x] Store JWK in Kubernetes secret\n- [x] Add AWS support\n- [x] Add Google support\n- [ ] Document AWS support\n- [ ] Document Google support\n\n## AWS NOTES\n\nGet your thumbprint by following this guide: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc_verify-thumbprint.html\n\n```bash\nISSUER=aks-oidc.domain.com\nTHUMBPRINT=$(echo | openssl s_client -connect ${ISSUER}:443 2\u003e\u0026- | openssl x509 -fingerprint -noout | sed 's/://g' | awk -F= '{print tolower($2)}')\naws iam create-open-id-connect-provider --url https://${ISSUER} --thumbprint-list ${THUMBPRINT} --client-id-list api://AWSTokenExchange\n```\n\nRequest token using:\n\n```shell\nTOKEN=$(cat /var/run/secrets/tokens/oidc-token)\ncurl -v -H \"Authorization: Bearer ${TOKEN}\" -k http://aad-oidc-identity/token/aws\n``` \n\n## GOOGLE NOTES\n\nWhen setting up the trust from the external identity to the Service Account, go into IAM \u003e Service Accounts \u003e [service account] \u003e Permissions.\n\nFrom there, click \"Grant Access\" and set the \"New Principal to:\n\n`principal://iam.googleapis.com/projects/GOOGLE_PROJECT_ID/locations/global/workloadIdentityPools/GOOGLE_POOL_ID/subject/system:serviceaccount:K8S_NAMESPACE:K8S_SERVICE_ACCOUNT_NAME`\n\nGrant it `Workload Identity User` role as well as the roles required to do what it needs.\n\nRequest token using:\n\n```shell\nTOKEN=$(cat /var/run/secrets/tokens/oidc-token)\ncurl -v -H \"Authorization: Bearer ${TOKEN}\" -k http://aad-oidc-identity/token/google\n``` \n\n## Overview\n\n### High level diagram\n\n![overview](assets/overview.png)\n\n### Flow\n\n1. Create a private key and store it as a Kubernetes secret (will be used to sign tokens sent to Azure AD)\n   ```bash\n   step-cli crypto keypair tmp/tls.crt tmp/tls.key --insecure --no-password --kty=RSA --size=2048\n   kubectl create secret generic aad-oidc-identity-jwks --from-file=tls.key=tmp/tls.key --from-file=tls.crt=tmp/tls.crt\n   ```\n1. Azure AD app is created and [federated identity credentials](https://docs.microsoft.com/en-us/graph/api/resources/federatedidentitycredentials-overview?view=graph-rest-beta) is configured\n   ```bash\n   AZ_APP_OBJECT_ID=$(az ad app show --id 00000000-0000-0000-0000-000000000000 --output tsv --query objectId)\n   az rest --method POST --uri 'https://graph.microsoft.com/beta/applications/${AZ_APP_OBJECT_ID}/federatedIdentityCredentials' --body '{\"name\":\"AKSCluster\",\"issuer\":\"https://aks-oidc.domain.com\",\"subject\":\"system:serviceaccount:team1:team1\",\"description\":\"AKS Cluster authentication with aad-oidc-identity\",\"audiences\":[\"api://AzureADTokenExchange\"]}'\n   ```\n1. Service account is created with an annotation for the client id\n   ```yaml\n   apiVersion: v1\n   kind: ServiceAccount\n   metadata:\n     annotations:\n       aad-oidc-identity.xenit.io/client-id: 00000000-0000-0000-0000-000000000000\n       aad-oidc-identity.xenit.io/role-arn: arn:aws:iam::123456789:role/test\n     namespace: team1\n     name: team1\n   ```\n1. A pod is created using the service account and [Service Account Token Volume Projection](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#service-account-token-volume-projection)\n   ```yaml\n   apiVersion: v1\n   kind: Pod\n   metadata:\n     name: app\n     namespace: team1\n   spec:\n     serviceAccountName: team1\n     containers:\n       - image: nginx:alpine\n         name: app\n         volumeMounts:\n           - mountPath: /var/run/secrets/tokens\n             name: oidc-token\n     volumes:\n       - name: oidc-token\n         projected:\n           sources:\n             - serviceAccountToken:\n                 path: oidc-token\n                 expirationSeconds: 7200\n                 audience: aad-oidc-identity\n   ```\n1. The pod (app) requests a token from aad-oidc-identity\n\n   ```bash\n   TOKEN=$(cat /var/run/secrets/tokens/oidc-token)\n   curl -H \"Authorization: Bearer ${TOKEN}\" -k http://aad-oidc-identity/token/azure\n   ```\n\n   _Note: future iterations may include what scopes are requested here._\n\n1. aad-oidc-identity receives the request and validates the token using [Service Account Issuer Discovery](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#service-account-issuer-discovery)\n1. _NOT IMPLEMENTED YET:_ Get Client ID (and Tenant ID if available - maybe even _scopes_ if not included in the request) through the Kubernetes API from the Service Account\n1. aad-oidc-identity creates a JWT (with the sub `system:serviceaccount:team1:team1`) and signs it with its own JWK\n1. aad-oidc-identity sends the new JWT using the [Client Credentials Grant Flow](https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow#third-case-access-token-request-with-a-federated-credential) to Azure AD\n1. Azure AD goes out to the OIDC Discovery Endpoint (metadata) based on the configured `issuer`, `https://aks-oidc.domain.com/.well-known/openid-configuration`, and grabs the `jwks_uri` from the JSON response\n1. Azure AD goes out to the `jwks_uri`, `https://aks-oidc.domain.com/jwks`, and downloads the public key(s)\n1. Azure AD validates the token based on the downloaded public key(s) and if valid issues an Azure AD access token\n1. aad-oidc-identity receives the Azure AD access token and responds with it to the pod (app)\n1. The pod now has an Azure AD access token that it can use for whatever tasks needed\n\n## Development\n\n## Testing\n\n```shell\nkubectl apply -f test/client-deployment.yaml\nkubectl exec -it client /bin/sh\nTOKEN=$(cat /var/run/secrets/tokens/oidc-token)\ncurl -v -H \"Authorization: Bearer ${TOKEN}\" -k http://aad-oidc-identity/token/azure\n```\n\n## Add custom federated identity\n\n```shell\naz rest --method POST --uri 'https://graph.microsoft.com/beta/applications/${APP_OBJECT_ID}/federatedIdentityCredentials' --body '{\"name\":\"Testing\",\"issuer\":\"${EXTERNAL_ISSUER}\",\"subject\":\"system:serviceaccount:default:default\",\"description\":\"Testing\",\"audiences\":[\"api://AzureADTokenExchange\"]}'\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxenitab%2Faad-oidc-identity","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxenitab%2Faad-oidc-identity","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxenitab%2Faad-oidc-identity/lists"}