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

[Saved Objects] Adds config flag to toggle hiddenFromHttpApis SO types conditionally #151512

Conversation

TinaHeiligers
Copy link
Contributor

@TinaHeiligers TinaHeiligers commented Feb 16, 2023

Fix #150471
Part of #149287

This PR adds a config option to set if the Saved Objects HTTP APIs should be accessible to types registered with hiddenFromHttpApis: true.

allowHttpApiAccess: true --------> grants access
allowHttpApiAccess: false --------> throws in Saved Objects HTTP APIs

allowHttpApiAccess can be configured in kibana.yml but we don't plan to document the option as it is not intended for public use.

The configuration prevents immediate breaking changes caused by saved objects adopting the option to be hidden from the HTTP APIs and is a stepping stone toward removing the Saved Objects HTTP APIs.

The option is only applicable to saved objects registered as hiddenFromHttpApis:true.

Checklist

  • Documentation was added for features that require explanation or tutorials. Code comments should be sufficient to describe the internal behavior.
  • Unit or functional tests were updated or added to match the most common scenarios
  • If a plugin configuration key changed, check if it needs to be allowlisted in the cloud and added to the docker list Docker list updated, we don't intend to add user settings in cloud.

Risk Matrix

Risk Probability Severity Mitigation/Notes
Code should gracefully handle cases when the HTTP APIs are disabled. Medium High Unit tests will verify that any feature flag or plugin combination still results in our service behaving the way intended.

For maintainers

How to test this

Ensure that allowHttpApiAccess can be set in kibana.yml to override the default:

Add the following debug log line to the SavedObjectsService setup contract after the config is set:

log config value
public async setup(setupDeps: SavedObjectsSetupDeps): Promise<InternalSavedObjectsServiceSetup> {
    this.logger.debug('Setting up SavedObjects service');

    this.setupDeps = setupDeps;
    const { http, elasticsearch, coreUsageData, deprecations } = setupDeps;

    const savedObjectsConfig = await firstValueFrom(
      this.coreContext.configService.atPath<SavedObjectsConfigType>('savedObjects')
    );
    const savedObjectsMigrationConfig = await firstValueFrom(
      this.coreContext.configService.atPath<SavedObjectsMigrationConfigType>('migrations')
    );
    this.config = new SavedObjectConfig(savedObjectsConfig, savedObjectsMigrationConfig);
   // add the debug log:
    this.logger.debug(
      `SavedObjects default allowHttpApiAccess configuration: ${this.config.allowHttpApiAccess}`
    );
    deprecations.getRegistry('savedObjects').registerDeprecations(
     <...rest>

Configure logging to include the saved objects service logs:
For example:

kibana.yml
logging:
  appenders:
    so-console:
      type: console
      layout:
        type: pattern
        highlight: true
        pattern: "SAVED_OBJECTS_SERVICE--[%date][%level][%logger]---%message"
  loggers:
    - name: savedobjects-service
      level: debug
      appenders: [so-console]

Start kibana (any version of es is fine) and ensure that allowHttpApiAccess is set. For example, when run from dev the log should read something like:
SAVED_OBJECTS_SERVICE--[2023-02-21T12:06:28.561-07:00][DEBUG][savedobjects-service]---SavedObjects default allowHttpApiAccess configuration: false

In kibana.yml, specifically set savedObjects.allowHttpApiAccess: true and recheck the logs. Using the same logging config as above, the log line should now read:
SAVED_OBJECTS_SERVICE--[2023-02-21T12:06:28.561-07:00][DEBUG][savedobjects-service]---SavedObjects default allowHttpApiAccess configuration: true

@TinaHeiligers TinaHeiligers added Team:Core Core services & architecture: plugins, logging, config, saved objects, http, ES client, i18n, etc Feature:Saved Objects release_note:skip Skip the PR/issue when compiling release notes backport:skip This commit does not require backporting v8.8.0 labels Feb 16, 2023
Copy link
Contributor Author

@TinaHeiligers TinaHeiligers left a comment

Choose a reason for hiding this comment

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

Self review on draft

@@ -42,6 +42,8 @@ export const savedObjectsMigrationConfig: ServiceConfigDescriptor<SavedObjectsMi
const soSchema = schema.object({
maxImportPayloadBytes: schema.byteSize({ defaultValue: 26_214_400 }),
maxImportExportSize: schema.number({ defaultValue: 10_000 }),
// Conditionally set within config, dependening on the env. In prod: allow all access(default), in dev: false
allowHttpApiAccess: schema.boolean({ defaultValue: true }),
Copy link
Contributor Author

@TinaHeiligers TinaHeiligers Feb 16, 2023

Choose a reason for hiding this comment

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

I've gone with defaulting to the "old" behavior where all visible types (those not hidden) use the HTTP APIs. We also need to allow access for self-managed & current cloud offering & cloud tests

Copy link
Member

@Bamieh Bamieh Feb 21, 2023

Choose a reason for hiding this comment

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

Is there a specific reason to depend on the environment and not distribution?

Instead of doing the override logic between the config and the env inside the code and having to inject the env into the classes, why not just do it from the config defaults here (like the example below). This makes the logic a lot more resilient and easier to understand. wdyt?

schema.conditional(
      schema.contextRef('dist'),
      true,
      schema.boolean({ defaultValue: false }),
      schema.boolean({ defaultValue: true })
)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Is there a specific reason to depend on the environment and not distribution?

I didn't think to use the distro rather, great idea thanks!
I'll change it and see how it improves the logic.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@Bamieh I've made the change you requested in 96bb95a (#151512).
Could you take another look, please?

public migration: SavedObjectsMigrationConfigType;

constructor(
rawConfig: SavedObjectsConfigType,
rawMigrationConfig: SavedObjectsMigrationConfigType
rawMigrationConfig: SavedObjectsMigrationConfigType,
allowHttpApiAccess: boolean
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Naming is hard and hideFromHttpApis or denyHttpApiAccess sound rather negative, hence the more "positive" choice.

this.config = new SavedObjectConfig(
savedObjectsConfig,
savedObjectsMigrationConfig,
this.allowHttpApiAccess
Copy link
Contributor Author

@TinaHeiligers TinaHeiligers Feb 16, 2023

Choose a reason for hiding this comment

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

I need to inject if Kibana's running in dev or prod mode from env and set the new config options from within the SO service to avoid instantiating SavedObjectConfig with:

new SavedObjectConfig(savedObjectsConfig, savedObjectsMigrationConfig, coreContext.env.mode.prod)

let savedObjectsClient: ReturnType<typeof savedObjectsClientMock.create>;
let coreUsageStatsClient: jest.Mocked<ICoreUsageStatsClient>;

beforeEach(async () => {
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 test and the others in the same folder test the route behavior in a "dev" environment, were we enforce API blocking.

They're verbose to setup (copies of the main route api_integration tests) and ideally should be condensed. I tried but haven't been able to just yet.


import { SavedObjectConfig } from '@kbn/core-saved-objects-base-server-internal';

export function setupConfig(allowAccess: boolean = false) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Strictly not necessary but I'm reusing the util in almost all the route's tests

@@ -139,6 +139,7 @@ kibana_vars=(
regionmap
savedObjects.maxImportExportSize
savedObjects.maxImportPayloadBytes
savedObjects.allowHttpApiAccess
Copy link
Contributor Author

Choose a reason for hiding this comment

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

New SO config option

@TinaHeiligers TinaHeiligers marked this pull request as ready for review February 16, 2023 22:52
@TinaHeiligers TinaHeiligers requested review from a team as code owners February 16, 2023 22:52
@elasticmachine
Copy link
Contributor

Pinging @elastic/kibana-core (Team:Core)

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.

kibana-docker

@TinaHeiligers
Copy link
Contributor Author

@elasticmachine merge upstream

@TinaHeiligers
Copy link
Contributor Author

@rudolf I added you as a reviewer since Pierre is out. Could you 👁️ when you get a chance? cc @jloleysens

Copy link
Member

@Bamieh Bamieh left a comment

Choose a reason for hiding this comment

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

i have a couple of comments/questions

await server.stop();
});

it('returns with status 400 when a type is hidden from the HTTP APIs', async () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
it('returns with status 400 when a type is hidden from the HTTP APIs', async () => {
it('returns with status 200 when a type is hidden from the HTTP APIs', async () => {

await server.stop();
});

it('returns with status 200 when a type is hidden from the HTTP APIs', async () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: these tests have inconsistent names across the different methods
uses config option allowHttpApiAccess to grant hiddenFromHttpApis types access
vs returns with status 200 when a type is hidden from the HTTP APIs

I prefer the latter

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@rudolf change is made: 75e11c7 (#151512)

@TinaHeiligers
Copy link
Contributor Author

@elasticmachine merge upstream

@TinaHeiligers TinaHeiligers requested a review from Bamieh February 21, 2023 19:26
@kibana-ci
Copy link
Collaborator

💚 Build Succeeded

Metrics [docs]

Public APIs missing comments

Total count of every public API that lacks a comment. Target amount is 0. Run node scripts/build_api_docs --plugin [yourplugin] --stats comments for more detailed information.

id before after diff
@kbn/core-saved-objects-base-server-internal 35 36 +1
Unknown metric groups

API count

id before after diff
@kbn/core-saved-objects-base-server-internal 46 47 +1

History

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

Copy link
Member

@Bamieh Bamieh left a comment

Choose a reason for hiding this comment

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

LGTM

@TinaHeiligers TinaHeiligers merged commit a8f10ed into elastic:main Feb 22, 2023
@TinaHeiligers TinaHeiligers deleted the kbn-150471-toggle-hiddenFromHttpApis-accessibility branch February 22, 2023 18:51
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:Saved Objects release_note:skip Skip the PR/issue when compiling release notes Team:Core Core services & architecture: plugins, logging, config, saved objects, http, ES client, i18n, etc v8.8.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Saved Objects] Use a config flag to change when hiddenFromHttpApis saved objects are accessible
7 participants