@platformatic/kafka 1.21.0 → 1.22.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/apis/enumerations.d.ts +1 -0
- package/dist/apis/enumerations.js +2 -1
- package/dist/clients/base/options.d.ts +3 -0
- package/dist/clients/base/options.js +2 -1
- package/dist/network/connection.d.ts +3 -0
- package/dist/network/connection.js +10 -4
- package/dist/protocol/index.d.ts +1 -0
- package/dist/protocol/index.js +1 -0
- package/dist/protocol/sasl/oauth-bearer.js +3 -2
- package/dist/protocol/sasl/plain.js +5 -3
- package/dist/protocol/sasl/scram-sha.d.ts +2 -0
- package/dist/protocol/sasl/scram-sha.js +7 -3
- package/dist/protocol/sasl/utils.d.ts +4 -0
- package/dist/protocol/sasl/{credential-provider.js → utils.js} +10 -5
- package/dist/version.js +1 -1
- package/package.json +4 -2
- package/dist/protocol/sasl/credential-provider.d.ts +0 -3
|
@@ -3,6 +3,7 @@ export declare const SASLMechanisms: {
|
|
|
3
3
|
readonly SCRAM_SHA_256: "SCRAM-SHA-256";
|
|
4
4
|
readonly SCRAM_SHA_512: "SCRAM-SHA-512";
|
|
5
5
|
readonly OAUTHBEARER: "OAUTHBEARER";
|
|
6
|
+
readonly GSSAPI: "GSSAPI";
|
|
6
7
|
};
|
|
7
8
|
export declare const allowedSASLMechanisms: SASLMechanismValue[];
|
|
8
9
|
export type SASLMechanism = keyof typeof SASLMechanisms;
|
|
@@ -3,7 +3,8 @@ export const SASLMechanisms = {
|
|
|
3
3
|
PLAIN: 'PLAIN',
|
|
4
4
|
SCRAM_SHA_256: 'SCRAM-SHA-256',
|
|
5
5
|
SCRAM_SHA_512: 'SCRAM-SHA-512',
|
|
6
|
-
OAUTHBEARER: 'OAUTHBEARER'
|
|
6
|
+
OAUTHBEARER: 'OAUTHBEARER',
|
|
7
|
+
GSSAPI: 'GSSAPI'
|
|
7
8
|
};
|
|
8
9
|
export const allowedSASLMechanisms = Object.values(SASLMechanisms);
|
|
9
10
|
// Metadata API
|
|
@@ -41,7 +41,8 @@ export const baseOptionsSchema = {
|
|
|
41
41
|
username: { oneOf: [{ type: 'string' }, { function: true }] },
|
|
42
42
|
password: { oneOf: [{ type: 'string' }, { function: true }] },
|
|
43
43
|
token: { oneOf: [{ type: 'string' }, { function: true }] },
|
|
44
|
-
authBytesValidator: { function: true }
|
|
44
|
+
authBytesValidator: { function: true },
|
|
45
|
+
authenticate: { function: true }
|
|
45
46
|
},
|
|
46
47
|
required: ['mechanism'],
|
|
47
48
|
additionalProperties: false
|
|
@@ -4,18 +4,21 @@ import { type ConnectionOptions as TLSConnectionOptions } from 'node:tls';
|
|
|
4
4
|
import { type CallbackWithPromise } from '../apis/callbacks.ts';
|
|
5
5
|
import { type Callback, type ResponseParser } from '../apis/definitions.ts';
|
|
6
6
|
import { type SASLMechanismValue } from '../apis/enumerations.ts';
|
|
7
|
+
import { type SaslAuthenticateResponse, type SASLAuthenticationAPI } from '../apis/security/sasl-authenticate-v2.ts';
|
|
7
8
|
import { Writer } from '../protocol/writer.ts';
|
|
8
9
|
export type SASLCredentialProvider = () => string | Promise<string>;
|
|
9
10
|
export interface Broker {
|
|
10
11
|
host: string;
|
|
11
12
|
port: number;
|
|
12
13
|
}
|
|
14
|
+
export type SASLCustomAuthenticator = (mechanism: SASLMechanismValue, connection: Connection, authenticate: SASLAuthenticationAPI, usernameProvider: string | SASLCredentialProvider | undefined, passwordProvider: string | SASLCredentialProvider | undefined, tokenProvider: string | SASLCredentialProvider | undefined, callback: CallbackWithPromise<SaslAuthenticateResponse>) => void;
|
|
13
15
|
export interface SASLOptions {
|
|
14
16
|
mechanism: SASLMechanismValue;
|
|
15
17
|
username?: string | SASLCredentialProvider;
|
|
16
18
|
password?: string | SASLCredentialProvider;
|
|
17
19
|
token?: string | SASLCredentialProvider;
|
|
18
20
|
authBytesValidator?: (authBytes: Buffer, callback: CallbackWithPromise<Buffer>) => void;
|
|
21
|
+
authenticate?: SASLCustomAuthenticator;
|
|
19
22
|
}
|
|
20
23
|
export interface ConnectionOptions {
|
|
21
24
|
connectTimeout?: number;
|
|
@@ -69,10 +69,10 @@ export class Connection extends EventEmitter {
|
|
|
69
69
|
notifyCreation('connection', this);
|
|
70
70
|
}
|
|
71
71
|
get host() {
|
|
72
|
-
return this.#status === ConnectionStatuses.CONNECTED ? this.#host : undefined;
|
|
72
|
+
return this.#status === ConnectionStatuses.CONNECTING || ConnectionStatuses.CONNECTED ? this.#host : undefined;
|
|
73
73
|
}
|
|
74
74
|
get port() {
|
|
75
|
-
return this.#status === ConnectionStatuses.CONNECTED ? this.#port : undefined;
|
|
75
|
+
return this.#status === ConnectionStatuses.CONNECTING || ConnectionStatuses.CONNECTED ? this.#port : undefined;
|
|
76
76
|
}
|
|
77
77
|
get instanceId() {
|
|
78
78
|
return this.#instanceId;
|
|
@@ -257,7 +257,7 @@ export class Connection extends EventEmitter {
|
|
|
257
257
|
if (this.#status === ConnectionStatuses.CONNECTING) {
|
|
258
258
|
this.#status = ConnectionStatuses.AUTHENTICATING;
|
|
259
259
|
}
|
|
260
|
-
const { mechanism, username, password, token } = this.#options.sasl;
|
|
260
|
+
const { mechanism, username, password, token, authenticate } = this.#options.sasl;
|
|
261
261
|
if (!allowedSASLMechanisms.includes(mechanism)) {
|
|
262
262
|
this.#onConnectionError(host, port, diagnosticContext, new UserError(`SASL mechanism ${mechanism} not supported.`));
|
|
263
263
|
return;
|
|
@@ -269,12 +269,18 @@ export class Connection extends EventEmitter {
|
|
|
269
269
|
}
|
|
270
270
|
this.emit('sasl:handshake', response.mechanisms);
|
|
271
271
|
const callback = this.#onSaslAuthenticate.bind(this, host, port, diagnosticContext);
|
|
272
|
-
if (
|
|
272
|
+
if (authenticate) {
|
|
273
|
+
authenticate(mechanism, this, saslAuthenticateV2.api, username, password, token, callback);
|
|
274
|
+
}
|
|
275
|
+
else if (mechanism === SASLMechanisms.PLAIN) {
|
|
273
276
|
saslPlain.authenticate(saslAuthenticateV2.api, this, username, password, callback);
|
|
274
277
|
}
|
|
275
278
|
else if (mechanism === SASLMechanisms.OAUTHBEARER) {
|
|
276
279
|
saslOAuthBearer.authenticate(saslAuthenticateV2.api, this, token, callback);
|
|
277
280
|
}
|
|
281
|
+
else if (mechanism === SASLMechanisms.GSSAPI) {
|
|
282
|
+
callback(new UserError('No custom SASL/GSSAPI authenticator provided.'), undefined);
|
|
283
|
+
}
|
|
278
284
|
else {
|
|
279
285
|
saslScramSha.authenticate(saslAuthenticateV2.api, this, mechanism.substring(6), username, password, defaultCrypto, callback);
|
|
280
286
|
}
|
package/dist/protocol/index.d.ts
CHANGED
|
@@ -11,5 +11,6 @@ export * from './records.ts';
|
|
|
11
11
|
export * as saslOAuthBearer from './sasl/oauth-bearer.ts';
|
|
12
12
|
export * as saslPlain from './sasl/plain.ts';
|
|
13
13
|
export * as saslScramSha from './sasl/scram-sha.ts';
|
|
14
|
+
export * as saslUtils from './sasl/utils.ts';
|
|
14
15
|
export * from './varint.ts';
|
|
15
16
|
export * from './writer.ts';
|
package/dist/protocol/index.js
CHANGED
|
@@ -11,5 +11,6 @@ export * from "./records.js";
|
|
|
11
11
|
export * as saslOAuthBearer from "./sasl/oauth-bearer.js";
|
|
12
12
|
export * as saslPlain from "./sasl/plain.js";
|
|
13
13
|
export * as saslScramSha from "./sasl/scram-sha.js";
|
|
14
|
+
export * as saslUtils from "./sasl/utils.js";
|
|
14
15
|
export * from "./varint.js";
|
|
15
16
|
export * from "./writer.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createPromisifiedCallback, kCallbackPromise } from "../../apis/callbacks.js";
|
|
2
2
|
import { AuthenticationError } from "../../errors.js";
|
|
3
|
-
import { getCredential } from "./
|
|
3
|
+
import { getCredential } from "./utils.js";
|
|
4
4
|
export function jwtValidateAuthenticationBytes(authBytes, callback) {
|
|
5
5
|
let authData = {};
|
|
6
6
|
try {
|
|
@@ -24,7 +24,8 @@ export function authenticate(authenticateAPI, connection, tokenOrProvider, callb
|
|
|
24
24
|
}
|
|
25
25
|
getCredential('SASL/OAUTHBEARER token', tokenOrProvider, (error, token) => {
|
|
26
26
|
if (error) {
|
|
27
|
-
|
|
27
|
+
callback(error, undefined);
|
|
28
|
+
return;
|
|
28
29
|
}
|
|
29
30
|
authenticateAPI(connection, Buffer.from(`n,,\x01auth=Bearer ${token}\x01\x01`), callback);
|
|
30
31
|
});
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import { createPromisifiedCallback, kCallbackPromise } from "../../apis/callbacks.js";
|
|
2
|
-
import { getCredential } from "./
|
|
2
|
+
import { getCredential } from "./utils.js";
|
|
3
3
|
export function authenticate(authenticateAPI, connection, usernameProvider, passwordProvider, callback) {
|
|
4
4
|
if (!callback) {
|
|
5
5
|
callback = createPromisifiedCallback();
|
|
6
6
|
}
|
|
7
7
|
getCredential('SASL/PLAIN username', usernameProvider, (error, username) => {
|
|
8
8
|
if (error) {
|
|
9
|
-
|
|
9
|
+
callback(error, undefined);
|
|
10
|
+
return;
|
|
10
11
|
}
|
|
11
12
|
getCredential('SASL/PLAIN password', passwordProvider, (error, password) => {
|
|
12
13
|
if (error) {
|
|
13
|
-
|
|
14
|
+
callback(error, undefined);
|
|
15
|
+
return;
|
|
14
16
|
}
|
|
15
17
|
authenticateAPI(connection, Buffer.from(['', username, password].join('\0')), callback);
|
|
16
18
|
});
|
|
@@ -14,11 +14,13 @@ export interface ScramCryptoModule {
|
|
|
14
14
|
}
|
|
15
15
|
export declare const ScramAlgorithms: {
|
|
16
16
|
readonly 'SHA-256': {
|
|
17
|
+
readonly id: "SHA-256";
|
|
17
18
|
readonly keyLength: 32;
|
|
18
19
|
readonly algorithm: "sha256";
|
|
19
20
|
readonly minIterations: 4096;
|
|
20
21
|
};
|
|
21
22
|
readonly 'SHA-512': {
|
|
23
|
+
readonly id: "SHA-512";
|
|
22
24
|
readonly keyLength: 64;
|
|
23
25
|
readonly algorithm: "sha512";
|
|
24
26
|
readonly minIterations: 4096;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createHash, createHmac, pbkdf2Sync, randomBytes } from 'node:crypto';
|
|
2
2
|
import { createPromisifiedCallback, kCallbackPromise } from "../../apis/callbacks.js";
|
|
3
3
|
import { AuthenticationError } from "../../errors.js";
|
|
4
|
-
import { getCredential } from "./
|
|
4
|
+
import { getCredential } from "./utils.js";
|
|
5
5
|
const GS2_HEADER = 'n,,';
|
|
6
6
|
const GS2_HEADER_BASE64 = Buffer.from(GS2_HEADER).toString('base64');
|
|
7
7
|
const HMAC_CLIENT_KEY = 'Client Key';
|
|
@@ -9,11 +9,13 @@ const HMAC_SERVER_KEY = 'Server Key';
|
|
|
9
9
|
const PARAMETERS_PARSER = /([^=]+)=(.+)/;
|
|
10
10
|
export const ScramAlgorithms = {
|
|
11
11
|
'SHA-256': {
|
|
12
|
+
id: 'SHA-256',
|
|
12
13
|
keyLength: 32,
|
|
13
14
|
algorithm: 'sha256',
|
|
14
15
|
minIterations: 4096
|
|
15
16
|
},
|
|
16
17
|
'SHA-512': {
|
|
18
|
+
id: 'SHA-512',
|
|
17
19
|
keyLength: 64,
|
|
18
20
|
algorithm: 'sha512',
|
|
19
21
|
minIterations: 4096
|
|
@@ -129,11 +131,13 @@ export function authenticate(authenticateAPI, connection, algorithm, usernamePro
|
|
|
129
131
|
}
|
|
130
132
|
getCredential(`SASL/SCRAM-${algorithm} username`, usernameProvider, (error, username) => {
|
|
131
133
|
if (error) {
|
|
132
|
-
|
|
134
|
+
callback(error, undefined);
|
|
135
|
+
return;
|
|
133
136
|
}
|
|
134
137
|
getCredential(`SASL/SCRAM-${algorithm} password`, passwordProvider, (error, password) => {
|
|
135
138
|
if (error) {
|
|
136
|
-
|
|
139
|
+
callback(error, undefined);
|
|
140
|
+
return;
|
|
137
141
|
}
|
|
138
142
|
performAuthentication(connection, algorithm, definition, authenticateAPI, crypto, username, password, callback);
|
|
139
143
|
});
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type CallbackWithPromise } from '../../apis/index.ts';
|
|
2
|
+
import { type SASLCredentialProvider } from '../../network/connection.ts';
|
|
3
|
+
export declare function getCredential(label: string, credentialOrProvider: string | SASLCredentialProvider, callback: CallbackWithPromise<string>): void;
|
|
4
|
+
export declare function getCredential(label: string, credentialOrProvider: string | SASLCredentialProvider): Promise<string>;
|
|
@@ -1,28 +1,32 @@
|
|
|
1
|
+
import { createPromisifiedCallback, kCallbackPromise } from "../../apis/index.js";
|
|
1
2
|
import { AuthenticationError } from "../../errors.js";
|
|
2
3
|
export function getCredential(label, credentialOrProvider, callback) {
|
|
4
|
+
if (!callback) {
|
|
5
|
+
callback = createPromisifiedCallback();
|
|
6
|
+
}
|
|
3
7
|
if (typeof credentialOrProvider === 'string') {
|
|
4
8
|
callback(null, credentialOrProvider);
|
|
5
|
-
return;
|
|
9
|
+
return callback[kCallbackPromise];
|
|
6
10
|
}
|
|
7
11
|
else if (typeof credentialOrProvider !== 'function') {
|
|
8
12
|
callback(new AuthenticationError(`The ${label} should be a string or a function.`), undefined);
|
|
9
|
-
return;
|
|
13
|
+
return callback[kCallbackPromise];
|
|
10
14
|
}
|
|
11
15
|
try {
|
|
12
16
|
const credential = credentialOrProvider();
|
|
13
17
|
if (typeof credential === 'string') {
|
|
14
18
|
callback(null, credential);
|
|
15
|
-
return;
|
|
19
|
+
return callback[kCallbackPromise];
|
|
16
20
|
}
|
|
17
21
|
else if (typeof credential?.then !== 'function') {
|
|
18
22
|
callback(new AuthenticationError(`The ${label} provider should return a string or a promise that resolves to a string.`), undefined);
|
|
19
|
-
return;
|
|
23
|
+
return callback[kCallbackPromise];
|
|
20
24
|
}
|
|
21
25
|
credential
|
|
22
26
|
.then(token => {
|
|
23
27
|
if (typeof token !== 'string') {
|
|
24
28
|
process.nextTick(callback, new AuthenticationError(`The ${label} provider should resolve to a string.`), undefined);
|
|
25
|
-
return;
|
|
29
|
+
return callback[kCallbackPromise];
|
|
26
30
|
}
|
|
27
31
|
process.nextTick(callback, null, token);
|
|
28
32
|
})
|
|
@@ -33,4 +37,5 @@ export function getCredential(label, credentialOrProvider, callback) {
|
|
|
33
37
|
catch (error) {
|
|
34
38
|
callback(new AuthenticationError(`The ${label} provider threw an error.`, { cause: error }), undefined);
|
|
35
39
|
}
|
|
40
|
+
return callback[kCallbackPromise];
|
|
36
41
|
}
|
package/dist/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export const name = "@platformatic/kafka";
|
|
2
|
-
export const version = "1.
|
|
2
|
+
export const version = "1.22.0-alpha.2";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platformatic/kafka",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.22.0-alpha.2",
|
|
4
4
|
"description": "Modern and performant client for Apache Kafka",
|
|
5
5
|
"homepage": "https://github.com/platformatic/kafka",
|
|
6
6
|
"author": "Platformatic Inc. <oss@platformatic.dev> (https://platformatic.dev)",
|
|
@@ -40,6 +40,7 @@
|
|
|
40
40
|
"@confluentinc/kafka-javascript": "^1.5.0",
|
|
41
41
|
"@platformatic/rdkafka": "^4.0.0",
|
|
42
42
|
"@types/debug": "^4.1.12",
|
|
43
|
+
"@types/kerberos": "^1.1.5",
|
|
43
44
|
"@types/node": "^22.18.5",
|
|
44
45
|
"@types/semver": "^7.7.1",
|
|
45
46
|
"@watchable/unpromise": "^1.0.2",
|
|
@@ -50,8 +51,9 @@
|
|
|
50
51
|
"eslint": "^9.35.0",
|
|
51
52
|
"fast-jwt": "^6.0.2",
|
|
52
53
|
"hwp": "^0.4.1",
|
|
53
|
-
"kafkajs": "^2.2.4",
|
|
54
54
|
"json5": "^2.2.3",
|
|
55
|
+
"kafkajs": "^2.2.4",
|
|
56
|
+
"kerberos": "^2.2.2",
|
|
55
57
|
"neostandard": "^0.12.2",
|
|
56
58
|
"parse5": "^7.3.0",
|
|
57
59
|
"prettier": "^3.6.2",
|