mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 01:13:23 -04:00
[Alerting] Split alerting feature privilege between rules and alerts and handle subfeature privilege specification (#100127)
* WIP - creating alerting authorization client factory and exposing authorization client on plugin start contract * Updating alerting feature privilege builder to handle different alerting types * Passing in alerting authorization type to AlertingActions class string builder * Passing in authorization type in each function call * Passing in exempt consumer ids. Adding authorization type to audit logger * Changing alertType to ruleType * Changing alertType to ruleType * Updating unit tests * Updating unit tests * Passing field names into authorization query builder. Adding kql/es dsl option * Converting to es query if requested * Fixing functional tests * Removing ability to specify feature privilege name in constructor * Fixing some types and tests * Consolidating alerting authorization kuery filter options * Cleanup and tests * Cleanup and tests * Initial commit with changes needed for subfeature privilege * Throwing error when AlertingAuthorizationClientFactory is not defined * Renaming authorizationType to entity * Renaming AlertsAuthorization to AlertingAuthorization * Fixing unit tests * Changing schema of alerting feature privilege * Changing schema of alerting feature privilege * Updating feature privilege iterator * Updating feature privilege builder * Fixing types check * Updating privilege string terminology * Updating privilege string terminology * Wip * Fixing unit tests * Unit tests * Updating README and removing stack subfeature privilege changes * Fixing README Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
f0e11bcd1b
commit
71379b755a
22 changed files with 1652 additions and 358 deletions
|
@ -44,7 +44,12 @@ export class AlertingExamplePlugin implements Plugin<void, void, AlertingExample
|
|||
privileges: {
|
||||
all: {
|
||||
alerting: {
|
||||
all: [alwaysFiringAlert.id, peopleInSpaceAlert.id, INDEX_THRESHOLD_ID],
|
||||
rule: {
|
||||
all: [alwaysFiringAlert.id, peopleInSpaceAlert.id, INDEX_THRESHOLD_ID],
|
||||
},
|
||||
alert: {
|
||||
all: [alwaysFiringAlert.id, peopleInSpaceAlert.id, INDEX_THRESHOLD_ID],
|
||||
},
|
||||
},
|
||||
savedObject: {
|
||||
all: [],
|
||||
|
@ -57,7 +62,12 @@ export class AlertingExamplePlugin implements Plugin<void, void, AlertingExample
|
|||
},
|
||||
read: {
|
||||
alerting: {
|
||||
read: [alwaysFiringAlert.id, peopleInSpaceAlert.id, INDEX_THRESHOLD_ID],
|
||||
rule: {
|
||||
read: [alwaysFiringAlert.id, peopleInSpaceAlert.id, INDEX_THRESHOLD_ID],
|
||||
},
|
||||
alert: {
|
||||
read: [alwaysFiringAlert.id, peopleInSpaceAlert.id, INDEX_THRESHOLD_ID],
|
||||
},
|
||||
},
|
||||
savedObject: {
|
||||
all: [],
|
||||
|
|
|
@ -326,9 +326,10 @@ server.newPlatform.setup.plugins.alerting.registerType(myRuleType);
|
|||
## Role Based Access-Control
|
||||
|
||||
Once you have registered your AlertType, you need to grant your users privileges to use it.
|
||||
When registering a feature in Kibana, you can specify multiple types of privileges which are granted to users when they're assigned certain roles.
|
||||
Assuming your feature introduces its own AlertTypes, you'll want to control which roles have all/read privileges for these AlertTypes when they're inside the feature.
|
||||
In addition, when users are inside your feature, you might want to grant them access to AlertTypes from other features, such as built-in stack rules or rule types provided by other features.
|
||||
When registering a feature in Kibana you can specify multiple types of privileges which are granted to users when they're assigned certain roles.
|
||||
|
||||
Assuming your feature introduces its own AlertTypes, you'll want to control which roles have all/read privileges for the rules and alerts for these AlertTypes when they're inside the feature.
|
||||
In addition, when users are inside your feature, you might want to grant them access to rules and alerts for AlertTypes from other features, such as built-in stack rules or rule types provided by other features.
|
||||
|
||||
You can control all of these abilities by assigning privileges to the Alerting Framework from within your own feature, for example:
|
||||
|
||||
|
@ -337,30 +338,61 @@ features.registerKibanaFeature({
|
|||
id: 'my-application-id',
|
||||
name: 'My Application',
|
||||
app: [],
|
||||
alerting: [
|
||||
'my-application-id.my-rule-type',
|
||||
'my-application-id.my-restricted-rule-type',
|
||||
'.index-threshold',
|
||||
'xpack.uptime.alerts.actionGroups.tls'
|
||||
],
|
||||
privileges: {
|
||||
all: {
|
||||
alerting: {
|
||||
all: [
|
||||
// grant `all` over our own types
|
||||
'my-application-id.my-rule-type',
|
||||
'my-application-id.my-restricted-rule-type',
|
||||
// grant `all` over the built-in IndexThreshold
|
||||
'.index-threshold',
|
||||
// grant `all` over Uptime's TLS rule type
|
||||
'xpack.uptime.alerts.actionGroups.tls'
|
||||
],
|
||||
rule: {
|
||||
all: [
|
||||
// grant `all` over our own types
|
||||
'my-application-id.my-rule-type',
|
||||
'my-application-id.my-restricted-rule-type',
|
||||
// grant `all` over the built-in IndexThreshold
|
||||
'.index-threshold',
|
||||
// grant `all` over Uptime's TLS rule type
|
||||
'xpack.uptime.alerts.actionGroups.tls'
|
||||
],
|
||||
},
|
||||
alert: {
|
||||
all: [
|
||||
// grant `all` over our own types
|
||||
'my-application-id.my-rule-type',
|
||||
'my-application-id.my-restricted-rule-type',
|
||||
// grant `all` over the built-in IndexThreshold
|
||||
'.index-threshold',
|
||||
// grant `all` over Uptime's TLS rule type
|
||||
'xpack.uptime.alerts.actionGroups.tls'
|
||||
],
|
||||
}
|
||||
},
|
||||
},
|
||||
read: {
|
||||
alerting: {
|
||||
read: [
|
||||
// grant `read` over our own type
|
||||
'my-application-id.my-rule-type',
|
||||
// grant `read` over the built-in IndexThreshold
|
||||
'.index-threshold',
|
||||
// grant `read` over Uptime's TLS rule type
|
||||
'xpack.uptime.alerts.actionGroups.tls'
|
||||
],
|
||||
rule: {
|
||||
read: [
|
||||
// grant `read` over our own type
|
||||
'my-application-id.my-alert-type',
|
||||
// grant `read` over the built-in IndexThreshold
|
||||
'.index-threshold',
|
||||
// grant `read` over Uptime's TLS AlertType
|
||||
'xpack.uptime.alerts.actionGroups.tls'
|
||||
],
|
||||
},
|
||||
alert: {
|
||||
read: [
|
||||
// grant `read` over our own type
|
||||
'my-application-id.my-alert-type',
|
||||
// grant `read` over the built-in IndexThreshold
|
||||
'.index-threshold',
|
||||
// grant `read` over Uptime's TLS AlertType
|
||||
'xpack.uptime.alerts.actionGroups.tls'
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -369,17 +401,21 @@ features.registerKibanaFeature({
|
|||
|
||||
In this example we can see the following:
|
||||
|
||||
- Our feature grants any user who's assigned the `all` role in our feature the `all` role in the Alerting framework over every rule of the `my-application-id.my-rule-type` type which is created _inside_ the feature. What that means is that this privilege will allow the user to execute any of the `all` operations (listed below) on these rules as long as their `consumer` is `my-application-id`. Below that you'll notice we've done the same with the `read` role, which grants the Alerting Framework's `read` role privileges over these very same rules.
|
||||
- In addition, our feature grants the same privileges over any rule of type `my-application-id.my-restricted-rule-type`, which is another hypothetical rule type registered by this feature. It's worth noting that this type has been omitted from the `read` role. What this means is that only users with the `all` role will be able to interact with rules of this type.
|
||||
- Next, lets look at the `.index-threshold` and `xpack.uptime.alerts.actionGroups.tls` types. These have been specified in both `read` and `all`, which means that all the users in the feature will gain privileges over rules of these types (as long as their `consumer` is `my-application-id`). The difference between these two and the previous two is that they are _produced_ by other features! `.index-threshold` is a built-in stack rule type, provided by the _Stack Rules_ feature, and `xpack.uptime.alerts.actionGroups.tls` is a rule type provided by the _Uptime_ feature. Specifying these types here tells the Alerting Framework that as far as the `my-application-id` feature is concerned, the user is privileged to use them (with `all` and `read` applied), but that isn't enough. Using another feature's rule type is only possible if both the producer of the rule type and the consumer of the rule type explicitly grant privileges to do so. In this case, the _Stack Rules_ & _Uptime_ features would have to explicitly add these privileges to a role and this role would have to be granted to this user.
|
||||
- Our feature grants any user who's assigned the `all` role in our feature the `all` role in the Alerting Framework over every rule and alert of the rule type `my-application-id.my-rule-type` type which is created _inside_ the feature. What that means is that this privilege will allow the user to execute any of the `all` operations (listed below) on these rules and alerts as long as their `consumer` is `my-application-id`. Below that you'll notice we've done the same with the `read` role, which is grants the Alerting Framework's `read` role privileges over these very same rules and alerts.
|
||||
- In addition, our feature grants the same privileges over any rule or alert of rule type `my-application-id.my-restricted-rule-type`, which is another hypothetical rule type registered by this feature. It's worth noting that this type has been omitted from the `read` role. What this means is that only users with the `all` role will be able to interact with rules and alerts of this rule type.
|
||||
- Next, let's look at the `.index-threshold` and `xpack.uptime.alerts.actionGroups.tls` types. These have been specified in both `read` and `all`, which means that all the users in the feature will gain privileges over rules and alerts of these rule types (as long as their `consumer` is `my-application-id`). The difference between these two and the previous two is that they are _produced_ by other features! `.index-threshold` is a built-in stack rule type, provided by the _Stack Rules_ feature, and `xpack.uptime.alerts.actionGroups.tls` is a rule type provided by the _Uptime_ feature. Specifying these types here tells the Alerting Framework that as far as the `my-application-id` feature is concerned, the user is privileged to use them (with `all` and `read` applied), but that isn't enough. Using another feature's rule type is only possible if both the producer of the rule type and the consumer of the rule type explicitly grant privileges to do so. In this case, the _Stack Rules_ & _Uptime_ features would have to explicitly add these privileges to a role and this role would have to be granted to this user.
|
||||
|
||||
It's important to note that any role can be granted a mix of `all` and `read` privileges accross multiple types, for example:
|
||||
It's important to note that any role can be granted a mix of `all` and `read` privileges across multiple types, for example:
|
||||
|
||||
```typescript
|
||||
features.registerKibanaFeature({
|
||||
id: 'my-application-id',
|
||||
name: 'My Application',
|
||||
app: [],
|
||||
alerting: [
|
||||
'my-application-id.my-rule-type',
|
||||
'my-application-id.my-restricted-rule-type'
|
||||
],
|
||||
privileges: {
|
||||
all: {
|
||||
app: ['my-application-id', 'kibana'],
|
||||
|
@ -393,12 +429,22 @@ features.registerKibanaFeature({
|
|||
read: {
|
||||
app: ['lens', 'kibana'],
|
||||
alerting: {
|
||||
all: [
|
||||
'my-application-id.my-rule-type'
|
||||
],
|
||||
read: [
|
||||
'my-application-id.my-restricted-rule-type'
|
||||
],
|
||||
rule: {
|
||||
all: [
|
||||
'my-application-id.my-rule-type'
|
||||
],
|
||||
read: [
|
||||
'my-application-id.my-restricted-rule-type'
|
||||
],
|
||||
},
|
||||
alert: {
|
||||
all: [
|
||||
'my-application-id.my-rule-type'
|
||||
],
|
||||
read: [
|
||||
'my-application-id.my-restricted-rule-type'
|
||||
],
|
||||
},
|
||||
},
|
||||
savedObject: {
|
||||
all: [],
|
||||
|
@ -414,6 +460,111 @@ features.registerKibanaFeature({
|
|||
In the above example, note that instead of denying users with the `read` role any access to the `my-application-id.my-restricted-rule-type` type, we've decided that these users _should_ be granted `read` privileges over the _restricted_ rule type.
|
||||
As part of that same change, we also decided that not only should they be allowed to `read` the _restricted_ rule type, but actually, despite having `read` privileges to the feature as a whole, we do actually want to allow them to create our basic 'my-application-id.my-rule-type' rule type, as we consider it an extension of _reading_ data in our feature, rather than _writing_ it.
|
||||
|
||||
### Subfeature privileges
|
||||
|
||||
In the above examples, we have been giving the same level of access to both rules and alerts for a particular rule type. There may be cases when you want your feature privilege to allow for escalated or de-escalated privileges for either rules or alerts within a feature. We can use subfeature privileges to achieve this granularity.
|
||||
|
||||
For more information and other examples of subfeature privilege, refer to the [user documentation](https://www.elastic.co/guide/en/kibana/master/development-security.html#example-3-discover).
|
||||
|
||||
```typescript
|
||||
features.registerKibanaFeature({
|
||||
id: 'my-application-id',
|
||||
name: 'My Application',
|
||||
app: [],
|
||||
alerting: [
|
||||
'my-application-id.my-rule-type',
|
||||
'my-application-id.my-other-rule-type'
|
||||
],
|
||||
privileges: {
|
||||
all: {
|
||||
app: ['my-application-id', 'kibana'],
|
||||
savedObject: {
|
||||
all: [],
|
||||
read: [],
|
||||
},
|
||||
alerting: {
|
||||
rule: {
|
||||
all: [
|
||||
'my-application-id.my-rule-type',
|
||||
'my-application-id.my-other-rule-type'
|
||||
]
|
||||
},
|
||||
alert: {
|
||||
read: [
|
||||
'my-application-id.my-rule-type',
|
||||
'my-application-id.my-other-rule-type'
|
||||
]
|
||||
}
|
||||
},
|
||||
ui: [],
|
||||
api: [],
|
||||
},
|
||||
read: {
|
||||
app: ['lens', 'kibana'],
|
||||
alerting: {
|
||||
rule: {
|
||||
read: [
|
||||
'my-application-id.my-rule-type',
|
||||
'my-application-id.my-other-rule-type'
|
||||
]
|
||||
},
|
||||
alert: {
|
||||
read: [
|
||||
'my-application-id.my-rule-type',
|
||||
'my-application-id.my-other-rule-type'
|
||||
]
|
||||
}
|
||||
},
|
||||
savedObject: {
|
||||
all: [],
|
||||
read: [],
|
||||
},
|
||||
ui: [],
|
||||
api: [],
|
||||
},
|
||||
},
|
||||
subFeatures: [
|
||||
{
|
||||
name: 'Manage Alerts',
|
||||
privilegeGroups: [
|
||||
{
|
||||
groupType: 'independent',
|
||||
privileges: [
|
||||
{
|
||||
id: 'alert_manage',
|
||||
name: 'Manage Alerts',
|
||||
includeIn: 'all',
|
||||
alerting: {
|
||||
alert: {
|
||||
all: [
|
||||
'my-application-id.my-rule-type',
|
||||
'my-application-id.my-other-rule-type'
|
||||
],
|
||||
},
|
||||
},
|
||||
savedObject: {
|
||||
all: [],
|
||||
read: [],
|
||||
},
|
||||
ui: [],
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
});
|
||||
```
|
||||
|
||||
In the above example, note that the base feature privilege grants users with the `all` role `all` access the rules of the specified rule types but only `read` access to the alerts of the same rule type. In order to get `all` access to the alerts of these rule types, the role must grant the `alert_manage` subfeature privilege. Because the `alert_manage` subfeature privilege has `includeIn` set to `all`, it is _automatically_ included in the `all` feature privilege but can be excluded when the role is defined.
|
||||
|
||||
This subfeature privilege definition allows for the following granularity:
|
||||
|
||||
- `all` privileges to rules for a rule type and `all` privileges to alerts for a rule type
|
||||
- `all` privileges to rules for a rule type and subprivilege de-escalation to grant only `read` privileges to alerts for a rule type
|
||||
- `read` privileges to rules for a rule type and `read` privileges to alerts for a rule type
|
||||
- `read` privileges to rules for a rule type and subprivilege escalation to grant `all` privileges to alerts for a rule type.
|
||||
|
||||
### `read` privileges vs. `all` privileges
|
||||
When a user is granted the `read` role in the Alerting Framework, they will be able to execute the following api calls:
|
||||
|
||||
|
|
|
@ -71,7 +71,12 @@ function mockFeature(appName: string, typeName?: string) {
|
|||
...(typeName
|
||||
? {
|
||||
alerting: {
|
||||
all: [typeName],
|
||||
rule: {
|
||||
all: [typeName],
|
||||
},
|
||||
alert: {
|
||||
all: [typeName],
|
||||
},
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
|
@ -85,7 +90,12 @@ function mockFeature(appName: string, typeName?: string) {
|
|||
...(typeName
|
||||
? {
|
||||
alerting: {
|
||||
read: [typeName],
|
||||
rule: {
|
||||
read: [typeName],
|
||||
},
|
||||
alert: {
|
||||
read: [typeName],
|
||||
},
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
|
@ -138,7 +148,9 @@ function mockFeatureWithSubFeature(appName: string, typeName: string) {
|
|||
name: 'sub feature alert',
|
||||
includeIn: 'all',
|
||||
alerting: {
|
||||
all: [typeName],
|
||||
rule: {
|
||||
all: [typeName],
|
||||
},
|
||||
},
|
||||
savedObject: {
|
||||
all: [],
|
||||
|
@ -151,7 +163,9 @@ function mockFeatureWithSubFeature(appName: string, typeName: string) {
|
|||
name: 'sub feature alert',
|
||||
includeIn: 'read',
|
||||
alerting: {
|
||||
read: [typeName],
|
||||
rule: {
|
||||
read: [typeName],
|
||||
},
|
||||
},
|
||||
savedObject: {
|
||||
all: [],
|
||||
|
@ -269,7 +283,7 @@ describe('AlertingAuthorization', () => {
|
|||
expect(alertTypeRegistry.get).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
test('ensures the user has privileges to execute the specified rule type, operation and alerting type without consumer when producer and consumer are the same', async () => {
|
||||
test('ensures the user has privileges to execute rules for the specified rule type and operation without consumer when producer and consumer are the same', async () => {
|
||||
const { authorization } = mockSecurity();
|
||||
const checkPrivileges: jest.MockedFunction<
|
||||
ReturnType<typeof authorization.checkPrivilegesDynamicallyWithRequest>
|
||||
|
@ -325,7 +339,63 @@ describe('AlertingAuthorization', () => {
|
|||
`);
|
||||
});
|
||||
|
||||
test('ensures the user has privileges to execute the specified rule type, operation and alerting type without consumer when consumer is exempt', async () => {
|
||||
test('ensures the user has privileges to execute alerts for the specified rule type and operation without consumer when producer and consumer are the same', async () => {
|
||||
const { authorization } = mockSecurity();
|
||||
const checkPrivileges: jest.MockedFunction<
|
||||
ReturnType<typeof authorization.checkPrivilegesDynamicallyWithRequest>
|
||||
> = jest.fn();
|
||||
authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges);
|
||||
const alertAuthorization = new AlertingAuthorization({
|
||||
request,
|
||||
authorization,
|
||||
alertTypeRegistry,
|
||||
features,
|
||||
auditLogger,
|
||||
getSpace,
|
||||
exemptConsumerIds,
|
||||
});
|
||||
|
||||
checkPrivileges.mockResolvedValueOnce({
|
||||
username: 'some-user',
|
||||
hasAllRequested: true,
|
||||
privileges: { kibana: [] },
|
||||
});
|
||||
|
||||
await alertAuthorization.ensureAuthorized({
|
||||
ruleTypeId: 'myType',
|
||||
consumer: 'myApp',
|
||||
operation: WriteOperations.Update,
|
||||
entity: AlertingAuthorizationEntity.Alert,
|
||||
});
|
||||
|
||||
expect(alertTypeRegistry.get).toHaveBeenCalledWith('myType');
|
||||
|
||||
expect(authorization.actions.alerting.get).toHaveBeenCalledTimes(2);
|
||||
expect(authorization.actions.alerting.get).toHaveBeenCalledWith(
|
||||
'myType',
|
||||
'myApp',
|
||||
'alert',
|
||||
'update'
|
||||
);
|
||||
expect(checkPrivileges).toHaveBeenCalledWith({
|
||||
kibana: [mockAuthorizationAction('myType', 'myApp', 'alert', 'update')],
|
||||
});
|
||||
|
||||
expect(auditLogger.logAuthorizationSuccess).toHaveBeenCalledTimes(1);
|
||||
expect(auditLogger.logAuthorizationFailure).not.toHaveBeenCalled();
|
||||
expect(auditLogger.logAuthorizationSuccess.mock.calls[0]).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"some-user",
|
||||
"myType",
|
||||
0,
|
||||
"myApp",
|
||||
"update",
|
||||
"alert",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
test('ensures the user has privileges to execute rules for the specified rule type and operation without consumer when consumer is exempt', async () => {
|
||||
const { authorization } = mockSecurity();
|
||||
const checkPrivileges: jest.MockedFunction<
|
||||
ReturnType<typeof authorization.checkPrivilegesDynamicallyWithRequest>
|
||||
|
@ -387,7 +457,69 @@ describe('AlertingAuthorization', () => {
|
|||
`);
|
||||
});
|
||||
|
||||
test('ensures the user has privileges to execute the specified rule type, operation, alerting type and producer when producer is different from consumer', async () => {
|
||||
test('ensures the user has privileges to execute alerts for the specified rule type and operation without consumer when consumer is exempt', async () => {
|
||||
const { authorization } = mockSecurity();
|
||||
const checkPrivileges: jest.MockedFunction<
|
||||
ReturnType<typeof authorization.checkPrivilegesDynamicallyWithRequest>
|
||||
> = jest.fn();
|
||||
authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges);
|
||||
const alertAuthorization = new AlertingAuthorization({
|
||||
request,
|
||||
authorization,
|
||||
alertTypeRegistry,
|
||||
features,
|
||||
auditLogger,
|
||||
getSpace,
|
||||
exemptConsumerIds: ['exemptConsumer'],
|
||||
});
|
||||
|
||||
checkPrivileges.mockResolvedValueOnce({
|
||||
username: 'some-user',
|
||||
hasAllRequested: true,
|
||||
privileges: { kibana: [] },
|
||||
});
|
||||
|
||||
await alertAuthorization.ensureAuthorized({
|
||||
ruleTypeId: 'myType',
|
||||
consumer: 'exemptConsumer',
|
||||
operation: WriteOperations.Update,
|
||||
entity: AlertingAuthorizationEntity.Alert,
|
||||
});
|
||||
|
||||
expect(alertTypeRegistry.get).toHaveBeenCalledWith('myType');
|
||||
|
||||
expect(authorization.actions.alerting.get).toHaveBeenCalledTimes(2);
|
||||
expect(authorization.actions.alerting.get).toHaveBeenCalledWith(
|
||||
'myType',
|
||||
'exemptConsumer',
|
||||
'alert',
|
||||
'update'
|
||||
);
|
||||
expect(authorization.actions.alerting.get).toHaveBeenCalledWith(
|
||||
'myType',
|
||||
'myApp',
|
||||
'alert',
|
||||
'update'
|
||||
);
|
||||
expect(checkPrivileges).toHaveBeenCalledWith({
|
||||
kibana: [mockAuthorizationAction('myType', 'myApp', 'alert', 'update')],
|
||||
});
|
||||
|
||||
expect(auditLogger.logAuthorizationSuccess).toHaveBeenCalledTimes(1);
|
||||
expect(auditLogger.logAuthorizationFailure).not.toHaveBeenCalled();
|
||||
expect(auditLogger.logAuthorizationSuccess.mock.calls[0]).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"some-user",
|
||||
"myType",
|
||||
0,
|
||||
"exemptConsumer",
|
||||
"update",
|
||||
"alert",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
test('ensures the user has privileges to execute rules for the specified rule type, operation and producer when producer is different from consumer', async () => {
|
||||
const { authorization } = mockSecurity();
|
||||
const checkPrivileges: jest.MockedFunction<
|
||||
ReturnType<typeof authorization.checkPrivilegesDynamicallyWithRequest>
|
||||
|
@ -452,7 +584,72 @@ describe('AlertingAuthorization', () => {
|
|||
`);
|
||||
});
|
||||
|
||||
test('throws if user lacks the required privileges for the consumer', async () => {
|
||||
test('ensures the user has privileges to execute alerts for the specified rule type, operation and producer when producer is different from consumer', async () => {
|
||||
const { authorization } = mockSecurity();
|
||||
const checkPrivileges: jest.MockedFunction<
|
||||
ReturnType<typeof authorization.checkPrivilegesDynamicallyWithRequest>
|
||||
> = jest.fn();
|
||||
authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges);
|
||||
checkPrivileges.mockResolvedValueOnce({
|
||||
username: 'some-user',
|
||||
hasAllRequested: true,
|
||||
privileges: { kibana: [] },
|
||||
});
|
||||
|
||||
const alertAuthorization = new AlertingAuthorization({
|
||||
request,
|
||||
authorization,
|
||||
alertTypeRegistry,
|
||||
features,
|
||||
auditLogger,
|
||||
getSpace,
|
||||
exemptConsumerIds,
|
||||
});
|
||||
|
||||
await alertAuthorization.ensureAuthorized({
|
||||
ruleTypeId: 'myType',
|
||||
consumer: 'myOtherApp',
|
||||
operation: WriteOperations.Update,
|
||||
entity: AlertingAuthorizationEntity.Alert,
|
||||
});
|
||||
|
||||
expect(alertTypeRegistry.get).toHaveBeenCalledWith('myType');
|
||||
|
||||
expect(authorization.actions.alerting.get).toHaveBeenCalledTimes(2);
|
||||
expect(authorization.actions.alerting.get).toHaveBeenCalledWith(
|
||||
'myType',
|
||||
'myApp',
|
||||
'alert',
|
||||
'update'
|
||||
);
|
||||
expect(authorization.actions.alerting.get).toHaveBeenCalledWith(
|
||||
'myType',
|
||||
'myOtherApp',
|
||||
'alert',
|
||||
'update'
|
||||
);
|
||||
expect(checkPrivileges).toHaveBeenCalledWith({
|
||||
kibana: [
|
||||
mockAuthorizationAction('myType', 'myOtherApp', 'alert', 'update'),
|
||||
mockAuthorizationAction('myType', 'myApp', 'alert', 'update'),
|
||||
],
|
||||
});
|
||||
|
||||
expect(auditLogger.logAuthorizationSuccess).toHaveBeenCalledTimes(1);
|
||||
expect(auditLogger.logAuthorizationFailure).not.toHaveBeenCalled();
|
||||
expect(auditLogger.logAuthorizationSuccess.mock.calls[0]).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"some-user",
|
||||
"myType",
|
||||
0,
|
||||
"myOtherApp",
|
||||
"update",
|
||||
"alert",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
test('throws if user lacks the required rule privileges for the consumer', async () => {
|
||||
const { authorization } = mockSecurity();
|
||||
const checkPrivileges: jest.MockedFunction<
|
||||
ReturnType<typeof authorization.checkPrivilegesDynamicallyWithRequest>
|
||||
|
@ -510,7 +707,7 @@ describe('AlertingAuthorization', () => {
|
|||
`);
|
||||
});
|
||||
|
||||
test('throws if user lacks the required privieleges for the producer', async () => {
|
||||
test('throws if user lacks the required alert privileges for the consumer', async () => {
|
||||
const { authorization } = mockSecurity();
|
||||
const checkPrivileges: jest.MockedFunction<
|
||||
ReturnType<typeof authorization.checkPrivilegesDynamicallyWithRequest>
|
||||
|
@ -532,11 +729,73 @@ describe('AlertingAuthorization', () => {
|
|||
privileges: {
|
||||
kibana: [
|
||||
{
|
||||
privilege: mockAuthorizationAction('myType', 'myOtherApp', 'alert', 'create'),
|
||||
privilege: mockAuthorizationAction('myType', 'myOtherApp', 'alert', 'update'),
|
||||
authorized: false,
|
||||
},
|
||||
{
|
||||
privilege: mockAuthorizationAction('myType', 'myApp', 'alert', 'update'),
|
||||
authorized: true,
|
||||
},
|
||||
{
|
||||
privilege: mockAuthorizationAction('myType', 'myApp', 'alert', 'create'),
|
||||
privilege: mockAuthorizationAction('myType', 'myAppRulesOnly', 'alert', 'update'),
|
||||
authorized: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
await expect(
|
||||
alertAuthorization.ensureAuthorized({
|
||||
ruleTypeId: 'myType',
|
||||
consumer: 'myAppRulesOnly',
|
||||
operation: WriteOperations.Update,
|
||||
entity: AlertingAuthorizationEntity.Alert,
|
||||
})
|
||||
).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||
`"Unauthorized to update a \\"myType\\" alert for \\"myAppRulesOnly\\""`
|
||||
);
|
||||
|
||||
expect(auditLogger.logAuthorizationSuccess).not.toHaveBeenCalled();
|
||||
expect(auditLogger.logAuthorizationFailure).toHaveBeenCalledTimes(1);
|
||||
expect(auditLogger.logAuthorizationFailure.mock.calls[0]).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"some-user",
|
||||
"myType",
|
||||
0,
|
||||
"myAppRulesOnly",
|
||||
"update",
|
||||
"alert",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
test('throws if user lacks the required privileges for the producer', async () => {
|
||||
const { authorization } = mockSecurity();
|
||||
const checkPrivileges: jest.MockedFunction<
|
||||
ReturnType<typeof authorization.checkPrivilegesDynamicallyWithRequest>
|
||||
> = jest.fn();
|
||||
authorization.checkPrivilegesDynamicallyWithRequest.mockReturnValue(checkPrivileges);
|
||||
const alertAuthorization = new AlertingAuthorization({
|
||||
request,
|
||||
authorization,
|
||||
alertTypeRegistry,
|
||||
features,
|
||||
auditLogger,
|
||||
getSpace,
|
||||
exemptConsumerIds,
|
||||
});
|
||||
|
||||
checkPrivileges.mockResolvedValueOnce({
|
||||
username: 'some-user',
|
||||
hasAllRequested: false,
|
||||
privileges: {
|
||||
kibana: [
|
||||
{
|
||||
privilege: mockAuthorizationAction('myType', 'myOtherApp', 'alert', 'update'),
|
||||
authorized: true,
|
||||
},
|
||||
{
|
||||
privilege: mockAuthorizationAction('myType', 'myApp', 'alert', 'update'),
|
||||
authorized: false,
|
||||
},
|
||||
],
|
||||
|
@ -547,11 +806,11 @@ describe('AlertingAuthorization', () => {
|
|||
alertAuthorization.ensureAuthorized({
|
||||
ruleTypeId: 'myType',
|
||||
consumer: 'myOtherApp',
|
||||
operation: WriteOperations.Create,
|
||||
operation: WriteOperations.Update,
|
||||
entity: AlertingAuthorizationEntity.Alert,
|
||||
})
|
||||
).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||
`"Unauthorized to create a \\"myType\\" alert by \\"myApp\\""`
|
||||
`"Unauthorized to update a \\"myType\\" alert by \\"myApp\\""`
|
||||
);
|
||||
|
||||
expect(auditLogger.logAuthorizationSuccess).not.toHaveBeenCalled();
|
||||
|
@ -562,13 +821,13 @@ describe('AlertingAuthorization', () => {
|
|||
"myType",
|
||||
1,
|
||||
"myApp",
|
||||
"create",
|
||||
"update",
|
||||
"alert",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
test('throws if user lacks the required privieleges for both consumer and producer', async () => {
|
||||
test('throws if user lacks the required privileges for both consumer and producer', async () => {
|
||||
const { authorization } = mockSecurity();
|
||||
const checkPrivileges: jest.MockedFunction<
|
||||
ReturnType<typeof authorization.checkPrivilegesDynamicallyWithRequest>
|
||||
|
@ -662,7 +921,6 @@ describe('AlertingAuthorization', () => {
|
|||
enabledInLicense: true,
|
||||
};
|
||||
const setOfAlertTypes = new Set([myAppAlertType, myOtherAppAlertType, mySecondAppAlertType]);
|
||||
|
||||
test('omits filter when there is no authorization api', async () => {
|
||||
const alertAuthorization = new AlertingAuthorization({
|
||||
request,
|
||||
|
@ -672,7 +930,6 @@ describe('AlertingAuthorization', () => {
|
|||
getSpace,
|
||||
exemptConsumerIds,
|
||||
});
|
||||
|
||||
const {
|
||||
filter,
|
||||
ensureRuleTypeIsAuthorized,
|
||||
|
@ -683,13 +940,10 @@ describe('AlertingAuthorization', () => {
|
|||
consumer: 'consumer',
|
||||
},
|
||||
});
|
||||
|
||||
expect(() => ensureRuleTypeIsAuthorized('someMadeUpType', 'myApp', 'rule')).not.toThrow();
|
||||
|
||||
expect(filter).toEqual(undefined);
|
||||
});
|
||||
|
||||
test('ensureAlertTypeIsAuthorized is no-op when there is no authorization api', async () => {
|
||||
test('ensureRuleTypeIsAuthorized is no-op when there is no authorization api', async () => {
|
||||
const alertAuthorization = new AlertingAuthorization({
|
||||
request,
|
||||
alertTypeRegistry,
|
||||
|
@ -698,7 +952,6 @@ describe('AlertingAuthorization', () => {
|
|||
getSpace,
|
||||
exemptConsumerIds,
|
||||
});
|
||||
|
||||
const { ensureRuleTypeIsAuthorized } = await alertAuthorization.getFindAuthorizationFilter(
|
||||
AlertingAuthorizationEntity.Rule,
|
||||
{
|
||||
|
@ -709,13 +962,10 @@ describe('AlertingAuthorization', () => {
|
|||
},
|
||||
}
|
||||
);
|
||||
|
||||
ensureRuleTypeIsAuthorized('someMadeUpType', 'myApp', 'rule');
|
||||
|
||||
expect(auditLogger.logAuthorizationSuccess).not.toHaveBeenCalled();
|
||||
expect(auditLogger.logAuthorizationFailure).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('creates a filter based on the privileged types', async () => {
|
||||
const { authorization } = mockSecurity();
|
||||
const checkPrivileges: jest.MockedFunction<
|
||||
|
@ -727,7 +977,6 @@ describe('AlertingAuthorization', () => {
|
|||
hasAllRequested: true,
|
||||
privileges: { kibana: [] },
|
||||
});
|
||||
|
||||
const alertAuthorization = new AlertingAuthorization({
|
||||
request,
|
||||
authorization,
|
||||
|
@ -738,7 +987,6 @@ describe('AlertingAuthorization', () => {
|
|||
exemptConsumerIds,
|
||||
});
|
||||
alertTypeRegistry.list.mockReturnValue(setOfAlertTypes);
|
||||
|
||||
expect(
|
||||
(
|
||||
await alertAuthorization.getFindAuthorizationFilter(AlertingAuthorizationEntity.Rule, {
|
||||
|
@ -754,11 +1002,9 @@ describe('AlertingAuthorization', () => {
|
|||
`((path.to.rule.id:myAppAlertType and consumer-field:(myApp or myOtherApp or myAppWithSubFeature)) or (path.to.rule.id:myOtherAppAlertType and consumer-field:(myApp or myOtherApp or myAppWithSubFeature)) or (path.to.rule.id:mySecondAppAlertType and consumer-field:(myApp or myOtherApp or myAppWithSubFeature)))`
|
||||
)
|
||||
);
|
||||
|
||||
expect(auditLogger.logAuthorizationSuccess).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('creates an `ensureAlertTypeIsAuthorized` function which throws if type is unauthorized', async () => {
|
||||
test('creates an `ensureRuleTypeIsAuthorized` function which throws if type is unauthorized', async () => {
|
||||
const { authorization } = mockSecurity();
|
||||
const checkPrivileges: jest.MockedFunction<
|
||||
ReturnType<typeof authorization.checkPrivilegesDynamicallyWithRequest>
|
||||
|
@ -793,7 +1039,6 @@ describe('AlertingAuthorization', () => {
|
|||
],
|
||||
},
|
||||
});
|
||||
|
||||
const alertAuthorization = new AlertingAuthorization({
|
||||
request,
|
||||
authorization,
|
||||
|
@ -804,7 +1049,6 @@ describe('AlertingAuthorization', () => {
|
|||
exemptConsumerIds,
|
||||
});
|
||||
alertTypeRegistry.list.mockReturnValue(setOfAlertTypes);
|
||||
|
||||
const { ensureRuleTypeIsAuthorized } = await alertAuthorization.getFindAuthorizationFilter(
|
||||
AlertingAuthorizationEntity.Alert,
|
||||
{
|
||||
|
@ -820,22 +1064,20 @@ describe('AlertingAuthorization', () => {
|
|||
}).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Unauthorized to find a \\"myAppAlertType\\" alert for \\"myOtherApp\\""`
|
||||
);
|
||||
|
||||
expect(auditLogger.logAuthorizationSuccess).not.toHaveBeenCalled();
|
||||
expect(auditLogger.logAuthorizationFailure).toHaveBeenCalledTimes(1);
|
||||
expect(auditLogger.logAuthorizationFailure.mock.calls[0]).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"some-user",
|
||||
"myAppAlertType",
|
||||
0,
|
||||
"myOtherApp",
|
||||
"find",
|
||||
"alert",
|
||||
]
|
||||
`);
|
||||
Array [
|
||||
"some-user",
|
||||
"myAppAlertType",
|
||||
0,
|
||||
"myOtherApp",
|
||||
"find",
|
||||
"alert",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
test('creates an `ensureAlertTypeIsAuthorized` function which is no-op if type is authorized', async () => {
|
||||
test('creates an `ensureRuleTypeIsAuthorized` function which is no-op if type is authorized', async () => {
|
||||
const { authorization } = mockSecurity();
|
||||
const checkPrivileges: jest.MockedFunction<
|
||||
ReturnType<typeof authorization.checkPrivilegesDynamicallyWithRequest>
|
||||
|
@ -870,7 +1112,6 @@ describe('AlertingAuthorization', () => {
|
|||
],
|
||||
},
|
||||
});
|
||||
|
||||
const alertAuthorization = new AlertingAuthorization({
|
||||
request,
|
||||
authorization,
|
||||
|
@ -881,7 +1122,6 @@ describe('AlertingAuthorization', () => {
|
|||
exemptConsumerIds,
|
||||
});
|
||||
alertTypeRegistry.list.mockReturnValue(setOfAlertTypes);
|
||||
|
||||
const { ensureRuleTypeIsAuthorized } = await alertAuthorization.getFindAuthorizationFilter(
|
||||
AlertingAuthorizationEntity.Rule,
|
||||
{
|
||||
|
@ -895,11 +1135,9 @@ describe('AlertingAuthorization', () => {
|
|||
expect(() => {
|
||||
ensureRuleTypeIsAuthorized('myAppAlertType', 'myOtherApp', 'rule');
|
||||
}).not.toThrow();
|
||||
|
||||
expect(auditLogger.logAuthorizationSuccess).not.toHaveBeenCalled();
|
||||
expect(auditLogger.logAuthorizationFailure).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('creates an `logSuccessfulAuthorization` function which logs every authorized type', async () => {
|
||||
const { authorization } = mockSecurity();
|
||||
const checkPrivileges: jest.MockedFunction<
|
||||
|
@ -948,7 +1186,6 @@ describe('AlertingAuthorization', () => {
|
|||
],
|
||||
},
|
||||
});
|
||||
|
||||
const alertAuthorization = new AlertingAuthorization({
|
||||
request,
|
||||
authorization,
|
||||
|
@ -959,7 +1196,6 @@ describe('AlertingAuthorization', () => {
|
|||
exemptConsumerIds,
|
||||
});
|
||||
alertTypeRegistry.list.mockReturnValue(setOfAlertTypes);
|
||||
|
||||
const {
|
||||
ensureRuleTypeIsAuthorized,
|
||||
logSuccessfulAuthorization,
|
||||
|
@ -975,35 +1211,32 @@ describe('AlertingAuthorization', () => {
|
|||
ensureRuleTypeIsAuthorized('mySecondAppAlertType', 'myOtherApp', 'rule');
|
||||
ensureRuleTypeIsAuthorized('myAppAlertType', 'myOtherApp', 'rule');
|
||||
}).not.toThrow();
|
||||
|
||||
expect(auditLogger.logAuthorizationSuccess).not.toHaveBeenCalled();
|
||||
expect(auditLogger.logAuthorizationFailure).not.toHaveBeenCalled();
|
||||
|
||||
logSuccessfulAuthorization();
|
||||
|
||||
expect(auditLogger.logBulkAuthorizationSuccess).toHaveBeenCalledTimes(1);
|
||||
expect(auditLogger.logBulkAuthorizationSuccess.mock.calls[0]).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"some-user",
|
||||
Array [
|
||||
"some-user",
|
||||
Array [
|
||||
"myAppAlertType",
|
||||
"myOtherApp",
|
||||
Array [
|
||||
"myAppAlertType",
|
||||
"myOtherApp",
|
||||
],
|
||||
Array [
|
||||
"mySecondAppAlertType",
|
||||
"myOtherApp",
|
||||
],
|
||||
],
|
||||
Array [
|
||||
"mySecondAppAlertType",
|
||||
"myOtherApp",
|
||||
],
|
||||
],
|
||||
0,
|
||||
"find",
|
||||
"rule",
|
||||
]
|
||||
`);
|
||||
0,
|
||||
"find",
|
||||
"rule",
|
||||
]
|
||||
`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('filterByAlertTypeAuthorization', () => {
|
||||
describe('filterByRuleTypeAuthorization', () => {
|
||||
const myOtherAppAlertType: RegistryAlertType = {
|
||||
actionGroups: [],
|
||||
actionVariables: undefined,
|
||||
|
|
|
@ -38,7 +38,12 @@ export const APM_FEATURE = {
|
|||
read: [],
|
||||
},
|
||||
alerting: {
|
||||
all: Object.values(AlertType),
|
||||
rule: {
|
||||
all: Object.values(AlertType),
|
||||
},
|
||||
alert: {
|
||||
all: Object.values(AlertType),
|
||||
},
|
||||
},
|
||||
management: {
|
||||
insightsAndAlerting: ['triggersActions'],
|
||||
|
@ -54,7 +59,12 @@ export const APM_FEATURE = {
|
|||
read: [],
|
||||
},
|
||||
alerting: {
|
||||
read: Object.values(AlertType),
|
||||
rule: {
|
||||
read: Object.values(AlertType),
|
||||
},
|
||||
alert: {
|
||||
read: Object.values(AlertType),
|
||||
},
|
||||
},
|
||||
management: {
|
||||
insightsAndAlerting: ['triggersActions'],
|
||||
|
|
|
@ -82,27 +82,50 @@ export interface FeatureKibanaPrivileges {
|
|||
* Alert Types and Alert Types provided by other features to which you wish to grant access.
|
||||
*/
|
||||
alerting?: {
|
||||
/**
|
||||
* List of alert types which users should have full read/write access to when granted this privilege.
|
||||
* @example
|
||||
* ```ts
|
||||
* {
|
||||
* all: ['my-alert-type-within-my-feature']
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
all?: readonly string[];
|
||||
|
||||
/**
|
||||
* List of alert types which users should have read-only access to when granted this privilege.
|
||||
* @example
|
||||
* ```ts
|
||||
* {
|
||||
* read: ['my-alert-type']
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
read?: readonly string[];
|
||||
rule?: {
|
||||
/**
|
||||
* List of rule types which users should have full read/write access to when granted this privilege.
|
||||
* @example
|
||||
* ```ts
|
||||
* {
|
||||
* all: ['my-alert-type-within-my-feature']
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
all?: readonly string[];
|
||||
/**
|
||||
* List of rule types which users should have read-only access to when granted this privilege.
|
||||
* @example
|
||||
* ```ts
|
||||
* {
|
||||
* read: ['my-alert-type']
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
read?: readonly string[];
|
||||
};
|
||||
alert?: {
|
||||
/**
|
||||
* List of rule types for which users should have full read/write access their alert data to when granted this privilege.
|
||||
* @example
|
||||
* ```ts
|
||||
* {
|
||||
* all: ['my-alert-type-within-my-feature']
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
all?: readonly string[];
|
||||
/**
|
||||
* List of rule types for which users should have read-only access to their alert data when granted this privilege.
|
||||
* @example
|
||||
* ```ts
|
||||
* {
|
||||
* read: ['my-alert-type']
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
read?: readonly string[];
|
||||
};
|
||||
};
|
||||
/**
|
||||
* If your feature requires access to specific saved objects, then specify your access needs here.
|
||||
|
|
|
@ -512,8 +512,14 @@ Array [
|
|||
Object {
|
||||
"privilege": Object {
|
||||
"alerting": Object {
|
||||
"all": Array [],
|
||||
"read": Array [],
|
||||
"alert": Object {
|
||||
"all": Array [],
|
||||
"read": Array [],
|
||||
},
|
||||
"rule": Object {
|
||||
"all": Array [],
|
||||
"read": Array [],
|
||||
},
|
||||
},
|
||||
"api": Array [
|
||||
"store_search_session",
|
||||
|
@ -651,8 +657,14 @@ Array [
|
|||
Object {
|
||||
"privilege": Object {
|
||||
"alerting": Object {
|
||||
"all": Array [],
|
||||
"read": Array [],
|
||||
"alert": Object {
|
||||
"all": Array [],
|
||||
"read": Array [],
|
||||
},
|
||||
"rule": Object {
|
||||
"all": Array [],
|
||||
"read": Array [],
|
||||
},
|
||||
},
|
||||
"api": Array [
|
||||
"store_search_session",
|
||||
|
@ -888,8 +900,14 @@ Array [
|
|||
Object {
|
||||
"privilege": Object {
|
||||
"alerting": Object {
|
||||
"all": Array [],
|
||||
"read": Array [],
|
||||
"alert": Object {
|
||||
"all": Array [],
|
||||
"read": Array [],
|
||||
},
|
||||
"rule": Object {
|
||||
"all": Array [],
|
||||
"read": Array [],
|
||||
},
|
||||
},
|
||||
"api": Array [],
|
||||
"app": Array [
|
||||
|
@ -1010,8 +1028,14 @@ Array [
|
|||
Object {
|
||||
"privilege": Object {
|
||||
"alerting": Object {
|
||||
"all": Array [],
|
||||
"read": Array [],
|
||||
"alert": Object {
|
||||
"all": Array [],
|
||||
"read": Array [],
|
||||
},
|
||||
"rule": Object {
|
||||
"all": Array [],
|
||||
"read": Array [],
|
||||
},
|
||||
},
|
||||
"api": Array [
|
||||
"store_search_session",
|
||||
|
@ -1149,8 +1173,14 @@ Array [
|
|||
Object {
|
||||
"privilege": Object {
|
||||
"alerting": Object {
|
||||
"all": Array [],
|
||||
"read": Array [],
|
||||
"alert": Object {
|
||||
"all": Array [],
|
||||
"read": Array [],
|
||||
},
|
||||
"rule": Object {
|
||||
"all": Array [],
|
||||
"read": Array [],
|
||||
},
|
||||
},
|
||||
"api": Array [
|
||||
"store_search_session",
|
||||
|
@ -1386,8 +1416,14 @@ Array [
|
|||
Object {
|
||||
"privilege": Object {
|
||||
"alerting": Object {
|
||||
"all": Array [],
|
||||
"read": Array [],
|
||||
"alert": Object {
|
||||
"all": Array [],
|
||||
"read": Array [],
|
||||
},
|
||||
"rule": Object {
|
||||
"all": Array [],
|
||||
"read": Array [],
|
||||
},
|
||||
},
|
||||
"api": Array [],
|
||||
"app": Array [
|
||||
|
|
|
@ -46,8 +46,14 @@ describe('featurePrivilegeIterator', () => {
|
|||
read: ['read-type'],
|
||||
},
|
||||
alerting: {
|
||||
all: ['alerting-all-type'],
|
||||
read: ['alerting-read-type'],
|
||||
rule: {
|
||||
all: ['alerting-all-type'],
|
||||
read: ['alerting-read-type'],
|
||||
},
|
||||
alert: {
|
||||
all: ['alerting-all-type'],
|
||||
read: [],
|
||||
},
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -63,7 +69,12 @@ describe('featurePrivilegeIterator', () => {
|
|||
read: ['read-type'],
|
||||
},
|
||||
alerting: {
|
||||
read: ['alerting-read-type'],
|
||||
rule: {
|
||||
read: ['alerting-read-type'],
|
||||
},
|
||||
alert: {
|
||||
read: ['alerting-read-type'],
|
||||
},
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -93,8 +104,14 @@ describe('featurePrivilegeIterator', () => {
|
|||
read: ['read-type'],
|
||||
},
|
||||
alerting: {
|
||||
all: ['alerting-all-type'],
|
||||
read: ['alerting-read-type'],
|
||||
rule: {
|
||||
all: ['alerting-all-type'],
|
||||
read: ['alerting-read-type'],
|
||||
},
|
||||
alert: {
|
||||
all: ['alerting-all-type'],
|
||||
read: [],
|
||||
},
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -113,7 +130,12 @@ describe('featurePrivilegeIterator', () => {
|
|||
read: ['read-type'],
|
||||
},
|
||||
alerting: {
|
||||
read: ['alerting-read-type'],
|
||||
rule: {
|
||||
read: ['alerting-read-type'],
|
||||
},
|
||||
alert: {
|
||||
read: ['alerting-read-type'],
|
||||
},
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -139,8 +161,14 @@ describe('featurePrivilegeIterator', () => {
|
|||
read: ['read-type'],
|
||||
},
|
||||
alerting: {
|
||||
all: ['alerting-all-type'],
|
||||
read: ['alerting-read-type'],
|
||||
rule: {
|
||||
all: ['alerting-all-type'],
|
||||
read: ['alerting-read-type'],
|
||||
},
|
||||
alert: {
|
||||
all: ['alerting-all-type'],
|
||||
read: ['alerting-read-type-alerts'],
|
||||
},
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -156,7 +184,12 @@ describe('featurePrivilegeIterator', () => {
|
|||
read: ['read-type'],
|
||||
},
|
||||
alerting: {
|
||||
read: ['alerting-read-type'],
|
||||
rule: {
|
||||
read: ['alerting-read-type'],
|
||||
},
|
||||
alert: {
|
||||
read: ['alerting-read-type'],
|
||||
},
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -187,8 +220,14 @@ describe('featurePrivilegeIterator', () => {
|
|||
read: ['read-type'],
|
||||
},
|
||||
alerting: {
|
||||
all: ['alerting-all-type'],
|
||||
read: ['alerting-read-type'],
|
||||
rule: {
|
||||
all: ['alerting-all-type'],
|
||||
read: ['alerting-read-type'],
|
||||
},
|
||||
alert: {
|
||||
all: ['alerting-all-type'],
|
||||
read: ['alerting-read-type-alerts'],
|
||||
},
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -212,11 +251,15 @@ describe('featurePrivilegeIterator', () => {
|
|||
},
|
||||
savedObject: {
|
||||
all: ['all-type'],
|
||||
read: ['read-type'],
|
||||
read: [],
|
||||
},
|
||||
alerting: {
|
||||
all: ['alerting-all-type'],
|
||||
read: ['alerting-read-type'],
|
||||
rule: {
|
||||
all: ['alerting-all-type'],
|
||||
},
|
||||
alert: {
|
||||
read: ['alerting-another-read-type'],
|
||||
},
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -232,7 +275,12 @@ describe('featurePrivilegeIterator', () => {
|
|||
read: ['read-type'],
|
||||
},
|
||||
alerting: {
|
||||
read: ['alerting-read-type'],
|
||||
rule: {
|
||||
read: ['alerting-read-type'],
|
||||
},
|
||||
alert: {
|
||||
read: ['alerting-read-type'],
|
||||
},
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -259,8 +307,9 @@ describe('featurePrivilegeIterator', () => {
|
|||
read: ['read-sub-type'],
|
||||
},
|
||||
alerting: {
|
||||
all: ['alerting-all-sub-type'],
|
||||
read: ['alerting-read-sub-type'],
|
||||
alert: {
|
||||
all: ['alerting-all-sub-type'],
|
||||
},
|
||||
},
|
||||
ui: ['ui-sub-type'],
|
||||
},
|
||||
|
@ -290,11 +339,15 @@ describe('featurePrivilegeIterator', () => {
|
|||
},
|
||||
savedObject: {
|
||||
all: ['all-type'],
|
||||
read: ['read-type'],
|
||||
read: [],
|
||||
},
|
||||
alerting: {
|
||||
all: ['alerting-all-type'],
|
||||
read: ['alerting-read-type'],
|
||||
rule: {
|
||||
all: ['alerting-all-type'],
|
||||
},
|
||||
alert: {
|
||||
read: ['alerting-another-read-type'],
|
||||
},
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -313,7 +366,12 @@ describe('featurePrivilegeIterator', () => {
|
|||
read: ['read-type'],
|
||||
},
|
||||
alerting: {
|
||||
read: ['alerting-read-type'],
|
||||
rule: {
|
||||
read: ['alerting-read-type'],
|
||||
},
|
||||
alert: {
|
||||
read: ['alerting-read-type'],
|
||||
},
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -340,8 +398,12 @@ describe('featurePrivilegeIterator', () => {
|
|||
read: ['read-type'],
|
||||
},
|
||||
alerting: {
|
||||
all: ['alerting-all-type'],
|
||||
read: ['alerting-read-type'],
|
||||
rule: {
|
||||
all: ['alerting-all-type'],
|
||||
},
|
||||
alert: {
|
||||
read: ['alerting-another-read-type'],
|
||||
},
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -357,7 +419,12 @@ describe('featurePrivilegeIterator', () => {
|
|||
read: ['read-type'],
|
||||
},
|
||||
alerting: {
|
||||
read: ['alerting-read-type'],
|
||||
rule: {
|
||||
read: ['alerting-read-type'],
|
||||
},
|
||||
alert: {
|
||||
read: ['alerting-read-type'],
|
||||
},
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -384,8 +451,9 @@ describe('featurePrivilegeIterator', () => {
|
|||
read: ['read-sub-type'],
|
||||
},
|
||||
alerting: {
|
||||
all: ['alerting-all-sub-type'],
|
||||
read: ['alerting-read-sub-type'],
|
||||
alert: {
|
||||
all: ['alerting-all-sub-type'],
|
||||
},
|
||||
},
|
||||
ui: ['ui-sub-type'],
|
||||
},
|
||||
|
@ -418,8 +486,12 @@ describe('featurePrivilegeIterator', () => {
|
|||
read: ['read-type'],
|
||||
},
|
||||
alerting: {
|
||||
all: ['alerting-all-type'],
|
||||
read: ['alerting-read-type'],
|
||||
rule: {
|
||||
all: ['alerting-all-type'],
|
||||
},
|
||||
alert: {
|
||||
read: ['alerting-another-read-type'],
|
||||
},
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -438,7 +510,12 @@ describe('featurePrivilegeIterator', () => {
|
|||
read: ['read-type'],
|
||||
},
|
||||
alerting: {
|
||||
read: ['alerting-read-type'],
|
||||
rule: {
|
||||
read: ['alerting-read-type'],
|
||||
},
|
||||
alert: {
|
||||
read: ['alerting-read-type'],
|
||||
},
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -465,8 +542,12 @@ describe('featurePrivilegeIterator', () => {
|
|||
read: ['read-type'],
|
||||
},
|
||||
alerting: {
|
||||
all: ['alerting-all-type'],
|
||||
read: ['alerting-read-type'],
|
||||
rule: {
|
||||
all: ['alerting-all-type'],
|
||||
},
|
||||
alert: {
|
||||
read: ['alerting-another-read-type'],
|
||||
},
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -482,7 +563,12 @@ describe('featurePrivilegeIterator', () => {
|
|||
read: ['read-type'],
|
||||
},
|
||||
alerting: {
|
||||
read: ['alerting-read-type'],
|
||||
rule: {
|
||||
read: ['alerting-read-type'],
|
||||
},
|
||||
alert: {
|
||||
read: ['alerting-read-type'],
|
||||
},
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -510,8 +596,9 @@ describe('featurePrivilegeIterator', () => {
|
|||
read: ['read-sub-type'],
|
||||
},
|
||||
alerting: {
|
||||
all: ['alerting-all-sub-type'],
|
||||
read: ['alerting-read-sub-type'],
|
||||
alert: {
|
||||
all: ['alerting-all-sub-type'],
|
||||
},
|
||||
},
|
||||
ui: ['ui-sub-type'],
|
||||
},
|
||||
|
@ -545,8 +632,14 @@ describe('featurePrivilegeIterator', () => {
|
|||
read: ['read-type', 'read-sub-type'],
|
||||
},
|
||||
alerting: {
|
||||
all: ['alerting-all-type', 'alerting-all-sub-type'],
|
||||
read: ['alerting-read-type', 'alerting-read-sub-type'],
|
||||
rule: {
|
||||
all: ['alerting-all-type'],
|
||||
read: [],
|
||||
},
|
||||
alert: {
|
||||
all: ['alerting-all-sub-type'],
|
||||
read: ['alerting-another-read-type'],
|
||||
},
|
||||
},
|
||||
ui: ['ui-action', 'ui-sub-type'],
|
||||
},
|
||||
|
@ -566,8 +659,14 @@ describe('featurePrivilegeIterator', () => {
|
|||
read: ['read-type', 'read-sub-type'],
|
||||
},
|
||||
alerting: {
|
||||
all: ['alerting-all-sub-type'],
|
||||
read: ['alerting-read-type', 'alerting-read-sub-type'],
|
||||
rule: {
|
||||
all: [],
|
||||
read: ['alerting-read-type'],
|
||||
},
|
||||
alert: {
|
||||
all: ['alerting-all-sub-type'],
|
||||
read: ['alerting-read-type'],
|
||||
},
|
||||
},
|
||||
ui: ['ui-action', 'ui-sub-type'],
|
||||
},
|
||||
|
@ -594,8 +693,14 @@ describe('featurePrivilegeIterator', () => {
|
|||
read: ['read-type'],
|
||||
},
|
||||
alerting: {
|
||||
all: ['alerting-all-type'],
|
||||
read: ['alerting-read-type'],
|
||||
rule: {
|
||||
all: ['alerting-all-type'],
|
||||
read: ['alerting-read-type'],
|
||||
},
|
||||
alert: {
|
||||
all: [],
|
||||
read: ['alerting-read-type'],
|
||||
},
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -611,7 +716,12 @@ describe('featurePrivilegeIterator', () => {
|
|||
read: ['read-type'],
|
||||
},
|
||||
alerting: {
|
||||
read: ['alerting-read-type'],
|
||||
rule: {
|
||||
read: ['alerting-read-type'],
|
||||
},
|
||||
alert: {
|
||||
read: ['alerting-read-type'],
|
||||
},
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -638,7 +748,9 @@ describe('featurePrivilegeIterator', () => {
|
|||
read: ['read-type'],
|
||||
},
|
||||
alerting: {
|
||||
read: ['alerting-read-type'],
|
||||
alert: {
|
||||
all: ['alerting-read-type'],
|
||||
},
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -671,8 +783,14 @@ describe('featurePrivilegeIterator', () => {
|
|||
read: ['read-type'],
|
||||
},
|
||||
alerting: {
|
||||
all: ['alerting-all-type'],
|
||||
read: ['alerting-read-type'],
|
||||
rule: {
|
||||
all: ['alerting-all-type'],
|
||||
read: ['alerting-read-type'],
|
||||
},
|
||||
alert: {
|
||||
all: ['alerting-read-type'],
|
||||
read: ['alerting-read-type'],
|
||||
},
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -691,8 +809,14 @@ describe('featurePrivilegeIterator', () => {
|
|||
read: ['read-type'],
|
||||
},
|
||||
alerting: {
|
||||
all: [],
|
||||
read: ['alerting-read-type'],
|
||||
rule: {
|
||||
all: [],
|
||||
read: ['alerting-read-type'],
|
||||
},
|
||||
alert: {
|
||||
all: ['alerting-read-type'],
|
||||
read: ['alerting-read-type'],
|
||||
},
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -719,8 +843,12 @@ describe('featurePrivilegeIterator', () => {
|
|||
read: ['read-type'],
|
||||
},
|
||||
alerting: {
|
||||
all: ['alerting-all-type'],
|
||||
read: ['alerting-read-type'],
|
||||
rule: {
|
||||
all: ['alerting-all-type'],
|
||||
},
|
||||
alert: {
|
||||
read: ['alerting-another-read-type'],
|
||||
},
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -736,7 +864,12 @@ describe('featurePrivilegeIterator', () => {
|
|||
read: ['read-type'],
|
||||
},
|
||||
alerting: {
|
||||
read: ['alerting-read-type'],
|
||||
rule: {
|
||||
read: ['alerting-read-type'],
|
||||
},
|
||||
alert: {
|
||||
read: ['alerting-read-type'],
|
||||
},
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -764,8 +897,9 @@ describe('featurePrivilegeIterator', () => {
|
|||
read: ['read-sub-type'],
|
||||
},
|
||||
alerting: {
|
||||
all: ['alerting-all-sub-type'],
|
||||
read: ['alerting-read-sub-type'],
|
||||
alert: {
|
||||
all: ['alerting-all-sub-type'],
|
||||
},
|
||||
},
|
||||
ui: ['ui-sub-type'],
|
||||
},
|
||||
|
@ -799,8 +933,14 @@ describe('featurePrivilegeIterator', () => {
|
|||
read: ['read-type', 'read-sub-type'],
|
||||
},
|
||||
alerting: {
|
||||
all: ['alerting-all-type', 'alerting-all-sub-type'],
|
||||
read: ['alerting-read-type', 'alerting-read-sub-type'],
|
||||
rule: {
|
||||
all: ['alerting-all-type'],
|
||||
read: [],
|
||||
},
|
||||
alert: {
|
||||
all: ['alerting-all-sub-type'],
|
||||
read: ['alerting-another-read-type'],
|
||||
},
|
||||
},
|
||||
ui: ['ui-action', 'ui-sub-type'],
|
||||
},
|
||||
|
@ -819,7 +959,12 @@ describe('featurePrivilegeIterator', () => {
|
|||
read: ['read-type'],
|
||||
},
|
||||
alerting: {
|
||||
read: ['alerting-read-type'],
|
||||
rule: {
|
||||
read: ['alerting-read-type'],
|
||||
},
|
||||
alert: {
|
||||
read: ['alerting-read-type'],
|
||||
},
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -846,8 +991,12 @@ describe('featurePrivilegeIterator', () => {
|
|||
read: ['read-type'],
|
||||
},
|
||||
alerting: {
|
||||
all: ['alerting-all-type'],
|
||||
read: ['alerting-read-type'],
|
||||
rule: {
|
||||
all: ['alerting-all-type'],
|
||||
},
|
||||
alert: {
|
||||
read: ['alerting-another-read-type'],
|
||||
},
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -863,7 +1012,12 @@ describe('featurePrivilegeIterator', () => {
|
|||
read: ['read-type'],
|
||||
},
|
||||
alerting: {
|
||||
read: ['alerting-read-type'],
|
||||
rule: {
|
||||
read: ['alerting-read-type'],
|
||||
},
|
||||
alert: {
|
||||
read: ['alerting-read-type'],
|
||||
},
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -892,8 +1046,9 @@ describe('featurePrivilegeIterator', () => {
|
|||
read: ['read-sub-type'],
|
||||
},
|
||||
alerting: {
|
||||
all: ['alerting-all-sub-type'],
|
||||
read: ['alerting-read-sub-type'],
|
||||
alert: {
|
||||
all: ['alerting-all-sub-type'],
|
||||
},
|
||||
},
|
||||
ui: ['ui-sub-type'],
|
||||
},
|
||||
|
@ -926,8 +1081,12 @@ describe('featurePrivilegeIterator', () => {
|
|||
read: ['read-type'],
|
||||
},
|
||||
alerting: {
|
||||
all: ['alerting-all-type'],
|
||||
read: ['alerting-read-type'],
|
||||
rule: {
|
||||
all: ['alerting-all-type'],
|
||||
},
|
||||
alert: {
|
||||
read: ['alerting-another-read-type'],
|
||||
},
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -946,7 +1105,12 @@ describe('featurePrivilegeIterator', () => {
|
|||
read: ['read-type'],
|
||||
},
|
||||
alerting: {
|
||||
read: ['alerting-read-type'],
|
||||
rule: {
|
||||
read: ['alerting-read-type'],
|
||||
},
|
||||
alert: {
|
||||
read: ['alerting-read-type'],
|
||||
},
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -999,8 +1163,10 @@ describe('featurePrivilegeIterator', () => {
|
|||
read: ['read-sub-type'],
|
||||
},
|
||||
alerting: {
|
||||
all: ['alerting-all-sub-type'],
|
||||
read: ['alerting-read-sub-type'],
|
||||
rule: {
|
||||
all: ['alerting-all-sub-type'],
|
||||
read: ['alerting-read-sub-type'],
|
||||
},
|
||||
},
|
||||
ui: ['ui-sub-type'],
|
||||
},
|
||||
|
@ -1034,8 +1200,14 @@ describe('featurePrivilegeIterator', () => {
|
|||
read: ['read-sub-type'],
|
||||
},
|
||||
alerting: {
|
||||
all: ['alerting-all-sub-type'],
|
||||
read: ['alerting-read-sub-type'],
|
||||
rule: {
|
||||
all: ['alerting-all-sub-type'],
|
||||
read: ['alerting-read-sub-type'],
|
||||
},
|
||||
alert: {
|
||||
all: [],
|
||||
read: [],
|
||||
},
|
||||
},
|
||||
ui: ['ui-sub-type'],
|
||||
},
|
||||
|
@ -1055,8 +1227,14 @@ describe('featurePrivilegeIterator', () => {
|
|||
read: ['read-sub-type'],
|
||||
},
|
||||
alerting: {
|
||||
all: ['alerting-all-sub-type'],
|
||||
read: ['alerting-read-sub-type'],
|
||||
rule: {
|
||||
all: ['alerting-all-sub-type'],
|
||||
read: ['alerting-read-sub-type'],
|
||||
},
|
||||
alert: {
|
||||
all: [],
|
||||
read: [],
|
||||
},
|
||||
},
|
||||
ui: ['ui-sub-type'],
|
||||
},
|
||||
|
@ -1083,8 +1261,12 @@ describe('featurePrivilegeIterator', () => {
|
|||
read: ['read-type'],
|
||||
},
|
||||
alerting: {
|
||||
all: ['alerting-all-type'],
|
||||
read: ['alerting-read-type'],
|
||||
rule: {
|
||||
all: ['alerting-all-type'],
|
||||
},
|
||||
alert: {
|
||||
read: ['alerting-another-read-type'],
|
||||
},
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -1100,7 +1282,12 @@ describe('featurePrivilegeIterator', () => {
|
|||
read: ['read-type'],
|
||||
},
|
||||
alerting: {
|
||||
read: ['alerting-read-type'],
|
||||
rule: {
|
||||
read: ['alerting-read-type'],
|
||||
},
|
||||
alert: {
|
||||
read: ['alerting-read-type'],
|
||||
},
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -1151,8 +1338,14 @@ describe('featurePrivilegeIterator', () => {
|
|||
read: ['read-type'],
|
||||
},
|
||||
alerting: {
|
||||
all: ['alerting-all-type'],
|
||||
read: ['alerting-read-type'],
|
||||
rule: {
|
||||
all: ['alerting-all-type'],
|
||||
read: [],
|
||||
},
|
||||
alert: {
|
||||
all: [],
|
||||
read: ['alerting-another-read-type'],
|
||||
},
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -1171,8 +1364,14 @@ describe('featurePrivilegeIterator', () => {
|
|||
read: ['read-type'],
|
||||
},
|
||||
alerting: {
|
||||
all: [],
|
||||
read: ['alerting-read-type'],
|
||||
rule: {
|
||||
all: [],
|
||||
read: ['alerting-read-type'],
|
||||
},
|
||||
alert: {
|
||||
all: [],
|
||||
read: ['alerting-read-type'],
|
||||
},
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
|
|
@ -110,11 +110,26 @@ function mergeWithSubFeatures(
|
|||
);
|
||||
|
||||
mergedConfig.alerting = {
|
||||
all: mergeArrays(mergedConfig.alerting?.all ?? [], subFeaturePrivilege.alerting?.all ?? []),
|
||||
read: mergeArrays(
|
||||
mergedConfig.alerting?.read ?? [],
|
||||
subFeaturePrivilege.alerting?.read ?? []
|
||||
),
|
||||
rule: {
|
||||
all: mergeArrays(
|
||||
mergedConfig.alerting?.rule?.all ?? [],
|
||||
subFeaturePrivilege.alerting?.rule?.all ?? []
|
||||
),
|
||||
read: mergeArrays(
|
||||
mergedConfig.alerting?.rule?.read ?? [],
|
||||
subFeaturePrivilege.alerting?.rule?.read ?? []
|
||||
),
|
||||
},
|
||||
alert: {
|
||||
all: mergeArrays(
|
||||
mergedConfig.alerting?.alert?.all ?? [],
|
||||
subFeaturePrivilege.alerting?.alert?.all ?? []
|
||||
),
|
||||
read: mergeArrays(
|
||||
mergedConfig.alerting?.alert?.read ?? [],
|
||||
subFeaturePrivilege.alerting?.alert?.read ?? []
|
||||
),
|
||||
},
|
||||
};
|
||||
}
|
||||
return mergedConfig;
|
||||
|
|
|
@ -828,7 +828,7 @@ describe('FeatureRegistry', () => {
|
|||
);
|
||||
});
|
||||
|
||||
it(`prevents privileges from specifying alerting entries that don't exist at the root level`, () => {
|
||||
it(`prevents privileges from specifying alerting/rule entries that don't exist at the root level`, () => {
|
||||
const feature: KibanaFeatureConfig = {
|
||||
id: 'test-feature',
|
||||
name: 'Test Feature',
|
||||
|
@ -838,8 +838,10 @@ describe('FeatureRegistry', () => {
|
|||
privileges: {
|
||||
all: {
|
||||
alerting: {
|
||||
all: ['foo', 'bar'],
|
||||
read: ['baz'],
|
||||
rule: {
|
||||
all: ['foo', 'bar'],
|
||||
read: ['baz'],
|
||||
},
|
||||
},
|
||||
savedObject: {
|
||||
all: [],
|
||||
|
@ -849,7 +851,11 @@ describe('FeatureRegistry', () => {
|
|||
app: [],
|
||||
},
|
||||
read: {
|
||||
alerting: { read: ['foo', 'bar', 'baz'] },
|
||||
alerting: {
|
||||
rule: {
|
||||
read: ['foo', 'bar', 'baz'],
|
||||
},
|
||||
},
|
||||
savedObject: {
|
||||
all: [],
|
||||
read: [],
|
||||
|
@ -869,16 +875,21 @@ describe('FeatureRegistry', () => {
|
|||
);
|
||||
});
|
||||
|
||||
it(`prevents features from specifying alerting entries that don't exist at the privilege level`, () => {
|
||||
it(`prevents privileges from specifying alerting/alert entries that don't exist at the root level`, () => {
|
||||
const feature: KibanaFeatureConfig = {
|
||||
id: 'test-feature',
|
||||
name: 'Test Feature',
|
||||
app: [],
|
||||
category: { id: 'foo', label: 'foo' },
|
||||
alerting: ['foo', 'bar', 'baz'],
|
||||
alerting: ['bar'],
|
||||
privileges: {
|
||||
all: {
|
||||
alerting: { all: ['foo'] },
|
||||
alerting: {
|
||||
alert: {
|
||||
all: ['foo', 'bar'],
|
||||
read: ['baz'],
|
||||
},
|
||||
},
|
||||
savedObject: {
|
||||
all: [],
|
||||
read: [],
|
||||
|
@ -887,7 +898,57 @@ describe('FeatureRegistry', () => {
|
|||
app: [],
|
||||
},
|
||||
read: {
|
||||
alerting: { all: ['foo'] },
|
||||
alerting: {
|
||||
alert: {
|
||||
read: ['foo', 'bar', 'baz'],
|
||||
},
|
||||
},
|
||||
savedObject: {
|
||||
all: [],
|
||||
read: [],
|
||||
},
|
||||
ui: [],
|
||||
app: [],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const featureRegistry = new FeatureRegistry();
|
||||
|
||||
expect(() =>
|
||||
featureRegistry.registerKibanaFeature(feature)
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Feature privilege test-feature.all has unknown alerting entries: foo, baz"`
|
||||
);
|
||||
});
|
||||
|
||||
it(`prevents features from specifying alerting/rule entries that don't exist at the privilege level`, () => {
|
||||
const feature: KibanaFeatureConfig = {
|
||||
id: 'test-feature',
|
||||
name: 'Test Feature',
|
||||
app: [],
|
||||
category: { id: 'foo', label: 'foo' },
|
||||
alerting: ['foo', 'bar', 'baz'],
|
||||
privileges: {
|
||||
all: {
|
||||
alerting: {
|
||||
rule: {
|
||||
all: ['foo'],
|
||||
},
|
||||
},
|
||||
savedObject: {
|
||||
all: [],
|
||||
read: [],
|
||||
},
|
||||
ui: [],
|
||||
app: [],
|
||||
},
|
||||
read: {
|
||||
alerting: {
|
||||
rule: {
|
||||
all: ['foo'],
|
||||
},
|
||||
},
|
||||
savedObject: {
|
||||
all: [],
|
||||
read: [],
|
||||
|
@ -912,7 +973,11 @@ describe('FeatureRegistry', () => {
|
|||
read: [],
|
||||
},
|
||||
ui: [],
|
||||
alerting: { all: ['bar'] },
|
||||
alerting: {
|
||||
rule: {
|
||||
all: ['bar'],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -930,7 +995,80 @@ describe('FeatureRegistry', () => {
|
|||
);
|
||||
});
|
||||
|
||||
it(`prevents reserved privileges from specifying alerting entries that don't exist at the root level`, () => {
|
||||
it(`prevents features from specifying alerting/alert entries that don't exist at the privilege level`, () => {
|
||||
const feature: KibanaFeatureConfig = {
|
||||
id: 'test-feature',
|
||||
name: 'Test Feature',
|
||||
app: [],
|
||||
category: { id: 'foo', label: 'foo' },
|
||||
alerting: ['foo', 'bar', 'baz'],
|
||||
privileges: {
|
||||
all: {
|
||||
alerting: {
|
||||
alert: {
|
||||
all: ['foo'],
|
||||
},
|
||||
},
|
||||
savedObject: {
|
||||
all: [],
|
||||
read: [],
|
||||
},
|
||||
ui: [],
|
||||
app: [],
|
||||
},
|
||||
read: {
|
||||
alerting: {
|
||||
alert: {
|
||||
all: ['foo'],
|
||||
},
|
||||
},
|
||||
savedObject: {
|
||||
all: [],
|
||||
read: [],
|
||||
},
|
||||
ui: [],
|
||||
app: [],
|
||||
},
|
||||
},
|
||||
subFeatures: [
|
||||
{
|
||||
name: 'my sub feature',
|
||||
privilegeGroups: [
|
||||
{
|
||||
groupType: 'independent',
|
||||
privileges: [
|
||||
{
|
||||
id: 'cool-sub-feature-privilege',
|
||||
name: 'cool privilege',
|
||||
includeIn: 'none',
|
||||
savedObject: {
|
||||
all: [],
|
||||
read: [],
|
||||
},
|
||||
ui: [],
|
||||
alerting: {
|
||||
alert: {
|
||||
all: ['bar'],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const featureRegistry = new FeatureRegistry();
|
||||
|
||||
expect(() =>
|
||||
featureRegistry.registerKibanaFeature(feature)
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Feature test-feature specifies alerting entries which are not granted to any privileges: baz"`
|
||||
);
|
||||
});
|
||||
|
||||
it(`prevents reserved privileges from specifying alerting/rule entries that don't exist at the root level`, () => {
|
||||
const feature: KibanaFeatureConfig = {
|
||||
id: 'test-feature',
|
||||
name: 'Test Feature',
|
||||
|
@ -944,7 +1082,11 @@ describe('FeatureRegistry', () => {
|
|||
{
|
||||
id: 'reserved',
|
||||
privilege: {
|
||||
alerting: { all: ['foo', 'bar', 'baz'] },
|
||||
alerting: {
|
||||
rule: {
|
||||
all: ['foo', 'bar', 'baz'],
|
||||
},
|
||||
},
|
||||
savedObject: {
|
||||
all: [],
|
||||
read: [],
|
||||
|
@ -966,7 +1108,47 @@ describe('FeatureRegistry', () => {
|
|||
);
|
||||
});
|
||||
|
||||
it(`prevents features from specifying alerting entries that don't exist at the reserved privilege level`, () => {
|
||||
it(`prevents reserved privileges from specifying alerting/alert entries that don't exist at the root level`, () => {
|
||||
const feature: KibanaFeatureConfig = {
|
||||
id: 'test-feature',
|
||||
name: 'Test Feature',
|
||||
app: [],
|
||||
category: { id: 'foo', label: 'foo' },
|
||||
alerting: ['bar'],
|
||||
privileges: null,
|
||||
reserved: {
|
||||
description: 'something',
|
||||
privileges: [
|
||||
{
|
||||
id: 'reserved',
|
||||
privilege: {
|
||||
alerting: {
|
||||
alert: {
|
||||
all: ['foo', 'bar', 'baz'],
|
||||
},
|
||||
},
|
||||
savedObject: {
|
||||
all: [],
|
||||
read: [],
|
||||
},
|
||||
ui: [],
|
||||
app: [],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
const featureRegistry = new FeatureRegistry();
|
||||
|
||||
expect(() =>
|
||||
featureRegistry.registerKibanaFeature(feature)
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Feature privilege test-feature.reserved has unknown alerting entries: foo, baz"`
|
||||
);
|
||||
});
|
||||
|
||||
it(`prevents features from specifying alerting/rule entries that don't exist at the reserved privilege level`, () => {
|
||||
const feature: KibanaFeatureConfig = {
|
||||
id: 'test-feature',
|
||||
name: 'Test Feature',
|
||||
|
@ -980,7 +1162,51 @@ describe('FeatureRegistry', () => {
|
|||
{
|
||||
id: 'reserved',
|
||||
privilege: {
|
||||
alerting: { all: ['foo', 'bar'] },
|
||||
alerting: {
|
||||
rule: {
|
||||
all: ['foo', 'bar'],
|
||||
},
|
||||
},
|
||||
savedObject: {
|
||||
all: [],
|
||||
read: [],
|
||||
},
|
||||
ui: [],
|
||||
app: [],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
const featureRegistry = new FeatureRegistry();
|
||||
|
||||
expect(() =>
|
||||
featureRegistry.registerKibanaFeature(feature)
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Feature test-feature specifies alerting entries which are not granted to any privileges: baz"`
|
||||
);
|
||||
});
|
||||
|
||||
it(`prevents features from specifying alerting/alert entries that don't exist at the reserved privilege level`, () => {
|
||||
const feature: KibanaFeatureConfig = {
|
||||
id: 'test-feature',
|
||||
name: 'Test Feature',
|
||||
app: [],
|
||||
category: { id: 'foo', label: 'foo' },
|
||||
alerting: ['foo', 'bar', 'baz'],
|
||||
privileges: null,
|
||||
reserved: {
|
||||
description: 'something',
|
||||
privileges: [
|
||||
{
|
||||
id: 'reserved',
|
||||
privilege: {
|
||||
alerting: {
|
||||
alert: {
|
||||
all: ['foo', 'bar'],
|
||||
},
|
||||
},
|
||||
savedObject: {
|
||||
all: [],
|
||||
read: [],
|
||||
|
|
|
@ -80,8 +80,18 @@ const kibanaPrivilegeSchema = schema.object({
|
|||
app: schema.maybe(schema.arrayOf(schema.string())),
|
||||
alerting: schema.maybe(
|
||||
schema.object({
|
||||
all: schema.maybe(alertingSchema),
|
||||
read: schema.maybe(alertingSchema),
|
||||
rule: schema.maybe(
|
||||
schema.object({
|
||||
all: schema.maybe(alertingSchema),
|
||||
read: schema.maybe(alertingSchema),
|
||||
})
|
||||
),
|
||||
alert: schema.maybe(
|
||||
schema.object({
|
||||
all: schema.maybe(alertingSchema),
|
||||
read: schema.maybe(alertingSchema),
|
||||
})
|
||||
),
|
||||
})
|
||||
),
|
||||
savedObject: schema.object({
|
||||
|
@ -106,8 +116,18 @@ const kibanaIndependentSubFeaturePrivilegeSchema = schema.object({
|
|||
catalogue: schema.maybe(catalogueSchema),
|
||||
alerting: schema.maybe(
|
||||
schema.object({
|
||||
all: schema.maybe(alertingSchema),
|
||||
read: schema.maybe(alertingSchema),
|
||||
rule: schema.maybe(
|
||||
schema.object({
|
||||
all: schema.maybe(alertingSchema),
|
||||
read: schema.maybe(alertingSchema),
|
||||
})
|
||||
),
|
||||
alert: schema.maybe(
|
||||
schema.object({
|
||||
all: schema.maybe(alertingSchema),
|
||||
read: schema.maybe(alertingSchema),
|
||||
})
|
||||
),
|
||||
})
|
||||
),
|
||||
api: schema.maybe(schema.arrayOf(schema.string())),
|
||||
|
@ -274,8 +294,8 @@ export function validateKibanaFeature(feature: KibanaFeatureConfig) {
|
|||
}
|
||||
|
||||
function validateAlertingEntry(privilegeId: string, entry: FeatureKibanaPrivileges['alerting']) {
|
||||
const all = entry?.all ?? [];
|
||||
const read = entry?.read ?? [];
|
||||
const all: string[] = [...(entry?.rule?.all ?? []), ...(entry?.alert?.all ?? [])];
|
||||
const read: string[] = [...(entry?.rule?.read ?? []), ...(entry?.alert?.read ?? [])];
|
||||
|
||||
all.forEach((privilegeAlertTypes) => unseenAlertTypes.delete(privilegeAlertTypes));
|
||||
read.forEach((privilegeAlertTypes) => unseenAlertTypes.delete(privilegeAlertTypes));
|
||||
|
|
|
@ -34,7 +34,12 @@ export const METRICS_FEATURE = {
|
|||
read: ['index-pattern'],
|
||||
},
|
||||
alerting: {
|
||||
all: [METRIC_THRESHOLD_ALERT_TYPE_ID, METRIC_INVENTORY_THRESHOLD_ALERT_TYPE_ID],
|
||||
rule: {
|
||||
all: [METRIC_THRESHOLD_ALERT_TYPE_ID, METRIC_INVENTORY_THRESHOLD_ALERT_TYPE_ID],
|
||||
},
|
||||
alert: {
|
||||
all: [METRIC_THRESHOLD_ALERT_TYPE_ID, METRIC_INVENTORY_THRESHOLD_ALERT_TYPE_ID],
|
||||
},
|
||||
},
|
||||
management: {
|
||||
insightsAndAlerting: ['triggersActions'],
|
||||
|
@ -50,7 +55,12 @@ export const METRICS_FEATURE = {
|
|||
read: ['infrastructure-ui-source', 'index-pattern'],
|
||||
},
|
||||
alerting: {
|
||||
read: [METRIC_THRESHOLD_ALERT_TYPE_ID, METRIC_INVENTORY_THRESHOLD_ALERT_TYPE_ID],
|
||||
rule: {
|
||||
read: [METRIC_THRESHOLD_ALERT_TYPE_ID, METRIC_INVENTORY_THRESHOLD_ALERT_TYPE_ID],
|
||||
},
|
||||
alert: {
|
||||
read: [METRIC_THRESHOLD_ALERT_TYPE_ID, METRIC_INVENTORY_THRESHOLD_ALERT_TYPE_ID],
|
||||
},
|
||||
},
|
||||
management: {
|
||||
insightsAndAlerting: ['triggersActions'],
|
||||
|
@ -83,7 +93,12 @@ export const LOGS_FEATURE = {
|
|||
read: [],
|
||||
},
|
||||
alerting: {
|
||||
all: [LOG_DOCUMENT_COUNT_ALERT_TYPE_ID],
|
||||
rule: {
|
||||
all: [LOG_DOCUMENT_COUNT_ALERT_TYPE_ID],
|
||||
},
|
||||
alert: {
|
||||
all: [LOG_DOCUMENT_COUNT_ALERT_TYPE_ID],
|
||||
},
|
||||
},
|
||||
management: {
|
||||
insightsAndAlerting: ['triggersActions'],
|
||||
|
@ -95,7 +110,12 @@ export const LOGS_FEATURE = {
|
|||
catalogue: ['infralogging', 'logs'],
|
||||
api: ['infra'],
|
||||
alerting: {
|
||||
read: [LOG_DOCUMENT_COUNT_ALERT_TYPE_ID],
|
||||
rule: {
|
||||
read: [LOG_DOCUMENT_COUNT_ALERT_TYPE_ID],
|
||||
},
|
||||
alert: {
|
||||
read: [LOG_DOCUMENT_COUNT_ALERT_TYPE_ID],
|
||||
},
|
||||
},
|
||||
management: {
|
||||
insightsAndAlerting: ['triggersActions'],
|
||||
|
|
|
@ -117,8 +117,12 @@ export function getPluginPrivileges() {
|
|||
read: savedObjects,
|
||||
},
|
||||
alerting: {
|
||||
all: Object.values(ML_ALERT_TYPES),
|
||||
read: [],
|
||||
rule: {
|
||||
all: Object.values(ML_ALERT_TYPES),
|
||||
},
|
||||
alert: {
|
||||
all: Object.values(ML_ALERT_TYPES),
|
||||
},
|
||||
},
|
||||
},
|
||||
user: {
|
||||
|
@ -132,8 +136,12 @@ export function getPluginPrivileges() {
|
|||
read: savedObjects,
|
||||
},
|
||||
alerting: {
|
||||
all: [],
|
||||
read: Object.values(ML_ALERT_TYPES),
|
||||
rule: {
|
||||
read: Object.values(ML_ALERT_TYPES),
|
||||
},
|
||||
alert: {
|
||||
read: Object.values(ML_ALERT_TYPES),
|
||||
},
|
||||
},
|
||||
},
|
||||
apmUser: {
|
||||
|
|
|
@ -262,7 +262,12 @@ export class MonitoringPlugin
|
|||
read: [],
|
||||
},
|
||||
alerting: {
|
||||
all: ALERTS,
|
||||
rule: {
|
||||
all: ALERTS,
|
||||
},
|
||||
alert: {
|
||||
all: ALERTS,
|
||||
},
|
||||
},
|
||||
ui: [],
|
||||
},
|
||||
|
|
|
@ -20,8 +20,14 @@ describe(`feature_privilege_builder`, () => {
|
|||
|
||||
const privilege: FeatureKibanaPrivileges = {
|
||||
alerting: {
|
||||
all: [],
|
||||
read: [],
|
||||
rule: {
|
||||
all: [],
|
||||
read: [],
|
||||
},
|
||||
alert: {
|
||||
all: [],
|
||||
read: [],
|
||||
},
|
||||
},
|
||||
|
||||
savedObject: {
|
||||
|
@ -46,14 +52,98 @@ describe(`feature_privilege_builder`, () => {
|
|||
});
|
||||
|
||||
describe(`within feature`, () => {
|
||||
test('grants `read` privileges under feature consumer', () => {
|
||||
test('grants `read` privileges to rules under feature consumer', () => {
|
||||
const actions = new Actions(version);
|
||||
const alertingFeaturePrivileges = new FeaturePrivilegeAlertingBuilder(actions);
|
||||
|
||||
const privilege: FeatureKibanaPrivileges = {
|
||||
alerting: {
|
||||
rule: {
|
||||
all: [],
|
||||
read: ['alert-type'],
|
||||
},
|
||||
},
|
||||
|
||||
savedObject: {
|
||||
all: [],
|
||||
read: ['alert-type'],
|
||||
read: [],
|
||||
},
|
||||
ui: [],
|
||||
};
|
||||
|
||||
const feature = new KibanaFeature({
|
||||
id: 'my-feature',
|
||||
name: 'my-feature',
|
||||
app: [],
|
||||
category: { id: 'foo', label: 'foo' },
|
||||
privileges: {
|
||||
all: privilege,
|
||||
read: privilege,
|
||||
},
|
||||
});
|
||||
|
||||
expect(alertingFeaturePrivileges.getActions(privilege, feature)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/get",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/getRuleState",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/getAlertSummary",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/find",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
test('grants `read` privileges to alerts under feature consumer', () => {
|
||||
const actions = new Actions(version);
|
||||
const alertingFeaturePrivileges = new FeaturePrivilegeAlertingBuilder(actions);
|
||||
|
||||
const privilege: FeatureKibanaPrivileges = {
|
||||
alerting: {
|
||||
alert: {
|
||||
all: [],
|
||||
read: ['alert-type'],
|
||||
},
|
||||
},
|
||||
|
||||
savedObject: {
|
||||
all: [],
|
||||
read: [],
|
||||
},
|
||||
ui: [],
|
||||
};
|
||||
|
||||
const feature = new KibanaFeature({
|
||||
id: 'my-feature',
|
||||
name: 'my-feature',
|
||||
app: [],
|
||||
category: { id: 'foo', label: 'foo' },
|
||||
privileges: {
|
||||
all: privilege,
|
||||
read: privilege,
|
||||
},
|
||||
});
|
||||
|
||||
expect(alertingFeaturePrivileges.getActions(privilege, feature)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/alert/get",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/alert/find",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
test('grants `read` privileges to rules and alerts under feature consumer', () => {
|
||||
const actions = new Actions(version);
|
||||
const alertingFeaturePrivileges = new FeaturePrivilegeAlertingBuilder(actions);
|
||||
|
||||
const privilege: FeatureKibanaPrivileges = {
|
||||
alerting: {
|
||||
rule: {
|
||||
all: [],
|
||||
read: ['alert-type'],
|
||||
},
|
||||
alert: {
|
||||
all: [],
|
||||
read: ['alert-type'],
|
||||
},
|
||||
},
|
||||
|
||||
savedObject: {
|
||||
|
@ -86,14 +176,16 @@ describe(`feature_privilege_builder`, () => {
|
|||
`);
|
||||
});
|
||||
|
||||
test('grants `all` privileges under feature consumer', () => {
|
||||
test('grants `all` privileges to rules under feature consumer', () => {
|
||||
const actions = new Actions(version);
|
||||
const alertingFeaturePrivileges = new FeaturePrivilegeAlertingBuilder(actions);
|
||||
|
||||
const privilege: FeatureKibanaPrivileges = {
|
||||
alerting: {
|
||||
all: ['alert-type'],
|
||||
read: [],
|
||||
rule: {
|
||||
all: ['alert-type'],
|
||||
read: [],
|
||||
},
|
||||
},
|
||||
|
||||
savedObject: {
|
||||
|
@ -115,36 +207,35 @@ describe(`feature_privilege_builder`, () => {
|
|||
});
|
||||
|
||||
expect(alertingFeaturePrivileges.getActions(privilege, feature)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/get",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/getRuleState",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/getAlertSummary",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/find",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/create",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/delete",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/update",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/updateApiKey",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/enable",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/disable",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/muteAll",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/unmuteAll",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/muteAlert",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/unmuteAlert",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/alert/get",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/alert/find",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/alert/update",
|
||||
]
|
||||
`);
|
||||
Array [
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/get",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/getRuleState",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/getAlertSummary",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/find",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/create",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/delete",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/update",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/updateApiKey",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/enable",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/disable",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/muteAll",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/unmuteAll",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/muteAlert",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/unmuteAlert",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
test('grants both `all` and `read` privileges under feature consumer', () => {
|
||||
test('grants `all` privileges to alerts under feature consumer', () => {
|
||||
const actions = new Actions(version);
|
||||
const alertingFeaturePrivileges = new FeaturePrivilegeAlertingBuilder(actions);
|
||||
|
||||
const privilege: FeatureKibanaPrivileges = {
|
||||
alerting: {
|
||||
all: ['alert-type'],
|
||||
read: ['readonly-alert-type'],
|
||||
alert: {
|
||||
all: ['alert-type'],
|
||||
read: [],
|
||||
},
|
||||
},
|
||||
|
||||
savedObject: {
|
||||
|
@ -166,32 +257,227 @@ describe(`feature_privilege_builder`, () => {
|
|||
});
|
||||
|
||||
expect(alertingFeaturePrivileges.getActions(privilege, feature)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/get",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/getRuleState",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/getAlertSummary",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/find",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/create",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/delete",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/update",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/updateApiKey",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/enable",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/disable",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/muteAll",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/unmuteAll",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/muteAlert",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/unmuteAlert",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/alert/get",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/alert/find",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/alert/update",
|
||||
"alerting:1.0.0-zeta1:readonly-alert-type/my-feature/rule/get",
|
||||
"alerting:1.0.0-zeta1:readonly-alert-type/my-feature/rule/getRuleState",
|
||||
"alerting:1.0.0-zeta1:readonly-alert-type/my-feature/rule/getAlertSummary",
|
||||
"alerting:1.0.0-zeta1:readonly-alert-type/my-feature/rule/find",
|
||||
"alerting:1.0.0-zeta1:readonly-alert-type/my-feature/alert/get",
|
||||
"alerting:1.0.0-zeta1:readonly-alert-type/my-feature/alert/find",
|
||||
]
|
||||
`);
|
||||
Array [
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/alert/get",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/alert/find",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/alert/update",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
test('grants `all` privileges to rules and alerts under feature consumer', () => {
|
||||
const actions = new Actions(version);
|
||||
const alertingFeaturePrivileges = new FeaturePrivilegeAlertingBuilder(actions);
|
||||
|
||||
const privilege: FeatureKibanaPrivileges = {
|
||||
alerting: {
|
||||
rule: {
|
||||
all: ['alert-type'],
|
||||
read: [],
|
||||
},
|
||||
alert: {
|
||||
all: ['alert-type'],
|
||||
read: [],
|
||||
},
|
||||
},
|
||||
|
||||
savedObject: {
|
||||
all: [],
|
||||
read: [],
|
||||
},
|
||||
ui: [],
|
||||
};
|
||||
|
||||
const feature = new KibanaFeature({
|
||||
id: 'my-feature',
|
||||
name: 'my-feature',
|
||||
app: [],
|
||||
category: { id: 'foo', label: 'foo' },
|
||||
privileges: {
|
||||
all: privilege,
|
||||
read: privilege,
|
||||
},
|
||||
});
|
||||
|
||||
expect(alertingFeaturePrivileges.getActions(privilege, feature)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/get",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/getRuleState",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/getAlertSummary",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/find",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/create",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/delete",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/update",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/updateApiKey",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/enable",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/disable",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/muteAll",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/unmuteAll",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/muteAlert",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/unmuteAlert",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/alert/get",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/alert/find",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/alert/update",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
test('grants both `all` and `read` to rules privileges under feature consumer', () => {
|
||||
const actions = new Actions(version);
|
||||
const alertingFeaturePrivileges = new FeaturePrivilegeAlertingBuilder(actions);
|
||||
|
||||
const privilege: FeatureKibanaPrivileges = {
|
||||
alerting: {
|
||||
rule: {
|
||||
all: ['alert-type'],
|
||||
read: ['readonly-alert-type'],
|
||||
},
|
||||
},
|
||||
|
||||
savedObject: {
|
||||
all: [],
|
||||
read: [],
|
||||
},
|
||||
ui: [],
|
||||
};
|
||||
|
||||
const feature = new KibanaFeature({
|
||||
id: 'my-feature',
|
||||
name: 'my-feature',
|
||||
app: [],
|
||||
category: { id: 'foo', label: 'foo' },
|
||||
privileges: {
|
||||
all: privilege,
|
||||
read: privilege,
|
||||
},
|
||||
});
|
||||
|
||||
expect(alertingFeaturePrivileges.getActions(privilege, feature)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/get",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/getRuleState",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/getAlertSummary",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/find",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/create",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/delete",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/update",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/updateApiKey",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/enable",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/disable",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/muteAll",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/unmuteAll",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/muteAlert",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/unmuteAlert",
|
||||
"alerting:1.0.0-zeta1:readonly-alert-type/my-feature/rule/get",
|
||||
"alerting:1.0.0-zeta1:readonly-alert-type/my-feature/rule/getRuleState",
|
||||
"alerting:1.0.0-zeta1:readonly-alert-type/my-feature/rule/getAlertSummary",
|
||||
"alerting:1.0.0-zeta1:readonly-alert-type/my-feature/rule/find",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
test('grants both `all` and `read` to alerts privileges under feature consumer', () => {
|
||||
const actions = new Actions(version);
|
||||
const alertingFeaturePrivileges = new FeaturePrivilegeAlertingBuilder(actions);
|
||||
|
||||
const privilege: FeatureKibanaPrivileges = {
|
||||
alerting: {
|
||||
alert: {
|
||||
all: ['alert-type'],
|
||||
read: ['readonly-alert-type'],
|
||||
},
|
||||
},
|
||||
|
||||
savedObject: {
|
||||
all: [],
|
||||
read: [],
|
||||
},
|
||||
ui: [],
|
||||
};
|
||||
|
||||
const feature = new KibanaFeature({
|
||||
id: 'my-feature',
|
||||
name: 'my-feature',
|
||||
app: [],
|
||||
category: { id: 'foo', label: 'foo' },
|
||||
privileges: {
|
||||
all: privilege,
|
||||
read: privilege,
|
||||
},
|
||||
});
|
||||
|
||||
expect(alertingFeaturePrivileges.getActions(privilege, feature)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/alert/get",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/alert/find",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/alert/update",
|
||||
"alerting:1.0.0-zeta1:readonly-alert-type/my-feature/alert/get",
|
||||
"alerting:1.0.0-zeta1:readonly-alert-type/my-feature/alert/find",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
test('grants both `all` and `read` to rules and alerts privileges under feature consumer', () => {
|
||||
const actions = new Actions(version);
|
||||
const alertingFeaturePrivileges = new FeaturePrivilegeAlertingBuilder(actions);
|
||||
|
||||
const privilege: FeatureKibanaPrivileges = {
|
||||
alerting: {
|
||||
rule: {
|
||||
all: ['alert-type'],
|
||||
read: ['readonly-alert-type'],
|
||||
},
|
||||
alert: {
|
||||
all: ['another-alert-type'],
|
||||
read: ['readonly-alert-type'],
|
||||
},
|
||||
},
|
||||
|
||||
savedObject: {
|
||||
all: [],
|
||||
read: [],
|
||||
},
|
||||
ui: [],
|
||||
};
|
||||
|
||||
const feature = new KibanaFeature({
|
||||
id: 'my-feature',
|
||||
name: 'my-feature',
|
||||
app: [],
|
||||
category: { id: 'foo', label: 'foo' },
|
||||
privileges: {
|
||||
all: privilege,
|
||||
read: privilege,
|
||||
},
|
||||
});
|
||||
|
||||
expect(alertingFeaturePrivileges.getActions(privilege, feature)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/get",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/getRuleState",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/getAlertSummary",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/find",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/create",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/delete",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/update",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/updateApiKey",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/enable",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/disable",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/muteAll",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/unmuteAll",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/muteAlert",
|
||||
"alerting:1.0.0-zeta1:alert-type/my-feature/rule/unmuteAlert",
|
||||
"alerting:1.0.0-zeta1:readonly-alert-type/my-feature/rule/get",
|
||||
"alerting:1.0.0-zeta1:readonly-alert-type/my-feature/rule/getRuleState",
|
||||
"alerting:1.0.0-zeta1:readonly-alert-type/my-feature/rule/getAlertSummary",
|
||||
"alerting:1.0.0-zeta1:readonly-alert-type/my-feature/rule/find",
|
||||
"alerting:1.0.0-zeta1:another-alert-type/my-feature/alert/get",
|
||||
"alerting:1.0.0-zeta1:another-alert-type/my-feature/alert/find",
|
||||
"alerting:1.0.0-zeta1:another-alert-type/my-feature/alert/update",
|
||||
"alerting:1.0.0-zeta1:readonly-alert-type/my-feature/alert/get",
|
||||
"alerting:1.0.0-zeta1:readonly-alert-type/my-feature/alert/find",
|
||||
]
|
||||
`);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -5,22 +5,22 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { uniq } from 'lodash';
|
||||
import { get, uniq } from 'lodash';
|
||||
|
||||
import type { FeatureKibanaPrivileges, KibanaFeature } from '../../../../../features/server';
|
||||
import { BaseFeaturePrivilegeBuilder } from './feature_privilege_builder';
|
||||
|
||||
enum AlertingType {
|
||||
enum AlertingEntity {
|
||||
RULE = 'rule',
|
||||
ALERT = 'alert',
|
||||
}
|
||||
|
||||
const readOperations: Record<AlertingType, string[]> = {
|
||||
const readOperations: Record<AlertingEntity, string[]> = {
|
||||
rule: ['get', 'getRuleState', 'getAlertSummary', 'find'],
|
||||
alert: ['get', 'find'],
|
||||
};
|
||||
|
||||
const writeOperations: Record<AlertingType, string[]> = {
|
||||
const writeOperations: Record<AlertingEntity, string[]> = {
|
||||
rule: [
|
||||
'create',
|
||||
'delete',
|
||||
|
@ -35,7 +35,7 @@ const writeOperations: Record<AlertingType, string[]> = {
|
|||
],
|
||||
alert: ['update'],
|
||||
};
|
||||
const allOperations: Record<AlertingType, string[]> = {
|
||||
const allOperations: Record<AlertingEntity, string[]> = {
|
||||
rule: [...readOperations.rule, ...writeOperations.rule],
|
||||
alert: [...readOperations.alert, ...writeOperations.alert],
|
||||
};
|
||||
|
@ -46,21 +46,30 @@ export class FeaturePrivilegeAlertingBuilder extends BaseFeaturePrivilegeBuilder
|
|||
feature: KibanaFeature
|
||||
): string[] {
|
||||
const getAlertingPrivilege = (
|
||||
operations: Record<AlertingType, string[]>,
|
||||
operations: string[],
|
||||
privilegedTypes: readonly string[],
|
||||
alertingEntity: string,
|
||||
consumer: string
|
||||
) =>
|
||||
privilegedTypes.flatMap((privilegedType) =>
|
||||
Object.values(AlertingType).flatMap((alertingType) =>
|
||||
operations[alertingType].map((operation) =>
|
||||
this.actions.alerting.get(privilegedType, consumer, alertingType, operation)
|
||||
)
|
||||
privilegedTypes.flatMap((type) =>
|
||||
operations.map((operation) =>
|
||||
this.actions.alerting.get(type, consumer, alertingEntity, operation)
|
||||
)
|
||||
);
|
||||
|
||||
const getPrivilegesForEntity = (entity: AlertingEntity) => {
|
||||
const all = get(privilegeDefinition.alerting, `${entity}.all`) ?? [];
|
||||
const read = get(privilegeDefinition.alerting, `${entity}.read`) ?? [];
|
||||
|
||||
return uniq([
|
||||
...getAlertingPrivilege(allOperations[entity], all, entity, feature.id),
|
||||
...getAlertingPrivilege(readOperations[entity], read, entity, feature.id),
|
||||
]);
|
||||
};
|
||||
|
||||
return uniq([
|
||||
...getAlertingPrivilege(allOperations, privilegeDefinition.alerting?.all ?? [], feature.id),
|
||||
...getAlertingPrivilege(readOperations, privilegeDefinition.alerting?.read ?? [], feature.id),
|
||||
...getPrivilegesForEntity(AlertingEntity.RULE),
|
||||
...getPrivilegesForEntity(AlertingEntity.ALERT),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -239,7 +239,12 @@ export class Plugin implements IPlugin<PluginSetup, PluginStart, SetupPlugins, S
|
|||
read: ['config'],
|
||||
},
|
||||
alerting: {
|
||||
all: [SIGNALS_ID, NOTIFICATIONS_ID],
|
||||
rule: {
|
||||
all: [SIGNALS_ID, NOTIFICATIONS_ID],
|
||||
},
|
||||
alert: {
|
||||
all: [SIGNALS_ID, NOTIFICATIONS_ID],
|
||||
},
|
||||
},
|
||||
management: {
|
||||
insightsAndAlerting: ['triggersActions'],
|
||||
|
@ -261,7 +266,12 @@ export class Plugin implements IPlugin<PluginSetup, PluginStart, SetupPlugins, S
|
|||
],
|
||||
},
|
||||
alerting: {
|
||||
read: [SIGNALS_ID, NOTIFICATIONS_ID],
|
||||
rule: {
|
||||
read: [SIGNALS_ID, NOTIFICATIONS_ID],
|
||||
},
|
||||
alert: {
|
||||
read: [SIGNALS_ID, NOTIFICATIONS_ID],
|
||||
},
|
||||
},
|
||||
management: {
|
||||
insightsAndAlerting: ['triggersActions'],
|
||||
|
|
|
@ -20,9 +20,11 @@ describe('Stack Alerts Feature Privileges', () => {
|
|||
const featuresSetup = featuresPluginMock.createSetup();
|
||||
await plugin.setup(coreSetup, { alerting: alertingSetup, features: featuresSetup });
|
||||
|
||||
const typesInFeaturePrivilege = BUILT_IN_ALERTS_FEATURE.alerting;
|
||||
const typesInFeaturePrivilegeAll = BUILT_IN_ALERTS_FEATURE.privileges.all.alerting.all;
|
||||
const typesInFeaturePrivilegeRead = BUILT_IN_ALERTS_FEATURE.privileges.read.alerting.read;
|
||||
const typesInFeaturePrivilege = BUILT_IN_ALERTS_FEATURE.alerting ?? [];
|
||||
const typesInFeaturePrivilegeAll =
|
||||
BUILT_IN_ALERTS_FEATURE.privileges?.all?.alerting?.rule?.all ?? [];
|
||||
const typesInFeaturePrivilegeRead =
|
||||
BUILT_IN_ALERTS_FEATURE.privileges?.read?.alerting?.rule?.read ?? [];
|
||||
expect(alertingSetup.registerType.mock.calls.length).toEqual(typesInFeaturePrivilege.length);
|
||||
expect(alertingSetup.registerType.mock.calls.length).toEqual(typesInFeaturePrivilegeAll.length);
|
||||
expect(alertingSetup.registerType.mock.calls.length).toEqual(
|
||||
|
|
|
@ -6,13 +6,14 @@
|
|||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { KibanaFeatureConfig } from '../../../plugins/features/common';
|
||||
import { ID as IndexThreshold } from './alert_types/index_threshold/alert_type';
|
||||
import { GEO_CONTAINMENT_ID as GeoContainment } from './alert_types/geo_containment/alert_type';
|
||||
import { ES_QUERY_ID as ElasticsearchQuery } from './alert_types/es_query/alert_type';
|
||||
import { STACK_ALERTS_FEATURE_ID } from '../common';
|
||||
import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/server';
|
||||
|
||||
export const BUILT_IN_ALERTS_FEATURE = {
|
||||
export const BUILT_IN_ALERTS_FEATURE: KibanaFeatureConfig = {
|
||||
id: STACK_ALERTS_FEATURE_ID,
|
||||
name: i18n.translate('xpack.stackAlerts.featureRegistry.actionsFeatureName', {
|
||||
defaultMessage: 'Stack Rules',
|
||||
|
@ -31,8 +32,12 @@ export const BUILT_IN_ALERTS_FEATURE = {
|
|||
insightsAndAlerting: ['triggersActions'],
|
||||
},
|
||||
alerting: {
|
||||
all: [IndexThreshold, GeoContainment, ElasticsearchQuery],
|
||||
read: [],
|
||||
rule: {
|
||||
all: [IndexThreshold, GeoContainment, ElasticsearchQuery],
|
||||
},
|
||||
alert: {
|
||||
all: [IndexThreshold, GeoContainment, ElasticsearchQuery],
|
||||
},
|
||||
},
|
||||
savedObject: {
|
||||
all: [],
|
||||
|
@ -48,8 +53,12 @@ export const BUILT_IN_ALERTS_FEATURE = {
|
|||
insightsAndAlerting: ['triggersActions'],
|
||||
},
|
||||
alerting: {
|
||||
all: [],
|
||||
read: [IndexThreshold, GeoContainment, ElasticsearchQuery],
|
||||
rule: {
|
||||
read: [IndexThreshold, GeoContainment, ElasticsearchQuery],
|
||||
},
|
||||
alert: {
|
||||
read: [IndexThreshold, GeoContainment, ElasticsearchQuery],
|
||||
},
|
||||
},
|
||||
savedObject: {
|
||||
all: [],
|
||||
|
|
|
@ -50,7 +50,12 @@ export const initServerWithKibana = (server: UptimeCoreSetup, plugins: UptimeCor
|
|||
read: [],
|
||||
},
|
||||
alerting: {
|
||||
all: ['xpack.uptime.alerts.tls', 'xpack.uptime.alerts.monitorStatus'],
|
||||
rule: {
|
||||
all: ['xpack.uptime.alerts.tls', 'xpack.uptime.alerts.monitorStatus'],
|
||||
},
|
||||
alert: {
|
||||
all: ['xpack.uptime.alerts.tls', 'xpack.uptime.alerts.monitorStatus'],
|
||||
},
|
||||
},
|
||||
management: {
|
||||
insightsAndAlerting: ['triggersActions'],
|
||||
|
@ -66,7 +71,12 @@ export const initServerWithKibana = (server: UptimeCoreSetup, plugins: UptimeCor
|
|||
read: [umDynamicSettings.name],
|
||||
},
|
||||
alerting: {
|
||||
read: ['xpack.uptime.alerts.tls', 'xpack.uptime.alerts.monitorStatus'],
|
||||
rule: {
|
||||
read: ['xpack.uptime.alerts.tls', 'xpack.uptime.alerts.monitorStatus'],
|
||||
},
|
||||
alert: {
|
||||
read: ['xpack.uptime.alerts.tls', 'xpack.uptime.alerts.monitorStatus'],
|
||||
},
|
||||
},
|
||||
management: {
|
||||
insightsAndAlerting: ['triggersActions'],
|
||||
|
|
|
@ -69,21 +69,23 @@ export class FixturePlugin implements Plugin<void, void, FixtureSetupDeps, Fixtu
|
|||
read: [],
|
||||
},
|
||||
alerting: {
|
||||
all: [
|
||||
'test.always-firing',
|
||||
'test.cumulative-firing',
|
||||
'test.never-firing',
|
||||
'test.failing',
|
||||
'test.authorization',
|
||||
'test.validation',
|
||||
'test.onlyContextVariables',
|
||||
'test.onlyStateVariables',
|
||||
'test.noop',
|
||||
'test.unrestricted-noop',
|
||||
'test.patternFiring',
|
||||
'test.throw',
|
||||
'test.longRunning',
|
||||
],
|
||||
rule: {
|
||||
all: [
|
||||
'test.always-firing',
|
||||
'test.cumulative-firing',
|
||||
'test.never-firing',
|
||||
'test.failing',
|
||||
'test.authorization',
|
||||
'test.validation',
|
||||
'test.onlyContextVariables',
|
||||
'test.onlyStateVariables',
|
||||
'test.noop',
|
||||
'test.unrestricted-noop',
|
||||
'test.patternFiring',
|
||||
'test.throw',
|
||||
'test.longRunning',
|
||||
],
|
||||
},
|
||||
},
|
||||
ui: [],
|
||||
},
|
||||
|
@ -94,21 +96,23 @@ export class FixturePlugin implements Plugin<void, void, FixtureSetupDeps, Fixtu
|
|||
read: ['alert'],
|
||||
},
|
||||
alerting: {
|
||||
read: [
|
||||
'test.always-firing',
|
||||
'test.cumulative-firing',
|
||||
'test.never-firing',
|
||||
'test.failing',
|
||||
'test.authorization',
|
||||
'test.validation',
|
||||
'test.onlyContextVariables',
|
||||
'test.onlyStateVariables',
|
||||
'test.noop',
|
||||
'test.unrestricted-noop',
|
||||
'test.patternFiring',
|
||||
'test.throw',
|
||||
'test.longRunning',
|
||||
],
|
||||
rule: {
|
||||
read: [
|
||||
'test.always-firing',
|
||||
'test.cumulative-firing',
|
||||
'test.never-firing',
|
||||
'test.failing',
|
||||
'test.authorization',
|
||||
'test.validation',
|
||||
'test.onlyContextVariables',
|
||||
'test.onlyStateVariables',
|
||||
'test.noop',
|
||||
'test.unrestricted-noop',
|
||||
'test.patternFiring',
|
||||
'test.throw',
|
||||
'test.longRunning',
|
||||
],
|
||||
},
|
||||
},
|
||||
ui: [],
|
||||
},
|
||||
|
|
|
@ -38,7 +38,9 @@ export class FixturePlugin implements Plugin<void, void, FixtureSetupDeps, Fixtu
|
|||
read: [],
|
||||
},
|
||||
alerting: {
|
||||
all: ['test.restricted-noop', 'test.unrestricted-noop', 'test.noop'],
|
||||
rule: {
|
||||
all: ['test.restricted-noop', 'test.unrestricted-noop', 'test.noop'],
|
||||
},
|
||||
},
|
||||
ui: [],
|
||||
},
|
||||
|
@ -49,7 +51,9 @@ export class FixturePlugin implements Plugin<void, void, FixtureSetupDeps, Fixtu
|
|||
read: [],
|
||||
},
|
||||
alerting: {
|
||||
read: ['test.restricted-noop', 'test.unrestricted-noop', 'test.noop'],
|
||||
rule: {
|
||||
read: ['test.restricted-noop', 'test.unrestricted-noop', 'test.noop'],
|
||||
},
|
||||
},
|
||||
ui: [],
|
||||
},
|
||||
|
|
|
@ -95,7 +95,9 @@ export class AlertingFixturePlugin implements Plugin<void, void, AlertingExample
|
|||
privileges: {
|
||||
all: {
|
||||
alerting: {
|
||||
all: ['test.always-firing', 'test.noop', 'test.failing'],
|
||||
rule: {
|
||||
all: ['test.always-firing', 'test.noop', 'test.failing'],
|
||||
},
|
||||
},
|
||||
savedObject: {
|
||||
all: [],
|
||||
|
@ -105,7 +107,9 @@ export class AlertingFixturePlugin implements Plugin<void, void, AlertingExample
|
|||
},
|
||||
read: {
|
||||
alerting: {
|
||||
all: ['test.always-firing', 'test.noop', 'test.failing'],
|
||||
rule: {
|
||||
all: ['test.always-firing', 'test.noop', 'test.failing'],
|
||||
},
|
||||
},
|
||||
savedObject: {
|
||||
all: [],
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue