Proper handling of ssl certificate validation (#21)
diff --git a/.travis.yml b/.travis.yml
index 051e253..d3a6dcc 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -22,7 +22,7 @@
- docker
env:
global:
- - IGNORE_CERTS=true
+ - __OW_IGNORE_CERTS=true
- REDIS=redis://172.17.0.1:6379
before_install:
- ./travis/scancode.sh
diff --git a/README.md b/README.md
index 238b23e..f12aadb 100644
--- a/README.md
+++ b/README.md
@@ -186,6 +186,27 @@
is progressing. Redis entries are deleted after completion and, as an added
safety, expire after twenty-four hours.
+# OpenWhisk SSL configuration
+
+Additional configuration is required when using an OpenWhisk instance with
+self-signed certificates to disable SSL certificate validation. The input
+parameter object must contain a parameter of type dictionary named `$composer`.
+This dictionary must contain a dictionary named `openwhisk`. The `openwhisk`
+dictionary must contain a field named `ignore_certs` with value `true`:
+```json
+{
+ "$composer": {
+ "openwhisk": {
+ "ignore_certs": true
+ }
+ },
+ ...
+}
+```
+
+This explicit SSL configuration is currently only necessary when using parallel
+combinators or the `async` combinator.
+
# Disclaimer
Apache OpenWhisk Composer is an effort undergoing incubation at The Apache Software Foundation (ASF), sponsored by the Apache Incubator. Incubation is required of all newly accepted projects until a further review indicates that the infrastructure, communications, and decision making process have stabilized in a manner consistent with other successful ASF projects. While incubation status is not necessarily a reflection of the completeness or stability of the code, it does indicate that the project has yet to be fully endorsed by the ASF.
diff --git a/conductor.js b/conductor.js
index ac595a4..fab979b 100644
--- a/conductor.js
+++ b/conductor.js
@@ -41,6 +41,7 @@
// try to extract apihost and key first from whisk property file file and then from process.env
let apihost
let apikey
+ let ignorecerts
try {
const wskpropsPath = process.env.WSK_CONFIG_FILE || path.join(os.homedir(), '.wskprops')
@@ -60,8 +61,9 @@
if (process.env.__OW_API_HOST) apihost = process.env.__OW_API_HOST
if (process.env.__OW_API_KEY) apikey = process.env.__OW_API_KEY
+ if (process.env.__OW_IGNORE_CERTS) ignorecerts = process.env.__OW_IGNORE_CERTS
- const wsk = openwhisk(Object.assign({ apihost, api_key: apikey }, options))
+ const wsk = openwhisk(Object.assign({ apihost, api_key: apikey, ignore_certs: ignorecerts }, options))
wsk.compositions = new Compositions(wsk)
return wsk
}
@@ -134,7 +136,7 @@
const stack = [{ marker: true }].concat(p.s.stack)
const barrierId = uuid()
console.log(`barrierId: ${barrierId}, spawning: ${array.length}`)
- if (!wsk) wsk = openwhisk({ ignore_certs: true })
+ if (!wsk) wsk = openwhisk(p.s.openwhisk)
if (!db) db = createRedisClient(p)
return db.lpushAsync(live(barrierId), 42) // push marker
.then(() => db.expireAsync(live(barrierId), expiration))
@@ -296,7 +298,7 @@
async ({ p, node, index, inspect, step }) {
p.params.$composer = { state: p.s.state, stack: [{ marker: true }].concat(p.s.stack), redis: p.s.redis }
p.s.state = index + node.return
- if (!wsk) wsk = openwhisk({ ignore_certs: true })
+ if (!wsk) wsk = openwhisk(p.s.openwhisk)
return wsk.actions.invoke({ name: process.env.__OW_ACTION_NAME, params: p.params })
.then(response => ({ method: 'async', activationId: response.activationId, sessionId: p.s.session }), error => {
console.error(error) // invoke failed
diff --git a/docs/COMBINATORS.md b/docs/COMBINATORS.md
index 9a157d2..336d7cc 100644
--- a/docs/COMBINATORS.md
+++ b/docs/COMBINATORS.md
@@ -424,6 +424,9 @@
## Async
+The `async` combinator may require an SSL configuration as discussed
+[here](../README.md#openwhisk-ssl-configuration).
+
`composer.async(composition_1, composition_2, ...)` runs a sequence of
compositions asynchronously. It invokes the sequence but does not wait for it to
execute. It immediately returns a dictionary that includes a field named
@@ -439,6 +442,9 @@
Parallel combinators require access to a Redis instance as discussed
[here](../README.md#parallel-compositions-with-redis).
+Parallel combinators may require an SSL configuration as discussed
+[here](../README.md#openwhisk-ssl-configuration).
+
`composer.parallel(composition_1, composition_2, ...)` and its synonymous
`composer.par(composition_1, composition_2, ...)` invoke a series of
compositions (possibly empty) in parallel.
@@ -468,6 +474,9 @@
Parallel combinators require access to a Redis instance as discussed
[here](../README.md#parallel-compositions-with-redis).
+Parallel combinators may require an SSL configuration as discussed
+[here](../README.md#openwhisk-ssl-configuration).
+
`composer.map(composition_1, composition_2, ...)` makes multiple parallel
invocations of a sequence of compositions.
diff --git a/docs/COMMANDS.md b/docs/COMMANDS.md
index dabe630..db45108 100644
--- a/docs/COMMANDS.md
+++ b/docs/COMMANDS.md
@@ -110,6 +110,10 @@
used in its place. If neither is available, the `deploy` command extracts the
`APIHOST` key from the whisk property file for the current user.
+If the `--insecure` flag is set or the environment variable `__OW_IGNORE_CERTS`
+is set to `true`, the `deploy` command ignores SSL certificates validation
+failures.
+
If the `--auth` flag is absent, the environment variable `__OW_API_KEY` is used
in its place. If neither is available, the `deploy` command extracts the `AUTH`
key from the whisk property file for the current user.
diff --git a/package.json b/package.json
index 058f1f0..4069188 100644
--- a/package.json
+++ b/package.json
@@ -31,7 +31,7 @@
],
"dependencies": {
"minimist": "^1.2.0",
- "openwhisk": "^3.11.0",
+ "openwhisk": "^3.18.0",
"terser": "^3.8.2"
},
"devDependencies": {
diff --git a/test/conductor.js b/test/conductor.js
index 90b936e..157d885 100644
--- a/test/conductor.js
+++ b/test/conductor.js
@@ -23,7 +23,7 @@
const composer = require('../composer')
const conductor = require('../conductor')
const name = 'TestAction'
-const wsk = conductor({ ignore_certs: process.env.IGNORE_CERTS && process.env.IGNORE_CERTS !== 'false' && process.env.IGNORE_CERTS !== '0' })
+const wsk = conductor()
// deploy action
const define = action => wsk.actions.delete(action.name).catch(() => { }).then(() => wsk.actions.create(action))
@@ -37,6 +37,9 @@
const redis = process.env.REDIS ? { uri: process.env.REDIS } : false
if (process.env.REDIS && process.env.REDIS_CA) redis.ca = process.env.REDIS_CA
+// openwhisk configuration
+const openwhisk = process.env.__OW_IGNORE_CERTS ? { ignore_certs: true } : {}
+
describe('composer', function () {
let n, x, y // dummy variables
@@ -63,7 +66,7 @@
})
it('action must return activationId', function () {
- return invoke(composer.async('isNotOne'), { n: 1 }).then(activation => assert.ok(activation.response.result.activationId))
+ return invoke(composer.async('isNotOne'), { n: 1, $composer: { openwhisk } }).then(activation => assert.ok(activation.response.result.activationId))
})
it('action name must parse to fully qualified', function () {
@@ -321,17 +324,17 @@
describe('parallel', function () {
const test = redis ? it : it.skip
test('parallel', function () {
- return invoke(composer.parallel('TripleAndIncrement', 'DivideByTwo'), { n: 42, $composer: { redis } })
+ return invoke(composer.parallel('TripleAndIncrement', 'DivideByTwo'), { n: 42, $composer: { redis, openwhisk } })
.then(activation => assert.deepStrictEqual(activation.response.result, { value: [{ n: 127 }, { n: 21 }] }))
})
test('par', function () {
- return invoke(composer.par('DivideByTwo', 'TripleAndIncrement', 'isEven'), { n: 42, $composer: { redis } })
+ return invoke(composer.par('DivideByTwo', 'TripleAndIncrement', 'isEven'), { n: 42, $composer: { redis, openwhisk } })
.then(activation => assert.deepStrictEqual(activation.response.result, { value: [{ n: 21 }, { n: 127 }, { value: true }] }))
})
test('map', function () {
- return invoke(composer.map('TripleAndIncrement', 'DivideByTwo'), { value: [{ n: 3 }, { n: 5 }, { n: 7 }], $composer: { redis } })
+ return invoke(composer.map('TripleAndIncrement', 'DivideByTwo'), { value: [{ n: 3 }, { n: 5 }, { n: 7 }], $composer: { redis, openwhisk } })
.then(activation => assert.deepStrictEqual(activation.response.result, { value: [{ n: 5 }, { n: 8 }, { n: 11 }] }))
})
})