Skip to content

Commit 3346d59

Browse files
authored
Support TLS server name (#270)
1 parent 8040241 commit 3346d59

File tree

7 files changed

+72
-2
lines changed

7 files changed

+72
-2
lines changed

kubernetes_asyncio/client/configuration.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,10 @@ def __init__(self, host=None,
189189
self.assert_hostname = None
190190
"""Set this to True/False to enable/disable SSL hostname verification.
191191
"""
192+
self.tls_server_name = None
193+
"""SSL/TLS Server Name Indication (SNI)
194+
Set this to the SNI value expected by Kubernetes API.
195+
"""
192196

193197
self.connection_pool_maxsize = 100
194198
"""This value is passed to the aiohttp to limit simultaneous connections.

kubernetes_asyncio/client/rest.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ def __init__(self, configuration, pools_size=4, maxsize=None):
5656
configuration.cert_file, keyfile=configuration.key_file
5757
)
5858

59+
self.server_hostname = configuration.tls_server_name
60+
5961
if not configuration.verify_ssl:
6062
ssl_context.check_hostname = False
6163
ssl_context.verify_mode = ssl.CERT_NONE
@@ -135,6 +137,9 @@ async def request(self, method, url, query_params=None, headers=None,
135137
if query_params:
136138
args["url"] += '?' + urlencode(query_params)
137139

140+
if self.server_hostname:
141+
args["server_hostname"] = self.server_hostname
142+
138143
# For `POST`, `PUT`, `PATCH`, `OPTIONS`, `DELETE`
139144
if method in ['POST', 'PUT', 'PATCH', 'OPTIONS', 'DELETE']:
140145
if (

kubernetes_asyncio/config/kube_config.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -393,14 +393,16 @@ def _load_cluster_info(self):
393393
temp_file_path=self._temp_file_path).as_file()
394394
if 'insecure-skip-tls-verify' in self._cluster:
395395
self.verify_ssl = not self._cluster['insecure-skip-tls-verify']
396+
if 'tls-server-name' in self._cluster:
397+
self.tls_server_name = self._cluster['tls-server-name']
396398

397399
def _set_config(self, client_configuration):
398400

399401
if 'token' in self.__dict__:
400402
client_configuration.api_key['BearerToken'] = self.token
401403

402404
# copy these keys directly from self to configuration object
403-
keys = ['host', 'ssl_ca_cert', 'cert_file', 'key_file', 'verify_ssl']
405+
keys = ['host', 'ssl_ca_cert', 'cert_file', 'key_file', 'verify_ssl', 'tls_server_name']
404406
for key in keys:
405407
if key in self.__dict__:
406408
setattr(client_configuration, key, getattr(self, key))

kubernetes_asyncio/config/kube_config_test.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ def _raise_exception(st):
7272
TEST_CLIENT_KEY_BASE64 = _base64(TEST_CLIENT_KEY)
7373
TEST_CLIENT_CERT = "client-cert"
7474
TEST_CLIENT_CERT_BASE64 = _base64(TEST_CLIENT_CERT)
75+
TEST_TLS_SERVER_NAME = "kubernetes.io"
7576

7677
TEST_OIDC_TOKEN = "test-oidc-token"
7778
TEST_OIDC_INFO = "{\"name\": \"test\"}"
@@ -443,6 +444,13 @@ class TestKubeConfigLoader(BaseTestCase):
443444
"user": "exec_cred_user_certificate"
444445
}
445446
},
447+
{
448+
"name": "tls-server-name",
449+
"context": {
450+
"cluster": "tls-server-name",
451+
"user": "ssl"
452+
}
453+
},
446454
],
447455
"clusters": [
448456
{
@@ -488,6 +496,16 @@ class TestKubeConfigLoader(BaseTestCase):
488496
"insecure-skip-tls-verify": False,
489497
}
490498
},
499+
{
500+
"name": "tls-server-name",
501+
"cluster": {
502+
"server": TEST_SSL_HOST,
503+
"certificate-authority-data":
504+
TEST_CERTIFICATE_AUTH_BASE64,
505+
"insecure-skip-tls-verify": False,
506+
"tls-server-name": TEST_TLS_SERVER_NAME,
507+
}
508+
},
491509
],
492510
"users": [
493511
{
@@ -863,6 +881,22 @@ async def test_ssl_verification(self):
863881
active_context="ssl_verification").load_and_set(actual)
864882
self.assertEqual(expected, actual)
865883

884+
async def test_tls_server_name(self):
885+
expected = FakeConfig(
886+
host=TEST_SSL_HOST,
887+
token=BEARER_TOKEN_FORMAT % TEST_DATA_BASE64,
888+
cert_file=self._create_temp_file(TEST_CLIENT_CERT),
889+
key_file=self._create_temp_file(TEST_CLIENT_KEY),
890+
ssl_ca_cert=self._create_temp_file(TEST_CERTIFICATE_AUTH),
891+
verify_ssl=True,
892+
tls_server_name=TEST_TLS_SERVER_NAME
893+
)
894+
actual = FakeConfig()
895+
await KubeConfigLoader(
896+
config_dict=self.TEST_KUBE_CONFIG,
897+
active_context="tls-server-name").load_and_set(actual)
898+
self.assertEqual(expected, actual)
899+
866900
def test_list_contexts(self):
867901
loader = KubeConfigLoader(
868902
config_dict=self.TEST_KUBE_CONFIG,

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@ python-dateutil>=2.5.3 # BSD
44
setuptools>=21.0.0 # PSF/ZPL
55
urllib3>=1.24.2 # MIT
66
pyyaml>=3.12 # MIT
7-
aiohttp>=3.7.0,<4.0.0 # # Apache-2.0
7+
aiohttp>=3.9.0,<4.0.0 # # Apache-2.0
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
diff --git a/kubernetes_asyncio/client/rest.py b/kubernetes_asyncio/client/rest.py
2+
index c5be7990..9e0daab4 100644
3+
--- a/kubernetes_asyncio/client/rest.py
4+
+++ b/kubernetes_asyncio/client/rest.py
5+
@@ -56,6 +56,8 @@ class RESTClientObject(object):
6+
configuration.cert_file, keyfile=configuration.key_file
7+
)
8+
9+
+ self.server_hostname = configuration.tls_server_name
10+
+
11+
if not configuration.verify_ssl:
12+
ssl_context.check_hostname = False
13+
ssl_context.verify_mode = ssl.CERT_NONE
14+
@@ -135,6 +137,9 @@ class RESTClientObject(object):
15+
if query_params:
16+
args["url"] += '?' + urlencode(query_params)
17+
18+
+ if self.server_hostname:
19+
+ args["server_hostname"] = self.server_hostname
20+
+
21+
# For `POST`, `PUT`, `PATCH`, `OPTIONS`, `DELETE`
22+
if method in ['POST', 'PUT', 'PATCH', 'OPTIONS', 'DELETE']:
23+
if re.search('json', headers['Content-Type'], re.IGNORECASE):

scripts/update-client.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ echo ">>> fix generated rest client for patching with strategic merge..."
6868
patch "${CLIENT_ROOT}/client/rest.py" "${SCRIPT_ROOT}/rest_client_patch.diff"
6969
echo ">>> fix generated rest client by increasing aiohttp read buffer to 2MiB..."
7070
patch "${CLIENT_ROOT}/client/rest.py" "${SCRIPT_ROOT}/rest_client_patch_read_bufsize.diff"
71+
echo ">>> fix generated rest client to support customer server hostname TLS verification..."
72+
patch "${CLIENT_ROOT}/client/rest.py" "${SCRIPT_ROOT}/rest_client_server_hostname_patch.diff"
7173

7274

7375
echo ">>> Remove invalid tests (workaround https://github.com/OpenAPITools/openapi-generator/issues/5377)"

0 commit comments

Comments
 (0)