2020-01-22 18:08:54 +01:00
/ *
* 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 .
* /
2020-10-28 11:03:04 +01:00
import type { PublicMethodsOf } from '@kbn/utility-types' ;
2020-11-21 05:27:03 +01:00
import { first } from 'rxjs/operators' ;
2020-03-12 18:46:24 +01:00
import { UsageCollectionSetup } from 'src/plugins/usage_collection/server' ;
2020-11-21 05:27:03 +01:00
import { Observable } from 'rxjs' ;
2020-01-22 18:08:54 +01:00
import {
PluginInitializerContext ,
Plugin ,
CoreSetup ,
CoreStart ,
KibanaRequest ,
Logger ,
IContextProvider ,
2020-04-15 17:07:57 +02:00
ElasticsearchServiceStart ,
2020-06-29 17:43:31 +02:00
ILegacyClusterClient ,
2020-05-22 10:07:09 +02:00
SavedObjectsClientContract ,
2021-01-13 01:25:23 +01:00
SavedObjectsBulkGetObject ,
2020-01-22 18:08:54 +01:00
} from '../../../../src/core/server' ;
import {
2020-02-03 14:43:10 +01:00
EncryptedSavedObjectsPluginSetup ,
EncryptedSavedObjectsPluginStart ,
2020-01-22 18:08:54 +01:00
} from '../../encrypted_saved_objects/server' ;
import { TaskManagerSetupContract , TaskManagerStartContract } from '../../task_manager/server' ;
2020-10-15 20:47:46 +02:00
import { LicensingPluginSetup , LicensingPluginStart } from '../../licensing/server' ;
2020-11-19 19:41:13 +01:00
import { SpacesPluginStart } from '../../spaces/server' ;
2020-07-22 15:45:57 +02:00
import { PluginSetupContract as FeaturesPluginSetup } from '../../features/server' ;
import { SecurityPluginSetup } from '../../security/server' ;
2020-01-22 18:08:54 +01:00
import { ActionsConfig } from './config' ;
2020-03-20 15:49:37 +01:00
import { ActionExecutor , TaskRunnerFactory , LicenseState , ILicenseState } from './lib' ;
2020-01-22 18:08:54 +01:00
import { ActionsClient } from './actions_client' ;
import { ActionTypeRegistry } from './action_type_registry' ;
2020-06-16 10:33:10 +02:00
import { createExecutionEnqueuerFunction } from './create_execute_function' ;
2020-01-22 18:08:54 +01:00
import { registerBuiltInActionTypes } from './builtin_action_types' ;
2020-03-12 18:46:24 +01:00
import { registerActionsUsageCollector } from './usage' ;
2020-08-04 21:50:17 +02:00
import {
Services ,
ActionType ,
PreConfiguredAction ,
ActionTypeConfig ,
ActionTypeSecrets ,
ActionTypeParams ,
2021-01-21 15:20:22 +01:00
ActionsRequestHandlerContext ,
2020-08-04 21:50:17 +02:00
} from './types' ;
2020-01-22 18:08:54 +01:00
import { getActionsConfigurationUtilities } from './actions_config' ;
import {
createActionRoute ,
deleteActionRoute ,
2020-04-08 18:54:42 +02:00
getAllActionRoute ,
2020-01-22 18:08:54 +01:00
getActionRoute ,
updateActionRoute ,
listActionTypesRoute ,
executeActionRoute ,
} from './routes' ;
import { IEventLogger , IEventLogService } from '../../event_log/server' ;
2020-03-12 18:46:24 +01:00
import { initializeActionsTelemetry , scheduleActionsTelemetry } from './usage/task' ;
2020-07-22 15:45:57 +02:00
import {
setupSavedObjects ,
ACTION_SAVED_OBJECT_TYPE ,
ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE ,
2020-09-16 12:47:37 +02:00
ALERT_SAVED_OBJECT_TYPE ,
2020-07-22 15:45:57 +02:00
} from './saved_objects' ;
import { ACTIONS_FEATURE } from './feature' ;
import { ActionsAuthorization } from './authorization/actions_authorization' ;
import { ActionsAuthorizationAuditLogger } from './authorization/audit_logger' ;
2020-09-16 12:47:37 +02:00
import { ActionExecutionSource } from './lib/action_execution_source' ;
2020-09-18 10:54:49 +02:00
import {
getAuthorizationModeBySource ,
AuthorizationMode ,
} from './authorization/get_authorization_mode_by_source' ;
2020-11-12 18:31:44 +01:00
import { ensureSufficientLicense } from './lib/ensure_sufficient_license' ;
Allow action types to perform their own mustache variable escaping in parameter templates (#83919)
resolves https://github.com/elastic/kibana/issues/79371
resolves https://github.com/elastic/kibana/issues/62928
In this PR, we allow action types to determine how to escape the
variables used in their parameters, when rendered as mustache
templates. Prior to this, action parameters were recursively
rendered as mustache templates using the default mustache
templating, by the alerts library. The default mustache
templating used html escaping.
Action types opt-in to the new capability via a new optional
method in the action type, `renderParameterTemplates()`. If not
provided, the previous recursive rendering is done, but now with
no escaping at all.
For #62928, changed the mustache template rendering to be
replaced with the error message, if an error occurred,
so at least you can now see that an error occurred. Useful
to diagnose problems with invalid mustache templates.
2020-12-15 02:41:13 +01:00
import { renderMustacheObject } from './lib/mustache_renderer' ;
2020-01-22 18:08:54 +01:00
const EVENT_LOG_PROVIDER = 'actions' ;
export const EVENT_LOG_ACTIONS = {
execute : 'execute' ,
executeViaHttp : 'execute-via-http' ,
} ;
export interface PluginSetupContract {
2020-08-04 21:50:17 +02:00
registerType <
Config extends ActionTypeConfig = ActionTypeConfig ,
Secrets extends ActionTypeSecrets = ActionTypeSecrets ,
2020-10-30 23:26:12 +01:00
Params extends ActionTypeParams = ActionTypeParams ,
ExecutorResultData = void
2020-08-04 21:50:17 +02:00
> (
2020-10-30 23:26:12 +01:00
actionType : ActionType < Config , Secrets , Params , ExecutorResultData >
2020-08-04 21:50:17 +02:00
) : void ;
2020-01-22 18:08:54 +01:00
}
export interface PluginStartContract {
2020-10-15 20:47:46 +02:00
isActionTypeEnabled ( id : string , options ? : { notifyUsage : boolean } ) : boolean ;
isActionExecutable (
actionId : string ,
actionTypeId : string ,
options ? : { notifyUsage : boolean }
) : boolean ;
2020-02-12 19:49:16 +01:00
getActionsClientWithRequest ( request : KibanaRequest ) : Promise < PublicMethodsOf < ActionsClient > > ;
2020-07-22 15:45:57 +02:00
getActionsAuthorizationWithRequest ( request : KibanaRequest ) : PublicMethodsOf < ActionsAuthorization > ;
2020-04-08 18:54:42 +02:00
preconfiguredActions : PreConfiguredAction [ ] ;
Allow action types to perform their own mustache variable escaping in parameter templates (#83919)
resolves https://github.com/elastic/kibana/issues/79371
resolves https://github.com/elastic/kibana/issues/62928
In this PR, we allow action types to determine how to escape the
variables used in their parameters, when rendered as mustache
templates. Prior to this, action parameters were recursively
rendered as mustache templates using the default mustache
templating, by the alerts library. The default mustache
templating used html escaping.
Action types opt-in to the new capability via a new optional
method in the action type, `renderParameterTemplates()`. If not
provided, the previous recursive rendering is done, but now with
no escaping at all.
For #62928, changed the mustache template rendering to be
replaced with the error message, if an error occurred,
so at least you can now see that an error occurred. Useful
to diagnose problems with invalid mustache templates.
2020-12-15 02:41:13 +01:00
renderActionParameterTemplates < Params extends ActionTypeParams = ActionTypeParams > (
actionTypeId : string ,
params : Params ,
variables : Record < string , unknown >
) : Params ;
2020-01-22 18:08:54 +01:00
}
export interface ActionsPluginsSetup {
taskManager : TaskManagerSetupContract ;
2020-02-03 14:43:10 +01:00
encryptedSavedObjects : EncryptedSavedObjectsPluginSetup ;
2020-01-22 18:08:54 +01:00
licensing : LicensingPluginSetup ;
2020-02-17 02:10:35 +01:00
eventLog : IEventLogService ;
2020-03-12 18:46:24 +01:00
usageCollection? : UsageCollectionSetup ;
2020-07-22 15:45:57 +02:00
security? : SecurityPluginSetup ;
features : FeaturesPluginSetup ;
2020-01-22 18:08:54 +01:00
}
export interface ActionsPluginsStart {
2020-02-03 14:43:10 +01:00
encryptedSavedObjects : EncryptedSavedObjectsPluginStart ;
2020-01-22 18:08:54 +01:00
taskManager : TaskManagerStartContract ;
2020-10-15 20:47:46 +02:00
licensing : LicensingPluginStart ;
2020-11-19 19:41:13 +01:00
spaces? : SpacesPluginStart ;
2020-01-22 18:08:54 +01:00
}
2020-09-16 12:47:37 +02:00
const includedHiddenTypes = [
ACTION_SAVED_OBJECT_TYPE ,
ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE ,
ALERT_SAVED_OBJECT_TYPE ,
] ;
2020-05-22 10:07:09 +02:00
2020-01-22 18:08:54 +01:00
export class ActionsPlugin implements Plugin < Promise < PluginSetupContract > , PluginStartContract > {
private readonly config : Promise < ActionsConfig > ;
private readonly logger : Logger ;
2020-08-14 23:20:12 +02:00
private actionsConfig? : ActionsConfig ;
2020-01-22 18:08:54 +01:00
private taskRunnerFactory? : TaskRunnerFactory ;
private actionTypeRegistry? : ActionTypeRegistry ;
private actionExecutor? : ActionExecutor ;
2020-03-20 15:49:37 +01:00
private licenseState : ILicenseState | null = null ;
2020-07-22 15:45:57 +02:00
private security? : SecurityPluginSetup ;
2020-08-11 16:00:02 +02:00
private eventLogService? : IEventLogService ;
2020-01-22 18:08:54 +01:00
private eventLogger? : IEventLogger ;
2020-02-12 19:49:16 +01:00
private isESOUsingEphemeralEncryptionKey? : boolean ;
2020-03-12 18:46:24 +01:00
private readonly telemetryLogger : Logger ;
2020-04-08 18:54:42 +02:00
private readonly preconfiguredActions : PreConfiguredAction [ ] ;
2020-11-21 05:27:03 +01:00
private readonly kibanaIndexConfig : Observable < { kibana : { index : string } } > ;
2020-01-22 18:08:54 +01:00
constructor ( initContext : PluginInitializerContext ) {
2020-05-22 09:08:58 +02:00
this . config = initContext . config . create < ActionsConfig > ( ) . pipe ( first ( ) ) . toPromise ( ) ;
2020-01-22 18:08:54 +01:00
this . logger = initContext . logger . get ( 'actions' ) ;
2020-10-01 09:25:05 +02:00
this . telemetryLogger = initContext . logger . get ( 'usage' ) ;
2020-04-08 18:54:42 +02:00
this . preconfiguredActions = [ ] ;
2020-11-21 05:27:03 +01:00
this . kibanaIndexConfig = initContext . config . legacy . globalConfig $ ;
2020-01-22 18:08:54 +01:00
}
2020-04-24 18:04:36 +02:00
public async setup (
core : CoreSetup < ActionsPluginsStart > ,
plugins : ActionsPluginsSetup
) : Promise < PluginSetupContract > {
2020-03-20 15:49:37 +01:00
this . licenseState = new LicenseState ( plugins . licensing . license $ ) ;
2020-02-12 19:49:16 +01:00
this . isESOUsingEphemeralEncryptionKey =
plugins . encryptedSavedObjects . usingEphemeralEncryptionKey ;
if ( this . isESOUsingEphemeralEncryptionKey ) {
this . logger . warn (
2020-11-19 19:41:48 +01:00
'APIs are disabled because the Encrypted Saved Objects plugin uses an ephemeral encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command.'
2020-02-12 19:49:16 +01:00
) ;
}
2020-09-14 15:30:47 +02:00
plugins . features . registerKibanaFeature ( ACTIONS_FEATURE ) ;
2020-04-29 16:46:54 +02:00
setupSavedObjects ( core . savedObjects , plugins . encryptedSavedObjects ) ;
2020-01-22 18:08:54 +01:00
2020-08-11 16:00:02 +02:00
this . eventLogService = plugins . eventLog ;
2020-02-17 02:10:35 +01:00
plugins . eventLog . registerProviderActions ( EVENT_LOG_PROVIDER , Object . values ( EVENT_LOG_ACTIONS ) ) ;
this . eventLogger = plugins . eventLog . getLogger ( {
2020-01-22 18:08:54 +01:00
event : { provider : EVENT_LOG_PROVIDER } ,
} ) ;
2020-02-12 19:49:16 +01:00
const actionExecutor = new ActionExecutor ( {
isESOUsingEphemeralEncryptionKey : this.isESOUsingEphemeralEncryptionKey ,
} ) ;
2020-03-12 18:46:24 +01:00
// get executions count
2020-01-22 18:08:54 +01:00
const taskRunnerFactory = new TaskRunnerFactory ( actionExecutor ) ;
2020-08-14 23:20:12 +02:00
this . actionsConfig = ( await this . config ) as ActionsConfig ;
const actionsConfigUtils = getActionsConfigurationUtilities ( this . actionsConfig ) ;
2020-04-08 18:54:42 +02:00
2020-08-14 23:20:12 +02:00
for ( const preconfiguredId of Object . keys ( this . actionsConfig . preconfigured ) ) {
2020-05-07 21:12:01 +02:00
this . preconfiguredActions . push ( {
2020-08-14 23:20:12 +02:00
. . . this . actionsConfig . preconfigured [ preconfiguredId ] ,
2020-05-07 21:12:01 +02:00
id : preconfiguredId ,
isPreconfigured : true ,
} ) ;
}
2020-01-22 18:08:54 +01:00
const actionTypeRegistry = new ActionTypeRegistry ( {
2020-10-15 20:47:46 +02:00
licensing : plugins.licensing ,
2020-01-22 18:08:54 +01:00
taskRunnerFactory ,
taskManager : plugins.taskManager ,
actionsConfigUtils ,
2020-03-20 15:49:37 +01:00
licenseState : this.licenseState ,
2020-04-24 23:38:28 +02:00
preconfiguredActions : this.preconfiguredActions ,
2020-01-22 18:08:54 +01:00
} ) ;
this . taskRunnerFactory = taskRunnerFactory ;
this . actionTypeRegistry = actionTypeRegistry ;
this . actionExecutor = actionExecutor ;
2020-07-22 15:45:57 +02:00
this . security = plugins . security ;
2020-01-22 18:08:54 +01:00
registerBuiltInActionTypes ( {
logger : this.logger ,
actionTypeRegistry ,
actionsConfigUtils ,
2020-12-15 19:51:44 +01:00
publicBaseUrl : core.http.basePath.publicBaseUrl ,
2020-01-22 18:08:54 +01:00
} ) ;
2020-03-12 18:46:24 +01:00
const usageCollection = plugins . usageCollection ;
if ( usageCollection ) {
2020-11-21 05:27:03 +01:00
registerActionsUsageCollector (
usageCollection ,
core . getStartServices ( ) . then ( ( [ _ , { taskManager } ] ) = > taskManager )
2020-05-06 10:57:26 +02:00
) ;
2020-03-12 18:46:24 +01:00
}
2020-11-21 05:27:03 +01:00
this . kibanaIndexConfig . subscribe ( ( config ) = > {
2021-01-21 15:20:22 +01:00
core . http . registerRouteHandlerContext < ActionsRequestHandlerContext , ' actions ' > (
2020-11-21 05:27:03 +01:00
'actions' ,
this . createRouteHandlerContext ( core , config . kibana . index )
) ;
if ( usageCollection ) {
initializeActionsTelemetry (
this . telemetryLogger ,
plugins . taskManager ,
core ,
config . kibana . index
) ;
}
} ) ;
2020-01-22 18:08:54 +01:00
// Routes
2021-01-21 15:20:22 +01:00
const router = core . http . createRouter < ActionsRequestHandlerContext > ( ) ;
2020-01-22 18:08:54 +01:00
createActionRoute ( router , this . licenseState ) ;
deleteActionRoute ( router , this . licenseState ) ;
getActionRoute ( router , this . licenseState ) ;
2020-04-08 18:54:42 +02:00
getAllActionRoute ( router , this . licenseState ) ;
2020-01-22 18:08:54 +01:00
updateActionRoute ( router , this . licenseState ) ;
listActionTypesRoute ( router , this . licenseState ) ;
2020-06-16 10:33:10 +02:00
executeActionRoute ( router , this . licenseState ) ;
2020-01-22 18:08:54 +01:00
return {
2020-08-04 21:50:17 +02:00
registerType : <
Config extends ActionTypeConfig = ActionTypeConfig ,
Secrets extends ActionTypeSecrets = ActionTypeSecrets ,
2020-10-30 15:45:24 +01:00
Params extends ActionTypeParams = ActionTypeParams ,
ExecutorResultData = void
2020-08-04 21:50:17 +02:00
> (
2020-10-30 15:45:24 +01:00
actionType : ActionType < Config , Secrets , Params , ExecutorResultData >
2020-08-04 21:50:17 +02:00
) = > {
2020-11-12 18:31:44 +01:00
ensureSufficientLicense ( actionType ) ;
2020-03-20 15:49:37 +01:00
actionTypeRegistry . register ( actionType ) ;
} ,
2020-01-22 18:08:54 +01:00
} ;
}
public start ( core : CoreStart , plugins : ActionsPluginsStart ) : PluginStartContract {
2020-01-22 22:26:34 +01:00
const {
logger ,
2020-10-15 20:47:46 +02:00
licenseState ,
2020-01-22 22:26:34 +01:00
actionExecutor ,
actionTypeRegistry ,
taskRunnerFactory ,
2020-11-21 05:27:03 +01:00
kibanaIndexConfig ,
2020-02-12 19:49:16 +01:00
isESOUsingEphemeralEncryptionKey ,
2020-04-08 18:54:42 +02:00
preconfiguredActions ,
2020-07-22 15:45:57 +02:00
instantiateAuthorization ,
2020-09-16 12:47:37 +02:00
getUnsecuredSavedObjectsClient ,
2020-01-22 22:26:34 +01:00
} = this ;
2020-01-22 18:08:54 +01:00
2020-10-15 20:47:46 +02:00
licenseState ? . setNotifyUsage ( plugins . licensing . featureUsage . notifyUsage ) ;
2020-05-22 10:07:09 +02:00
const encryptedSavedObjectsClient = plugins . encryptedSavedObjects . getClient ( {
includedHiddenTypes ,
} ) ;
2020-09-16 12:47:37 +02:00
const getActionsClientWithRequest = async (
request : KibanaRequest ,
2020-09-18 10:54:49 +02:00
authorizationContext? : ActionExecutionSource < unknown >
2020-09-16 12:47:37 +02:00
) = > {
2020-07-22 15:45:57 +02:00
if ( isESOUsingEphemeralEncryptionKey === true ) {
throw new Error (
2020-11-19 19:41:48 +01:00
` Unable to create actions client because the Encrypted Saved Objects plugin uses an ephemeral encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command. `
2020-07-22 15:45:57 +02:00
) ;
}
2020-09-16 12:47:37 +02:00
const unsecuredSavedObjectsClient = getUnsecuredSavedObjectsClient (
core . savedObjects ,
request
) ;
2020-11-21 05:27:03 +01:00
const kibanaIndex = ( await kibanaIndexConfig . pipe ( first ( ) ) . toPromise ( ) ) . kibana . index ;
2020-07-22 15:45:57 +02:00
return new ActionsClient ( {
2020-09-16 12:47:37 +02:00
unsecuredSavedObjectsClient ,
2020-07-22 15:45:57 +02:00
actionTypeRegistry : actionTypeRegistry ! ,
2020-11-21 05:27:03 +01:00
defaultKibanaIndex : kibanaIndex ,
2020-07-22 15:45:57 +02:00
scopedClusterClient : core.elasticsearch.legacy.client.asScoped ( request ) ,
preconfiguredActions ,
request ,
2020-09-16 12:47:37 +02:00
authorization : instantiateAuthorization (
request ,
2020-09-18 10:54:49 +02:00
await getAuthorizationModeBySource ( unsecuredSavedObjectsClient , authorizationContext )
2020-09-16 12:47:37 +02:00
) ,
2020-07-22 15:45:57 +02:00
actionExecutor : actionExecutor ! ,
executionEnqueuer : createExecutionEnqueuerFunction ( {
taskManager : plugins.taskManager ,
actionTypeRegistry : actionTypeRegistry ! ,
isESOUsingEphemeralEncryptionKey : isESOUsingEphemeralEncryptionKey ! ,
preconfiguredActions ,
} ) ,
2020-12-04 20:13:30 +01:00
auditLogger : this.security?.audit.asScoped ( request ) ,
2020-05-22 10:07:09 +02:00
} ) ;
2020-07-22 15:45:57 +02:00
} ;
2020-05-22 10:07:09 +02:00
2020-09-16 12:47:37 +02:00
// Ensure the public API cannot be used to circumvent authorization
2020-09-18 10:54:49 +02:00
// using our legacy exemption mechanism by passing in a legacy SO
// as authorizationContext which would then set a Legacy AuthorizationMode
2020-09-16 12:47:37 +02:00
const secureGetActionsClientWithRequest = ( request : KibanaRequest ) = >
getActionsClientWithRequest ( request ) ;
2020-08-11 16:00:02 +02:00
this . eventLogService ! . registerSavedObjectProvider ( 'action' , ( request ) = > {
2020-09-16 12:47:37 +02:00
const client = secureGetActionsClientWithRequest ( request ) ;
2021-01-13 01:25:23 +01:00
return ( objects? : SavedObjectsBulkGetObject [ ] ) = >
objects
? Promise . all (
objects . map ( async ( objectItem ) = > await ( await client ) . get ( { id : objectItem.id } ) )
)
: Promise . resolve ( [ ] ) ;
2020-08-11 16:00:02 +02:00
} ) ;
2020-05-22 10:07:09 +02:00
const getScopedSavedObjectsClientWithoutAccessToActions = ( request : KibanaRequest ) = >
core . savedObjects . getScopedClient ( request ) ;
2020-05-20 10:55:02 +02:00
2020-01-22 18:08:54 +01:00
actionExecutor ! . initialize ( {
logger ,
eventLogger : this.eventLogger ! ,
2020-11-19 19:41:13 +01:00
spaces : plugins.spaces?.spacesService ,
2020-07-22 15:45:57 +02:00
getActionsClientWithRequest ,
2020-05-22 10:07:09 +02:00
getServices : this.getServicesFactory (
getScopedSavedObjectsClientWithoutAccessToActions ,
core . elasticsearch
) ,
2020-05-20 10:55:02 +02:00
encryptedSavedObjectsClient ,
2020-01-22 18:08:54 +01:00
actionTypeRegistry : actionTypeRegistry ! ,
2020-04-15 00:20:50 +02:00
preconfiguredActions ,
2020-01-22 18:08:54 +01:00
} ) ;
2020-11-19 19:41:13 +01:00
const spaceIdToNamespace = ( spaceId? : string ) = > {
return plugins . spaces && spaceId
? plugins . spaces . spacesService . spaceIdToNamespace ( spaceId )
: undefined ;
} ;
2020-01-22 18:08:54 +01:00
taskRunnerFactory ! . initialize ( {
2020-01-27 21:02:44 +01:00
logger ,
2020-03-20 15:49:37 +01:00
actionTypeRegistry : actionTypeRegistry ! ,
2020-05-20 10:55:02 +02:00
encryptedSavedObjectsClient ,
2020-11-19 19:41:13 +01:00
basePathService : core.http.basePath ,
spaceIdToNamespace ,
2020-09-16 12:47:37 +02:00
getUnsecuredSavedObjectsClient : ( request : KibanaRequest ) = >
this . getUnsecuredSavedObjectsClient ( core . savedObjects , request ) ,
2020-01-22 18:08:54 +01:00
} ) ;
2020-03-12 18:46:24 +01:00
scheduleActionsTelemetry ( this . telemetryLogger , plugins . taskManager ) ;
2020-01-22 18:08:54 +01:00
return {
2020-10-15 20:47:46 +02:00
isActionTypeEnabled : ( id , options = { notifyUsage : false } ) = > {
return this . actionTypeRegistry ! . isActionTypeEnabled ( id , options ) ;
2020-03-20 15:49:37 +01:00
} ,
2020-10-15 20:47:46 +02:00
isActionExecutable : (
actionId : string ,
actionTypeId : string ,
options = { notifyUsage : false }
) = > {
return this . actionTypeRegistry ! . isActionExecutable ( actionId , actionTypeId , options ) ;
2020-04-24 23:38:28 +02:00
} ,
2020-07-22 15:45:57 +02:00
getActionsAuthorizationWithRequest ( request : KibanaRequest ) {
return instantiateAuthorization ( request ) ;
2020-01-22 22:26:34 +01:00
} ,
2020-09-16 12:47:37 +02:00
getActionsClientWithRequest : secureGetActionsClientWithRequest ,
2020-04-08 18:54:42 +02:00
preconfiguredActions ,
Allow action types to perform their own mustache variable escaping in parameter templates (#83919)
resolves https://github.com/elastic/kibana/issues/79371
resolves https://github.com/elastic/kibana/issues/62928
In this PR, we allow action types to determine how to escape the
variables used in their parameters, when rendered as mustache
templates. Prior to this, action parameters were recursively
rendered as mustache templates using the default mustache
templating, by the alerts library. The default mustache
templating used html escaping.
Action types opt-in to the new capability via a new optional
method in the action type, `renderParameterTemplates()`. If not
provided, the previous recursive rendering is done, but now with
no escaping at all.
For #62928, changed the mustache template rendering to be
replaced with the error message, if an error occurred,
so at least you can now see that an error occurred. Useful
to diagnose problems with invalid mustache templates.
2020-12-15 02:41:13 +01:00
renderActionParameterTemplates : ( . . . args ) = >
renderActionParameterTemplates ( actionTypeRegistry , . . . args ) ,
2020-01-22 18:08:54 +01:00
} ;
}
2020-09-16 12:47:37 +02:00
private getUnsecuredSavedObjectsClient = (
savedObjects : CoreStart [ 'savedObjects' ] ,
request : KibanaRequest
) = >
savedObjects . getScopedClient ( request , {
excludedWrappers : [ 'security' ] ,
includedHiddenTypes ,
} ) ;
private instantiateAuthorization = (
request : KibanaRequest ,
2020-09-18 10:54:49 +02:00
authorizationMode? : AuthorizationMode
2020-09-16 12:47:37 +02:00
) = > {
2020-07-22 15:45:57 +02:00
return new ActionsAuthorization ( {
request ,
2020-09-18 10:54:49 +02:00
authorizationMode ,
2020-07-22 15:45:57 +02:00
authorization : this.security?.authz ,
2020-09-16 12:47:37 +02:00
authentication : this.security?.authc ,
2020-07-22 15:45:57 +02:00
auditLogger : new ActionsAuthorizationAuditLogger (
this . security ? . audit . getLogger ( ACTIONS_FEATURE . id )
) ,
} ) ;
} ;
2020-01-22 18:08:54 +01:00
private getServicesFactory (
2020-05-22 10:07:09 +02:00
getScopedClient : ( request : KibanaRequest ) = > SavedObjectsClientContract ,
2020-04-15 17:07:57 +02:00
elasticsearch : ElasticsearchServiceStart
2020-01-22 18:08:54 +01:00
) : ( request : KibanaRequest ) = > Services {
2020-05-22 09:08:58 +02:00
return ( request ) = > ( {
2020-04-15 17:07:57 +02:00
callCluster : elasticsearch.legacy.client.asScoped ( request ) . callAsCurrentUser ,
2020-05-22 10:07:09 +02:00
savedObjectsClient : getScopedClient ( request ) ,
2020-10-20 15:54:48 +02:00
scopedClusterClient : elasticsearch.client.asScoped ( request ) . asCurrentUser ,
2020-07-14 16:48:24 +02:00
getLegacyScopedClusterClient ( clusterClient : ILegacyClusterClient ) {
return clusterClient . asScoped ( request ) ;
2020-04-27 19:46:04 +02:00
} ,
2020-01-22 18:08:54 +01:00
} ) ;
}
private createRouteHandlerContext = (
2020-05-22 10:07:09 +02:00
core : CoreSetup < ActionsPluginsStart > ,
2020-01-22 18:08:54 +01:00
defaultKibanaIndex : string
2021-01-21 15:20:22 +01:00
) : IContextProvider < ActionsRequestHandlerContext , ' actions ' > = > {
2020-06-16 10:33:10 +02:00
const {
actionTypeRegistry ,
isESOUsingEphemeralEncryptionKey ,
preconfiguredActions ,
actionExecutor ,
2020-07-22 15:45:57 +02:00
instantiateAuthorization ,
2020-12-04 20:13:30 +01:00
security ,
2020-06-16 10:33:10 +02:00
} = this ;
2020-04-15 17:07:57 +02:00
2020-01-22 18:08:54 +01:00
return async function actionsRouteHandlerContext ( context , request ) {
2020-06-16 10:33:10 +02:00
const [ { savedObjects } , { taskManager } ] = await core . getStartServices ( ) ;
2020-01-22 18:08:54 +01:00
return {
getActionsClient : ( ) = > {
2020-02-12 19:49:16 +01:00
if ( isESOUsingEphemeralEncryptionKey === true ) {
throw new Error (
2020-11-19 19:41:48 +01:00
` Unable to create actions client because the Encrypted Saved Objects plugin uses an ephemeral encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command. `
2020-02-12 19:49:16 +01:00
) ;
}
2020-01-22 18:08:54 +01:00
return new ActionsClient ( {
2020-07-22 15:45:57 +02:00
unsecuredSavedObjectsClient : savedObjects.getScopedClient ( request , {
excludedWrappers : [ 'security' ] ,
includedHiddenTypes ,
} ) ,
2020-01-22 18:08:54 +01:00
actionTypeRegistry : actionTypeRegistry ! ,
defaultKibanaIndex ,
2020-05-27 19:00:16 +02:00
scopedClusterClient : context.core.elasticsearch.legacy.client ,
2020-04-08 18:54:42 +02:00
preconfiguredActions ,
2020-06-16 10:33:10 +02:00
request ,
2020-07-22 15:45:57 +02:00
authorization : instantiateAuthorization ( request ) ,
2020-06-16 10:33:10 +02:00
actionExecutor : actionExecutor ! ,
executionEnqueuer : createExecutionEnqueuerFunction ( {
taskManager ,
actionTypeRegistry : actionTypeRegistry ! ,
isESOUsingEphemeralEncryptionKey : isESOUsingEphemeralEncryptionKey ! ,
preconfiguredActions ,
} ) ,
2020-12-04 20:13:30 +01:00
auditLogger : security?.audit.asScoped ( request ) ,
2020-01-22 18:08:54 +01:00
} ) ;
} ,
listTypes : actionTypeRegistry ! . list . bind ( actionTypeRegistry ! ) ,
} ;
} ;
} ;
public stop() {
if ( this . licenseState ) {
this . licenseState . clean ( ) ;
}
}
}
Allow action types to perform their own mustache variable escaping in parameter templates (#83919)
resolves https://github.com/elastic/kibana/issues/79371
resolves https://github.com/elastic/kibana/issues/62928
In this PR, we allow action types to determine how to escape the
variables used in their parameters, when rendered as mustache
templates. Prior to this, action parameters were recursively
rendered as mustache templates using the default mustache
templating, by the alerts library. The default mustache
templating used html escaping.
Action types opt-in to the new capability via a new optional
method in the action type, `renderParameterTemplates()`. If not
provided, the previous recursive rendering is done, but now with
no escaping at all.
For #62928, changed the mustache template rendering to be
replaced with the error message, if an error occurred,
so at least you can now see that an error occurred. Useful
to diagnose problems with invalid mustache templates.
2020-12-15 02:41:13 +01:00
export function renderActionParameterTemplates < Params extends ActionTypeParams = ActionTypeParams > (
actionTypeRegistry : ActionTypeRegistry | undefined ,
actionTypeId : string ,
params : Params ,
variables : Record < string , unknown >
) : Params {
const actionType = actionTypeRegistry ? . get ( actionTypeId ) ;
if ( actionType ? . renderParameterTemplates ) {
return actionType . renderParameterTemplates ( params , variables ) as Params ;
} else {
return renderMustacheObject ( params , variables ) ;
}
}