Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions servers/zts/conf/zts.properties
Original file line number Diff line number Diff line change
Expand Up @@ -867,3 +867,8 @@ athenz.zts.k8s_provider_distribution_validator_factory_class=com.yahoo.athenz.in
# Setting this property to true well disable reporting these metrics to skip unnecessary
# metrics if the administrator is never looking at them. The default value is false.
#athenz.zts.skip_error_metrics=false

# When requesting an identity x.509 certificate, the caller has the option to request
# a service token as well. By default, it returns the old proprietary token format
# but if this setting is set to true, then the server will return a JWT ID token instead.
#athenz.zts.cert_request_token_type_jwt=false
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ public final class ZTSConsts {
public static final String ZTS_PROP_CERT_REFRESH_RESET_TIME = "athenz.zts.cert_refresh_reset_time";
public static final String ZTS_PROP_CERT_REQUEST_VERIFY_IP = "athenz.zts.cert_request_verify_ip";
public static final String ZTS_PROP_CERT_REQUEST_VERIFY_SUBJECT_OU = "athenz.zts.cert_request_verify_subject_ou";
public static final String ZTS_PROP_CERT_REQUEST_TOKEN_TYPE_JWT = "athenz.zts.cert_request_token_type_jwt";

public static final String ZTS_PROP_CERT_DNS_SUFFIX = "athenz.zts.cert_dns_suffix";
public static final String ZTS_PROP_CERT_FILE_STORE_PATH = "athenz.zts.cert_file_store_path";
Expand Down
62 changes: 55 additions & 7 deletions servers/zts/src/main/java/com/yahoo/athenz/zts/ZTSImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ public class ZTSImpl implements ZTSHandler {
protected TokenConfigOptions tokenConfigOptions = null;
protected ProviderConfigManager providerConfigManager;
protected IssuerResolver issuerResolver;
protected boolean instanceRegisterTokenTypeJWT = false;

private static final String TYPE_DOMAIN_NAME = "DomainName";
private static final String TYPE_SIMPLE_NAME = "SimpleName";
Expand Down Expand Up @@ -774,6 +775,11 @@ void loadConfigurationSettings() {

jwtCurveRfcSupportOnly = Boolean.parseBoolean(
System.getProperty(ZTSConsts.ZTS_PROP_JWK_CURVE_RFC_SUPPORT_ONLY, "false"));

// check if we should return jwt id tokens in the cert request token response

instanceRegisterTokenTypeJWT = Boolean.parseBoolean(
System.getProperty(ZTSConsts.ZTS_PROP_CERT_REQUEST_TOKEN_TYPE_JWT, "false"));
}

static String getServerHostName() {
Expand Down Expand Up @@ -4660,16 +4666,11 @@ Response postInstanceX509CertificateRegister(ResourceContext ctx, InstanceRegist
info.getHostname(), newCert.getNotAfter());
}

// if we're asked to return an NToken in addition to ZTS Certificate
// if we're asked to return an identity token in addition to ZTS Certificate
// then we'll generate one and include in the identity object

if (info.getToken() == Boolean.TRUE) {
ServerPrivateKey privateKey = getServerPrivateKey(keyAlgoForProprietaryObjects);
PrincipalToken svcToken = new PrincipalToken.Builder("S1", domain, service)
.expirationWindow(svcTokenTimeout).keyId(privateKey.getId()).host(serverHostName)
.ip(ipAddress).keyService(ZTSConsts.ZTS_SERVICE).build();
svcToken.sign(privateKey.getKey());
identity.setServiceToken(svcToken.getSignedToken());
identity.setServiceToken(getCertRequestServiceToken(ctx, info, domain, service, cn, ipAddress));
}

fillAthenzJWKConfig(ctx, info.getAthenzJWK(), info.getAthenzJWKModified(), identity);
Expand All @@ -4684,10 +4685,57 @@ Response postInstanceX509CertificateRegister(ResourceContext ctx, InstanceRegist
.header("Location", location).build();
}

String getCertRequestServiceToken(ResourceContext ctx, InstanceRegisterInformation info, final String domain,
final String service, final String cn, final String ipAddress) {

if (instanceRegisterTokenTypeJWT) {

// we must have the audience value in order to generate a token
// if the audience is not specified then we'll default as the issuer

long iat = System.currentTimeMillis() / 1000;
final String issuer = issuerResolver.getIDTokenIssuer(ctx.request(), null);

IdToken idToken = new IdToken();
idToken.setVersion(1);
idToken.setAudience(StringUtil.isEmpty(info.getJwtSVIDAudience()) ? issuer : info.getJwtSVIDAudience());
idToken.setIssuer(issuer);
idToken.setNonce(StringUtil.isEmpty(info.getJwtSVIDNonce()) ? Crypto.randomSalt() : info.getJwtSVIDNonce());
idToken.setIssueTime(iat);
idToken.setAuthTime(iat);
idToken.setSubject(cn);

// for user principals we're going to use the default 1 hour while for
// service principals 12 hours as the max timeout, unless the client
// is explicitly asking for something smaller.

long expiryTime = iat + determineOIDCIdTokenTimeout(domain, info.getExpiryTime());
idToken.setExpiryTime(expiryTime);

ServerPrivateKey signPrivateKey = getSignPrivateKey(info.getJwtSVIDKeyType());
return idToken.getSignedToken(signPrivateKey.getKey(), signPrivateKey.getId(), signPrivateKey.getAlgorithm());

} else {

ServerPrivateKey privateKey = getServerPrivateKey(keyAlgoForProprietaryObjects);
PrincipalToken svcToken = new PrincipalToken.Builder("S1", domain, service)
.expirationWindow(svcTokenTimeout).keyId(privateKey.getId()).host(serverHostName)
.ip(ipAddress).keyService(ZTSConsts.ZTS_SERVICE).build();
svcToken.sign(privateKey.getKey());
return svcToken.getSignedToken();
}
}

Response postInstanceJWTRegister(ResourceContext ctx, InstanceRegisterInformation info,
final String domain, final String service, final String cn, final String principalDomain,
final String provider, final String caller) {

// make sure we have valid audience value

if (StringUtil.isEmpty(info.getJwtSVIDAudience())) {
throw requestError("Audience is required for jwt SVID requests", caller, domain, principalDomain);
}

// we need to validate our spiffe value if one is provided

final String spiffeUri = info.getJwtSVIDSpiffe();
Expand Down
Loading
Loading