Add SSL support for Kafka queue connection in JS executor
This commit is contained in:
parent
bda9159fc7
commit
5c6b4122d3
@ -62,3 +62,7 @@ export function parseJsErrorDetails(err: any): string | undefined {
|
|||||||
export function isNotUUID(candidate: string) {
|
export function isNotUUID(candidate: string) {
|
||||||
return candidate.length != 36 || !candidate.includes('-');
|
return candidate.length != 36 || !candidate.includes('-');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isNotEmptyStr(value: any): boolean {
|
||||||
|
return typeof value === 'string' && value.trim().length > 0;
|
||||||
|
}
|
||||||
|
|||||||
@ -38,6 +38,17 @@ kafka:
|
|||||||
topic_properties: "TB_QUEUE_KAFKA_JE_TOPIC_PROPERTIES"
|
topic_properties: "TB_QUEUE_KAFKA_JE_TOPIC_PROPERTIES"
|
||||||
use_confluent_cloud: "TB_QUEUE_KAFKA_USE_CONFLUENT_CLOUD"
|
use_confluent_cloud: "TB_QUEUE_KAFKA_USE_CONFLUENT_CLOUD"
|
||||||
client_id: "KAFKA_CLIENT_ID" #inject pod name to easy identify the client using /opt/kafka/bin/kafka-consumer-groups.sh
|
client_id: "KAFKA_CLIENT_ID" #inject pod name to easy identify the client using /opt/kafka/bin/kafka-consumer-groups.sh
|
||||||
|
ssl:
|
||||||
|
# Enable or disable SSL for Kafka communication.
|
||||||
|
enabled: "TB_KAFKA_SSL_ENABLED"
|
||||||
|
# Path to the server certificate file. This file can hold the server certificate or a certificate chain and may include the server private key.
|
||||||
|
cert_file: "TB_KAFKA_SSL_PEM_CERTIFICATE"
|
||||||
|
# Optional: Path to the server certificate private key file. Required if the private key is not included in the server certificate file.
|
||||||
|
key_file: "TB_KAFKA_SSL_PEM_KEY"
|
||||||
|
# Optional: Password for the server certificate private key, if applicable.
|
||||||
|
key_password: "TB_KAFKA_SSL_PEM_KEY_PASSWORD"
|
||||||
|
# Optional: Path to a custom CA certificate file. Defaults to trusting well-known CAs curated by Mozilla.
|
||||||
|
ca_file: "TB_KAFKA_SSL_PEM_TRUSTS_CERTIFICATE"
|
||||||
confluent:
|
confluent:
|
||||||
sasl:
|
sasl:
|
||||||
mechanism: "TB_QUEUE_KAFKA_CONFLUENT_SASL_MECHANISM"
|
mechanism: "TB_QUEUE_KAFKA_CONFLUENT_SASL_MECHANISM"
|
||||||
|
|||||||
@ -38,6 +38,8 @@ kafka:
|
|||||||
topic_properties: "retention.ms:604800000;segment.bytes:26214400;retention.bytes:104857600;partitions:100;min.insync.replicas:1"
|
topic_properties: "retention.ms:604800000;segment.bytes:26214400;retention.bytes:104857600;partitions:100;min.insync.replicas:1"
|
||||||
use_confluent_cloud: false
|
use_confluent_cloud: false
|
||||||
client_id: "kafkajs" #inject pod name to easy identify the client using /opt/kafka/bin/kafka-consumer-groups.sh
|
client_id: "kafkajs" #inject pod name to easy identify the client using /opt/kafka/bin/kafka-consumer-groups.sh
|
||||||
|
ssl:
|
||||||
|
enabled: false
|
||||||
confluent:
|
confluent:
|
||||||
sasl:
|
sasl:
|
||||||
mechanism: "PLAIN"
|
mechanism: "PLAIN"
|
||||||
|
|||||||
@ -15,6 +15,7 @@
|
|||||||
///
|
///
|
||||||
|
|
||||||
import config from 'config';
|
import config from 'config';
|
||||||
|
import fs from 'node:fs';
|
||||||
import { _logger, KafkaJsWinstonLogCreator } from '../config/logger';
|
import { _logger, KafkaJsWinstonLogCreator } from '../config/logger';
|
||||||
import { JsInvokeMessageProcessor } from '../api/jsInvokeMessageProcessor'
|
import { JsInvokeMessageProcessor } from '../api/jsInvokeMessageProcessor'
|
||||||
import { IQueue } from './queue.models';
|
import { IQueue } from './queue.models';
|
||||||
@ -29,8 +30,10 @@ import {
|
|||||||
Producer,
|
Producer,
|
||||||
TopicMessages
|
TopicMessages
|
||||||
} from 'kafkajs';
|
} from 'kafkajs';
|
||||||
|
import { isNotEmptyStr } from '../api/utils';
|
||||||
|
import { KeyObject } from 'tls';
|
||||||
|
|
||||||
import process, { kill, exit } from 'process';
|
import process, { exit, kill } from 'process';
|
||||||
|
|
||||||
export class KafkaTemplate implements IQueue {
|
export class KafkaTemplate implements IQueue {
|
||||||
|
|
||||||
@ -64,6 +67,7 @@ export class KafkaTemplate implements IQueue {
|
|||||||
const queuePrefix: string = config.get('queue_prefix');
|
const queuePrefix: string = config.get('queue_prefix');
|
||||||
const requestTopic: string = queuePrefix ? queuePrefix + "." + config.get('request_topic') : config.get('request_topic');
|
const requestTopic: string = queuePrefix ? queuePrefix + "." + config.get('request_topic') : config.get('request_topic');
|
||||||
const useConfluent = config.get('kafka.use_confluent_cloud');
|
const useConfluent = config.get('kafka.use_confluent_cloud');
|
||||||
|
const enabledSsl = Boolean(config.get('kafka.ssl.enabled'));
|
||||||
const groupId:string = queuePrefix ? queuePrefix + ".js-executor-group" : "js-executor-group";
|
const groupId:string = queuePrefix ? queuePrefix + ".js-executor-group" : "js-executor-group";
|
||||||
this.logger.info('Kafka Bootstrap Servers: %s', kafkaBootstrapServers);
|
this.logger.info('Kafka Bootstrap Servers: %s', kafkaBootstrapServers);
|
||||||
this.logger.info('Kafka Requests Topic: %s', requestTopic);
|
this.logger.info('Kafka Requests Topic: %s', requestTopic);
|
||||||
@ -93,6 +97,31 @@ export class KafkaTemplate implements IQueue {
|
|||||||
kafkaConfig['ssl'] = true;
|
kafkaConfig['ssl'] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (enabledSsl) {
|
||||||
|
const certFilePath: string = config.has('kafka.ssl.cert_file') ? config.get('kafka.ssl.cert_file') : '';
|
||||||
|
const keyFilePath: string = config.has('kafka.ssl.key_file') ? config.get('kafka.ssl.key_file') : '';
|
||||||
|
const keyPassword: string = config.has('kafka.ssl.key_password') ? config.get('kafka.ssl.key_password') : '';
|
||||||
|
const caFilePath: string = config.has('kafka.ssl.ca_file') ? config.get('kafka.ssl.ca_file') : '';
|
||||||
|
|
||||||
|
kafkaConfig.ssl = {};
|
||||||
|
|
||||||
|
if (isNotEmptyStr(certFilePath)) {
|
||||||
|
kafkaConfig.ssl.cert = fs.readFileSync(certFilePath, 'utf-8');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNotEmptyStr(keyFilePath)) {
|
||||||
|
const keyConfig: KeyObject = {pem: fs.readFileSync(keyFilePath, 'utf-8')};
|
||||||
|
if (isNotEmptyStr(keyPassword)) {
|
||||||
|
keyConfig.passphrase = keyPassword;
|
||||||
|
}
|
||||||
|
kafkaConfig.ssl.key = [keyConfig];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNotEmptyStr(caFilePath)) {
|
||||||
|
kafkaConfig.ssl.ca = fs.readFileSync(caFilePath, 'utf-8');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.parseTopicProperties();
|
this.parseTopicProperties();
|
||||||
|
|
||||||
this.kafkaClient = new Kafka(kafkaConfig);
|
this.kafkaClient = new Kafka(kafkaConfig);
|
||||||
@ -213,6 +242,7 @@ export class KafkaTemplate implements IQueue {
|
|||||||
|
|
||||||
private createTopic(topic: string, partitions: number): Promise<boolean> {
|
private createTopic(topic: string, partitions: number): Promise<boolean> {
|
||||||
return this.kafkaAdmin.createTopics({
|
return this.kafkaAdmin.createTopics({
|
||||||
|
timeout: this.requestTimeout,
|
||||||
topics: [{
|
topics: [{
|
||||||
topic: topic,
|
topic: topic,
|
||||||
numPartitions: partitions,
|
numPartitions: partitions,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user