Skip to content

fix: support mTLS in 1.0 Binary and Structured emitters #53

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)

## [Unreleased]

### Fixed

- Support for mTLS in v1.0 Binary and Structured Emitters: issue [#48](https://github.com/cloudevents/sdk-javascript/issues/48). Note that this fix is only valid for v1.0 and does not address the problem in v0.3 and below.

## [1.0.0]

### Added
Expand Down
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
};