Skip to content

Commit 1adb9a7

Browse files
authored
Merge pull request #702 from mansona/gcp-auth-file
split cloud_auth into gcp and azure
2 parents 6b713dc + 1eddbe5 commit 1adb9a7

File tree

6 files changed

+683
-260
lines changed

6 files changed

+683
-260
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/azure_auth_test.ts

Lines changed: 288 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,288 @@
1+
import { expect } from 'chai';
2+
import * as requestlib from 'request';
3+
import { join } from 'path';
4+
5+
import { User, Cluster } from './config_types';
6+
import { AzureAuth } from './azure_auth';
7+
import { KubeConfig } from './config';
8+
9+
describe('AzureAuth', () => {
10+
var auth: AzureAuth;
11+
beforeEach(() => {
12+
auth = new AzureAuth();
13+
});
14+
15+
it('should be true for azure user', () => {
16+
const user = {
17+
authProvider: {
18+
name: 'azure',
19+
},
20+
} as User;
21+
22+
expect(auth.isAuthProvider(user)).to.equal(true);
23+
});
24+
25+
it('should be false for other user', () => {
26+
const user = {
27+
authProvider: {
28+
name: 'gcp',
29+
},
30+
} as User;
31+
32+
expect(auth.isAuthProvider(user)).to.equal(false);
33+
});
34+
35+
it('should be false for null user.authProvider', () => {
36+
const user = {} as User;
37+
38+
expect(auth.isAuthProvider(user)).to.equal(false);
39+
});
40+
41+
it('should populate from auth provider', async () => {
42+
const config = new KubeConfig();
43+
const token = 'token';
44+
config.loadFromClusterAndUser(
45+
{ skipTLSVerify: false } as Cluster,
46+
{
47+
authProvider: {
48+
name: 'azure',
49+
config: {
50+
'access-token': token,
51+
expiry: 'Fri Aug 24 07:32:05 PDT 3018',
52+
},
53+
},
54+
} as User,
55+
);
56+
const opts = {} as requestlib.Options;
57+
58+
await config.applyToRequest(opts);
59+
expect(opts.headers).to.not.be.undefined;
60+
if (opts.headers) {
61+
expect(opts.headers.Authorization).to.equal(`Bearer ${token}`);
62+
}
63+
opts.headers = [];
64+
opts.headers.Host = 'foo.com';
65+
await config.applyToRequest(opts);
66+
expect(opts.headers.Authorization).to.equal(`Bearer ${token}`);
67+
});
68+
69+
it('should populate from auth provider without expirty', async () => {
70+
const config = new KubeConfig();
71+
const token = 'token';
72+
config.loadFromClusterAndUser(
73+
{ skipTLSVerify: false } as Cluster,
74+
{
75+
authProvider: {
76+
name: 'azure',
77+
config: {
78+
'access-token': token,
79+
},
80+
},
81+
} as User,
82+
);
83+
const opts = {} as requestlib.Options;
84+
85+
await config.applyToRequest(opts);
86+
expect(opts.headers).to.not.be.undefined;
87+
if (opts.headers) {
88+
expect(opts.headers.Authorization).to.equal(`Bearer ${token}`);
89+
}
90+
});
91+
92+
it('should populate rejectUnauthorized=false when skipTLSVerify is set', async () => {
93+
const config = new KubeConfig();
94+
const token = 'token';
95+
config.loadFromClusterAndUser(
96+
{ skipTLSVerify: true } as Cluster,
97+
{
98+
authProvider: {
99+
name: 'azure',
100+
config: {
101+
'access-token': token,
102+
},
103+
},
104+
} as User,
105+
);
106+
const opts = {} as requestlib.Options;
107+
108+
await config.applyToRequest(opts);
109+
expect(opts.rejectUnauthorized).to.equal(false);
110+
});
111+
112+
it('should not set rejectUnauthorized if skipTLSVerify is not set', async () => {
113+
// This test is just making 100% sure we validate certs unless we explictly set
114+
// skipTLSVerify = true
115+
const config = new KubeConfig();
116+
const token = 'token';
117+
config.loadFromClusterAndUser(
118+
{} as Cluster,
119+
{
120+
authProvider: {
121+
name: 'azure',
122+
config: {
123+
'access-token': token,
124+
},
125+
},
126+
} as User,
127+
);
128+
const opts = {} as requestlib.Options;
129+
130+
await config.applyToRequest(opts);
131+
expect(opts.rejectUnauthorized).to.equal(undefined);
132+
});
133+
134+
it('should throw with expired token and no cmd', () => {
135+
const config = new KubeConfig();
136+
config.loadFromClusterAndUser(
137+
{ skipTLSVerify: false } as Cluster,
138+
{
139+
authProvider: {
140+
name: 'azure',
141+
config: {
142+
expiry: 'Aug 24 07:32:05 PDT 2017',
143+
},
144+
},
145+
} as User,
146+
);
147+
const opts = {} as requestlib.Options;
148+
149+
return expect(config.applyToRequest(opts)).to.eventually.be.rejectedWith('Token is expired!');
150+
});
151+
152+
it('should throw with bad command', () => {
153+
const config = new KubeConfig();
154+
config.loadFromClusterAndUser(
155+
{ skipTLSVerify: false } as Cluster,
156+
{
157+
authProvider: {
158+
name: 'azure',
159+
config: {
160+
'access-token': 'token',
161+
expiry: 'Aug 24 07:32:05 PDT 2017',
162+
'cmd-path': 'non-existent-command',
163+
},
164+
},
165+
} as User,
166+
);
167+
const opts = {} as requestlib.Options;
168+
return expect(config.applyToRequest(opts)).to.eventually.be.rejectedWith(/Failed to refresh token/);
169+
});
170+
171+
it('should exec with expired token', async () => {
172+
// TODO: fix this test for Windows
173+
if (process.platform === 'win32') {
174+
return;
175+
}
176+
const config = new KubeConfig();
177+
const token = 'token';
178+
const responseStr = `{"token":{"accessToken":"${token}"}}`;
179+
config.loadFromClusterAndUser(
180+
{ skipTLSVerify: false } as Cluster,
181+
{
182+
authProvider: {
183+
name: 'azure',
184+
config: {
185+
expiry: 'Aug 24 07:32:05 PDT 2017',
186+
'cmd-path': 'echo',
187+
'cmd-args': `'${responseStr}'`,
188+
'token-key': '{.token.accessToken}',
189+
'expiry-key': '{.token.token_expiry}',
190+
},
191+
},
192+
} as User,
193+
);
194+
const opts = {} as requestlib.Options;
195+
await config.applyToRequest(opts);
196+
expect(opts.headers).to.not.be.undefined;
197+
if (opts.headers) {
198+
expect(opts.headers.Authorization).to.equal(`Bearer ${token}`);
199+
}
200+
});
201+
it('should exec without access-token', async () => {
202+
// TODO: fix this test for Windows
203+
if (process.platform === 'win32') {
204+
return;
205+
}
206+
const config = new KubeConfig();
207+
const token = 'token';
208+
const responseStr = `{"token":{"accessToken":"${token}"}}`;
209+
config.loadFromClusterAndUser(
210+
{ skipTLSVerify: false } as Cluster,
211+
{
212+
authProvider: {
213+
name: 'azure',
214+
config: {
215+
'cmd-path': 'echo',
216+
'cmd-args': `'${responseStr}'`,
217+
'token-key': '{.token.accessToken}',
218+
'expiry-key': '{.token.token_expiry}',
219+
},
220+
},
221+
} as User,
222+
);
223+
const opts = {} as requestlib.Options;
224+
await config.applyToRequest(opts);
225+
expect(opts.headers).to.not.be.undefined;
226+
if (opts.headers) {
227+
expect(opts.headers.Authorization).to.equal(`Bearer ${token}`);
228+
}
229+
});
230+
it('should exec without access-token', async () => {
231+
// TODO: fix this test for Windows
232+
if (process.platform === 'win32') {
233+
return;
234+
}
235+
const config = new KubeConfig();
236+
const token = 'token';
237+
const responseStr = `{"token":{"accessToken":"${token}"}}`;
238+
config.loadFromClusterAndUser(
239+
{ skipTLSVerify: false } as Cluster,
240+
{
241+
authProvider: {
242+
name: 'azure',
243+
config: {
244+
'cmd-path': 'echo',
245+
'cmd-args': `'${responseStr}'`,
246+
'token-key': '{.token.accessToken}',
247+
'expiry-key': '{.token.token_expiry}',
248+
},
249+
},
250+
} as User,
251+
);
252+
const opts = {} as requestlib.Options;
253+
await config.applyToRequest(opts);
254+
expect(opts.headers).to.not.be.undefined;
255+
if (opts.headers) {
256+
expect(opts.headers.Authorization).to.equal(`Bearer ${token}`);
257+
}
258+
});
259+
it('should exec succesfully with spaces in cmd', async () => {
260+
// TODO: fix this test for Windows
261+
if (process.platform === 'win32') {
262+
return;
263+
}
264+
const config = new KubeConfig();
265+
const token = 'token';
266+
const responseStr = `{"token":{"accessToken":"${token}"}}`;
267+
config.loadFromClusterAndUser(
268+
{ skipTLSVerify: false } as Cluster,
269+
{
270+
authProvider: {
271+
name: 'azure',
272+
config: {
273+
'cmd-path': join(__dirname, '..', 'test', 'echo space.js'),
274+
'cmd-args': `'${responseStr}'`,
275+
'token-key': '{.token.accessToken}',
276+
'expiry-key': '{.token.token_expiry}',
277+
},
278+
},
279+
} as User,
280+
);
281+
const opts = {} as requestlib.Options;
282+
await config.applyToRequest(opts);
283+
expect(opts.headers).to.not.be.undefined;
284+
if (opts.headers) {
285+
expect(opts.headers.Authorization).to.equal(`Bearer ${token}`);
286+
}
287+
});
288+
});

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(),

0 commit comments

Comments
 (0)