Skip to content

Commit

Permalink
chore(app): simplify and fix secret filtering
Browse files Browse the repository at this point in the history
We apply filtering during logging, to ensure no secrets are leaked.

Unfortunately the previous implementation was not side-effect free,
and would inadvertently change the connection options, when used.

This changes the behavior, but also ensures the filtering is SIMPLE
enough. When it comes to security (and many other things) simplicity
trumps.
  • Loading branch information
nikku committed Feb 20, 2025
1 parent c68d31b commit 89e74b1
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 54 deletions.
91 changes: 41 additions & 50 deletions app/lib/zeebe-api/zeebe-api.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,8 @@ const createLog = require('../log');
const { X509Certificate } = require('node:crypto');

const {
get,
isDefined,
pick,
set,
values,
merge
values
} = require('min-dash');

const ERROR_REASONS = {
Expand All @@ -48,18 +44,6 @@ const RESOURCE_TYPES = {
FORM: 'form'
};

const ENDPOINT_SECRETS = [
'endpoint.clientId',
'endpoint.clientSecret',
'endpoint.basicAuthUsername',
'endpoint.basicAuthPassword'
];

const CLIENT_OPTIONS_SECRETS = [
'options.basicAuth.username',
'options.basicAuth.password'
];

/**
* @typedef {Object} ZeebeClientParameters
* @property {Endpoint} endpoint
Expand Down Expand Up @@ -156,15 +140,15 @@ class ZeebeAPI {
const client = await this._getZeebeClient(endpoint);

this._log.debug('check connection', {
parameters: withoutSecrets(parameters, ENDPOINT_SECRETS)
parameters: filterEndpointParameters(parameters)
});

try {
await client.topology();
return { success: true };
} catch (err) {
this._log.error('connection check failed', {
parameters: withoutSecrets(parameters, ENDPOINT_SECRETS)
parameters: filterEndpointParameters(parameters)
}, err);

return {
Expand Down Expand Up @@ -196,7 +180,7 @@ class ZeebeAPI {
} = this._fs.readFile(filePath, { encoding: false });

this._log.debug('deploy', {
parameters: withoutSecrets(parameters, ENDPOINT_SECRETS)
parameters: filterEndpointParameters(parameters)
});

const client = await this._getZeebeClient(endpoint);
Expand All @@ -215,7 +199,7 @@ class ZeebeAPI {
response: response
};
} catch (err) {
this._log.error('deploy failed', withoutSecrets(parameters, ENDPOINT_SECRETS), err);
this._log.error('deploy failed', filterEndpointParameters(parameters), err);

return {
success: false,
Expand All @@ -242,7 +226,7 @@ class ZeebeAPI {
} = parameters;

this._log.debug('run', {
parameters: withoutSecrets(parameters, ENDPOINT_SECRETS)
parameters: filterEndpointParameters(parameters)
});

const client = await this._getZeebeClient(endpoint);
Expand All @@ -261,7 +245,7 @@ class ZeebeAPI {
};
} catch (err) {
this._log.error('run failed', {
parameters: withoutSecrets(parameters, ENDPOINT_SECRETS)
parameters: filterEndpointParameters(parameters)
}, err);

return {
Expand All @@ -286,7 +270,7 @@ class ZeebeAPI {
} = parameters;

this._log.debug('fetch gateway version', {
parameters: withoutSecrets(parameters, ENDPOINT_SECRETS)
parameters: filterEndpointParameters(parameters)
});

const client = await this._getZeebeClient(endpoint);
Expand All @@ -302,7 +286,7 @@ class ZeebeAPI {
};
} catch (err) {
this._log.error('fetch gateway version failed', {
parameters: withoutSecrets(parameters, ENDPOINT_SECRETS)
parameters: filterEndpointParameters(parameters)
}, err);

return {
Expand Down Expand Up @@ -420,15 +404,7 @@ class ZeebeAPI {

this._log.debug('creating client', {
url,
options: withoutSecrets(
filterRecursive(options, [
'clientId:secret',
'clientSecret:secret',
'customRootCert:blob',
'rootCerts:blob'
]),
CLIENT_OPTIONS_SECRETS
)
options: filterCamunda8Options(options)
});

const camundaClient = new this._Camunda8(options);
Expand Down Expand Up @@ -637,25 +613,40 @@ function isHashEqual(parameter1, parameter2) {
return JSON.stringify(parameter1) === JSON.stringify(parameter2);
}

function withoutSecrets(parameters, paths) {

const newParameters = merge({}, parameters);

paths.forEach(secret => {
const path = secret.split('.');

const value = get(parameters, path);

if (isDefined(value)) {
set(newParameters, path, '******');
}
});
function asSerializedError(error) {
return pick(error, [ 'message', 'code', 'details' ]);
}

return newParameters;
/**
* Filter endpoint connection parameters, so they can safely logged
* without leaking secrets.
*
* @param {any} parameters
*
* @return {any} filtered parameters
*/
function filterEndpointParameters(parameters) {
return filterRecursive(parameters, [
'clientSecret:secret',
'basicAuthPassword:secret'
]);
}

function asSerializedError(error) {
return pick(error, [ 'message', 'code', 'details' ]);
/**
* Filter Camunda8 options, so they can safely logged
* without leaking secrets.
*
* @param {any} options
*
* @return {any} filtered options
*/
function filterCamunda8Options(options) {
return filterRecursive(options, [
'ZEEBE_CLIENT_SECRET:secret',
'CAMUNDA_CONSOLE_CLIENT_SECRET:secret',
'CAMUNDA_BASIC_AUTH_PASSWORD:secret',
'CAMUNDA_CUSTOM_ROOT_CERT_STRING:blob'
]);
}

function filterRecursive(obj, keys) {
Expand Down
8 changes: 4 additions & 4 deletions app/test/spec/zeebe-api/zeebe-api-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2288,7 +2288,7 @@ describe('ZeebeAPI', function() {
},
ZEEBE_GRPC_ADDRESS: 'localhost:26500',
CAMUNDA_AUTH_STRATEGY: 'BASIC',
CAMUNDA_BASIC_AUTH_USERNAME: '******',
CAMUNDA_BASIC_AUTH_USERNAME: 'username',
CAMUNDA_BASIC_AUTH_PASSWORD: '******',
CAMUNDA_SECURE_CONNECTION: false
}
Expand All @@ -2303,7 +2303,7 @@ describe('ZeebeAPI', function() {
endpoint: {
type: ENDPOINT_TYPES.SELF_HOSTED,
authType: AUTH_TYPES.BASIC,
basicAuthUsername: '******',
basicAuthUsername: 'username',
basicAuthPassword: '******',
url: TEST_URL
}
Expand Down Expand Up @@ -2361,7 +2361,7 @@ describe('ZeebeAPI', function() {
CAMUNDA_AUTH_STRATEGY: 'OAUTH',
CAMUNDA_TOKEN_DISK_CACHE_DISABLE: true,
CAMUNDA_TOKEN_SCOPE: 'scope',
ZEEBE_CLIENT_ID: '******',
ZEEBE_CLIENT_ID: 'clientId',
ZEEBE_CLIENT_SECRET: '******',
CAMUNDA_CONSOLE_OAUTH_AUDIENCE: 'audience',
CAMUNDA_OAUTH_URL: 'oauthURL',
Expand All @@ -2382,7 +2382,7 @@ describe('ZeebeAPI', function() {
oauthURL: 'oauthURL',
audience: 'audience',
scope: 'scope',
clientId: '******',
clientId: 'clientId',
clientSecret: '******'
}
}
Expand Down

0 comments on commit 89e74b1

Please sign in to comment.