diff --git a/README.md b/README.md index dd69c21..44d372e 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/lib/basic-auth-request.js b/lib/basic-auth-request.js index c299420..81f9616 100644 --- a/lib/basic-auth-request.js +++ b/lib/basic-auth-request.js @@ -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); @@ -46,5 +71,6 @@ async function getTokenFromBasicAuth (settings) { } module.exports = { - getTokenFromBasicAuth + getTokenFromBasicAuth, + getUserFromAuthToken }; diff --git a/lib/openshift-rest-client.js b/lib/openshift-rest-client.js index 29a8727..f8428c5 100644 --- a/lib/openshift-rest-client.js +++ b/lib/openshift-rest-client.js @@ -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'); @@ -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 @@ -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+:|^)\/\//, ''); diff --git a/test/basic-auth-request-test.js b/test/basic-auth-request-test.js index b842632..612032d 100644 --- a/test/basic-auth-request-test.js +++ b/test/basic-auth-request-test.js @@ -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(); + }); +}); diff --git a/test/openshift-client-test.js b/test/openshift-client-test.js index 01a273f..6203035 100644 --- a/test/openshift-client-test.js +++ b/test/openshift-client-test.js @@ -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: {