diff --git a/.github/workflows/check-remote.yaml b/.github/workflows/check-remote.yaml
index d1d41d2..8c3de1d 100644
--- a/.github/workflows/check-remote.yaml
+++ b/.github/workflows/check-remote.yaml
@@ -56,7 +56,7 @@ jobs:
| jq -r .[].tag_name \
| grep -E ".*(v[0-9]*.[0-9]*.[0-9]*).*" \
| sed -e 's/.*v\([0-9]*.[0-9]*.[0-9]*\).*/\1/g' \
- | sort -ru \
+ | sort -ruV \
| head -n1
)"
TAG_VERSION="$( \
@@ -64,7 +64,7 @@ jobs:
| jq -r .[].tag_name \
| grep -E ".*(v[0-9]*.[0-9]*.[0-9]*).*" \
| sed -e 's/.*\(v[0-9]*.[0-9]*.[0-9]*\).*/\1/g' \
- | sort -ru \
+ | sort -ruV \
| head -n1
)"
fi
diff --git a/pom.xml.template b/pom.xml.template
index 902166b..98f36ee 100644
--- a/pom.xml.template
+++ b/pom.xml.template
@@ -3,7 +3,7 @@
4.0.0
athenz-plugins
- Core Auth Interfaces
+ Athenz Plugin Implementations
io.athenz
athenz-plugins
0.0.0
diff --git a/src/main/java/com/yahoo/athenz/instance/provider/impl/DefaultAWSElasticKubernetesServiceValidator.java b/src/main/java/com/yahoo/athenz/instance/provider/impl/DefaultAWSElasticKubernetesServiceValidator.java
new file mode 100644
index 0000000..8e6fafc
--- /dev/null
+++ b/src/main/java/com/yahoo/athenz/instance/provider/impl/DefaultAWSElasticKubernetesServiceValidator.java
@@ -0,0 +1,231 @@
+package com.yahoo.athenz.instance.provider.impl;
+
+import com.yahoo.athenz.auth.Authorizer;
+import com.yahoo.athenz.auth.Principal;
+import com.yahoo.athenz.auth.impl.SimplePrincipal;
+import com.yahoo.athenz.common.server.util.config.dynamic.DynamicConfigBoolean;
+import com.yahoo.athenz.common.server.util.config.dynamic.DynamicConfigCsv;
+import com.yahoo.athenz.instance.provider.AttrValidator;
+import com.yahoo.athenz.instance.provider.AttrValidatorFactory;
+import com.yahoo.athenz.instance.provider.InstanceConfirmation;
+import org.eclipse.jetty.util.StringUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.net.ssl.SSLContext;
+import java.lang.invoke.MethodHandles;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import software.amazon.awssdk.auth.credentials.AwsSessionCredentials;
+import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
+import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.sts.StsClient;
+import software.amazon.awssdk.services.iam.model.ListOpenIdConnectProvidersRequest;
+import software.amazon.awssdk.services.iam.model.ListOpenIdConnectProvidersResponse;
+import software.amazon.awssdk.services.iam.model.OpenIDConnectProviderListEntry;
+import software.amazon.awssdk.services.iam.IamClient;
+import software.amazon.awssdk.services.sts.model.AssumeRoleRequest;
+import software.amazon.awssdk.services.sts.model.AssumeRoleResponse;
+
+import static com.yahoo.athenz.common.server.util.config.ConfigManagerSingleton.CONFIG_MANAGER;
+import static com.yahoo.athenz.instance.provider.InstanceProvider.ZTS_INSTANCE_AWS_ACCOUNT;
+import static com.yahoo.athenz.instance.provider.impl.InstanceAWSProvider.*;
+
+public class DefaultAWSElasticKubernetesServiceValidator extends CommonKubernetesDistributionValidator {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+ private static final DefaultAWSElasticKubernetesServiceValidator INSTANCE = new DefaultAWSElasticKubernetesServiceValidator();
+ static final String AWS_EKS_OIDC_ISSUER_REGEX = "oidc\\.eks\\.[a-z0-9-]+\\.amazonaws\\.com";
+ private static final Pattern AWS_EKS_OIDC_ISSUER_PATTERN = Pattern.compile(AWS_EKS_OIDC_ISSUER_REGEX);
+
+ private static final String ZTS_PROP_K8S_PROVIDER_ATTESTATION_AWS_ASSUME_ROLE_NAME = "athenz.zts.k8s_provider_attestation_aws_assume_role_name";
+ private static final String ASSUME_ROLE_NAME = System.getProperty(ZTS_PROP_K8S_PROVIDER_ATTESTATION_AWS_ASSUME_ROLE_NAME, "oidc-issuers-reader");
+ static final String ZTS_PROP_K8S_PROVIDER_AWS_ATTR_VALIDATOR_FACTORY_CLASS = "athenz.zts.k8s_provider_aws_attr_validator_factory_class";
+
+ StsClient stsClient;
+ String serverRegion;
+
+ Set awsDNSSuffixes = new HashSet<>();
+ List eksDnsSuffixes;
+ DynamicConfigCsv eksClusterNames; // list of eks cluster names
+
+ private static final String ZTS_PROP_K8S_PROVIDER_AWS_ATTESTATION_USING_IAM_ROLE = "athenz.zts.k8s_provider_aws_attestation_using_iam_role";
+ DynamicConfigBoolean useIamRoleForIssuerAttestation;
+ AttrValidator attrValidator;
+
+ public static DefaultAWSElasticKubernetesServiceValidator getInstance() {
+ return INSTANCE;
+ }
+
+ private DefaultAWSElasticKubernetesServiceValidator() {
+ }
+
+ static AttrValidator newAttrValidator(final SSLContext sslContext) {
+ final String factoryClass = System.getProperty(ZTS_PROP_K8S_PROVIDER_AWS_ATTR_VALIDATOR_FACTORY_CLASS);
+ LOGGER.info("AWS K8S AttributeValidatorFactory class: {}", factoryClass);
+ if (factoryClass == null) {
+ return null;
+ }
+
+ AttrValidatorFactory attrValidatorFactory;
+ try {
+ attrValidatorFactory = (AttrValidatorFactory) Class.forName(factoryClass).getConstructor().newInstance();
+ } catch (Exception e) {
+ LOGGER.error("Invalid AttributeValidatorFactory class: {}", factoryClass, e);
+ throw new IllegalArgumentException("Invalid AttributeValidatorFactory class");
+ }
+
+ return attrValidatorFactory.create(sslContext);
+ }
+
+ @Override
+ public void initialize(final SSLContext sslContext, Authorizer authorizer) {
+ super.initialize(sslContext, authorizer);
+ serverRegion = System.getProperty(AWS_PROP_REGION_NAME);
+
+ useIamRoleForIssuerAttestation = new DynamicConfigBoolean(CONFIG_MANAGER, ZTS_PROP_K8S_PROVIDER_AWS_ATTESTATION_USING_IAM_ROLE, true);
+
+ if (useIamRoleForIssuerValidation()) {
+ // Create an STS client using default credentials
+ stsClient = StsClient.builder().credentialsProvider(DefaultCredentialsProvider.builder().build())
+ .region(Region.of(serverRegion)).build();
+ }
+ final String dnsSuffix = System.getProperty(AWS_PROP_DNS_SUFFIX);
+ if (!StringUtil.isEmpty(dnsSuffix)) {
+ awsDNSSuffixes.addAll(Arrays.asList(dnsSuffix.split(",")));
+ }
+ // get our allowed eks dns suffixes
+ eksDnsSuffixes = InstanceUtils.processK8SDnsSuffixList(AWS_PROP_EKS_DNS_SUFFIX);
+ // get our dynamic list of eks cluster names
+ eksClusterNames = new DynamicConfigCsv(CONFIG_MANAGER, AWS_PROP_EKS_CLUSTER_NAMES, null);
+
+ this.attrValidator = newAttrValidator(sslContext);
+ }
+
+ @Override
+ public String validateIssuer(InstanceConfirmation confirmation, IdTokenAttestationData attestationData, StringBuilder errMsg) {
+
+ String issuer = getIssuerFromToken(attestationData, errMsg);
+ if (StringUtil.isEmpty(issuer)) {
+ return null;
+ }
+
+ String issuerDomain = InstanceUtils.extractURLDomainName(issuer);
+ if (issuerDomain == null) {
+ return null;
+ }
+ Matcher matcher = AWS_EKS_OIDC_ISSUER_PATTERN.matcher(issuerDomain);
+ if (!matcher.matches()) {
+ return null;
+ }
+
+ if (useIamRoleForIssuerValidation()) {
+ String awsAccount = confirmation.getAttributes().get(ZTS_INSTANCE_AWS_ACCOUNT);
+ if (!verifyIssuerPresenceInDomainAWSAccount(issuer, awsAccount)) {
+ return null;
+ }
+ // If the issuer is present in the same AWS account as the requested identity
+ // then we should use the same for the launch authorization
+ confirmation.getAttributes().put(ZTS_INSTANCE_ISSUER_AWS_ACCOUNT, awsAccount);
+ } else {
+ if (attrValidator != null) {
+ confirmation.getAttributes().put(ZTS_INSTANCE_UNATTESTED_ISSUER, issuer);
+ // Confirm the issuer as per the attribute validator
+ if (!attrValidator.confirm(confirmation)) {
+ return null;
+ }
+ }
+ }
+
+ final String domainName = confirmation.getDomain();
+ final String serviceName = confirmation.getService();
+ // attribute set after iam role validation or attribute validation
+ final String issuerAwsAccount = confirmation.getAttributes().get(ZTS_INSTANCE_ISSUER_AWS_ACCOUNT);
+ final String resource = String.format("%s:%s:%s", domainName, serviceName, issuerAwsAccount);
+
+ Principal principal = SimplePrincipal.create(domainName, serviceName, (String) null);
+ boolean accessCheck = authorizer.access(ACTION_LAUNCH, resource, principal, null);
+ if (!accessCheck) {
+ errMsg.append("eks launch authorization check failed for action: ").append(ACTION_LAUNCH)
+ .append(" resource: ").append(resource);
+ return null;
+ }
+
+ return issuer;
+ }
+
+ IamClient getIamClient(final String awsAccount) {
+
+ final String roleArn = String.format("arn:aws:iam::%s:role/%s", awsAccount, ASSUME_ROLE_NAME);
+ final String roleSessionName = ASSUME_ROLE_NAME + "-Session";
+
+ // Assume the role in the target AWS account
+
+ AssumeRoleRequest assumeRoleRequest = AssumeRoleRequest.builder()
+ .roleArn(roleArn).roleSessionName(roleSessionName).build();
+ AssumeRoleResponse assumeRoleResponse = stsClient.assumeRole(assumeRoleRequest);
+
+ // Create Static Credentials Provider
+
+ StaticCredentialsProvider credentialsProvider = StaticCredentialsProvider.create(
+ AwsSessionCredentials.create(assumeRoleResponse.credentials().accessKeyId(),
+ assumeRoleResponse.credentials().secretAccessKey(),
+ assumeRoleResponse.credentials().sessionToken()));
+
+ // Create IAM Client
+
+ return IamClient.builder().credentialsProvider(credentialsProvider).region(Region.of(serverRegion)).build();
+ }
+
+ boolean verifyIssuerPresenceInDomainAWSAccount(final String issuer, final String awsAccount) {
+
+ boolean result = false;
+
+ // get our IAM Client
+
+ IamClient iamClient = getIamClient(awsAccount);
+
+ // Call the IAM API to get the list of OIDC issuers
+
+ ListOpenIdConnectProvidersRequest request = ListOpenIdConnectProvidersRequest.builder().build();
+ ListOpenIdConnectProvidersResponse response = iamClient.listOpenIDConnectProviders(request);
+ List oidcIssuers = response.openIDConnectProviderList();
+ if (oidcIssuers != null) {
+ String issuerWithoutProtocol = issuer.replaceFirst("^https://", "");
+ for (OpenIDConnectProviderListEntry oidcIssuer : oidcIssuers) {
+ if (oidcIssuer != null && oidcIssuer.arn() != null && oidcIssuer.arn().endsWith(issuerWithoutProtocol)) {
+ result = true;
+ break;
+ }
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public boolean validateSanDNSEntries(InstanceConfirmation confirmation, StringBuilder errMsg) {
+
+ StringBuilder instanceId = new StringBuilder(256);
+ final Map instanceAttributes = confirmation.getAttributes();
+ final String awsAccount = InstanceUtils.getInstanceProperty(instanceAttributes, ZTS_INSTANCE_AWS_ACCOUNT);
+ if (StringUtil.isEmpty(awsAccount)) {
+ errMsg.append("Unable to find AWS account number");
+ return false;
+ }
+ if (!InstanceUtils.validateCertRequestSanDnsNames(instanceAttributes, confirmation.getDomain(),
+ confirmation.getService(), awsDNSSuffixes, eksDnsSuffixes, eksClusterNames.getStringsList(),
+ true, instanceId, null)) {
+ errMsg.append("Unable to validate certificate request hostnames");
+ return false;
+ }
+ return true;
+ }
+
+ boolean useIamRoleForIssuerValidation() {
+ return Boolean.TRUE.equals(useIamRoleForIssuerAttestation.get());
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/yahoo/athenz/instance/provider/impl/DefaultGCPGoogleKubernetesEngineValidator.java b/src/main/java/com/yahoo/athenz/instance/provider/impl/DefaultGCPGoogleKubernetesEngineValidator.java
new file mode 100644
index 0000000..2b632ee
--- /dev/null
+++ b/src/main/java/com/yahoo/athenz/instance/provider/impl/DefaultGCPGoogleKubernetesEngineValidator.java
@@ -0,0 +1,129 @@
+package com.yahoo.athenz.instance.provider.impl;
+
+import com.yahoo.athenz.auth.Authorizer;
+import com.yahoo.athenz.auth.Principal;
+import com.yahoo.athenz.auth.impl.SimplePrincipal;
+import com.yahoo.athenz.common.server.util.config.dynamic.DynamicConfigCsv;
+import com.yahoo.athenz.instance.provider.AttrValidator;
+import com.yahoo.athenz.instance.provider.AttrValidatorFactory;
+import com.yahoo.athenz.instance.provider.InstanceConfirmation;
+import com.yahoo.athenz.instance.provider.InstanceProvider;
+import javax.net.ssl.SSLContext;
+import org.eclipse.jetty.util.StringUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.lang.invoke.MethodHandles;
+import java.util.*;
+
+import static com.yahoo.athenz.common.server.util.config.ConfigManagerSingleton.CONFIG_MANAGER;
+import static com.yahoo.athenz.instance.provider.impl.InstanceGCPProvider.*;
+
+public class DefaultGCPGoogleKubernetesEngineValidator extends CommonKubernetesDistributionValidator {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+ Set gcpDNSSuffixes = new HashSet<>();
+ List gkeDnsSuffixes;
+ DynamicConfigCsv gkeClusterNames;
+
+ private static final DefaultGCPGoogleKubernetesEngineValidator INSTANCE = new DefaultGCPGoogleKubernetesEngineValidator();
+ static final String GCP_OIDC_ISSUER_PREFIX = "https://container.googleapis.com/v1/projects/";
+ AttrValidator attrValidator;
+ static final String ZTS_PROP_K8S_PROVIDER_GCP_ATTR_VALIDATOR_FACTORY_CLASS = "athenz.zts.k8s_provider_gcp_attr_validator_factory_class";
+
+ public static DefaultGCPGoogleKubernetesEngineValidator getInstance() {
+ return INSTANCE;
+ }
+ private DefaultGCPGoogleKubernetesEngineValidator() {
+ }
+
+ static AttrValidator newAttrValidator(final SSLContext sslContext) {
+ final String factoryClass = System.getProperty(ZTS_PROP_K8S_PROVIDER_GCP_ATTR_VALIDATOR_FACTORY_CLASS);
+ LOGGER.info("GCP K8S AttributeValidatorFactory class: {}", factoryClass);
+ if (factoryClass == null) {
+ return null;
+ }
+
+ AttrValidatorFactory attrValidatorFactory;
+ try {
+ attrValidatorFactory = (AttrValidatorFactory) Class.forName(factoryClass).getConstructor().newInstance();
+ } catch (Exception e) {
+ LOGGER.error("Invalid AttributeValidatorFactory class: {}", factoryClass, e);
+ throw new IllegalArgumentException("Invalid AttributeValidatorFactory class");
+ }
+
+ return attrValidatorFactory.create(sslContext);
+ }
+
+ @Override
+ public void initialize(final SSLContext sslContext, Authorizer authorizer) {
+ super.initialize(sslContext, authorizer);
+ final String dnsSuffix = System.getProperty(GCP_PROP_DNS_SUFFIX);
+ if (!StringUtil.isEmpty(dnsSuffix)) {
+ gcpDNSSuffixes.addAll(Arrays.asList(dnsSuffix.split(",")));
+ }
+ // get our allowed gke dns suffixes
+ gkeDnsSuffixes = InstanceUtils.processK8SDnsSuffixList(GCP_PROP_GKE_DNS_SUFFIX);
+ // get our dynamic list of gke cluster names
+ gkeClusterNames = new DynamicConfigCsv(CONFIG_MANAGER, GCP_PROP_GKE_CLUSTER_NAMES, null);
+ this.attrValidator = newAttrValidator(sslContext);
+ }
+
+ @Override
+ public String validateIssuer(InstanceConfirmation confirmation, IdTokenAttestationData attestationData, StringBuilder errMsg) {
+ String issuer = getIssuerFromToken(attestationData, errMsg);
+ if (StringUtil.isEmpty(issuer)) {
+ return null;
+ }
+ String gcpProject = confirmation.getAttributes().get(InstanceProvider.ZTS_INSTANCE_GCP_PROJECT);
+ if (!issuer.startsWith(GCP_OIDC_ISSUER_PREFIX + gcpProject)) {
+ // could be a multi-tenant setup where the issuer is not present in the identity's GCP project
+ if (attrValidator != null) {
+ confirmation.getAttributes().put(ZTS_INSTANCE_UNATTESTED_ISSUER, issuer);
+ // Confirm the issuer as per the attribute validator
+ if (!attrValidator.confirm(confirmation)) {
+ return null;
+ }
+ } else {
+ errMsg.append("Issuer is not present in the GCP project associated with the domain");
+ return null;
+ }
+ } else {
+ // issuer exists in the same GCP project as the requested identity
+ confirmation.getAttributes().put(ZTS_INSTANCE_ISSUER_GCP_PROJECT, gcpProject);
+ }
+
+ final String domainName = confirmation.getDomain();
+ final String serviceName = confirmation.getService();
+ // attribute set after verification above or attribute validation
+ final String issuerGcpProject = confirmation.getAttributes().get(ZTS_INSTANCE_ISSUER_GCP_PROJECT);
+ final String resource = String.format("%s:%s:%s", domainName, serviceName, issuerGcpProject);
+
+ Principal principal = SimplePrincipal.create(domainName, serviceName, (String) null);
+ boolean accessCheck = authorizer.access(ACTION_LAUNCH, resource, principal, null);
+ if (!accessCheck) {
+ errMsg.append("gke launch authorization check failed for action: ").append(ACTION_LAUNCH)
+ .append(" resource: ").append(resource);
+ return null;
+ }
+ return issuer;
+ }
+
+ @Override
+ public boolean validateSanDNSEntries(InstanceConfirmation confirmation, StringBuilder errMsg) {
+ StringBuilder instanceId = new StringBuilder(256);
+ final Map instanceAttributes = confirmation.getAttributes();
+ final String gcpProject = InstanceUtils.getInstanceProperty(instanceAttributes, ZTS_INSTANCE_GCP_PROJECT);
+ if (StringUtil.isEmpty(gcpProject)) {
+ errMsg.append("Unable to find GCP project id");
+ return false;
+ }
+ if (!InstanceUtils.validateCertRequestSanDnsNames(instanceAttributes, confirmation.getDomain(),
+ confirmation.getService(), gcpDNSSuffixes, gkeDnsSuffixes, gkeClusterNames.getStringsList(),
+ true, instanceId, null)) {
+ errMsg.append("Unable to validate certificate request hostnames");
+ return false;
+ }
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/yahoo/athenz/instance/provider/impl/DefaultKubernetesValidator.java b/src/main/java/com/yahoo/athenz/instance/provider/impl/DefaultKubernetesValidator.java
new file mode 100644
index 0000000..254ac55
--- /dev/null
+++ b/src/main/java/com/yahoo/athenz/instance/provider/impl/DefaultKubernetesValidator.java
@@ -0,0 +1,90 @@
+package com.yahoo.athenz.instance.provider.impl;
+
+import com.yahoo.athenz.auth.Authorizer;
+import com.yahoo.athenz.auth.Principal;
+import com.yahoo.athenz.auth.impl.SimplePrincipal;
+import com.yahoo.athenz.instance.provider.InstanceConfirmation;
+import javax.net.ssl.SSLContext;
+import org.eclipse.jetty.util.StringUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.lang.invoke.MethodHandles;
+import java.util.*;
+
+import static com.yahoo.athenz.instance.provider.impl.InstanceGCPProvider.*;
+
+public class DefaultKubernetesValidator extends CommonKubernetesDistributionValidator {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+ Set k8sDNSSuffixes;
+
+ private static final DefaultKubernetesValidator INSTANCE = new DefaultKubernetesValidator();
+ static final String K8S_OIDC_ISSUER = "https://kubernetes.default.svc.cluster.local";
+ static final String K8S_PROP_BOOT_TIME_OFFSET = "athenz.zts.k8s_boot_time_offset";
+ static final String K8S_PROP_DNS_SUFFIX = "athenz.zts.k8s_dns_suffix";
+
+ public static DefaultKubernetesValidator getInstance() {
+ return INSTANCE;
+ }
+ private DefaultKubernetesValidator() {
+ }
+
+ @Override
+ public void initialize(final SSLContext sslContext, Authorizer authorizer) {
+ super.initialize(sslContext, authorizer);
+ final String dnsSuffix = System.getProperty(K8S_PROP_DNS_SUFFIX);
+ if (!StringUtil.isEmpty(dnsSuffix)) {
+ k8sDNSSuffixes.addAll(Arrays.asList(dnsSuffix.split(",")));
+ }
+ }
+
+ @Override
+ public String validateIssuer(InstanceConfirmation confirmation, IdTokenAttestationData attestationData, StringBuilder errMsg) {
+ String issuer = getIssuerFromToken(attestationData, errMsg);
+ if (StringUtil.isEmpty(issuer)) {
+ errMsg.append("Issuer is empty");
+ return null;
+ }
+ if (!issuer.equals(K8S_OIDC_ISSUER)) {
+ errMsg.append("Issuer is not ").append(K8S_OIDC_ISSUER);
+ return null;
+ }
+ final Map instanceAttributes = confirmation.getAttributes();
+ final String cloudName = InstanceUtils.getInstanceProperty(instanceAttributes, ZTS_INSTANCE_CLOUD);
+ final String providerName = confirmation.getProvider();
+ final String k8sNamespaceName = attestationData.getIdentityToken();
+ final String k8sServiceAccountName = attestationData.getIdentityToken();
+
+ final String domainName = confirmation.getDomain();
+ final String serviceName = confirmation.getService();
+ // attribute set after verification above or attribute validation
+ final String resource = String.format("cloud:%s:provider:%s:system:serviceaccount:%s:%s", cloudName, providerName, k8sNamespaceName, k8sServiceAccountName);
+
+ Principal principal = SimplePrincipal.create(domainName, serviceName, (String) null);
+ boolean accessCheck = authorizer.access(ACTION_LAUNCH, resource, principal, null);
+ if (!accessCheck) {
+ errMsg.append("k8s launch authorization check failed for action: ").append(ACTION_LAUNCH)
+ .append(" resource: ").append(resource);
+ return null;
+ }
+ return issuer;
+ }
+
+ @Override
+ public boolean validateSanDNSEntries(InstanceConfirmation confirmation, StringBuilder errMsg) {
+ StringBuilder instanceId = new StringBuilder(256);
+ final Map instanceAttributes = confirmation.getAttributes();
+ final String cloudName = InstanceUtils.getInstanceProperty(instanceAttributes, ZTS_INSTANCE_CLOUD);
+ if (StringUtil.isEmpty(cloudName) || cloudName.equals("")) {
+ errMsg.append("Unable to find cloud name");
+ return false;
+ }
+ if (!InstanceUtils.validateCertRequestSanDnsNames(instanceAttributes, confirmation.getDomain(),
+ confirmation.getService(), k8sDNSSuffixes, null, null, false, instanceId, null)) {
+ errMsg.append("Unable to validate certificate request hostnames for SAN DNS names");
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/src/main/java/com/yahoo/athenz/instance/provider/impl/InstanceJenkinsProvider.java b/src/main/java/com/yahoo/athenz/instance/provider/impl/InstanceJenkinsProvider.java
index 21521bb..eed595a 100644
--- a/src/main/java/com/yahoo/athenz/instance/provider/impl/InstanceJenkinsProvider.java
+++ b/src/main/java/com/yahoo/athenz/instance/provider/impl/InstanceJenkinsProvider.java
@@ -305,16 +305,15 @@ boolean validateTenantDomainToken(final JWTClaimsSet claimsSet, final String dom
// we need to extract and generate our action value for the authz check
- final String action = "jenkins-pipeline";
+ final String action = "run_jenkins_pipeline";
// we need to generate our resource value based on the subject
- final String subject = claimsSet.getSubject();
+ final String resource = claimsSet.getSubject();
// generate our principal object and carry out authorization check
-
- final String resource = domainName + ":" + subject;
Principal principal = SimplePrincipal.create(domainName, serviceName, (String) null);
+
boolean accessCheck = authorizer.access(action, resource, principal, null);
if (!accessCheck) {
errMsg.append("authorization check failed for action: ").append(action)
diff --git a/src/main/java/com/yahoo/athenz/instance/provider/impl/SimpleKubernetesDistributionValidatorFactory.java b/src/main/java/com/yahoo/athenz/instance/provider/impl/SimpleKubernetesDistributionValidatorFactory.java
new file mode 100644
index 0000000..70abfdc
--- /dev/null
+++ b/src/main/java/com/yahoo/athenz/instance/provider/impl/SimpleKubernetesDistributionValidatorFactory.java
@@ -0,0 +1,23 @@
+package com.yahoo.athenz.instance.provider.impl;
+
+import com.yahoo.athenz.instance.provider.KubernetesDistributionValidator;
+import com.yahoo.athenz.instance.provider.KubernetesDistributionValidatorFactory;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class SimpleKubernetesDistributionValidatorFactory implements KubernetesDistributionValidatorFactory {
+
+ Map supportedDistributionsMap = new HashMap<>();
+ static final String CLOUD_K8S = "k8s";
+
+ @Override
+ public void initialize() {
+ supportedDistributionsMap.put(CLOUD_K8S, DefaultKubernetesValidator.getInstance());
+ }
+
+ @Override
+ public Map getSupportedDistributions() {
+ return supportedDistributionsMap;
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/yahoo/athenz/instance/provider/impl/InstanceJenkinsProviderTest.java b/src/test/java/com/yahoo/athenz/instance/provider/impl/InstanceJenkinsProviderTest.java
index 052c856..a7efae1 100644
--- a/src/test/java/com/yahoo/athenz/instance/provider/impl/InstanceJenkinsProviderTest.java
+++ b/src/test/java/com/yahoo/athenz/instance/provider/impl/InstanceJenkinsProviderTest.java
@@ -119,7 +119,7 @@ public void testConfirmInstance() throws JOSEException, ProviderResourceExceptio
Authorizer authorizer = Mockito.mock(Authorizer.class);
Principal principal = SimplePrincipal.create("sports", "api", (String) null);
- Mockito.when(authorizer.access("jenkins-pipeline", "sports:https://jenkins.athenz.svc.cluster.local/job/test-project/1", principal, null))
+ Mockito.when(authorizer.access("run_jenkins_pipeline", "https://jenkins.athenz.svc.cluster.local/job/test-project/1", principal, null))
.thenReturn(true);
provider.setAuthorizer(authorizer);
@@ -156,7 +156,7 @@ public void testConfirmInstanceFailuresInvalidSANEntries() throws JOSEException
Authorizer authorizer = Mockito.mock(Authorizer.class);
Principal principal = SimplePrincipal.create("sports", "api", (String) null);
- Mockito.when(authorizer.access("jenkins-pipeline", "sports:https://jenkins.athenz.svc.cluster.local/job/test-project/1", principal, null))
+ Mockito.when(authorizer.access("run_jenkins_pipeline", "https://jenkins.athenz.svc.cluster.local/job/test-project/1", principal, null))
.thenReturn(true);
provider.setAuthorizer(authorizer);