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

[Serverless] Add internal uiSettings routes and expose public routes in self-managed only #160499

Merged
merged 8 commits into from
Jul 14, 2023

Conversation

ElenaStoeva
Copy link
Contributor

@ElenaStoeva ElenaStoeva commented Jun 26, 2023

Partially addresses #159590

Summary

This PR adds an an internal uiSettings API that is a duplicate of the public API and is intended for use by the browser-side uiSettings client.

The PR also adds a config settings that is configured in serverless context only and exposes the public uiSettings routes based on the value of this setting (it defaults to false since we don't want to expose the public routes in serverless).

How to test:

I. Verify that in serverless the internal routes are exposed but the public ones aren't:

  1. Start Es with yarn es snapshot and Kibana with yarn serverless-{mode} where {mode} can be es, oblt, or security (the public routes should be disabled for all projects).
  2. Verify that the public endpoints are not accessible. For example, curl --user elastic:changeme 'http://localhost:5601/zhb/api/kibana/settings' -X 'GET' should return {"statusCode":404,"error":"Not Found","message":"Not Found"}.
  3. Verify that the internal endpoints are accessible. For example, curl --user elastic:changeme 'http://localhost:5601/zhb/internal/kibana/settings' -X 'GET' should return {"settings":{"buildNum":{"userValue":9007199254740991},"isDefaultIndexMigrated":{"userValue":true},"defaultRoute":{"isOverridden":true,"userValue":"/app/elasticsearch"}}}

II. Verify that the both public and internal routes are exposed in self-managed:

  1. Start Es with yarn es snapshot and Kibana with yarn start
  2. Verify that the public endpoints are accessible. For example, curl --user elastic:changeme 'http://localhost:5601/zhb/api/kibana/settings' -X 'GET' should return {"settings":{"buildNum":{"userValue":9007199254740991},"isDefaultIndexMigrated":{"userValue":true}}}
  3. Verify that the internal endpoints are accessible. For example, curl --user elastic:changeme 'http://localhost:5601/zhb/internal/kibana/settings' -X 'GET' should return {"settings":{"buildNum":{"userValue":9007199254740991},"isDefaultIndexMigrated":{"userValue":true}}}

III. Verify that the plugins/services that consume the internal uiSettings endpoints work as expected in both self-managed and serverless environment.

For maintainers

@ElenaStoeva ElenaStoeva added Team:Kibana Management Dev Tools, Index Management, Upgrade Assistant, ILM, Ingest Node Pipelines, and more Feature:uiSettings labels Jun 26, 2023
@ElenaStoeva ElenaStoeva self-assigned this Jun 26, 2023
@ElenaStoeva ElenaStoeva added release_note:skip Skip the PR/issue when compiling release notes v8.10.0 labels Jun 26, 2023
@ElenaStoeva ElenaStoeva requested a review from a team June 26, 2023 17:08
@ElenaStoeva ElenaStoeva marked this pull request as ready for review June 28, 2023 11:33
@ElenaStoeva ElenaStoeva requested review from a team as code owners June 28, 2023 11:33
@elasticmachine
Copy link
Contributor

Pinging @elastic/platform-deployment-management (Team:Deployment Management)

Copy link
Contributor

@pgayvallet pgayvallet left a comment

Choose a reason for hiding this comment

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

Approach looks fine to me, but PR still needs changes to be ready to merge.

@@ -51,15 +51,33 @@ export function registerDeleteRoute(router: InternalUiSettingsRouter) {
throw error;
}
};
if (publicApiEnabled) {
Copy link
Contributor

@pgayvallet pgayvallet Jun 30, 2023

Choose a reason for hiding this comment

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

General comment for all routes:

Either we decide that for now, those two API prefix (/api and /internal) should have the exact same behavior, in which case I would reuse the handlers, instead of duplicating them, e.g

const deleteHandler: HttpRequestHandler<forgotWhichGenerics> = async (context, request, response) => {
        const uiSettingsClient = (await context.core).uiSettings.client;
        return await deleteFromRequest(uiSettingsClient, context, request, response);
      }

if (publicApiEnabled) {
   router.delete({ path: '/api/kibana/settings/{key}', validate }, deleteHandler);
}
router.delete({ path: '/internal/kibana/global_settings/{key}', validate, options: { access: 'internal' } }, deleteHandler)

Or we decide that the code may diverge, in which case the registration should be fully dissociated, with an individual file for the public and one for the internal API.

Given we decided to go the "public + internal" way in case we may want to make the APIs diverge, I would go with later.

We can for example have two folders:

  • packages/core/ui-settings/core-ui-settings-server-internal/src/routes/public
  • packages/core/ui-settings/core-ui-settings-server-internal/src/routes/internal

Or, what we sometimes do for Core routes:

  • packages/core/ui-settings/core-ui-settings-server-internal/src/routes/ <- public routes
  • packages/core/ui-settings/core-ui-settings-server-internal/src/routes/internal <- internal routes

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I agree that separating the public and the internal routes in different files is the better option given what we discussed about potentially evolving the public routes in the future.
I took the Core routes approach for structuring the files (having public routes in /src/routes and internal ones in /src/routes/internal).

registerDeleteRoute(router);
registerSetRoute(router);
registerSetManyRoute(router);
export function registerRoutes(router: InternalUiSettingsRouter, publicApiEnabled: boolean = true) {
Copy link
Contributor

@pgayvallet pgayvallet Jun 30, 2023

Choose a reason for hiding this comment

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

publicApiEnabled being optional is misleading and potentially error-prone. Just make the option mandatory and adapt existing usages (if not done already)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This argument is no longer needed after separating the public from the internal routes in different files.

Comment on lines 86 to 93
if (config.hasOwnProperty('publicApiEnabled')) {
registerRoutes(
http.createRouter<InternalUiSettingsRequestHandlerContext>(''),
config.publicApiEnabled
);
} else {
registerRoutes(http.createRouter<InternalUiSettingsRequestHandlerContext>(''));
}
Copy link
Contributor

Choose a reason for hiding this comment

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

NIT: unnecessary duplication

const publicApiEnabled = config.hasOwnProperty('publicApiEnabled') && config.publicApiEnabled === true;
registerRoutes(
        http.createRouter<InternalUiSettingsRequestHandlerContext>(''),
        publicApiEnabled
);

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure, I refactored these lines of code, but I don't think the condition config.hasOwnProperty('publicApiEnabled') && config.publicApiEnabled === true would work for self-managed where this would evaluate to false since we don't have the publicApiEnabled setting configured, so I changed this logic a bit.

Comment on lines 47 to 53
describe('set', () => {
it('validates value', async () => {
const response = await request
.post(root, '/api/kibana/settings/custom')
.post(root, '/internal/kibana/settings/custom')
.send({ value: 100 })
.expect(400);

Copy link
Contributor

Choose a reason for hiding this comment

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

We gonna need proper test coverage for the public routes too. Those tests needs to be running against the public routes (duplicating them is fine)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure, I added a duplicate set of tests for both public and internal routes.

@botelastic botelastic bot added Team:APM All issues that need APM UI Team support Team:Fleet Team label for Observability Data Collection Fleet team labels Jun 30, 2023
@elasticmachine
Copy link
Contributor

Pinging @elastic/apm-ui (Team:APM)

@elasticmachine
Copy link
Contributor

Pinging @elastic/fleet (Team:Fleet)

@ElenaStoeva
Copy link
Contributor Author

@elasticmachine merge upstream

@ElenaStoeva
Copy link
Contributor Author

Thanks a lot for the review @pgayvallet! I made the changes that you suggested and left a couple of comments. Let me know if any additional changes are needed.

@kibana-ci
Copy link
Collaborator

💛 Build succeeded, but was flaky

Failed CI Steps

Test Failures

  • [job] [logs] Security Solution Tests #1 / Exceptions viewer read only "before each" hook for "Cannot add an exception from empty viewer screen"

Metrics [docs]

Page load bundle

Size of the bundles that are downloaded on every page load. Target size is below 100kb

id before after diff
core 363.5KB 363.5KB +10.0B
Unknown metric groups

ESLint disabled line counts

id before after diff
enterpriseSearch 14 16 +2
securitySolution 410 414 +4
total +6

Total ESLint disabled count

id before after diff
enterpriseSearch 15 17 +2
securitySolution 489 493 +4
total +6

History

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

cc @ElenaStoeva

Copy link
Contributor

@pgayvallet pgayvallet left a comment

Choose a reason for hiding this comment

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

LGTM, thanks for the changes!

@ElenaStoeva
Copy link
Contributor Author

@elastic/apm-ui and @elastic/security-solution, can you please verify that, with these changes, your plugins work as expected in self-managed and serverless environment?

Copy link
Member

@sorenlouv sorenlouv left a comment

Choose a reason for hiding this comment

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

apm changes lgtm

Copy link
Member

@jbudz jbudz left a comment

Choose a reason for hiding this comment

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

packages/kbn-test LGTM

Copy link
Contributor

@YulNaumenko YulNaumenko left a comment

Choose a reason for hiding this comment

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

Changes doesn't impact security_solution functionality. Could you please clarify why do we need to switch to internal APIs for the self-managed tests you've changed in security_solution?

@ElenaStoeva
Copy link
Contributor Author

Changes doesn't impact security_solution functionality. Could you please clarify why do we need to switch to internal APIs for the self-managed tests you've changed in security_solution?

Thanks a lot for the review @YulNaumenko!

The internal routes are intended for use by the browser-side clients in both serverless and self-managed (sorry if that wasn't clear from the PR description). This is why I replaced all usages of the public routes across Kibana with the internal ones. The public API is intended for use by the user and will only be available in self-managed. Also, it may be changed or even removed in the future.
Do you think the security_solution tests should use the public routes instead of the internal ones?

Copy link
Member

@dmlemeshko dmlemeshko left a comment

Choose a reason for hiding this comment

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

Appex-QA changes LGTM

@ElenaStoeva ElenaStoeva merged commit 4105619 into elastic:main Jul 14, 2023
@kibanamachine kibanamachine added the backport:skip This commit does not require backporting label Jul 14, 2023
@ElenaStoeva ElenaStoeva deleted the serverless-uisettings-routes branch July 14, 2023 14:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport:skip This commit does not require backporting Feature:uiSettings release_note:skip Skip the PR/issue when compiling release notes Team:APM All issues that need APM UI Team support Team:Fleet Team label for Observability Data Collection Fleet team Team:Kibana Management Dev Tools, Index Management, Upgrade Assistant, ILM, Ingest Node Pipelines, and more v8.10.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.