diff options
author | Bjørn Christian Seime <bjorncs@verizonmedia.com> | 2021-02-24 17:14:08 +0100 |
---|---|---|
committer | Bjørn Christian Seime <bjorncs@verizonmedia.com> | 2021-02-24 17:14:08 +0100 |
commit | 23e018497c07d9a1e8451c3531dc073e93b73617 (patch) | |
tree | 5986b3f493cfdd39cf0a595881cc4eb25539fbbb /security-utils/src | |
parent | 3e0954075fde4f01717c9a9e987231af95812a31 (diff) |
Make TLS protocol version configurable in TLS config file
Only protocols listed in allowlist can be configured.
TLSv1.2 is the only supported version at the moment, but TLSv1.3 will most likely be included in the future.
Diffstat (limited to 'security-utils/src')
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 |