Skip to content

Commit

Permalink
fix: support mTLS in 1.0 Binary and Structured emitters
Browse files Browse the repository at this point in the history
This commit modifies both of the 1.0 emitters so that they may
accept typed objects as a part of the configuration. When using
mTLS in Node, you need to provide an `Agent` to the underlying
HTTP handler. In this case, Axios will pass this object along to
Node.js when it is provided.

Fixes: cloudevents#48

Signed-off-by: Lance Ball <lball@redhat.com>
  • Loading branch information
lance committed Apr 8, 2020
1 parent 4a199d4 commit 3a063d7
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 57 deletions.
46 changes: 18 additions & 28 deletions lib/bindings/http/emitter_binary.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,58 +2,48 @@ var axios = require("axios");
var empty = require("is-empty");

const Constants = require("./constants.js");
const defaults = {};
defaults[Constants.HEADERS] = {};
defaults[Constants.HEADERS][Constants.HEADER_CONTENT_TYPE] = Constants.DEFAULT_CONTENT_TYPE;

function BinaryHTTPEmitter(config, headerByGetter, extensionPrefix){
this.config = JSON.parse(JSON.stringify(config));
this.config = Object.assign({}, defaults, config);
this.headerByGetter = headerByGetter;
this.extensionPrefix = extensionPrefix;

this.config[Constants.HEADERS] =
(!this.config[Constants.HEADERS]
? {}
: this.config[Constants.HEADERS]);

// default is json
if(!this.config[Constants.HEADERS][Constants.HEADER_CONTENT_TYPE]){
this.config[Constants.HEADERS][Constants.HEADER_CONTENT_TYPE] =
Constants.DEFAULT_CONTENT_TYPE;
}
}

BinaryHTTPEmitter.prototype.emit = function(cloudevent) {
// Create new request object
var _config = JSON.parse(JSON.stringify(this.config));

// Always set stuff in _config
var _headers = _config[Constants.HEADERS];
BinaryHTTPEmitter.prototype.emit = function (cloudevent) {
const config = Object.assign({}, this.config);
const headers = Object.assign({}, this.config[Constants.HEADERS]);

Object.keys(this.headerByGetter)
.filter((getter) => cloudevent[getter]())
.forEach((getter) => {
let header = this.headerByGetter[getter];
_headers[header.name] =
const header = this.headerByGetter[getter];
headers[header.name] =
header.parser(
cloudevent[getter]()
);
});

// Set the cloudevent payload
let formatted = cloudevent.format();
const formatted = cloudevent.format();
let data = formatted.data;
data = (formatted.data_base64 ? formatted.data_base64: data);

_config[Constants.DATA_ATTRIBUTE] = data;

// Have extensions?
var exts = cloudevent.getExtensions();
const exts = cloudevent.getExtensions();
Object.keys(exts)
.filter((ext) => Object.hasOwnProperty.call(exts, ext))
.forEach((ext) => {
_headers[this.extensionPrefix + ext] = exts[ext];
headers[this.extensionPrefix + ext] = exts[ext];
});

// Return the Promise
return axios.request(_config);
};
config[Constants.DATA_ATTRIBUTE] = data;
config.headers = headers;

// Return the Promise
return axios.request(config);
};

module.exports = BinaryHTTPEmitter;
27 changes: 10 additions & 17 deletions lib/bindings/http/emitter_structured.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,23 @@
var axios = require("axios");

const Constants = require("./constants.js");
const defaults = {};
defaults[Constants.HEADERS] = {};
defaults[Constants.HEADERS][Constants.HEADER_CONTENT_TYPE] = Constants.DEFAULT_CE_CONTENT_TYPE;

function StructuredHTTPEmitter(configuration){
this.config = JSON.parse(JSON.stringify(configuration));

this.config[Constants.HEADERS] =
(!this.config[Constants.HEADERS]
? {}
: this.config[Constants.HEADERS]);

if(!this.config[Constants.HEADERS][Constants.HEADER_CONTENT_TYPE]){
this.config[Constants.HEADERS][Constants.HEADER_CONTENT_TYPE] =
Constants.DEFAULT_CE_CONTENT_TYPE;
}
this.config = Object.assign({}, defaults, configuration);
}

StructuredHTTPEmitter.prototype.emit = function(cloudevent) {
// Create new request object
var _config = JSON.parse(JSON.stringify(this.config));

StructuredHTTPEmitter.prototype.emit = function (cloudevent) {
// Set the cloudevent payload
_config[Constants.DATA_ATTRIBUTE] = cloudevent.format();
this.config[Constants.DATA_ATTRIBUTE] = cloudevent.format();

// Return the Promise
return axios.request(_config);
return axios.request(this.config).then(response => {
delete this.config[Constants.DATA_ATTRIBUTE];
return response;
});
};

module.exports = StructuredHTTPEmitter;
54 changes: 42 additions & 12 deletions test/http_binding_1.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
const expect = require("chai").expect;
const nock = require("nock");
const http = require("http");
const request = require("request");
const https = require("https");
const {asBase64} = require("../lib/utils/fun.js");

const BinaryHTTPEmitter =
require("../lib/bindings/http/emitter_binary_1.js");
const Cloudevent = require("../lib/cloudevent.js");

const v1 = require("../v1/index.js");
const {
Spec,
BinaryHTTPEmitter,
StructuredHTTPEmitter,
Cloudevent
} = require("../v1/index.js");

const type = "com.github.pull.create";
const source = "urn:event:from:myapi/resourse/123";
Expand All @@ -28,7 +28,7 @@ const ext2Name = "extension2";
const ext2Value = "acme";

const cloudevent =
new Cloudevent(v1.Spec)
new Cloudevent(Spec)
.type(type)
.source(source)
.dataContentType(ceContentType)
Expand All @@ -48,7 +48,7 @@ const httpcfg = {
};

const binary = new BinaryHTTPEmitter(httpcfg);
const structured = new v1.StructuredHTTPEmitter(httpcfg);
const structured = new StructuredHTTPEmitter(httpcfg);

describe("HTTP Transport Binding - Version 1.0", () => {
beforeEach(() => {
Expand All @@ -59,6 +59,21 @@ describe("HTTP Transport Binding - Version 1.0", () => {
});

describe("Structured", () => {
it('works with mTLS authentication', () => {
const event = new StructuredHTTPEmitter({
method: 'POST',
url: `${webhook}/json`,
httpsAgent: new https.Agent({
cert: 'some value',
key: 'other value'
})
})
return event.emit(cloudevent).then(response => {
expect(response.config.headers['Content-Type'])
.to.equal(contentType);
});
});

describe("JSON Format", () => {
it("requires '" + contentType + "' Content-Type in the header", () => {
return structured.emit(cloudevent)
Expand All @@ -81,7 +96,7 @@ describe("HTTP Transport Binding - Version 1.0", () => {
let bindata = Uint32Array.from(dataString, (c) => c.codePointAt(0));
let expected = asBase64(bindata);
let binevent =
new Cloudevent(v1.Spec)
new Cloudevent(Spec)
.type(type)
.source(source)
.dataContentType("text/plain")
Expand All @@ -98,7 +113,7 @@ describe("HTTP Transport Binding - Version 1.0", () => {

it("the payload must have 'data_base64' when data is binary", () => {
let binevent =
new Cloudevent(v1.Spec)
new Cloudevent(Spec)
.type(type)
.source(source)
.dataContentType("text/plain")
Expand All @@ -117,6 +132,21 @@ describe("HTTP Transport Binding - Version 1.0", () => {
});

describe("Binary", () => {
it('works with mTLS authentication', () => {
const event = new BinaryHTTPEmitter({
method: 'POST',
url: `${webhook}/json`,
httpsAgent: new https.Agent({
cert: 'some value',
key: 'other value'
})
})
return event.emit(cloudevent).then(response => {
expect(response.config.headers['Content-Type'])
.to.equal(cloudevent.getDataContentType());
});
});

describe("JSON Format", () => {
it("requires '" + cloudevent.getDataContentType() + "' Content-Type in the header", () => {
return binary.emit(cloudevent)
Expand All @@ -138,7 +168,7 @@ describe("HTTP Transport Binding - Version 1.0", () => {
let bindata = Uint32Array.from(dataString, (c) => c.codePointAt(0));
let expected = asBase64(bindata);
let binevent =
new Cloudevent(v1.Spec)
new Cloudevent(Spec)
.type(type)
.source(source)
.dataContentType("text/plain")
Expand Down
2 changes: 2 additions & 0 deletions v1/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,7 @@ module.exports = {
BinaryHTTPEmitter,
StructuredHTTPReceiver,
BinaryHTTPReceiver,
Cloudevent: event,
CloudEvent: event,
event
};

0 comments on commit 3a063d7

Please sign in to comment.