Skip to content

[AIENG-545][Backend] OIDC Jenkins provider support + verify --oidc flow#1351

Merged
gokul-cloudbees merged 4 commits into
mainfrom
AIENG-545-Ph-2
Jul 8, 2026
Merged

[AIENG-545][Backend] OIDC Jenkins provider support + verify --oidc flow#1351
gokul-cloudbees merged 4 commits into
mainfrom
AIENG-545-Ph-2

Conversation

@gokul-cloudbees

@gokul-cloudbees gokul-cloudbees commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

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 --oidc

Credential-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-issuer

Run 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.

@gokul-cloudbees
gokul-cloudbees marked this pull request as ready for review July 3, 2026 17:01
Comment thread smart_tests/args4p/option.py Outdated
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`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

@gokul-cloudbees gokul-cloudbees Jul 7, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, SMART_TESTS_TOKEN takes precedence as I thought it is primary auth mechanism. I will check @samyakk-rai for the same

@gokul-cloudbees
gokul-cloudbees requested a review from Konboi July 7, 2026 10:20
# (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)}')

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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={})

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
res = http_client.request("post", OIDC_VERIFY_PATH, payload={})
res = http_client.request("post", OIDC_VERIFY_PATH, payload={}, additional_headers={"Authorization": f"Bearer {token}"})

@gokul-cloudbees
gokul-cloudbees merged commit e24d7a6 into main Jul 8, 2026
3 checks passed
@gokul-cloudbees
gokul-cloudbees deleted the AIENG-545-Ph-2 branch July 8, 2026 08:32
@github-actions github-actions Bot mentioned this pull request Jul 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants