Skip to content

Commit 8e8ea85

Browse files
authored
Merge pull request #4402 from kubernetes-client/copilot/fix-tls-server-name-validation
Support tls-server-name field from kubeconfig for SNI
2 parents 4401a55 + 8fde880 commit 8e8ea85

File tree

5 files changed

+91
-0
lines changed

5 files changed

+91
-0
lines changed

util/src/main/java/io/kubernetes/client/util/ClientBuilder.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ public class ClientBuilder {
6464
private boolean verifyingSsl = true;
6565
private Authentication authentication;
6666
private String keyStorePassphrase;
67+
private String tlsServerName;
6768
// defaulting client protocols to HTTP1.1 and HTTP 2
6869
private List<Protocol> protocols = Arrays.asList(Protocol.HTTP_2, Protocol.HTTP_1_1);
6970
// default to unlimited read timeout
@@ -312,6 +313,11 @@ public static ClientBuilder kubeconfig(KubeConfig config, Duration tokenRefreshP
312313
}
313314
builder.setVerifyingSsl(config.verifySSL());
314315

316+
String tlsServerName = config.getTlsServerName();
317+
if (tlsServerName != null && !tlsServerName.isEmpty()) {
318+
builder.setTlsServerName(tlsServerName);
319+
}
320+
315321
builder.setBasePath(server);
316322
builder.setAuthentication(new KubeconfigAuthentication(config, tokenRefreshPeriod));
317323
return builder;
@@ -436,6 +442,15 @@ public ClientBuilder setKeyStorePassphrase(String keyStorePassphrase) {
436442
return this;
437443
}
438444

445+
public String getTlsServerName() {
446+
return tlsServerName;
447+
}
448+
449+
public ClientBuilder setTlsServerName(String tlsServerName) {
450+
this.tlsServerName = tlsServerName;
451+
return this;
452+
}
453+
439454
public ApiClient getApiClient() {
440455
return this.apiClient;
441456
}
@@ -466,6 +481,10 @@ public ApiClient build() {
466481

467482
client.setVerifyingSsl(verifyingSsl);
468483

484+
if (tlsServerName != null && !tlsServerName.isEmpty()) {
485+
client.setTlsServerName(tlsServerName);
486+
}
487+
469488
if (authentication != null) {
470489
if (StringUtils.isNotEmpty(keyStorePassphrase)) {
471490
if (authentication instanceof KubeconfigAuthentication) {

util/src/main/java/io/kubernetes/client/util/KubeConfig.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,10 @@ public String getCertificateAuthorityFile() {
176176
return getData(currentCluster, "certificate-authority");
177177
}
178178

179+
public String getTlsServerName() {
180+
return getData(currentCluster, "tls-server-name");
181+
}
182+
179183
public String getClientCertificateFile() {
180184
return getData(currentUser, "client-certificate");
181185
}

util/src/test/java/io/kubernetes/client/util/ClientBuilderTest.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ class ClientBuilderTest {
4848
Resources.getResource("kubeconfig-https").getPath();
4949
private static final String KUBECONFIG_HTTPS_X509_FILE_PATH =
5050
Resources.getResource("kubeconfig-https-x509").getPath();
51+
private static final String KUBECONFIG_TLS_SERVER_NAME_FILE_PATH =
52+
Resources.getResource("kubeconfig-tls-server-name").getPath();
5153
private static final String SSL_CA_CERT_PATH =
5254
new File(Resources.getResource("ca-cert.pem").getPath()).toString();
5355
private static final String INVALID_SSL_CA_CERT_PATH =
@@ -321,4 +323,22 @@ void detectsServerNotSet() {
321323
ClientBuilder.kubeconfig(kubeConfigWithoutServer);
322324
}).hasMessage("No server in kubeconfig").isInstanceOf(IllegalArgumentException.class);
323325
}
326+
327+
@Test
328+
void tlsServerNameSetFromKubeConfig() throws IOException {
329+
ApiClient client =
330+
ClientBuilder.kubeconfig(
331+
KubeConfig.loadKubeConfig(new FileReader(KUBECONFIG_TLS_SERVER_NAME_FILE_PATH)))
332+
.build();
333+
assertThat(client.getTlsServerName()).isEqualTo("my-cluster.example.com");
334+
}
335+
336+
@Test
337+
void tlsServerNameNotSetWhenNotInKubeConfig() throws IOException {
338+
ApiClient client =
339+
ClientBuilder.kubeconfig(
340+
KubeConfig.loadKubeConfig(new FileReader(KUBECONFIG_HTTPS_FILE_PATH)))
341+
.build();
342+
assertThat(client.getTlsServerName()).isNull();
343+
}
324344
}

util/src/test/java/io/kubernetes/client/util/KubeConfigTest.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,4 +425,35 @@ void execCredentialsCertificate() {
425425
assertThat(kc.getCredentials()).containsEntry(KubeConfig.CRED_CLIENT_KEY_DATA_KEY, "key");
426426
assertThat(kc.getCredentials().get(KubeConfig.CRED_TOKEN_KEY)).isNull();
427427
}
428+
429+
@Test
430+
void tlsServerName() {
431+
String configWithTlsServerName =
432+
"apiVersion: v1\n"
433+
+ "clusters:\n"
434+
+ "- cluster:\n"
435+
+ " server: https://192.168.1.1:6443\n"
436+
+ " tls-server-name: my-cluster.example.com\n"
437+
+ " certificate-authority-data: dGVzdAo=\n"
438+
+ " name: test-cluster\n"
439+
+ "users:\n"
440+
+ "- user:\n"
441+
+ " token: test-token\n"
442+
+ " name: test-user\n"
443+
+ "contexts:\n"
444+
+ "- context:\n"
445+
+ " cluster: test-cluster\n"
446+
+ " user: test-user\n"
447+
+ " name: test-context\n"
448+
+ "current-context: test-context\n";
449+
450+
KubeConfig config = KubeConfig.loadKubeConfig(new StringReader(configWithTlsServerName));
451+
assertThat("my-cluster.example.com").isEqualTo(config.getTlsServerName());
452+
}
453+
454+
@Test
455+
void tlsServerNameNotPresent() {
456+
KubeConfig config = KubeConfig.loadKubeConfig(new StringReader(KUBECONFIG_TOKEN));
457+
assertThat(config.getTlsServerName()).isNull();
458+
}
428459
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
apiVersion: v1
2+
clusters:
3+
- cluster:
4+
server: https://192.168.1.1:6443
5+
tls-server-name: my-cluster.example.com
6+
certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJkekNDQVIyZ0F3SUJBZ0lCQURBS0JnZ3Foa2pPUFFRREFqQWpNU0V3SHdZRFZRUUREQmhyTTNNdGMyVnkKZG1WeUxXTmhRREUzTXpNMU1qYzFPVGN3SGhjTk1qUXhNREkzTVRnek1ETTNXaGNOTXpReE1ESTFNVGd6TURNMwpXakFqTVNFd0h3WURWUVFEREJock0zTXRjMlZ5ZG1WeUxXTmhRREUzTXpNMU1qYzFPVGN3V1RBVEJnY3Foa2pPClBRSUJCZ2dxaGtqT1BRTUJCd05DQUFUMmY5dzdYZEJLRktDN2ptQUxYaDFlNVgyWjNYL0h5K2JYR0MxV1VoeHUKS3BZUUJ5Q0oxcU5RUjhQWHhOWEdvd3BJUFp0ekU0T2NQdjFRUlJyd0hvNkZvMEl3UURBT0JnTlZIUThCQWY4RQpCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVXdYam5rdWRSek55T1N2VmY2Mm1PCnFqc2FxREF3Q2dZSUtvWkl6ajBFQXdJRFNBQXdSUUlnRGRYelNuYTRnS2x6akJ2MllLVDJqM0VlSzY1WndPa2cKNGMxaG1nK29CVHdDSVFEdTBGR2NjRVE3OXE2U0pGTkF1bUhsd0JaY3lmeE5sOWhDb3hSRUdWVy93Zz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
7+
name: test-cluster
8+
users:
9+
- user:
10+
token: test-token
11+
name: test-user
12+
contexts:
13+
- context:
14+
cluster: test-cluster
15+
user: test-user
16+
name: test-context
17+
current-context: test-context

0 commit comments

Comments
 (0)