Skip to content

Commit

Permalink
enabled actions scoped within the stack to register at Basic license
Browse files Browse the repository at this point in the history
  • Loading branch information
gmmorris committed Nov 9, 2020
1 parent bc05e79 commit 34d4a6c
Show file tree
Hide file tree
Showing 8 changed files with 114 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,11 @@ const ParamsSchema = schema.object({
documents: schema.arrayOf(schema.recordOf(schema.string(), schema.any())),
});

export const ES_INDEX_ACTION_ID = '.index';
// action type definition
export function getActionType({ logger }: { logger: Logger }): ESIndexActionType {
return {
id: '.index',
id: ES_INDEX_ACTION_ID,
minimumLicenseRequired: 'basic',
name: i18n.translate('xpack.actions.builtin.esIndexTitle', {
defaultMessage: 'Index',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,11 @@ const ParamsSchema = schema.object({
),
});

export const SERVER_LOG_ACTION_ID = '.server-log';
// action type definition
export function getActionType({ logger }: { logger: Logger }): ServerLogActionType {
return {
id: '.server-log',
id: SERVER_LOG_ACTION_ID,
minimumLicenseRequired: 'basic',
name: i18n.translate('xpack.actions.builtin.serverLogTitle', {
defaultMessage: 'Server log',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { ActionType } from '../types';
import { ensureSufficientLicense } from './ensure_sufficient_license';

const sampleActionType: ActionType = {
id: 'test',
name: 'test',
minimumLicenseRequired: 'basic',
async executor({ actionId }) {
return { status: 'ok', actionId };
},
};

describe('ensureSufficientLicense()', () => {
it('throws for licenses below gold', () => {
expect(() => ensureSufficientLicense(sampleActionType)).toThrowErrorMatchingInlineSnapshot(
`"Third party action type \\"test\\" can only set minimumLicenseRequired to a gold license or higher"`
);
});

it('allows licenses below gold for allowed connectors', () => {
expect(() =>
ensureSufficientLicense({ ...sampleActionType, id: '.case', minimumLicenseRequired: 'basic' })
).not.toThrow();
expect(() =>
ensureSufficientLicense({
...sampleActionType,
id: '.server-log',
minimumLicenseRequired: 'basic',
})
).not.toThrow();
expect(() =>
ensureSufficientLicense({
...sampleActionType,
id: '.index',
minimumLicenseRequired: 'basic',
})
).not.toThrow();
});

it('allows licenses at gold', () => {
expect(() =>
ensureSufficientLicense({ ...sampleActionType, minimumLicenseRequired: 'gold' })
).not.toThrow();
});

it('allows licenses above gold', () => {
expect(() =>
ensureSufficientLicense({ ...sampleActionType, minimumLicenseRequired: 'platinum' })
).not.toThrow();
});

it('throws when license type is invalid', async () => {
expect(() =>
ensureSufficientLicense({
...sampleActionType,
// we're faking an invalid value, this requires stripping the typing
// eslint-disable-next-line @typescript-eslint/no-explicit-any
minimumLicenseRequired: 'foo' as any,
})
).toThrowErrorMatchingInlineSnapshot(`"\\"foo\\" is not a valid license type"`);
});
});
36 changes: 36 additions & 0 deletions x-pack/plugins/actions/server/lib/ensure_sufficient_license.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { ActionType } from '../types';
import { LICENSE_TYPE } from '../../../licensing/common/types';
import { SERVER_LOG_ACTION_ID } from '../builtin_action_types/server_log';
import { ES_INDEX_ACTION_ID } from '../builtin_action_types/es_index';
import { CASE_ACTION_ID } from '../../../case/server';
import { ActionTypeConfig, ActionTypeSecrets, ActionTypeParams } from '../types';

const ACTIONS_SCOPED_WITHIN_STACK = new Set([
SERVER_LOG_ACTION_ID,
ES_INDEX_ACTION_ID,
CASE_ACTION_ID,
]);

export function ensureSufficientLicense<
Config extends ActionTypeConfig,
Secrets extends ActionTypeSecrets,
Params extends ActionTypeParams,
ExecutorResultData
>(actionType: ActionType<Config, Secrets, Params, ExecutorResultData>) {
if (!(actionType.minimumLicenseRequired in LICENSE_TYPE)) {
throw new Error(`"${actionType.minimumLicenseRequired}" is not a valid license type`);
}
if (
LICENSE_TYPE[actionType.minimumLicenseRequired] < LICENSE_TYPE.gold &&
!ACTIONS_SCOPED_WITHIN_STACK.has(actionType.id)
) {
throw new Error(
`Third party action type "${actionType.id}" can only set minimumLicenseRequired to a gold license or higher`
);
}
}
11 changes: 2 additions & 9 deletions x-pack/plugins/actions/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import {
} from '../../encrypted_saved_objects/server';
import { TaskManagerSetupContract, TaskManagerStartContract } from '../../task_manager/server';
import { LicensingPluginSetup, LicensingPluginStart } from '../../licensing/server';
import { LICENSE_TYPE } from '../../licensing/common/types';
import { SpacesPluginSetup, SpacesServiceSetup } from '../../spaces/server';
import { PluginSetupContract as FeaturesPluginSetup } from '../../features/server';
import { SecurityPluginSetup } from '../../security/server';
Expand Down Expand Up @@ -75,6 +74,7 @@ import {
getAuthorizationModeBySource,
AuthorizationMode,
} from './authorization/get_authorization_mode_by_source';
import { ensureSufficientLicense } from './lib/ensure_sufficient_license';

const EVENT_LOG_PROVIDER = 'actions';
export const EVENT_LOG_ACTIONS = {
Expand Down Expand Up @@ -260,14 +260,7 @@ export class ActionsPlugin implements Plugin<Promise<PluginSetupContract>, Plugi
>(
actionType: ActionType<Config, Secrets, Params, ExecutorResultData>
) => {
if (!(actionType.minimumLicenseRequired in LICENSE_TYPE)) {
throw new Error(`"${actionType.minimumLicenseRequired}" is not a valid license type`);
}
if (LICENSE_TYPE[actionType.minimumLicenseRequired] < LICENSE_TYPE.gold) {
throw new Error(
`Third party action type "${actionType.id}" can only set minimumLicenseRequired to a gold license or higher`
);
}
ensureSufficientLicense(actionType);
actionTypeRegistry.register(actionType);
},
};
Expand Down
3 changes: 2 additions & 1 deletion x-pack/plugins/case/server/connectors/case/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { GetActionTypeParams } from '..';

const supportedSubActions: string[] = ['create', 'update', 'addComment'];

export const CASE_ACTION_ID = '.case';
// action type definition
export function getActionType({
logger,
Expand All @@ -31,7 +32,7 @@ export function getActionType({
userActionService,
}: GetActionTypeParams): CaseActionType {
return {
id: '.case',
id: CASE_ACTION_ID,
minimumLicenseRequired: 'gold',
name: i18n.NAME,
validate: {
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/case/server/connectors/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
} from '../services';

import { getActionType as getCaseConnector } from './case';
export { CASE_ACTION_ID } from './case';

export interface GetActionTypeParams {
logger: Logger;
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/case/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { PluginInitializerContext } from '../../../../src/core/server';
import { ConfigSchema } from './config';
import { CasePlugin } from './plugin';

export { CASE_ACTION_ID } from './connectors';
export const config = { schema: ConfigSchema };
export const plugin = (initializerContext: PluginInitializerContext) =>
new CasePlugin(initializerContext);

0 comments on commit 34d4a6c

Please sign in to comment.