All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.uid2.shared.secure.gcpoidc.PolicyValidator Maven / Gradle / Ivy
package com.uid2.shared.secure.gcpoidc;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.uid2.shared.Utils;
import com.uid2.shared.secure.AttestationClientException;
import com.uid2.shared.secure.AttestationException;
import com.uid2.shared.secure.AttestationFailure;
import com.uid2.shared.util.UrlEquivalenceValidator;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class PolicyValidator implements IPolicyValidator {
private static final Logger LOGGER = LoggerFactory.getLogger(PolicyValidator.class);
public static final String ENV_ENVIRONMENT = "DEPLOYMENT_ENVIRONMENT";
public static final String ENV_OPERATOR_API_KEY_SECRET_NAME = "API_TOKEN_SECRET_NAME";
public static final String ENV_CORE_ENDPOINT = "CORE_BASE_URL";
public static final String ENV_OPT_OUT_ENDPOINT = "OPTOUT_BASE_URL";
public static final String EU_REGION_PREFIX = "europe";
private static final List REQUIRED_ENV_OVERRIDES = ImmutableList.of(
ENV_ENVIRONMENT,
ENV_OPERATOR_API_KEY_SECRET_NAME
);
private static final Map> OPTIONAL_ENV_OVERRIDES_MAP = ImmutableMap.of(
Environment.Production, ImmutableList.of(
ENV_CORE_ENDPOINT,
ENV_OPT_OUT_ENDPOINT
),
Environment.Integration, ImmutableList.of(
ENV_CORE_ENDPOINT,
ENV_OPT_OUT_ENDPOINT
)
);
private final String attestationUrl;
public PolicyValidator(String attestationUrl) {
this.attestationUrl = attestationUrl;
}
@Override
public String getVersion() {
return "V1";
}
@Override
public String validate(TokenPayload payload) throws AttestationException {
checkRegion(payload);
var isDebugMode = checkConfidentialSpace(payload);
var digest = checkWorkload(payload);
checkCmdOverrides(payload);
var env = checkEnvOverrides(payload);
return generateEnclaveId(isDebugMode, digest, env);
}
private static boolean checkConfidentialSpace(TokenPayload payload) throws AttestationException{
if(!payload.isConfidentialSpaceSW()){
throw new AttestationClientException("Unexpected SW_NAME: " + payload.getSwName(), AttestationFailure.BAD_FORMAT);
}
var isDebugMode = payload.isDebugMode();
if(!isDebugMode && !payload.isStableVersion()){
throw new AttestationClientException("Confidential space image version is not stable.", AttestationFailure.BAD_FORMAT);
}
return isDebugMode;
}
private static String checkWorkload(TokenPayload payload) throws AttestationException{
if(!payload.isRestartPolicyNever()){
throw new AttestationClientException("Restart policy is not set to Never. Value: " + payload.getRestartPolicy(), AttestationFailure.BAD_FORMAT);
}
return payload.getWorkloadImageDigest();
}
// We don't support to launch UID2 instance in EU.
// Currently, there's no GCP serving options in China mainland, so we will skip the check for CN.
// More details about zone in https://cloud.google.com/compute/docs/regions-zones.
private static String checkRegion(TokenPayload payload) throws AttestationException{
var region = payload.getGceZone();
if(Strings.isNullOrEmpty(region) || region.startsWith(EU_REGION_PREFIX)){
throw new AttestationClientException("Region is not supported. Value: " + region, AttestationFailure.BAD_FORMAT);
}
return region;
}
private static void checkCmdOverrides(TokenPayload payload) throws AttestationException{
if(!CollectionUtils.isEmpty(payload.getCmdOverrides())){
throw new AttestationClientException("Payload should not have cmd overrides", AttestationFailure.BAD_FORMAT);
}
}
private Environment checkEnvOverrides(TokenPayload payload) throws AttestationException{
var envOverrides = payload.getEnvOverrides();
if(MapUtils.isEmpty(envOverrides)){
throw new AttestationClientException("env overrides should not be empty", AttestationFailure.BAD_FORMAT);
}
HashMap envOverridesCopy = new HashMap(envOverrides);
// check all required env overrides
for(var envKey: REQUIRED_ENV_OVERRIDES){
if(Strings.isNullOrEmpty(envOverridesCopy.get(envKey))){
throw new AttestationClientException("Required env override is missing. key: " + envKey, AttestationFailure.BAD_FORMAT);
}
}
// env could be parsed
var env = Environment.fromString(envOverridesCopy.get(ENV_ENVIRONMENT));
if(env == null){
throw new AttestationClientException("Environment can not be parsed. " + envOverridesCopy.get(ENV_ENVIRONMENT), AttestationFailure.BAD_FORMAT);
}
// make sure there's no unexpected overrides
for(var envKey: REQUIRED_ENV_OVERRIDES){
envOverridesCopy.remove(envKey);
}
var optionalEnvOverrides = OPTIONAL_ENV_OVERRIDES_MAP.get(env);
if(!CollectionUtils.isEmpty(optionalEnvOverrides)){
for(var envKey: optionalEnvOverrides){
envOverridesCopy.remove(envKey);
}
}
checkAttestationUrl(new HashMap<>(envOverrides));
if(!envOverridesCopy.isEmpty()){
throw new AttestationClientException("More env overrides than allowed. " + envOverridesCopy, AttestationFailure.BAD_FORMAT);
}
return env;
}
private void checkAttestationUrl(HashMap optionalEnvOverrides) throws AttestationException {
if (!Strings.isNullOrEmpty(optionalEnvOverrides.get(ENV_CORE_ENDPOINT))) {
String givenAttestationUrl = optionalEnvOverrides.get(ENV_CORE_ENDPOINT);
if (!UrlEquivalenceValidator.areUrlsEquivalent(givenAttestationUrl, this.attestationUrl)) {
throw new AttestationClientException("The given attestation URL is unknown. Given URL: " + givenAttestationUrl, AttestationFailure.UNKNOWN_ATTESTATION_URL);
}
}
}
private String generateEnclaveId(boolean isDebugMode, String imageDigest, Environment env) throws AttestationException {
var str = String.format("%s,%s,%s", getVersion(), isDebugMode, imageDigest);
LOGGER.info("Meta used to generate GCP EnclaveId: " + str);
try {
return getSha256Base64Encoded(str);
} catch (NoSuchAlgorithmException e) {
throw new AttestationException(e);
}
}
private static String getSha256Base64Encoded(String input) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance("SHA-256");
// input should contain only US-ASCII chars
md.update(input.getBytes(StandardCharsets.US_ASCII));
return Utils.toBase64String(md.digest());
}
}