Skip to content

Commit a6f31fd

Browse files
committed
Jsonata: Support creating TLS server
Signed-off-by: Pierangelo Di Pilato <pierdipi@redhat.com>
1 parent 1e6f101 commit a6f31fd

File tree

6 files changed

+167
-23
lines changed

6 files changed

+167
-23
lines changed

transform-jsonata/README.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,12 @@ broker <- trigger <- (response) <-
1515
Assuming current working directory is `transform-jsonata`
1616

1717
```shell
18-
npm dev
18+
npm run dev
1919

20-
# or npm dev-kubevirt to inject a different example transformation
20+
npm run dev-kubevirt # to inject a different example transformation
21+
22+
npm run dev-tls # to start the HTTP and HTTPS Servers
23+
npm run dev-tls-only # to start the HTTPS Server only
2124
```
2225

2326
### Tracing

transform-jsonata/jsonata.js

Lines changed: 91 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ const express = require('express');
22
const {HTTP} = require("cloudevents");
33
const jsonata = require('jsonata');
44
const fs = require('node:fs');
5+
const http = require('http');
6+
const https = require('https');
57
const fsPromises = require('node:fs').promises;
68
const {buffer} = require('node:stream/consumers');
79

@@ -31,10 +33,18 @@ const {ZipkinExporter} = require('@opentelemetry/exporter-zipkin');
3133
const {W3CTraceContextPropagator, CompositePropagator} = require("@opentelemetry/core");
3234
const {B3InjectEncoding, B3Propagator} = require("@opentelemetry/propagator-b3");
3335

34-
const port = process.env.PORT = process.env.PORT || 8080;
36+
const httpPort = process.env.HTTP_PORT || 8080;
37+
const httpsPort = process.env.HTTPS_PORT || 8443;
38+
const httpsCertPath = process.env.HTTPS_CERT_PATH;
39+
const httpsKeyPath = process.env.HTTPS_KEY_PATH;
40+
const disableHTTPServer = process.env.DISABLE_HTTP_SERVER === 'true';
3541
const k_sink = process.env.K_SINK || undefined;
3642
const jsonata_transform_file_name = process.env.JSONATA_TRANSFORM_FILE_NAME || undefined;
3743

44+
if (disableHTTPServer && (!httpsKeyPath || !fs.existsSync(httpsKeyPath) || !httpsCertPath || !fs.existsSync(httpsCertPath))) {
45+
throw new Error(`HTTP and HTTPS server are both disabled, disableHTTPServer='${disableHTTPServer}', httpsKeyPath='${httpsKeyPath}', httpsCertPath=${httpsCertPath}`);
46+
}
47+
3848
// Allow transforming the response received by the endpoint defined by K_SINK
3949
const jsonata_response_transform_file_name = process.env.JSONATA_RESPONSE_TRANSFORM_FILE_NAME || undefined;
4050

@@ -250,7 +260,7 @@ app.post("/", async (req, res) => {
250260
const k_sink_url = new URL(k_sink)
251261
const kSinkSendSpan = tracer.startSpan('k_sink_send', {
252262
attributes: {
253-
[ATTR_URL_SCHEME]: k_sink_url.protocol.endsWith(':') ? k_sink_url.protocol.substring(0, k_sink_url.protocol.length-1) : k_sink_url.protocol,
263+
[ATTR_URL_SCHEME]: k_sink_url.protocol.endsWith(':') ? k_sink_url.protocol.substring(0, k_sink_url.protocol.length - 1) : k_sink_url.protocol,
254264
[ATTR_SERVER_ADDRESS]: k_sink_url.hostname,
255265
[ATTR_SERVER_PORT]: k_sink_url.port,
256266
}
@@ -267,6 +277,7 @@ app.post("/", async (req, res) => {
267277
headers: k_sink_request_headers,
268278
body: JSON.stringify(transformed),
269279
redirect: 'error',
280+
signal: req.signal,
270281
})
271282
kSinkSendSpan.setAttributes({
272283
'http.status_code': result.status,
@@ -384,19 +395,71 @@ app.get('/readyz', (req, res) => {
384395

385396
app.disable('x-powered-by');
386397

387-
const server = app.listen(port, () => {
388-
console.log(`Jsonata server listening on port ${port}`)
389-
})
398+
let httpServer = null
399+
let httpsServer = null
400+
401+
if (!disableHTTPServer) {
402+
httpServer = http.createServer(app)
403+
.listen(httpPort, () => {
404+
console.log(`Jsonata HTTP server listening on port ${httpPort}`)
405+
})
406+
}
407+
408+
if (httpsCertPath && httpsKeyPath) {
409+
const httpsServerOptions = {
410+
cert: fs.readFileSync(httpsCertPath),
411+
key: fs.readFileSync(httpsKeyPath),
412+
413+
// TLS Versions
414+
minVersion: 'TLSv1.2', // Minimum TLS version (avoid older, less secure protocols)
415+
maxVersion: 'TLSv1.3', // Maximum TLS version
416+
417+
// Cipher Suites
418+
ciphers: [
419+
'ECDHE-ECDSA-AES128-GCM-SHA256',
420+
'ECDHE-RSA-AES128-GCM-SHA256',
421+
'ECDHE-ECDSA-AES256-GCM-SHA384',
422+
'ECDHE-RSA-AES256-GCM-SHA384',
423+
'ECDHE-ECDSA-CHACHA20-POLY1305',
424+
'ECDHE-RSA-CHACHA20-POLY1305',
425+
'DHE-RSA-AES128-GCM-SHA256',
426+
'DHE-RSA-AES256-GCM-SHA384'
427+
].join(':'),
428+
429+
// Attempt to use server cipher suite preference instead of clients
430+
honorCipherOrder: true,
431+
432+
// Additional security options
433+
secureOptions:
434+
require('constants').SSL_OP_NO_TLSv1 |
435+
require('constants').SSL_OP_NO_TLSv1_1 |
436+
require('constants').SSL_OP_NO_COMPRESSION,
437+
}
438+
439+
httpsServer = https.createServer(httpsServerOptions, app)
440+
.listen(httpsPort, () => {
441+
console.log(`Jsonata HTTPS server listening on port ${httpsPort}`)
442+
})
443+
}
390444

391445
process.on('SIGINT', shutDown);
392446
process.on('SIGTERM', shutDownNow);
393447

394448
let connections = [];
395449

396-
server.on('connection', connection => {
397-
connections.push(connection);
398-
connection.on('close', () => connections = connections.filter(curr => curr !== connection));
399-
});
450+
if (httpServer) {
451+
httpServer.on('connection', connection => {
452+
connections.push(connection);
453+
connection.on('close', () => connections = connections.filter(curr => curr !== connection));
454+
});
455+
}
456+
457+
if (httpsServer) {
458+
httpsServer.on('connection', connection => {
459+
connections.push(connection);
460+
connection.on('close', () => connections = connections.filter(curr => curr !== connection));
461+
});
462+
}
400463

401464
function shutDown() {
402465
console.log('Received interrupt signal, shutting down gracefully');
@@ -413,14 +476,30 @@ function shutDown() {
413476
function shutDownNow() {
414477
console.log('Shutting down gracefully');
415478

416-
server.close(() => {
417-
console.log('Closed out remaining connections');
479+
const closePromises = []
480+
if (httpServer) {
481+
closePromises.push(new Promise((resolve, _) => {
482+
httpServer.close(() => {
483+
console.log('Closed out remaining HTTP connections');
484+
resolve()
485+
});
486+
}))
487+
}
488+
if (httpsServer) {
489+
closePromises.push(new Promise((resolve, _) => {
490+
httpsServer.close(() => {
491+
console.log('Closed out remaining HTTPS connections');
492+
resolve()
493+
});
494+
}))
495+
}
418496

497+
Promise.all(closePromises).then(() => {
419498
console.log('Shutting down tracing...');
420499
batchSpanProcessor.shutdown().then(() => {
421500
process.exit(0);
422501
});
423-
});
502+
})
424503

425504
setTimeout(() => {
426505
console.error('Could not close connections in time, forcefully shutting down');

transform-jsonata/package-lock.json

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

transform-jsonata/package.json

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,28 @@
33
"author": "Knative authors",
44
"scripts": {
55
"dev": "NODE_ENV=development OIDC_TOKEN_FILE=./examples/example-token.txt JSONATA_TRANSFORM_FILE_NAME=./examples/jsonata_transform_identity.jsonata nodemon ./jsonata.js",
6+
"dev-tls": "HTTPS_CERT_PATH=./ssl/server.crt HTTPS_KEY_PATH=./ssl/server.key npm run dev",
7+
"dev-tls-only": "DISABLE_HTTP_SERVER=true HTTPS_CERT_PATH=./ssl/server.crt HTTPS_KEY_PATH=./ssl/server.key npm run dev",
68
"dev-kubevirt": "NODE_ENV=development OIDC_TOKEN_FILE=./examples/example-token.txt JSONATA_TRANSFORM_FILE_NAME=./examples/ce_apiserversource_kubevirt.jsonata nodemon ./jsonata.js",
79
"dev-zipkin": "NODE_ENV=development K_TRACING_CONFIG='{\"backend\":\"zipkin\", \"zipkin-endpoint\": \"http://localhost:9411/api/v2/spans\", \"sample-rate\":\"1\"}' OIDC_TOKEN_FILE=./examples/example-token.txt JSONATA_TRANSFORM_FILE_NAME=./examples/jsonata_transform_identity.jsonata nodemon ./jsonata.js"
810
},
911
"dependencies": {
10-
"jsonata": "^2.0.6",
11-
"cloudevents": "^8.0.2",
12-
"express": "^4.21.2",
1312
"@opentelemetry/api": "1.9.0",
1413
"@opentelemetry/core": "^1.30.1",
15-
"@opentelemetry/sdk-trace-node": "^1.30.1",
14+
"@opentelemetry/exporter-zipkin": "^1.30.1",
15+
"@opentelemetry/propagator-b3": "^1.30.1",
1616
"@opentelemetry/resources": "^1.30.1",
17-
"@opentelemetry/semantic-conventions": "^1.30.0",
1817
"@opentelemetry/sdk-trace-base": "^1.30.1",
19-
"@opentelemetry/exporter-zipkin": "^1.30.1",
20-
"@opentelemetry/propagator-b3": "^1.30.1"
18+
"@opentelemetry/sdk-trace-node": "^1.30.1",
19+
"@opentelemetry/semantic-conventions": "^1.30.0",
20+
"cloudevents": "^8.0.2",
21+
"constants": "^0.0.2",
22+
"express": "^4.21.2",
23+
"jsonata": "^2.0.6"
2124
},
2225
"devDependencies": {
23-
"nodemon": "^3.1.9",
26+
"@types/express": "^4.17.21",
2427
"@types/node": "^22.13.1",
25-
"@types/express": "^4.17.21"
28+
"nodemon": "^3.1.9"
2629
}
2730
}

transform-jsonata/ssl/server.crt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIDZTCCAk2gAwIBAgIUJiHToGug5ZT3z3Gw4vSVem5U9FYwDQYJKoZIhvcNAQEL
3+
BQAwQjELMAkGA1UEBhMCWFgxFTATBgNVBAcMDERlZmF1bHQgQ2l0eTEcMBoGA1UE
4+
CgwTRGVmYXVsdCBDb21wYW55IEx0ZDAeFw0yNTAzMDQxNDQwNDhaFw0yNjAzMDQx
5+
NDQwNDhaMEIxCzAJBgNVBAYTAlhYMRUwEwYDVQQHDAxEZWZhdWx0IENpdHkxHDAa
6+
BgNVBAoME0RlZmF1bHQgQ29tcGFueSBMdGQwggEiMA0GCSqGSIb3DQEBAQUAA4IB
7+
DwAwggEKAoIBAQC6I8jX2OPxGA0ZaGWx2OQ/pkrfNit2m6AbrgcOUKV/5DXt6Ixz
8+
6zPZCDf6J1vglZMDIwEmfFsQGjNA8UJwOBhUw//hXJVXEl8coBCsBySlhUmSZdrl
9+
19IWZwM4qE3qhWVbOgUZVQoCZn1aZezg3uh5XknTNh7rQImvgx7bo9OD5zKfkKLT
10+
3uET7dBYWJkKxuNPNbIz5rbSBzaVGnGxTNlp2xvPgUUCeEQfVtFNIqjLHk4Gi4lM
11+
YsqJpLptGGCx9xJDcqg0uoFWxNn8i1bBp+YK4IsjqgnIhCKRWmo6gUnBILZuUyvt
12+
pWMxD+9USxn7b3DvPKinIluYzFG1BaqVeYa7AgMBAAGjUzBRMB0GA1UdDgQWBBQZ
13+
+uCFRmib6b2cg2a+20//Iva92TAfBgNVHSMEGDAWgBQZ+uCFRmib6b2cg2a+20//
14+
Iva92TAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCFywZPNVZk
15+
qx83Hm15O0KZ7qI4VfQI895dtuQrTMIxtu/GhdZq5P8Gc4Rt0cxfldZSNtVADXCM
16+
LFWk9EjBTUZUGavT/okoFPM5cMWrp3FYInYJJEfIvhvVeOcVLwaxvrKQLM8llj66
17+
OC7OTzvkKFBu4LYJIIg/4ZGOwSa1n7Sjo2jmbZMmij8cQjI7xNfLRV3mpkw5lHzY
18+
ZF/SrvBElOU3oqXV3P78TGqJe5Ji9k08aBuzJZcijYQ9IFP9bz6JK+BDZUxIicAD
19+
1ftC0b+S3Ni+qV84NV40SKGpgPQVn4XxKz96zJCehjGjkXGCzJEcK5tJtu5dXPm5
20+
Sy7ybr6/xnt3
21+
-----END CERTIFICATE-----

transform-jsonata/ssl/server.key

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
-----BEGIN PRIVATE KEY-----
2+
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC6I8jX2OPxGA0Z
3+
aGWx2OQ/pkrfNit2m6AbrgcOUKV/5DXt6Ixz6zPZCDf6J1vglZMDIwEmfFsQGjNA
4+
8UJwOBhUw//hXJVXEl8coBCsBySlhUmSZdrl19IWZwM4qE3qhWVbOgUZVQoCZn1a
5+
Zezg3uh5XknTNh7rQImvgx7bo9OD5zKfkKLT3uET7dBYWJkKxuNPNbIz5rbSBzaV
6+
GnGxTNlp2xvPgUUCeEQfVtFNIqjLHk4Gi4lMYsqJpLptGGCx9xJDcqg0uoFWxNn8
7+
i1bBp+YK4IsjqgnIhCKRWmo6gUnBILZuUyvtpWMxD+9USxn7b3DvPKinIluYzFG1
8+
BaqVeYa7AgMBAAECggEAMI+MYq9tTCUrqbDAMyUz6t0N1GzT6vYPz5jXs2bbvmFB
9+
pocQOV+nn5vSyrrA7/blqyBTOQChWzKSo4Mtg4xG4Lpfg6I9PcGHubaSkuasK1h6
10+
CKz07hifcQO/5eSWqzPQ7PtWgDTczyKA2ngT09ijiqJMHUOVzmcAZJ8PClsTn+nb
11+
VbkN4/oCm1OAU8gIxhVLNr0vBQrLfL4Yu+gq4C+yX02Nq/Hzr0prGQcNl6ynwzoD
12+
RbGhsi0HMYdICxA3Ojevfv8D0F5xvVYKS+VQf+YX8Auo7wCla4CkeNsSMMvmX71S
13+
INyER9oLuXoElIlx4agKdqoiOLO7JQgZlu8o131Y9QKBgQDs5kHxOTFWaNMXTS8+
14+
4Va4snGRl58mMvVwCpjzC43WvdSz6J2q73dTgQqWl08eemn/m6/AUMppBbk6y9g/
15+
9dp9ZY2wCR1+aq1l8LPoy+1hueEvwE8Ob5JdQhTHKlG1KUVwr/IKP54xjRnUApOG
16+
Mk28Gps7DSdslWOIi8jUmbFY/wKBgQDJJdFp1LbrxTkbrmBRKzn1vg1yL+xP1TXa
17+
bNDiccBhLHqkKRrnCf7zPzW1Tiwg8eQ4QwgsjkgoZnBFJdrDnnlX3UAa6MrsoXwV
18+
oqHnHid2ZZ8LNohdse1/EGhOXuegGQpMBaft1JfxmdBE67S9uxppqc52AuGjnt6q
19+
fvgRh1l2RQKBgQCpIVbw5lkwDNSwLR3O8cgdQuDMBgjMl9Mcs6Qw2Q3hw1OJQkjW
20+
kfKKPnWVv97vrovgvoECd2ubAUgWDxSLzXW40vkONePFrlmvjuKTEIygmbmIgu6u
21+
Kr+/Lv9wlekRwq5d3m+aG4NQcyF+eHxkcaOH6SLsTN7ZqeoOwWWXS0cPdwKBgA4Q
22+
LNH/Y0KcqV98E5PZN9YskXgYTadPOtKopPoQBelFWNW9YfohQsfy9WhVrNQo1VHx
23+
rdKfp//bGaJcAS2IGOfBukenWvisWaaRlkw4WX33oOUBzQrv87Dcjs5b6EnTNlsW
24+
UiVYpb7oiB0pdZuGR1R34M1zah8sbljxQ5rGIcUZAoGAMTTYP9KpoUwm4Qcb+eGI
25+
n2NoAF3IDXpnZe/IOZlB9obGQUbW7Orn6SquhsITZ/dRVkRsPidsglBV6YxaM7xE
26+
Y5E31b3SAxcbV7c2YhD9Fb+H88JJx7lIhEe8pU+c5T6iIWQRmkwBfLp/P2c29U/v
27+
650+8LA12K/y9WHMNhtgx6s=
28+
-----END PRIVATE KEY-----

0 commit comments

Comments
 (0)