Skip to content
This repository was archived by the owner on Dec 9, 2024. It is now read-only.

Commit 9e6930f

Browse files
committed
Adding IAM support for IBM Cloud Functions using explicit env var
OW_IAM_NAMESPACE_API_KEY is used to provide API key. This pulls in the auth handler to manage retrieving IAM tokens at runtime.
1 parent 4dcb474 commit 9e6930f

File tree

6 files changed

+39
-10
lines changed

6 files changed

+39
-10
lines changed

README.md

+4-3
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ This plugin enables support for the [Apache OpenWhisk platform](https://openwhis
66

77
## Getting Started
88

9-
### Register account with OpenWhisk
9+
### Register account with Apache OpenWhisk
1010

11-
Before you can deploy your service to OpenWhisk, you need to have an account registered with the platform.
11+
Before you can deploy your service to Apache OpenWhisk, you need to have an account registered with the platform.
1212

1313
- *Want to run the platform locally?* Please read the project's [*Quick Start*](https://github.com/openwhisk/openwhisk#quick-start) guide for deploying it locally.
14-
- *Want to use a hosted provider?* Please sign up for a free account with [IBM Cloud](https://console.ng.bluemix.net/) and then follow the instructions for getting access to [OpenWhisk on Bluemix](https://console.ng.bluemix.net/openwhisk/).
14+
- *Want to use a hosted provider?* Please [sign up](https://cloud.ibm.com/registration) for a free account with [IBM Cloud](https://cloud.ibm.com/) and then follow the instructions for getting access to [IBM Cloud Functions (Apache OpenWhisk)](https://cloud.ibm.com/openwhisk).
1515

1616
### Set up account credentials
1717

@@ -25,6 +25,7 @@ Account credentials for OpenWhisk can be provided through a configuration file o
2525
- *OW_AUTH* - Authentication key, e.g. `xxxxxx:yyyyy`
2626
- *OW_NAMESPACE* - Namespace, defaults to user-provided credentials
2727
- *OW_APIGW_ACCESS_TOKEN* - API gateway access token (optional)
28+
- *OW_IAM_NAMESPACE_API_KEY* - IBM Cloud IAM API key (optional & overrides `auth`).
2829

2930
### Install Serverless Framework
3031

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
},
3030
"homepage": "https://github.com/serverless/serverless-openwhisk#readme",
3131
"dependencies": {
32+
"@ibm-functions/iam-token-manager": "^1.0.3",
3233
"bluebird": "^3.4.6",
3334
"chalk": "^1.1.3",
3435
"fs-extra": "^1.0.0",

provider/credentials.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
const path = require('path');
44
const fs = require('fs-extra');
55

6-
const ENV_PARAMS = ['OW_APIHOST', 'OW_AUTH', 'OW_NAMESPACE', 'OW_APIGW_ACCESS_TOKEN'];
6+
const ENV_PARAMS = ['OW_APIHOST', 'OW_AUTH', 'OW_NAMESPACE', 'OW_APIGW_ACCESS_TOKEN', 'OW_IAM_NAMESPACE_API_KEY'];
77

88
function getWskPropsFile() {
99
const Home = process.env[(process.platform === 'win32') ? 'USERPROFILE' : 'HOME'];

provider/openwhiskProvider.js

+10-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
const BbPromise = require('bluebird');
44
const openwhisk = require('openwhisk')
5+
const IamTokenManager = require('@ibm-functions/iam-token-manager')
56
const Credentials = require('./credentials');
67

78
const constants = {
@@ -26,8 +27,15 @@ class OpenwhiskProvider {
2627
if (this._client) return BbPromise.resolve(this._client)
2728

2829
const ignore_certs = this.serverless.service.provider.ignore_certs || false
29-
return this.props().then(this.hasValidCreds).then(wskProps => {
30-
this._client = openwhisk({ apihost: wskProps.apihost, api_key: wskProps.auth, namespace: wskProps.namespace, ignore_certs, apigw_token: wskProps.apigw_access_token });
30+
return this.props().then(props => {
31+
if (props.hasOwnProperty('iam_namespace_api_key')) {
32+
const auth_handler = new IamTokenManager({ iamApikey: props.iam_namespace_api_key });
33+
this._client = openwhisk({ apihost: props.apihost, auth_handler, namespace: props.namespace, ignore_certs });
34+
} else {
35+
this.hasValidCreds(props)
36+
this._client = openwhisk({ apihost: props.apihost, api_key: props.auth, namespace: props.namespace, ignore_certs, apigw_token: props.apigw_access_token });
37+
}
38+
3139
return this._client
3240
})
3341
}

provider/tests/credentials.js

+9-4
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,12 @@ describe('#getWskProps()', () => {
2626
auth: 'user:pass',
2727
namespace: '[email protected]_dev',
2828
apigw_access_token: 'blahblahblahkey1234',
29+
iam_namespace_api_key: 'some-api-key-value',
2930
};
3031

3132
const wskProps =
3233
'APIHOST=openwhisk.ng.bluemix.net\[email protected]_dev\n' +
33-
'AUTH=user:pass\nAPIGW_ACCESS_TOKEN=blahblahblahkey1234\n';
34+
'AUTH=user:pass\nAPIGW_ACCESS_TOKEN=blahblahblahkey1234\nIAM_NAMESPACE_API_KEY=some-api-key-value';
3435

3536
it('when the default is used', () => {
3637
const home = process.env[(process.platform === 'win32') ? 'USERPROFILE' : 'HOME'];
@@ -62,7 +63,8 @@ describe('#getWskProps()', () => {
6263
apihost: 'blah.blah.com',
6364
auth: 'another_user:another_pass',
6465
namespace: '[email protected]',
65-
apigw_access_token: 'some_access_token'
66+
apigw_access_token: 'some_access_token',
67+
iam_namespace_api_key: 'some_api_key'
6668
};
6769

6870
sandbox.stub(fs, 'readFile', (path, encoding, cb) => {
@@ -73,6 +75,7 @@ describe('#getWskProps()', () => {
7375
process.env.OW_AUTH = 'another_user:another_pass';
7476
process.env.OW_NAMESPACE = '[email protected]';
7577
process.env.OW_APIGW_ACCESS_TOKEN = 'some_access_token';
78+
process.env.OW_IAM_NAMESPACE_API_KEY = 'some_api_key';
7679

7780
return expect(Credentials.getWskProps()).to.eventually.deep.equal(mockObject);
7881
});
@@ -82,11 +85,12 @@ describe('#getWskProps()', () => {
8285
apihost: 'blah.blah.com',
8386
auth: 'another_user:another_pass',
8487
namespace: '[email protected]',
85-
apigw_access_token: 'some_access_token'
88+
apigw_access_token: 'some_access_token',
89+
iam_namespace_api_key: 'some_api_key'
8690
};
8791

8892
const wskProps =
89-
'APIHOST=openwhisk.ng.bluemix.net\[email protected]_dev\nAUTH=user:pass\nAPIGW_ACCESS_TOKEN=hello\n';
93+
'APIHOST=openwhisk.ng.bluemix.net\[email protected]_dev\nAUTH=user:pass\nAPIGW_ACCESS_TOKEN=hello\nIAM_NAMESPACE_API_KEY=old_key';
9094

9195
sandbox.stub(fs, 'readFile', (path, encoding, cb) => {
9296
cb(null, wskProps);
@@ -96,6 +100,7 @@ describe('#getWskProps()', () => {
96100
process.env.OW_AUTH = 'another_user:another_pass';
97101
process.env.OW_NAMESPACE = '[email protected]';
98102
process.env.OW_APIGW_ACCESS_TOKEN = 'some_access_token';
103+
process.env.OW_IAM_NAMESPACE_API_KEY = 'some_api_key';
99104

100105
return expect(Credentials.getWskProps()).to.eventually.deep.equal(mockObject);
101106
});

provider/tests/openwhiskProvider.js

+14
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,20 @@ describe('OpenwhiskProvider', () => {
9191
expect(client).to.be.equal(openwhiskProvider._client)
9292
})
9393
})
94+
95+
it('should support client auth using IBM Cloud IAM API key', () => {
96+
openwhiskProvider._client = null
97+
const API_KEY = 'some-key-value';
98+
const creds = {iam_namespace_api_key: API_KEY, apihost: 'some_api', namespace: 'a34dd39e-e3de-4160-bbab-59ac345678ed'}
99+
sandbox.stub(openwhiskProvider, "props").returns(BbPromise.resolve(creds))
100+
101+
return openwhiskProvider.client().then(client => {
102+
expect(client.actions.client.options.namespace).to.be.deep.equal(creds.namespace)
103+
expect(client.actions.client.options.api).to.be.deep.equal(`https://${creds.apihost}/api/v1/`)
104+
expect(typeof client.actions.client.options.authHandler).to.not.equal('undefined')
105+
expect(client.actions.client.options.authHandler.iamApikey).to.be.deep.equal(API_KEY)
106+
})
107+
})
94108
})
95109

96110
describe('#props()', () => {

0 commit comments

Comments
 (0)