Skip to content

Commit 4e93cbe

Browse files
authored
Merge pull request #168 from brendandburns/exec
Fix Exec implementation, improve tests.
2 parents d90e420 + 24408c6 commit 4e93cbe

File tree

3 files changed

+38
-11
lines changed

3 files changed

+38
-11
lines changed

src/config.ts

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,16 @@ import { CloudAuth } from './cloud_auth';
1313
import { Cluster, Context, newClusters, newContexts, newUsers, User } from './config_types';
1414
import { ExecAuth } from './exec_auth';
1515

16+
// fs.existsSync was removed in node 10
17+
function fileExists(filepath: string): boolean {
18+
try {
19+
fs.accessSync(filepath);
20+
return true;
21+
// tslint:disable-next-line:no-empty
22+
} catch (ignore) { }
23+
return false;
24+
}
25+
1626
export class KubeConfig {
1727
private static authenticators: Authenticator[] = [
1828
new CloudAuth(),
@@ -197,12 +207,10 @@ export class KubeConfig {
197207
const home = findHomeDir();
198208
if (home) {
199209
const config = path.join(home, '.kube', 'config');
200-
try {
201-
fs.accessSync(config);
210+
if (fileExists(config)) {
202211
this.loadFromFile(config);
203212
return;
204-
// tslint:disable-next-line:no-empty
205-
} catch (ignore) {}
213+
}
206214
}
207215
if (process.platform === 'win32' && shelljs.which('wsl.exe')) {
208216
// TODO: Handle if someome set $KUBECONFIG in wsl here...
@@ -213,12 +221,10 @@ export class KubeConfig {
213221
}
214222
}
215223

216-
try {
217-
fs.accessSync(Config.SERVICEACCOUNT_TOKEN_PATH);
224+
if (fileExists(Config.SERVICEACCOUNT_TOKEN_PATH)) {
218225
this.loadFromCluster();
219226
return;
220-
// tslint:disable-next-line:no-empty
221-
} catch (ignore) {}
227+
}
222228

223229
this.loadFromClusterAndUser(
224230
{ name: 'cluster', server: 'http://localhost:8080' } as Cluster,

src/config_test.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -654,7 +654,7 @@ describe('KubeConfig', () => {
654654
it('should exec with exec auth and env vars', () => {
655655
const config = new KubeConfig();
656656
const token = 'token';
657-
const responseStr = `'{ "token": "${token}" }'`;
657+
const responseStr = `'{"status": { "token": "${token}" }}'`;
658658
config.loadFromClusterAndUser(
659659
{ skipTLSVerify: false } as Cluster,
660660
{
@@ -685,7 +685,13 @@ describe('KubeConfig', () => {
685685
it('should exec with exec auth', () => {
686686
const config = new KubeConfig();
687687
const token = 'token';
688-
const responseStr = `'{ "token": "${token}" }'`;
688+
const responseStr = `'{
689+
"apiVersion": "client.authentication.k8s.io/v1beta1",
690+
"kind": "ExecCredential",
691+
"status": {
692+
"token": "${token}"
693+
}
694+
}'`;
689695
config.loadFromClusterAndUser(
690696
{ skipTLSVerify: false } as Cluster,
691697
{

src/exec_auth.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,26 @@ import { Authenticator } from './auth';
44
import { User } from './config_types';
55

66
export class ExecAuth implements Authenticator {
7+
private readonly tokenCache: { [key: string]: any } = {};
8+
79
public isAuthProvider(user: User) {
810
return user.authProvider.name === 'exec' ||
911
(user.authProvider.config && user.authProvider.config.exec);
1012
}
1113

1214
public getToken(user: User): string | null {
15+
// TODO: Handle client cert auth here, requires auth refactor.
16+
// See https://kubernetes.io/docs/reference/access-authn-authz/authentication/#input-and-output-formats
17+
// for details on this protocol.
18+
// TODO: Add a unit test for token caching.
19+
const cachedToken = this.tokenCache[user.name];
20+
if (cachedToken) {
21+
const date = Date.parse(cachedToken.status.expirationTimestamp);
22+
if (date < Date.now()) {
23+
return `Bearer ${cachedToken.status.token}`;
24+
}
25+
this.tokenCache[user.name] = null;
26+
}
1327
const config = user.authProvider.config;
1428
if (!config.exec.command) {
1529
throw new Error('No command was specified for exec authProvider!');
@@ -27,7 +41,8 @@ export class ExecAuth implements Authenticator {
2741
const result = shell.exec(cmd, opts);
2842
if (result.code === 0) {
2943
const obj = JSON.parse(result.stdout);
30-
return `Bearer ${obj.token}`;
44+
this.tokenCache[user.name] = obj;
45+
return `Bearer ${obj.status.token}`;
3146
}
3247
throw new Error(result.stderr);
3348
}

0 commit comments

Comments
 (0)