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

[8.x] Authorized route migration for routes owned by kibana-security (#198380) #198657

Merged
merged 1 commit into from
Nov 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ describe('GET all roles by space id', () => {

const paramsSchema = (config.validate as any).params;

expect(config.options).toEqual({ tags: ['access:manageSpaces'] });
expect(config.security?.authz).toEqual({ requiredPrivileges: ['manage_spaces'] });
expect(() => paramsSchema.validate({})).toThrowErrorMatchingInlineSnapshot(
`"[spaceId]: expected value of type [string] but got [undefined]"`
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ export function defineGetAllRolesBySpaceRoutes({
router.get(
{
path: '/internal/security/roles/{spaceId}',
options: {
tags: ['access:manageSpaces'],
security: {
authz: {
requiredPrivileges: ['manage_spaces'],
},
},
validate: {
params: schema.object({ spaceId: schema.string({ minLength: 1 }) }),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,10 @@ describe('Invalidate sessions routes', () => {
expect(routeConfig.options).toEqual({
access: 'public',
summary: 'Invalidate user sessions',
tags: ['access:sessionManagement'],
});

expect(routeConfig.security?.authz).toEqual({ requiredPrivileges: ['sessionManagement'] });

const bodySchema = (routeConfig.validate as any).body as ObjectType;
expect(() => bodySchema.validate({})).toThrowErrorMatchingInlineSnapshot(
`"[match]: expected at least one defined value but got [undefined]"`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,19 @@ export function defineInvalidateSessionsRoutes({
),
}),
},
security: {
authz: {
requiredPrivileges: ['sessionManagement'],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: just for my understanding, I see we renamed access:manageSpaces to manage_spaces, but access:sessionManagement stayed as sessionManagement, is it intentional?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably, we just forgot to rename it too, there should consistency between naming

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Created an issue for that #198716

},
},
options: {
// The invalidate session API was introduced to address situations where the session index
// could grow rapidly - when session timeouts are disabled, or with anonymous access.
// In the serverless environment, sessions timeouts are always be enabled, and there is no
// anonymous access. However, keeping this endpoint available internally in serverless would
// be useful in situations where we need to batch-invalidate user sessions.
access: buildFlavor === 'serverless' ? 'internal' : 'public',
tags: ['access:sessionManagement'],

summary: `Invalidate user sessions`,
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ describe('Bulk get profile routes', () => {
});

it('correctly defines route.', () => {
expect(routeConfig.options).toEqual({ tags: ['access:bulkGetUserProfiles'] });
expect(routeConfig.security?.authz).toEqual({ requiredPrivileges: ['bulkGetUserProfiles'] });

const bodySchema = (routeConfig.validate as any).body as ObjectType;
expect(() => bodySchema.validate(0)).toThrowErrorMatchingInlineSnapshot(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@ export function defineBulkGetUserProfilesRoute({
dataPath: schema.maybe(schema.string()),
}),
},
options: { tags: ['access:bulkGetUserProfiles'] },
security: {
authz: {
requiredPrivileges: ['bulkGetUserProfiles'],
},
},
},
createLicensedRouteHandler(async (context, request, response) => {
const userProfileServiceInternal = getUserProfileService();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,14 @@ export function initCopyToSpacesApi(deps: ExternalRouteDeps) {
router.post(
{
path: '/api/spaces/_copy_saved_objects',
security: {
authz: {
requiredPrivileges: ['copySavedObjectsToSpaces'],
},
},
options: {
access: isServerless ? 'internal' : 'public',
tags: ['access:copySavedObjectsToSpaces', 'oas-tag:spaces'],
tags: ['oas-tag:spaces'],
summary: `Copy saved objects between spaces`,
description:
'It also allows you to automatically copy related objects, so when you copy a dashboard, this can automatically copy over the associated visualizations, data views, and saved searches, as required. You can request to overwrite any objects that already exist in the target space if they share an identifier or you can use the resolve copy saved objects conflicts API to do this on a per-object basis.',
Expand Down Expand Up @@ -188,9 +193,14 @@ export function initCopyToSpacesApi(deps: ExternalRouteDeps) {
router.post(
{
path: '/api/spaces/_resolve_copy_saved_objects_errors',
security: {
authz: {
requiredPrivileges: ['copySavedObjectsToSpaces'],
},
},
options: {
access: isServerless ? 'internal' : 'public',
tags: ['access:copySavedObjectsToSpaces'],

summary: `Resolve conflicts copying saved objects`,
description:
'Overwrite saved objects that are returned as errors from the copy saved objects to space API.',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ describe('GET /internal/spaces/{spaceId}/content_summary', () => {

const paramsSchema = (config.validate as any).params;

expect(config.options).toEqual({ tags: ['access:manageSpaces'] });
expect(config.security?.authz).toEqual({ requiredPrivileges: ['manage_spaces'] });
expect(() => paramsSchema.validate({})).toThrowErrorMatchingInlineSnapshot(
`"[spaceId]: expected value of type [string] but got [undefined]"`
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,10 @@ export function initGetSpaceContentSummaryApi(deps: InternalRouteDeps) {
router.get(
{
path: '/internal/spaces/{spaceId}/content_summary',
options: {
tags: ['access:manageSpaces'],
security: {
authz: {
requiredPrivileges: ['manage_spaces'],
},
},
validate: {
params: schema.object({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,8 @@ export function copyToSpaceTestSuiteFactory(context: FtrProviderContext) {
expect(resp.body).to.eql({
statusCode: 403,
error: 'Forbidden',
message: 'Forbidden',
message:
'API [POST /api/spaces/_copy_saved_objects] is unauthorized for user, this action is granted by the Kibana privileges [copySavedObjectsToSpaces]',
});
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,8 @@ export function resolveCopyToSpaceConflictsSuite(context: FtrProviderContext) {
expect(resp.body).to.eql({
statusCode: 403,
error: 'Forbidden',
message: 'Forbidden',
message:
'API [POST /api/spaces/_resolve_copy_saved_objects_errors] is unauthorized for user, this action is granted by the Kibana privileges [copySavedObjectsToSpaces]',
});
};

Expand Down