From 7103cc02c57bd4c99c47dce4349c208bbfeeef74 Mon Sep 17 00:00:00 2001 From: Ankit Arora Date: Thu, 19 Nov 2020 12:07:29 +0530 Subject: [PATCH 01/21] Add stub for oci signature v1 auth protocol --- lib/authorizer/oci-v1.js | 81 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 lib/authorizer/oci-v1.js diff --git a/lib/authorizer/oci-v1.js b/lib/authorizer/oci-v1.js new file mode 100644 index 000000000..7f97c8a5b --- /dev/null +++ b/lib/authorizer/oci-v1.js @@ -0,0 +1,81 @@ +/** + * @fileOverview + * + * Implements the Oracle Cloud Infrastructure Signature v1 authentication method. + * Specification document: https://docs.cloud.oracle.com/en-us/iaas/Content/API/Concepts/signingrequests.htm + */ + +var _ = require('lodash'), + uuid = require('uuid/v4'), + crypto = require('crypto'), + sdk = require('postman-collection'), + RequestBody = sdk.RequestBody, + urlEncoder = require('postman-url-encoder'), + bodyBuilder = require('../requester/core-body-builder'); + +/** + * @implements {AuthHandlerInterface} + */ +module.exports = { + /** + * @property {AuthHandlerInterface~AuthManifest} + */ + // TODO: Fix the manifest + manifest: { + info: { + name: 'oci-v1', + version: '1.0.0' + }, + updates: [ + { + property: 'Authorization', + type: 'header' + } + ] + }, + + /** + * Initializes a item (fetches all required parameters, etc) before the actual authorization step. + * + * @param {AuthInterface} auth AuthInterface instance created with request auth + * @param {Response} response Response of intermediate request (it any) + * @param {AuthHandlerInterface~authInitHookCallback} done Callback function called with error as first argument + */ + init: function (auth, response, done) { + done(null); + }, + + /** + * Checks the item, and fetches any parameters that are not already provided. + * + * @param {AuthInterface} auth AuthInterface instance created with request auth + * @param {AuthHandlerInterface~authPreHookCallback} done Callback function called with error, success and request + */ + pre: function (auth, done) { + // TODO: Check the right params + done(null, Boolean(auth.get('accessToken') && auth.get('clientToken') && auth.get('clientSecret'))); + }, + + /** + * Verifies whether the request was successful after being sent. + * + * @param {AuthInterface} auth AuthInterface instance created with request auth + * @param {Requester} response Response of the request + * @param {AuthHandlerInterface~authPostHookCallback} done Callback function called with error and success + */ + post: function (auth, response, done) { + done(null, true); + }, + + /** + * Signs a request. + * + * @param {AuthInterface} auth AuthInterface instance created with request auth + * @param {Request} request Request to be sent + * @param {AuthHandlerInterface~authSignHookCallback} done Callback function + */ + sign: function (auth, request, done) { + // TODO: Implement logic + return done(); + } +}; From f8be798ae4b9bf245a914e5067d1066ebdfdc488 Mon Sep 17 00:00:00 2001 From: Ankit Arora Date: Thu, 19 Nov 2020 20:26:00 +0530 Subject: [PATCH 02/21] Implement some parts of oci authorizer --- lib/authorizer/oci-v1.js | 49 ++++++++--- package-lock.json | 177 +++++++++++++++++++++++++++++++++++++-- package.json | 1 + 3 files changed, 211 insertions(+), 16 deletions(-) diff --git a/lib/authorizer/oci-v1.js b/lib/authorizer/oci-v1.js index 7f97c8a5b..db103bdb9 100644 --- a/lib/authorizer/oci-v1.js +++ b/lib/authorizer/oci-v1.js @@ -5,13 +5,17 @@ * Specification document: https://docs.cloud.oracle.com/en-us/iaas/Content/API/Concepts/signingrequests.htm */ -var _ = require('lodash'), - uuid = require('uuid/v4'), - crypto = require('crypto'), - sdk = require('postman-collection'), - RequestBody = sdk.RequestBody, - urlEncoder = require('postman-url-encoder'), - bodyBuilder = require('../requester/core-body-builder'); +var oci = require('oci-common'), + convertPostmanRequestToOCIRequest = function (request) { + // need to convert request from `module:postman-collection.Request` + // to oci-common/lib/http-request.d.ts.HttpRequest + return { + uri: request.url, + headers: request.headers, // TODO: Convert to DOM headers class + method: request.method, + body: request.body // TODO: Convert to supported format + }; + }; /** * @implements {AuthHandlerInterface} @@ -28,7 +32,7 @@ module.exports = { }, updates: [ { - property: 'Authorization', + property: 'authorization', type: 'header' } ] @@ -53,7 +57,15 @@ module.exports = { */ pre: function (auth, done) { // TODO: Check the right params - done(null, Boolean(auth.get('accessToken') && auth.get('clientToken') && auth.get('clientSecret'))); + // config = from_file() + // auth = Signer( + // tenancy=config['tenancy'], + // user=config['user'], + // fingerprint=config['fingerprint'], + // private_key_file_location=config['key_file'], + // ) + done(null, Boolean(auth.get('tenancy') && auth.get('user') && + auth.get('fingerprint') && auth.get('private_key'))); }, /** @@ -76,6 +88,23 @@ module.exports = { */ sign: function (auth, request, done) { // TODO: Implement logic - return done(); + let provider = new oci.SimpleAuthenticationDetailsProvider( + auth.get('tenancy'), auth.get('user'), auth.get('fingerprint'), auth.get('private_key') + ), + signer = new oci.DefaultRequestSigner(provider), + ociRequest = convertPostmanRequestToOCIRequest(request); + + signer.signHttpRequest(ociRequest).then(function () { + request.headers.add({ + key: 'authorization', + value: ociRequest.headers.get('authorization'), + system: true + }); + + done(null); + } + ).catch(function (err) { + done(new Error('Unable to sign')); + }); } }; diff --git a/package-lock.json b/package-lock.json index f5e1c6fab..416081729 100644 --- a/package-lock.json +++ b/package-lock.json @@ -234,6 +234,11 @@ "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", "dev": true }, + "@types/isomorphic-fetch": { + "version": "0.0.35", + "resolved": "https://registry.npmjs.org/@types/isomorphic-fetch/-/isomorphic-fetch-0.0.35.tgz", + "integrity": "sha512-DaZNUvLDCAnCTjgwxgiL1eQdxIKEpNLOlTNtAgnZc50bG2copGhRrFN9/PxPBuJe+tZVLCbQ7ls0xveXVRPkvw==" + }, "JSONStream": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", @@ -1013,6 +1018,11 @@ "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", "dev": true }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" + }, "buffer-fill": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", @@ -2134,6 +2144,14 @@ "safer-buffer": "^2.1.0" } }, + "ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "requires": { + "safe-buffer": "^5.0.1" + } + }, "editorconfig": { "version": "0.15.3", "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz", @@ -2187,6 +2205,24 @@ "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", "dev": true }, + "encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "requires": { + "iconv-lite": "^0.6.2" + }, + "dependencies": { + "iconv-lite": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", + "integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + } + } + }, "engine.io": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz", @@ -2330,6 +2366,11 @@ "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", "dev": true }, + "es6-promise": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.6.tgz", + "integrity": "sha512-aRVgGdnmW2OiySVPUC9e6m+plolMAJKjZnQlCwNSuK5yQ0JN61DZSO1X1Ufd1foqWRAlig0rhduTCHe7sVtK5Q==" + }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -3838,8 +3879,7 @@ "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" }, "is-symbol": { "version": "1.0.2", @@ -3888,6 +3928,15 @@ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true }, + "isomorphic-fetch": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", + "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", + "requires": { + "node-fetch": "^1.0.1", + "whatwg-fetch": ">=0.10.0" + } + }, "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", @@ -4188,6 +4237,23 @@ "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", "dev": true }, + "jsonwebtoken": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", + "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", + "requires": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^5.6.0" + } + }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -4199,12 +4265,36 @@ "verror": "1.10.0" } }, + "jssha": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/jssha/-/jssha-2.4.1.tgz", + "integrity": "sha512-77DN1YurYgh+7FPCTJ2CQ6hVDHgIWiHxm4Y5/mAdnpETKYagX22pVWMz4xfKF5fcpNfMaztgVj+/B1bt2k23Eg==" + }, "just-extend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.0.2.tgz", "integrity": "sha512-FrLwOgm+iXrPV+5zDU6Jqu4gCRXbWEQg2O3SKONsWE4w7AXFRkryS53bpWdaL9cNol+AmR3AEYz6kn+o0fCPnw==", "dev": true }, + "jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "requires": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, "karma": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/karma/-/karma-3.1.4.tgz", @@ -4674,6 +4764,26 @@ "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", "dev": true }, + "lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" + }, + "lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" + }, + "lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" + }, + "lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=" + }, "lodash.isplainobject": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", @@ -4701,6 +4811,11 @@ "integrity": "sha1-brGa5aHuHdnfC5aeZs4Lf6MLXmA=", "dev": true }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" + }, "lodash.padend": { "version": "4.6.1", "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz", @@ -5289,8 +5404,7 @@ "ms": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" }, "mute-stream": { "version": "0.0.7", @@ -5385,6 +5499,15 @@ } } }, + "node-fetch": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", + "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", + "requires": { + "encoding": "^0.1.11", + "is-stream": "^1.0.1" + } + }, "node-oauth1": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/node-oauth1/-/node-oauth1-1.3.0.tgz", @@ -5657,6 +5780,39 @@ "isobject": "^3.0.1" } }, + "oci-common": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/oci-common/-/oci-common-1.8.0.tgz", + "integrity": "sha512-vcLJ6fxCRPiipRqI8n7emcYORiDNt8R1PQFVOP63oU+al7Nh5NT//AGuu+0NELr+iO74X2qNQEReU8yvSZFv4Q==", + "requires": { + "@types/isomorphic-fetch": "0.0.35", + "es6-promise": "4.2.6", + "http-signature": "1.3.1", + "isomorphic-fetch": "2.2.1", + "jsonwebtoken": "8.5.1", + "jssha": "2.4.1", + "opossum": "5.0.1", + "sshpk": "1.16.1", + "uuid": "3.3.3" + }, + "dependencies": { + "http-signature": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.1.tgz", + "integrity": "sha512-Y29YKEc8MQsjch/VzkUVJ+2MXd9WcR42fK5u36CZf4G8bXw2DXMTWuESiB0R6m59JAWxlPPw5/Fri/t/AyyueA==", + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.14.1" + } + }, + "uuid": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", + "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==" + } + } + }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -5684,6 +5840,11 @@ "mimic-fn": "^1.0.0" } }, + "opossum": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/opossum/-/opossum-5.0.1.tgz", + "integrity": "sha512-iUDUQmFl3RanaBVLMDTZ6WtXj/Hk84pwJ5JWoJaQd1lXGifdApHhszI3biZvdBDdpTERCmB6x+7+uNvzhzVZIg==" + }, "optimist": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", @@ -6660,8 +6821,7 @@ "semver": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", - "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", - "dev": true + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==" }, "send": { "version": "0.17.1", @@ -8568,6 +8728,11 @@ "integrity": "sha512-kudCA8PXVQfrqv2mFTG72vDBRi8BKWxGgFLwPpzHcpZnSwZk93WMwUDVcLHWNsnm+Y0AC4Vb6MUNRgaHfyV2DQ==", "dev": true }, + "whatwg-fetch": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.5.0.tgz", + "integrity": "sha512-jXkLtsR42xhXg7akoDKvKWE40eJeI+2KZqcp2h3NsOrRnDvtWX36KcKl30dy+hxECivdk2BVUHVNrPtoMBUx6A==" + }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", diff --git a/package.json b/package.json index c6c78fa19..d7b96f98f 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "dependencies": { "async": "2.6.3", "aws4": "1.10.1", + "oci-common": "1.8.0", "eventemitter3": "4.0.7", "handlebars": "4.7.6", "http-reasons": "0.1.0", From aac783ad4de9d8684e030a7746ce3cc4671210e7 Mon Sep 17 00:00:00 2001 From: Ankit Arora Date: Thu, 19 Nov 2020 20:56:23 +0530 Subject: [PATCH 03/21] Add conditions to handle different types of request body --- lib/authorizer/oci-v1.js | 46 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/lib/authorizer/oci-v1.js b/lib/authorizer/oci-v1.js index db103bdb9..1227c8a53 100644 --- a/lib/authorizer/oci-v1.js +++ b/lib/authorizer/oci-v1.js @@ -5,15 +5,53 @@ * Specification document: https://docs.cloud.oracle.com/en-us/iaas/Content/API/Concepts/signingrequests.htm */ -var oci = require('oci-common'), +var _ = require('lodash'), + oci = require('oci-common'), + stream = require('stream'), + bodyBuilder = require('../requester/core-body-builder'), + sdk = require('postman-collection'), + RequestBody = sdk.RequestBody, + getRequestBodyStream = function (request) { + + let bodyStream; + + if (request.body.mode === RequestBody.MODES.raw) { + let rawBody = bodyBuilder.raw(request.body.raw).body; + // https://stackoverflow.com/questions/12755997/how-to-create-streams-from-string-in-node-js + + bodyStream = stream.Readable.from([rawBody]); + } + + if (request.body.mode === RequestBody.MODES.urlencoded) { + let urlencodedBody = bodyBuilder.urlencoded(request.body.urlencoded).form; + + urlencodedBody = urlEncoder.encodeQueryString(urlencodedBody); + } + + if (request.body.mode === RequestBody.MODES.file) { + let originalReadStream = _.get(request.body, 'file.content'); + + if (!originalReadStream) { + return callback(); + } + } + + if (request.body.mode === RequestBody.MODES.graphql) { + let graphqlBody = bodyBuilder.graphql(request.body.graphql).body; + } + + return bodyStream; + }, + convertToDomHeadersObject = function(headers) { + }, convertPostmanRequestToOCIRequest = function (request) { // need to convert request from `module:postman-collection.Request` // to oci-common/lib/http-request.d.ts.HttpRequest return { uri: request.url, - headers: request.headers, // TODO: Convert to DOM headers class - method: request.method, - body: request.body // TODO: Convert to supported format + headers: convertToDomHeadersObject(request.headers), + method: request.method.toUpperCase(), + body: getRequestBodyStream(request.body) }; }; From 81c65e4274e76e429a7907898e6ab257f588bdf6 Mon Sep 17 00:00:00 2001 From: Ankit Arora Date: Fri, 20 Nov 2020 12:52:57 +0530 Subject: [PATCH 04/21] Remove everything to do with request body in oci auth method --- lib/authorizer/oci-v1.js | 74 ++++++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 34 deletions(-) diff --git a/lib/authorizer/oci-v1.js b/lib/authorizer/oci-v1.js index 1227c8a53..6be34890b 100644 --- a/lib/authorizer/oci-v1.js +++ b/lib/authorizer/oci-v1.js @@ -11,37 +11,37 @@ var _ = require('lodash'), bodyBuilder = require('../requester/core-body-builder'), sdk = require('postman-collection'), RequestBody = sdk.RequestBody, - getRequestBodyStream = function (request) { - - let bodyStream; - - if (request.body.mode === RequestBody.MODES.raw) { - let rawBody = bodyBuilder.raw(request.body.raw).body; - // https://stackoverflow.com/questions/12755997/how-to-create-streams-from-string-in-node-js - - bodyStream = stream.Readable.from([rawBody]); - } - - if (request.body.mode === RequestBody.MODES.urlencoded) { - let urlencodedBody = bodyBuilder.urlencoded(request.body.urlencoded).form; - - urlencodedBody = urlEncoder.encodeQueryString(urlencodedBody); - } - - if (request.body.mode === RequestBody.MODES.file) { - let originalReadStream = _.get(request.body, 'file.content'); - - if (!originalReadStream) { - return callback(); - } - } - - if (request.body.mode === RequestBody.MODES.graphql) { - let graphqlBody = bodyBuilder.graphql(request.body.graphql).body; - } - - return bodyStream; - }, + // getRequestBodyStream = function (request) { + // + // let bodyStream; + // + // if (request.body.mode === RequestBody.MODES.raw) { + // let rawBody = bodyBuilder.raw(request.body.raw).body; + // // https://stackoverflow.com/questions/12755997/how-to-create-streams-from-string-in-node-js + // + // bodyStream = stream.Readable.from([rawBody]); + // } + // + // if (request.body.mode === RequestBody.MODES.urlencoded) { + // let urlencodedBody = bodyBuilder.urlencoded(request.body.urlencoded).form; + // + // urlencodedBody = urlEncoder.encodeQueryString(urlencodedBody); + // } + // + // if (request.body.mode === RequestBody.MODES.file) { + // let originalReadStream = _.get(request.body, 'file.content'); + // + // if (!originalReadStream) { + // return callback(); + // } + // } + // + // if (request.body.mode === RequestBody.MODES.graphql) { + // let graphqlBody = bodyBuilder.graphql(request.body.graphql).body; + // } + // + // return bodyStream; + // }, convertToDomHeadersObject = function(headers) { }, convertPostmanRequestToOCIRequest = function (request) { @@ -50,8 +50,8 @@ var _ = require('lodash'), return { uri: request.url, headers: convertToDomHeadersObject(request.headers), - method: request.method.toUpperCase(), - body: getRequestBodyStream(request.body) + method: request.method.toUpperCase() + // body: getRequestBodyStream(request.body) }; }; @@ -125,7 +125,13 @@ module.exports = { * @param {AuthHandlerInterface~authSignHookCallback} done Callback function */ sign: function (auth, request, done) { - // TODO: Implement logic + // TODO: Remove restrictions on body and method + if (request.body && !request.body.isEmpty()) { + return done(new Error('Request body not supported')); + } + if (request.method.toUpperCase() !== 'GET') { + return done(new Error('Only GET methods are supported at the moment')) + } let provider = new oci.SimpleAuthenticationDetailsProvider( auth.get('tenancy'), auth.get('user'), auth.get('fingerprint'), auth.get('private_key') ), From b5f829c4acd96eecdd606658d7488a9161c49461 Mon Sep 17 00:00:00 2001 From: Ankit Arora Date: Fri, 20 Nov 2020 13:08:02 +0530 Subject: [PATCH 05/21] Add polyfill for DOM Headers object, implement conversion function --- lib/authorizer/oci-v1.js | 81 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 73 insertions(+), 8 deletions(-) diff --git a/lib/authorizer/oci-v1.js b/lib/authorizer/oci-v1.js index 6be34890b..a769e8ee7 100644 --- a/lib/authorizer/oci-v1.js +++ b/lib/authorizer/oci-v1.js @@ -5,12 +5,70 @@ * Specification document: https://docs.cloud.oracle.com/en-us/iaas/Content/API/Concepts/signingrequests.htm */ -var _ = require('lodash'), - oci = require('oci-common'), - stream = require('stream'), - bodyBuilder = require('../requester/core-body-builder'), - sdk = require('postman-collection'), - RequestBody = sdk.RequestBody, +// -------------------- HEADERS POLYFILL --------------------------- + +function Headers (values) { + this._values = values || {}; +} + +Headers.prototype.append = function (name, value) { + this._values[name] = value; +}; + +Headers.prototype.delete = function (name) { + delete this._values[name]; +}; + +Headers.prototype.entries = function () { + const result = []; + + for (let key in this._values) { + result.push([key, this._values[key]]); + } + + return result; +}; + +Headers.prototype.get = function (name) { + return this._values[name]; +}; + +Headers.prototype.has = function (name) { + return name in this._values; +}; + +Headers.prototype.keys = function () { + const result = []; + + for (let key in this._values) { + result.push(key); + } + + return result; +}; + +Headers.prototype.set = function (name, value) { + this._values[name] = value; +}; + +Headers.prototype.values = function (name, value) { + const result = []; + + for (let key in this._values) { + result.push(this._values[key]); + } + + return result; +}; + +// ------------------------------------------------------------ + +var oci = require('oci-common'), + // _ = require('lodash'), + // stream = require('stream'), + // bodyBuilder = require('../requester/core-body-builder'), + // sdk = require('postman-collection'), + // RequestBody = sdk.RequestBody, // getRequestBodyStream = function (request) { // // let bodyStream; @@ -42,7 +100,14 @@ var _ = require('lodash'), // // return bodyStream; // }, - convertToDomHeadersObject = function(headers) { + convertToDomHeadersObject = function (postmanHeaders) { + let rawHeaders = {}; + + postmanHeaders.all().forEach(function (each) { + rawHeaders[each.key] = each.value; + }); + + return new Headers(rawHeaders); }, convertPostmanRequestToOCIRequest = function (request) { // need to convert request from `module:postman-collection.Request` @@ -130,7 +195,7 @@ module.exports = { return done(new Error('Request body not supported')); } if (request.method.toUpperCase() !== 'GET') { - return done(new Error('Only GET methods are supported at the moment')) + return done(new Error('Only GET methods are supported at the moment')); } let provider = new oci.SimpleAuthenticationDetailsProvider( auth.get('tenancy'), auth.get('user'), auth.get('fingerprint'), auth.get('private_key') From b733d35d6b711a85195241709c017a93d5eedb23 Mon Sep 17 00:00:00 2001 From: Ankit Arora Date: Mon, 7 Dec 2020 11:20:31 +0530 Subject: [PATCH 06/21] Signature working! --- lib/authorizer/index.js | 3 +- lib/authorizer/oci-v1.js | 113 +++++++++--------- package-lock.json | 194 ++----------------------------- package.json | 4 +- test/fixtures/auth-requests.json | 13 +++ test/unit/auth-handlers.test.js | 21 ++++ 6 files changed, 106 insertions(+), 242 deletions(-) diff --git a/lib/authorizer/index.js b/lib/authorizer/index.js index cfad4cf0b..917433126 100644 --- a/lib/authorizer/index.js +++ b/lib/authorizer/index.js @@ -88,7 +88,8 @@ _.forEach({ oauth2: require('./oauth2'), ntlm: require('./ntlm'), apikey: require('./apikey'), - edgegrid: require('./edgegrid') + edgegrid: require('./edgegrid'), + oci: require('./oci-v1') }, AuthLoader.addHandler); /** diff --git a/lib/authorizer/oci-v1.js b/lib/authorizer/oci-v1.js index a769e8ee7..330c6cae9 100644 --- a/lib/authorizer/oci-v1.js +++ b/lib/authorizer/oci-v1.js @@ -61,45 +61,12 @@ Headers.prototype.values = function (name, value) { return result; }; + // ------------------------------------------------------------ -var oci = require('oci-common'), - // _ = require('lodash'), - // stream = require('stream'), - // bodyBuilder = require('../requester/core-body-builder'), - // sdk = require('postman-collection'), - // RequestBody = sdk.RequestBody, - // getRequestBodyStream = function (request) { - // - // let bodyStream; - // - // if (request.body.mode === RequestBody.MODES.raw) { - // let rawBody = bodyBuilder.raw(request.body.raw).body; - // // https://stackoverflow.com/questions/12755997/how-to-create-streams-from-string-in-node-js - // - // bodyStream = stream.Readable.from([rawBody]); - // } - // - // if (request.body.mode === RequestBody.MODES.urlencoded) { - // let urlencodedBody = bodyBuilder.urlencoded(request.body.urlencoded).form; - // - // urlencodedBody = urlEncoder.encodeQueryString(urlencodedBody); - // } - // - // if (request.body.mode === RequestBody.MODES.file) { - // let originalReadStream = _.get(request.body, 'file.content'); - // - // if (!originalReadStream) { - // return callback(); - // } - // } - // - // if (request.body.mode === RequestBody.MODES.graphql) { - // let graphqlBody = bodyBuilder.graphql(request.body.graphql).body; - // } - // - // return bodyStream; - // }, +var sshpk = require('sshpk'), + UrlParser = require('url'), + httpSignature = require('http-signature'), convertToDomHeadersObject = function (postmanHeaders) { let rawHeaders = {}; @@ -112,14 +79,31 @@ var oci = require('oci-common'), convertPostmanRequestToOCIRequest = function (request) { // need to convert request from `module:postman-collection.Request` // to oci-common/lib/http-request.d.ts.HttpRequest + console.log('converting object request.url=', request.url.path) return { - uri: request.url, + uri: request.url.getRaw(), headers: convertToDomHeadersObject(request.headers), method: request.method.toUpperCase() // body: getRequestBodyStream(request.body) }; }; +class SignerRequest { + constructor (method, url, headers) { + this.headers = headers; + this.method = method; + this.path = UrlParser.parse(url).path; + } + + getHeader (name) { + return this.headers.get(name); + } + + setHeader (name, value) { + this.headers.set(name, value); + } +} + /** * @implements {AuthHandlerInterface} */ @@ -190,6 +174,8 @@ module.exports = { * @param {AuthHandlerInterface~authSignHookCallback} done Callback function */ sign: function (auth, request, done) { + console.log('OCI SIGN CALLED'); + console.log('request headers 1: ', request.headers); // TODO: Remove restrictions on body and method if (request.body && !request.body.isEmpty()) { return done(new Error('Request body not supported')); @@ -197,23 +183,42 @@ module.exports = { if (request.method.toUpperCase() !== 'GET') { return done(new Error('Only GET methods are supported at the moment')); } - let provider = new oci.SimpleAuthenticationDetailsProvider( - auth.get('tenancy'), auth.get('user'), auth.get('fingerprint'), auth.get('private_key') - ), - signer = new oci.DefaultRequestSigner(provider), - ociRequest = convertPostmanRequestToOCIRequest(request); - - signer.signHttpRequest(ociRequest).then(function () { - request.headers.add({ - key: 'authorization', - value: ociRequest.headers.get('authorization'), - system: true - }); - - done(null); + + console.log('yo 1'); + const ociRequest = convertPostmanRequestToOCIRequest(request); + console.log('yo 2'); + // Host header + if (!ociRequest.headers.has('host')) { + const url = UrlParser.parse(ociRequest.uri); + console.log('yo 3'); + if (url.host) { + ociRequest.headers.set('host', url.host); + } + else { + throw new Error('Cannot parse host from url'); + } + } + + // Date header + if (!ociRequest.headers.has('x-date')) { + ociRequest.headers.set('x-date', new Date().toUTCString()); } - ).catch(function (err) { - done(new Error('Unable to sign')); + console.log('request headers 2: ', ociRequest.headers); + + var headersToSign = ['x-date', '(request-target)', 'host']; + + const keyId = auth.get('tenancy') + '/' + auth.get('user') + '/' + auth.get('fingerprint'), + privateKeyBuffer = sshpk.parsePrivateKey(auth.get('private_key'), 'auto').toBuffer('pem', {}); + + console.log('keyId: ', keyId); + httpSignature.sign(new SignerRequest(ociRequest.method, ociRequest.uri, ociRequest.headers), { + key: privateKeyBuffer, + keyId: keyId, + headers: headersToSign }); + const authorizationHeader = ociRequest.headers.get('Authorization'); + console.log('result: ', authorizationHeader); + + return done(); } }; diff --git a/package-lock.json b/package-lock.json index 416081729..809c3b1b8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -234,11 +234,6 @@ "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", "dev": true }, - "@types/isomorphic-fetch": { - "version": "0.0.35", - "resolved": "https://registry.npmjs.org/@types/isomorphic-fetch/-/isomorphic-fetch-0.0.35.tgz", - "integrity": "sha512-DaZNUvLDCAnCTjgwxgiL1eQdxIKEpNLOlTNtAgnZc50bG2copGhRrFN9/PxPBuJe+tZVLCbQ7ls0xveXVRPkvw==" - }, "JSONStream": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", @@ -1018,11 +1013,6 @@ "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", "dev": true }, - "buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" - }, "buffer-fill": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", @@ -2144,14 +2134,6 @@ "safer-buffer": "^2.1.0" } }, - "ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "requires": { - "safe-buffer": "^5.0.1" - } - }, "editorconfig": { "version": "0.15.3", "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz", @@ -2205,24 +2187,6 @@ "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", "dev": true }, - "encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "requires": { - "iconv-lite": "^0.6.2" - }, - "dependencies": { - "iconv-lite": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", - "integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - } - } - } - }, "engine.io": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz", @@ -2366,11 +2330,6 @@ "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", "dev": true }, - "es6-promise": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.6.tgz", - "integrity": "sha512-aRVgGdnmW2OiySVPUC9e6m+plolMAJKjZnQlCwNSuK5yQ0JN61DZSO1X1Ufd1foqWRAlig0rhduTCHe7sVtK5Q==" - }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -3522,9 +3481,9 @@ "integrity": "sha1-qVPKZwB4Zp3eFCzomUAbnW6F07Q=" }, "http-signature": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.5.tgz", - "integrity": "sha512-NwoTQYSJoFt34jSBbwzDHDofoA61NGXzu6wXh95o1Ry62EnmKjXb/nR/RknLeZ3G/uGwrlKNY2z7uPt+Cdl7Tw==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.1.tgz", + "integrity": "sha512-Y29YKEc8MQsjch/VzkUVJ+2MXd9WcR42fK5u36CZf4G8bXw2DXMTWuESiB0R6m59JAWxlPPw5/Fri/t/AyyueA==", "requires": { "assert-plus": "^1.0.0", "jsprim": "^1.2.2", @@ -3879,7 +3838,8 @@ "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true }, "is-symbol": { "version": "1.0.2", @@ -3928,15 +3888,6 @@ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true }, - "isomorphic-fetch": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", - "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", - "requires": { - "node-fetch": "^1.0.1", - "whatwg-fetch": ">=0.10.0" - } - }, "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", @@ -4237,23 +4188,6 @@ "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", "dev": true }, - "jsonwebtoken": { - "version": "8.5.1", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", - "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", - "requires": { - "jws": "^3.2.2", - "lodash.includes": "^4.3.0", - "lodash.isboolean": "^3.0.3", - "lodash.isinteger": "^4.0.4", - "lodash.isnumber": "^3.0.3", - "lodash.isplainobject": "^4.0.6", - "lodash.isstring": "^4.0.1", - "lodash.once": "^4.0.0", - "ms": "^2.1.1", - "semver": "^5.6.0" - } - }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -4265,36 +4199,12 @@ "verror": "1.10.0" } }, - "jssha": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/jssha/-/jssha-2.4.1.tgz", - "integrity": "sha512-77DN1YurYgh+7FPCTJ2CQ6hVDHgIWiHxm4Y5/mAdnpETKYagX22pVWMz4xfKF5fcpNfMaztgVj+/B1bt2k23Eg==" - }, "just-extend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.0.2.tgz", "integrity": "sha512-FrLwOgm+iXrPV+5zDU6Jqu4gCRXbWEQg2O3SKONsWE4w7AXFRkryS53bpWdaL9cNol+AmR3AEYz6kn+o0fCPnw==", "dev": true }, - "jwa": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", - "requires": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", - "requires": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, "karma": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/karma/-/karma-3.1.4.tgz", @@ -4764,26 +4674,6 @@ "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", "dev": true }, - "lodash.includes": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", - "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" - }, - "lodash.isboolean": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", - "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" - }, - "lodash.isinteger": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", - "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" - }, - "lodash.isnumber": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", - "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=" - }, "lodash.isplainobject": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", @@ -4811,11 +4701,6 @@ "integrity": "sha1-brGa5aHuHdnfC5aeZs4Lf6MLXmA=", "dev": true }, - "lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" - }, "lodash.padend": { "version": "4.6.1", "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz", @@ -5404,7 +5289,8 @@ "ms": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true }, "mute-stream": { "version": "0.0.7", @@ -5499,15 +5385,6 @@ } } }, - "node-fetch": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", - "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", - "requires": { - "encoding": "^0.1.11", - "is-stream": "^1.0.1" - } - }, "node-oauth1": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/node-oauth1/-/node-oauth1-1.3.0.tgz", @@ -5523,17 +5400,6 @@ "resolve": "^1.10.0", "semver": "2 || 3 || 4 || 5", "validate-npm-package-license": "^3.0.1" - }, - "dependencies": { - "resolve": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.13.1.tgz", - "integrity": "sha512-CxqObCX8K8YtAhOBRg+lrcdn+LK+WYOS8tSjqSFbjtrI5PnS63QPhZl4+yKfrU9tdsbMu9Anr/amegT87M9Z6w==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - } } }, "normalize-path": { @@ -5780,39 +5646,6 @@ "isobject": "^3.0.1" } }, - "oci-common": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/oci-common/-/oci-common-1.8.0.tgz", - "integrity": "sha512-vcLJ6fxCRPiipRqI8n7emcYORiDNt8R1PQFVOP63oU+al7Nh5NT//AGuu+0NELr+iO74X2qNQEReU8yvSZFv4Q==", - "requires": { - "@types/isomorphic-fetch": "0.0.35", - "es6-promise": "4.2.6", - "http-signature": "1.3.1", - "isomorphic-fetch": "2.2.1", - "jsonwebtoken": "8.5.1", - "jssha": "2.4.1", - "opossum": "5.0.1", - "sshpk": "1.16.1", - "uuid": "3.3.3" - }, - "dependencies": { - "http-signature": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.1.tgz", - "integrity": "sha512-Y29YKEc8MQsjch/VzkUVJ+2MXd9WcR42fK5u36CZf4G8bXw2DXMTWuESiB0R6m59JAWxlPPw5/Fri/t/AyyueA==", - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.14.1" - } - }, - "uuid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", - "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==" - } - } - }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -5840,11 +5673,6 @@ "mimic-fn": "^1.0.0" } }, - "opossum": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/opossum/-/opossum-5.0.1.tgz", - "integrity": "sha512-iUDUQmFl3RanaBVLMDTZ6WtXj/Hk84pwJ5JWoJaQd1lXGifdApHhszI3biZvdBDdpTERCmB6x+7+uNvzhzVZIg==" - }, "optimist": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", @@ -6821,7 +6649,8 @@ "semver": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", - "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==" + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", + "dev": true }, "send": { "version": "0.17.1", @@ -8728,11 +8557,6 @@ "integrity": "sha512-kudCA8PXVQfrqv2mFTG72vDBRi8BKWxGgFLwPpzHcpZnSwZk93WMwUDVcLHWNsnm+Y0AC4Vb6MUNRgaHfyV2DQ==", "dev": true }, - "whatwg-fetch": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.5.0.tgz", - "integrity": "sha512-jXkLtsR42xhXg7akoDKvKWE40eJeI+2KZqcp2h3NsOrRnDvtWX36KcKl30dy+hxECivdk2BVUHVNrPtoMBUx6A==" - }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", diff --git a/package.json b/package.json index d7b96f98f..6f63cd9c5 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,6 @@ "dependencies": { "async": "2.6.3", "aws4": "1.10.1", - "oci-common": "1.8.0", "eventemitter3": "4.0.7", "handlebars": "4.7.6", "http-reasons": "0.1.0", @@ -53,7 +52,8 @@ "resolve-from": "5.0.0", "serialised-error": "1.1.3", "tough-cookie": "3.0.1", - "uuid": "3.4.0" + "uuid": "3.4.0", + "sshpk": "1.16.1" }, "devDependencies": { "@postman/shipit": "0.2.0", diff --git a/test/fixtures/auth-requests.json b/test/fixtures/auth-requests.json index 9c6e940b1..44823971e 100644 --- a/test/fixtures/auth-requests.json +++ b/test/fixtures/auth-requests.json @@ -247,5 +247,18 @@ "raw": "Hello World!!" }, "description": "" + }, + "oci": { + "auth": { + "type": "oci", + "oci": { + "tenancy": "ocid1.tenancy.oc1..aaaaaaaa5h4h55rwzjwrufcfaqp4h5gxcqv65ozk7rytrvcltwujfj45g25a", + "user": "ocid1.user.oc1..aaaaaaaag4r7qnp7q5dtnklgl4xzjlawksq3ql3o5so6wajhxtgry3fsvfga", + "fingerprint": "42:34:8b:df:0a:9c:b0:c8:b6:ac:7a:c2:ce:7e:45:85", + "private_key": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEAvOxs9ybstMcalgCEbNIHeNh7oqVBLAC0+bhi7KEr2xYFSQws\nu4MdPXqSCTQu1/4fsMoCbRLZMRmC8YonjjhdRyVFZrAkE5Q9WfF3N40s/GVK8Myb\nWxBS5hZnc4td/d+OoGLE5aKNwaFNoTn7iDCU1JfG+d4l7Z5twzHESs3XnzNSeRms\n/MAFk3zdjlpOm9pbafFqFoim6Be8dRXtWU0xN5VRHD3txisQJlcLVNMm6IK9UWUg\nJzmn8d5ASwvU75/nJKc8DLoQ0cVeYaIhXWGME6ApXyb62zKmccPpkRzRZSJYPeUo\nLK2JC/w/os1NAi0mTGb/KqOzd7BJf1RO0SQYHwIDAQABAoIBAGRS4KJ2hyiQuquB\nZtEqz1D7FNyQCQXG8lPR+KZUCCf1j6T01CRXQgXNuxMsJNwKVOXawGMPqUqLk5+U\nj+DUSaRoRGx9iQrko5fJxFc5nvQBDkTFQpKfHoaUyybukWEpgGHnUUvogIKcl87Q\nLaRqt/4VA1LZByciBIOtP+HBYYlmGlg6UDeOFTku9nFbraz8FlzqLAy7xSUB3aDs\n1JeDwR9PBQsRG72GQkJR/EmPbD2Y/r+zmZP25/97pouO/ji9DJwDcVc1qFpn4JKf\nLABBUEwfWEIWa4cefbDi0dCzVKxrS/RU9EYB6HtMklcy3qyxbdcLmFY8qgsxjG8K\nw2iD2iECgYEA+AtmXff5lnSZq3CJhcxBpi+MuCByWH7gB2/G50XSduRmW+lzI6iv\n+r8ADEI87+KBIju++qNvj886N9H1sm+k6j3nEE51i2nwwKB79Xzu0J23+XMSCV0D\nYb6bvNogGCOhKslQNC51ZvgsZlTu6F8/EkPlboEL8E2h4eYwx3L6UbcCgYEAwvub\nB+rhUk4+TwXVnfNZEcmQiz90yU7CI/TjDrHVq+ZJIKRHILB+7Mt7Mpi+7Ie2Cx/f\nA1Alv8I44wmLhZX63Du9hwoz3t4Y0+AiT/RMp3EkmxKIkPFZNKsmY659dNzROMG9\nEVYEmBYode17mrSc4UJi8I4iHCv1A83BC3DhzNkCgYBSE8Od2I5YQOEQn76B7aLT\nkOxpiSMNMX6EN3KD2NDZ0p4kT81vwUPqHwWvCMQNRNAiOc7qNOaXmaTUD7/TeaoC\ncNViyfOPXFD0DKa4Bs0nbukPvAn92y9hSqdSCIOSOUf9VnwZqD3lAr3+ZqBfeBTw\nwFLNDBqdO7MTgw4lEWDPZQKBgQCIm3c2yN0sqR0GiHPtwfz5dVsL9F2CXOewAXbD\naNznHuTFNdOPl5iVlsqt3E6HsV1d1eqNi62m+BCbIKjb4wRrIH/dCMzmrHyAlVv0\n4JiEB8U50HZV9oIlYHP5Ctti8QK03Sf16Wo2k++tD8G11izDtZtUJoDHdBSpoZJK\nzb+loQKBgQC0/VewDbcRW5FymBPJiEnrTtpHk40x14pNfRbRrNDIx/jIx/gnqwyI\n6ud7uJkK+LAHw+r2HjHtSMVE9I54zr+QG8fAe8alJQ3mSP1tlpLbMaMb7LpomKo/\nfVVz1laGP3tcpXDEp80hbrDxO7aOexUgCFKHrYTAgVCm8Eqzz8HdsQ==\n-----END RSA PRIVATE KEY-----" + } + }, + "url": "https://postman-echo.com/auth/yolo", + "method": "GET" } } diff --git a/test/unit/auth-handlers.test.js b/test/unit/auth-handlers.test.js index ff983960c..a5392fe36 100644 --- a/test/unit/auth-handlers.test.js +++ b/test/unit/auth-handlers.test.js @@ -2613,4 +2613,25 @@ describe('Auth Handler:', function () { }); }); }); + + describe('oci', function () { + it('should add the Auth header', function (done) { + var request = new Request(rawRequests.oci), + auth = request.auth, + authInterface = createAuthInterface(auth), + handler = AuthLoader.getHandler(auth.type), + headers; + + handler.sign(authInterface, request, function () { + headers = request.getHeaders({ + ignoreCase: true + }); + console.log('In test case, back from handler.sign'); + console.log(headers.authorization); + // Ensure that the required headers have been added. + // expect(headers).to.have.property('authorization'); + done(); + }); + }); + }); }); From 652bbc9176f5e0c2617133f14a6b5d82fec66608 Mon Sep 17 00:00:00 2001 From: Ankit Arora Date: Mon, 7 Dec 2020 11:44:35 +0530 Subject: [PATCH 07/21] Add headers to postman request object --- lib/authorizer/oci-v1.js | 94 +++++++++++++++++++++------------ test/unit/auth-handlers.test.js | 12 +++-- 2 files changed, 69 insertions(+), 37 deletions(-) diff --git a/lib/authorizer/oci-v1.js b/lib/authorizer/oci-v1.js index 330c6cae9..fdf956e43 100644 --- a/lib/authorizer/oci-v1.js +++ b/lib/authorizer/oci-v1.js @@ -79,7 +79,8 @@ var sshpk = require('sshpk'), convertPostmanRequestToOCIRequest = function (request) { // need to convert request from `module:postman-collection.Request` // to oci-common/lib/http-request.d.ts.HttpRequest - console.log('converting object request.url=', request.url.path) + console.log('converting object request.url=', request.url.path); + return { uri: request.url.getRaw(), headers: convertToDomHeadersObject(request.headers), @@ -104,6 +105,41 @@ class SignerRequest { } } +const processRequestForOci = function (ociRequest, auth) { + // Host header + if (!ociRequest.headers.has('host')) { + const url = UrlParser.parse(ociRequest.uri); + + if (url.host) { + ociRequest.headers.set('host', url.host); + } + else { + throw new Error('Cannot parse host from url'); + } + } + + // Date header + if (!ociRequest.headers.has('x-date')) { + ociRequest.headers.set('x-date', new Date().toUTCString()); + } + + var headersToSign = ['x-date', '(request-target)', 'host'], + keyId = auth.get('tenancy') + '/' + auth.get('user') + '/' + auth.get('fingerprint'), + privateKeyBuffer = sshpk.parsePrivateKey(auth.get('private_key'), 'auto').toBuffer('pem', {}); + + httpSignature.sign(new SignerRequest(ociRequest.method, ociRequest.uri, ociRequest.headers), { + key: privateKeyBuffer, + keyId: keyId, + headers: headersToSign + }); + const authorizationHeader = ociRequest.headers.get('Authorization'); + + ociRequest.headers.set('authorization', authorizationHeader.replace('Signature ', 'Signature version="1",')); + console.log('result: ', authorizationHeader); + + return ociRequest; +}; + /** * @implements {AuthHandlerInterface} */ @@ -121,6 +157,14 @@ module.exports = { { property: 'authorization', type: 'header' + }, + { + property: 'host', + type: 'header' + }, + { + property: 'x-date', + type: 'header' } ] }, @@ -184,40 +228,24 @@ module.exports = { return done(new Error('Only GET methods are supported at the moment')); } - console.log('yo 1'); - const ociRequest = convertPostmanRequestToOCIRequest(request); - console.log('yo 2'); - // Host header - if (!ociRequest.headers.has('host')) { - const url = UrlParser.parse(ociRequest.uri); - console.log('yo 3'); - if (url.host) { - ociRequest.headers.set('host', url.host); - } - else { - throw new Error('Cannot parse host from url'); - } - } + const ociRequest = convertPostmanRequestToOCIRequest(request), + signedOciRequest = processRequestForOci(ociRequest, auth); - // Date header - if (!ociRequest.headers.has('x-date')) { - ociRequest.headers.set('x-date', new Date().toUTCString()); - } - console.log('request headers 2: ', ociRequest.headers); - - var headersToSign = ['x-date', '(request-target)', 'host']; - - const keyId = auth.get('tenancy') + '/' + auth.get('user') + '/' + auth.get('fingerprint'), - privateKeyBuffer = sshpk.parsePrivateKey(auth.get('private_key'), 'auto').toBuffer('pem', {}); - - console.log('keyId: ', keyId); - httpSignature.sign(new SignerRequest(ociRequest.method, ociRequest.uri, ociRequest.headers), { - key: privateKeyBuffer, - keyId: keyId, - headers: headersToSign + request.addHeader({ + key: 'authorization', + value: signedOciRequest.headers.get('authorization'), + system: true + }); + request.addHeader({ + key: 'x-date', + value: signedOciRequest.headers.get('x-date'), + system: true + }); + request.addHeader({ + key: 'host', + value: signedOciRequest.headers.get('host'), + system: true }); - const authorizationHeader = ociRequest.headers.get('Authorization'); - console.log('result: ', authorizationHeader); return done(); } diff --git a/test/unit/auth-handlers.test.js b/test/unit/auth-handlers.test.js index a5392fe36..21849c0f6 100644 --- a/test/unit/auth-handlers.test.js +++ b/test/unit/auth-handlers.test.js @@ -2623,13 +2623,17 @@ describe('Auth Handler:', function () { headers; handler.sign(authInterface, request, function () { - headers = request.getHeaders({ - ignoreCase: true - }); + // headers = request.getHeaders({ + // ignoreCase: true + // }); console.log('In test case, back from handler.sign'); - console.log(headers.authorization); + // console.log(headers.authorization); // Ensure that the required headers have been added. // expect(headers).to.have.property('authorization'); + console.log('printing all headers') + request.headers.all().forEach(function (each) { + console.log(each.key, each.value); + }); done(); }); }); From 3d21a3d1ae7d1f1ac36c1e2424a8c4b8f27a1a31 Mon Sep 17 00:00:00 2001 From: Ankit Arora Date: Mon, 7 Dec 2020 13:26:10 +0530 Subject: [PATCH 08/21] GET Request working via test case + postman! --- lib/authorizer/oci-v1.js | 6 +- package-lock.json | 167 +++++++++++++++++++++++++++++-- test/fixtures/auth-requests.json | 4 +- test/unit/auth-handlers.test.js | 7 +- 4 files changed, 171 insertions(+), 13 deletions(-) diff --git a/lib/authorizer/oci-v1.js b/lib/authorizer/oci-v1.js index fdf956e43..75ab3f680 100644 --- a/lib/authorizer/oci-v1.js +++ b/lib/authorizer/oci-v1.js @@ -79,8 +79,6 @@ var sshpk = require('sshpk'), convertPostmanRequestToOCIRequest = function (request) { // need to convert request from `module:postman-collection.Request` // to oci-common/lib/http-request.d.ts.HttpRequest - console.log('converting object request.url=', request.url.path); - return { uri: request.url.getRaw(), headers: convertToDomHeadersObject(request.headers), @@ -136,7 +134,7 @@ const processRequestForOci = function (ociRequest, auth) { ociRequest.headers.set('authorization', authorizationHeader.replace('Signature ', 'Signature version="1",')); console.log('result: ', authorizationHeader); - + console.log('allHeaders', ociRequest.headers); return ociRequest; }; @@ -230,7 +228,7 @@ module.exports = { const ociRequest = convertPostmanRequestToOCIRequest(request), signedOciRequest = processRequestForOci(ociRequest, auth); - + console.log(signedOciRequest.body); request.addHeader({ key: 'authorization', value: signedOciRequest.headers.get('authorization'), diff --git a/package-lock.json b/package-lock.json index 809c3b1b8..4afad69c1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -234,6 +234,11 @@ "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", "dev": true }, + "@types/isomorphic-fetch": { + "version": "0.0.35", + "resolved": "https://registry.npmjs.org/@types/isomorphic-fetch/-/isomorphic-fetch-0.0.35.tgz", + "integrity": "sha512-DaZNUvLDCAnCTjgwxgiL1eQdxIKEpNLOlTNtAgnZc50bG2copGhRrFN9/PxPBuJe+tZVLCbQ7ls0xveXVRPkvw==" + }, "JSONStream": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", @@ -1013,6 +1018,11 @@ "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", "dev": true }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" + }, "buffer-fill": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", @@ -2134,6 +2144,14 @@ "safer-buffer": "^2.1.0" } }, + "ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "requires": { + "safe-buffer": "^5.0.1" + } + }, "editorconfig": { "version": "0.15.3", "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz", @@ -2187,6 +2205,24 @@ "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", "dev": true }, + "encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "requires": { + "iconv-lite": "^0.6.2" + }, + "dependencies": { + "iconv-lite": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", + "integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + } + } + }, "engine.io": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz", @@ -2330,6 +2366,11 @@ "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", "dev": true }, + "es6-promise": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.6.tgz", + "integrity": "sha512-aRVgGdnmW2OiySVPUC9e6m+plolMAJKjZnQlCwNSuK5yQ0JN61DZSO1X1Ufd1foqWRAlig0rhduTCHe7sVtK5Q==" + }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -3838,8 +3879,7 @@ "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" }, "is-symbol": { "version": "1.0.2", @@ -3888,6 +3928,15 @@ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true }, + "isomorphic-fetch": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", + "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", + "requires": { + "node-fetch": "^1.0.1", + "whatwg-fetch": ">=0.10.0" + } + }, "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", @@ -4188,6 +4237,23 @@ "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", "dev": true }, + "jsonwebtoken": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", + "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", + "requires": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^5.6.0" + } + }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -4199,12 +4265,36 @@ "verror": "1.10.0" } }, + "jssha": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/jssha/-/jssha-2.4.1.tgz", + "integrity": "sha512-77DN1YurYgh+7FPCTJ2CQ6hVDHgIWiHxm4Y5/mAdnpETKYagX22pVWMz4xfKF5fcpNfMaztgVj+/B1bt2k23Eg==" + }, "just-extend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.0.2.tgz", "integrity": "sha512-FrLwOgm+iXrPV+5zDU6Jqu4gCRXbWEQg2O3SKONsWE4w7AXFRkryS53bpWdaL9cNol+AmR3AEYz6kn+o0fCPnw==", "dev": true }, + "jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "requires": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, "karma": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/karma/-/karma-3.1.4.tgz", @@ -4674,6 +4764,26 @@ "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", "dev": true }, + "lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" + }, + "lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" + }, + "lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" + }, + "lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=" + }, "lodash.isplainobject": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", @@ -4701,6 +4811,11 @@ "integrity": "sha1-brGa5aHuHdnfC5aeZs4Lf6MLXmA=", "dev": true }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" + }, "lodash.padend": { "version": "4.6.1", "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz", @@ -5289,8 +5404,7 @@ "ms": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" }, "mute-stream": { "version": "0.0.7", @@ -5385,6 +5499,15 @@ } } }, + "node-fetch": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", + "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", + "requires": { + "encoding": "^0.1.11", + "is-stream": "^1.0.1" + } + }, "node-oauth1": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/node-oauth1/-/node-oauth1-1.3.0.tgz", @@ -5646,6 +5769,29 @@ "isobject": "^3.0.1" } }, + "oci-common": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/oci-common/-/oci-common-1.9.0.tgz", + "integrity": "sha512-+gJloBEJOKBfOiPoaR/TVsT2mi/s89iOg147K3uyOHanyIHC17B1LOuVylDhFW68TTup2J8QxLBNZiS9889Bsg==", + "requires": { + "@types/isomorphic-fetch": "0.0.35", + "es6-promise": "4.2.6", + "http-signature": "1.3.1", + "isomorphic-fetch": "2.2.1", + "jsonwebtoken": "8.5.1", + "jssha": "2.4.1", + "opossum": "5.0.1", + "sshpk": "1.16.1", + "uuid": "3.3.3" + }, + "dependencies": { + "uuid": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", + "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==" + } + } + }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -5673,6 +5819,11 @@ "mimic-fn": "^1.0.0" } }, + "opossum": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/opossum/-/opossum-5.0.1.tgz", + "integrity": "sha512-iUDUQmFl3RanaBVLMDTZ6WtXj/Hk84pwJ5JWoJaQd1lXGifdApHhszI3biZvdBDdpTERCmB6x+7+uNvzhzVZIg==" + }, "optimist": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", @@ -6649,8 +6800,7 @@ "semver": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", - "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", - "dev": true + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==" }, "send": { "version": "0.17.1", @@ -8557,6 +8707,11 @@ "integrity": "sha512-kudCA8PXVQfrqv2mFTG72vDBRi8BKWxGgFLwPpzHcpZnSwZk93WMwUDVcLHWNsnm+Y0AC4Vb6MUNRgaHfyV2DQ==", "dev": true }, + "whatwg-fetch": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.5.0.tgz", + "integrity": "sha512-jXkLtsR42xhXg7akoDKvKWE40eJeI+2KZqcp2h3NsOrRnDvtWX36KcKl30dy+hxECivdk2BVUHVNrPtoMBUx6A==" + }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", diff --git a/test/fixtures/auth-requests.json b/test/fixtures/auth-requests.json index 44823971e..f46fe927c 100644 --- a/test/fixtures/auth-requests.json +++ b/test/fixtures/auth-requests.json @@ -253,12 +253,12 @@ "type": "oci", "oci": { "tenancy": "ocid1.tenancy.oc1..aaaaaaaa5h4h55rwzjwrufcfaqp4h5gxcqv65ozk7rytrvcltwujfj45g25a", - "user": "ocid1.user.oc1..aaaaaaaag4r7qnp7q5dtnklgl4xzjlawksq3ql3o5so6wajhxtgry3fsvfga", + "user": "ocid1.user.oc1..aaaaaaaax4esyzwnhlxdb6h5dfopzkuw5kujtffz3y4yvczqnjwlpbnk7q7q", "fingerprint": "42:34:8b:df:0a:9c:b0:c8:b6:ac:7a:c2:ce:7e:45:85", "private_key": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEAvOxs9ybstMcalgCEbNIHeNh7oqVBLAC0+bhi7KEr2xYFSQws\nu4MdPXqSCTQu1/4fsMoCbRLZMRmC8YonjjhdRyVFZrAkE5Q9WfF3N40s/GVK8Myb\nWxBS5hZnc4td/d+OoGLE5aKNwaFNoTn7iDCU1JfG+d4l7Z5twzHESs3XnzNSeRms\n/MAFk3zdjlpOm9pbafFqFoim6Be8dRXtWU0xN5VRHD3txisQJlcLVNMm6IK9UWUg\nJzmn8d5ASwvU75/nJKc8DLoQ0cVeYaIhXWGME6ApXyb62zKmccPpkRzRZSJYPeUo\nLK2JC/w/os1NAi0mTGb/KqOzd7BJf1RO0SQYHwIDAQABAoIBAGRS4KJ2hyiQuquB\nZtEqz1D7FNyQCQXG8lPR+KZUCCf1j6T01CRXQgXNuxMsJNwKVOXawGMPqUqLk5+U\nj+DUSaRoRGx9iQrko5fJxFc5nvQBDkTFQpKfHoaUyybukWEpgGHnUUvogIKcl87Q\nLaRqt/4VA1LZByciBIOtP+HBYYlmGlg6UDeOFTku9nFbraz8FlzqLAy7xSUB3aDs\n1JeDwR9PBQsRG72GQkJR/EmPbD2Y/r+zmZP25/97pouO/ji9DJwDcVc1qFpn4JKf\nLABBUEwfWEIWa4cefbDi0dCzVKxrS/RU9EYB6HtMklcy3qyxbdcLmFY8qgsxjG8K\nw2iD2iECgYEA+AtmXff5lnSZq3CJhcxBpi+MuCByWH7gB2/G50XSduRmW+lzI6iv\n+r8ADEI87+KBIju++qNvj886N9H1sm+k6j3nEE51i2nwwKB79Xzu0J23+XMSCV0D\nYb6bvNogGCOhKslQNC51ZvgsZlTu6F8/EkPlboEL8E2h4eYwx3L6UbcCgYEAwvub\nB+rhUk4+TwXVnfNZEcmQiz90yU7CI/TjDrHVq+ZJIKRHILB+7Mt7Mpi+7Ie2Cx/f\nA1Alv8I44wmLhZX63Du9hwoz3t4Y0+AiT/RMp3EkmxKIkPFZNKsmY659dNzROMG9\nEVYEmBYode17mrSc4UJi8I4iHCv1A83BC3DhzNkCgYBSE8Od2I5YQOEQn76B7aLT\nkOxpiSMNMX6EN3KD2NDZ0p4kT81vwUPqHwWvCMQNRNAiOc7qNOaXmaTUD7/TeaoC\ncNViyfOPXFD0DKa4Bs0nbukPvAn92y9hSqdSCIOSOUf9VnwZqD3lAr3+ZqBfeBTw\nwFLNDBqdO7MTgw4lEWDPZQKBgQCIm3c2yN0sqR0GiHPtwfz5dVsL9F2CXOewAXbD\naNznHuTFNdOPl5iVlsqt3E6HsV1d1eqNi62m+BCbIKjb4wRrIH/dCMzmrHyAlVv0\n4JiEB8U50HZV9oIlYHP5Ctti8QK03Sf16Wo2k++tD8G11izDtZtUJoDHdBSpoZJK\nzb+loQKBgQC0/VewDbcRW5FymBPJiEnrTtpHk40x14pNfRbRrNDIx/jIx/gnqwyI\n6ud7uJkK+LAHw+r2HjHtSMVE9I54zr+QG8fAe8alJQ3mSP1tlpLbMaMb7LpomKo/\nfVVz1laGP3tcpXDEp80hbrDxO7aOexUgCFKHrYTAgVCm8Eqzz8HdsQ==\n-----END RSA PRIVATE KEY-----" } }, - "url": "https://postman-echo.com/auth/yolo", + "url": "https://identity.ap-hyderabad-1.oraclecloud.com/20160918/users/ocid1.user.oc1..aaaaaaaax4esyzwnhlxdb6h5dfopzkuw5kujtffz3y4yvczqnjwlpbnk7q7q", "method": "GET" } } diff --git a/test/unit/auth-handlers.test.js b/test/unit/auth-handlers.test.js index 21849c0f6..eaf590282 100644 --- a/test/unit/auth-handlers.test.js +++ b/test/unit/auth-handlers.test.js @@ -2630,11 +2630,16 @@ describe('Auth Handler:', function () { // console.log(headers.authorization); // Ensure that the required headers have been added. // expect(headers).to.have.property('authorization'); - console.log('printing all headers') + console.log('printing all headers'); + const rawHeaders = {}; + request.headers.all().forEach(function (each) { console.log(each.key, each.value); + rawHeaders[each.key] = each.value; }); + console.log(request.headers.get('authorization')) done(); + }); }); }); From 30426a0282cb6fcaade6a3574094f6eb0a77da48 Mon Sep 17 00:00:00 2001 From: Ankit Arora Date: Mon, 7 Dec 2020 18:48:54 +0530 Subject: [PATCH 09/21] Add code to handle request body (only raw) --- lib/authorizer/oci-v1.js | 181 +++++++++++++++++++++++++++------------ package.json | 3 +- 2 files changed, 127 insertions(+), 57 deletions(-) diff --git a/lib/authorizer/oci-v1.js b/lib/authorizer/oci-v1.js index 75ab3f680..f03485df9 100644 --- a/lib/authorizer/oci-v1.js +++ b/lib/authorizer/oci-v1.js @@ -4,7 +4,19 @@ * Implements the Oracle Cloud Infrastructure Signature v1 authentication method. * Specification document: https://docs.cloud.oracle.com/en-us/iaas/Content/API/Concepts/signingrequests.htm */ +var sshpk = require('sshpk'), + UrlParser = require('url'), + _ = require('lodash'), + httpSignature = require('http-signature'), + jssha = require('jssha'), + RequestBody = require('postman-collection').RequestBody, + bodyBuilder = require('../requester/core-body-builder'); + +const HEADER_CONTENT_SHA = 'x-content-sha256', + HEADER_CONTENT_LEN = 'content-length', + HEADER_CONTENT_TYPE = 'content-type', + EMPTY_SHA = '47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU='; // -------------------- HEADERS POLYFILL --------------------------- function Headers (values) { @@ -61,82 +73,123 @@ Headers.prototype.values = function (name, value) { return result; }; +class SignerRequest { + constructor (method, url, headers) { + this.headers = headers; + this.method = method; + this.path = UrlParser.parse(url).path; + } + + getHeader (name) { + return this.headers.get(name); + } + + setHeader (name, value) { + this.headers.set(name, value); + } +} // ------------------------------------------------------------ -var sshpk = require('sshpk'), - UrlParser = require('url'), - httpSignature = require('http-signature'), +// eslint-disable-next-line one-var +var minimumHeadersToSign = ['x-date', '(request-target)', 'host'], + methodsThatRequireExtraHeaders = ['POST', 'PUT', 'PATCH'], convertToDomHeadersObject = function (postmanHeaders) { let rawHeaders = {}; postmanHeaders.all().forEach(function (each) { - rawHeaders[each.key] = each.value; + rawHeaders[each.key.lowercase()] = each.value; }); return new Headers(rawHeaders); }, + getBodyString = function (body) { + if (body.mode === RequestBody.MODES.raw) { + return bodyBuilder.raw(body.raw).body; + } + console.log('unable to get body string'); + throw new Error('Unable to get body string!'); + }, convertPostmanRequestToOCIRequest = function (request) { // need to convert request from `module:postman-collection.Request` // to oci-common/lib/http-request.d.ts.HttpRequest return { uri: request.url.getRaw(), headers: convertToDomHeadersObject(request.headers), - method: request.method.toUpperCase() - // body: getRequestBodyStream(request.body) + method: request.method.toUpperCase(), + body: request.body }; - }; - -class SignerRequest { - constructor (method, url, headers) { - this.headers = headers; - this.method = method; - this.path = UrlParser.parse(url).path; - } - - getHeader (name) { - return this.headers.get(name); - } + }, + processRequestForOci = function (ociRequest, auth) { + // Host header + if (!ociRequest.headers.has('host')) { + const url = UrlParser.parse(ociRequest.uri); - setHeader (name, value) { - this.headers.set(name, value); - } -} + if (url.host) { + ociRequest.headers.set('host', url.host); + } + else { + throw new Error('Cannot parse host from url'); + } + } -const processRequestForOci = function (ociRequest, auth) { - // Host header - if (!ociRequest.headers.has('host')) { - const url = UrlParser.parse(ociRequest.uri); + // Date header + if (!ociRequest.headers.has('x-date')) { + ociRequest.headers.set('x-date', new Date().toUTCString()); + } + let headersToSign = [...minimumHeadersToSign]; - if (url.host) { - ociRequest.headers.set('host', url.host); + console.log('-----> before body if '); + if (ociRequest.body && _.includes(methodsThatRequireExtraHeaders, ociRequest.method)) { + if (!ociRequest.headers.has(HEADER_CONTENT_TYPE)) { + ociRequest.headers.set(HEADER_CONTENT_TYPE, 'application/json'); + } + let contentLen = 0; + const shaObj = new jssha('SHA-256', 'TEXT'), + requestBodyString = getBodyString(ociRequest.body); + + if (requestBodyString) { + shaObj.update(requestBodyString); + ociRequest.headers.set(HEADER_CONTENT_SHA, shaObj.getHash('B64')); + contentLen = Buffer.byteLength(requestBodyString, 'utf8'); + } + if (contentLen === 0) { + // if buffer is empty, it can only be an empty string payload + ociRequest.headers.set(HEADER_CONTENT_SHA, EMPTY_SHA); + } + if (!ociRequest.headers.has(HEADER_CONTENT_LEN)) { + ociRequest.headers.set(HEADER_CONTENT_LEN, `${contentLen}`); + } + headersToSign = headersToSign.concat(HEADER_CONTENT_TYPE, HEADER_CONTENT_LEN, HEADER_CONTENT_SHA); } else { - throw new Error('Cannot parse host from url'); + console.log('NO REQUEST BODY LOL'); } - } - // Date header - if (!ociRequest.headers.has('x-date')) { - ociRequest.headers.set('x-date', new Date().toUTCString()); - } - var headersToSign = ['x-date', '(request-target)', 'host'], - keyId = auth.get('tenancy') + '/' + auth.get('user') + '/' + auth.get('fingerprint'), - privateKeyBuffer = sshpk.parsePrivateKey(auth.get('private_key'), 'auto').toBuffer('pem', {}); - - httpSignature.sign(new SignerRequest(ociRequest.method, ociRequest.uri, ociRequest.headers), { - key: privateKeyBuffer, - keyId: keyId, - headers: headersToSign - }); - const authorizationHeader = ociRequest.headers.get('Authorization'); - - ociRequest.headers.set('authorization', authorizationHeader.replace('Signature ', 'Signature version="1",')); - console.log('result: ', authorizationHeader); - console.log('allHeaders', ociRequest.headers); - return ociRequest; -}; + var keyId = auth.get('tenancy') + '/' + auth.get('user') + '/' + auth.get('fingerprint'), + privateKeyBuffer = sshpk.parsePrivateKey(auth.get('private_key'), 'auto').toBuffer('pem', {}); + + console.log('Before httpSignature.sign', ociRequest.headers); + httpSignature.sign(new SignerRequest(ociRequest.method, ociRequest.uri, ociRequest.headers), { + key: privateKeyBuffer, + keyId: keyId, + headers: headersToSign + }); + + // NOTE: OCI needs 'authorization' but our version of httpSignature puts signature in 'Authorizaiton' + const authorizationHeader = ociRequest.headers.get('Authorization'); + + ociRequest.headers.set('authorization', authorizationHeader.replace('Signature ', 'Signature version="1",')); + ociRequest.headers.delete('Authorization'); + + + console.log('result: ', authorizationHeader); + console.log('allHeaders', ociRequest.headers); + + return ociRequest; + }; + /** * @implements {AuthHandlerInterface} @@ -219,15 +272,10 @@ module.exports = { console.log('OCI SIGN CALLED'); console.log('request headers 1: ', request.headers); // TODO: Remove restrictions on body and method - if (request.body && !request.body.isEmpty()) { - return done(new Error('Request body not supported')); - } - if (request.method.toUpperCase() !== 'GET') { - return done(new Error('Only GET methods are supported at the moment')); - } const ociRequest = convertPostmanRequestToOCIRequest(request), signedOciRequest = processRequestForOci(ociRequest, auth); + console.log(signedOciRequest.body); request.addHeader({ key: 'authorization', @@ -244,6 +292,27 @@ module.exports = { value: signedOciRequest.headers.get('host'), system: true }); + if (signedOciRequest.headers.get(HEADER_CONTENT_LEN)) { + request.addHeader({ + key: HEADER_CONTENT_LEN, + value: signedOciRequest.headers.get(HEADER_CONTENT_LEN), + system: true + }); + } + if (signedOciRequest.headers.get(HEADER_CONTENT_SHA)) { + request.addHeader({ + key: HEADER_CONTENT_SHA, + value: signedOciRequest.headers.get(HEADER_CONTENT_SHA), + system: true + }); + } + if (signedOciRequest.headers.get(HEADER_CONTENT_TYPE)) { + request.addHeader({ + key: HEADER_CONTENT_TYPE, + value: signedOciRequest.headers.get(HEADER_CONTENT_TYPE), + system: true + }); + } return done(); } diff --git a/package.json b/package.json index 6f63cd9c5..b69a5c019 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,8 @@ "serialised-error": "1.1.3", "tough-cookie": "3.0.1", "uuid": "3.4.0", - "sshpk": "1.16.1" + "sshpk": "1.16.1", + "http-signature": "1.3.1" }, "devDependencies": { "@postman/shipit": "0.2.0", From 9b7cbbe21256d69976c12ce203a2531be353f85e Mon Sep 17 00:00:00 2001 From: Ankit Arora Date: Mon, 7 Dec 2020 20:36:52 +0530 Subject: [PATCH 10/21] Code cleanup --- lib/authorizer/oci-v1.js | 156 +++++++++++++++------------------------ 1 file changed, 61 insertions(+), 95 deletions(-) diff --git a/lib/authorizer/oci-v1.js b/lib/authorizer/oci-v1.js index f03485df9..edb377cf9 100644 --- a/lib/authorizer/oci-v1.js +++ b/lib/authorizer/oci-v1.js @@ -16,7 +16,10 @@ var sshpk = require('sshpk'), const HEADER_CONTENT_SHA = 'x-content-sha256', HEADER_CONTENT_LEN = 'content-length', HEADER_CONTENT_TYPE = 'content-type', - EMPTY_SHA = '47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU='; + EMPTY_SHA = '47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=', + HEADER_AUTHORIZATION = 'authorization', + HEADER_DATE = 'x-date', + EXTRA_HEADER_METHODS = ['POST', 'PUT', 'PATCH']; // -------------------- HEADERS POLYFILL --------------------------- function Headers (values) { @@ -92,9 +95,7 @@ class SignerRequest { // ------------------------------------------------------------ // eslint-disable-next-line one-var -var minimumHeadersToSign = ['x-date', '(request-target)', 'host'], - methodsThatRequireExtraHeaders = ['POST', 'PUT', 'PATCH'], - convertToDomHeadersObject = function (postmanHeaders) { +var convertToDomHeadersObject = function (postmanHeaders) { let rawHeaders = {}; postmanHeaders.all().forEach(function (each) { @@ -107,26 +108,19 @@ var minimumHeadersToSign = ['x-date', '(request-target)', 'host'], if (body.mode === RequestBody.MODES.raw) { return bodyBuilder.raw(body.raw).body; } - console.log('unable to get body string'); - throw new Error('Unable to get body string!'); + throw new Error(`Request body mode ${body.mode} is not supported. Please use ${RequestBody.MODES.raw}`); }, - convertPostmanRequestToOCIRequest = function (request) { - // need to convert request from `module:postman-collection.Request` - // to oci-common/lib/http-request.d.ts.HttpRequest - return { - uri: request.url.getRaw(), - headers: convertToDomHeadersObject(request.headers), - method: request.method.toUpperCase(), - body: request.body - }; - }, - processRequestForOci = function (ociRequest, auth) { - // Host header - if (!ociRequest.headers.has('host')) { - const url = UrlParser.parse(ociRequest.uri); + processRequestForOci = function (request, auth) { + const rawRequestUri = request.url.getRaw(), + domHeadersObject = convertToDomHeadersObject(request.headers), + uppercaseMethod = request.method.toUpperCase(), + minimumHeadersToSign = ['x-date', '(request-target)', 'host'];; + + if (!domHeadersObject.has('host')) { + const url = UrlParser.parse(rawRequestUri); if (url.host) { - ociRequest.headers.set('host', url.host); + domHeadersObject.set('host', url.host); } else { throw new Error('Cannot parse host from url'); @@ -134,60 +128,52 @@ var minimumHeadersToSign = ['x-date', '(request-target)', 'host'], } // Date header - if (!ociRequest.headers.has('x-date')) { - ociRequest.headers.set('x-date', new Date().toUTCString()); + if (!domHeadersObject.has(HEADER_DATE)) { + domHeadersObject.set(HEADER_DATE, new Date().toUTCString()); } let headersToSign = [...minimumHeadersToSign]; - console.log('-----> before body if '); - if (ociRequest.body && _.includes(methodsThatRequireExtraHeaders, ociRequest.method)) { - if (!ociRequest.headers.has(HEADER_CONTENT_TYPE)) { - ociRequest.headers.set(HEADER_CONTENT_TYPE, 'application/json'); + if (request.body && _.includes(EXTRA_HEADER_METHODS, uppercaseMethod)) { + if (!domHeadersObject.has(HEADER_CONTENT_TYPE)) { + domHeadersObject.set(HEADER_CONTENT_TYPE, 'application/json'); } let contentLen = 0; const shaObj = new jssha('SHA-256', 'TEXT'), - requestBodyString = getBodyString(ociRequest.body); + requestBodyString = getBodyString(request.body); if (requestBodyString) { shaObj.update(requestBodyString); - ociRequest.headers.set(HEADER_CONTENT_SHA, shaObj.getHash('B64')); + domHeadersObject.set(HEADER_CONTENT_SHA, shaObj.getHash('B64')); contentLen = Buffer.byteLength(requestBodyString, 'utf8'); } if (contentLen === 0) { // if buffer is empty, it can only be an empty string payload - ociRequest.headers.set(HEADER_CONTENT_SHA, EMPTY_SHA); + domHeadersObject.set(HEADER_CONTENT_SHA, EMPTY_SHA); } - if (!ociRequest.headers.has(HEADER_CONTENT_LEN)) { - ociRequest.headers.set(HEADER_CONTENT_LEN, `${contentLen}`); + if (!domHeadersObject.has(HEADER_CONTENT_LEN)) { + domHeadersObject.set(HEADER_CONTENT_LEN, `${contentLen}`); } headersToSign = headersToSign.concat(HEADER_CONTENT_TYPE, HEADER_CONTENT_LEN, HEADER_CONTENT_SHA); } - else { - console.log('NO REQUEST BODY LOL'); - } - var keyId = auth.get('tenancy') + '/' + auth.get('user') + '/' + auth.get('fingerprint'), privateKeyBuffer = sshpk.parsePrivateKey(auth.get('private_key'), 'auto').toBuffer('pem', {}); - console.log('Before httpSignature.sign', ociRequest.headers); - httpSignature.sign(new SignerRequest(ociRequest.method, ociRequest.uri, ociRequest.headers), { + httpSignature.sign(new SignerRequest(uppercaseMethod, rawRequestUri, domHeadersObject), { key: privateKeyBuffer, keyId: keyId, headers: headersToSign }); + // NOTE: OCI needs 'authorization' but our version of httpSignature puts signature in 'Authorization' + const AUTH_HEADER_BACKWARD_COMPATIBLE = 'Authorization', + authorizationHeader = domHeadersObject.get(AUTH_HEADER_BACKWARD_COMPATIBLE); - // NOTE: OCI needs 'authorization' but our version of httpSignature puts signature in 'Authorizaiton' - const authorizationHeader = ociRequest.headers.get('Authorization'); - - ociRequest.headers.set('authorization', authorizationHeader.replace('Signature ', 'Signature version="1",')); - ociRequest.headers.delete('Authorization'); - + domHeadersObject.set(HEADER_AUTHORIZATION, + authorizationHeader.replace('Signature ', 'Signature version="1",')); + domHeadersObject.delete(AUTH_HEADER_BACKWARD_COMPATIBLE); + console.log('allHeaders', domHeadersObject.keys()); - console.log('result: ', authorizationHeader); - console.log('allHeaders', ociRequest.headers); - - return ociRequest; + return domHeadersObject; }; @@ -206,15 +192,23 @@ module.exports = { }, updates: [ { - property: 'authorization', + property: HEADER_AUTHORIZATION, type: 'header' }, { - property: 'host', + property: HEADER_DATE, type: 'header' }, { - property: 'x-date', + property: HEADER_CONTENT_LEN, + type: 'header' + }, + { + property: HEADER_CONTENT_TYPE, + type: 'header' + }, + { + property: HEADER_CONTENT_SHA, type: 'header' } ] @@ -269,50 +263,22 @@ module.exports = { * @param {AuthHandlerInterface~authSignHookCallback} done Callback function */ sign: function (auth, request, done) { - console.log('OCI SIGN CALLED'); - console.log('request headers 1: ', request.headers); - // TODO: Remove restrictions on body and method - - const ociRequest = convertPostmanRequestToOCIRequest(request), - signedOciRequest = processRequestForOci(ociRequest, auth); - - console.log(signedOciRequest.body); - request.addHeader({ - key: 'authorization', - value: signedOciRequest.headers.get('authorization'), - system: true - }); - request.addHeader({ - key: 'x-date', - value: signedOciRequest.headers.get('x-date'), - system: true - }); - request.addHeader({ - key: 'host', - value: signedOciRequest.headers.get('host'), - system: true - }); - if (signedOciRequest.headers.get(HEADER_CONTENT_LEN)) { - request.addHeader({ - key: HEADER_CONTENT_LEN, - value: signedOciRequest.headers.get(HEADER_CONTENT_LEN), - system: true - }); - } - if (signedOciRequest.headers.get(HEADER_CONTENT_SHA)) { - request.addHeader({ - key: HEADER_CONTENT_SHA, - value: signedOciRequest.headers.get(HEADER_CONTENT_SHA), - system: true - }); - } - if (signedOciRequest.headers.get(HEADER_CONTENT_TYPE)) { - request.addHeader({ - key: HEADER_CONTENT_TYPE, - value: signedOciRequest.headers.get(HEADER_CONTENT_TYPE), - system: true - }); - } + const newHeaders = processRequestForOci(request, auth), + setHeaderIfAvailable = function (headerName) { + const currentHeader = newHeaders.get(headerName); + + if (currentHeader) { + request.addHeader({ + key: headerName, + value: currentHeader, + system: true + }); + } + }, + allPossibleHeaders = [HEADER_AUTHORIZATION, HEADER_DATE, HEADER_CONTENT_LEN, + HEADER_CONTENT_SHA, HEADER_CONTENT_TYPE]; + + allPossibleHeaders.forEach(setHeaderIfAvailable); return done(); } From da900db17947952c4ba7a1a473b5d7011ab0a9c9 Mon Sep 17 00:00:00 2001 From: Ankit Arora Date: Fri, 11 Dec 2020 13:37:09 +0530 Subject: [PATCH 11/21] Add test case for OCI Auth for request with body --- lib/authorizer/oci-v1.js | 9 ----- test/fixtures/auth-requests.json | 35 ++++++++++++++++++- test/unit/auth-handlers.test.js | 59 ++++++++++++++++++++++++-------- 3 files changed, 78 insertions(+), 25 deletions(-) diff --git a/lib/authorizer/oci-v1.js b/lib/authorizer/oci-v1.js index edb377cf9..0b5de7273 100644 --- a/lib/authorizer/oci-v1.js +++ b/lib/authorizer/oci-v1.js @@ -171,7 +171,6 @@ var convertToDomHeadersObject = function (postmanHeaders) { domHeadersObject.set(HEADER_AUTHORIZATION, authorizationHeader.replace('Signature ', 'Signature version="1",')); domHeadersObject.delete(AUTH_HEADER_BACKWARD_COMPATIBLE); - console.log('allHeaders', domHeadersObject.keys()); return domHeadersObject; }; @@ -232,14 +231,6 @@ module.exports = { * @param {AuthHandlerInterface~authPreHookCallback} done Callback function called with error, success and request */ pre: function (auth, done) { - // TODO: Check the right params - // config = from_file() - // auth = Signer( - // tenancy=config['tenancy'], - // user=config['user'], - // fingerprint=config['fingerprint'], - // private_key_file_location=config['key_file'], - // ) done(null, Boolean(auth.get('tenancy') && auth.get('user') && auth.get('fingerprint') && auth.get('private_key'))); }, diff --git a/test/fixtures/auth-requests.json b/test/fixtures/auth-requests.json index f46fe927c..8924c1e65 100644 --- a/test/fixtures/auth-requests.json +++ b/test/fixtures/auth-requests.json @@ -248,7 +248,7 @@ }, "description": "" }, - "oci": { + "ociWithoutBody": { "auth": { "type": "oci", "oci": { @@ -260,5 +260,38 @@ }, "url": "https://identity.ap-hyderabad-1.oraclecloud.com/20160918/users/ocid1.user.oc1..aaaaaaaax4esyzwnhlxdb6h5dfopzkuw5kujtffz3y4yvczqnjwlpbnk7q7q", "method": "GET" + }, + "ociWithBody": { + "auth": { + "type": "oci", + "oci": { + "tenancy": "ocid1.tenancy.oc1..aaaaaaaa5h4h55rwzjwrufcfaqp4h5gxcqv65ozk7rytrvcltwujfj45g25a", + "user": "ocid1.user.oc1..aaaaaaaax4esyzwnhlxdb6h5dfopzkuw5kujtffz3y4yvczqnjwlpbnk7q7q", + "fingerprint": "42:34:8b:df:0a:9c:b0:c8:b6:ac:7a:c2:ce:7e:45:85", + "private_key": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEAvOxs9ybstMcalgCEbNIHeNh7oqVBLAC0+bhi7KEr2xYFSQws\nu4MdPXqSCTQu1/4fsMoCbRLZMRmC8YonjjhdRyVFZrAkE5Q9WfF3N40s/GVK8Myb\nWxBS5hZnc4td/d+OoGLE5aKNwaFNoTn7iDCU1JfG+d4l7Z5twzHESs3XnzNSeRms\n/MAFk3zdjlpOm9pbafFqFoim6Be8dRXtWU0xN5VRHD3txisQJlcLVNMm6IK9UWUg\nJzmn8d5ASwvU75/nJKc8DLoQ0cVeYaIhXWGME6ApXyb62zKmccPpkRzRZSJYPeUo\nLK2JC/w/os1NAi0mTGb/KqOzd7BJf1RO0SQYHwIDAQABAoIBAGRS4KJ2hyiQuquB\nZtEqz1D7FNyQCQXG8lPR+KZUCCf1j6T01CRXQgXNuxMsJNwKVOXawGMPqUqLk5+U\nj+DUSaRoRGx9iQrko5fJxFc5nvQBDkTFQpKfHoaUyybukWEpgGHnUUvogIKcl87Q\nLaRqt/4VA1LZByciBIOtP+HBYYlmGlg6UDeOFTku9nFbraz8FlzqLAy7xSUB3aDs\n1JeDwR9PBQsRG72GQkJR/EmPbD2Y/r+zmZP25/97pouO/ji9DJwDcVc1qFpn4JKf\nLABBUEwfWEIWa4cefbDi0dCzVKxrS/RU9EYB6HtMklcy3qyxbdcLmFY8qgsxjG8K\nw2iD2iECgYEA+AtmXff5lnSZq3CJhcxBpi+MuCByWH7gB2/G50XSduRmW+lzI6iv\n+r8ADEI87+KBIju++qNvj886N9H1sm+k6j3nEE51i2nwwKB79Xzu0J23+XMSCV0D\nYb6bvNogGCOhKslQNC51ZvgsZlTu6F8/EkPlboEL8E2h4eYwx3L6UbcCgYEAwvub\nB+rhUk4+TwXVnfNZEcmQiz90yU7CI/TjDrHVq+ZJIKRHILB+7Mt7Mpi+7Ie2Cx/f\nA1Alv8I44wmLhZX63Du9hwoz3t4Y0+AiT/RMp3EkmxKIkPFZNKsmY659dNzROMG9\nEVYEmBYode17mrSc4UJi8I4iHCv1A83BC3DhzNkCgYBSE8Od2I5YQOEQn76B7aLT\nkOxpiSMNMX6EN3KD2NDZ0p4kT81vwUPqHwWvCMQNRNAiOc7qNOaXmaTUD7/TeaoC\ncNViyfOPXFD0DKa4Bs0nbukPvAn92y9hSqdSCIOSOUf9VnwZqD3lAr3+ZqBfeBTw\nwFLNDBqdO7MTgw4lEWDPZQKBgQCIm3c2yN0sqR0GiHPtwfz5dVsL9F2CXOewAXbD\naNznHuTFNdOPl5iVlsqt3E6HsV1d1eqNi62m+BCbIKjb4wRrIH/dCMzmrHyAlVv0\n4JiEB8U50HZV9oIlYHP5Ctti8QK03Sf16Wo2k++tD8G11izDtZtUJoDHdBSpoZJK\nzb+loQKBgQC0/VewDbcRW5FymBPJiEnrTtpHk40x14pNfRbRrNDIx/jIx/gnqwyI\n6ud7uJkK+LAHw+r2HjHtSMVE9I54zr+QG8fAe8alJQ3mSP1tlpLbMaMb7LpomKo/\nfVVz1laGP3tcpXDEp80hbrDxO7aOexUgCFKHrYTAgVCm8Eqzz8HdsQ==\n-----END RSA PRIVATE KEY-----" + } + }, + "body": { + "mode": "raw", + "raw": "{\"compartmentId\": \"ocid1.tenancy.oc1..aaaaaaaa5h4h55rwzjwrufcfaqp4h5gxcqv65ozk7rytrvcltwujfj45g25a\",\"targets\": [\"192.0.2.0\"],\"protocol\": \"ICMP\"}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "https://healthchecks.ap-hyderabad-1.oraclecloud.com/20160918/users/ocid1.user.oc1..aaaaaaaax4esyzwnhlxdb6h5dfopzkuw5kujtffz3y4yvczqnjwlpbnk7q7q", + "protocol": "https", + "host": [ + "healthchecks.ap-hyderabad-1.oraclecloud", + "com" + ], + "path": [ + "20180501", + "pingProbeResults" + ] + }, + "method": "POST" } } diff --git a/test/unit/auth-handlers.test.js b/test/unit/auth-handlers.test.js index eaf590282..e8a13aa18 100644 --- a/test/unit/auth-handlers.test.js +++ b/test/unit/auth-handlers.test.js @@ -2615,31 +2615,60 @@ describe('Auth Handler:', function () { }); describe('oci', function () { - it('should add the Auth header', function (done) { - var request = new Request(rawRequests.oci), + it('should have all necessary headers', function (done) { + var request = new Request(rawRequests.ociWithoutBody), auth = request.auth, authInterface = createAuthInterface(auth), handler = AuthLoader.getHandler(auth.type), headers; handler.sign(authInterface, request, function () { - // headers = request.getHeaders({ - // ignoreCase: true - // }); - console.log('In test case, back from handler.sign'); - // console.log(headers.authorization); - // Ensure that the required headers have been added. - // expect(headers).to.have.property('authorization'); - console.log('printing all headers'); - const rawHeaders = {}; + headers = request.getHeaders({ + ignoreCase: true + }); + expect(headers).to.have.property('authorization'); + expect(headers).to.have.property('x-date'); + done(); + }); + }); + it('should have correct structure of auth header - without body', function (done) { + var request = new Request(rawRequests.ociWithoutBody), + auth = request.auth, + authInterface = createAuthInterface(auth), + handler = AuthLoader.getHandler(auth.type), + headers; - request.headers.all().forEach(function (each) { - console.log(each.key, each.value); - rawHeaders[each.key] = each.value; + handler.sign(authInterface, request, function () { + headers = request.getHeaders({ + ignoreCase: true }); - console.log(request.headers.get('authorization')) + expect(Object.keys(headers)).to.eql(['authorization', 'x-date']) + expect(headers).to.have.property('authorization'); + expect(headers.authorization).to.include('Signature version="1"'); + expect(headers.authorization).to.include('x-date (request-target) host'); + expect(headers.authorization).to.include('algorithm="rsa-sha256"'); done(); + }); + }); + + it('should have correct structure of auth header - with body', function (done) { + var request = new Request(rawRequests.ociWithBody), + auth = request.auth, + authInterface = createAuthInterface(auth), + handler = AuthLoader.getHandler(auth.type), + headers; + handler.sign(authInterface, request, function () { + headers = request.getHeaders({ + ignoreCase: true + }); + expect(Object.keys(headers).sort()) + .to.eql(['authorization', 'x-date', 'content-length', 'x-content-sha256', 'content-type'].sort()) + expect(headers.authorization).to.include('Signature version="1"'); + expect(headers.authorization) + .to.include('x-date (request-target) host content-type content-length x-content-sha256'); + expect(headers.authorization).to.include('algorithm="rsa-sha256"'); + done(); }); }); }); From e5d38c471b0a48394566af08b22e7e7046a9b054 Mon Sep 17 00:00:00 2001 From: Ankit Arora Date: Mon, 14 Dec 2020 09:32:30 +0530 Subject: [PATCH 12/21] Cleaner code --- lib/authorizer/oci-v1.js | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/lib/authorizer/oci-v1.js b/lib/authorizer/oci-v1.js index 0b5de7273..dc2ecca29 100644 --- a/lib/authorizer/oci-v1.js +++ b/lib/authorizer/oci-v1.js @@ -19,8 +19,12 @@ const HEADER_CONTENT_SHA = 'x-content-sha256', EMPTY_SHA = '47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=', HEADER_AUTHORIZATION = 'authorization', HEADER_DATE = 'x-date', - EXTRA_HEADER_METHODS = ['POST', 'PUT', 'PATCH']; -// -------------------- HEADERS POLYFILL --------------------------- + HEADER_HOST = 'host', + CONTENT_TYPE_JSON = 'application/json', + EXTRA_HEADER_METHODS = ['POST', 'PUT', 'PATCH'], + PSEUDOHEADER_REQUEST_TARGET = '(request-target)'; + +// -------------------- POLYFILL for input to httpSignature.sign --------------------------- function Headers (values) { this._values = values || {}; @@ -66,9 +70,11 @@ Headers.prototype.set = function (name, value) { this._values[name] = value; }; +// eslint-disable-next-line no-unused-vars Headers.prototype.values = function (name, value) { const result = []; + // eslint-disable-next-line guard-for-in for (let key in this._values) { result.push(this._values[key]); } @@ -114,20 +120,21 @@ var convertToDomHeadersObject = function (postmanHeaders) { const rawRequestUri = request.url.getRaw(), domHeadersObject = convertToDomHeadersObject(request.headers), uppercaseMethod = request.method.toUpperCase(), - minimumHeadersToSign = ['x-date', '(request-target)', 'host'];; + minimumHeadersToSign = [HEADER_DATE, PSEUDOHEADER_REQUEST_TARGET, HEADER_HOST], + keyId = auth.get('tenancy') + '/' + auth.get('user') + '/' + auth.get('fingerprint'), + privateKeyBuffer = sshpk.parsePrivateKey(auth.get('private_key'), 'auto').toBuffer('pem', {}); - if (!domHeadersObject.has('host')) { + if (!domHeadersObject.has(HEADER_HOST)) { const url = UrlParser.parse(rawRequestUri); if (url.host) { - domHeadersObject.set('host', url.host); + domHeadersObject.set(HEADER_HOST, url.host); } else { throw new Error('Cannot parse host from url'); } } - // Date header if (!domHeadersObject.has(HEADER_DATE)) { domHeadersObject.set(HEADER_DATE, new Date().toUTCString()); } @@ -135,8 +142,12 @@ var convertToDomHeadersObject = function (postmanHeaders) { if (request.body && _.includes(EXTRA_HEADER_METHODS, uppercaseMethod)) { if (!domHeadersObject.has(HEADER_CONTENT_TYPE)) { - domHeadersObject.set(HEADER_CONTENT_TYPE, 'application/json'); + domHeadersObject.set(HEADER_CONTENT_TYPE, CONTENT_TYPE_JSON); + } + else if (domHeadersObject.get(HEADER_CONTENT_TYPE) !== CONTENT_TYPE_JSON) { + throw new Error(`Only ${CONTENT_TYPE_JSON} is supported by OCI Auth has Header`); } + let contentLen = 0; const shaObj = new jssha('SHA-256', 'TEXT'), requestBodyString = getBodyString(request.body); @@ -156,15 +167,13 @@ var convertToDomHeadersObject = function (postmanHeaders) { headersToSign = headersToSign.concat(HEADER_CONTENT_TYPE, HEADER_CONTENT_LEN, HEADER_CONTENT_SHA); } - var keyId = auth.get('tenancy') + '/' + auth.get('user') + '/' + auth.get('fingerprint'), - privateKeyBuffer = sshpk.parsePrivateKey(auth.get('private_key'), 'auto').toBuffer('pem', {}); - httpSignature.sign(new SignerRequest(uppercaseMethod, rawRequestUri, domHeadersObject), { key: privateKeyBuffer, keyId: keyId, headers: headersToSign }); - // NOTE: OCI needs 'authorization' but our version of httpSignature puts signature in 'Authorization' + // NOTE: OCI needs 'authorization' but our version of httpSignature (1.3.1) puts signature in 'Authorization' + // eslint-disable-next-line one-var const AUTH_HEADER_BACKWARD_COMPATIBLE = 'Authorization', authorizationHeader = domHeadersObject.get(AUTH_HEADER_BACKWARD_COMPATIBLE); From 4532e6b18deae940476476bf58da73565623fcad Mon Sep 17 00:00:00 2001 From: Ankit Arora Date: Mon, 14 Dec 2020 11:42:33 +0530 Subject: [PATCH 13/21] Propagate error via done callback --- lib/authorizer/oci-v1.js | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/lib/authorizer/oci-v1.js b/lib/authorizer/oci-v1.js index dc2ecca29..17b10036f 100644 --- a/lib/authorizer/oci-v1.js +++ b/lib/authorizer/oci-v1.js @@ -263,22 +263,27 @@ module.exports = { * @param {AuthHandlerInterface~authSignHookCallback} done Callback function */ sign: function (auth, request, done) { - const newHeaders = processRequestForOci(request, auth), - setHeaderIfAvailable = function (headerName) { - const currentHeader = newHeaders.get(headerName); - - if (currentHeader) { - request.addHeader({ - key: headerName, - value: currentHeader, - system: true - }); - } - }, - allPossibleHeaders = [HEADER_AUTHORIZATION, HEADER_DATE, HEADER_CONTENT_LEN, - HEADER_CONTENT_SHA, HEADER_CONTENT_TYPE]; - - allPossibleHeaders.forEach(setHeaderIfAvailable); + try { + const newHeaders = processRequestForOci(request, auth), + setHeaderIfAvailable = function (headerName) { + const currentHeader = newHeaders.get(headerName); + + if (currentHeader) { + request.addHeader({ + key: headerName, + value: currentHeader, + system: true + }); + } + }, + allPossibleHeaders = [HEADER_AUTHORIZATION, HEADER_DATE, HEADER_CONTENT_LEN, + HEADER_CONTENT_SHA, HEADER_CONTENT_TYPE]; + + allPossibleHeaders.forEach(setHeaderIfAvailable); + } + catch (e) { + done(e); + } return done(); } From 555cbbea1972a30425f0c733dcd38ad611c3160c Mon Sep 17 00:00:00 2001 From: Ankit Arora Date: Mon, 14 Dec 2020 13:03:29 +0530 Subject: [PATCH 14/21] Add test case for incorrect content type --- lib/authorizer/oci-v1.js | 28 ++++++++---------- test/fixtures/auth-requests.json | 4 +-- test/unit/auth-handlers.test.js | 51 ++++++++++++++++++++++---------- 3 files changed, 51 insertions(+), 32 deletions(-) diff --git a/lib/authorizer/oci-v1.js b/lib/authorizer/oci-v1.js index 17b10036f..ae382b556 100644 --- a/lib/authorizer/oci-v1.js +++ b/lib/authorizer/oci-v1.js @@ -105,7 +105,7 @@ var convertToDomHeadersObject = function (postmanHeaders) { let rawHeaders = {}; postmanHeaders.all().forEach(function (each) { - rawHeaders[each.key.lowercase()] = each.value; + rawHeaders[each.key.toLowerCase()] = each.value; }); return new Headers(rawHeaders); @@ -116,13 +116,13 @@ var convertToDomHeadersObject = function (postmanHeaders) { } throw new Error(`Request body mode ${body.mode} is not supported. Please use ${RequestBody.MODES.raw}`); }, - processRequestForOci = function (request, auth) { + processRequestForOci = function (request, auth, callback) { const rawRequestUri = request.url.getRaw(), domHeadersObject = convertToDomHeadersObject(request.headers), uppercaseMethod = request.method.toUpperCase(), minimumHeadersToSign = [HEADER_DATE, PSEUDOHEADER_REQUEST_TARGET, HEADER_HOST], keyId = auth.get('tenancy') + '/' + auth.get('user') + '/' + auth.get('fingerprint'), - privateKeyBuffer = sshpk.parsePrivateKey(auth.get('private_key'), 'auto').toBuffer('pem', {}); + privateKeyBuffer = sshpk.parsePrivateKey(auth.get('privatekey'), 'auto').toBuffer('pem', {}); if (!domHeadersObject.has(HEADER_HOST)) { const url = UrlParser.parse(rawRequestUri); @@ -131,7 +131,7 @@ var convertToDomHeadersObject = function (postmanHeaders) { domHeadersObject.set(HEADER_HOST, url.host); } else { - throw new Error('Cannot parse host from url'); + return callback(new Error('Cannot parse host from url')); } } @@ -140,12 +140,12 @@ var convertToDomHeadersObject = function (postmanHeaders) { } let headersToSign = [...minimumHeadersToSign]; - if (request.body && _.includes(EXTRA_HEADER_METHODS, uppercaseMethod)) { + if (!auth.get('forceDisableBodyHashing') && request.body && _.includes(EXTRA_HEADER_METHODS, uppercaseMethod)) { if (!domHeadersObject.has(HEADER_CONTENT_TYPE)) { domHeadersObject.set(HEADER_CONTENT_TYPE, CONTENT_TYPE_JSON); } else if (domHeadersObject.get(HEADER_CONTENT_TYPE) !== CONTENT_TYPE_JSON) { - throw new Error(`Only ${CONTENT_TYPE_JSON} is supported by OCI Auth has Header`); + return callback(new Error(`Only ${CONTENT_TYPE_JSON} is supported by OCI Auth`)); } let contentLen = 0; @@ -181,7 +181,7 @@ var convertToDomHeadersObject = function (postmanHeaders) { authorizationHeader.replace('Signature ', 'Signature version="1",')); domHeadersObject.delete(AUTH_HEADER_BACKWARD_COMPATIBLE); - return domHeadersObject; + return callback(domHeadersObject); }; @@ -263,8 +263,10 @@ module.exports = { * @param {AuthHandlerInterface~authSignHookCallback} done Callback function */ sign: function (auth, request, done) { - try { - const newHeaders = processRequestForOci(request, auth), + processRequestForOci(request, auth, function (result) { + if (!result) { return done(); } + if (result instanceof Error) { return done(result); } + const newHeaders = result, setHeaderIfAvailable = function (headerName) { const currentHeader = newHeaders.get(headerName); @@ -280,11 +282,7 @@ module.exports = { HEADER_CONTENT_SHA, HEADER_CONTENT_TYPE]; allPossibleHeaders.forEach(setHeaderIfAvailable); - } - catch (e) { - done(e); - } - - return done(); + done(); + }); } }; diff --git a/test/fixtures/auth-requests.json b/test/fixtures/auth-requests.json index 8924c1e65..120755e13 100644 --- a/test/fixtures/auth-requests.json +++ b/test/fixtures/auth-requests.json @@ -255,7 +255,7 @@ "tenancy": "ocid1.tenancy.oc1..aaaaaaaa5h4h55rwzjwrufcfaqp4h5gxcqv65ozk7rytrvcltwujfj45g25a", "user": "ocid1.user.oc1..aaaaaaaax4esyzwnhlxdb6h5dfopzkuw5kujtffz3y4yvczqnjwlpbnk7q7q", "fingerprint": "42:34:8b:df:0a:9c:b0:c8:b6:ac:7a:c2:ce:7e:45:85", - "private_key": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEAvOxs9ybstMcalgCEbNIHeNh7oqVBLAC0+bhi7KEr2xYFSQws\nu4MdPXqSCTQu1/4fsMoCbRLZMRmC8YonjjhdRyVFZrAkE5Q9WfF3N40s/GVK8Myb\nWxBS5hZnc4td/d+OoGLE5aKNwaFNoTn7iDCU1JfG+d4l7Z5twzHESs3XnzNSeRms\n/MAFk3zdjlpOm9pbafFqFoim6Be8dRXtWU0xN5VRHD3txisQJlcLVNMm6IK9UWUg\nJzmn8d5ASwvU75/nJKc8DLoQ0cVeYaIhXWGME6ApXyb62zKmccPpkRzRZSJYPeUo\nLK2JC/w/os1NAi0mTGb/KqOzd7BJf1RO0SQYHwIDAQABAoIBAGRS4KJ2hyiQuquB\nZtEqz1D7FNyQCQXG8lPR+KZUCCf1j6T01CRXQgXNuxMsJNwKVOXawGMPqUqLk5+U\nj+DUSaRoRGx9iQrko5fJxFc5nvQBDkTFQpKfHoaUyybukWEpgGHnUUvogIKcl87Q\nLaRqt/4VA1LZByciBIOtP+HBYYlmGlg6UDeOFTku9nFbraz8FlzqLAy7xSUB3aDs\n1JeDwR9PBQsRG72GQkJR/EmPbD2Y/r+zmZP25/97pouO/ji9DJwDcVc1qFpn4JKf\nLABBUEwfWEIWa4cefbDi0dCzVKxrS/RU9EYB6HtMklcy3qyxbdcLmFY8qgsxjG8K\nw2iD2iECgYEA+AtmXff5lnSZq3CJhcxBpi+MuCByWH7gB2/G50XSduRmW+lzI6iv\n+r8ADEI87+KBIju++qNvj886N9H1sm+k6j3nEE51i2nwwKB79Xzu0J23+XMSCV0D\nYb6bvNogGCOhKslQNC51ZvgsZlTu6F8/EkPlboEL8E2h4eYwx3L6UbcCgYEAwvub\nB+rhUk4+TwXVnfNZEcmQiz90yU7CI/TjDrHVq+ZJIKRHILB+7Mt7Mpi+7Ie2Cx/f\nA1Alv8I44wmLhZX63Du9hwoz3t4Y0+AiT/RMp3EkmxKIkPFZNKsmY659dNzROMG9\nEVYEmBYode17mrSc4UJi8I4iHCv1A83BC3DhzNkCgYBSE8Od2I5YQOEQn76B7aLT\nkOxpiSMNMX6EN3KD2NDZ0p4kT81vwUPqHwWvCMQNRNAiOc7qNOaXmaTUD7/TeaoC\ncNViyfOPXFD0DKa4Bs0nbukPvAn92y9hSqdSCIOSOUf9VnwZqD3lAr3+ZqBfeBTw\nwFLNDBqdO7MTgw4lEWDPZQKBgQCIm3c2yN0sqR0GiHPtwfz5dVsL9F2CXOewAXbD\naNznHuTFNdOPl5iVlsqt3E6HsV1d1eqNi62m+BCbIKjb4wRrIH/dCMzmrHyAlVv0\n4JiEB8U50HZV9oIlYHP5Ctti8QK03Sf16Wo2k++tD8G11izDtZtUJoDHdBSpoZJK\nzb+loQKBgQC0/VewDbcRW5FymBPJiEnrTtpHk40x14pNfRbRrNDIx/jIx/gnqwyI\n6ud7uJkK+LAHw+r2HjHtSMVE9I54zr+QG8fAe8alJQ3mSP1tlpLbMaMb7LpomKo/\nfVVz1laGP3tcpXDEp80hbrDxO7aOexUgCFKHrYTAgVCm8Eqzz8HdsQ==\n-----END RSA PRIVATE KEY-----" + "privatekey": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEAvOxs9ybstMcalgCEbNIHeNh7oqVBLAC0+bhi7KEr2xYFSQws\nu4MdPXqSCTQu1/4fsMoCbRLZMRmC8YonjjhdRyVFZrAkE5Q9WfF3N40s/GVK8Myb\nWxBS5hZnc4td/d+OoGLE5aKNwaFNoTn7iDCU1JfG+d4l7Z5twzHESs3XnzNSeRms\n/MAFk3zdjlpOm9pbafFqFoim6Be8dRXtWU0xN5VRHD3txisQJlcLVNMm6IK9UWUg\nJzmn8d5ASwvU75/nJKc8DLoQ0cVeYaIhXWGME6ApXyb62zKmccPpkRzRZSJYPeUo\nLK2JC/w/os1NAi0mTGb/KqOzd7BJf1RO0SQYHwIDAQABAoIBAGRS4KJ2hyiQuquB\nZtEqz1D7FNyQCQXG8lPR+KZUCCf1j6T01CRXQgXNuxMsJNwKVOXawGMPqUqLk5+U\nj+DUSaRoRGx9iQrko5fJxFc5nvQBDkTFQpKfHoaUyybukWEpgGHnUUvogIKcl87Q\nLaRqt/4VA1LZByciBIOtP+HBYYlmGlg6UDeOFTku9nFbraz8FlzqLAy7xSUB3aDs\n1JeDwR9PBQsRG72GQkJR/EmPbD2Y/r+zmZP25/97pouO/ji9DJwDcVc1qFpn4JKf\nLABBUEwfWEIWa4cefbDi0dCzVKxrS/RU9EYB6HtMklcy3qyxbdcLmFY8qgsxjG8K\nw2iD2iECgYEA+AtmXff5lnSZq3CJhcxBpi+MuCByWH7gB2/G50XSduRmW+lzI6iv\n+r8ADEI87+KBIju++qNvj886N9H1sm+k6j3nEE51i2nwwKB79Xzu0J23+XMSCV0D\nYb6bvNogGCOhKslQNC51ZvgsZlTu6F8/EkPlboEL8E2h4eYwx3L6UbcCgYEAwvub\nB+rhUk4+TwXVnfNZEcmQiz90yU7CI/TjDrHVq+ZJIKRHILB+7Mt7Mpi+7Ie2Cx/f\nA1Alv8I44wmLhZX63Du9hwoz3t4Y0+AiT/RMp3EkmxKIkPFZNKsmY659dNzROMG9\nEVYEmBYode17mrSc4UJi8I4iHCv1A83BC3DhzNkCgYBSE8Od2I5YQOEQn76B7aLT\nkOxpiSMNMX6EN3KD2NDZ0p4kT81vwUPqHwWvCMQNRNAiOc7qNOaXmaTUD7/TeaoC\ncNViyfOPXFD0DKa4Bs0nbukPvAn92y9hSqdSCIOSOUf9VnwZqD3lAr3+ZqBfeBTw\nwFLNDBqdO7MTgw4lEWDPZQKBgQCIm3c2yN0sqR0GiHPtwfz5dVsL9F2CXOewAXbD\naNznHuTFNdOPl5iVlsqt3E6HsV1d1eqNi62m+BCbIKjb4wRrIH/dCMzmrHyAlVv0\n4JiEB8U50HZV9oIlYHP5Ctti8QK03Sf16Wo2k++tD8G11izDtZtUJoDHdBSpoZJK\nzb+loQKBgQC0/VewDbcRW5FymBPJiEnrTtpHk40x14pNfRbRrNDIx/jIx/gnqwyI\n6ud7uJkK+LAHw+r2HjHtSMVE9I54zr+QG8fAe8alJQ3mSP1tlpLbMaMb7LpomKo/\nfVVz1laGP3tcpXDEp80hbrDxO7aOexUgCFKHrYTAgVCm8Eqzz8HdsQ==\n-----END RSA PRIVATE KEY-----" } }, "url": "https://identity.ap-hyderabad-1.oraclecloud.com/20160918/users/ocid1.user.oc1..aaaaaaaax4esyzwnhlxdb6h5dfopzkuw5kujtffz3y4yvczqnjwlpbnk7q7q", @@ -268,7 +268,7 @@ "tenancy": "ocid1.tenancy.oc1..aaaaaaaa5h4h55rwzjwrufcfaqp4h5gxcqv65ozk7rytrvcltwujfj45g25a", "user": "ocid1.user.oc1..aaaaaaaax4esyzwnhlxdb6h5dfopzkuw5kujtffz3y4yvczqnjwlpbnk7q7q", "fingerprint": "42:34:8b:df:0a:9c:b0:c8:b6:ac:7a:c2:ce:7e:45:85", - "private_key": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEAvOxs9ybstMcalgCEbNIHeNh7oqVBLAC0+bhi7KEr2xYFSQws\nu4MdPXqSCTQu1/4fsMoCbRLZMRmC8YonjjhdRyVFZrAkE5Q9WfF3N40s/GVK8Myb\nWxBS5hZnc4td/d+OoGLE5aKNwaFNoTn7iDCU1JfG+d4l7Z5twzHESs3XnzNSeRms\n/MAFk3zdjlpOm9pbafFqFoim6Be8dRXtWU0xN5VRHD3txisQJlcLVNMm6IK9UWUg\nJzmn8d5ASwvU75/nJKc8DLoQ0cVeYaIhXWGME6ApXyb62zKmccPpkRzRZSJYPeUo\nLK2JC/w/os1NAi0mTGb/KqOzd7BJf1RO0SQYHwIDAQABAoIBAGRS4KJ2hyiQuquB\nZtEqz1D7FNyQCQXG8lPR+KZUCCf1j6T01CRXQgXNuxMsJNwKVOXawGMPqUqLk5+U\nj+DUSaRoRGx9iQrko5fJxFc5nvQBDkTFQpKfHoaUyybukWEpgGHnUUvogIKcl87Q\nLaRqt/4VA1LZByciBIOtP+HBYYlmGlg6UDeOFTku9nFbraz8FlzqLAy7xSUB3aDs\n1JeDwR9PBQsRG72GQkJR/EmPbD2Y/r+zmZP25/97pouO/ji9DJwDcVc1qFpn4JKf\nLABBUEwfWEIWa4cefbDi0dCzVKxrS/RU9EYB6HtMklcy3qyxbdcLmFY8qgsxjG8K\nw2iD2iECgYEA+AtmXff5lnSZq3CJhcxBpi+MuCByWH7gB2/G50XSduRmW+lzI6iv\n+r8ADEI87+KBIju++qNvj886N9H1sm+k6j3nEE51i2nwwKB79Xzu0J23+XMSCV0D\nYb6bvNogGCOhKslQNC51ZvgsZlTu6F8/EkPlboEL8E2h4eYwx3L6UbcCgYEAwvub\nB+rhUk4+TwXVnfNZEcmQiz90yU7CI/TjDrHVq+ZJIKRHILB+7Mt7Mpi+7Ie2Cx/f\nA1Alv8I44wmLhZX63Du9hwoz3t4Y0+AiT/RMp3EkmxKIkPFZNKsmY659dNzROMG9\nEVYEmBYode17mrSc4UJi8I4iHCv1A83BC3DhzNkCgYBSE8Od2I5YQOEQn76B7aLT\nkOxpiSMNMX6EN3KD2NDZ0p4kT81vwUPqHwWvCMQNRNAiOc7qNOaXmaTUD7/TeaoC\ncNViyfOPXFD0DKa4Bs0nbukPvAn92y9hSqdSCIOSOUf9VnwZqD3lAr3+ZqBfeBTw\nwFLNDBqdO7MTgw4lEWDPZQKBgQCIm3c2yN0sqR0GiHPtwfz5dVsL9F2CXOewAXbD\naNznHuTFNdOPl5iVlsqt3E6HsV1d1eqNi62m+BCbIKjb4wRrIH/dCMzmrHyAlVv0\n4JiEB8U50HZV9oIlYHP5Ctti8QK03Sf16Wo2k++tD8G11izDtZtUJoDHdBSpoZJK\nzb+loQKBgQC0/VewDbcRW5FymBPJiEnrTtpHk40x14pNfRbRrNDIx/jIx/gnqwyI\n6ud7uJkK+LAHw+r2HjHtSMVE9I54zr+QG8fAe8alJQ3mSP1tlpLbMaMb7LpomKo/\nfVVz1laGP3tcpXDEp80hbrDxO7aOexUgCFKHrYTAgVCm8Eqzz8HdsQ==\n-----END RSA PRIVATE KEY-----" + "privatekey": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEAvOxs9ybstMcalgCEbNIHeNh7oqVBLAC0+bhi7KEr2xYFSQws\nu4MdPXqSCTQu1/4fsMoCbRLZMRmC8YonjjhdRyVFZrAkE5Q9WfF3N40s/GVK8Myb\nWxBS5hZnc4td/d+OoGLE5aKNwaFNoTn7iDCU1JfG+d4l7Z5twzHESs3XnzNSeRms\n/MAFk3zdjlpOm9pbafFqFoim6Be8dRXtWU0xN5VRHD3txisQJlcLVNMm6IK9UWUg\nJzmn8d5ASwvU75/nJKc8DLoQ0cVeYaIhXWGME6ApXyb62zKmccPpkRzRZSJYPeUo\nLK2JC/w/os1NAi0mTGb/KqOzd7BJf1RO0SQYHwIDAQABAoIBAGRS4KJ2hyiQuquB\nZtEqz1D7FNyQCQXG8lPR+KZUCCf1j6T01CRXQgXNuxMsJNwKVOXawGMPqUqLk5+U\nj+DUSaRoRGx9iQrko5fJxFc5nvQBDkTFQpKfHoaUyybukWEpgGHnUUvogIKcl87Q\nLaRqt/4VA1LZByciBIOtP+HBYYlmGlg6UDeOFTku9nFbraz8FlzqLAy7xSUB3aDs\n1JeDwR9PBQsRG72GQkJR/EmPbD2Y/r+zmZP25/97pouO/ji9DJwDcVc1qFpn4JKf\nLABBUEwfWEIWa4cefbDi0dCzVKxrS/RU9EYB6HtMklcy3qyxbdcLmFY8qgsxjG8K\nw2iD2iECgYEA+AtmXff5lnSZq3CJhcxBpi+MuCByWH7gB2/G50XSduRmW+lzI6iv\n+r8ADEI87+KBIju++qNvj886N9H1sm+k6j3nEE51i2nwwKB79Xzu0J23+XMSCV0D\nYb6bvNogGCOhKslQNC51ZvgsZlTu6F8/EkPlboEL8E2h4eYwx3L6UbcCgYEAwvub\nB+rhUk4+TwXVnfNZEcmQiz90yU7CI/TjDrHVq+ZJIKRHILB+7Mt7Mpi+7Ie2Cx/f\nA1Alv8I44wmLhZX63Du9hwoz3t4Y0+AiT/RMp3EkmxKIkPFZNKsmY659dNzROMG9\nEVYEmBYode17mrSc4UJi8I4iHCv1A83BC3DhzNkCgYBSE8Od2I5YQOEQn76B7aLT\nkOxpiSMNMX6EN3KD2NDZ0p4kT81vwUPqHwWvCMQNRNAiOc7qNOaXmaTUD7/TeaoC\ncNViyfOPXFD0DKa4Bs0nbukPvAn92y9hSqdSCIOSOUf9VnwZqD3lAr3+ZqBfeBTw\nwFLNDBqdO7MTgw4lEWDPZQKBgQCIm3c2yN0sqR0GiHPtwfz5dVsL9F2CXOewAXbD\naNznHuTFNdOPl5iVlsqt3E6HsV1d1eqNi62m+BCbIKjb4wRrIH/dCMzmrHyAlVv0\n4JiEB8U50HZV9oIlYHP5Ctti8QK03Sf16Wo2k++tD8G11izDtZtUJoDHdBSpoZJK\nzb+loQKBgQC0/VewDbcRW5FymBPJiEnrTtpHk40x14pNfRbRrNDIx/jIx/gnqwyI\n6ud7uJkK+LAHw+r2HjHtSMVE9I54zr+QG8fAe8alJQ3mSP1tlpLbMaMb7LpomKo/\nfVVz1laGP3tcpXDEp80hbrDxO7aOexUgCFKHrYTAgVCm8Eqzz8HdsQ==\n-----END RSA PRIVATE KEY-----" } }, "body": { diff --git a/test/unit/auth-handlers.test.js b/test/unit/auth-handlers.test.js index e8a13aa18..f51d8bc6b 100644 --- a/test/unit/auth-handlers.test.js +++ b/test/unit/auth-handlers.test.js @@ -2615,8 +2615,8 @@ describe('Auth Handler:', function () { }); describe('oci', function () { - it('should have all necessary headers', function (done) { - var request = new Request(rawRequests.ociWithoutBody), + it('should have correct structure of auth header - without body', function (done) { + var request = new Request(_.cloneDeep(rawRequests.ociWithoutBody)), auth = request.auth, authInterface = createAuthInterface(auth), handler = AuthLoader.getHandler(auth.type), @@ -2626,13 +2626,16 @@ describe('Auth Handler:', function () { headers = request.getHeaders({ ignoreCase: true }); + expect(Object.keys(headers)).to.eql(['authorization', 'x-date']); expect(headers).to.have.property('authorization'); - expect(headers).to.have.property('x-date'); + expect(headers.authorization).to.include('Signature version="1"'); + expect(headers.authorization).to.include('x-date (request-target) host'); + expect(headers.authorization).to.include('algorithm="rsa-sha256"'); done(); }); }); - it('should have correct structure of auth header - without body', function (done) { - var request = new Request(rawRequests.ociWithoutBody), + it('should have correct structure of auth header - with body', function (done) { + var request = new Request(_.cloneDeep(rawRequests.ociWithBody)), auth = request.auth, authInterface = createAuthInterface(auth), handler = AuthLoader.getHandler(auth.type), @@ -2642,17 +2645,21 @@ describe('Auth Handler:', function () { headers = request.getHeaders({ ignoreCase: true }); - expect(Object.keys(headers)).to.eql(['authorization', 'x-date']) - expect(headers).to.have.property('authorization'); + expect(Object.keys(headers).sort()) + .to.eql(['authorization', 'x-date', 'content-length', 'x-content-sha256', 'content-type'].sort()); expect(headers.authorization).to.include('Signature version="1"'); - expect(headers.authorization).to.include('x-date (request-target) host'); + expect(headers.authorization) + .to.include('x-date (request-target) host content-type content-length x-content-sha256'); expect(headers.authorization).to.include('algorithm="rsa-sha256"'); done(); }); }); - - it('should have correct structure of auth header - with body', function (done) { - var request = new Request(rawRequests.ociWithBody), + it('should have correct structure of auth header - with body but force disabled', function (done) { + var rawRequest = _.merge( + _.cloneDeep(rawRequests.ociWithBody), + {auth: {oci: {forceDisableBodyHashing: true}}} + ), + request = new Request(rawRequest), auth = request.auth, authInterface = createAuthInterface(auth), handler = AuthLoader.getHandler(auth.type), @@ -2662,14 +2669,28 @@ describe('Auth Handler:', function () { headers = request.getHeaders({ ignoreCase: true }); - expect(Object.keys(headers).sort()) - .to.eql(['authorization', 'x-date', 'content-length', 'x-content-sha256', 'content-type'].sort()) + expect(Object.keys(headers)).to.eql(['authorization', 'x-date']); + expect(headers).to.have.property('authorization'); expect(headers.authorization).to.include('Signature version="1"'); - expect(headers.authorization) - .to.include('x-date (request-target) host content-type content-length x-content-sha256'); + expect(headers.authorization).to.include('x-date (request-target) host'); expect(headers.authorization).to.include('algorithm="rsa-sha256"'); done(); }); }); + it('should not work when content type is not JSON', function (done) { + var rawRequest = _.merge( + _.cloneDeep(rawRequests.ociWithBody), + {header: [{key: 'content-type', value: 'foobar'}]} + ), + request = new Request(rawRequest), + auth = request.auth, + authInterface = createAuthInterface(auth), + handler = AuthLoader.getHandler(auth.type); + + handler.sign(authInterface, request, function (res) { + expect(res).to.be.an.instanceof(Error); + done(); + }); + }); }); }); From ade7087c1f4988b3833f03b4b90987ab0159a182 Mon Sep 17 00:00:00 2001 From: Ankit Arora Date: Mon, 14 Dec 2020 14:47:01 +0530 Subject: [PATCH 15/21] Get body content properly --- lib/authorizer/oci-v1.js | 189 +++++++++++++++++++++++++-------------- package.json | 1 - 2 files changed, 124 insertions(+), 66 deletions(-) diff --git a/lib/authorizer/oci-v1.js b/lib/authorizer/oci-v1.js index ae382b556..9ff92af40 100644 --- a/lib/authorizer/oci-v1.js +++ b/lib/authorizer/oci-v1.js @@ -6,9 +6,10 @@ */ var sshpk = require('sshpk'), UrlParser = require('url'), + crypto = require('crypto'), _ = require('lodash'), httpSignature = require('http-signature'), - jssha = require('jssha'), + urlEncoder = require('postman-url-encoder'), RequestBody = require('postman-collection').RequestBody, bodyBuilder = require('../requester/core-body-builder'); @@ -98,6 +99,69 @@ class SignerRequest { } } +function computeBodyHash (body, algorithm, digestEncoding, callback) { + if (!(body && algorithm && digestEncoding) || body.isEmpty()) { return callback(); } + + var hash = crypto.createHash(algorithm), + originalReadStream, + rawBody, + urlencodedBody, + graphqlBody; + + + if (body.mode === RequestBody.MODES.raw) { + rawBody = bodyBuilder.raw(body.raw).body; + hash.update(rawBody); + + // hash.update('\n'); + return callback(hash.digest(digestEncoding), rawBody.length); + } + + if (body.mode === RequestBody.MODES.urlencoded) { + urlencodedBody = bodyBuilder.urlencoded(body.urlencoded).form; + urlencodedBody = urlEncoder.encodeQueryString(urlencodedBody); + hash.update(urlencodedBody); + hash.update('\n'); + + return callback(hash.digest(digestEncoding), urlencodedBody.length); + } + + if (body.mode === RequestBody.MODES.file) { + originalReadStream = _.get(body, 'file.content'); + + if (!originalReadStream) { + return callback(); + } + + return originalReadStream.cloneReadStream(function (err, clonedStream) { + if (err) { return callback(); } + var streamContentLength = 0; + + clonedStream.on('data', function (chunk) { + hash.update(chunk); + streamContentLength += chunk.length; + }); + + clonedStream.on('end', function () { + hash.update('\n'); + callback(hash.digest(digestEncoding), streamContentLength); + }); + }); + } + + if (body.mode === RequestBody.MODES.graphql) { + graphqlBody = bodyBuilder.graphql(body.graphql).body; + hash.update(graphqlBody); + hash.update('\n'); + + return callback(hash.digest(digestEncoding), graphqlBody.length); + } + + // @todo: Figure out a way to calculate hash for formdata body type. + + // ensure that callback is called if body.mode doesn't match with any of the above modes + return callback(); +} // ------------------------------------------------------------ // eslint-disable-next-line one-var @@ -110,78 +174,73 @@ var convertToDomHeadersObject = function (postmanHeaders) { return new Headers(rawHeaders); }, - getBodyString = function (body) { - if (body.mode === RequestBody.MODES.raw) { - return bodyBuilder.raw(body.raw).body; - } - throw new Error(`Request body mode ${body.mode} is not supported. Please use ${RequestBody.MODES.raw}`); + getBodyDetails = function (body, callback) { + computeBodyHash(body, 'sha256', 'base64', callback); }, processRequestForOci = function (request, auth, callback) { - const rawRequestUri = request.url.getRaw(), - domHeadersObject = convertToDomHeadersObject(request.headers), - uppercaseMethod = request.method.toUpperCase(), - minimumHeadersToSign = [HEADER_DATE, PSEUDOHEADER_REQUEST_TARGET, HEADER_HOST], - keyId = auth.get('tenancy') + '/' + auth.get('user') + '/' + auth.get('fingerprint'), - privateKeyBuffer = sshpk.parsePrivateKey(auth.get('privatekey'), 'auto').toBuffer('pem', {}); - - if (!domHeadersObject.has(HEADER_HOST)) { - const url = UrlParser.parse(rawRequestUri); - - if (url.host) { - domHeadersObject.set(HEADER_HOST, url.host); + getBodyDetails(request.body, function (bodyHash, bodyContentLength) { + const rawRequestUri = request.url.getRaw(), + domHeadersObject = convertToDomHeadersObject(request.headers), + uppercaseMethod = request.method.toUpperCase(), + minimumHeadersToSign = [HEADER_DATE, PSEUDOHEADER_REQUEST_TARGET, HEADER_HOST], + keyId = auth.get('tenancy') + '/' + auth.get('user') + '/' + auth.get('fingerprint'), + privateKeyBuffer = sshpk.parsePrivateKey(auth.get('privatekey'), 'auto').toBuffer('pem', {}); + + if (!domHeadersObject.has(HEADER_HOST)) { + const url = UrlParser.parse(rawRequestUri); + + if (url.host) { + domHeadersObject.set(HEADER_HOST, url.host); + } + else { + return callback(new Error('Cannot parse host from url')); + } } - else { - return callback(new Error('Cannot parse host from url')); - } - } - - if (!domHeadersObject.has(HEADER_DATE)) { - domHeadersObject.set(HEADER_DATE, new Date().toUTCString()); - } - let headersToSign = [...minimumHeadersToSign]; - if (!auth.get('forceDisableBodyHashing') && request.body && _.includes(EXTRA_HEADER_METHODS, uppercaseMethod)) { - if (!domHeadersObject.has(HEADER_CONTENT_TYPE)) { - domHeadersObject.set(HEADER_CONTENT_TYPE, CONTENT_TYPE_JSON); + if (!domHeadersObject.has(HEADER_DATE)) { + domHeadersObject.set(HEADER_DATE, new Date().toUTCString()); } - else if (domHeadersObject.get(HEADER_CONTENT_TYPE) !== CONTENT_TYPE_JSON) { - return callback(new Error(`Only ${CONTENT_TYPE_JSON} is supported by OCI Auth`)); + let headersToSign = [...minimumHeadersToSign]; + + if (!auth.get('forceDisableBodyHashing') && bodyHash && bodyContentLength && + _.includes(EXTRA_HEADER_METHODS, uppercaseMethod)) { + if (!domHeadersObject.has(HEADER_CONTENT_TYPE)) { + domHeadersObject.set(HEADER_CONTENT_TYPE, CONTENT_TYPE_JSON); + } + else if (domHeadersObject.get(HEADER_CONTENT_TYPE) !== CONTENT_TYPE_JSON) { + return callback(new Error(`Only ${CONTENT_TYPE_JSON} is supported by OCI Auth`)); + } + + if (bodyHash) { + domHeadersObject.set(HEADER_CONTENT_SHA, bodyHash); + } + if (bodyContentLength === 0) { + // if buffer is empty, it can only be an empty string payload + domHeadersObject.set(HEADER_CONTENT_SHA, EMPTY_SHA); + } + if (!domHeadersObject.has(HEADER_CONTENT_LEN)) { + domHeadersObject.set(HEADER_CONTENT_LEN, `${bodyContentLength}`); + } + headersToSign = headersToSign.concat(HEADER_CONTENT_TYPE, HEADER_CONTENT_LEN, HEADER_CONTENT_SHA); } - let contentLen = 0; - const shaObj = new jssha('SHA-256', 'TEXT'), - requestBodyString = getBodyString(request.body); - - if (requestBodyString) { - shaObj.update(requestBodyString); - domHeadersObject.set(HEADER_CONTENT_SHA, shaObj.getHash('B64')); - contentLen = Buffer.byteLength(requestBodyString, 'utf8'); - } - if (contentLen === 0) { - // if buffer is empty, it can only be an empty string payload - domHeadersObject.set(HEADER_CONTENT_SHA, EMPTY_SHA); - } - if (!domHeadersObject.has(HEADER_CONTENT_LEN)) { - domHeadersObject.set(HEADER_CONTENT_LEN, `${contentLen}`); - } - headersToSign = headersToSign.concat(HEADER_CONTENT_TYPE, HEADER_CONTENT_LEN, HEADER_CONTENT_SHA); - } - - httpSignature.sign(new SignerRequest(uppercaseMethod, rawRequestUri, domHeadersObject), { - key: privateKeyBuffer, - keyId: keyId, - headers: headersToSign + httpSignature.sign(new SignerRequest(uppercaseMethod, rawRequestUri, domHeadersObject), { + key: privateKeyBuffer, + keyId: keyId, + headers: headersToSign + }); + // NOTE: OCI needs 'authorization' but our version of httpSignature (1.3.1) + // puts signature in 'Authorization' + // eslint-disable-next-line one-var + const AUTH_HEADER_BACKWARD_COMPATIBLE = 'Authorization', + authorizationHeader = domHeadersObject.get(AUTH_HEADER_BACKWARD_COMPATIBLE); + + domHeadersObject.set(HEADER_AUTHORIZATION, + authorizationHeader.replace('Signature ', 'Signature version="1",')); + domHeadersObject.delete(AUTH_HEADER_BACKWARD_COMPATIBLE); + + return callback(domHeadersObject); }); - // NOTE: OCI needs 'authorization' but our version of httpSignature (1.3.1) puts signature in 'Authorization' - // eslint-disable-next-line one-var - const AUTH_HEADER_BACKWARD_COMPATIBLE = 'Authorization', - authorizationHeader = domHeadersObject.get(AUTH_HEADER_BACKWARD_COMPATIBLE); - - domHeadersObject.set(HEADER_AUTHORIZATION, - authorizationHeader.replace('Signature ', 'Signature version="1",')); - domHeadersObject.delete(AUTH_HEADER_BACKWARD_COMPATIBLE); - - return callback(domHeadersObject); }; diff --git a/package.json b/package.json index b69a5c019..7c9d1cb30 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,6 @@ "serialised-error": "1.1.3", "tough-cookie": "3.0.1", "uuid": "3.4.0", - "sshpk": "1.16.1", "http-signature": "1.3.1" }, "devDependencies": { From f9fc8f0fcf4b1df0bf7547cc05f8d47c2805aa3c Mon Sep 17 00:00:00 2001 From: Ankit Arora Date: Mon, 14 Dec 2020 14:51:49 +0530 Subject: [PATCH 16/21] Use correct content length --- lib/authorizer/oci-v1.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/authorizer/oci-v1.js b/lib/authorizer/oci-v1.js index 9ff92af40..ad11d3d20 100644 --- a/lib/authorizer/oci-v1.js +++ b/lib/authorizer/oci-v1.js @@ -123,7 +123,7 @@ function computeBodyHash (body, algorithm, digestEncoding, callback) { hash.update(urlencodedBody); hash.update('\n'); - return callback(hash.digest(digestEncoding), urlencodedBody.length); + return callback(hash.digest(digestEncoding), urlencodedBody.length + 1); } if (body.mode === RequestBody.MODES.file) { @@ -154,7 +154,7 @@ function computeBodyHash (body, algorithm, digestEncoding, callback) { hash.update(graphqlBody); hash.update('\n'); - return callback(hash.digest(digestEncoding), graphqlBody.length); + return callback(hash.digest(digestEncoding), graphqlBody.length + 1); } // @todo: Figure out a way to calculate hash for formdata body type. From 458912e10371f73831926742841a3cdbaf6e51d7 Mon Sep 17 00:00:00 2001 From: Ankit Arora Date: Mon, 14 Dec 2020 15:03:27 +0530 Subject: [PATCH 17/21] minor fix --- lib/authorizer/oci-v1.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/authorizer/oci-v1.js b/lib/authorizer/oci-v1.js index ad11d3d20..9483fb546 100644 --- a/lib/authorizer/oci-v1.js +++ b/lib/authorizer/oci-v1.js @@ -300,7 +300,7 @@ module.exports = { */ pre: function (auth, done) { done(null, Boolean(auth.get('tenancy') && auth.get('user') && - auth.get('fingerprint') && auth.get('private_key'))); + auth.get('fingerprint') && auth.get('privatekey'))); }, /** From 94b72080be1d28f660dbf89a4525e92b0e17d7fd Mon Sep 17 00:00:00 2001 From: Ankit Arora Date: Mon, 14 Dec 2020 15:20:19 +0530 Subject: [PATCH 18/21] Move headers polyfill to separate file --- lib/authorizer/oci-v1.js | 57 +--------------------------------------- lib/authorizer/util.js | 56 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 56 deletions(-) create mode 100644 lib/authorizer/util.js diff --git a/lib/authorizer/oci-v1.js b/lib/authorizer/oci-v1.js index 9483fb546..3e323cbaa 100644 --- a/lib/authorizer/oci-v1.js +++ b/lib/authorizer/oci-v1.js @@ -7,6 +7,7 @@ var sshpk = require('sshpk'), UrlParser = require('url'), crypto = require('crypto'), + Headers = require('./util'), _ = require('lodash'), httpSignature = require('http-signature'), urlEncoder = require('postman-url-encoder'), @@ -27,62 +28,6 @@ const HEADER_CONTENT_SHA = 'x-content-sha256', // -------------------- POLYFILL for input to httpSignature.sign --------------------------- -function Headers (values) { - this._values = values || {}; -} - -Headers.prototype.append = function (name, value) { - this._values[name] = value; -}; - -Headers.prototype.delete = function (name) { - delete this._values[name]; -}; - -Headers.prototype.entries = function () { - const result = []; - - for (let key in this._values) { - result.push([key, this._values[key]]); - } - - return result; -}; - -Headers.prototype.get = function (name) { - return this._values[name]; -}; - -Headers.prototype.has = function (name) { - return name in this._values; -}; - -Headers.prototype.keys = function () { - const result = []; - - for (let key in this._values) { - result.push(key); - } - - return result; -}; - -Headers.prototype.set = function (name, value) { - this._values[name] = value; -}; - -// eslint-disable-next-line no-unused-vars -Headers.prototype.values = function (name, value) { - const result = []; - - // eslint-disable-next-line guard-for-in - for (let key in this._values) { - result.push(this._values[key]); - } - - return result; -}; - class SignerRequest { constructor (method, url, headers) { this.headers = headers; diff --git a/lib/authorizer/util.js b/lib/authorizer/util.js new file mode 100644 index 000000000..7902a96d5 --- /dev/null +++ b/lib/authorizer/util.js @@ -0,0 +1,56 @@ + +function Headers (values) { + this._values = values || {}; +} + +Headers.prototype.append = function (name, value) { + this._values[name] = value; +}; + +Headers.prototype.delete = function (name) { + delete this._values[name]; +}; + +Headers.prototype.entries = function () { + const result = []; + + for (let key in this._values) { + result.push([key, this._values[key]]); + } + + return result; +}; + +Headers.prototype.get = function (name) { + return this._values[name]; +}; + +Headers.prototype.has = function (name) { + return name in this._values; +}; + +Headers.prototype.keys = function () { + const result = []; + + for (let key in this._values) { + result.push(key); + } + + return result; +}; + +Headers.prototype.set = function (name, value) { + this._values[name] = value; +}; + +// eslint-disable-next-line no-unused-vars +Headers.prototype.values = function (name, value) { + const result = []; + + // eslint-disable-next-line guard-for-in + for (let key in this._values) { + result.push(this._values[key]); + } + + return result; +}; From ae6d1c5453ea9788f84795a081de3ef134312449 Mon Sep 17 00:00:00 2001 From: Ankit Arora Date: Mon, 14 Dec 2020 15:59:34 +0530 Subject: [PATCH 19/21] Add sshpk dependency back --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 7c9d1cb30..8421e5abd 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,8 @@ "serialised-error": "1.1.3", "tough-cookie": "3.0.1", "uuid": "3.4.0", - "http-signature": "1.3.1" + "http-signature": "1.3.1", + "sshpk": "1.16.1" }, "devDependencies": { "@postman/shipit": "0.2.0", From d87fb1fb5ffefa1a08a8d668e0f15e963c8647b7 Mon Sep 17 00:00:00 2001 From: Ankit Arora Date: Mon, 14 Dec 2020 16:03:44 +0530 Subject: [PATCH 20/21] Fix headers import --- lib/authorizer/oci-v1.js | 2 +- lib/authorizer/util.js | 4 + package-lock.json | 167 ++------------------------------------- 3 files changed, 11 insertions(+), 162 deletions(-) diff --git a/lib/authorizer/oci-v1.js b/lib/authorizer/oci-v1.js index 3e323cbaa..5f8427e38 100644 --- a/lib/authorizer/oci-v1.js +++ b/lib/authorizer/oci-v1.js @@ -7,7 +7,7 @@ var sshpk = require('sshpk'), UrlParser = require('url'), crypto = require('crypto'), - Headers = require('./util'), + Headers = require('./util').Headers, _ = require('lodash'), httpSignature = require('http-signature'), urlEncoder = require('postman-url-encoder'), diff --git a/lib/authorizer/util.js b/lib/authorizer/util.js index 7902a96d5..258d0f32a 100644 --- a/lib/authorizer/util.js +++ b/lib/authorizer/util.js @@ -54,3 +54,7 @@ Headers.prototype.values = function (name, value) { return result; }; + +module.exports = { + Headers: Headers +}; diff --git a/package-lock.json b/package-lock.json index 4afad69c1..809c3b1b8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -234,11 +234,6 @@ "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", "dev": true }, - "@types/isomorphic-fetch": { - "version": "0.0.35", - "resolved": "https://registry.npmjs.org/@types/isomorphic-fetch/-/isomorphic-fetch-0.0.35.tgz", - "integrity": "sha512-DaZNUvLDCAnCTjgwxgiL1eQdxIKEpNLOlTNtAgnZc50bG2copGhRrFN9/PxPBuJe+tZVLCbQ7ls0xveXVRPkvw==" - }, "JSONStream": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", @@ -1018,11 +1013,6 @@ "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", "dev": true }, - "buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" - }, "buffer-fill": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", @@ -2144,14 +2134,6 @@ "safer-buffer": "^2.1.0" } }, - "ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "requires": { - "safe-buffer": "^5.0.1" - } - }, "editorconfig": { "version": "0.15.3", "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz", @@ -2205,24 +2187,6 @@ "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", "dev": true }, - "encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "requires": { - "iconv-lite": "^0.6.2" - }, - "dependencies": { - "iconv-lite": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", - "integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - } - } - } - }, "engine.io": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz", @@ -2366,11 +2330,6 @@ "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", "dev": true }, - "es6-promise": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.6.tgz", - "integrity": "sha512-aRVgGdnmW2OiySVPUC9e6m+plolMAJKjZnQlCwNSuK5yQ0JN61DZSO1X1Ufd1foqWRAlig0rhduTCHe7sVtK5Q==" - }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -3879,7 +3838,8 @@ "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true }, "is-symbol": { "version": "1.0.2", @@ -3928,15 +3888,6 @@ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true }, - "isomorphic-fetch": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", - "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", - "requires": { - "node-fetch": "^1.0.1", - "whatwg-fetch": ">=0.10.0" - } - }, "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", @@ -4237,23 +4188,6 @@ "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", "dev": true }, - "jsonwebtoken": { - "version": "8.5.1", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", - "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", - "requires": { - "jws": "^3.2.2", - "lodash.includes": "^4.3.0", - "lodash.isboolean": "^3.0.3", - "lodash.isinteger": "^4.0.4", - "lodash.isnumber": "^3.0.3", - "lodash.isplainobject": "^4.0.6", - "lodash.isstring": "^4.0.1", - "lodash.once": "^4.0.0", - "ms": "^2.1.1", - "semver": "^5.6.0" - } - }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -4265,36 +4199,12 @@ "verror": "1.10.0" } }, - "jssha": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/jssha/-/jssha-2.4.1.tgz", - "integrity": "sha512-77DN1YurYgh+7FPCTJ2CQ6hVDHgIWiHxm4Y5/mAdnpETKYagX22pVWMz4xfKF5fcpNfMaztgVj+/B1bt2k23Eg==" - }, "just-extend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.0.2.tgz", "integrity": "sha512-FrLwOgm+iXrPV+5zDU6Jqu4gCRXbWEQg2O3SKONsWE4w7AXFRkryS53bpWdaL9cNol+AmR3AEYz6kn+o0fCPnw==", "dev": true }, - "jwa": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", - "requires": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", - "requires": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, "karma": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/karma/-/karma-3.1.4.tgz", @@ -4764,26 +4674,6 @@ "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", "dev": true }, - "lodash.includes": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", - "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" - }, - "lodash.isboolean": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", - "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" - }, - "lodash.isinteger": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", - "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" - }, - "lodash.isnumber": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", - "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=" - }, "lodash.isplainobject": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", @@ -4811,11 +4701,6 @@ "integrity": "sha1-brGa5aHuHdnfC5aeZs4Lf6MLXmA=", "dev": true }, - "lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" - }, "lodash.padend": { "version": "4.6.1", "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz", @@ -5404,7 +5289,8 @@ "ms": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true }, "mute-stream": { "version": "0.0.7", @@ -5499,15 +5385,6 @@ } } }, - "node-fetch": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", - "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", - "requires": { - "encoding": "^0.1.11", - "is-stream": "^1.0.1" - } - }, "node-oauth1": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/node-oauth1/-/node-oauth1-1.3.0.tgz", @@ -5769,29 +5646,6 @@ "isobject": "^3.0.1" } }, - "oci-common": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/oci-common/-/oci-common-1.9.0.tgz", - "integrity": "sha512-+gJloBEJOKBfOiPoaR/TVsT2mi/s89iOg147K3uyOHanyIHC17B1LOuVylDhFW68TTup2J8QxLBNZiS9889Bsg==", - "requires": { - "@types/isomorphic-fetch": "0.0.35", - "es6-promise": "4.2.6", - "http-signature": "1.3.1", - "isomorphic-fetch": "2.2.1", - "jsonwebtoken": "8.5.1", - "jssha": "2.4.1", - "opossum": "5.0.1", - "sshpk": "1.16.1", - "uuid": "3.3.3" - }, - "dependencies": { - "uuid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", - "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==" - } - } - }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -5819,11 +5673,6 @@ "mimic-fn": "^1.0.0" } }, - "opossum": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/opossum/-/opossum-5.0.1.tgz", - "integrity": "sha512-iUDUQmFl3RanaBVLMDTZ6WtXj/Hk84pwJ5JWoJaQd1lXGifdApHhszI3biZvdBDdpTERCmB6x+7+uNvzhzVZIg==" - }, "optimist": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", @@ -6800,7 +6649,8 @@ "semver": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", - "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==" + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", + "dev": true }, "send": { "version": "0.17.1", @@ -8707,11 +8557,6 @@ "integrity": "sha512-kudCA8PXVQfrqv2mFTG72vDBRi8BKWxGgFLwPpzHcpZnSwZk93WMwUDVcLHWNsnm+Y0AC4Vb6MUNRgaHfyV2DQ==", "dev": true }, - "whatwg-fetch": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.5.0.tgz", - "integrity": "sha512-jXkLtsR42xhXg7akoDKvKWE40eJeI+2KZqcp2h3NsOrRnDvtWX36KcKl30dy+hxECivdk2BVUHVNrPtoMBUx6A==" - }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", From d84866489c8eb87eb6fd29b922a2e5d9921b7d79 Mon Sep 17 00:00:00 2001 From: Ankit Arora Date: Mon, 14 Dec 2020 20:10:55 +0530 Subject: [PATCH 21/21] Add test case for pre --- test/unit/auth-handlers.test.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/unit/auth-handlers.test.js b/test/unit/auth-handlers.test.js index f51d8bc6b..7217a9d34 100644 --- a/test/unit/auth-handlers.test.js +++ b/test/unit/auth-handlers.test.js @@ -2692,5 +2692,19 @@ describe('Auth Handler:', function () { done(); }); }); + it('should not allow sign to be reached if required parameters arent there', function (done) { + var rawRequest = _.cloneDeep(rawRequests.ociWithBody); + + rawRequest.auth.oci.privatekey = undefined; + var request = new Request(rawRequest), + auth = request.auth, + authInterface = createAuthInterface(auth), + handler = AuthLoader.getHandler(auth.type); + + handler.pre(authInterface, function (a, b) { + expect(b).to.be.eql(false); + done(); + }); + }); }); });