Skip to content

Commit

Permalink
feat: Pass a valid auth token. (#248)
Browse files Browse the repository at this point in the history
* feat:  Pass a valid auth token.

This allows the user to pass a valid auth token to the client to autheticate requests
  • Loading branch information
lholmquist authored Jan 13, 2021
1 parent 7fae6ff commit 558bcdb
Show file tree
Hide file tree
Showing 5 changed files with 208 additions and 5 deletions.
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,21 @@ const openshiftRestClient = require('openshift-rest-client').OpenshiftClient;
})();
```

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:

```
const settings = {
};
settings.config = {
url: process.env.CLUSTER_URL,
auth: {
token: process.env.TOKEN
},
insecureSkipTlsVerify: true
};
```

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)

#### Load API from a Remote Cluster
Expand Down
28 changes: 27 additions & 1 deletion lib/basic-auth-request.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,31 @@ const buildError = (requestError) => {
return err;
};

// Use this function if a user passes in just an auth token
// This will return a User Openshift Object
async function getUserFromAuthToken (settings) {
return new Promise((resolve, reject) => {
const req = {
method: 'GET',
url: `${settings.url}/apis/user.openshift.io/v1/users/~`,
auth: {
bearer: settings.token
},
strictSSL: 'insecureSkipTlsVerify' in settings ? !settings.insecureSkipTlsVerify : true
};

request(req, (err, resp, body) => {
if (err) return reject(buildError(err));

if (resp.statusCode === 401) {
return reject(new Error(`401 Unable to authenticate with token ${settings.token}`));
}

return resolve(JSON.parse(body));
});
});
}

async function getTokenFromBasicAuth (settings) {
// Get the Auth URL from Openshift endpoint
const authUrl = await getAuthUrlFromOCP(settings.url, 'insecureSkipTlsVerify' in settings ? !settings.insecureSkipTlsVerify : true);
Expand Down Expand Up @@ -46,5 +71,6 @@ async function getTokenFromBasicAuth (settings) {
}

module.exports = {
getTokenFromBasicAuth
getTokenFromBasicAuth,
getUserFromAuthToken
};
17 changes: 13 additions & 4 deletions lib/openshift-rest-client.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const fs = require('fs');
const path = require('path');

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

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

const accessToken = await getTokenFromBasicAuth({ insecureSkipTlsVerify, url, user, password, authUrl });
let accessToken;

if (config.auth.token) {
const openshiftUser = await getUserFromAuthToken({ insecureSkipTlsVerify, url, token: config.auth.token });
accessToken = config.auth.token;
user = openshiftUser.metadata.name;
} else {
accessToken = await getTokenFromBasicAuth({ insecureSkipTlsVerify, url, user, password, authUrl });
}
const clusterUrl = url;
// Create clusterName from clusterUrl by removing 'https://'
const clusterName = clusterUrl.replace(/(^\w+:|^)\/\//, '');
Expand Down
87 changes: 87 additions & 0 deletions test/basic-auth-request-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,3 +147,90 @@ test('basic auth request with request error', (t) => {
t.end();
});
});

// Getting the User from a Token Tests

test('get user from token', (t) => {
const basicAuthRequest = proxyquire('../lib/basic-auth-request', {
request: (requestObject, cb) => {
t.equal(requestObject.strictSSL, false, 'should be false');
return cb(null, {
statusCode: 200
},
JSON.stringify({
kind: 'User',
metadata: {
name: 'developer'
}
})
);
}
});

const settings = {
url: 'http://',
token: '12346',
insecureSkipTlsVerify: true
};

const p = basicAuthRequest.getUserFromAuthToken(settings);

t.equal(p instanceof Promise, true, 'is an Promise');

p.then((userObject) => {
t.equal(userObject.metadata.name, 'developer', 'user should be equal');
t.end();
});
});

test('get user from token with 401 status code', (t) => {
const basicAuthRequest = proxyquire('../lib/basic-auth-request', {
request: (requestObject, cb) => {
t.equal(requestObject.strictSSL, false, 'should be false');
return cb(null, {
statusCode: 401,
request: {
uri: {
host: 'https://'
}
}
});
}
});

const settings = {
url: 'http://',
token: '12346',
insecureSkipTlsVerify: true
};

const p = basicAuthRequest.getUserFromAuthToken(settings);

t.equal(p instanceof Promise, true, 'is an Promise');

p.catch((error) => {
t.equal(error.message,
'401 Unable to authenticate with token 12346',
'should be equal');
t.end();
});
});

test('get user from token with request error', (t) => {
const basicAuthRequest = proxyquire('../lib/basic-auth-request', {
request: (requestObject, cb) => {
return cb({ message: 'Error' }, {});
}
});

const settings = {};

const p = basicAuthRequest.getUserFromAuthToken(settings);

t.equal(p instanceof Promise, true, 'is an Promise');

p.catch((error) => {
t.equal(error.message, 'Error', 'should be equal');
t.end();
});
});
66 changes: 66 additions & 0 deletions test/openshift-client-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,72 @@ test('test basic auth - username/password', async (t) => {
t.end();
});

test('test basic auth - token', async (t) => {
const settings = {
config: {
url: 'http://test-url',
auth: {
token: '12345'
}
}
};

const openshiftRestClient = proxyquire('../lib/openshift-rest-client', {
'./basic-auth-request': {
getTokenFromBasicAuth: () => {
t.fail('should not reach this');
},
getUserFromAuthToken: () => {
t.pass('should reach here');
return Promise.resolve({
kind: 'User',
metadata: {
user: 'developer'
}
});
}
}
});

await openshiftRestClient(settings);
t.pass();
t.end();
});

test('test basic auth - token, user and password', async (t) => {
const settings = {
config: {
url: 'http://test-url',
auth: {
username: 'developer',
password: 'developer',
token: '12345'
}
}
};

const openshiftRestClient = proxyquire('../lib/openshift-rest-client', {
'./basic-auth-request': {
getTokenFromBasicAuth: () => {
t.fail('should not reach this');
},
getUserFromAuthToken: () => {
t.pass('should reach here');
return Promise.resolve({
kind: 'User',
metadata: {
user: 'developer'
}
});
}
}
});

await openshiftRestClient(settings);
t.pass();
t.end();
});

test('test basic auth - user/pass', async (t) => {
const settings = {
config: {
Expand Down

0 comments on commit 558bcdb

Please sign in to comment.