Skip to content
This repository was archived by the owner on Mar 13, 2022. It is now read-only.

Commit 1b6fdcf

Browse files
committed
Add option to refresh gcp token when config is cmd-path
1 parent a2d1024 commit 1b6fdcf

File tree

2 files changed

+85
-6
lines changed

2 files changed

+85
-6
lines changed

Diff for: config/kube_config.py

+73
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@
2020
import logging
2121
import os
2222
import platform
23+
import subprocess
2324
import tempfile
2425
import time
26+
from collections import namedtuple
2527

2628
import google.auth
2729
import google.auth.transport.requests
@@ -133,6 +135,46 @@ def as_data(self):
133135
return self._data
134136

135137

138+
class CommandTokenSource(object):
139+
def __init__(self, cmd, args, tokenKey, expiryKey):
140+
self._cmd = cmd
141+
self._args = args
142+
if not tokenKey:
143+
self._tokenKey = '{.access_token}'
144+
else:
145+
self._tokenKey = tokenKey
146+
if not expiryKey:
147+
self._expiryKey = '{.token_expiry}'
148+
else:
149+
self._expiryKey = expiryKey
150+
151+
def token(self):
152+
fullCmd = self._cmd + (" ") + " ".join(self._args)
153+
process = subprocess.Popen(
154+
[self._cmd] + self._args,
155+
stdout=subprocess.PIPE,
156+
stderr=subprocess.PIPE,
157+
universal_newlines=True)
158+
(stdout, stderr) = process.communicate()
159+
exit_code = process.wait()
160+
if exit_code != 0:
161+
msg = 'cmd-path: process returned %d' % exit_code
162+
msg += "\nCmd: %s" % fullCmd
163+
stderr = stderr.strip()
164+
if stderr:
165+
msg += '\nStderr: %s' % stderr
166+
raise ConfigException(msg)
167+
try:
168+
data = json.loads(stdout)
169+
except ValueError as de:
170+
raise ConfigException(
171+
'exec: failed to decode process output: %s' % de)
172+
A = namedtuple('A', ['token', 'expiry'])
173+
return A(
174+
token=data['credential']['access_token'],
175+
expiry=parse_rfc3339(data['credential']['token_expiry']))
176+
177+
136178
class KubeConfigLoader(object):
137179

138180
def __init__(self, config_dict, active_context=None,
@@ -156,7 +198,38 @@ def __init__(self, config_dict, active_context=None,
156198
self._config_base_path = config_base_path
157199
self._config_persister = config_persister
158200

201+
def _refresh_credentials_with_cmd_path():
202+
config = self._user['auth-provider']['config']
203+
cmd = config['cmd-path']
204+
if len(cmd) == 0:
205+
raise ConfigException(
206+
'missing access token cmd '
207+
'(cmd-path is an empty string in your kubeconfig file)')
208+
if 'scopes' in config and config['scopes'] != "":
209+
raise ConfigException(
210+
'scopes can only be used '
211+
'when kubectl is using a gcp service account key')
212+
args = []
213+
if 'cmd-args' in config:
214+
args = config['cmd-args'].split()
215+
else:
216+
fields = config['cmd-path'].split()
217+
cmd = fields[0]
218+
args = fields[1:]
219+
220+
commandTokenSource = CommandTokenSource(
221+
cmd, args,
222+
config.safe_get('token-key'),
223+
config.safe_get('expiry-key'))
224+
return commandTokenSource.token()
225+
159226
def _refresh_credentials():
227+
# Refresh credentials using cmd-path
228+
if ('auth-provider' in self._user and
229+
'config' in self._user['auth-provider'] and
230+
'cmd-path' in self._user['auth-provider']['config']):
231+
return _refresh_credentials_with_cmd_path()
232+
160233
credentials, project_id = google.auth.default(scopes=[
161234
'https://www.googleapis.com/auth/cloud-platform',
162235
'https://www.googleapis.com/auth/userinfo.email'

Diff for: config/kube_config_test.py

+12-6
Original file line numberDiff line numberDiff line change
@@ -661,7 +661,8 @@ class TestKubeConfigLoader(BaseTestCase):
661661
"auth-provider": {
662662
"config": {
663663
"access-token": TEST_AZURE_TOKEN,
664-
"apiserver-id": "00000002-0000-0000-c000-000000000000",
664+
"apiserver-id": "00000002-0000-0000-c000-"
665+
"000000000000",
665666
"environment": "AzurePublicCloud",
666667
"refresh-token": "refreshToken",
667668
"tenant-id": "9d2ac018-e843-4e14-9e2b-4e0ddac75433"
@@ -676,7 +677,8 @@ class TestKubeConfigLoader(BaseTestCase):
676677
"auth-provider": {
677678
"config": {
678679
"access-token": TEST_AZURE_TOKEN,
679-
"apiserver-id": "00000002-0000-0000-c000-000000000000",
680+
"apiserver-id": "00000002-0000-0000-c000-"
681+
"000000000000",
680682
"environment": "AzurePublicCloud",
681683
"expires-in": "0",
682684
"expires-on": "156207275",
@@ -693,7 +695,8 @@ class TestKubeConfigLoader(BaseTestCase):
693695
"auth-provider": {
694696
"config": {
695697
"access-token": TEST_AZURE_TOKEN,
696-
"apiserver-id": "00000002-0000-0000-c000-000000000000",
698+
"apiserver-id": "00000002-0000-0000-c000-"
699+
"000000000000",
697700
"environment": "AzurePublicCloud",
698701
"expires-in": "0",
699702
"expires-on": "2018-10-18 00:52:29.044727",
@@ -710,7 +713,8 @@ class TestKubeConfigLoader(BaseTestCase):
710713
"auth-provider": {
711714
"config": {
712715
"access-token": TEST_AZURE_TOKEN,
713-
"apiserver-id": "00000002-0000-0000-c000-000000000000",
716+
"apiserver-id": "00000002-0000-0000-c000-"
717+
"000000000000",
714718
"environment": "AzurePublicCloud",
715719
"expires-in": "0",
716720
"expires-on": "2018-10-18 00:52",
@@ -727,7 +731,8 @@ class TestKubeConfigLoader(BaseTestCase):
727731
"auth-provider": {
728732
"config": {
729733
"access-token": TEST_AZURE_TOKEN,
730-
"apiserver-id": "00000002-0000-0000-c000-000000000000",
734+
"apiserver-id": "00000002-0000-0000-c000-"
735+
"000000000000",
731736
"environment": "AzurePublicCloud",
732737
"expires-in": "0",
733738
"expires-on": "-1",
@@ -1439,7 +1444,8 @@ def test_list_kube_config_contexts(self):
14391444
{'context': {'cluster': 'ssl', 'user': 'ssl'}, 'name': 'ssl'},
14401445
{'context': {'cluster': 'default', 'user': 'simple_token'},
14411446
'name': 'simple_token'},
1442-
{'context': {'cluster': 'default', 'user': 'expired_oidc'}, 'name': 'expired_oidc'}]
1447+
{'context': {'cluster': 'default', 'user': 'expired_oidc'},
1448+
'name': 'expired_oidc'}]
14431449

14441450
contexts, active_context = list_kube_config_contexts(
14451451
config_file=kubeconfigs)

0 commit comments

Comments
 (0)