Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[RAC] [RBAC] Adds bulk update route to rule registry and bulk update function to alerts client #106297

Merged
merged 9 commits into from
Aug 9, 2021
2 changes: 2 additions & 0 deletions packages/kbn-rule-data-utils/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@ NPM_MODULE_EXTRA_FILES = [
]

SRC_DEPS = [
"//packages/kbn-es-query",
"@npm//tslib",
"@npm//utility-types",
"@npm//@elastic/elasticsearch",
]

TYPES_DEPS = [
Expand Down
58 changes: 58 additions & 0 deletions packages/kbn-rule-data-utils/src/alerts_as_data_rbac.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
* Side Public License, v 1.
*/

import type { estypes } from '@elastic/elasticsearch';
import type { EsQueryConfig } from '@kbn/es-query';

/**
* registering a new instance of the rule data client
* in a new plugin will require updating the below data structure
Expand All @@ -24,6 +27,7 @@ export const AlertConsumers = {
SYNTHETICS: 'synthetics',
} as const;
export type AlertConsumers = typeof AlertConsumers[keyof typeof AlertConsumers];
export type STATUS_VALUES = 'open' | 'acknowledged' | 'closed';

export const mapConsumerToIndexName: Record<AlertConsumers, string | string[]> = {
apm: '.alerts-observability-apm',
Expand All @@ -38,3 +42,57 @@ export type ValidFeatureId = keyof typeof mapConsumerToIndexName;
export const validFeatureIds = Object.keys(mapConsumerToIndexName);
export const isValidFeatureId = (a: unknown): a is ValidFeatureId =>
typeof a === 'string' && validFeatureIds.includes(a);

/**
* Prevent javascript from returning Number.MAX_SAFE_INTEGER when Elasticsearch expects
* Java's Long.MAX_VALUE. This happens when sorting fields by date which are
* unmapped in the provided index
*
* Ref: https://github.com/elastic/elasticsearch/issues/28806#issuecomment-369303620
*
* return stringified Long.MAX_VALUE if we receive Number.MAX_SAFE_INTEGER
* @param sortIds estypes.SearchSortResults | undefined
* @returns SortResults
*/
export const getSafeSortIds = (sortIds: estypes.SearchSortResults | null | undefined) => {
if (sortIds == null) {
return sortIds;
}
return sortIds.map((sortId) => {
// haven't determined when we would receive a null value for a sort id
// but in case we do, default to sending the stringified Java max_int
if (sortId == null || sortId === '' || sortId >= Number.MAX_SAFE_INTEGER) {
return '9223372036854775807';
}
return sortId;
});
};

interface GetEsQueryConfigParamType {
allowLeadingWildcards?: EsQueryConfig['allowLeadingWildcards'];
queryStringOptions?: EsQueryConfig['queryStringOptions'];
ignoreFilterIfFieldNotInIndex?: EsQueryConfig['ignoreFilterIfFieldNotInIndex'];
dateFormatTZ?: EsQueryConfig['dateFormatTZ'];
}

type ConfigKeys = keyof GetEsQueryConfigParamType;

export const getEsQueryConfig = (params?: GetEsQueryConfigParamType): EsQueryConfig => {
const defaultConfigValues = {
allowLeadingWildcards: true,
queryStringOptions: { analyze_wildcard: true },
ignoreFilterIfFieldNotInIndex: false,
dateFormatTZ: 'Zulu',
};
if (params == null) {
return defaultConfigValues;
}
const paramKeysWithValues = Object.keys(params).reduce((acc: EsQueryConfig, key) => {
const configKey = key as ConfigKeys;
if (params[configKey] != null) {
return { [key]: params[configKey], ...acc };
}
return { [key]: defaultConfigValues[configKey], ...acc };
}, {} as EsQueryConfig);
return paramKeysWithValues;
};
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const createAlertingAuthorizationMock = () => {
const mocked: AlertingAuthorizationMock = {
ensureAuthorized: jest.fn(),
filterByRuleTypeAuthorization: jest.fn(),
getAuthorizationFilter: jest.fn(),
getFindAuthorizationFilter: jest.fn(),
getAugmentedRuleTypesWithAuthorization: jest.fn(),
getSpaceId: jest.fn(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -281,11 +281,23 @@ export class AlertingAuthorization {
filter?: KueryNode | JsonObject;
ensureRuleTypeIsAuthorized: (ruleTypeId: string, consumer: string, auth: string) => void;
logSuccessfulAuthorization: () => void;
}> {
return this.getAuthorizationFilter(authorizationEntity, filterOpts, ReadOperations.Find);
}

public async getAuthorizationFilter(
authorizationEntity: AlertingAuthorizationEntity,
filterOpts: AlertingAuthorizationFilterOpts,
operation: WriteOperations | ReadOperations
): Promise<{
filter?: KueryNode | JsonObject;
ensureRuleTypeIsAuthorized: (ruleTypeId: string, consumer: string, auth: string) => void;
logSuccessfulAuthorization: () => void;
}> {
if (this.authorization && this.shouldCheckAuthorization()) {
const { username, authorizedRuleTypes } = await this.augmentRuleTypesWithAuthorization(
this.ruleTypeRegistry.list(),
[ReadOperations.Find],
[operation],
authorizationEntity
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ const alert: Alert = {
'rule.name': ['Latency threshold | frontend-rum'],
[ALERT_DURATION]: [62879000],
[ALERT_STATUS]: ['open'],
[SPACE_IDS]: ['myfakespaceid'],
tags: ['apm', 'service.name:frontend-rum'],
'transaction.type': ['page-load'],
[ALERT_PRODUCER]: ['apm'],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ Alerts as data client API Interface

### Interfaces

- [BulkUpdateOptions](interfaces/bulkupdateoptions.md)
- [ConstructorOptions](interfaces/constructoroptions.md)
- [UpdateOptions](interfaces/updateoptions.md)
Loading