summaryrefslogtreecommitdiffstats
path: root/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/ca/restapi/CertificateAuthorityApiHandler.java
diff options
context:
space:
mode:
Diffstat (limited to 'athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/ca/restapi/CertificateAuthorityApiHandler.java')
-rw-r--r--athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/ca/restapi/CertificateAuthorityApiHandler.java72
1 files changed, 3 insertions, 69 deletions
diff --git a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/ca/restapi/CertificateAuthorityApiHandler.java b/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/ca/restapi/CertificateAuthorityApiHandler.java
index 4c01b0943e4..1b9bdcdb987 100644
--- a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/ca/restapi/CertificateAuthorityApiHandler.java
+++ b/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/ca/restapi/CertificateAuthorityApiHandler.java
@@ -6,24 +6,16 @@ import com.yahoo.container.jdisc.HttpRequest;
import com.yahoo.container.jdisc.HttpResponse;
import com.yahoo.container.jdisc.LoggingRequestHandler;
import com.yahoo.container.jdisc.secretstore.SecretStore;
-import com.yahoo.jdisc.http.servlet.ServletRequest;
-import com.yahoo.log.LogLevel;
import com.yahoo.restapi.ErrorResponse;
import com.yahoo.restapi.Path;
import com.yahoo.restapi.SlimeJsonResponse;
import com.yahoo.security.KeyUtils;
-import com.yahoo.security.SubjectAlternativeName;
import com.yahoo.security.X509CertificateUtils;
import com.yahoo.slime.Slime;
-import com.yahoo.vespa.athenz.api.AthenzService;
-import com.yahoo.vespa.athenz.identityprovider.api.EntityBindingsMapper;
import com.yahoo.vespa.config.SlimeUtils;
import com.yahoo.vespa.hosted.athenz.instanceproviderservice.config.AthenzProviderServiceConfig;
-import com.yahoo.vespa.hosted.athenz.instanceproviderservice.instanceconfirmation.InstanceConfirmation;
-import com.yahoo.vespa.hosted.athenz.instanceproviderservice.instanceconfirmation.InstanceValidator;
import com.yahoo.vespa.hosted.ca.Certificates;
import com.yahoo.vespa.hosted.ca.instance.InstanceIdentity;
-import com.yahoo.vespa.hosted.ca.instance.InstanceRefresh;
import com.yahoo.yolean.Exceptions;
import java.io.IOException;
@@ -31,10 +23,6 @@ import java.io.UncheckedIOException;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.time.Clock;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import java.util.logging.Level;
@@ -55,20 +43,18 @@ public class CertificateAuthorityApiHandler extends LoggingRequestHandler {
private final Certificates certificates;
private final String caPrivateKeySecretName;
private final String caCertificateSecretName;
- private final InstanceValidator instanceValidator;
@Inject
- public CertificateAuthorityApiHandler(Context ctx, SecretStore secretStore, AthenzProviderServiceConfig athenzProviderServiceConfig, InstanceValidator instanceValidator) {
- this(ctx, secretStore, new Certificates(Clock.systemUTC()), athenzProviderServiceConfig, instanceValidator);
+ public CertificateAuthorityApiHandler(Context ctx, SecretStore secretStore, AthenzProviderServiceConfig athenzProviderServiceConfig) {
+ this(ctx, secretStore, new Certificates(Clock.systemUTC()), athenzProviderServiceConfig);
}
- CertificateAuthorityApiHandler(Context ctx, SecretStore secretStore, Certificates certificates, AthenzProviderServiceConfig athenzProviderServiceConfig, InstanceValidator instanceValidator) {
+ CertificateAuthorityApiHandler(Context ctx, SecretStore secretStore, Certificates certificates, AthenzProviderServiceConfig athenzProviderServiceConfig) {
super(ctx);
this.secretStore = secretStore;
this.certificates = certificates;
this.caPrivateKeySecretName = athenzProviderServiceConfig.secretName();
this.caCertificateSecretName = athenzProviderServiceConfig.domain() + ".ca.cert";
- this.instanceValidator = instanceValidator;
}
@Override
@@ -95,14 +81,6 @@ public class CertificateAuthorityApiHandler extends LoggingRequestHandler {
private HttpResponse registerInstance(HttpRequest request) {
var instanceRegistration = deserializeRequest(request, InstanceSerializer::registrationFromSlime);
-
- InstanceConfirmation confirmation = new InstanceConfirmation(instanceRegistration.provider(), instanceRegistration.domain(), instanceRegistration.service(), EntityBindingsMapper.toSignedIdentityDocumentEntity(instanceRegistration.attestationData()));
- confirmation.set(InstanceValidator.SAN_IPS_ATTRNAME, Certificates.getSubjectAlternativeNames(instanceRegistration.csr(), SubjectAlternativeName.Type.IP_ADDRESS));
- confirmation.set(InstanceValidator.SAN_DNS_ATTRNAME, Certificates.getSubjectAlternativeNames(instanceRegistration.csr(), SubjectAlternativeName.Type.DNS_NAME));
- if (!instanceValidator.isValidInstance(confirmation)) {
- log.log(LogLevel.INFO, "Invalid instance registration for " + instanceRegistration.toString());
- return ErrorResponse.forbidden("Unable to launch service: " +instanceRegistration.service());
- }
var certificate = certificates.create(instanceRegistration.csr(), caCertificate(), caPrivateKey());
var instanceId = Certificates.instanceIdFrom(instanceRegistration.csr());
var identity = new InstanceIdentity(instanceRegistration.provider(), instanceRegistration.service(), instanceId,
@@ -113,65 +91,21 @@ public class CertificateAuthorityApiHandler extends LoggingRequestHandler {
private HttpResponse refreshInstance(HttpRequest request, String provider, String service, String instanceId) {
var instanceRefresh = deserializeRequest(request, InstanceSerializer::refreshFromSlime);
var instanceIdFromCsr = Certificates.instanceIdFrom(instanceRefresh.csr());
- var athenzService = new AthenzService(request.getJDiscRequest().getUserPrincipal().getName());
if (!instanceIdFromCsr.equals(instanceId)) {
throw new IllegalArgumentException("Mismatch between instance ID in URL path and instance ID in CSR " +
"[instanceId=" + instanceId + ",instanceIdFromCsr=" + instanceIdFromCsr +
"]");
}
-
- // Verify that the csr instance id matches one of the certificates in the chain
- refreshesSameInstanceId(instanceIdFromCsr, request);
-
-
- // Validate that there is no privilege escalation (can only refresh same service)
- refreshesSameService(instanceRefresh, athenzService);
-
- InstanceConfirmation instanceConfirmation = new InstanceConfirmation(provider, athenzService.getDomain().getName(), athenzService.getName(), null);
- instanceConfirmation.set(InstanceValidator.SAN_IPS_ATTRNAME, Certificates.getSubjectAlternativeNames(instanceRefresh.csr(), SubjectAlternativeName.Type.IP_ADDRESS));
- instanceConfirmation.set(InstanceValidator.SAN_DNS_ATTRNAME, Certificates.getSubjectAlternativeNames(instanceRefresh.csr(), SubjectAlternativeName.Type.DNS_NAME));
- if(!instanceValidator.isValidRefresh(instanceConfirmation)) {
- return ErrorResponse.forbidden("Unable to refresh cert: " + instanceRefresh.csr().getSubject().toString());
- }
-
var certificate = certificates.create(instanceRefresh.csr(), caCertificate(), caPrivateKey());
var identity = new InstanceIdentity(provider, service, instanceIdFromCsr, Optional.of(certificate));
return new SlimeJsonResponse(InstanceSerializer.identityToSlime(identity));
}
- public void refreshesSameInstanceId(String csrInstanceId, HttpRequest request) {
- String certificateInstanceId = getRequestCertificateChain(request).stream()
- .map(Certificates::instanceIdFrom)
- .filter(Optional::isPresent)
- .map(Optional::get)
- .findAny().orElseThrow(() -> new IllegalArgumentException("No client certificate with instance id in request."));
-
- if(! Objects.equals(certificateInstanceId, csrInstanceId)) {
- throw new IllegalArgumentException("Mismatch between instance ID in client certificate and instance ID in CSR " +
- "[instanceId=" + certificateInstanceId + ",instanceIdFromCsr=" + csrInstanceId +
- "]");
- }
- }
-
- private void refreshesSameService(InstanceRefresh instanceRefresh, AthenzService athenzService) {
- List<String> commonNames = X509CertificateUtils.getCommonNames(instanceRefresh.csr().getSubject());
- if(commonNames.size() != 1 && !Objects.equals(commonNames.get(0), athenzService.getFullName())) {
- throw new IllegalArgumentException(String.format("Invalid request, trying to refresh service %s using service %s.", instanceRefresh.csr().getSubject().getName(), athenzService.getFullName()));
- }
- }
-
/** Returns CA certificate from secret store */
private X509Certificate caCertificate() {
return X509CertificateUtils.fromPem(secretStore.getSecret(caCertificateSecretName));
}
- private List<X509Certificate> getRequestCertificateChain(HttpRequest request) {
- return Optional.ofNullable(request.getJDiscRequest().context().get(ServletRequest.JDISC_REQUEST_X509CERT))
- .map(X509Certificate[].class::cast)
- .map(Arrays::asList)
- .orElse(Collections.emptyList());
- }
-
/** Returns CA private key from secret store */
private PrivateKey caPrivateKey() {
return KeyUtils.fromPemEncodedPrivateKey(secretStore.getSecret(caPrivateKeySecretName));