diff --git a/CHANGELOG.md b/CHANGELOG.md index 9fa9416a468..c7b4554526d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,8 @@ ### 6.7-SNAPSHOT #### Bugs -Fix #5145: [java-generator] handle `additionalProperties: true` emitting a field of type `AnyType` +* Fix #5125: TLS 1.3 only should be supported +* Fix #5145: [java-generator] handle `additionalProperties: true` emitting a field of type `AnyType` #### Improvements @@ -20,6 +21,8 @@ Fix #5145: [java-generator] handle `additionalProperties: true` emitting a field * Fix #4662: removed deprecated classes/methods: ReflectUtils, ReplaceValueStream, ParameterNamespaceListVisitFromServerGetDeleteRecreateWaitApplicable, ResourceCompare, and Serialization methods taking parameters * Fix #4662: deprecated serialization static logic: several IOHelpers methods, Serialization methods, such as access to the static jsonMapper. Please use KubernetesSerialization methods instead. * Fix #4662: deprecated Helper.getAnnotationValue, use HasMetadata methods instead. +* Fix #5125: support for TLSv1.3 is now enabled by default +* Fix #5125: usage of TlsVersion.TLS_1_1, TLS_1_0, and SSL_3_0 have been deprecated ### 6.6.2 (2023-05-15) diff --git a/README.md b/README.md index e9fb3a88708..ae3b3f2e727 100644 --- a/README.md +++ b/README.md @@ -112,7 +112,7 @@ System properties are preferred over environment variables. The following system | `kubernetes.max.concurrent.requests.per.host` / `KUBERNETES_MAX_CONCURRENT_REQUESTS_PER_HOST` | | `5` | | `kubernetes.impersonate.username` / `KUBERNETES_IMPERSONATE_USERNAME` | `Impersonate-User` HTTP header value | | | `kubernetes.impersonate.group` / `KUBERNETES_IMPERSONATE_GROUP` | `Impersonate-Group` HTTP header value | | -| `kubernetes.tls.versions` / `KUBERNETES_TLS_VERSIONS` | TLS versions separated by `,` | `TLSv1.2` | +| `kubernetes.tls.versions` / `KUBERNETES_TLS_VERSIONS` | TLS versions separated by `,` | `TLSv1.2,TLSv1.3` | | `kubernetes.truststore.file` / `KUBERNETES_TRUSTSTORE_FILE` | | | | `kubernetes.truststore.passphrase` / `KUBERNETES_TRUSTSTORE_PASSPHRASE` | | | | `kubernetes.keystore.file` / `KUBERNETES_KEYSTORE_FILE` | | | diff --git a/httpclient-vertx/src/main/java/io/fabric8/kubernetes/client/vertx/VertxHttpClientBuilder.java b/httpclient-vertx/src/main/java/io/fabric8/kubernetes/client/vertx/VertxHttpClientBuilder.java index 19ca5b344d9..8c63cec9b88 100644 --- a/httpclient-vertx/src/main/java/io/fabric8/kubernetes/client/vertx/VertxHttpClientBuilder.java +++ b/httpclient-vertx/src/main/java/io/fabric8/kubernetes/client/vertx/VertxHttpClientBuilder.java @@ -29,6 +29,8 @@ import io.vertx.core.spi.tls.SslContextFactory; import io.vertx.ext.web.client.WebClientOptions; +import java.util.Arrays; +import java.util.HashSet; import java.util.concurrent.TimeUnit; import java.util.stream.Stream; @@ -73,8 +75,12 @@ public VertxHttpClient build() { options.setProxyOptions(proxyOptions); } + final String[] protocols; if (tlsVersions != null && tlsVersions.length > 0) { - Stream.of(tlsVersions).map(TlsVersion::javaName).forEach(options::addEnabledSecureTransportProtocol); + protocols = Stream.of(tlsVersions).map(TlsVersion::javaName).toArray(String[]::new); + options.setEnabledSecureTransportProtocols(new HashSet<>(Arrays.asList(protocols))); + } else { + protocols = null; } if (this.preferHttp11) { @@ -98,7 +104,7 @@ public SslContextFactory sslContextFactory() { IdentityCipherSuiteFilter.INSTANCE, ApplicationProtocolConfig.DISABLED, io.netty.handler.ssl.ClientAuth.NONE, - null, + protocols, false); } }); diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/Config.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/Config.java index 47269765479..31af965cec8 100644 --- a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/Config.java +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/Config.java @@ -215,7 +215,7 @@ public class Config { private String proxyPassword; private String[] noProxy; private String userAgent = "fabric8-kubernetes-client/" + Version.clientVersion(); - private TlsVersion[] tlsVersions = new TlsVersion[] { TlsVersion.TLS_1_2 }; + private TlsVersion[] tlsVersions = new TlsVersion[] { TlsVersion.TLS_1_3, TlsVersion.TLS_1_2 }; private Map errorMessages = new HashMap<>(); diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/http/TlsVersion.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/http/TlsVersion.java index 4e02fdf5e96..e4e1624d7f1 100644 --- a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/http/TlsVersion.java +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/http/TlsVersion.java @@ -18,15 +18,19 @@ /** * TODO: determine if java names should be used here as well or instead - * + * * Replacement for okhttp3.TlsVersion */ public enum TlsVersion { + // these need to be kept in preference order TLS_1_3("TLSv1.3"), TLS_1_2("TLSv1.2"), + @Deprecated TLS_1_1("TLSv1.1"), + @Deprecated TLS_1_0("TLSv1"), + @Deprecated SSL_3_0("SSLv3"), ; diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/internal/SSLUtils.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/internal/SSLUtils.java index 86d0a22b2ab..f77489e6e26 100644 --- a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/internal/SSLUtils.java +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/internal/SSLUtils.java @@ -17,6 +17,7 @@ import io.fabric8.kubernetes.client.Config; import io.fabric8.kubernetes.client.KubernetesClientException; +import io.fabric8.kubernetes.client.http.TlsVersion; import io.fabric8.kubernetes.client.utils.Utils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -83,11 +84,30 @@ public static SSLContext sslContext(Config config) throws CertificateException, } public static SSLContext sslContext(KeyManager[] keyManagers, TrustManager[] trustManagers) { + SSLContext sslContext = null; + NoSuchAlgorithmException noSuch = null; + // v1.3 is not supported on all vms, and of course there may be later versions added. + // so try to find one starting with the latest + for (TlsVersion version : TlsVersion.values()) { + try { + sslContext = SSLContext.getInstance(version.javaName()); + break; + } catch (NoSuchAlgorithmException e) { + if (noSuch == null) { + noSuch = e; + } + continue; + } + } + + if (sslContext == null) { + throw KubernetesClientException.launderThrowable(noSuch); + } + try { - SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); sslContext.init(keyManagers, trustManagers, new SecureRandom()); return sslContext; - } catch (KeyManagementException | NoSuchAlgorithmException e) { + } catch (KeyManagementException e) { throw KubernetesClientException.launderThrowable(e); } } diff --git a/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/ConfigTest.java b/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/ConfigTest.java index 4967ddde509..4136a8b91fc 100644 --- a/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/ConfigTest.java +++ b/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/ConfigTest.java @@ -599,7 +599,7 @@ void testEmptyConfig() { assertTrue(emptyConfig.getImpersonateExtras().isEmpty()); assertEquals(0, emptyConfig.getImpersonateGroups().length); assertFalse(emptyConfig.isHttp2Disable()); - assertEquals(1, emptyConfig.getTlsVersions().length); + assertEquals(2, emptyConfig.getTlsVersions().length); assertTrue(emptyConfig.getErrorMessages().isEmpty()); assertNotNull(emptyConfig.getUserAgent()); }