Skip to content

[AIENG-679] Unify GitHub Actions OIDC onto the generic OIDC flow - #1366

Open
gokul-cloudbees wants to merge 4 commits into
mainfrom
AIENG-679
Open

[AIENG-679] Unify GitHub Actions OIDC onto the generic OIDC flow#1366
gokul-cloudbees wants to merge 4 commits into
mainfrom
AIENG-679

Conversation

@gokul-cloudbees

@gokul-cloudbees gokul-cloudbees commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Summary

Routes GitHub Actions OIDC through the same generic flow used for Jenkins. The legacy path is preserved behind an explicit opt-in.

Changes

  • New env var SMART_TESTS_GITHUB_OIDC_TOKEN_AUTH=1. CLI fetches the runner's id-token with audience=https://app.cloudbees.io/smart-tests and presents it as a plain OIDC bearer (same code path as SMART_TESTS_OIDC_TOKEN for Jenkins)
    • Legacy env var EXPERIMENTAL_GITHUB_OIDC_TOKEN_AUTH=1 still works, but now: Fetches the id-token without an audience (as before).
      • Adds the GitHub-OIDC-Legacy: 1 header so Intake routes to the legacy verifier.
      • Prints a deprecation warning pointing at the migration doc.
    • Added OIDC_AUDIENCE_KEY for callers that need a non-default audience.

@gokul-cloudbees gokul-cloudbees changed the title [AIENG-679][CLI] apply generic OIDC flow for github default and send … [AIENG-679] Unify GitHub Actions OIDC onto the generic OIDC flow Aug 27, 2026
@ono-max

ono-max commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Should we modify the Java part? I guess we need to do the same thing there, too.

/** Ensures all the configuration is properly in place. */
private void parseConfiguration() throws CmdLineException {
String apiToken = launchableToken;
if (launchableToken == null) {
apiToken = System.getenv("SMART_TESTS_TOKEN");
}
if (apiToken == null || apiToken.isEmpty()) {
if (System.getenv("GITHUB_ACTIONS") != null) {
String o = System.getenv("SMART_TESTS_ORGANIZATION");
if (org == null && o == null) {
throw new CmdLineException("SMART_TESTS_ORGANIZATION env variable is not set");
}
String w = System.getenv("SMART_TESTS_WORKSPACE");
if (ws == null && w == null) {
throw new CmdLineException("SMART_TESTS_WORKSPACE env variable is not set");
}
if (org == null) {
this.org = o;
}
if (ws == null) {
this.ws = w;
}
if (System.getenv("EXPERIMENTAL_GITHUB_OIDC_TOKEN_AUTH") != null) {
authenticator = new GitHubIdTokenAuthenticator();
} else {
authenticator = new GitHubActionsAuthenticator();
}
return;
}
throw new CmdLineException("SMART_TESTS_TOKEN env variable is not set");
}
this.parseLaunchableToken(apiToken);
}

Comment thread smart_tests/utils/authentication.py Outdated
# The header tells Intake to take the legacy branch; without it the token would be verified
# through the generic path.
if os.getenv(LEGACY_GITHUB_OIDC_KEY):
click.secho(

@ono-max ono-max Aug 31, 2026

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 warning is within authentication_headers method, meaning that CLI will print it every time API is called. It might be annoyed, so can we think about a way to reduce the frequency?

@ono-max
ono-max requested a review from gayanW August 31, 2026 07:52
gokul-cloudbees and others added 2 commits August 31, 2026 16:43
Java commit-ingester source changed in 58359b5 but the checked-in jar
was not rebuilt, failing the "Check exe_deploy.jar is up to date" CI step.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

if (System.getenv("EXPERIMENTAL_GITHUB_OIDC_TOKEN_AUTH") != null) {
authenticator = new GitHubIdTokenAuthenticator();
if (System.getenv("SMART_TESTS_GITHUB_OIDC_TOKEN_AUTH") != null) {

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.

// and matches the normalized `repo:OWNER/REPO` subject against trusted_oidc_subjects. The
// audience is required because the generic path enforces `aud` for GitHub's issuer.
String audience = System.getenv("SMART_TESTS_OIDC_AUDIENCE");
if (audience == null || audience.isEmpty()) {

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.

audience = GitHubIdTokenAuthenticator.DEFAULT_OIDC_AUDIENCE;
}
authenticator = new GitHubIdTokenAuthenticator(audience, false);
} else if (System.getenv("EXPERIMENTAL_GITHUB_OIDC_TOKEN_AUTH") != null) {

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.

@ono-max

ono-max commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

In the following code, we first check if SMART_TESTS_OIDC_TOKEN exists in get_oidc_token() method, right? However, in the new OIDC flow for GH, we are asking users to configure SMART_TESTS_GITHUB_OIDC_TOKEN_AUTH, not SMART_TESTS_OIDC_TOKEN. Do we need to check SMART_TESTS_GITHUB_OIDC_TOKEN_AUTH in verify_oidc() method?

def verify_oidc(app_instance: Application):
'''
Credential-free OIDC bootstrap. Presents the pipeline's OIDC id-token to Intake's
/intake/oidc/verify endpoint and translates the 200/403/401 contract into CLI behavior:
- 200: the subject is registered. Print `export` lines (org/workspace/oidc-token) so the
pipeline can `eval "$(smart-tests verify --oidc)"` and authenticate subsequent
commands with the same token. Exit 0.
- 403: the token verified but its subject isn't registered to any workspace yet. Show the
normalized `sub` so the user can register it from the WebApp settings. Exit 1.
- 401: the token is missing/expired/invalid. Exit 1.
'''
tracking_client = TrackingClient(Command.VERIFY, app=app_instance)
token = get_oidc_token()
if not token:
msg = (f"OIDC authentication requires the {OIDC_TOKEN_KEY} environment variable to hold the "
"pipeline's OIDC id-token. In Jenkins, bind an id-token credential to this variable; "
"see the OIDC pipeline-authentication setup guide.")
click.secho(msg, fg='red', err=True)
tracking_client.send_error_event(
event_name=Tracking.ErrorEvent.USER_ERROR,
stack_trace=msg,
)
raise typer.Exit(2)

@ono-max

ono-max commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

@gokul-cloudbees

The following comments are just trivial changes, so you don't have to address them, but the last comment here might be critical, so you can focus on it.

#1366 (comment)
#1366 (comment)
#1366 (comment)

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.

2 participants