-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
Extract License service from CCR and Watcher into license_api_guard plugin in x-pack #95973
Extract License service from CCR and Watcher into license_api_guard plugin in x-pack #95973
Conversation
Pinging @elastic/es-ui (Team:Elasticsearch UI) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for working on this @cjcenizal! I’m happy with this approach and also verified the changes locally.
Next steps: If reviewers approve of this direction, I'll extract this approach into a reusable service and then apply it to similar code in Watcher.
👍 I can re-review once this is complete. Can this service be used more broadly across our other plugins as well (perhaps addressed in a separate PR)?
{ licensing, logger }: { licensing: LicensingPluginSetup; logger: Logger } | ||
) { | ||
this.logger = logger; | ||
|
||
licensing.license$.subscribe((license) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not directly related to this PR - but I noticed while looking at the code in my IDE that LicensingPluginSetup.license$
is deprecated, and we should be using license$
provided by the start contract.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point! Done.
361d501
to
4ba7a29
Compare
5e573a1
to
87c0a21
Compare
RequestHandlerContext, | ||
} from 'src/core/server'; | ||
|
||
/* eslint-disable @kbn/eslint/no-restricted-paths */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@elastic/kibana-core Do we still need this linting rule to disallow importing x-pack modules into non-x-pack?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For concrete imports, we definitely do, as it would plainly breaks on OSS distrib.
For types, it's not a 'technical' requirement, but until the basic plugins are moved out of xpack, we should stick with that rule.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAIK we don't release OSS distributable starting from v7.11 https://www.elastic.co/downloads/past-releases#kibana-oss
But I'd rather plugins didn't import from x-pack
. Note that the code in src/
and x-pack
have different licenses, so it's easy to leak commercial code outside by importing runtime
code accidentally.
Regarding the current use case: why licensing
code lives in src/
at all? Licensing
compatible types can be declared in the current file, but maybe an x-pack
plugin is a better place?
937ed8a
to
3c6acd7
Compare
3c6acd7
to
7c34572
Compare
start({ pluginId, minimumLicenseType, licensing }: StartSettings) { | ||
licensing.license$.subscribe((license) => { | ||
this.licenseType = license.type; | ||
this.licenseCheckState = license.check(pluginId, minimumLicenseType!).state; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To testers: you can hardcode a value here, e.g. 'invalid', to test the behavior under various conditions.
@alisonelizabeth @jloleysens This is ready for your 👀 ! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know this may change soon, but I'm not at ease with the fact a xpack-dependent utility class importing types from licensing
is exposed from an OSS plugin.
@mshustov wdyt?
RequestHandlerContext, | ||
} from 'src/core/server'; | ||
|
||
/* eslint-disable @kbn/eslint/no-restricted-paths */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For concrete imports, we definitely do, as it would plainly breaks on OSS distrib.
For types, it's not a 'technical' requirement, but until the basic plugins are moved out of xpack, we should stick with that rule.
@alisonelizabeth @jloleysens @pgayvallet @mshustov Thanks for your reviews! I've addressed your feedback. I agree that we should sequester @alisonelizabeth To your question about using this in our other plugins -- I just checked and I believe all of our other plugins are licensed under Basic, so there's no need to guard their API routes this way. Reviewers, would you mind taking another look at sharing your thoughts? Thanks! |
import { of } from 'rxjs'; | ||
import type { KibanaRequest, RequestHandlerContext } from 'src/core/server'; | ||
// eslint-disable-next-line @kbn/eslint/no-restricted-paths | ||
import { httpServerMock } from 'src/core/server/http/http_server.mocks'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mshustov Do you think we could update src/core/server
to export these helpers publicly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They are available from src/core/server/mocks
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, fixed in #97334
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
At some point in the future I think we could discuss either moving it into the licensing plugin if we think non-ESUI plugins would benefit from it, or into an x-pack-specific version of es_ui_shared if not.
We are planning to add something similar #56926
} | ||
|
||
start({ pluginId, minimumLicenseType, licensing }: StartSettings) { | ||
licensing.license$.subscribe((license: ILicense) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldn't we unsubscribe on the stop
lifecycle?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mshustov I was under the impression that stop
is never called in server-side plugins -- plugins just "live" until the Kibana server process is killed. Is that not the case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
plugins just "live" until the Kibana server process is killed.
@cjcenizal Nope. It's always called during the normal teardown process (unless Kibana crashes).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When does teardown occur? How can I trigger it?
const licenseErrorMessage = this.getLicenseErrorMessage(this.licenseCheckState); | ||
this.logger?.warn(licenseErrorMessage); | ||
|
||
return response.customError({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not response.forbidden
?
return response.forbidden({
body: {
message: licenseErrorMessage,
},
});
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good suggestion!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes LGTM. Thanks @cjcenizal!
@alisonelizabeth To your question about using this in our other plugins -- I just checked and I believe all of our other plugins are licensed under Basic, so there's no need to guard their API routes this way.
I think most - if not all - of our plugins have a similar license check (for example, Ingest Node Pipelines, Index Management and ILM). Can we remove this guard now?
}, | ||
].forEach(({ licenseState, expectedMessage }) => { | ||
describe(`${licenseState} license`, () => { | ||
it('replies with 403 and message and logs the message', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it('replies with 403 and message and logs the message', () => { | |
it('replies with 403 status and logs the message', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for addressing that feedback @cjcenizal. Happy with the current changes!
Co-authored-by: Alison Goryachev <[email protected]>
@alisonelizabeth Great call, I created #97314 to track this work. @mshustov I'm going to go ahead and merge once CI is green. We can follow up on your comment about unsubscribing from the license service in another PR if this needs to be addressed. |
💚 Build Succeeded
Metrics [docs]
History
To update your PR or re-run it, just comment with: |
Release note
Cross-cluster Replication and Watcher used to log misleading warnings about the basic license on Kibana startup. These warnings have been removed.
Summary
Fixes #95032
When you're on the Basic license, Watcher and CCR log disconcerting license failure messages to the command line on startup. These messages are phrased in a way that makes users think something is wrong, when in reality nothing is wrong. This PR makes two fundamental changes:
I also refactored our internal license service to leverage the types exposed by the core license service.
Here's how license failures are now surfaced to the user in the UI and CLI for CCR:
Watcher is not quite as helpful but we can address that separately:
Steps to test
license.ts
service to fake the license status.Checklist