Skip to content

Commit 34822f1

Browse files
committed
fix: access-token does not get refreshed if not present
1 parent d7d3dad commit 34822f1

File tree

2 files changed

+83
-39
lines changed

2 files changed

+83
-39
lines changed

src/cloud_auth.ts

Lines changed: 56 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -7,51 +7,69 @@ import { User } from './config_types';
77

88
export class CloudAuth implements Authenticator {
99
public isAuthProvider(user: User): boolean {
10-
return user.authProvider.name === 'azure' ||
11-
user.authProvider.name === 'gcp';
10+
return (
11+
user.authProvider.name === 'azure' ||
12+
user.authProvider.name === 'gcp'
13+
);
1214
}
1315

1416
public getToken(user: User): string | null {
1517
const config = user.authProvider.config;
16-
// This should probably be extracted as auth-provider specific plugins...
17-
let token: string = 'Bearer ' + config['access-token'];
18+
if (this.isExpired(config)) {
19+
this.updateAccessToken(config);
20+
}
21+
return 'Bearer ' + config['access-token'];
22+
}
23+
24+
private isExpired(config) {
25+
const token = config['access-token']
1826
const expiry = config.expiry;
27+
if (!token) {
28+
return true;
29+
}
30+
if(!expiry) {
31+
return false
32+
}
33+
34+
const expiration = Date.parse(expiry);
35+
if (expiration < Date.now()) {
36+
return true;
37+
}
38+
return false;
39+
}
1940

20-
if (expiry) {
21-
const expiration = Date.parse(expiry);
22-
if (expiration < Date.now()) {
23-
if (config['cmd-path']) {
24-
const args = config['cmd-args'];
25-
// TODO: Cache to file?
26-
// TODO: do this asynchronously
27-
let result: any;
28-
try {
29-
let cmd = config['cmd-path'];
30-
if (args) {
31-
cmd = `${cmd} ${args}`;
32-
}
33-
result = shelljs.exec(cmd);
34-
if (result.code !== 0) {
35-
throw new Error(result.stderr);
36-
}
37-
} catch (err) {
38-
throw new Error('Failed to refresh token: ' + err.message);
39-
}
40-
41-
const output = result.stdout.toString();
42-
const resultObj = JSON.parse(output);
43-
44-
let pathKey = config['token-key'];
45-
// Format in file is {<query>}, so slice it out and add '$'
46-
pathKey = '$' + pathKey.slice(1, -1);
47-
48-
config['access-token'] = jsonpath.query(resultObj, pathKey);
49-
token = 'Bearer ' + config['access-token'];
50-
} else {
51-
throw new Error('Token is expired!');
52-
}
41+
private updateAccessToken(config) {
42+
if (!config['cmd-path']) {
43+
throw new Error('Token is expired!');
44+
}
45+
const args = config['cmd-args'];
46+
// TODO: Cache to file?
47+
// TODO: do this asynchronously
48+
let result: any;
49+
try {
50+
let cmd = config['cmd-path'];
51+
if (args) {
52+
cmd = `${cmd} ${args}`;
5353
}
54+
result = shelljs.exec(cmd);
55+
if (result.code !== 0) {
56+
throw new Error(result.stderr);
57+
}
58+
} catch (err) {
59+
throw new Error('Failed to refresh token: ' + err.message);
5460
}
55-
return token;
61+
62+
const output = result.stdout.toString();
63+
const resultObj = JSON.parse(output);
64+
65+
let tokenPathKey = config['token-key'];
66+
67+
let expiryPathKey = config['token-key'];
68+
// Format in file is {<query>}, so slice it out and add '$'
69+
tokenPathKey = '$' + tokenPathKey.slice(1, -1);
70+
expiryPathKey = '$' + expiryPathKey.slice(1, -1);
71+
72+
config['access-token'] = jsonpath.query(resultObj, tokenPathKey);
73+
config['expiry'] = jsonpath.query(resultObj, expiryPathKey);
5674
}
5775
}

src/config_test.ts

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,7 @@ describe('KubeConfig', () => {
542542
config.applyToRequest(opts);
543543
expect(opts.headers.Authorization).to.equal(`Bearer ${token}`);
544544
});
545+
545546
it('should populate from auth provider without expirty', () => {
546547
const config = new KubeConfig();
547548
const token = 'token';
@@ -589,14 +590,15 @@ describe('KubeConfig', () => {
589590
authProvider: {
590591
name: 'azure',
591592
config: {
593+
'access-token': 'token',
592594
'expiry': 'Aug 24 07:32:05 PDT 2017',
593595
'cmd-path': 'non-existent-command',
594596
},
595597
},
596598
} as User);
597599
const opts = {} as requestlib.Options;
598600
expect(() => config.applyToRequest(opts)).to.throw(
599-
'Failed to refresh token: /bin/sh: 1: non-existent-command: not found');
601+
/Failed to refresh token/);
600602
});
601603

602604
it('should exec with expired token', () => {
@@ -624,6 +626,30 @@ describe('KubeConfig', () => {
624626
}
625627
});
626628

629+
it('should exec without access-token', () => {
630+
const config = new KubeConfig();
631+
const token = 'token';
632+
const responseStr = `{ "token": { "accessToken": "${token}" } }`;
633+
config.loadFromClusterAndUser(
634+
{ skipTLSVerify: false } as Cluster,
635+
{
636+
authProvider: {
637+
name: 'azure',
638+
config: {
639+
'cmd-path': 'echo',
640+
'cmd-args': `'${responseStr}'`,
641+
'token-key': '{.token.accessToken}',
642+
},
643+
},
644+
} as User);
645+
const opts = {} as requestlib.Options;
646+
config.applyToRequest(opts);
647+
expect(opts.headers).to.not.be.undefined;
648+
if (opts.headers) {
649+
expect(opts.headers.Authorization).to.equal(`Bearer ${token}`);
650+
}
651+
});
652+
627653
it('should exec with exec auth', () => {
628654
const config = new KubeConfig();
629655
const token = 'token';

0 commit comments

Comments
 (0)