Skip to content

Commit

Permalink
Migrate ElasticsearchConfig deprecation out of Core deprecations
Browse files Browse the repository at this point in the history
  • Loading branch information
jportner committed Jan 9, 2020
1 parent 719ff25 commit b8fd76d
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 115 deletions.
31 changes: 0 additions & 31 deletions src/core/server/config/deprecation/core_deprecations.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -208,35 +208,4 @@ describe('core deprecations', () => {
).toEqual([`worker-src blob:`]);
});
});

describe('elasticsearchUsernameDeprecation', () => {
it('logs a warning if elasticsearch.username is set to "elastic"', () => {
const { messages } = applyCoreDeprecations({
elasticsearch: {
username: 'elastic',
},
});
expect(messages).toMatchInlineSnapshot(`
Array [
"Setting elasticsearch.username to \\"elastic\\" is deprecated. You should use the \\"kibana\\" user instead.",
]
`);
});

it('does not log a warning if elasticsearch.username is set to something besides "elastic"', () => {
const { messages } = applyCoreDeprecations({
elasticsearch: {
username: 'otheruser',
},
});
expect(messages).toHaveLength(0);
});

it('does not log a warning if elasticsearch.username is unset', () => {
const { messages } = applyCoreDeprecations({
elasticsearch: {},
});
expect(messages).toHaveLength(0);
});
});
});
11 changes: 0 additions & 11 deletions src/core/server/config/deprecation/core_deprecations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,16 +91,6 @@ const cspRulesDeprecation: ConfigDeprecation = (settings, fromPath, log) => {
return settings;
};

const elasticsearchUsernameDeprecation: ConfigDeprecation = (settings, _fromPath, log) => {
const username: string | undefined = get(settings, 'elasticsearch.username');
if (username === 'elastic') {
log(
`Setting elasticsearch.username to "elastic" is deprecated. You should use the "kibana" user instead.`
);
}
return settings;
};

export const coreDeprecationProvider: ConfigDeprecationProvider = ({
unusedFromRoot,
renameFromRoot,
Expand All @@ -120,5 +110,4 @@ export const coreDeprecationProvider: ConfigDeprecationProvider = ({
dataPathDeprecation,
rewriteBasePathDeprecation,
cspRulesDeprecation,
elasticsearchUsernameDeprecation,
];
43 changes: 43 additions & 0 deletions src/core/server/elasticsearch/elasticsearch_config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ import {
import { ElasticsearchConfig, config, ElasticsearchConfigType } from './elasticsearch_config';
import { loggingServiceMock } from '../mocks';
import { Logger } from '../logging';
import { applyDeprecations, configDeprecationFactory } from '../config/deprecation';

const CONFIG_PATH = 'elasticsearch';

const createElasticsearchConfig = (rawConfig: ElasticsearchConfigType, log?: Logger) => {
if (!log) {
Expand All @@ -34,6 +37,25 @@ const createElasticsearchConfig = (rawConfig: ElasticsearchConfigType, log?: Log
return new ElasticsearchConfig(rawConfig, log);
};

const applyElasticsearchDeprecations = (settings: Record<string, any> = {}) => {
const deprecations = config.deprecations!(configDeprecationFactory);
const deprecationMessages: string[] = [];
const _config: any = {};
_config[CONFIG_PATH] = settings;
const migrated = applyDeprecations(
_config,
deprecations.map(deprecation => ({
deprecation,
path: CONFIG_PATH,
})),
msg => deprecationMessages.push(msg)
);
return {
messages: deprecationMessages,
migrated,
};
};

test('set correct defaults', () => {
const configValue = createElasticsearchConfig(config.schema.validate({}));
expect(configValue).toMatchInlineSnapshot(`
Expand Down Expand Up @@ -319,6 +341,27 @@ describe('logs warnings', () => {
});
});

describe('deprecations', () => {
it('logs a warning if elasticsearch.username is set to "elastic"', () => {
const { messages } = applyElasticsearchDeprecations({ username: 'elastic' });
expect(messages).toMatchInlineSnapshot(`
Array [
"Setting [${CONFIG_PATH}.username] to \\"elastic\\" is deprecated. You should use the \\"kibana\\" user instead.",
]
`);
});

it('does not log a warning if elasticsearch.username is set to something besides "elastic"', () => {
const { messages } = applyElasticsearchDeprecations({ username: 'otheruser' });
expect(messages).toHaveLength(0);
});

it('does not log a warning if elasticsearch.username is unset', () => {
const { messages } = applyElasticsearchDeprecations({});
expect(messages).toHaveLength(0);
});
});

test('#username throws if equal to "elastic", only while running from source', () => {
const obj = {
username: 'elastic',
Expand Down
166 changes: 93 additions & 73 deletions src/core/server/elasticsearch/elasticsearch_config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,92 +20,112 @@
import { schema, TypeOf } from '@kbn/config-schema';
import { Duration } from 'moment';
import { readFileSync } from 'fs';
import { ConfigDeprecationProvider } from 'src/core/server';
import { readPkcs12Keystore, readPkcs12Truststore } from '../../utils';
import { Logger } from '../logging';
import { ServiceConfigDescriptor } from '../internal_types';

const hostURISchema = schema.uri({ scheme: ['http', 'https'] });

export const DEFAULT_API_VERSION = 'master';

export type ElasticsearchConfigType = TypeOf<typeof config.schema>;
export type ElasticsearchConfigType = TypeOf<typeof configSchema>;
type SslConfigSchema = ElasticsearchConfigType['ssl'];

export const config = {
path: 'elasticsearch',
schema: schema.object({
sniffOnStart: schema.boolean({ defaultValue: false }),
sniffInterval: schema.oneOf([schema.duration(), schema.literal(false)], {
defaultValue: false,
}),
sniffOnConnectionFault: schema.boolean({ defaultValue: false }),
hosts: schema.oneOf([hostURISchema, schema.arrayOf(hostURISchema, { minSize: 1 })], {
defaultValue: 'http://localhost:9200',
}),
preserveHost: schema.boolean({ defaultValue: true }),
username: schema.maybe(
schema.conditional(
schema.contextRef('dist'),
false,
schema.string({
validate: rawConfig => {
if (rawConfig === 'elastic') {
return (
'value of "elastic" is forbidden. This is a superuser account that can obfuscate ' +
'privilege-related issues. You should use the "kibana" user instead.'
);
}
},
}),
schema.string()
)
),
password: schema.maybe(schema.string()),
requestHeadersWhitelist: schema.oneOf([schema.string(), schema.arrayOf(schema.string())], {
defaultValue: ['authorization'],
}),
customHeaders: schema.recordOf(schema.string(), schema.string(), { defaultValue: {} }),
shardTimeout: schema.duration({ defaultValue: '30s' }),
requestTimeout: schema.duration({ defaultValue: '30s' }),
pingTimeout: schema.duration({ defaultValue: schema.siblingRef('requestTimeout') }),
startupTimeout: schema.duration({ defaultValue: '5s' }),
logQueries: schema.boolean({ defaultValue: false }),
ssl: schema.object(
{
verificationMode: schema.oneOf(
[schema.literal('none'), schema.literal('certificate'), schema.literal('full')],
{ defaultValue: 'full' }
),
certificateAuthorities: schema.maybe(
schema.oneOf([schema.string(), schema.arrayOf(schema.string(), { minSize: 1 })])
),
certificate: schema.maybe(schema.string()),
key: schema.maybe(schema.string()),
keyPassphrase: schema.maybe(schema.string()),
keystore: schema.object({
path: schema.maybe(schema.string()),
password: schema.maybe(schema.string()),
}),
truststore: schema.object({
path: schema.maybe(schema.string()),
password: schema.maybe(schema.string()),
}),
alwaysPresentCertificate: schema.boolean({ defaultValue: false }),
},
{
const configSchema = schema.object({
sniffOnStart: schema.boolean({ defaultValue: false }),
sniffInterval: schema.oneOf([schema.duration(), schema.literal(false)], {
defaultValue: false,
}),
sniffOnConnectionFault: schema.boolean({ defaultValue: false }),
hosts: schema.oneOf([hostURISchema, schema.arrayOf(hostURISchema, { minSize: 1 })], {
defaultValue: 'http://localhost:9200',
}),
preserveHost: schema.boolean({ defaultValue: true }),
username: schema.maybe(
schema.conditional(
schema.contextRef('dist'),
false,
schema.string({
validate: rawConfig => {
if (rawConfig.key && rawConfig.keystore.path) {
return 'cannot use [key] when [keystore.path] is specified';
}
if (rawConfig.certificate && rawConfig.keystore.path) {
return 'cannot use [certificate] when [keystore.path] is specified';
if (rawConfig === 'elastic') {
return (
'value of "elastic" is forbidden. This is a superuser account that can obfuscate ' +
'privilege-related issues. You should use the "kibana" user instead.'
);
}
},
}
),
apiVersion: schema.string({ defaultValue: DEFAULT_API_VERSION }),
healthCheck: schema.object({ delay: schema.duration({ defaultValue: 2500 }) }),
ignoreVersionMismatch: schema.boolean({ defaultValue: false }),
}),
schema.string()
)
),
password: schema.maybe(schema.string()),
requestHeadersWhitelist: schema.oneOf([schema.string(), schema.arrayOf(schema.string())], {
defaultValue: ['authorization'],
}),
customHeaders: schema.recordOf(schema.string(), schema.string(), { defaultValue: {} }),
shardTimeout: schema.duration({ defaultValue: '30s' }),
requestTimeout: schema.duration({ defaultValue: '30s' }),
pingTimeout: schema.duration({ defaultValue: schema.siblingRef('requestTimeout') }),
startupTimeout: schema.duration({ defaultValue: '5s' }),
logQueries: schema.boolean({ defaultValue: false }),
ssl: schema.object(
{
verificationMode: schema.oneOf(
[schema.literal('none'), schema.literal('certificate'), schema.literal('full')],
{ defaultValue: 'full' }
),
certificateAuthorities: schema.maybe(
schema.oneOf([schema.string(), schema.arrayOf(schema.string(), { minSize: 1 })])
),
certificate: schema.maybe(schema.string()),
key: schema.maybe(schema.string()),
keyPassphrase: schema.maybe(schema.string()),
keystore: schema.object({
path: schema.maybe(schema.string()),
password: schema.maybe(schema.string()),
}),
truststore: schema.object({
path: schema.maybe(schema.string()),
password: schema.maybe(schema.string()),
}),
alwaysPresentCertificate: schema.boolean({ defaultValue: false }),
},
{
validate: rawConfig => {
if (rawConfig.key && rawConfig.keystore.path) {
return 'cannot use [key] when [keystore.path] is specified';
}
if (rawConfig.certificate && rawConfig.keystore.path) {
return 'cannot use [certificate] when [keystore.path] is specified';
}
},
}
),
apiVersion: schema.string({ defaultValue: DEFAULT_API_VERSION }),
healthCheck: schema.object({ delay: schema.duration({ defaultValue: 2500 }) }),
ignoreVersionMismatch: schema.boolean({ defaultValue: false }),
});

const deprecations: ConfigDeprecationProvider = () => [
(settings, fromPath, log) => {
const es = settings[fromPath];
if (!es) {
return settings;
}
if (es.username === 'elastic') {
log(
`Setting [${fromPath}.username] to "elastic" is deprecated. You should use the "kibana" user instead.`
);
}
return settings;
},
];

export const config: ServiceConfigDescriptor<ElasticsearchConfigType> = {
path: 'elasticsearch',
schema: configSchema,
deprecations,
};

export class ElasticsearchConfig {
Expand Down
4 changes: 4 additions & 0 deletions src/core/server/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,10 @@ export class Server {
];

this.configService.addDeprecationProvider(rootConfigPath, coreDeprecationProvider);
this.configService.addDeprecationProvider(
elasticsearchConfig.path,
elasticsearchConfig.deprecations!
);
this.configService.addDeprecationProvider(
uiSettingsConfig.path,
uiSettingsConfig.deprecations!
Expand Down

0 comments on commit b8fd76d

Please sign in to comment.