Skip to content

Fix websocket tls options #41

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 28, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 45 additions & 11 deletions node-client/src/config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import fs = require('fs');
import os = require('os');
import path = require('path');
import https = require('https');

import base64 = require('base-64');
import jsonpath = require('jsonpath');
Expand Down Expand Up @@ -80,15 +81,15 @@ export class KubeConfig {
return this.getCluster(this.getCurrentContextObject()['cluster']);
}

public getCluster(name: string) {
public getCluster(name: string): Cluster {
return KubeConfig.findObject(this.clusters, name, 'cluster');
}

public getCurrentUser() {
return this.getUser(this.getCurrentContextObject()['user']);
}

public getUser(name: string) {
public getUser(name: string): User {
return KubeConfig.findObject(this.users, name, 'user');
}

Expand All @@ -106,22 +107,25 @@ export class KubeConfig {
return null;
}

public applyToRequest(opts: request.Options) {
let cluster = this.getCurrentCluster();
let user = this.getCurrentUser();
private applyHTTPSOptions(opts: request.Options | https.RequestOptions) {
const cluster = this.getCurrentCluster();
const user = this.getCurrentUser();

if (cluster.skipTLSVerify) {
opts.strictSSL = false
}
opts.ca = this.bufferFromFileOrString(cluster.caFile, cluster.caData);
opts.cert = this.bufferFromFileOrString(user.certFile, user.certData);
opts.key = this.bufferFromFileOrString(user.keyFile, user.keyData);
}

private applyAuthorizationHeader(opts: request.Options | https.RequestOptions) {
const user = this.getCurrentUser();
let token = null;

if (user.authProvider && user.authProvider.config) {
let config = user.authProvider.config;
const config = user.authProvider.config;
// This should probably be extracted as auth-provider specific plugins...
token = 'Bearer ' + config['access-token'];
let expiry = config['expiry'];
const expiry = config['expiry'];

if (expiry) {
let expiration = Date.parse(expiry);
if (expiration < Date.now()) {
Expand All @@ -131,7 +135,7 @@ export class KubeConfig {
cmd = cmd + ' ' + config['cmd-args'];
}
// TODO: Cache to file?
let result = shelljs.exec(cmd, { silent: true });
const result = shelljs.exec(cmd, { silent: true });
if (result['code'] != 0) {
throw new Error('Failed to refresh token: ' + result);
}
Expand All @@ -148,13 +152,43 @@ export class KubeConfig {
}
}
}

}

if (user.token) {
token = 'Bearer ' + user.token;
}

if (token) {
opts.headers['Authorization'] = token;
}
}

private applyOptions(opts: request.Options | https.RequestOptions) {
this.applyHTTPSOptions(opts);
this.applyAuthorizationHeader(opts);
}

public applytoHTTPSOptions(opts: https.RequestOptions) {
const user = this.getCurrentUser();

this.applyOptions(opts);

if (user.username) {
opts.auth = `${user.username}:${user.password}`;
}
}

public applyToRequest(opts: request.Options) {
const cluster = this.getCurrentCluster();
const user = this.getCurrentUser();

this.applyOptions(opts);

if (cluster.skipTLSVerify) {
opts.strictSSL = false
}

if (user.username) {
opts.auth = {
username: user.username,
Expand Down
36 changes: 28 additions & 8 deletions node-client/src/config_test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { KubeConfig, Config } from './config';
import { expect } from 'chai';
import 'mocha';

import { expect } from 'chai';
import * as https from 'https';
import * as base64 from 'base-64';

import { KubeConfig, Config } from './config';

const kcFileName = "testdata/kubeconfig.yaml";

describe("Config", () => {
Expand Down Expand Up @@ -51,22 +55,22 @@ describe("KubeConfig", () => {
let cluster1 = kc.clusters[0];
let cluster2 = kc.clusters[1];
expect(cluster1.name).to.equal("cluster1");
expect(cluster1.caData).to.equal("CADATA");
expect(cluster1.caData).to.equal("Q0FEQVRB");
expect(cluster1.server).to.equal("http://example.com");
expect(cluster2.name).to.equal("cluster2");
expect(cluster2.caData).to.equal("CADATA2");
expect(cluster2.caData).to.equal("Q0FEQVRBMg==");
expect(cluster2.server).to.equal("http://example2.com");

// check users
expect(kc.users.length).to.equal(2);
let user1 = kc.users[0];
let user2 = kc.users[1];
expect(user1.name).to.equal("user1");
expect(user1.certData).to.equal("USER_CADATA");
expect(user1.keyData).to.equal("USER_CKDATA");
expect(user1.certData).to.equal("VVNFUl9DQURBVEE=");
expect(user1.keyData).to.equal("VVNFUl9DS0RBVEE=");
expect(user2.name).to.equal("user2");
expect(user2.certData).to.equal("USER2_CADATA");
expect(user2.keyData).to.equal("USER2_CKDATA");
expect(user2.certData).to.equal("VVNFUjJfQ0FEQVRB");
expect(user2.keyData).to.equal("VVNFUjJfQ0tEQVRB");

// check contexts
expect(kc.contexts.length).to.equal(2);
Expand All @@ -87,4 +91,20 @@ describe("KubeConfig", () => {
// expect(kc.loadFromFile("missing.yaml")).to.throw();
});
});

describe("applyHTTPSOptions", () => {
it("should apply cert configs", () => {
const kc = new KubeConfig();
kc.loadFromFile(kcFileName);

const opts: https.RequestOptions = {};
kc.applytoHTTPSOptions(opts);

expect(opts).to.deep.equal({
ca: new Buffer('CADATA2', 'utf-8'),
cert: new Buffer('USER2_CADATA', 'utf-8'),
key: new Buffer('USER2_CKDATA', 'utf-8'),
});
});
});
});
2 changes: 1 addition & 1 deletion node-client/src/config_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export interface User {
readonly certFile: string
readonly keyData: string
readonly keyFile: string
readonly authProvider: Object
readonly authProvider: any
readonly token: string
readonly username: string
readonly password: string
Expand Down
6 changes: 5 additions & 1 deletion node-client/src/web-socket-handler.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import stream = require('stream');
import https = require('https');

import ws = require('websocket');
import { KubeConfig } from './config';
Expand Down Expand Up @@ -32,7 +33,10 @@ export class WebSocketHandler {
const target = server.startsWith('https://') ? server.substr(8) : server.substr(7);
const uri = `wss://${target}${path}`;

const client = new ws.client();
const opts : https.RequestOptions = {};
this.config.applytoHTTPsOptions(opts)

const client = new ws.client({ tlsOptions: opts } );

return new Promise((resolve, reject) => {
client.on('connect', (connection) => {
Expand Down
16 changes: 8 additions & 8 deletions node-client/testdata/kubeconfig.yaml
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: CADATA
certificate-authority-data: Q0FEQVRB
server: http://example.com
name: cluster1
- cluster:
certificate-authority-data: CADATA2
certificate-authority-data: Q0FEQVRBMg==
server: http://example2.com
name: cluster2

contexts:
- context:
cluster: cluster1
user: user1
user: user1
name: context1
- context:
cluster: cluster2
Expand All @@ -23,11 +23,11 @@ current-context: context2
kind: Config
preferences: {}
users:
- name: user1
- name: user1
user:
client-certificate-data: USER_CADATA
client-key-data: USER_CKDATA
client-certificate-data: VVNFUl9DQURBVEE=
client-key-data: VVNFUl9DS0RBVEE=
- name: user2
user:
client-certificate-data: USER2_CADATA
client-key-data: USER2_CKDATA
client-certificate-data: VVNFUjJfQ0FEQVRB
client-key-data: VVNFUjJfQ0tEQVRB