diff options
8 files changed, 49 insertions, 11 deletions
diff --git a/security-utils/src/main/java/com/yahoo/security/tls/ConfigFileBasedTlsContext.java b/security-utils/src/main/java/com/yahoo/security/tls/ConfigFileBasedTlsContext.java index b061d2f9165..acc70d50d6a 100644 --- a/security-utils/src/main/java/com/yahoo/security/tls/ConfigFileBasedTlsContext.java +++ b/security-utils/src/main/java/com/yahoo/security/tls/ConfigFileBasedTlsContext.java @@ -118,7 +118,9 @@ public class ConfigFileBasedTlsContext implements TlsContext { .build(); List<String> acceptedCiphers = options.getAcceptedCiphers(); Set<String> ciphers = acceptedCiphers.isEmpty() ? TlsContext.ALLOWED_CIPHER_SUITES : new HashSet<>(acceptedCiphers); - return new DefaultTlsContext(sslContext, ciphers, peerAuthentication); + List<String> acceptedProtocols = options.getAcceptedProtocols(); + Set<String> protocols = acceptedProtocols.isEmpty() ? TlsContext.ALLOWED_PROTOCOLS : new HashSet<>(acceptedProtocols); + return new DefaultTlsContext(sslContext, ciphers, protocols, peerAuthentication); } // Wrapped methods from TlsContext diff --git a/security-utils/src/main/java/com/yahoo/security/tls/DefaultTlsContext.java b/security-utils/src/main/java/com/yahoo/security/tls/DefaultTlsContext.java index d2a42d21973..250596628ee 100644 --- a/security-utils/src/main/java/com/yahoo/security/tls/DefaultTlsContext.java +++ b/security-utils/src/main/java/com/yahoo/security/tls/DefaultTlsContext.java @@ -10,6 +10,7 @@ import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLParameters; import java.security.PrivateKey; import java.security.cert.X509Certificate; +import java.util.Arrays; import java.util.List; import java.util.Set; import java.util.logging.Level; @@ -40,14 +41,14 @@ public class DefaultTlsContext implements TlsContext { } public DefaultTlsContext(SSLContext sslContext, PeerAuthentication peerAuthentication) { - this(sslContext, TlsContext.ALLOWED_CIPHER_SUITES, peerAuthentication); + this(sslContext, TlsContext.ALLOWED_CIPHER_SUITES, TlsContext.ALLOWED_PROTOCOLS, peerAuthentication); } - DefaultTlsContext(SSLContext sslContext, Set<String> acceptedCiphers, PeerAuthentication peerAuthentication) { + DefaultTlsContext(SSLContext sslContext, Set<String> acceptedCiphers, Set<String> acceptedProtocols, PeerAuthentication peerAuthentication) { this.sslContext = sslContext; this.peerAuthentication = peerAuthentication; this.validCiphers = getAllowedCiphers(sslContext, acceptedCiphers); - this.validProtocols = getAllowedProtocols(sslContext); + this.validProtocols = getAllowedProtocols(sslContext, acceptedProtocols); } private static String[] getAllowedCiphers(SSLContext sslContext, Set<String> acceptedCiphers) { @@ -64,10 +65,18 @@ public class DefaultTlsContext implements TlsContext { return allowedCiphers; } - private static String[] getAllowedProtocols(SSLContext sslContext) { - Set<String> allowedProtocols = TlsContext.getAllowedProtocols(sslContext); - log.log(Level.FINE, () -> String.format("Allowed protocols that are supported: %s", com.yahoo.vespa.jdk8compat.List.of(allowedProtocols))); - return com.yahoo.vespa.jdk8compat.Collection.toArray(allowedProtocols, String[]::new); + private static String[] getAllowedProtocols(SSLContext sslContext, Set<String> acceptedProtocols) { + Set<String> supportedProtocols = TlsContext.getAllowedProtocols(sslContext); + String[] allowedProtocols = supportedProtocols.stream() + .filter(acceptedProtocols::contains) + .toArray(String[]::new); + if (allowedProtocols.length == 0) { + throw new IllegalStateException( + String.format("None of the accepted protocols are supported (supported=%s, accepted=%s)", + supportedProtocols, acceptedProtocols)); + } + log.log(Level.FINE, () -> String.format("Allowed protocols that are supported: %s", Arrays.toString(allowedProtocols))); + return allowedProtocols; } @Override diff --git a/security-utils/src/main/java/com/yahoo/security/tls/TransportSecurityOptions.java b/security-utils/src/main/java/com/yahoo/security/tls/TransportSecurityOptions.java index 5db6d551193..82c19878dfb 100644 --- a/security-utils/src/main/java/com/yahoo/security/tls/TransportSecurityOptions.java +++ b/security-utils/src/main/java/com/yahoo/security/tls/TransportSecurityOptions.java @@ -30,6 +30,7 @@ public class TransportSecurityOptions { private final Path caCertificatesFile; private final AuthorizedPeers authorizedPeers; private final List<String> acceptedCiphers; + private final List<String> acceptedProtocols; private final boolean isHostnameValidationDisabled; private TransportSecurityOptions(Builder builder) { @@ -38,6 +39,7 @@ public class TransportSecurityOptions { this.caCertificatesFile = builder.caCertificatesFile; this.authorizedPeers = builder.authorizedPeers; this.acceptedCiphers = builder.acceptedCiphers; + this.acceptedProtocols = builder.acceptedProtocols; this.isHostnameValidationDisabled = builder.isHostnameValidationDisabled; } @@ -59,6 +61,8 @@ public class TransportSecurityOptions { public List<String> getAcceptedCiphers() { return acceptedCiphers; } + public List<String> getAcceptedProtocols() { return acceptedProtocols; } + public boolean isHostnameValidationDisabled() { return isHostnameValidationDisabled; } public static TransportSecurityOptions fromJsonFile(Path file) { @@ -95,6 +99,7 @@ public class TransportSecurityOptions { private AuthorizedPeers authorizedPeers; private List<String> acceptedCiphers = new ArrayList<>(); private boolean isHostnameValidationDisabled; + private List<String> acceptedProtocols = new ArrayList<>(); public Builder() {} @@ -119,6 +124,11 @@ public class TransportSecurityOptions { return this; } + public Builder withAcceptedProtocols(List<String> acceptedProtocols) { + this.acceptedProtocols = acceptedProtocols; + return this; + } + public Builder withHostnameValidationDisabled(boolean isDisabled) { this.isHostnameValidationDisabled = isDisabled; return this; @@ -137,6 +147,7 @@ public class TransportSecurityOptions { ", caCertificatesFile=" + caCertificatesFile + ", authorizedPeers=" + authorizedPeers + ", acceptedCiphers=" + acceptedCiphers + + ", acceptedProtocols=" + acceptedProtocols + ", isHostnameValidationDisabled=" + isHostnameValidationDisabled + '}'; } @@ -151,11 +162,13 @@ public class TransportSecurityOptions { Objects.equals(certificatesFile, that.certificatesFile) && Objects.equals(caCertificatesFile, that.caCertificatesFile) && Objects.equals(authorizedPeers, that.authorizedPeers) && - Objects.equals(acceptedCiphers, that.acceptedCiphers); + Objects.equals(acceptedCiphers, that.acceptedCiphers) && + Objects.equals(acceptedProtocols, that.acceptedProtocols); } @Override public int hashCode() { - return Objects.hash(privateKeyFile, certificatesFile, caCertificatesFile, authorizedPeers, acceptedCiphers, isHostnameValidationDisabled); + return Objects.hash(privateKeyFile, certificatesFile, caCertificatesFile, authorizedPeers, acceptedCiphers, + acceptedProtocols, isHostnameValidationDisabled); } }
\ No newline at end of file diff --git a/security-utils/src/main/java/com/yahoo/security/tls/json/TransportSecurityOptionsEntity.java b/security-utils/src/main/java/com/yahoo/security/tls/json/TransportSecurityOptionsEntity.java index 35eef68cef2..68801002c66 100644 --- a/security-utils/src/main/java/com/yahoo/security/tls/json/TransportSecurityOptionsEntity.java +++ b/security-utils/src/main/java/com/yahoo/security/tls/json/TransportSecurityOptionsEntity.java @@ -21,6 +21,7 @@ class TransportSecurityOptionsEntity { @JsonProperty("files") Files files; @JsonProperty("authorized-peers") @JsonInclude(NON_EMPTY) List<AuthorizedPeer> authorizedPeers; @JsonProperty("accepted-ciphers") @JsonInclude(NON_EMPTY) List<String> acceptedCiphers; + @JsonProperty("accepted-protocols") @JsonInclude(NON_EMPTY) List<String> acceptedProtocols; @JsonProperty("disable-hostname-validation") @JsonInclude(NON_NULL) Boolean isHostnameValidationDisabled; @JsonIgnoreProperties(ignoreUnknown = true) diff --git a/security-utils/src/main/java/com/yahoo/security/tls/json/TransportSecurityOptionsJsonSerializer.java b/security-utils/src/main/java/com/yahoo/security/tls/json/TransportSecurityOptionsJsonSerializer.java index 75134e20b68..45819e2f974 100644 --- a/security-utils/src/main/java/com/yahoo/security/tls/json/TransportSecurityOptionsJsonSerializer.java +++ b/security-utils/src/main/java/com/yahoo/security/tls/json/TransportSecurityOptionsJsonSerializer.java @@ -76,6 +76,12 @@ public class TransportSecurityOptionsJsonSerializer { } builder.withAcceptedCiphers(entity.acceptedCiphers); } + if (entity.acceptedProtocols != null) { + if (entity.acceptedProtocols.isEmpty()) { + throw new IllegalArgumentException("'accepted-protocols' cannot be empty"); + } + builder.withAcceptedProtocols(entity.acceptedProtocols); + } if (entity.isHostnameValidationDisabled != null) { builder.withHostnameValidationDisabled(entity.isHostnameValidationDisabled); } @@ -162,6 +168,9 @@ public class TransportSecurityOptionsJsonSerializer { if (!options.getAcceptedCiphers().isEmpty()) { entity.acceptedCiphers = options.getAcceptedCiphers(); } + if (!options.getAcceptedProtocols().isEmpty()) { + entity.acceptedProtocols = options.getAcceptedProtocols(); + } if (options.isHostnameValidationDisabled()) { entity.isHostnameValidationDisabled = true; } diff --git a/security-utils/src/test/java/com/yahoo/security/tls/TransportSecurityOptionsTest.java b/security-utils/src/test/java/com/yahoo/security/tls/TransportSecurityOptionsTest.java index f2d2b932cd0..8fd2ca065c7 100644 --- a/security-utils/src/test/java/com/yahoo/security/tls/TransportSecurityOptionsTest.java +++ b/security-utils/src/test/java/com/yahoo/security/tls/TransportSecurityOptionsTest.java @@ -8,6 +8,7 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Collections; import static org.junit.Assert.assertEquals; @@ -21,6 +22,7 @@ public class TransportSecurityOptionsTest { .withCertificates(Paths.get("certs.pem"), Paths.get("myhost.key")) .withCaCertificates(Paths.get("my_cas.pem")) .withAcceptedCiphers(com.yahoo.vespa.jdk8compat.List.of("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" , "TLS_AES_256_GCM_SHA384")) + .withAcceptedProtocols(Collections.singletonList("TLSv1.2")) .withHostnameValidationDisabled(true) .build(); diff --git a/security-utils/src/test/java/com/yahoo/security/tls/json/TransportSecurityOptionsJsonSerializerTest.java b/security-utils/src/test/java/com/yahoo/security/tls/json/TransportSecurityOptionsJsonSerializerTest.java index ee1fa12b15f..e14b3d99212 100644 --- a/security-utils/src/test/java/com/yahoo/security/tls/json/TransportSecurityOptionsJsonSerializerTest.java +++ b/security-utils/src/test/java/com/yahoo/security/tls/json/TransportSecurityOptionsJsonSerializerTest.java @@ -69,6 +69,7 @@ public class TransportSecurityOptionsJsonSerializerTest { .withCertificates(Paths.get("certs.pem"), Paths.get("myhost.key")) .withCaCertificates(Paths.get("my_cas.pem")) .withAcceptedCiphers(com.yahoo.vespa.jdk8compat.List.of("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" , "TLS_AES_256_GCM_SHA384")) + .withAcceptedProtocols(Collections.singletonList("TLSv1.2")) .withHostnameValidationDisabled(true) .build(); File outputFile = tempDirectory.newFile(); diff --git a/security-utils/src/test/resources/transport-security-options.json b/security-utils/src/test/resources/transport-security-options.json index 7983982f644..f9987363a1f 100644 --- a/security-utils/src/test/resources/transport-security-options.json +++ b/security-utils/src/test/resources/transport-security-options.json @@ -5,5 +5,6 @@ "ca-certificates": "my_cas.pem", "certificates": "certs.pem" }, - "accepted-ciphers": ["TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "TLS_AES_256_GCM_SHA384"] + "accepted-ciphers": ["TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "TLS_AES_256_GCM_SHA384"], + "accepted-protocols": ["TLSv1.2"] }
\ No newline at end of file |