Skip to content

Commit c0d0a6c

Browse files
committed
split cloud_auth into gcp and azure
1 parent 6b713dc commit c0d0a6c

File tree

3 files changed

+102
-4
lines changed

3 files changed

+102
-4
lines changed

src/cloud_auth.ts renamed to src/azure_auth.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ interface Config {
1818
['expiry-key']: string;
1919
['access-token']?: string;
2020
}
21-
export class CloudAuth implements Authenticator {
21+
export class AzureAuth implements Authenticator {
2222
public isAuthProvider(user: User): boolean {
2323
if (!user || !user.authProvider) {
2424
return false;
2525
}
26-
return user.authProvider.name === 'azure' || user.authProvider.name === 'gcp';
26+
return user.authProvider.name === 'azure';
2727
}
2828

2929
public async applyAuthentication(

src/config.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import shelljs = require('shelljs');
1010

1111
import * as api from './api';
1212
import { Authenticator } from './auth';
13-
import { CloudAuth } from './cloud_auth';
13+
import { AzureAuth } from './azure_auth';
1414
import {
1515
Cluster,
1616
ConfigOptions,
@@ -25,6 +25,7 @@ import {
2525
} from './config_types';
2626
import { ExecAuth } from './exec_auth';
2727
import { FileAuth } from './file_auth';
28+
import { GoogleCloudPlatformAuth } from './gcp_auth';
2829
import { OpenIDConnectAuth } from './oidc_auth';
2930

3031
// fs.existsSync was removed in node 10
@@ -39,7 +40,8 @@ function fileExists(filepath: string): boolean {
3940

4041
export class KubeConfig {
4142
private static authenticators: Authenticator[] = [
42-
new CloudAuth(),
43+
new AzureAuth(),
44+
new GoogleCloudPlatformAuth(),
4345
new ExecAuth(),
4446
new FileAuth(),
4547
new OpenIDConnectAuth(),

src/gcp_auth.ts

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import * as proc from 'child_process';
2+
import https = require('https');
3+
import * as jsonpath from 'jsonpath-plus';
4+
import request = require('request');
5+
6+
import { Authenticator } from './auth';
7+
import { User } from './config_types';
8+
9+
/* FIXME: maybe we can extend the User and User.authProvider type to have a proper type.
10+
Currently user.authProvider has `any` type and so we don't have a type for user.authProvider.config.
11+
We therefore define its type here
12+
*/
13+
interface Config {
14+
expiry: string;
15+
['cmd-args']?: string;
16+
['cmd-path']?: string;
17+
['token-key']: string;
18+
['expiry-key']: string;
19+
['access-token']?: string;
20+
}
21+
export class GoogleCloudPlatformAuth implements Authenticator {
22+
public isAuthProvider(user: User): boolean {
23+
if (!user || !user.authProvider) {
24+
return false;
25+
}
26+
return user.authProvider.name === 'gcp';
27+
}
28+
29+
public async applyAuthentication(
30+
user: User,
31+
opts: request.Options | https.RequestOptions,
32+
): Promise<void> {
33+
const token = this.getToken(user);
34+
if (token) {
35+
opts.headers!.Authorization = `Bearer ${token}`;
36+
}
37+
}
38+
39+
private getToken(user: User): string | null {
40+
const config = user.authProvider.config;
41+
if (this.isExpired(config)) {
42+
this.updateAccessToken(config);
43+
}
44+
return config['access-token'];
45+
}
46+
47+
private isExpired(config: Config): boolean {
48+
const token = config['access-token'];
49+
const expiry = config.expiry;
50+
if (!token) {
51+
return true;
52+
}
53+
if (!expiry) {
54+
return false;
55+
}
56+
57+
const expiration = Date.parse(expiry);
58+
if (expiration < Date.now()) {
59+
return true;
60+
}
61+
return false;
62+
}
63+
64+
private updateAccessToken(config: Config): void {
65+
let cmd = config['cmd-path'];
66+
if (!cmd) {
67+
throw new Error('Token is expired!');
68+
}
69+
// Wrap cmd in quotes to make it cope with spaces in path
70+
cmd = `"${cmd}"`;
71+
const args = config['cmd-args'];
72+
if (args) {
73+
cmd = cmd + ' ' + args;
74+
}
75+
// TODO: Cache to file?
76+
// TODO: do this asynchronously
77+
let output: any;
78+
try {
79+
output = proc.execSync(cmd);
80+
} catch (err) {
81+
throw new Error('Failed to refresh token: ' + err.message);
82+
}
83+
84+
const resultObj = JSON.parse(output);
85+
86+
const tokenPathKeyInConfig = config['token-key'];
87+
const expiryPathKeyInConfig = config['expiry-key'];
88+
89+
// Format in file is {<query>}, so slice it out and add '$'
90+
const tokenPathKey = '$' + tokenPathKeyInConfig.slice(1, -1);
91+
const expiryPathKey = '$' + expiryPathKeyInConfig.slice(1, -1);
92+
93+
config['access-token'] = jsonpath.JSONPath(tokenPathKey, resultObj);
94+
config.expiry = jsonpath.JSONPath(expiryPathKey, resultObj);
95+
}
96+
}

0 commit comments

Comments
 (0)