[AIENG-545][Backend] OIDC Jenkins provider support + verify --oidc flow#1351
Conversation
| self.metavar = metavar | ||
| self.multiple = multiple | ||
| self.hidden = hidden | ||
| # When True, the value is taken ONLY from an inline `--opt=value` form; a bare `--opt` |
There was a problem hiding this comment.
I understand the motivation, but unless I’m missing something, it looks like the newly added verify options aren’t actually being used anywhere as a boolean flag.
Am I misunderstanding something?
There was a problem hiding this comment.
refactored this now.
| # A pipeline that authenticated via `verify --oidc` carries no SMART_TESTS_TOKEN; it presents | ||
| # its OIDC id-token directly. Intake routes this by `iss` (RESTAuthVerifier) to the generic OIDC | ||
| # verifier, so subsequent workspace-scoped calls authenticate with the same JWT. | ||
| oidc_token = get_oidc_token() |
There was a problem hiding this comment.
This is probably a rare case, but if both SMART_TESTS_TOKEN and the OIDC token are set, SMART_TESTS_TOKEN will take precedence. Is that intentional?
I don’t see a strong reason to make it an error, but just in case
There was a problem hiding this comment.
Yeah, SMART_TESTS_TOKEN takes precedence as I thought it is primary auth mechanism. I will check @samyakk-rai for the same
| # (kept in SMART_TESTS_OIDC_TOKEN) as their bearer. | ||
| click.echo(f'export {ORGANIZATION_KEY}={_shell_quote(org)}') | ||
| click.echo(f'export {WORKSPACE_KEY}={_shell_quote(workspace)}') | ||
| click.echo(f'export {OIDC_TOKEN_KEY}={_shell_quote(token)}') |
There was a problem hiding this comment.
Do we really need to export OIDC_TOKEN_KEY? The token must be present to run the command, so this might create unnecessary credential exposure.
There was a problem hiding this comment.
this is to support jenkins cred binding plugin. As it can pass the jwt to env, we have this env introduced. other OIDC supports either local envs or APIs to get the token and Jenkins is quite different.
| # bearer by authentication_headers(). | ||
| http_client = _HttpClient(app=app_instance) | ||
| try: | ||
| res = http_client.request("post", OIDC_VERIFY_PATH, payload={}) |
There was a problem hiding this comment.
Personal opinion: When I read the code, I lost track of where the token was configured. Passing token in the header directly seems more natural to me because we've already gotten the token in the previous step.
| res = http_client.request("post", OIDC_VERIFY_PATH, payload={}) | |
| res = http_client.request("post", OIDC_VERIFY_PATH, payload={}, additional_headers={"Authorization": f"Bearer {token}"}) |
Summary
Adds tokenless authentication to the CLI using any OIDC identity provider the CI can act as (Jenkins via the oidc-provider plugin, GitLab, custom IdPs). Instead of a static SMART_TESTS_TOKEN, the pipeline presents a short-lived, signed OIDC id-token that Intake verifies cryptographically. This is the CLI half of AIENG-545 Phase 2 (the Intake backend + WebApp changes ship separately).
Two new actions on the verify command:
smart-tests verify --oidcCredential-free bootstrap. Presents the id-token to /intake/oidc/verify, prints eval-able export lines for org/workspace/token so later commands authenticate with the same JWT.
smart-tests verify --oidc-fetch-issuerRun from inside a private network. Reads the issuer from the token, fetches its public JWKS via OIDC discovery, and prints an {issuer, jwks} block for an admin to paste into the WebApp. Authenticates nothing; contacts only the issuer.