Skip to content

Commit 03ee970

Browse files
authored
Merge pull request #2091 from krmodelski/proxy-url
Proxy url
2 parents fe1fa2e + f7fe1fe commit 03ee970

9 files changed

+212
-17
lines changed

package-lock.json

+131-6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@
6363
"stream-buffers": "^3.0.2",
6464
"tar": "^7.0.0",
6565
"tslib": "^2.4.1",
66-
"ws": "^8.18.0"
66+
"ws": "^8.18.0",
67+
"socks-proxy-agent": "^8.0.4"
6768
},
6869
"devDependencies": {
6970
"@types/byline": "^4.2.31",

src/config.ts

+9
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import path = require('path');
77

88
import request = require('request');
99
import WebSocket = require('ws');
10+
import SocksProxyAgent = require('socks-proxy-agent');
1011

1112
import * as api from './api';
1213
import { Authenticator } from './auth';
@@ -170,6 +171,14 @@ export class KubeConfig {
170171
if (cluster && cluster.tlsServerName) {
171172
opts.agentOptions = { servername: cluster.tlsServerName } as https.AgentOptions;
172173
}
174+
175+
if (cluster && cluster.proxyUrl) {
176+
if (cluster.proxyUrl.startsWith('socks')) {
177+
opts.agent = new SocksProxyAgent.SocksProxyAgent(cluster.proxyUrl);
178+
} else {
179+
opts.proxy = cluster.proxyUrl;
180+
}
181+
}
173182
}
174183

175184
public loadFromString(config: string, opts?: Partial<ConfigOptions>): void {

src/config_test.ts

+26
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ const kc2FileName = 'testdata/kubeconfig-2.yaml';
1818
const kcDupeCluster = 'testdata/kubeconfig-dupe-cluster.yaml';
1919
const kcDupeContext = 'testdata/kubeconfig-dupe-context.yaml';
2020
const kcDupeUser = 'testdata/kubeconfig-dupe-user.yaml';
21+
const kcProxyUrl = 'testdata/kubeconfig-proxy-url.yaml';
2122

2223
const kcNoUserFileName = 'testdata/empty-user-kubeconfig.yaml';
2324
const kcInvalidContextFileName = 'testdata/empty-context-kubeconfig.yaml';
@@ -36,6 +37,7 @@ function validateFileLoad(kc: KubeConfig) {
3637
expect(cluster1.name).to.equal('cluster1');
3738
expect(cluster1.caData).to.equal('Q0FEQVRB');
3839
expect(cluster1.server).to.equal('http://example.com');
40+
expect(cluster1.proxyUrl).to.equal('socks5://localhost:1181');
3941
expect(cluster2.name).to.equal('cluster2');
4042
expect(cluster2.caData).to.equal('Q0FEQVRBMg==');
4143
expect(cluster2.server).to.equal('http://example2.com');
@@ -403,6 +405,30 @@ describe('KubeConfig', () => {
403405
rejectUnauthorized: false,
404406
});
405407
});
408+
it('should apply proxy to request.Options', async () => {
409+
const kc = new KubeConfig();
410+
kc.loadFromFile(kc2FileName);
411+
412+
const opts = {} as requestlib.Options;
413+
414+
await kc.applyToRequest(opts);
415+
416+
expect(opts).to.deep.equal({
417+
headers: {},
418+
ca: Buffer.from('CADAT@', 'utf-8'),
419+
cert: Buffer.from(']SER_CADATA', 'utf-8'),
420+
key: Buffer.from(']SER_CKDATA', 'utf-8'),
421+
proxy: 'https://localhost:1181',
422+
});
423+
});
424+
it('should apply agent to request.Options', async () => {
425+
const kc = new KubeConfig();
426+
kc.loadFromFile(kcProxyUrl);
427+
428+
const opts = {} as requestlib.Options;
429+
await kc.applyToRequest(opts);
430+
expect(opts.agent).to.exist;
431+
});
406432
});
407433

408434
describe('loadClusterConfigObjects', () => {

src/config_types.ts

+3
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export interface Cluster {
2222
readonly server: string;
2323
readonly skipTLSVerify?: boolean;
2424
readonly tlsServerName?: string;
25+
readonly proxyUrl?: string;
2526
}
2627

2728
export function newClusters(a: any, opts?: Partial<ConfigOptions>): Cluster[] {
@@ -43,6 +44,7 @@ export function exportCluster(cluster: Cluster): any {
4344
'certificate-authority': cluster.caFile,
4445
'insecure-skip-tls-verify': cluster.skipTLSVerify,
4546
'tls-server-name': cluster.tlsServerName,
47+
'proxy-url': cluster.proxyUrl,
4648
},
4749
};
4850
}
@@ -68,6 +70,7 @@ function clusterIterator(
6870
server: elt.cluster.server.replace(/\/$/, ''),
6971
skipTLSVerify: elt.cluster['insecure-skip-tls-verify'] === true,
7072
tlsServerName: elt.cluster['tls-server-name'],
73+
proxyUrl: elt.cluster['proxy-url'],
7174
};
7275
} catch (err) {
7376
switch (onInvalidEntry) {

src/web-socket-handler.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ export class WebSocketHandler implements WebSocketInterface {
126126
if (data instanceof Buffer) {
127127
data.copy(buff, 1);
128128
} else {
129-
buff.write(data, 1);
129+
buff.write(data as string, 1);
130130
}
131131

132132
let i = 0;

testdata/kubeconfig-2.yaml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
apiVersion: v1
22
clusters:
33
- cluster:
4-
certificate-authority-data: Q0FEQVRA
4+
certificate-authority-data: Q0FEQVRA
55
server: http://example2.com
6+
proxy-url: https://localhost:1181
67
name: clusterA
78

89
contexts:
@@ -27,4 +28,3 @@ users:
2728
user:
2829
username: foo
2930
password: bar
30-

testdata/kubeconfig-proxy-url.yaml

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
apiVersion: v1
2+
clusters:
3+
- cluster:
4+
certificate-authority-data: Q0FEQVRA
5+
server: http://example2.com
6+
proxy-url: socks://example:1187
7+
name: clusterA
8+
9+
contexts:
10+
- context:
11+
cluster: clusterA
12+
user: userA
13+
name: contextA
14+
15+
current-context: contextA
16+
kind: Config
17+
preferences: {}
18+
users:
19+
- name: userA
20+
user:
21+
client-certificate-data: XVNFUl9DQURBVEE=
22+
client-key-data: XVNFUl9DS0RBVEE=
23+
- name: userB
24+
user:
25+
client-certificate-data: XVNFUjJfQ0FEQVRB
26+
client-key-data: XVNFUjJfQ0tEQVRB
27+
- name: userC
28+
user:
29+
username: foo
30+
password: bar

0 commit comments

Comments
 (0)