Skip to content

Commit 558bcdb

Browse files
authored
feat: Pass a valid auth token. (#248)
* feat: Pass a valid auth token. This allows the user to pass a valid auth token to the client to autheticate requests
1 parent 7fae6ff commit 558bcdb

File tree

5 files changed

+208
-5
lines changed

5 files changed

+208
-5
lines changed

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,21 @@ const openshiftRestClient = require('openshift-rest-client').OpenshiftClient;
188188
})();
189189
```
190190

191+
It is also possible to send in a valid auth token instead of a username/password. If we use the above example, the settings object might look something like this:
192+
193+
```
194+
const settings = {
195+
};
196+
197+
settings.config = {
198+
url: process.env.CLUSTER_URL,
199+
auth: {
200+
token: process.env.TOKEN
201+
},
202+
insecureSkipTlsVerify: true
203+
};
204+
```
205+
191206
To see more examples of how to customize your config, check out the [kubernetes-client Initializing section](https://www.npmjs.com/package/kubernetes-client#initializing)
192207

193208
#### Load API from a Remote Cluster

lib/basic-auth-request.js

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,31 @@ const buildError = (requestError) => {
99
return err;
1010
};
1111

12+
// Use this function if a user passes in just an auth token
13+
// This will return a User Openshift Object
14+
async function getUserFromAuthToken (settings) {
15+
return new Promise((resolve, reject) => {
16+
const req = {
17+
method: 'GET',
18+
url: `${settings.url}/apis/user.openshift.io/v1/users/~`,
19+
auth: {
20+
bearer: settings.token
21+
},
22+
strictSSL: 'insecureSkipTlsVerify' in settings ? !settings.insecureSkipTlsVerify : true
23+
};
24+
25+
request(req, (err, resp, body) => {
26+
if (err) return reject(buildError(err));
27+
28+
if (resp.statusCode === 401) {
29+
return reject(new Error(`401 Unable to authenticate with token ${settings.token}`));
30+
}
31+
32+
return resolve(JSON.parse(body));
33+
});
34+
});
35+
}
36+
1237
async function getTokenFromBasicAuth (settings) {
1338
// Get the Auth URL from Openshift endpoint
1439
const authUrl = await getAuthUrlFromOCP(settings.url, 'insecureSkipTlsVerify' in settings ? !settings.insecureSkipTlsVerify : true);
@@ -46,5 +71,6 @@ async function getTokenFromBasicAuth (settings) {
4671
}
4772

4873
module.exports = {
49-
getTokenFromBasicAuth
74+
getTokenFromBasicAuth,
75+
getUserFromAuthToken
5076
};

lib/openshift-rest-client.js

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ const fs = require('fs');
2323
const path = require('path');
2424

2525
const { Client, alias, KubeConfig } = require('kubernetes-client');
26-
const { getTokenFromBasicAuth } = require('./basic-auth-request');
26+
const { getTokenFromBasicAuth, getUserFromAuthToken } = require('./basic-auth-request');
2727
const Request = require('kubernetes-client/backends/request');
2828

2929
const serviceCatalogCRD = require('./specs/service-catalog-crd.json');
@@ -65,6 +65,7 @@ const spec = JSON.parse(zlib.gunzipSync(fs.readFileSync(path.join(__dirname, 'sp
6565
* @param {object|string} [settings.config] - custom config object(KubeConfig or object). String value will assume a config file location.
6666
* @param {string} [settings.config.url] - Openshift cluster url
6767
* @param {object} [settings.config.auth] -
68+
* @param {string} [settings.config.auth.token] - auth token used to authenticate to the Openshift Cluster
6869
* @param {string} [settings.config.auth.username] - username to authenticate to Openshift
6970
* @param {string} [settings.config.auth.password] - password to authenticate to Openshift
7071
* @param {boolean} [settings.config.insecureSkipTlsVerify] - flag to ignore TLS verification
@@ -92,15 +93,23 @@ async function openshiftClient (settings = {}) {
9293
clientConfig.backend = new Request({ kubeconfig });
9394
} else if (typeof config === 'object' && config.auth) {
9495
// Check for the auth username password
95-
if ('user' in config.auth || 'username' in config.auth) {
96+
if ('user' in config.auth || 'username' in config.auth || 'token' in config.auth) {
9697
// They are trying the basic auth.
9798
// Get the access token using the username and password
9899
// Check to see if we are passing in a username/password
99100
const { insecureSkipTlsVerify, url, authUrl } = config;
100-
const user = config.auth.username || config.auth.user;
101+
let user = config.auth.username || config.auth.user;
101102
const password = config.auth.password || config.auth.pass;
102103

103-
const accessToken = await getTokenFromBasicAuth({ insecureSkipTlsVerify, url, user, password, authUrl });
104+
let accessToken;
105+
106+
if (config.auth.token) {
107+
const openshiftUser = await getUserFromAuthToken({ insecureSkipTlsVerify, url, token: config.auth.token });
108+
accessToken = config.auth.token;
109+
user = openshiftUser.metadata.name;
110+
} else {
111+
accessToken = await getTokenFromBasicAuth({ insecureSkipTlsVerify, url, user, password, authUrl });
112+
}
104113
const clusterUrl = url;
105114
// Create clusterName from clusterUrl by removing 'https://'
106115
const clusterName = clusterUrl.replace(/(^\w+:|^)\/\//, '');

test/basic-auth-request-test.js

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,3 +147,90 @@ test('basic auth request with request error', (t) => {
147147
t.end();
148148
});
149149
});
150+
151+
// Getting the User from a Token Tests
152+
153+
test('get user from token', (t) => {
154+
const basicAuthRequest = proxyquire('../lib/basic-auth-request', {
155+
request: (requestObject, cb) => {
156+
t.equal(requestObject.strictSSL, false, 'should be false');
157+
return cb(null, {
158+
statusCode: 200
159+
},
160+
JSON.stringify({
161+
kind: 'User',
162+
metadata: {
163+
name: 'developer'
164+
}
165+
})
166+
);
167+
}
168+
});
169+
170+
const settings = {
171+
url: 'http://',
172+
token: '12346',
173+
insecureSkipTlsVerify: true
174+
};
175+
176+
const p = basicAuthRequest.getUserFromAuthToken(settings);
177+
178+
t.equal(p instanceof Promise, true, 'is an Promise');
179+
180+
p.then((userObject) => {
181+
t.equal(userObject.metadata.name, 'developer', 'user should be equal');
182+
t.end();
183+
});
184+
});
185+
186+
test('get user from token with 401 status code', (t) => {
187+
const basicAuthRequest = proxyquire('../lib/basic-auth-request', {
188+
request: (requestObject, cb) => {
189+
t.equal(requestObject.strictSSL, false, 'should be false');
190+
return cb(null, {
191+
statusCode: 401,
192+
request: {
193+
uri: {
194+
host: 'https://'
195+
}
196+
}
197+
});
198+
}
199+
});
200+
201+
const settings = {
202+
url: 'http://',
203+
token: '12346',
204+
insecureSkipTlsVerify: true
205+
};
206+
207+
const p = basicAuthRequest.getUserFromAuthToken(settings);
208+
209+
t.equal(p instanceof Promise, true, 'is an Promise');
210+
211+
p.catch((error) => {
212+
t.equal(error.message,
213+
'401 Unable to authenticate with token 12346',
214+
'should be equal');
215+
t.end();
216+
});
217+
});
218+
219+
test('get user from token with request error', (t) => {
220+
const basicAuthRequest = proxyquire('../lib/basic-auth-request', {
221+
request: (requestObject, cb) => {
222+
return cb({ message: 'Error' }, {});
223+
}
224+
});
225+
226+
const settings = {};
227+
228+
const p = basicAuthRequest.getUserFromAuthToken(settings);
229+
230+
t.equal(p instanceof Promise, true, 'is an Promise');
231+
232+
p.catch((error) => {
233+
t.equal(error.message, 'Error', 'should be equal');
234+
t.end();
235+
});
236+
});

test/openshift-client-test.js

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,72 @@ test('test basic auth - username/password', async (t) => {
9090
t.end();
9191
});
9292

93+
test('test basic auth - token', async (t) => {
94+
const settings = {
95+
config: {
96+
url: 'http://test-url',
97+
auth: {
98+
token: '12345'
99+
}
100+
}
101+
};
102+
103+
const openshiftRestClient = proxyquire('../lib/openshift-rest-client', {
104+
'./basic-auth-request': {
105+
getTokenFromBasicAuth: () => {
106+
t.fail('should not reach this');
107+
},
108+
getUserFromAuthToken: () => {
109+
t.pass('should reach here');
110+
return Promise.resolve({
111+
kind: 'User',
112+
metadata: {
113+
user: 'developer'
114+
}
115+
});
116+
}
117+
}
118+
});
119+
120+
await openshiftRestClient(settings);
121+
t.pass();
122+
t.end();
123+
});
124+
125+
test('test basic auth - token, user and password', async (t) => {
126+
const settings = {
127+
config: {
128+
url: 'http://test-url',
129+
auth: {
130+
username: 'developer',
131+
password: 'developer',
132+
token: '12345'
133+
}
134+
}
135+
};
136+
137+
const openshiftRestClient = proxyquire('../lib/openshift-rest-client', {
138+
'./basic-auth-request': {
139+
getTokenFromBasicAuth: () => {
140+
t.fail('should not reach this');
141+
},
142+
getUserFromAuthToken: () => {
143+
t.pass('should reach here');
144+
return Promise.resolve({
145+
kind: 'User',
146+
metadata: {
147+
user: 'developer'
148+
}
149+
});
150+
}
151+
}
152+
});
153+
154+
await openshiftRestClient(settings);
155+
t.pass();
156+
t.end();
157+
});
158+
93159
test('test basic auth - user/pass', async (t) => {
94160
const settings = {
95161
config: {

0 commit comments

Comments
 (0)