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

Commit

Permalink
Add option to refresh gcp token when config is cmd-path
Browse files Browse the repository at this point in the history
  • Loading branch information
jfrabaute committed Jan 7, 2020
1 parent a2d1024 commit 1b6fdcf
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 6 deletions.
73 changes: 73 additions & 0 deletions config/kube_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@
import logging
import os
import platform
import subprocess
import tempfile
import time
from collections import namedtuple

import google.auth
import google.auth.transport.requests
Expand Down Expand Up @@ -133,6 +135,46 @@ def as_data(self):
return self._data


class CommandTokenSource(object):
def __init__(self, cmd, args, tokenKey, expiryKey):
self._cmd = cmd
self._args = args
if not tokenKey:
self._tokenKey = '{.access_token}'
else:
self._tokenKey = tokenKey
if not expiryKey:
self._expiryKey = '{.token_expiry}'
else:
self._expiryKey = expiryKey

def token(self):
fullCmd = self._cmd + (" ") + " ".join(self._args)
process = subprocess.Popen(
[self._cmd] + self._args,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True)
(stdout, stderr) = process.communicate()
exit_code = process.wait()
if exit_code != 0:
msg = 'cmd-path: process returned %d' % exit_code
msg += "\nCmd: %s" % fullCmd
stderr = stderr.strip()
if stderr:
msg += '\nStderr: %s' % stderr
raise ConfigException(msg)
try:
data = json.loads(stdout)
except ValueError as de:
raise ConfigException(
'exec: failed to decode process output: %s' % de)
A = namedtuple('A', ['token', 'expiry'])
return A(
token=data['credential']['access_token'],
expiry=parse_rfc3339(data['credential']['token_expiry']))


class KubeConfigLoader(object):

def __init__(self, config_dict, active_context=None,
Expand All @@ -156,7 +198,38 @@ def __init__(self, config_dict, active_context=None,
self._config_base_path = config_base_path
self._config_persister = config_persister

def _refresh_credentials_with_cmd_path():
config = self._user['auth-provider']['config']
cmd = config['cmd-path']
if len(cmd) == 0:
raise ConfigException(
'missing access token cmd '
'(cmd-path is an empty string in your kubeconfig file)')
if 'scopes' in config and config['scopes'] != "":
raise ConfigException(
'scopes can only be used '
'when kubectl is using a gcp service account key')
args = []
if 'cmd-args' in config:
args = config['cmd-args'].split()
else:
fields = config['cmd-path'].split()
cmd = fields[0]
args = fields[1:]

commandTokenSource = CommandTokenSource(
cmd, args,
config.safe_get('token-key'),
config.safe_get('expiry-key'))
return commandTokenSource.token()

def _refresh_credentials():
# Refresh credentials using cmd-path
if ('auth-provider' in self._user and
'config' in self._user['auth-provider'] and
'cmd-path' in self._user['auth-provider']['config']):
return _refresh_credentials_with_cmd_path()

credentials, project_id = google.auth.default(scopes=[
'https://www.googleapis.com/auth/cloud-platform',
'https://www.googleapis.com/auth/userinfo.email'
Expand Down
18 changes: 12 additions & 6 deletions config/kube_config_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -661,7 +661,8 @@ class TestKubeConfigLoader(BaseTestCase):
"auth-provider": {
"config": {
"access-token": TEST_AZURE_TOKEN,
"apiserver-id": "00000002-0000-0000-c000-000000000000",
"apiserver-id": "00000002-0000-0000-c000-"
"000000000000",
"environment": "AzurePublicCloud",
"refresh-token": "refreshToken",
"tenant-id": "9d2ac018-e843-4e14-9e2b-4e0ddac75433"
Expand All @@ -676,7 +677,8 @@ class TestKubeConfigLoader(BaseTestCase):
"auth-provider": {
"config": {
"access-token": TEST_AZURE_TOKEN,
"apiserver-id": "00000002-0000-0000-c000-000000000000",
"apiserver-id": "00000002-0000-0000-c000-"
"000000000000",
"environment": "AzurePublicCloud",
"expires-in": "0",
"expires-on": "156207275",
Expand All @@ -693,7 +695,8 @@ class TestKubeConfigLoader(BaseTestCase):
"auth-provider": {
"config": {
"access-token": TEST_AZURE_TOKEN,
"apiserver-id": "00000002-0000-0000-c000-000000000000",
"apiserver-id": "00000002-0000-0000-c000-"
"000000000000",
"environment": "AzurePublicCloud",
"expires-in": "0",
"expires-on": "2018-10-18 00:52:29.044727",
Expand All @@ -710,7 +713,8 @@ class TestKubeConfigLoader(BaseTestCase):
"auth-provider": {
"config": {
"access-token": TEST_AZURE_TOKEN,
"apiserver-id": "00000002-0000-0000-c000-000000000000",
"apiserver-id": "00000002-0000-0000-c000-"
"000000000000",
"environment": "AzurePublicCloud",
"expires-in": "0",
"expires-on": "2018-10-18 00:52",
Expand All @@ -727,7 +731,8 @@ class TestKubeConfigLoader(BaseTestCase):
"auth-provider": {
"config": {
"access-token": TEST_AZURE_TOKEN,
"apiserver-id": "00000002-0000-0000-c000-000000000000",
"apiserver-id": "00000002-0000-0000-c000-"
"000000000000",
"environment": "AzurePublicCloud",
"expires-in": "0",
"expires-on": "-1",
Expand Down Expand Up @@ -1439,7 +1444,8 @@ def test_list_kube_config_contexts(self):
{'context': {'cluster': 'ssl', 'user': 'ssl'}, 'name': 'ssl'},
{'context': {'cluster': 'default', 'user': 'simple_token'},
'name': 'simple_token'},
{'context': {'cluster': 'default', 'user': 'expired_oidc'}, 'name': 'expired_oidc'}]
{'context': {'cluster': 'default', 'user': 'expired_oidc'},
'name': 'expired_oidc'}]

contexts, active_context = list_kube_config_contexts(
config_file=kubeconfigs)
Expand Down

0 comments on commit 1b6fdcf

Please sign in to comment.