Skip to content

Commit

Permalink
Update oidc provider detection
Browse files Browse the repository at this point in the history
Signed-off-by: Appu Goundan <[email protected]>
  • Loading branch information
loosebazooka committed Apr 11, 2024
1 parent 8bd98de commit 84c11d0
Show file tree
Hide file tree
Showing 9 changed files with 108 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import dev.sigstore.oidc.client.OidcException;
import dev.sigstore.oidc.client.OidcToken;
import java.io.IOException;
import java.util.Map;

public class TokenStringOidcClient implements OidcClient {

Expand All @@ -32,12 +33,12 @@ public TokenStringOidcClient(String idToken) {
}

@Override
public boolean isEnabled() {
public boolean isEnabled(Map<String, String> env) {
return true;
}

@Override
public OidcToken getIDToken() throws OidcException {
public OidcToken getIDToken(Map<String, String> env) throws OidcException {
try {
var jws = JsonWebSignature.parse(new GsonFactory(), idToken);
return ImmutableOidcToken.builder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import dev.sigstore.http.ImmutableHttpParams;
import io.grpc.Internal;
import java.io.IOException;
import java.util.Map;
import java.util.logging.Logger;

/**
Expand All @@ -35,9 +36,9 @@ public class GithubActionsOidcClient implements OidcClient {

private static final Logger log = Logger.getLogger(GithubActionsOidcClient.class.getName());

private static final String GITHUB_ACTIONS_KEY = "GITHUB_ACTIONS";
private static final String REQUEST_TOKEN_KEY = "ACTIONS_ID_TOKEN_REQUEST_TOKEN";
private static final String REQUEST_URL_KEY = "ACTIONS_ID_TOKEN_REQUEST_URL";
static final String GITHUB_ACTIONS_KEY = "GITHUB_ACTIONS";
static final String REQUEST_TOKEN_KEY = "ACTIONS_ID_TOKEN_REQUEST_TOKEN";
static final String REQUEST_URL_KEY = "ACTIONS_ID_TOKEN_REQUEST_URL";

private static final String DEFAULT_AUDIENCE = "sigstore";

Expand Down Expand Up @@ -75,19 +76,25 @@ public GithubActionsOidcClient build() {
}

@Override
public boolean isEnabled() {
var githubActions = System.getenv(GITHUB_ACTIONS_KEY);
public boolean isEnabled(Map<String, String> env) {
var githubActions = env.get(GITHUB_ACTIONS_KEY);
if (githubActions == null || githubActions.isEmpty()) {
log.fine("Github env not detected: skipping github actions oidc");
return false;
}
var bearer = env.get(REQUEST_TOKEN_KEY);
var urlBase = env.get(REQUEST_URL_KEY);
if (bearer == null || bearer.isEmpty() || urlBase == null || urlBase.isEmpty()) {
log.info("Github env detected, but github idtoken not found: skipping github actions oidc");
return false;
}
return true;
}

@Override
public OidcToken getIDToken() throws OidcException {
var bearer = System.getenv(REQUEST_TOKEN_KEY);
var urlBase = System.getenv(REQUEST_URL_KEY);
public OidcToken getIDToken(Map<String, String> env) throws OidcException {
var bearer = env.get(REQUEST_TOKEN_KEY);
var urlBase = env.get(REQUEST_URL_KEY);
if (bearer == null) {
throw new OidcException(
"Could not get github actions environment variable '" + REQUEST_TOKEN_KEY + "'");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,18 @@
*/
package dev.sigstore.oidc.client;

import java.util.Map;

public interface OidcClient {

/**
* Determine if this client can be used in the current environment. For example, we can ignore
* Oidc Clients that are scoped to a specific CI environment
*
* @param env the configured system environment
* @return true if we should use credentials from this client
*/
boolean isEnabled();
boolean isEnabled(Map<String, String> env);

OidcToken getIDToken() throws OidcException;
OidcToken getIDToken(Map<String, String> env) throws OidcException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,14 @@
package dev.sigstore.oidc.client;

import com.google.common.collect.ImmutableList;
import java.util.Map;
import java.util.logging.Logger;

/** An ordered list of oidc clients to use when looking for credentials. */
public class OidcClients {

private static final Logger log = Logger.getLogger(OidcClients.class.getName());

public static final OidcClients PUBLIC_GOOD =
of(GithubActionsOidcClient.builder().build(), WebOidcClient.builder().build());

Expand All @@ -29,13 +33,15 @@ public class OidcClients {
WebOidcClient.builder().setIssuer(WebOidcClient.STAGING_DEX_ISSUER).build());

private final ImmutableList<OidcClient> clients;
private final Map<String, String> env;

public static OidcClients of(OidcClient... clients) {
return new OidcClients(ImmutableList.copyOf(clients));
return new OidcClients(ImmutableList.copyOf(clients), System.getenv());
}

private OidcClients(ImmutableList<OidcClient> clients) {
private OidcClients(ImmutableList<OidcClient> clients, Map<String, String> env) {
this.clients = clients;
this.env = env;
}

/**
Expand All @@ -47,10 +53,12 @@ private OidcClients(ImmutableList<OidcClient> clients) {
*/
public OidcToken getIDToken() throws OidcException {
for (var client : clients) {
if (client.isEnabled()) {
return client.getIDToken();
if (client.isEnabled(env)) {
return client.getIDToken(env);
}
}
log.info(
"Could not find an oidc provider, if you are in CI make sure the token is available to the sigstore signing process");
throw new OidcException("Could not find an oidc provider");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,16 @@
import java.io.IOException;
import java.util.Arrays;
import java.util.Locale;
import java.util.Map;
import java.util.logging.Logger;

/**
* A client to obtain oidc tokens from an oauth provider via web workflow for use with sigstore. By
* default this client is configued to use the public sigstore dex instance.
*/
public class WebOidcClient implements OidcClient {
private static final Logger log = Logger.getLogger(WebOidcClient.class.getName());

public static final String PUBLIC_DEX_ISSUER = "https://oauth2.sigstore.dev/auth";
public static final String STAGING_DEX_ISSUER = "https://oauth2.sigstage.dev/auth";

Expand Down Expand Up @@ -112,12 +116,13 @@ public WebOidcClient build() {
}
}

/**
* This provider is always enabled by default, however it should be lower priority over other
* providers which obtain ambient credentials.
*/
/** This provider is usually enabled unless we're in CI. */
@Override
public boolean isEnabled() {
public boolean isEnabled(Map<String, String> env) {
if ("true".equalsIgnoreCase(env.get("CI"))) {
log.info("Skipping browser based oidc provider because CI detected");
return false;
}
return true;
}

Expand All @@ -128,7 +133,7 @@ public boolean isEnabled() {
* @throws OidcException if an error occurs doing the authorization flow
*/
@Override
public OidcToken getIDToken() throws OidcException {
public OidcToken getIDToken(Map<String, String> env) throws OidcException {
JsonFactory jsonFactory = new GsonFactory();
HttpTransport httpTransport = HttpClients.newHttpTransport(httpParams);
DataStoreFactory memStoreFactory = new MemoryDataStoreFactory();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,8 @@ public void sign_passGithubOidcCheck() throws Exception {
// silly way to get the right oidc identity to make sure our simple matcher works
var jws =
JsonWebSignature.parse(
new GsonFactory(), GithubActionsOidcClient.builder().build().getIDToken().getIdToken());
new GsonFactory(),
GithubActionsOidcClient.builder().build().getIDToken(System.getenv()).getIdToken());
var expectedGithubSubject = jws.getPayload().getSubject();
var signer =
KeylessSigner.builder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,56 @@

import dev.sigstore.testkit.annotations.EnabledIfOidcExists;
import dev.sigstore.testkit.annotations.OidcProviderType;
import io.github.netmikey.logunit.api.LogCapturer;
import java.util.Map;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.slf4j.event.Level;

public class GithubActionsOidcClientTest {

@RegisterExtension
LogCapturer logs =
LogCapturer.create().captureForType(GithubActionsOidcClient.class, Level.DEBUG);

@Test
@EnabledIfOidcExists(provider = OidcProviderType.GITHUB)
public void getToken() throws OidcException {
var client = GithubActionsOidcClient.builder().build();
var token = client.getIDToken();
var token = client.getIDToken(System.getenv());

Assertions.assertNotNull(token.getSubjectAlternativeName());
Assertions.assertNotNull(token.getIdToken());
}

@Test
public void isEnabled_github() {
var client = GithubActionsOidcClient.builder().build();
var env =
Map.of(
GithubActionsOidcClient.GITHUB_ACTIONS_KEY,
"ignored",
GithubActionsOidcClient.REQUEST_TOKEN_KEY,
"ignored",
GithubActionsOidcClient.REQUEST_URL_KEY,
"ignored");
Assertions.assertTrue(client.isEnabled(env));
}

@Test
public void isEnabled_githubButNoTokenInfo() {
var client = GithubActionsOidcClient.builder().build();
var env = Map.of(GithubActionsOidcClient.GITHUB_ACTIONS_KEY, "ignored");
Assertions.assertFalse(client.isEnabled(env));
logs.assertContains(
"Github env detected, but github idtoken not found: skipping github actions oidc");
}

@Test
public void isEnabled_notGithub() {
var client = GithubActionsOidcClient.builder().build();
Assertions.assertFalse(client.isEnabled(Map.of()));
logs.assertContains("Github env not detected: skipping github actions oidc");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,21 @@

import com.gargoylesoftware.htmlunit.WebClient;
import dev.sigstore.testing.MockOAuth2ServerExtension;
import io.github.netmikey.logunit.api.LogCapturer;
import java.util.Map;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.slf4j.event.Level;

public class WebOidcClientTest {

@RegisterExtension
private static final MockOAuth2ServerExtension server = new MockOAuth2ServerExtension();

@RegisterExtension
LogCapturer logs = LogCapturer.create().captureForType(WebOidcClient.class, Level.DEBUG);

@Test
public void testAuthFlow() throws OidcException {
try (var webClient = new WebClient()) {
Expand All @@ -35,9 +41,22 @@ public void testAuthFlow() throws OidcException {
.setBrowser(webClient::getPage)
.build();

var eid = oidcClient.getIDToken();
var eid = oidcClient.getIDToken(System.getenv());
Assertions.assertEquals(
MockOAuth2ServerExtension.DEFAULT_CONFIGURED_EMAIL, eid.getSubjectAlternativeName());
}
}

@Test
public void isEnabled_CI() {
var client = WebOidcClient.builder().build();
Assertions.assertFalse(client.isEnabled(Map.of("CI", "true")));
logs.assertContains("Skipping browser based oidc provider because CI detected");
}

@Test
public void isEnabled_notCI() {
var client = WebOidcClient.builder().build();
Assertions.assertTrue(client.isEnabled(Map.of("CI", "false")));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public OidcToken getOidcToken() throws OidcException {
.setBrowser(webClient::getPage)
.build();

return oidcClient.getIDToken();
return oidcClient.getIDToken(System.getenv());
}
}

Expand Down

0 comments on commit 84c11d0

Please sign in to comment.