mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
Add an option to disable APM user redaction (#176566)
## Summary Fix https://github.com/elastic/kibana/issues/174743 Add an `elastic.apm.redactUsers` configuration option that defaults to `true` (preserving current behavior) --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
aae8639263
commit
d65460cb39
5 changed files with 68 additions and 13 deletions
|
@ -24,4 +24,5 @@ const apmReusableConfigSchema = schema.object(
|
|||
|
||||
export const apmConfigSchema = apmReusableConfigSchema.extends({
|
||||
servicesOverrides: schema.maybe(schema.recordOf(schema.string(), apmReusableConfigSchema)),
|
||||
redactUsers: schema.maybe(schema.boolean({ defaultValue: true })),
|
||||
});
|
||||
|
|
|
@ -405,4 +405,30 @@ describe('ApmConfiguration', () => {
|
|||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isUsersRedactionEnabled', () => {
|
||||
it('defaults to true', () => {
|
||||
const kibanaConfig = {
|
||||
elastic: {
|
||||
apm: {},
|
||||
},
|
||||
};
|
||||
|
||||
const config = new ApmConfiguration(mockedRootDir, kibanaConfig, false);
|
||||
expect(config.isUsersRedactionEnabled()).toEqual(true);
|
||||
});
|
||||
|
||||
it('uses the value defined in the config if specified', () => {
|
||||
const kibanaConfig = {
|
||||
elastic: {
|
||||
apm: {
|
||||
redactUsers: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const config = new ApmConfiguration(mockedRootDir, kibanaConfig, false);
|
||||
expect(config.isUsersRedactionEnabled()).toEqual(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -93,6 +93,11 @@ export class ApmConfiguration {
|
|||
return baseConfig;
|
||||
}
|
||||
|
||||
public isUsersRedactionEnabled(): boolean {
|
||||
const { redactUsers = true } = this.getConfigFromKibanaConfig();
|
||||
return redactUsers;
|
||||
}
|
||||
|
||||
private getBaseConfig() {
|
||||
if (!this.baseConfig) {
|
||||
const configFromSources = this.getConfigFromAllSources();
|
||||
|
@ -287,7 +292,8 @@ export class ApmConfiguration {
|
|||
* Reads APM configuration from different sources and merges them together.
|
||||
*/
|
||||
private getConfigFromAllSources(): AgentConfigOptions {
|
||||
const { servicesOverrides, ...configFromKibanaConfig } = this.getConfigFromKibanaConfig();
|
||||
const { servicesOverrides, redactUsers, ...configFromKibanaConfig } =
|
||||
this.getConfigFromKibanaConfig();
|
||||
const configFromEnv = this.getConfigFromEnv(configFromKibanaConfig);
|
||||
const config = merge({}, configFromKibanaConfig, configFromEnv);
|
||||
|
||||
|
|
|
@ -15,14 +15,17 @@ describe('initApm', () => {
|
|||
let apmAddFilterMock: jest.Mock;
|
||||
let apmStartMock: jest.Mock;
|
||||
let getConfig: jest.Mock;
|
||||
let isUsersRedactionEnabled: jest.Mock;
|
||||
|
||||
beforeEach(() => {
|
||||
apmAddFilterMock = apm.addFilter as jest.Mock;
|
||||
apmStartMock = apm.start as jest.Mock;
|
||||
getConfig = jest.fn();
|
||||
isUsersRedactionEnabled = jest.fn();
|
||||
|
||||
mockLoadConfiguration.mockImplementation(() => ({
|
||||
getConfig,
|
||||
isUsersRedactionEnabled,
|
||||
}));
|
||||
});
|
||||
|
||||
|
@ -46,13 +49,29 @@ describe('initApm', () => {
|
|||
expect(getConfig).toHaveBeenCalledWith('service-name');
|
||||
});
|
||||
|
||||
it('registers a filter using `addFilter`', () => {
|
||||
it('calls `apmConfigLoader.isUsersRedactionEnabled`', () => {
|
||||
initApm(['foo', 'bar'], 'rootDir', true, 'service-name');
|
||||
|
||||
expect(isUsersRedactionEnabled).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('registers a filter using `addFilter` when user redaction is enabled', () => {
|
||||
isUsersRedactionEnabled.mockReturnValue(true);
|
||||
|
||||
initApm(['foo', 'bar'], 'rootDir', true, 'service-name');
|
||||
|
||||
expect(apmAddFilterMock).toHaveBeenCalledTimes(1);
|
||||
expect(apmAddFilterMock).toHaveBeenCalledWith(expect.any(Function));
|
||||
});
|
||||
|
||||
it('does not register a filter using `addFilter` when user redaction is disabled', () => {
|
||||
isUsersRedactionEnabled.mockReturnValue(false);
|
||||
|
||||
initApm(['foo', 'bar'], 'rootDir', true, 'service-name');
|
||||
|
||||
expect(apmAddFilterMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('starts apm with the config returned from `getConfig`', () => {
|
||||
const config = {
|
||||
foo: 'bar',
|
||||
|
|
|
@ -16,24 +16,27 @@ export const initApm = (
|
|||
) => {
|
||||
const apmConfigLoader = loadConfiguration(argv, rootDir, isDistributable);
|
||||
const apmConfig = apmConfigLoader.getConfig(serviceName);
|
||||
const shouldRedactUsers = apmConfigLoader.isUsersRedactionEnabled();
|
||||
|
||||
// we want to only load the module when effectively used
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const apm = require('elastic-apm-node');
|
||||
|
||||
// Filter out all user PII
|
||||
apm.addFilter((payload: Record<string, any>) => {
|
||||
try {
|
||||
if (payload.context?.user && typeof payload.context.user === 'object') {
|
||||
Object.keys(payload.context.user).forEach((key) => {
|
||||
payload.context.user[key] = '[REDACTED]';
|
||||
});
|
||||
if (shouldRedactUsers) {
|
||||
apm.addFilter((payload: Record<string, any>) => {
|
||||
try {
|
||||
if (payload.context?.user && typeof payload.context.user === 'object') {
|
||||
Object.keys(payload.context.user).forEach((key) => {
|
||||
payload.context.user[key] = '[REDACTED]';
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
// just silently ignore the error
|
||||
}
|
||||
} catch (e) {
|
||||
// just silently ignore the error
|
||||
}
|
||||
return payload;
|
||||
});
|
||||
return payload;
|
||||
});
|
||||
}
|
||||
|
||||
apm.start(apmConfig);
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue