Fix checkPrivilege to query with indicies (#214002)

## Summary
`apmIndices` has the form: 
```
  "transaction": "traces-apm*,apm-*,traces-*.otel-*",
  "span": "traces-apm*,apm-*,traces-*.otel-*",
  "error": "logs-apm*,apm-*,logs-*.otel-*",
  "metric": "metrics-apm*,apm-*,metrics-*.otel-*",
  "onboarding": "apm-*",
  "sourcemap": "apm-*"
```

`mapValues(apmIndices, () => ['read']),` was producing an object that
looked like :
```
{
  "transaction": [
    "read"
  ],
  "span": [
    "read"
  ],
  "error": [
    "read"
  ],
  "metric": [
    "read"
  ],
  "onboarding": [
    "read"
  ],
  "sourcemap": [
    "read"
  ]
}
```

It seems this ought to check privileges on the actual indices, so this
PR restructures the `index` parameter to this :
 
```
{
  "traces-apm*": [
    "read"
  ],
  "apm-*": [
    "read"
  ],
  "traces-*.otel-*": [
    "read"
  ],
  "logs-apm*": [
    "read"
  ],
  "logs-*.otel-*": [
    "read"
  ],
  "metrics-apm*": [
    "read"
  ],
  "metrics-*.otel-*": [
    "read"
  ]
```

### Checklist

Check the PR satisfies following conditions. 

Reviewers should verify this PR satisfies this list as well.



- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios

- [x] The PR description includes the appropriate Release Notes section,
and the correct `release_note:*` label is applied per the
[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)
This commit is contained in:
Bryce Buchanan 2025-03-14 09:10:05 -07:00 committed by GitHub
parent 7e8d0c61cc
commit 3df90c8f2a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 48 additions and 8 deletions

View file

@ -0,0 +1,32 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { convertIndiciesToPrivilege } from './check_privileges';
describe('test CheckPrivileges', () => {
it('shourp properly convert apmIndices to privilege format', () => {
const apmIndices = {
transaction: 'traces-apm*,apm-*,traces-*.otel-*',
span: 'traces-apm*,apm-*,traces-*.otel-*',
error: 'logs-apm*,apm-*,logs-*.otel-*',
metric: 'metrics-apm*,apm-*,metrics-*.otel-*',
onboarding: 'apm-*',
sourcemap: 'apm-*',
};
const expectedFormat = {
'traces-apm*': ['read'],
'apm-*': ['read'],
'traces-*.otel-*': ['read'],
'logs-apm*': ['read'],
'logs-*.otel-*': ['read'],
'metrics-apm*': ['read'],
'metrics-*.otel-*': ['read'],
};
const result = convertIndiciesToPrivilege(apmIndices);
expect(expectedFormat).toEqual(result);
});
});

View file

@ -7,13 +7,21 @@
import type { KibanaRequest } from '@kbn/core-http-server';
import type { SecurityPluginStart } from '@kbn/security-plugin-types-server';
import { mapValues } from 'lodash';
import type { APMIndices } from '..';
export interface ApmDataAccessPrivilegesCheck {
request: KibanaRequest;
security?: SecurityPluginStart;
getApmIndices: () => Promise<APMIndices>;
getApmIndices: (request: KibanaRequest) => Promise<APMIndices>;
}
export function convertIndiciesToPrivilege(apmIndices: APMIndices) {
return Object.values(apmIndices)
.map((value) => value.split(','))
.flat()
.reduce<Record<string, string[]>>((obj, item, index) => {
obj[item] = ['read'];
return obj;
}, {});
}
export async function checkPrivileges({
@ -27,16 +35,15 @@ export async function checkPrivileges({
}
const [apmIndices, checkPrivilegesFn] = await Promise.all([
getApmIndices(),
getApmIndices(request),
authorization.checkPrivilegesDynamicallyWithRequest(request),
]);
const { hasAllRequested } = await checkPrivilegesFn({
elasticsearch: {
cluster: [],
index: mapValues(apmIndices, () => ['read']),
index: convertIndiciesToPrivilege(apmIndices),
},
});
return hasAllRequested;
}

View file

@ -12,6 +12,7 @@ import type {
Plugin,
SavedObjectsClientContract,
Logger,
KibanaRequest,
} from '@kbn/core/server';
import type { APMDataAccessConfig } from '.';
import type {
@ -64,8 +65,8 @@ export class ApmDataAccessPlugin
this.logger.error(e);
});
const getApmIndicesWithInternalUserFn = async () => {
const soClient = core.savedObjects.createInternalRepository();
const getApmIndicesWithInternalUserFn = async (request: KibanaRequest) => {
const soClient = core.savedObjects.getScopedClient(request);
return this.getApmIndices(soClient);
};