diff options
author | Morten Tokle <mortent@yahooinc.com> | 2022-11-30 15:49:30 +0100 |
---|---|---|
committer | Morten Tokle <mortent@yahooinc.com> | 2022-11-30 15:49:30 +0100 |
commit | 1f801694fe726cd3ebf1dfd10161355573a3af69 (patch) | |
tree | e39e109f7eb0bf3e0354a5934c0844ae7ff85d65 /config-model/src | |
parent | f611155a289870ad02b79e0cb9068a9fa1d55f67 (diff) |
Add validation override for certificate removal
Diffstat (limited to 'config-model/src')
3 files changed, 99 insertions, 0 deletions
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/Validation.java b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/Validation.java index 68b5adcc84f..b81b3524c67 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/Validation.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/Validation.java @@ -86,6 +86,7 @@ public class Validation { new CloudWatchValidator().validate(model, deployState); new QuotaValidator().validate(model, deployState); new UriBindingsValidator().validate(model, deployState); + new CloudDataPlaneFilterValidator().validate(model, deployState); additionalValidators.forEach(v -> v.validate(model, deployState)); diff --git a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/CertificateRemovalChangeValidator.java b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/CertificateRemovalChangeValidator.java new file mode 100644 index 00000000000..50fd6572bcc --- /dev/null +++ b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/change/CertificateRemovalChangeValidator.java @@ -0,0 +1,47 @@ +package com.yahoo.vespa.model.application.validation.change; + +import com.yahoo.config.application.api.ValidationId; +import com.yahoo.config.application.api.ValidationOverrides; +import com.yahoo.config.model.api.ConfigChangeAction; +import com.yahoo.vespa.model.VespaModel; +import com.yahoo.vespa.model.container.http.Client; + +import java.security.cert.X509Certificate; +import java.time.Instant; +import java.util.Collection; +import java.util.List; + +public class CertificateRemovalChangeValidator implements ChangeValidator { + @Override + public List<ConfigChangeAction> validate(VespaModel current, VespaModel next, ValidationOverrides overrides, Instant now) { + + current.getContainerClusters() + .forEach((clusterId, currentCluster) -> { + validateClients(clusterId, currentCluster.getClients(), next.getContainerClusters().get(clusterId).getClients(), overrides, now); + }); + + return List.of(); + } + + void validateClients(String clusterId, List<Client> current, List<Client> next, ValidationOverrides overrides, Instant now) { + + List<X509Certificate> currentCertificates = current.stream() + .map(Client::certificates) + .flatMap(Collection::stream) + .toList(); + List<X509Certificate> nextCertificates = next.stream() + .map(Client::certificates) + .flatMap(Collection::stream) + .toList(); + + List<X509Certificate> missingCerts = currentCertificates.stream().filter(cert -> !nextCertificates.contains(cert)).toList(); + if (!missingCerts.isEmpty()) { + overrides.invalid(ValidationId.certificateRemoval, + "Data plane certificate(s) from cluster '" + clusterId + "' is removed " + + "(removed certificates: " + missingCerts.stream().map(x509Certificate -> x509Certificate.getSubjectX500Principal().getName()).toList() + ") " + + "This can cause client connection issues.", + now); + } + + } +} diff --git a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/CertificateRemovalChangeValidatorTest.java b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/CertificateRemovalChangeValidatorTest.java new file mode 100644 index 00000000000..f89c75362da --- /dev/null +++ b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/CertificateRemovalChangeValidatorTest.java @@ -0,0 +1,51 @@ +package com.yahoo.vespa.model.application.validation.change; + +import com.yahoo.config.application.api.ValidationOverrides; +import com.yahoo.security.X509CertificateUtils; +import com.yahoo.vespa.model.container.http.Client; +import org.junit.jupiter.api.Test; + +import java.security.cert.X509Certificate; +import java.time.Duration; +import java.time.Instant; +import java.time.LocalDate; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class CertificateRemovalChangeValidatorTest { + + private static final String validationOverrides = + "<validation-overrides>\n" + + " <allow until='2000-01-14' comment='test override'>certificate-removal</allow>\n" + + "</validation-overrides>\n"; + + @Test + void validate() { + Instant now = LocalDate.parse("2000-01-01", DateTimeFormatter.ISO_DATE).atStartOfDay().atZone(ZoneOffset.UTC).toInstant(); + + Client c1 = new Client("c1", List.of(), List.of(certificate("cn=c1"))); + Client c2 = new Client("c2", List.of(), List.of(certificate("cn=c2"))); + Client c3 = new Client("c3", List.of(), List.of(certificate("cn=c3"))); + + CertificateRemovalChangeValidator validator = new CertificateRemovalChangeValidator(); + + // Adding certs -> ok + validator.validateClients("clusterId", List.of(c1,c2), List.of(c1, c2, c3), ValidationOverrides.empty, now); + + // Removing certs -> fails + assertThrows(ValidationOverrides.ValidationException.class, + () ->validator.validateClients("clusterId", List.of(c1, c2, c3), List.of(c1, c3), ValidationOverrides.empty, now)); + + // Removing certs with validationoverrides -> ok + validator.validateClients("clusterId", List.of(c1, c2, c3), List.of(c1, c3), ValidationOverrides.fromXml(validationOverrides), now); + + } + + static X509Certificate certificate(String cn) { + return X509CertificateUtils.createSelfSigned(cn, Duration.ofHours(1)).certificate(); + } + +} |