Skip to content

Commit

Permalink
[7.x] [es] disable wildcards in destructive actions (elastic#88986) (e…
Browse files Browse the repository at this point in the history
…lastic#90804)

Co-authored-by: spalger <spalger@users.noreply.github.com>
  • Loading branch information
Spencer and spalger authored Feb 9, 2021
1 parent d1a1287 commit 684edff
Show file tree
Hide file tree
Showing 50 changed files with 229 additions and 151 deletions.
2 changes: 1 addition & 1 deletion packages/kbn-es/src/cluster.js
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ exports.Cluster = class Cluster {
this._log.info(chalk.bold('Starting'));
this._log.indent(4);

const esArgs = [].concat(options.esArgs || []);
const esArgs = ['action.destructive_requires_name=true'].concat(options.esArgs || []);
// Add to esArgs if ssl is enabled
if (this._ssl) {
esArgs.push('xpack.security.http.ssl.enabled=true');
Expand Down
8 changes: 6 additions & 2 deletions packages/kbn-es/src/integration_tests/cluster.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,9 @@ describe('#start(installPath)', () => {
expect(extractConfigFiles.mock.calls).toMatchInlineSnapshot(`
Array [
Array [
Array [],
Array [
"action.destructive_requires_name=true",
],
undefined,
Object {
"log": <ToolingLog>,
Expand Down Expand Up @@ -340,7 +342,9 @@ describe('#run()', () => {
expect(extractConfigFiles.mock.calls).toMatchInlineSnapshot(`
Array [
Array [
Array [],
Array [
"action.destructive_requires_name=true",
],
undefined,
Object {
"log": <ToolingLog>,
Expand Down
4 changes: 2 additions & 2 deletions test/api_integration/apis/saved_objects/bulk_create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import { getKibanaVersion } from './lib/saved_objects_test_utils';

export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
const es = getService('es');
const esArchiver = getService('esArchiver');
const esDeleteAllIndices = getService('esDeleteAllIndices');

const BULK_REQUESTS = [
{
Expand Down Expand Up @@ -97,7 +97,7 @@ export default function ({ getService }: FtrProviderContext) {
before(
async () =>
// just in case the kibana server has recreated it
await es.indices.delete({ index: '.kibana' }, { ignore: [404] })
await esDeleteAllIndices('.kibana')
);

it('should return 200 with individual responses', async () =>
Expand Down
4 changes: 2 additions & 2 deletions test/api_integration/apis/saved_objects/bulk_get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import { getKibanaVersion } from './lib/saved_objects_test_utils';

export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
const es = getService('es');
const esArchiver = getService('esArchiver');
const esDeleteAllIndices = getService('esDeleteAllIndices');

const BULK_REQUESTS = [
{
Expand Down Expand Up @@ -108,7 +108,7 @@ export default function ({ getService }: FtrProviderContext) {
before(
async () =>
// just in case the kibana server has recreated it
await es.indices.delete({ index: '.kibana' }, { ignore: [404] })
await esDeleteAllIndices('.kibana')
);

it('should return 200 with individual responses', async () =>
Expand Down
4 changes: 2 additions & 2 deletions test/api_integration/apis/saved_objects/bulk_update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import { FtrProviderContext } from '../../ftr_provider_context';

export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
const es = getService('es');
const esArchiver = getService('esArchiver');
const esDeleteAllIndices = getService('esDeleteAllIndices');

describe('bulkUpdate', () => {
describe('with kibana index', () => {
Expand Down Expand Up @@ -235,7 +235,7 @@ export default function ({ getService }: FtrProviderContext) {
before(
async () =>
// just in case the kibana server has recreated it
await es.indices.delete({ index: '.kibana' }, { ignore: [404] })
await esDeleteAllIndices('.kibana')
);

it('should return generic 404', async () => {
Expand Down
3 changes: 2 additions & 1 deletion test/api_integration/apis/saved_objects/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
const es = getService('es');
const esArchiver = getService('esArchiver');
const esDeleteAllIndices = getService('esDeleteAllIndices');

describe('create', () => {
let KIBANA_VERSION: string;
Expand Down Expand Up @@ -82,7 +83,7 @@ export default function ({ getService }: FtrProviderContext) {
before(
async () =>
// just in case the kibana server has recreated it
await es.indices.delete({ index: '.kibana' }, { ignore: [404] })
await esDeleteAllIndices('.kibana')
);

it('should return 200 and create kibana index', async () => {
Expand Down
4 changes: 2 additions & 2 deletions test/api_integration/apis/saved_objects/delete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import { FtrProviderContext } from '../../ftr_provider_context';

export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
const es = getService('es');
const esArchiver = getService('esArchiver');
const esDeleteAllIndices = getService('esDeleteAllIndices');

describe('delete', () => {
describe('with kibana index', () => {
Expand Down Expand Up @@ -44,7 +44,7 @@ export default function ({ getService }: FtrProviderContext) {
before(
async () =>
// just in case the kibana server has recreated it
await es.indices.delete({ index: '.kibana' }, { ignore: [404] })
await esDeleteAllIndices('.kibana')
);

it('returns generic 404 when kibana index is missing', async () =>
Expand Down
4 changes: 2 additions & 2 deletions test/api_integration/apis/saved_objects/export.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ function ndjsonToObject(input: string) {
}
export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
const es = getService('es');
const esArchiver = getService('esArchiver');
const esDeleteAllIndices = getService('esDeleteAllIndices');

describe('export', () => {
let KIBANA_VERSION: string;
Expand Down Expand Up @@ -534,7 +534,7 @@ export default function ({ getService }: FtrProviderContext) {
before(
async () =>
// just in case the kibana server has recreated it
await es.indices.delete({ index: '.kibana' }, { ignore: [404] })
await esDeleteAllIndices('.kibana')
);

it('should return empty response', async () => {
Expand Down
4 changes: 2 additions & 2 deletions test/api_integration/apis/saved_objects/find.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import { getKibanaVersion } from './lib/saved_objects_test_utils';

export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
const es = getService('es');
const esArchiver = getService('esArchiver');
const esDeleteAllIndices = getService('esDeleteAllIndices');

describe('find', () => {
let KIBANA_VERSION: string;
Expand Down Expand Up @@ -430,7 +430,7 @@ export default function ({ getService }: FtrProviderContext) {
before(
async () =>
// just in case the kibana server has recreated it
await es.indices.delete({ index: '.kibana' }, { ignore: [404] })
await esDeleteAllIndices('.kibana')
);

it('should return 200 with empty response', async () =>
Expand Down
4 changes: 2 additions & 2 deletions test/api_integration/apis/saved_objects/get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import { getKibanaVersion } from './lib/saved_objects_test_utils';

export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
const es = getService('es');
const esArchiver = getService('esArchiver');
const esDeleteAllIndices = getService('esDeleteAllIndices');

describe('get', () => {
let KIBANA_VERSION: string;
Expand Down Expand Up @@ -78,7 +78,7 @@ export default function ({ getService }: FtrProviderContext) {
before(
async () =>
// just in case the kibana server has recreated it
await es.indices.delete({ index: '.kibana' }, { ignore: [404] })
await esDeleteAllIndices('.kibana')
);

it('should return basic 404 without mentioning index', async () =>
Expand Down
24 changes: 17 additions & 7 deletions test/api_integration/apis/saved_objects/migrations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,10 @@ function getLogMock() {
}
export default ({ getService }: FtrProviderContext) => {
const esClient = getService('es');
const esDeleteAllIndices = getService('esDeleteAllIndices');

describe('Kibana index migration', () => {
before(() => esClient.indices.delete({ index: '.migrate-*' }));
before(() => esDeleteAllIndices('.migrate-*'));

it('Migrates an existing index that has never been migrated before', async () => {
const index = '.migration-a';
Expand Down Expand Up @@ -99,7 +100,7 @@ export default ({ getService }: FtrProviderContext) => {
},
];

await createIndex({ esClient, index });
await createIndex({ esClient, index, esDeleteAllIndices });
await createDocs({ esClient, index, docs: originalDocs });

// Test that unrelated index templates are unaffected
Expand Down Expand Up @@ -233,7 +234,7 @@ export default ({ getService }: FtrProviderContext) => {
},
];

await createIndex({ esClient, index });
await createIndex({ esClient, index, esDeleteAllIndices });
await createDocs({ esClient, index, docs: originalDocs });

await migrateIndex({ esClient, index, savedObjectTypes, mappingProperties });
Expand Down Expand Up @@ -347,7 +348,7 @@ export default ({ getService }: FtrProviderContext) => {
},
];

await createIndex({ esClient, index });
await createIndex({ esClient, index, esDeleteAllIndices });
await createDocs({ esClient, index, docs: originalDocs });

const result = await Promise.all([
Expand Down Expand Up @@ -445,7 +446,7 @@ export default ({ getService }: FtrProviderContext) => {
BAZ_TYPE, // must be registered for reference transforms to be applied to objects of this type
];

await createIndex({ esClient, index });
await createIndex({ esClient, index, esDeleteAllIndices });
await createDocs({ esClient, index, docs: originalDocs });

await migrateIndex({
Expand Down Expand Up @@ -554,8 +555,17 @@ export default ({ getService }: FtrProviderContext) => {
});
};

async function createIndex({ esClient, index }: { esClient: ElasticsearchClient; index: string }) {
await esClient.indices.delete({ index: `${index}*` }, { ignore: [404] });
async function createIndex({
esClient,
index,
esDeleteAllIndices,
}: {
esClient: ElasticsearchClient;
index: string;
esDeleteAllIndices: (pattern: string) => Promise<void>;
}) {
await esDeleteAllIndices(`${index}*`);

const properties = {
type: { type: 'keyword' },
foo: { properties: { name: { type: 'keyword' } } },
Expand Down
4 changes: 2 additions & 2 deletions test/api_integration/apis/saved_objects/resolve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import { getKibanaVersion } from './lib/saved_objects_test_utils';

export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
const es = getService('es');
const esArchiver = getService('esArchiver');
const esDeleteAllIndices = getService('esDeleteAllIndices');

describe('resolve', () => {
let KIBANA_VERSION: string;
Expand Down Expand Up @@ -81,7 +81,7 @@ export default function ({ getService }: FtrProviderContext) {
before(
async () =>
// just in case the kibana server has recreated it
await es.indices.delete({ index: '.kibana' }, { ignore: [404] })
await esDeleteAllIndices('.kibana')
);

it('should return basic 404 without mentioning index', async () =>
Expand Down
4 changes: 2 additions & 2 deletions test/api_integration/apis/saved_objects/update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import { FtrProviderContext } from '../../ftr_provider_context';

export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
const es = getService('es');
const esArchiver = getService('esArchiver');
const esDeleteAllIndices = getService('esDeleteAllIndices');

describe('update', () => {
describe('with kibana index', () => {
Expand Down Expand Up @@ -121,7 +121,7 @@ export default function ({ getService }: FtrProviderContext) {
before(
async () =>
// just in case the kibana server has recreated it
await es.indices.delete({ index: '.kibana' }, { ignore: [404] })
await esDeleteAllIndices('.kibana')
);

it('should return generic 404', async () =>
Expand Down
4 changes: 2 additions & 2 deletions test/api_integration/apis/saved_objects_management/find.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { Response } from 'supertest';
import { FtrProviderContext } from '../../ftr_provider_context';

export default function ({ getService }: FtrProviderContext) {
const es = getService('es');
const esDeleteAllIndices = getService('esDeleteAllIndices');
const supertest = getService('supertest');
const esArchiver = getService('esArchiver');
const kibanaServer = getService('kibanaServer');
Expand Down Expand Up @@ -184,7 +184,7 @@ export default function ({ getService }: FtrProviderContext) {
before(
async () =>
// just in case the kibana server has recreated it
await es.indices.delete({ index: '.kibana' }, { ignore: [404] })
await esDeleteAllIndices('.kibana')
);

it('should return 200 with empty response', async () =>
Expand Down
4 changes: 2 additions & 2 deletions test/api_integration/apis/saved_objects_management/get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { Response } from 'supertest';
import { FtrProviderContext } from '../../ftr_provider_context';

export default function ({ getService }: FtrProviderContext) {
const es = getService('es');
const esDeleteAllIndices = getService('esDeleteAllIndices');
const supertest = getService('supertest');
const esArchiver = getService('esArchiver');

Expand Down Expand Up @@ -45,7 +45,7 @@ export default function ({ getService }: FtrProviderContext) {
before(
async () =>
// just in case the kibana server has recreated it
await es.indices.delete({ index: '.kibana' }, { ignore: [404] })
await esDeleteAllIndices('.kibana')
);

it('should return 404 for object that no longer exists', async () =>
Expand Down
61 changes: 61 additions & 0 deletions test/common/services/es_delete_all_indices.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import { FtrProviderContext } from '../ftr_provider_context';

export function EsDeleteAllIndicesProvider({ getService }: FtrProviderContext) {
const es = getService('es');
const log = getService('log');

async function deleteConcreteIndices(indices: string[]) {
try {
await es.indices.delete({
index: indices,
ignore_unavailable: true,
});
} catch (error) {
log.debug(`Failed to delete indices [${indices}], but ignoring error: ${error.message}`);
}
}

return async (patterns: string | string[]) => {
for (const pattern of [patterns].flat()) {
for (let attempt = 1; ; attempt++) {
if (attempt > 5) {
throw new Error(`Failed to delete all indices with pattern [${pattern}]`);
}

// resolve pattern to concrete index names
const resp = await es.indices.getAlias(
{
index: pattern,
},
{
ignore: [404],
}
);
const indices = Object.keys(resp.body) as string[];

// if no indexes exits then we're done with this pattern
if (resp.statusCode === 404 || !indices.length) {
if (attempt === 1) {
log.debug(`No indices to delete [pattern=${pattern}]`);
}
break;
}

log.debug(
`Deleting indices [attempt=${attempt}] [pattern=${pattern}] "${indices.join('", "')}"`
);

// delete the concrete indexes we found and try again until this pattern resolves to no indexes
await deleteConcreteIndices(indices);
}
}
};
}
2 changes: 2 additions & 0 deletions test/common/services/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { KibanaServerProvider } from './kibana_server';
import { RetryProvider } from './retry';
import { RandomnessProvider } from './randomness';
import { SecurityServiceProvider } from './security';
import { EsDeleteAllIndicesProvider } from './es_delete_all_indices';

export const services = {
deployment: DeploymentProvider,
Expand All @@ -24,4 +25,5 @@ export const services = {
retry: RetryProvider,
randomness: RandomnessProvider,
security: SecurityServiceProvider,
esDeleteAllIndices: EsDeleteAllIndicesProvider,
};
Loading

0 comments on commit 684edff

Please sign in to comment.