diff --git a/docs/provider_github_actions.md b/docs/provider_github_actions.md index 720b35bfddc..abb5633ca43 100644 --- a/docs/provider_github_actions.md +++ b/docs/provider_github_actions.md @@ -175,3 +175,45 @@ The following changes are necessary for the ZTS server to support GitHub Actions - ZTS enforces IP ranges where services are authorized to request identities for service identities from a given provider. It is expected that the worker nodes for a team will be configured to run in their own private AWS accounts, for example, and as such the team needs to provide the NAT gateway IP addresses for the account, so they can be authorized. + + +The following attributes must be configured in the ZTS server configuration file: + +```sh +athenz.zts.github_actions.provider_dns_suffix= +athenz.zts.github_actions.issuer= +athenz.zts.github_actions.audience= +``` + +By default, your `issuer` value will generate a derived `jwks_uri` with the suffix `/.well-known/openid-configuration`, which is used to fetch the public keys for validating the OIDC token signature. If you want to use a different endpoint for fetching the public keys, you can specify `jwks_uri`: + +```sh +athenz.zts.github_actions.jwks_uri=https://your-github-website.com/_services/token/.well-known/jwks +``` + +If you want to use multiple environments for the same GitHub Actions provider, you can create a JSON file locally on your ZTS server and specify its path with `athenz.zts.github_actions.prop_file_path` in your ZTS server configuration file. The JSON file should contain an array of objects with the following attributes: + +> [!WARNING] +> It is recommended to use the `prop_file_path` attribute only if you want to offer multiple environments for the same GitHub Actions provider. If you want to use only one environment, you can set the attributes directly in the ZTS server configuration file. The `prop_file_path` will override your direct configuration in the ZTS server configuration file if the same `issuer` is used in the JSON file + +```json +{ + "props": [ + { + "provider_dns_suffix": "test-provider-suffix,another-test-provider-suffix", + "enterprise": "test-enterprise", + "audience": "test-audience", + "issuer": "test-issuer", + "jwks_uri": "https://test-jwks-uri.com/openid/v1/jwks" + }, + { + "provider_dns_suffix": "test-provider-suffix,another-test-provider-suffix", + "enterprise": "test-enterprise", + "audience": "test-audience", + "issuer": "test-issuer", + "jwks_uri": "https://test-jwks-uri.com/openid/v1/jwks" + }, + ... + ] +} +``` diff --git a/libs/java/instance_provider/src/main/java/com/yahoo/athenz/instance/provider/impl/InstanceGithubActionsProvider.java b/libs/java/instance_provider/src/main/java/com/yahoo/athenz/instance/provider/impl/InstanceGithubActionsProvider.java index 75c8a6a4214..3bd603a87d8 100644 --- a/libs/java/instance_provider/src/main/java/com/yahoo/athenz/instance/provider/impl/InstanceGithubActionsProvider.java +++ b/libs/java/instance_provider/src/main/java/com/yahoo/athenz/instance/provider/impl/InstanceGithubActionsProvider.java @@ -15,6 +15,8 @@ */ package com.yahoo.athenz.instance.provider.impl; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.core.type.TypeReference; import com.nimbusds.jose.proc.SecurityContext; import com.nimbusds.jwt.JWTClaimsSet; import com.nimbusds.jwt.proc.ConfigurableJWTProcessor; @@ -33,8 +35,15 @@ import org.slf4j.LoggerFactory; import javax.net.ssl.SSLContext; +import com.nimbusds.jwt.SignedJWT; + +import java.io.IOException; import java.util.*; import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import static com.yahoo.athenz.common.server.util.config.ConfigManagerSingleton.CONFIG_MANAGER; @@ -45,13 +54,21 @@ public class InstanceGithubActionsProvider implements InstanceProvider { private static final String URI_INSTANCE_ID_PREFIX = "athenz://instanceid/"; private static final String URI_SPIFFE_PREFIX = "spiffe://"; - static final String GITHUB_ACTIONS_PROP_PROVIDER_DNS_SUFFIX = "athenz.zts.github_actions.provider_dns_suffix"; + static final String KEY_PROVIDER_DNS_SUFFIX = "provider_dns_suffix"; + static final String KEY_AUDIENCE = "audience"; + static final String KEY_ENTERPRISE = "enterprise"; + static final String KEY_JWKS_URI = "jwks_uri"; + static final String KEY_ISSUER = "issuer"; + static final String KEY_JWK_PROCESSOR = "jwk_processor"; + + static final String GITHUB_ACTIONS_PROP_FILE_PATH = "athenz.zts.github_actions.prop_file_path"; + static final String GITHUB_ACTIONS_PROP_PROVIDER_DNS_SUFFIX = "athenz.zts.github_actions." + KEY_PROVIDER_DNS_SUFFIX; static final String GITHUB_ACTIONS_PROP_BOOT_TIME_OFFSET = "athenz.zts.github_actions.boot_time_offset"; static final String GITHUB_ACTIONS_PROP_CERT_EXPIRY_TIME = "athenz.zts.github_actions.cert_expiry_time"; - static final String GITHUB_ACTIONS_PROP_ENTERPRISE = "athenz.zts.github_actions.enterprise"; - static final String GITHUB_ACTIONS_PROP_AUDIENCE = "athenz.zts.github_actions.audience"; - static final String GITHUB_ACTIONS_PROP_ISSUER = "athenz.zts.github_actions.issuer"; - static final String GITHUB_ACTIONS_PROP_JWKS_URI = "athenz.zts.github_actions.jwks_uri"; + static final String GITHUB_ACTIONS_PROP_ENTERPRISE = "athenz.zts.github_actions." + KEY_ENTERPRISE; + static final String GITHUB_ACTIONS_PROP_AUDIENCE = "athenz.zts.github_actions." + KEY_AUDIENCE; + static final String GITHUB_ACTIONS_PROP_ISSUER = "athenz.zts.github_actions." + KEY_ISSUER; + static final String GITHUB_ACTIONS_PROP_JWKS_URI = "athenz.zts.github_actions." + KEY_JWKS_URI; static final String GITHUB_ACTIONS_ISSUER = "https://token.actions.githubusercontent.com"; static final String GITHUB_ACTIONS_ISSUER_JWKS_URI = "https://token.actions.githubusercontent.com/.well-known/jwks"; @@ -61,21 +78,56 @@ public class InstanceGithubActionsProvider implements InstanceProvider { public static final String CLAIM_EVENT_NAME = "event_name"; public static final String CLAIM_REPOSITORY = "repository"; - Set dnsSuffixes = null; - String githubIssuer = null; + Map> props = null; + // Set dnsSuffixes = null; // TODO: Wanna remove this + // String githubIssuer = null; // TODO: Wanna remove this String provider = null; - String audience = null; - String enterprise = null; - ConfigurableJWTProcessor jwtProcessor = null; + // String audience = null; // TODO: Wanna remove this + // String enterprise = null; // TODO: Wanna remove this + // ConfigurableJWTProcessor jwtProcessor = null; // TODO: Wanna remove this Authorizer authorizer = null; - DynamicConfigLong bootTimeOffsetSeconds; - long certExpiryTime; + DynamicConfigLong bootTimeOffsetSeconds; // TODO: Wanna remove this + long certExpiryTime; // ? USE THIS AS THE ONLY SOURCE? @Override public Scheme getProviderScheme() { return Scheme.CLASS; } + public void initializeFromFilePath() throws ProviderResourceException { + final String propFilePath = System.getProperty(GITHUB_ACTIONS_PROP_FILE_PATH, ""); + if (StringUtil.isEmpty(propFilePath)) { + return; // no prop file path specified, nothing to do + } + + Path path = Paths.get(propFilePath); + try { + Map>> propJson = new ObjectMapper().readValue( + Files.readAllBytes(path), + new TypeReference>>>() { } + ); + + for (Map prop : propJson.get("props")) { + String issuer = (String) prop.get(KEY_ISSUER); + if (StringUtil.isEmpty(issuer)) { + throw forbiddenError("Missing required issuer prop file: " + propFilePath); + } + + // Put Data: + props.put(issuer, Map.of( + KEY_PROVIDER_DNS_SUFFIX, (String) prop.get(KEY_PROVIDER_DNS_SUFFIX), + KEY_AUDIENCE, (String) prop.get(KEY_AUDIENCE), + KEY_ENTERPRISE, (String) prop.get(KEY_ENTERPRISE), // optional + KEY_JWKS_URI, extractGitHubIssuerJwksUri(issuer, (String) prop.get(KEY_JWKS_URI)) + )); + } + + } catch (IOException ex) { + throw forbiddenError("Unable to parse jwk endpoints file: " + propFilePath + + ", error: " + ex.getMessage()); + } + } + @Override public void initialize(String provider, String providerEndpoint, SSLContext sslContext, KeyStore keyStore) { @@ -86,13 +138,14 @@ public void initialize(String provider, String providerEndpoint, SSLContext sslC // lookup the zts audience. if not specified we'll default to athenz.io - audience = System.getProperty(GITHUB_ACTIONS_PROP_AUDIENCE, "athenz.io"); + // audience = System.getProperty(GITHUB_ACTIONS_PROP_AUDIENCE, "athenz.io"); // determine the dns suffix. if this is not specified we'll just default to github-actions.athenz.cloud - final String dnsSuffix = System.getProperty(GITHUB_ACTIONS_PROP_PROVIDER_DNS_SUFFIX, "github-actions.athenz.io"); - dnsSuffixes = new HashSet<>(); - dnsSuffixes.addAll(Arrays.asList(dnsSuffix.split(","))); + // TODO: I dont have to do this here, I can just do so once I send it to the function for InstanceUtils.validateCertRequestSanDnsNames() + // final String dnsSuffix = System.getProperty(GITHUB_ACTIONS_PROP_PROVIDER_DNS_SUFFIX, "github-actions.athenz.io"); + // dnsSuffixes = new HashSet<>(); + // dnsSuffixes.addAll(Arrays.asList(dnsSuffix.split(","))); // how long the instance must be booted in the past before we // stop validating the instance requests @@ -102,7 +155,7 @@ public void initialize(String provider, String providerEndpoint, SSLContext sslC // determine if we're running in enterprise mode - enterprise = System.getProperty(GITHUB_ACTIONS_PROP_ENTERPRISE); + // enterprise = System.getProperty(GITHUB_ACTIONS_PROP_ENTERPRISE); // TODO: Remove ME! // get default/max expiry time for any generated tokens - 6 hours @@ -110,15 +163,34 @@ public void initialize(String provider, String providerEndpoint, SSLContext sslC // initialize our jwt processor - githubIssuer = System.getProperty(GITHUB_ACTIONS_PROP_ISSUER, GITHUB_ACTIONS_ISSUER); - jwtProcessor = JwtsHelper.getJWTProcessor(new JwtsSigningKeyResolver(extractGitHubIssuerJwksUri(githubIssuer), null)); + // githubIssuer = System.getProperty(GITHUB_ACTIONS_PROP_ISSUER, GITHUB_ACTIONS_ISSUER); // TODO: Remove ME! + // // TODO: Remove BELOW! + // jwtProcessor = JwtsHelper.getJWTProcessor(new JwtsSigningKeyResolver(extractGitHubIssuerJwksUri(githubIssuer, System.getProperty(GITHUB_ACTIONS_PROP_JWKS_URI)), null)); + + props.put(System.getProperty(GITHUB_ACTIONS_PROP_ISSUER, GITHUB_ACTIONS_ISSUER), Map.of( + KEY_PROVIDER_DNS_SUFFIX, System.getProperty(GITHUB_ACTIONS_PROP_PROVIDER_DNS_SUFFIX, "github-actions.athenz.io"), + KEY_AUDIENCE, System.getProperty(GITHUB_ACTIONS_PROP_AUDIENCE, "athenz.io"), + KEY_ENTERPRISE, System.getProperty(GITHUB_ACTIONS_PROP_ENTERPRISE), // optional + KEY_JWKS_URI, extractGitHubIssuerJwksUri( + System.getProperty(GITHUB_ACTIONS_PROP_ISSUER, GITHUB_ACTIONS_ISSUER), + System.getProperty(GITHUB_ACTIONS_PROP_JWKS_URI) + ), + KEY_JWK_PROCESSOR, JwtsHelper.getJWTProcessor(new JwtsSigningKeyResolver(extractGitHubIssuerJwksUri( + System.getProperty(GITHUB_ACTIONS_PROP_ISSUER, GITHUB_ACTIONS_ISSUER), + System.getProperty(GITHUB_ACTIONS_PROP_JWKS_URI) + ), null)) + )); + try { + initializeFromFilePath(); // initialize from file path if specified. If not specified, nothing happens. + } catch (ProviderResourceException ex) { + LOGGER.error("Unable to initialize from file path: {}", ex.getMessage()); + } } - String extractGitHubIssuerJwksUri(final String issuer) { + String extractGitHubIssuerJwksUri(final String issuer, String jwksUri) { // if we have the value configured then that's what we're going to use - String jwksUri = System.getProperty(GITHUB_ACTIONS_PROP_JWKS_URI); if (!StringUtil.isEmpty(jwksUri)) { return jwksUri; } @@ -187,17 +259,28 @@ public InstanceConfirmation confirmInstance(InstanceConfirmation confirmation) t } StringBuilder errMsg = new StringBuilder(256); + + String claimIssuer = null; + try { + // parse the token and get the issuer claim + claimIssuer = SignedJWT.parse(attestationData).getJWTClaimsSet().getIssuer(); + } catch (Exception ex) { + errMsg.append("Unable to parse token: ").append(ex.getMessage()); + throw forbiddenError("Unable to parse token: " + ex.getMessage()); + } + final String reqInstanceId = InstanceUtils.getInstanceProperty(instanceAttributes, InstanceProvider.ZTS_INSTANCE_ID); - if (!validateOIDCToken(attestationData, instanceDomain, instanceService, reqInstanceId, errMsg)) { - throw forbiddenError("Unable to validate Certificate Request: " + errMsg); + if (!validateOIDCToken(claimIssuer, attestationData, instanceDomain, instanceService, reqInstanceId, errMsg)) { + throw forbiddenError("Unable to validate Certificate Request: " + errMsg); } // validate the certificate san DNS names StringBuilder instanceId = new StringBuilder(256); + if (!InstanceUtils.validateCertRequestSanDnsNames(instanceAttributes, instanceDomain, - instanceService, dnsSuffixes, null, null, false, instanceId, null)) { + instanceService, Arrays.stream(((String) props.get(claimIssuer).get(KEY_PROVIDER_DNS_SUFFIX)).split(",")).collect(Collectors.toSet()), null, null, false, instanceId, null)) { throw forbiddenError("Unable to validate certificate request sanDNS entries"); } @@ -245,8 +328,23 @@ boolean validateSanUri(final String sanUri) { return true; } - boolean validateOIDCToken(final String jwToken, final String domainName, final String serviceName, + boolean validateOIDCToken(final String claimIssuer, final String jwToken, final String domainName, final String serviceName, final String instanceId, StringBuilder errMsg) { + if (StringUtil.isEmpty(claimIssuer)) { + errMsg.append("token does not contain required issuer claim"); + return false; + } + + Map prop = props.get(claimIssuer) + .entrySet() + .stream() + .filter(entry -> entry.getValue() instanceof String) + .collect(Collectors.toMap( + Map.Entry::getKey, + entry -> (String) entry.getValue() + )); + + ConfigurableJWTProcessor jwtProcessor = JwtsHelper.getJWTProcessor(new JwtsSigningKeyResolver(prop.get(KEY_JWKS_URI), null)); if (jwtProcessor == null) { errMsg.append("JWT Processor not initialized"); @@ -263,23 +361,23 @@ boolean validateOIDCToken(final String jwToken, final String domainName, final S // verify the issuer in set to GitHub Actions - if (!githubIssuer.equals(claimsSet.getIssuer())) { + if (!prop.get(KEY_ISSUER).equals(claimsSet.getIssuer())) { errMsg.append("token issuer is not GitHub Actions: ").append(claimsSet.getIssuer()); return false; } // verify that token audience is set for our service - if (!audience.equals(JwtsHelper.getAudience(claimsSet))) { + if (!prop.get(KEY_AUDIENCE).equals(JwtsHelper.getAudience(claimsSet))) { errMsg.append("token audience is not ZTS Server audience: ").append(JwtsHelper.getAudience(claimsSet)); return false; } // verify that token issuer is set for our enterprise if one is configured - if (!StringUtil.isEmpty(enterprise)) { + if (!StringUtil.isEmpty((String) prop.get(KEY_ENTERPRISE))) { final String tokenEnterprise = JwtsHelper.getStringClaim(claimsSet, CLAIM_ENTERPRISE); - if (!enterprise.equals(tokenEnterprise)) { + if (!prop.get(KEY_ENTERPRISE).equals(tokenEnterprise)) { errMsg.append("token enterprise is not the configured enterprise: ").append(tokenEnterprise); return false; } diff --git a/libs/java/instance_provider/src/main/java/com/yahoo/athenz/instance/provider/impl/InstanceGithubActionsSample.json b/libs/java/instance_provider/src/main/java/com/yahoo/athenz/instance/provider/impl/InstanceGithubActionsSample.json new file mode 100644 index 00000000000..97ad02ccd41 --- /dev/null +++ b/libs/java/instance_provider/src/main/java/com/yahoo/athenz/instance/provider/impl/InstanceGithubActionsSample.json @@ -0,0 +1,11 @@ +{ + "props": [ + { + "provider_dns_suffix": "test-provider-suffix,another-test-provider-suffix", + "enterprise": "test-enterprise", + "audience": "test-audience", + "issuer": "test-issuer", + "jwks_uri": "https://test-jwks-uri.com/openid/v1/jwks" + } + ] +} \ No newline at end of file diff --git a/libs/java/instance_provider/src/test/java/com/yahoo/athenz/instance/provider/impl/InstanceGithubActionsProviderTest.java b/libs/java/instance_provider/src/test/java/com/yahoo/athenz/instance/provider/impl/InstanceGithubActionsProviderTest.java index 14406732471..2b2f49e4903 100644 --- a/libs/java/instance_provider/src/test/java/com/yahoo/athenz/instance/provider/impl/InstanceGithubActionsProviderTest.java +++ b/libs/java/instance_provider/src/test/java/com/yahoo/athenz/instance/provider/impl/InstanceGithubActionsProviderTest.java @@ -389,9 +389,9 @@ public void testValidateSanUri() { public void testValidateOIDCTokenWithoutJWTProcessor() { InstanceGithubActionsProvider provider = new InstanceGithubActionsProvider(); - + String issuer = "https://token.actions.githubusercontent.com"; StringBuilder errMsg = new StringBuilder(256); - assertFalse(provider.validateOIDCToken("some-jwt", "sports", "api", "athenz:sia:0001", errMsg)); + assertFalse(provider.validateOIDCToken(issuer, "some-jwt", "sports", "api", "athenz:sia:0001", errMsg)); assertTrue(errMsg.toString().contains("JWT Processor not initialized")); provider.close(); @@ -409,10 +409,11 @@ public void testValidateOIDCTokenIssuerMismatch() throws JOSEException { // our issuer will not match - String idToken = generateIdToken("https://token-actions.githubusercontent.com", + String wrongIssuer = "https://token-actions.githubusercontent.com"; + String idToken = generateIdToken(wrongIssuer, System.currentTimeMillis() / 1000, false, false, false, false, false); StringBuilder errMsg = new StringBuilder(256); - boolean result = provider.validateOIDCToken(idToken, "sports", "api", "athenz:sia:0001", errMsg); + boolean result = provider.validateOIDCToken(wrongIssuer, idToken, "sports", "api", "athenz:sia:0001", errMsg); assertFalse(result); assertTrue(errMsg.toString().contains("token issuer is not GitHub Actions")); } @@ -429,10 +430,11 @@ public void testValidateOIDCTokenAudienceMismatch() throws JOSEException { // our audience will not match - String idToken = generateIdToken("https://token.actions.githubusercontent.com", + String issuer = "https://token.actions.githubusercontent.com"; + String idToken = generateIdToken(issuer, System.currentTimeMillis() / 1000, false, false, false, false, false); StringBuilder errMsg = new StringBuilder(256); - boolean result = provider.validateOIDCToken(idToken, "sports", "api", "athenz:sia:0001", errMsg); + boolean result = provider.validateOIDCToken(issuer, idToken, "sports", "api", "athenz:sia:0001", errMsg); assertFalse(result); assertTrue(errMsg.toString().contains("token audience is not ZTS Server audience")); } @@ -450,10 +452,11 @@ public void testValidateOIDCTokenEnterpriseMismatch() throws JOSEException { // our enterprise will not match - String idToken = generateIdToken("https://token.actions.githubusercontent.com", + String issuer = "https://token.actions.githubusercontent.com"; + String idToken = generateIdToken(issuer, System.currentTimeMillis() / 1000, false, false, false, false, false); StringBuilder errMsg = new StringBuilder(256); - boolean result = provider.validateOIDCToken(idToken, "sports", "api", "athenz:sia:0001", errMsg); + boolean result = provider.validateOIDCToken(issuer, idToken, "sports", "api", "athenz:sia:0001", errMsg); assertFalse(result); assertTrue(errMsg.toString().contains("token enterprise is not the configured enterprise")); } @@ -471,19 +474,19 @@ public void testValidateOIDCTokenStartNotRecentEnough() throws JOSEException { // our issue time is not recent enough - String idToken = generateIdToken("https://token.actions.githubusercontent.com", + String issuer = "https://token.actions.githubusercontent.com"; + String idToken = generateIdToken(issuer, System.currentTimeMillis() / 1000 - 400, false, false, false, false, false); StringBuilder errMsg = new StringBuilder(256); - boolean result = provider.validateOIDCToken(idToken, "sports", "api", "athenz:sia:0001", errMsg); + boolean result = provider.validateOIDCToken(issuer, idToken, "sports", "api", "athenz:sia:0001", errMsg); assertFalse(result); assertTrue(errMsg.toString().contains("job start time is not recent enough")); // create another token without the issue time - - idToken = generateIdToken("https://token.actions.githubusercontent.com", + idToken = generateIdToken(issuer, System.currentTimeMillis() / 1000, false, false, true, false, false); errMsg.setLength(0); - result = provider.validateOIDCToken(idToken, "sports", "api", "athenz:sia:0001", errMsg); + result = provider.validateOIDCToken(issuer, idToken, "sports", "api", "athenz:sia:0001", errMsg); assertFalse(result); assertTrue(errMsg.toString().contains("job start time is not recent enough")); } @@ -500,25 +503,25 @@ public void testValidateOIDCTokenRunIdMismatch() throws JOSEException { "class://com.yahoo.athenz.instance.provider.impl.InstanceGithubActionsProvider", null, null); // our issue time is not recent enough - - String idToken = generateIdToken("https://token.actions.githubusercontent.com", + String issuer = "https://token.actions.githubusercontent.com"; + String idToken = generateIdToken(issuer, System.currentTimeMillis() / 1000, false, false, false, false, false); StringBuilder errMsg = new StringBuilder(256); - boolean result = provider.validateOIDCToken(idToken, "sports", "api", "athenz:sia:1001", errMsg); + boolean result = provider.validateOIDCToken(issuer, idToken, "sports", "api", "athenz:sia:1001", errMsg); assertFalse(result); assertTrue(errMsg.toString().contains("invalid instance id: athenz:sia:0001/athenz:sia:1001")); - idToken = generateIdToken("https://token.actions.githubusercontent.com", + idToken = generateIdToken(issuer, System.currentTimeMillis() / 1000, false, false, false, true, false); errMsg.setLength(0); - result = provider.validateOIDCToken(idToken, "sports", "api", "athenz:sia:1001", errMsg); + result = provider.validateOIDCToken(issuer, idToken, "sports", "api", "athenz:sia:1001", errMsg); assertFalse(result); assertTrue(errMsg.toString().contains("token does not contain required run_id or repository claims")); - idToken = generateIdToken("https://token.actions.githubusercontent.com", + idToken = generateIdToken(issuer, System.currentTimeMillis() / 1000, false, false, false, false, true); errMsg.setLength(0); - result = provider.validateOIDCToken(idToken, "sports", "api", "athenz:sia:1001", errMsg); + result = provider.validateOIDCToken(issuer, idToken, "sports", "api", "athenz:sia:1001", errMsg); assertFalse(result); assertTrue(errMsg.toString().contains("token does not contain required run_id or repository claims")); } @@ -538,12 +541,12 @@ public void testValidateOIDCTokenMissingEventName() throws JOSEException { //provider.signingKeyResolver.addPublicKey("0", Crypto.loadPublicKey(ecPublicKey)); // create an id token without the event_name claim - - String idToken = generateIdToken("https://token.actions.githubusercontent.com", + String issuer = "https://token.actions.githubusercontent.com"; + String idToken = generateIdToken(issuer, System.currentTimeMillis() / 1000, false, true, false, false, false); StringBuilder errMsg = new StringBuilder(256); - boolean result = provider.validateOIDCToken(idToken, "sports", "api", "athenz:sia:0001", errMsg); + boolean result = provider.validateOIDCToken(issuer, idToken, "sports", "api", "athenz:sia:0001", errMsg); assertFalse(result); assertTrue(errMsg.toString().contains("token does not contain required event_name claim")); } @@ -560,12 +563,12 @@ public void testValidateOIDCTokenMissingSubject() throws JOSEException { "class://com.yahoo.athenz.instance.provider.impl.InstanceGithubActionsProvider", null, null); // create an id token without the subject claim - - String idToken = generateIdToken("https://token.actions.githubusercontent.com", + String issuer = "https://token.actions.githubusercontent.com"; + String idToken = generateIdToken(issuer, System.currentTimeMillis() / 1000, true, false, false, false, false); StringBuilder errMsg = new StringBuilder(256); - boolean result = provider.validateOIDCToken(idToken, "sports", "api", "athenz:sia:0001", errMsg); + boolean result = provider.validateOIDCToken(issuer, idToken, "sports", "api", "athenz:sia:0001", errMsg); assertFalse(result); assertTrue(errMsg.toString().contains("token does not contain required subject claim")); } @@ -589,12 +592,12 @@ public void testValidateOIDCTokenAuthorizationFailure() throws JOSEException { provider.setAuthorizer(authorizer); // create an id token - - String idToken = generateIdToken("https://token.actions.githubusercontent.com", + String issuer = "https://token.actions.githubusercontent.com"; + String idToken = generateIdToken(issuer, System.currentTimeMillis() / 1000, false, false, false, false, false); StringBuilder errMsg = new StringBuilder(256); - boolean result = provider.validateOIDCToken(idToken, "sports", "api", "athenz:sia:0001", errMsg); + boolean result = provider.validateOIDCToken(issuer, idToken, "sports", "api", "athenz:sia:0001", errMsg); assertFalse(result); assertTrue(errMsg.toString().contains("authorization check failed for action")); }