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

Set spaces and roles CRUD APIs to public #193534

Merged
merged 32 commits into from
Oct 3, 2024
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
6c13264
Explicitly sets spaces and roles HTTP API endpoints access to public
jeramysoucy Sep 20, 2024
930acf4
Merge remote-tracking branch 'upstream/main' into set-serverless-publ…
jeramysoucy Sep 20, 2024
a4a640f
Updates API integration tests
jeramysoucy Sep 20, 2024
27d69d3
Updates roles api tests
jeramysoucy Sep 23, 2024
ecf8197
Uncomments test index files
jeramysoucy Sep 23, 2024
fbd920f
Uncomments management test index
jeramysoucy Sep 23, 2024
6cf4f86
Merge branch 'main' into set-serverless-public-apis
jeramysoucy Sep 23, 2024
f9b1e51
Removes unused constants
jeramysoucy Sep 23, 2024
3d813de
Use versioned router for public endpoints
jeramysoucy Sep 24, 2024
e319dcb
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine Sep 24, 2024
4d348d2
Merge branch 'main' into set-serverless-public-apis
jeramysoucy Sep 25, 2024
fe76a89
Merge branch 'main' into set-serverless-public-apis
jeramysoucy Sep 25, 2024
0aa971e
Adds version header to axios request in ftr roles util
jeramysoucy Sep 25, 2024
031c564
[CI] Auto-commit changed files from 'node scripts/notice'
kibanamachine Sep 25, 2024
34ef027
Merge branch 'main' into set-serverless-public-apis
jeramysoucy Sep 25, 2024
fe2e7eb
Adds version header to spaces FTR service axios config
jeramysoucy Sep 26, 2024
e9f5d63
Merge branch 'main' into set-serverless-public-apis
jeramysoucy Sep 26, 2024
68de9e8
Adds version to http calls from spaces manager
jeramysoucy Sep 27, 2024
15ea4df
Uses common def for api version
jeramysoucy Sep 27, 2024
262673d
Comments version prop of fetch options, removes "experimental"
jeramysoucy Sep 27, 2024
c85715a
Fixes typo
jeramysoucy Sep 27, 2024
5e42731
Adds versionResolution to FTR runTests
jeramysoucy Sep 27, 2024
df5a112
[CI] Auto-commit changed files from 'node scripts/notice'
kibanamachine Sep 27, 2024
2abd2e6
Removes commented code
jeramysoucy Sep 27, 2024
a8217e0
Merge branch 'main' into set-serverless-public-apis
jeramysoucy Sep 30, 2024
7e17054
Adds API version option to requests in the roles client and edit role…
jeramysoucy Sep 30, 2024
a855b6a
Merge branch 'main' into set-serverless-public-apis
jeramysoucy Sep 30, 2024
4de5ea8
Adds OAS tags
jeramysoucy Oct 2, 2024
8b4bf9f
Merge branch 'main' into set-serverless-public-apis
jeramysoucy Oct 3, 2024
9497dbf
Adds roles and spaces API paths to OAS doc script
jeramysoucy Oct 3, 2024
6ae6950
[CI] Auto-commit changed files from 'node scripts/capture_oas_snapsho…
kibanamachine Oct 3, 2024
b44b348
[CI] Auto-commit changed files from 'make api-docs && make api-docs-s…
kibanamachine Oct 3, 2024
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
5 changes: 4 additions & 1 deletion packages/core/http/core-http-browser/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,10 @@ export interface HttpFetchOptions extends HttpRequestInit {

context?: KibanaExecutionContext;

/** @experimental */
/**
* When defined, the API version string used to populate the ELASTIC_HTTP_VERSION_HEADER.
* Defaults to undefined.
*/
version?: ApiVersion;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,19 @@ export class Role {

public async create(name: string, role: any) {
this.log.debug(`creating role ${name}`);
const { data, status, statusText } = await this.kibanaServer.request({
path: `/api/security/role/${name}`,
method: 'PUT',
body: {
kibana: role.kibana,
elasticsearch: role.elasticsearch,
},
retries: 0,
});
const { data, status, statusText } = await this.kibanaServer
.request({
path: `/api/security/role/${name}`,
method: 'PUT',
body: {
kibana: role.kibana,
elasticsearch: role.elasticsearch,
},
retries: 0,
})
.catch((e) => {
throw new Error(util.inspect(e.axiosError.response, true));
});
if (status !== 204) {
throw new Error(
`Expected status code of 204, received ${status} ${statusText}: ${util.inspect(data)}`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@
"@kbn/test-subj-selector",
"@kbn/ftr-common-functional-services",
"@kbn/std",
"@kbn/expect"
"@kbn/expect",
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,11 @@ export async function runTests(log: ToolingLog, options: RunTestsOptions) {
logsDir: options.logsDir,
installDir: options.installDir,
onEarlyExit,
extraKbnOpts: [
config.get('serverless')
? '--server.versioned.versionResolution=newest'
: '--server.versioned.versionResolution=oldest',
],
});

if (abortCtrl.signal.aborted) {
Expand Down
11 changes: 11 additions & 0 deletions x-pack/plugins/security/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,14 @@ export const SESSION_ROUTE = '/internal/security/session';
* Allowed image file types for uploading an image as avatar
*/
export const IMAGE_FILE_TYPES = ['image/svg+xml', 'image/jpeg', 'image/png', 'image/gif'];

/**
* The API version numbers used with the versioned router.
*/
export const API_VERSIONS = {
roles: {
public: {
v1: '2023-10-31',
},
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ import Boom from '@hapi/boom';

import { kibanaResponseFactory } from '@kbn/core/server';
import { coreMock, httpServerMock } from '@kbn/core/server/mocks';
import type { MockedVersionedRouter } from '@kbn/core-http-router-server-mocks';
import type { LicenseCheck } from '@kbn/licensing-plugin/server';

import { defineDeleteRolesRoutes } from './delete';
import { API_VERSIONS } from '../../../../common/constants';
import { routeDefinitionParamsMock } from '../../index.mock';

interface TestOptions {
Expand All @@ -28,6 +30,8 @@ describe('DELETE role', () => {
) => {
test(description, async () => {
const mockRouteDefinitionParams = routeDefinitionParamsMock.create();
const versionedRouterMock = mockRouteDefinitionParams.router
.versioned as MockedVersionedRouter;
const mockCoreContext = coreMock.createRequestHandlerContext();
const mockLicensingContext = {
license: { check: jest.fn().mockReturnValue(licenseCheckResult) },
Expand All @@ -44,7 +48,9 @@ describe('DELETE role', () => {
}

defineDeleteRolesRoutes(mockRouteDefinitionParams);
const [[, handler]] = mockRouteDefinitionParams.router.delete.mock.calls;
const handler = versionedRouterMock.getRoute('delete', '/api/security/role/{name}').versions[
API_VERSIONS.roles.public.v1
].handler;

const headers = { authorization: 'foo' };
const mockRequest = httpServerMock.createKibanaRequest({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,37 @@
import { schema } from '@kbn/config-schema';

import type { RouteDefinitionParams } from '../..';
import { API_VERSIONS } from '../../../../common/constants';
import { wrapIntoCustomErrorResponse } from '../../../errors';
import { createLicensedRouteHandler } from '../../licensed_route_handler';

export function defineDeleteRolesRoutes({ router }: RouteDefinitionParams) {
router.delete(
{
router.versioned
.delete({
path: '/api/security/role/{name}',
options: {
access: 'public',
summary: `Delete a role`,
},
validate: {
params: schema.object({ name: schema.string({ minLength: 1 }) }),
access: 'public',
summary: `Delete a role`,
})
.addVersion(
{
version: API_VERSIONS.roles.public.v1,
validate: {
request: {
params: schema.object({ name: schema.string({ minLength: 1 }) }),
},
},
},
},
createLicensedRouteHandler(async (context, request, response) => {
try {
const esClient = (await context.core).elasticsearch.client;
await esClient.asCurrentUser.security.deleteRole({
name: request.params.name,
});
createLicensedRouteHandler(async (context, request, response) => {
try {
const esClient = (await context.core).elasticsearch.client;
await esClient.asCurrentUser.security.deleteRole({
name: request.params.name,
});

return response.noContent();
} catch (error) {
return response.customError(wrapIntoCustomErrorResponse(error));
}
})
);
return response.noContent();
} catch (error) {
return response.customError(wrapIntoCustomErrorResponse(error));
}
})
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ import Boom from '@hapi/boom';

import { kibanaResponseFactory } from '@kbn/core/server';
import { coreMock, httpServerMock } from '@kbn/core/server/mocks';
import type { MockedVersionedRouter } from '@kbn/core-http-router-server-mocks';
import type { LicenseCheck } from '@kbn/licensing-plugin/server';

import { defineGetRolesRoutes } from './get';
import { API_VERSIONS } from '../../../../common/constants';
import { routeDefinitionParamsMock } from '../../index.mock';

const application = 'kibana-.kibana';
Expand All @@ -31,6 +33,8 @@ describe('GET role', () => {
) => {
test(description, async () => {
const mockRouteDefinitionParams = routeDefinitionParamsMock.create();
const versionedRouterMock = mockRouteDefinitionParams.router
.versioned as MockedVersionedRouter;
mockRouteDefinitionParams.authz.applicationName = application;
mockRouteDefinitionParams.getFeatures = jest.fn().mockResolvedValue([]);

Expand All @@ -50,7 +54,9 @@ describe('GET role', () => {
}

defineGetRolesRoutes(mockRouteDefinitionParams);
const [[, handler]] = mockRouteDefinitionParams.router.get.mock.calls;
const handler = versionedRouterMock.getRoute('get', '/api/security/role/{name}').versions[
API_VERSIONS.roles.public.v1
].handler;

const headers = { authorization: 'foo' };
const mockRequest = httpServerMock.createKibanaRequest({
Expand Down
79 changes: 42 additions & 37 deletions x-pack/plugins/security/server/routes/authorization/roles/get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import { schema } from '@kbn/config-schema';

import type { RouteDefinitionParams } from '../..';
import { API_VERSIONS } from '../../../../common/constants';
import { transformElasticsearchRoleToRole } from '../../../authorization';
import { wrapIntoCustomErrorResponse } from '../../../errors';
import { createLicensedRouteHandler } from '../../licensed_route_handler';
Expand All @@ -18,47 +19,51 @@ export function defineGetRolesRoutes({
getFeatures,
logger,
}: RouteDefinitionParams) {
router.get(
{
router.versioned
.get({
path: '/api/security/role/{name}',
options: {
access: 'public',
summary: `Get a role`,
},
validate: {
params: schema.object({ name: schema.string({ minLength: 1 }) }),
access: 'public',
summary: `Get a role`,
})
.addVersion(
{
version: API_VERSIONS.roles.public.v1,
validate: {
request: {
params: schema.object({ name: schema.string({ minLength: 1 }) }),
},
},
},
},
createLicensedRouteHandler(async (context, request, response) => {
try {
const esClient = (await context.core).elasticsearch.client;
createLicensedRouteHandler(async (context, request, response) => {
try {
const esClient = (await context.core).elasticsearch.client;

const [features, elasticsearchRoles] = await Promise.all([
getFeatures(),
await esClient.asCurrentUser.security.getRole({
name: request.params.name,
}),
]);
const [features, elasticsearchRoles] = await Promise.all([
getFeatures(),
await esClient.asCurrentUser.security.getRole({
name: request.params.name,
}),
]);

const elasticsearchRole = elasticsearchRoles[request.params.name];
const elasticsearchRole = elasticsearchRoles[request.params.name];

if (elasticsearchRole) {
return response.ok({
body: transformElasticsearchRoleToRole(
features,
// @ts-expect-error `SecurityIndicesPrivileges.names` expected to be `string[]`
elasticsearchRole,
request.params.name,
authz.applicationName,
logger
),
});
}
if (elasticsearchRole) {
return response.ok({
body: transformElasticsearchRoleToRole(
features,
// @ts-expect-error `SecurityIndicesPrivileges.names` expected to be `string[]`
elasticsearchRole,
request.params.name,
authz.applicationName,
logger
),
});
}

return response.notFound();
} catch (error) {
return response.customError(wrapIntoCustomErrorResponse(error));
}
})
);
return response.notFound();
} catch (error) {
return response.customError(wrapIntoCustomErrorResponse(error));
}
})
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ import Boom from '@hapi/boom';

import { kibanaResponseFactory } from '@kbn/core/server';
import { coreMock, httpServerMock } from '@kbn/core/server/mocks';
import type { MockedVersionedRouter } from '@kbn/core-http-router-server-mocks';
import type { LicenseCheck } from '@kbn/licensing-plugin/server';

import { defineGetAllRolesRoutes } from './get_all';
import { API_VERSIONS } from '../../../../common/constants';
import { routeDefinitionParamsMock } from '../../index.mock';

const application = 'kibana-.kibana';
Expand All @@ -31,6 +33,8 @@ describe('GET all roles', () => {
) => {
test(description, async () => {
const mockRouteDefinitionParams = routeDefinitionParamsMock.create();
const versionedRouterMock = mockRouteDefinitionParams.router
.versioned as MockedVersionedRouter;
mockRouteDefinitionParams.authz.applicationName = application;
mockRouteDefinitionParams.getFeatures = jest.fn().mockResolvedValue([]);

Expand All @@ -50,7 +54,9 @@ describe('GET all roles', () => {
}

defineGetAllRolesRoutes(mockRouteDefinitionParams);
const [[, handler]] = mockRouteDefinitionParams.router.get.mock.calls;
const handler = versionedRouterMock.getRoute('get', '/api/security/role').versions[
API_VERSIONS.roles.public.v1
].handler;

const headers = { authorization: 'foo' };
const mockRequest = httpServerMock.createKibanaRequest({
Expand Down
Loading