Skip to content

Commit

Permalink
fix: allow iam client id and secret to be read from constructor (#17)
Browse files Browse the repository at this point in the history
* fix: allow iam client id and secret to be read from constructor

* refactor: add a warning for the user if they dont pass both clientid and secret
  • Loading branch information
dpopp07 committed Apr 29, 2019
1 parent e46cbcf commit 3c88edb
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 5 deletions.
24 changes: 24 additions & 0 deletions iam-token-manager/v1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,22 @@
import extend = require('extend');
import { sendRequest } from '../lib/requestwrapper';

/**
* Check for only one of two elements being defined.
* Returns true if a is defined and b is undefined,
* or vice versa. Returns false if both are defined
* or both are undefined.
*
* @param {any} a - The first object
* @param {any} b - The second object
* @returns {boolean}
*/
function onlyOne(a: any, b: any): boolean {
return Boolean((a && !b) || (b && !a));
}

const CLIENT_ID_SECRET_WARNING = 'Warning: Client ID and Secret must BOTH be given, or the defaults will be used.';

export type Options = {
iamApikey?: string;
iamAccessToken?: string;
Expand Down Expand Up @@ -72,6 +88,10 @@ export class IamTokenManagerV1 {
if (options.iamSecret) {
this.iamSecret = options.iamSecret;
}
if (onlyOne(options.iamClientId, options.iamSecret)) {
// tslint:disable-next-line
console.log(CLIENT_ID_SECRET_WARNING);
}
}

/**
Expand Down Expand Up @@ -120,6 +140,10 @@ export class IamTokenManagerV1 {
public setIamAuthorizationInfo(iamClientId: string, iamSecret: string): void {
this.iamClientId = iamClientId;
this.iamSecret = iamSecret;
if (onlyOne(iamClientId, iamSecret)) {
// tslint:disable-next-line
console.log(CLIENT_ID_SECRET_WARNING);
}
}

/**
Expand Down
15 changes: 13 additions & 2 deletions lib/base_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ export interface UserOptions {
iam_access_token?: string;
iam_apikey?: string;
iam_url?: string;
iam_client_id?: string;
iam_secret?: string;
disable_ssl_verification?: boolean;
}

Expand Down Expand Up @@ -121,6 +123,11 @@ export class BaseService {
/**
* Internal base class that other services inherit from
* @param {UserOptions} options
* @param {string} [options.iam_apikey] - api key used to retrieve an iam access token
* @param {string} [options.iam_access_token] - iam access token provided and managed by user
* @param {string} [options.iam_url] - url for iam service api, needed for services in staging
* @param {string} [options.iam_client_id] - client id (username) for request to iam service
* @param {string} [options.iam_secret] - secret (password) for request to iam service
* @param {string} [options.username] - required unless use_unauthenticated is set
* @param {string} [options.password] - required unless use_unauthenticated is set
* @param {boolean} [options.use_unauthenticated] - skip credential requirement
Expand Down Expand Up @@ -158,12 +165,16 @@ export class BaseService {
this.tokenManager = new IamTokenManagerV1({
iamApikey: _options.iam_apikey,
iamAccessToken: _options.iam_access_token,
iamUrl: _options.iam_url
iamUrl: _options.iam_url,
iamClientId: _options.iam_client_id,
iamSecret: _options.iam_secret
});
} else if (usesBasicForIam(_options)) {
this.tokenManager = new IamTokenManagerV1({
iamApikey: _options.password,
iamUrl: _options.iam_url
iamUrl: _options.iam_url,
iamClientId: _options.iam_client_id,
iamSecret: _options.iam_secret
});
} else {
this.tokenManager = null;
Expand Down
35 changes: 35 additions & 0 deletions test/unit/baseService.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,41 @@ describe('BaseService', function() {
});
});

it('should pass all credentials to token manager when given iam creds', function() {
const instance = new TestService({
iam_apikey: 'key1234',
iam_access_token: 'real-token-84',
iam_url: 'iam.com/api',
iam_client_id: 'abc',
iam_secret: 'abc',
});

expect(instance.tokenManager).toBeDefined();
expect(instance.tokenManager).not.toBeNull();
expect(instance.tokenManager.iamApikey).toBeDefined();
expect(instance.tokenManager.userAccessToken).toBeDefined();
expect(instance.tokenManager.iamUrl).toBeDefined();
expect(instance.tokenManager.iamClientId).toBeDefined();
expect(instance.tokenManager.iamSecret).toBeDefined();
});

it('should pass all credentials to token manager when given iam with basic', function() {
const instance = new TestService({
username: 'apikey',
password: 'key1234',
iam_url: 'iam.com/api',
iam_client_id: 'abc',
iam_secret: 'abc',
});

expect(instance.tokenManager).toBeDefined();
expect(instance.tokenManager).not.toBeNull();
expect(instance.tokenManager.iamApikey).toBeDefined();
expect(instance.tokenManager.iamUrl).toBeDefined();
expect(instance.tokenManager.iamClientId).toBeDefined();
expect(instance.tokenManager.iamSecret).toBeDefined();
});

it('should not fail if setAccessToken is called and token manager is null', function() {
const instance = new TestService({ username: 'user', password: 'pass' });
expect(instance.tokenManager).toBeNull();
Expand Down
35 changes: 32 additions & 3 deletions test/unit/iamTokenManager.test.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
/* eslint-disable no-alert, no-console */
'use strict';

const requestWrapper = require('../../lib/requestwrapper');
requestWrapper.sendRequest = jest.fn();

const IamTokenManagerV1 = require('../../iam-token-manager/v1').IamTokenManagerV1;

const CLIENT_ID_SECRET_WARNING =
'Warning: Client ID and Secret must BOTH be given, or the defaults will be used.';

describe('iam_token_manager_v1', function() {
beforeEach(() => {
requestWrapper.sendRequest.mockReset();
Expand Down Expand Up @@ -235,11 +239,18 @@ describe('iam_token_manager_v1', function() {
});

it('should use the default Authorization header - clientid only via ctor', function(done) {
jest.spyOn(console, 'log').mockImplementation(() => {});

const instance = new IamTokenManagerV1({
iamApikey: 'abcd-1234',
iamClientId: 'foo',
});

// verify warning was triggered
expect(console.log).toHaveBeenCalled();
expect(console.log.mock.calls[0][0]).toBe(CLIENT_ID_SECRET_WARNING);
console.log.mockRestore();

requestWrapper.sendRequest.mockImplementation((parameters, _callback) => {
_callback();
});
Expand All @@ -253,11 +264,17 @@ describe('iam_token_manager_v1', function() {
});

it('should use the default Authorization header, secret only via ctor', function(done) {
jest.spyOn(console, 'log').mockImplementation(() => {});
const instance = new IamTokenManagerV1({
iamApikey: 'abcd-1234',
iamSecret: 'bar',
});

// verify warning was triggered
expect(console.log).toHaveBeenCalled();
expect(console.log.mock.calls[0][0]).toBe(CLIENT_ID_SECRET_WARNING);
console.log.mockRestore();

requestWrapper.sendRequest.mockImplementation((parameters, _callback) => {
_callback();
});
Expand Down Expand Up @@ -294,8 +311,15 @@ describe('iam_token_manager_v1', function() {
iamApikey: 'abcd-1234',
});

jest.spyOn(console, 'log').mockImplementation(() => {});

instance.setIamAuthorizationInfo('foo', null);

// verify warning was triggered
expect(console.log).toHaveBeenCalled();
expect(console.log.mock.calls[0][0]).toBe(CLIENT_ID_SECRET_WARNING);
console.log.mockRestore();

requestWrapper.sendRequest.mockImplementation((parameters, _callback) => {
_callback();
});
Expand All @@ -308,14 +332,20 @@ describe('iam_token_manager_v1', function() {
});
});

it('should use the default Authorization header, secret only via ctor', function(done) {
it('should use the default Authorization header, secret only via setter', function(done) {
const instance = new IamTokenManagerV1({
iamApikey: 'abcd-1234',
iamSecret: 'bar',
});

jest.spyOn(console, 'log').mockImplementation(() => {});

instance.setIamAuthorizationInfo(null, 'bar');

// verify warning was triggered
expect(console.log).toHaveBeenCalled();
expect(console.log.mock.calls[0][0]).toBe(CLIENT_ID_SECRET_WARNING);
console.log.mockRestore();

requestWrapper.sendRequest.mockImplementation((parameters, _callback) => {
_callback();
});
Expand All @@ -331,7 +361,6 @@ describe('iam_token_manager_v1', function() {
it('should use the default Authorization header, nulls passed to setter', function(done) {
const instance = new IamTokenManagerV1({
iamApikey: 'abcd-1234',
iamSecret: 'bar',
});

instance.setIamAuthorizationInfo(null, null);
Expand Down

0 comments on commit 3c88edb

Please sign in to comment.