Skip to content

Conversation

@afharo
Copy link
Member

@afharo afharo commented Nov 25, 2024

Summary

Resolves #201442.

The underlying issue is that isEnabledAtPath validates the entire config object when it only cares about .enabled. This PR performs that check using stripUnknownKeys: true, as we'll perform the actual validation later on.

Checklist

@afharo afharo added Team:Core Platform Core services: plugins, logging, config, saved objects, http, ES client, i18n, etc t// release_note:skip Skip the PR/issue when compiling release notes Feature:Configuration Settings in kibana.yml backport:skip This PR does not require backporting labels Nov 25, 2024
@afharo afharo self-assigned this Nov 25, 2024
@afharo afharo force-pushed the config/strip-unknown-on-serverless branch from 3e45864 to b852da7 Compare November 25, 2024 12:55
@afharo afharo force-pushed the config/strip-unknown-on-serverless branch from b852da7 to e7c0bd7 Compare November 25, 2024 12:59
Copy link
Member Author

Choose a reason for hiding this comment

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

proving that stripUnknownKeys works as intended


const validatedConfig = hasSchema
? await this.atPath<{ enabled?: boolean }>(path).pipe(first()).toPromise()
? await firstValueFrom(
Copy link
Member Author

Choose a reason for hiding this comment

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

I took the opportunity to change the deprecated usage of .toPromise()

Comment on lines +223 to +235
// Special use case: when the provided config includes `enabled` and the validated config doesn't,
// it's quite likely that's not an allowed config and it should fail.
// Applying "normal" validation (not stripping unknowns) in that case.
if (
hasSchema &&
typeof config.get(path)?.enabled !== 'undefined' &&
typeof validatedConfig?.enabled === 'undefined'
) {
validatedConfig = await firstValueFrom(
this.getValidatedConfigAtPath$(path) as Observable<{ enabled?: boolean }>,
{ defaultValue: undefined }
);
}
Copy link
Member Author

Choose a reason for hiding this comment

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

I had to add this special use case since stripUnknownKeys effectively breaks it 😿

Copy link
Contributor

Choose a reason for hiding this comment

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

This makes sense, although it's possible that the validation error may contain more than just "enabled"... perhaps we can catch and throw a more specific message here about the special "enabled" setting?

Copy link
Member Author

Choose a reason for hiding this comment

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

Great point! I created #202490 for us to discuss the new potential message.

@afharo afharo marked this pull request as ready for review November 25, 2024 17:58
@afharo afharo requested a review from a team as a code owner November 25, 2024 17:58
@elasticmachine
Copy link
Contributor

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

Copy link
Contributor

@jloleysens jloleysens left a comment

Choose a reason for hiding this comment

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

Overall lgtm, left a comment about a test and an error message. Let me know what you think! Non blockers.

)
: undefined;

// Special use case: when the provided config includes `enabled` and the validated config doesn't,
Copy link
Contributor

Choose a reason for hiding this comment

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

This is only at the top level of the object?

Also could we add a test case for this?

Copy link
Member Author

@afharo afharo Dec 2, 2024

Choose a reason for hiding this comment

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

This is the existing test that reminded me that I would introduce a regression with simply using stripUnknownKeys: true above:

test('throws if reading "enabled" when it is not present in the schema', async () => {
const initialConfig = {
foo: {
enabled: false,
},
};
const rawConfigProvider = createRawConfigServiceMock({ rawConfig: initialConfig });
const configService = new ConfigService(rawConfigProvider, defaultEnv, logger);
configService.setSchema(
'foo',
schema.object({
bar: schema.maybe(schema.string()),
})
);
await expect(
async () => await configService.isEnabledAtPath('foo')
).rejects.toThrowErrorMatchingInlineSnapshot(
`"[config validation of [foo].enabled]: definition for this key is missing"`
);
});

Comment on lines +223 to +235
// Special use case: when the provided config includes `enabled` and the validated config doesn't,
// it's quite likely that's not an allowed config and it should fail.
// Applying "normal" validation (not stripping unknowns) in that case.
if (
hasSchema &&
typeof config.get(path)?.enabled !== 'undefined' &&
typeof validatedConfig?.enabled === 'undefined'
) {
validatedConfig = await firstValueFrom(
this.getValidatedConfigAtPath$(path) as Observable<{ enabled?: boolean }>,
{ defaultValue: undefined }
);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

This makes sense, although it's possible that the validation error may contain more than just "enabled"... perhaps we can catch and throw a more specific message here about the special "enabled" setting?

@afharo afharo enabled auto-merge (squash) December 2, 2024 14:48
@afharo afharo added backport:prev-minor and removed backport:skip This PR does not require backporting labels Dec 2, 2024
@afharo
Copy link
Member Author

afharo commented Dec 2, 2024

This feature is Serverless-only. However, I chose to backport to prev-minor to avoid harder conflicts in the future.

@afharo afharo merged commit 3e1d62e into elastic:main Dec 2, 2024
12 checks passed
@afharo afharo deleted the config/strip-unknown-on-serverless branch December 2, 2024 16:30
@elasticmachine
Copy link
Contributor

💚 Build Succeeded

Metrics [docs]

✅ unchanged

History

cc @afharo

@kibanamachine
Copy link
Contributor

Starting backport for target branches: 8.x

https://github.com/elastic/kibana/actions/runs/12123693009

kibanamachine pushed a commit to kibanamachine/kibana that referenced this pull request Dec 2, 2024
…lastic#201579)

## Summary

Resolves elastic#201442.

The underlying issue is that `isEnabledAtPath` validates the entire
config object when it only cares about `.enabled`. This PR performs that
check using `stripUnknownKeys: true`, as we'll perform the actual
validation later on.

### Checklist

- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios

(cherry picked from commit 3e1d62e)
@kibanamachine
Copy link
Contributor

💚 All backports created successfully

Status Branch Result
8.x

Note: Successful backport PRs will be merged automatically after passing CI.

Questions ?

Please refer to the Backport tool documentation

kibanamachine added a commit that referenced this pull request Dec 2, 2024
…ed&#x60; flags (#201579) (#202531)

# Backport

This will backport the following commits from `main` to `8.x`:
- [[Config Service] Use stripUnknownKeys when checking
&#x60;enabled&#x60; flags
(#201579)](#201579)

<!--- Backport version: 9.4.3 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Alejandro Fernández
Haro","email":"afharo@gmail.com"},"sourceCommit":{"committedDate":"2024-12-02T16:30:09Z","message":"[Config
Service] Use stripUnknownKeys when checking `enabled` flags
(#201579)\n\n## Summary\n\nResolves #201442.\n\nThe underlying issue is
that `isEnabledAtPath` validates the entire\nconfig object when it only
cares about `.enabled`. This PR performs that\ncheck using
`stripUnknownKeys: true`, as we'll perform the actual\nvalidation later
on.\n\n\n### Checklist\n\n- [x] [Unit or
functional\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\nwere
updated or added to match the most common
scenarios","sha":"3e1d62ebc4530a1f9ebc05d9cbff858aa46ce438","branchLabelMapping":{"^v9.0.0$":"main","^v8.18.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["Team:Core","release_note:skip","Feature:Configuration","v9.0.0","backport:prev-minor"],"title":"[Config
Service] Use stripUnknownKeys when checking `enabled`
flags","number":201579,"url":"https://github.com/elastic/kibana/pull/201579","mergeCommit":{"message":"[Config
Service] Use stripUnknownKeys when checking `enabled` flags
(#201579)\n\n## Summary\n\nResolves #201442.\n\nThe underlying issue is
that `isEnabledAtPath` validates the entire\nconfig object when it only
cares about `.enabled`. This PR performs that\ncheck using
`stripUnknownKeys: true`, as we'll perform the actual\nvalidation later
on.\n\n\n### Checklist\n\n- [x] [Unit or
functional\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\nwere
updated or added to match the most common
scenarios","sha":"3e1d62ebc4530a1f9ebc05d9cbff858aa46ce438"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","branchLabelMappingKey":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/201579","number":201579,"mergeCommit":{"message":"[Config
Service] Use stripUnknownKeys when checking `enabled` flags
(#201579)\n\n## Summary\n\nResolves #201442.\n\nThe underlying issue is
that `isEnabledAtPath` validates the entire\nconfig object when it only
cares about `.enabled`. This PR performs that\ncheck using
`stripUnknownKeys: true`, as we'll perform the actual\nvalidation later
on.\n\n\n### Checklist\n\n- [x] [Unit or
functional\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\nwere
updated or added to match the most common
scenarios","sha":"3e1d62ebc4530a1f9ebc05d9cbff858aa46ce438"}}]}]
BACKPORT-->

Co-authored-by: Alejandro Fernández Haro <afharo@gmail.com>
CAWilson94 pushed a commit to CAWilson94/kibana that referenced this pull request Dec 12, 2024
…lastic#201579)

## Summary

Resolves elastic#201442.

The underlying issue is that `isEnabledAtPath` validates the entire
config object when it only cares about `.enabled`. This PR performs that
check using `stripUnknownKeys: true`, as we'll perform the actual
validation later on.


### Checklist

- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Feature:Configuration Settings in kibana.yml release_note:skip Skip the PR/issue when compiling release notes Team:Core Platform Core services: plugins, logging, config, saved objects, http, ES client, i18n, etc t// v8.18.0 v9.0.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Serverless] Global strip unknown keys doesn't work on nested objects

4 participants