mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
Decouple Authorization subsystem from Legacy API. (#52638)
This commit is contained in:
parent
f0eb4bb675
commit
7e27f0d35f
13 changed files with 37 additions and 37 deletions
|
@ -132,7 +132,6 @@ export const security = (kibana) => new kibana.Plugin({
|
|||
server.plugins.kibana.systemApi
|
||||
),
|
||||
cspRules: createCSPRuleString(config.get('csp.rules')),
|
||||
kibanaIndexName: config.get('kibana.index'),
|
||||
});
|
||||
|
||||
// Legacy xPack Info endpoint returns whatever we return in a callback for `registerLicenseCheckResultsGenerator`
|
||||
|
|
|
@ -48,7 +48,7 @@ describe('#atSpace', () => {
|
|||
const checkPrivilegesWithRequest = checkPrivilegesWithRequestFactory(
|
||||
mockActions,
|
||||
mockClusterClient,
|
||||
() => application
|
||||
application
|
||||
);
|
||||
const request = httpServerMock.createKibanaRequest();
|
||||
const checkPrivileges = checkPrivilegesWithRequest(request);
|
||||
|
@ -291,7 +291,7 @@ describe('#atSpaces', () => {
|
|||
const checkPrivilegesWithRequest = checkPrivilegesWithRequestFactory(
|
||||
mockActions,
|
||||
mockClusterClient,
|
||||
() => application
|
||||
application
|
||||
);
|
||||
const request = httpServerMock.createKibanaRequest();
|
||||
const checkPrivileges = checkPrivilegesWithRequest(request);
|
||||
|
@ -772,7 +772,7 @@ describe('#globally', () => {
|
|||
const checkPrivilegesWithRequest = checkPrivilegesWithRequestFactory(
|
||||
mockActions,
|
||||
mockClusterClient,
|
||||
() => application
|
||||
application
|
||||
);
|
||||
const request = httpServerMock.createKibanaRequest();
|
||||
const checkPrivileges = checkPrivilegesWithRequest(request);
|
||||
|
|
|
@ -61,7 +61,7 @@ export interface CheckPrivileges {
|
|||
export function checkPrivilegesWithRequestFactory(
|
||||
actions: CheckPrivilegesActions,
|
||||
clusterClient: IClusterClient,
|
||||
getApplicationName: () => string
|
||||
applicationName: string
|
||||
) {
|
||||
const hasIncompatibleVersion = (
|
||||
applicationPrivilegesResponse: HasPrivilegesResponseApplication
|
||||
|
@ -81,23 +81,24 @@ export function checkPrivilegesWithRequestFactory(
|
|||
: [privilegeOrPrivileges];
|
||||
const allApplicationPrivileges = uniq([actions.version, actions.login, ...privileges]);
|
||||
|
||||
const application = getApplicationName();
|
||||
const hasPrivilegesResponse = (await clusterClient
|
||||
.asScoped(request)
|
||||
.callAsCurrentUser('shield.hasPrivileges', {
|
||||
body: {
|
||||
applications: [{ application, resources, privileges: allApplicationPrivileges }],
|
||||
applications: [
|
||||
{ application: applicationName, resources, privileges: allApplicationPrivileges },
|
||||
],
|
||||
},
|
||||
})) as HasPrivilegesResponse;
|
||||
|
||||
validateEsPrivilegeResponse(
|
||||
hasPrivilegesResponse,
|
||||
application,
|
||||
applicationName,
|
||||
allApplicationPrivileges,
|
||||
resources
|
||||
);
|
||||
|
||||
const applicationPrivilegesResponse = hasPrivilegesResponse.application[application];
|
||||
const applicationPrivilegesResponse = hasPrivilegesResponse.application[applicationName];
|
||||
|
||||
if (hasIncompatibleVersion(applicationPrivilegesResponse)) {
|
||||
throw new Error(
|
||||
|
|
|
@ -8,12 +8,15 @@ import { Actions } from '.';
|
|||
import { AuthorizationMode } from './mode';
|
||||
|
||||
export const authorizationMock = {
|
||||
create: ({ version = 'mock-version' }: { version?: string } = {}) => ({
|
||||
create: ({
|
||||
version = 'mock-version',
|
||||
applicationName = 'mock-application',
|
||||
}: { version?: string; applicationName?: string } = {}) => ({
|
||||
actions: new Actions(version),
|
||||
checkPrivilegesWithRequest: jest.fn(),
|
||||
checkPrivilegesDynamicallyWithRequest: jest.fn(),
|
||||
checkSavedObjectsPrivilegesWithRequest: jest.fn(),
|
||||
getApplicationName: jest.fn().mockReturnValue('mock-application'),
|
||||
applicationName,
|
||||
mode: { useRbacForRequest: jest.fn() } as jest.Mocked<AuthorizationMode>,
|
||||
privileges: { get: jest.fn() },
|
||||
registerPrivilegesWithCluster: jest.fn(),
|
||||
|
|
|
@ -53,7 +53,6 @@ test(`returns exposed services`, () => {
|
|||
.fn()
|
||||
.mockReturnValue({ getSpaceId: jest.fn(), namespaceToSpaceId: jest.fn() });
|
||||
const mockFeaturesService = { getFeatures: () => [] };
|
||||
const mockGetLegacyAPI = () => ({ kibanaIndexName });
|
||||
const mockLicense = licenseMock.create();
|
||||
|
||||
const authz = setupAuthorization({
|
||||
|
@ -61,20 +60,20 @@ test(`returns exposed services`, () => {
|
|||
clusterClient: mockClusterClient,
|
||||
license: mockLicense,
|
||||
loggers: loggingServiceMock.create(),
|
||||
getLegacyAPI: mockGetLegacyAPI,
|
||||
kibanaIndexName,
|
||||
packageVersion: 'some-version',
|
||||
featuresService: mockFeaturesService,
|
||||
getSpacesService: mockGetSpacesService,
|
||||
});
|
||||
|
||||
expect(authz.actions.version).toBe('version:some-version');
|
||||
expect(authz.getApplicationName()).toBe(application);
|
||||
expect(authz.applicationName).toBe(application);
|
||||
|
||||
expect(authz.checkPrivilegesWithRequest).toBe(mockCheckPrivilegesWithRequest);
|
||||
expect(checkPrivilegesWithRequestFactory).toHaveBeenCalledWith(
|
||||
authz.actions,
|
||||
mockClusterClient,
|
||||
authz.getApplicationName
|
||||
authz.applicationName
|
||||
);
|
||||
|
||||
expect(authz.checkPrivilegesDynamicallyWithRequest).toBe(
|
||||
|
|
|
@ -12,7 +12,7 @@ import {
|
|||
IClusterClient,
|
||||
} from '../../../../../src/core/server';
|
||||
|
||||
import { FeaturesService, LegacyAPI, SpacesService } from '../plugin';
|
||||
import { FeaturesService, SpacesService } from '../plugin';
|
||||
import { Actions } from './actions';
|
||||
import { CheckPrivilegesWithRequest, checkPrivilegesWithRequestFactory } from './check_privileges';
|
||||
import {
|
||||
|
@ -43,7 +43,7 @@ interface SetupAuthorizationParams {
|
|||
license: SecurityLicense;
|
||||
loggers: LoggerFactory;
|
||||
featuresService: FeaturesService;
|
||||
getLegacyAPI(): Pick<LegacyAPI, 'kibanaIndexName'>;
|
||||
kibanaIndexName: string;
|
||||
getSpacesService(): SpacesService | undefined;
|
||||
}
|
||||
|
||||
|
@ -52,7 +52,7 @@ export interface Authorization {
|
|||
checkPrivilegesWithRequest: CheckPrivilegesWithRequest;
|
||||
checkPrivilegesDynamicallyWithRequest: CheckPrivilegesDynamicallyWithRequest;
|
||||
checkSavedObjectsPrivilegesWithRequest: CheckSavedObjectsPrivilegesWithRequest;
|
||||
getApplicationName: () => string;
|
||||
applicationName: string;
|
||||
mode: AuthorizationMode;
|
||||
privileges: PrivilegesService;
|
||||
disableUnauthorizedCapabilities: (
|
||||
|
@ -69,23 +69,23 @@ export function setupAuthorization({
|
|||
license,
|
||||
loggers,
|
||||
featuresService,
|
||||
getLegacyAPI,
|
||||
kibanaIndexName,
|
||||
getSpacesService,
|
||||
}: SetupAuthorizationParams): Authorization {
|
||||
const actions = new Actions(packageVersion);
|
||||
const mode = authorizationModeFactory(license);
|
||||
const getApplicationName = () => `${APPLICATION_PREFIX}${getLegacyAPI().kibanaIndexName}`;
|
||||
const applicationName = `${APPLICATION_PREFIX}${kibanaIndexName}`;
|
||||
const checkPrivilegesWithRequest = checkPrivilegesWithRequestFactory(
|
||||
actions,
|
||||
clusterClient,
|
||||
getApplicationName
|
||||
applicationName
|
||||
);
|
||||
const privileges = privilegesFactory(actions, featuresService);
|
||||
const logger = loggers.get('authorization');
|
||||
|
||||
const authz = {
|
||||
actions,
|
||||
getApplicationName,
|
||||
applicationName,
|
||||
checkPrivilegesWithRequest,
|
||||
checkPrivilegesDynamicallyWithRequest: checkPrivilegesDynamicallyWithRequestFactory(
|
||||
checkPrivilegesWithRequest,
|
||||
|
@ -123,7 +123,7 @@ export function setupAuthorization({
|
|||
registerPrivilegesWithCluster: async () => {
|
||||
validateFeaturePrivileges(actions, featuresService.getFeatures());
|
||||
|
||||
await registerPrivilegesWithCluster(logger, privileges, getApplicationName(), clusterClient);
|
||||
await registerPrivilegesWithCluster(logger, privileges, applicationName, clusterClient);
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { Subscription } from 'rxjs';
|
||||
import { Subscription, combineLatest } from 'rxjs';
|
||||
import { first } from 'rxjs/operators';
|
||||
import {
|
||||
IClusterClient,
|
||||
|
@ -42,7 +42,6 @@ export type FeaturesService = Pick<FeaturesSetupContract, 'getFeatures'>;
|
|||
*/
|
||||
export interface LegacyAPI {
|
||||
isSystemAPIRequest: (request: KibanaRequest) => boolean;
|
||||
kibanaIndexName: string;
|
||||
cspRules: string;
|
||||
savedObjects: SavedObjectsLegacyService<KibanaRequest | LegacyRequest>;
|
||||
auditLogger: {
|
||||
|
@ -121,7 +120,10 @@ export class Plugin {
|
|||
core: CoreSetup,
|
||||
{ features, licensing }: PluginSetupDependencies
|
||||
): Promise<RecursiveReadonly<PluginSetupContract>> {
|
||||
const config = await createConfig$(this.initializerContext, core.http.isTlsEnabled)
|
||||
const [config, legacyConfig] = await combineLatest([
|
||||
createConfig$(this.initializerContext, core.http.isTlsEnabled),
|
||||
this.initializerContext.config.legacy.globalConfig$,
|
||||
])
|
||||
.pipe(first())
|
||||
.toPromise();
|
||||
|
||||
|
@ -148,7 +150,7 @@ export class Plugin {
|
|||
clusterClient: this.clusterClient,
|
||||
license,
|
||||
loggers: this.initializerContext.logger,
|
||||
getLegacyAPI: this.getLegacyAPI,
|
||||
kibanaIndexName: legacyConfig.kibana.index,
|
||||
packageVersion: this.initializerContext.env.packageInfo.version,
|
||||
getSpacesService: this.getSpacesService,
|
||||
featuresService: features,
|
||||
|
|
|
@ -36,7 +36,7 @@ describe('GET role', () => {
|
|||
) => {
|
||||
test(description, async () => {
|
||||
const mockRouteDefinitionParams = routeDefinitionParamsMock.create();
|
||||
mockRouteDefinitionParams.authz.getApplicationName.mockReturnValue(application);
|
||||
mockRouteDefinitionParams.authz.applicationName = application;
|
||||
|
||||
const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient();
|
||||
mockRouteDefinitionParams.clusterClient.asScoped.mockReturnValue(mockScopedClusterClient);
|
||||
|
|
|
@ -28,7 +28,7 @@ export function defineGetRolesRoutes({ router, authz, clusterClient }: RouteDefi
|
|||
body: transformElasticsearchRoleToRole(
|
||||
elasticsearchRole,
|
||||
request.params.name,
|
||||
authz.getApplicationName()
|
||||
authz.applicationName
|
||||
),
|
||||
});
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ describe('GET all roles', () => {
|
|||
) => {
|
||||
test(description, async () => {
|
||||
const mockRouteDefinitionParams = routeDefinitionParamsMock.create();
|
||||
mockRouteDefinitionParams.authz.getApplicationName.mockReturnValue(application);
|
||||
mockRouteDefinitionParams.authz.applicationName = application;
|
||||
|
||||
const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient();
|
||||
mockRouteDefinitionParams.clusterClient.asScoped.mockReturnValue(mockScopedClusterClient);
|
||||
|
|
|
@ -22,11 +22,7 @@ export function defineGetAllRolesRoutes({ router, authz, clusterClient }: RouteD
|
|||
return response.ok({
|
||||
body: Object.entries(elasticsearchRoles)
|
||||
.map(([roleName, elasticsearchRole]) =>
|
||||
transformElasticsearchRoleToRole(
|
||||
elasticsearchRole,
|
||||
roleName,
|
||||
authz.getApplicationName()
|
||||
)
|
||||
transformElasticsearchRoleToRole(elasticsearchRole, roleName, authz.applicationName)
|
||||
)
|
||||
.sort((roleA, roleB) => {
|
||||
if (roleA.name < roleB.name) {
|
||||
|
|
|
@ -62,7 +62,7 @@ const putRoleTest = (
|
|||
) => {
|
||||
test(description, async () => {
|
||||
const mockRouteDefinitionParams = routeDefinitionParamsMock.create();
|
||||
mockRouteDefinitionParams.authz.getApplicationName.mockReturnValue(application);
|
||||
mockRouteDefinitionParams.authz.applicationName = application;
|
||||
mockRouteDefinitionParams.authz.privileges.get.mockReturnValue(privilegeMap);
|
||||
|
||||
const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient();
|
||||
|
|
|
@ -42,7 +42,7 @@ export function definePutRolesRoutes({ router, authz, clusterClient }: RouteDefi
|
|||
|
||||
const body = transformPutPayloadToElasticsearchRole(
|
||||
request.body,
|
||||
authz.getApplicationName(),
|
||||
authz.applicationName,
|
||||
rawRoles[name] ? rawRoles[name].applications : []
|
||||
);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue