Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ResponseOps][Alerting] action validators should be passed allow-list config utils #139438

Merged
1 change: 1 addition & 0 deletions x-pack/plugins/actions/server/action_type_registry.mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const createActionTypeRegistryMock = () => {
ensureActionTypeEnabled: jest.fn(),
isActionTypeEnabled: jest.fn(),
isActionExecutable: jest.fn(),
getUtils: jest.fn(),
};
return mocked;
};
Expand Down
7 changes: 7 additions & 0 deletions x-pack/plugins/actions/server/action_type_registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,4 +212,11 @@ export class ActionTypeRegistry {
supportedFeatureIds: actionType.supportedFeatureIds,
}));
}

/**
* Returns the actions configuration utilities
*/
public getUtils(): ActionsConfigurationUtilities {
return this.actionsConfigUtils;
}
}
16 changes: 10 additions & 6 deletions x-pack/plugins/actions/server/actions_client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -376,9 +376,11 @@ describe('create()', () => {
minimumLicenseRequired: 'basic',
supportedFeatureIds: ['alerting'],
validate: {
config: schema.object({
param1: schema.string(),
}),
config: {
schema: schema.object({
param1: schema.string(),
}),
},
},
executor,
});
Expand Down Expand Up @@ -1949,9 +1951,11 @@ describe('update()', () => {
minimumLicenseRequired: 'basic',
supportedFeatureIds: ['alerting'],
validate: {
config: schema.object({
param1: schema.string(),
}),
config: {
schema: schema.object({
param1: schema.string(),
}),
},
},
executor,
});
Expand Down
18 changes: 14 additions & 4 deletions x-pack/plugins/actions/server/actions_client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,13 @@ export class ActionsClient {
}

const actionType = this.actionTypeRegistry.get(actionTypeId);
const validatedActionTypeConfig = validateConfig(actionType, config);
const validatedActionTypeSecrets = validateSecrets(actionType, secrets);
const configurationUtilities = this.actionTypeRegistry.getUtils();
const validatedActionTypeConfig = validateConfig(actionType, config, {
configurationUtilities,
});
const validatedActionTypeSecrets = validateSecrets(actionType, secrets, {
configurationUtilities,
});
if (actionType.validate?.connector) {
validateConnector(actionType, { config, secrets });
}
Expand Down Expand Up @@ -262,8 +267,13 @@ export class ActionsClient {
const { actionTypeId } = attributes;
const { name, config, secrets } = action;
const actionType = this.actionTypeRegistry.get(actionTypeId);
const validatedActionTypeConfig = validateConfig(actionType, config);
const validatedActionTypeSecrets = validateSecrets(actionType, secrets);
const configurationUtilities = this.actionTypeRegistry.getUtils();
const validatedActionTypeConfig = validateConfig(actionType, config, {
configurationUtilities,
});
const validatedActionTypeSecrets = validateSecrets(actionType, secrets, {
configurationUtilities,
});
if (actionType.validate?.connector) {
validateConnector(actionType, { config, secrets });
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
*/

import { curry } from 'lodash';
import { schema } from '@kbn/config-schema';
import { Logger } from '@kbn/core/server';
import { CasesConnectorFeatureId } from '../../../common';
import {
Expand All @@ -22,8 +21,8 @@ import { ActionsConfigurationUtilities } from '../../actions_config';
import { createExternalService } from './service';
import {
ExecutorParamsSchema,
ExternalIncidentServiceConfiguration,
ExternalIncidentServiceSecretConfiguration,
ExternalIncidentServiceConfigurationSchema,
ExternalIncidentServiceSecretConfigurationSchema,
} from './schema';
import { api } from './api';
import { validate } from './validators';
Expand All @@ -50,13 +49,17 @@ export function getActionType({
minimumLicenseRequired: 'gold',
name: i18n.NAME,
validate: {
config: schema.object(ExternalIncidentServiceConfiguration, {
validate: curry(validate.config)(configurationUtilities),
}),
secrets: schema.object(ExternalIncidentServiceSecretConfiguration, {
validate: curry(validate.secrets),
}),
params: ExecutorParamsSchema,
config: {
schema: ExternalIncidentServiceConfigurationSchema,
customValidator: validate.config,
},
secrets: {
schema: ExternalIncidentServiceSecretConfigurationSchema,
customValidator: validate.secrets,
},
params: {
schema: ExecutorParamsSchema,
},
connector: validate.connector,
},
executor: curry(executor)({ logger, configurationUtilities }),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import { TypeOf } from '@kbn/config-schema';
import { Logger } from '@kbn/core/server';
import { ActionsConfigurationUtilities } from '../../actions_config';
import { ValidatorServices } from '../../types';
import {
ExecutorParamsSchema,
ExecutorSubActionPushParamsSchema,
Expand Down Expand Up @@ -40,10 +40,13 @@ export interface ExternalServiceCredentials {

export interface ExternalServiceValidation {
config: (
configurationUtilities: ActionsConfigurationUtilities,
configObject: CasesWebhookPublicConfigurationType
configObject: CasesWebhookPublicConfigurationType,
validatorServices: ValidatorServices
) => void;
secrets: (
secrets: CasesWebhookSecretConfigurationType,
validatorServices: ValidatorServices
) => void;
secrets: (secrets: CasesWebhookSecretConfigurationType) => void;
connector: (
configObject: CasesWebhookPublicConfigurationType,
secrets: CasesWebhookSecretConfigurationType
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ import {
CasesWebhookSecretConfigurationType,
ExternalServiceValidation,
} from './types';
import { ValidatorServices } from '../../types';

const validateConfig = (
configurationUtilities: ActionsConfigurationUtilities,
configObject: CasesWebhookPublicConfigurationType
configObject: CasesWebhookPublicConfigurationType,
validatorServices: ValidatorServices
) => {
const { configurationUtilities } = validatorServices;
const {
createCommentUrl,
createIncidentUrl,
Expand All @@ -38,12 +40,12 @@ const validateConfig = (
try {
new URL(url);
} catch (err) {
return i18n.INVALID_URL(err, url);
throw new Error(i18n.INVALID_URL(err, url));
}
try {
configurationUtilities.ensureUriAllowed(url);
} catch (allowListError) {
return i18n.CONFIG_ERR(allowListError.message);
throw new Error(i18n.CONFIG_ERR(allowListError.message));
}
}
}
Expand All @@ -59,11 +61,14 @@ export const validateConnector = (
return i18n.INVALID_USER_PW;
};

export const validateSecrets = (secrets: CasesWebhookSecretConfigurationType) => {
export const validateSecrets = (
secrets: CasesWebhookSecretConfigurationType,
validatorServices: ValidatorServices
) => {
// user and password must be set together (or not at all)
if (!secrets.password && !secrets.user) return;
if (secrets.password && secrets.user) return;
return i18n.INVALID_USER_PW;
throw new Error(i18n.INVALID_USER_PW);
};

export const validate: ExternalServiceValidation = {
Expand Down
Loading