Skip to content

Commit bc2949f

Browse files
Merge pull request #2668 from ealeonraz/fix-oidc-refresh-tempfile-windows-async
Fix OIDC token refresh failing on Windows in the asyncio client
2 parents 9bc5eac + 880f227 commit bc2949f

1 file changed

Lines changed: 40 additions & 30 deletions

File tree

kubernetes/aio/config/kube_config.py

Lines changed: 40 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,26 @@ def _cleanup_temp_files():
5252
_temp_files = {}
5353

5454

55+
def _create_temp_file_with_content(content, temp_file_path=None, force_recreate=False):
56+
if len(_temp_files) == 0:
57+
atexit.register(_cleanup_temp_files)
58+
59+
# Because we may change context several times, try to remember files we
60+
# created and reuse them at a small memory cost.
61+
content_key = str(content)
62+
63+
if not force_recreate and content_key in _temp_files:
64+
return _temp_files[content_key]
65+
if temp_file_path and not os.path.isdir(temp_file_path):
66+
os.makedirs(name=temp_file_path)
67+
fd, name = tempfile.mkstemp(dir=temp_file_path)
68+
os.close(fd)
69+
_temp_files[content_key] = name
70+
with open(name, 'wb') as fd:
71+
fd.write(content.encode() if isinstance(content, str) else content)
72+
return name
73+
74+
5575
def _is_expired(expiry):
5676
return ((parse_rfc3339(expiry) - EXPIRY_SKEW_PREVENTION_DELAY)
5777
<= datetime.datetime.utcnow().replace(tzinfo=UTC))
@@ -85,18 +105,7 @@ def __init__(self, obj, file_key_name, data_key_name=None,
85105
os.path.join(file_base_path, obj[file_key_name]))
86106

87107
def _create_temp_file_with_content(self, content):
88-
if len(_temp_files) == 0:
89-
atexit.register(_cleanup_temp_files)
90-
# Because we may change context several times, try to remember files we
91-
# created and reuse them at a small memory cost.
92-
content_key = str(content)
93-
if content_key in _temp_files:
94-
return _temp_files[content_key]
95-
_, name = tempfile.mkstemp(dir=self._temp_file_path)
96-
_temp_files[content_key] = name
97-
with open(name, 'wb') as fd:
98-
fd.write(content.encode() if isinstance(content, str) else content)
99-
return name
108+
return _create_temp_file_with_content(content, self._temp_file_path)
100109

101110
def as_file(self):
102111
"""If obj[%data_key_name] exists, return name of a file with base64
@@ -282,28 +291,29 @@ async def _refresh_oidc(self, provider):
282291
if 'refresh-token' not in provider['config']:
283292
raise ConfigException('oidc: No valid id-token, and cannot refresh without refresh-token')
284293

285-
with tempfile.NamedTemporaryFile(delete=True) as certfile:
286-
ssl_ca_cert = None
287-
cert_auth_data = self._retrieve_oidc_cacert(provider)
288-
if cert_auth_data is not None:
289-
certfile.write(cert_auth_data)
290-
certfile.flush()
291-
ssl_ca_cert = certfile.name
294+
ssl_ca_cert = None
295+
cert_auth_data = self._retrieve_oidc_cacert(provider)
292296

293-
requestor = OpenIDRequestor(
294-
provider['config']['client-id'],
295-
provider['config']['client-secret'],
296-
provider['config']['idp-issuer-url'],
297-
ssl_ca_cert,
298-
)
297+
if cert_auth_data is not None:
298+
# Write through the shared helper instead of handing out the name
299+
# of an open NamedTemporaryFile, which cannot be reopened by path
300+
# on Windows while the original handle is still open.
301+
ssl_ca_cert = _create_temp_file_with_content(cert_auth_data)
299302

300-
resp = await requestor.refresh_token(provider['config']['refresh-token'])
303+
requestor = OpenIDRequestor(
304+
provider['config']['client-id'],
305+
provider['config']['client-secret'],
306+
provider['config']['idp-issuer-url'],
307+
ssl_ca_cert,
308+
)
301309

302-
provider['config'].value['id-token'] = resp['id_token']
303-
provider['config'].value['refresh-token'] = resp['refresh_token']
310+
resp = await requestor.refresh_token(provider['config']['refresh-token'])
304311

305-
if self._config_persister:
306-
self._config_persister(self._config.value)
312+
provider['config'].value['id-token'] = resp['id_token']
313+
provider['config'].value['refresh-token'] = resp['refresh_token']
314+
315+
if self._config_persister:
316+
self._config_persister(self._config.value)
307317

308318
def _retrieve_oidc_cacert(self, provider):
309319
if 'idp-certificate-authority-data' in provider['config']:

0 commit comments

Comments
 (0)