Fix typo in license_api_guard README name and import http server mocks from public interface (#97334)
* Reject basic minimum licenses.
This commit is contained in:
parent
787b493403
commit
681bd642fb
|
@ -444,8 +444,8 @@ the infrastructure monitoring use-case within Kibana.
|
||||||
|Visualization editor allowing to quickly and easily configure compelling visualizations to use on dashboards and canvas workpads.
|
|Visualization editor allowing to quickly and easily configure compelling visualizations to use on dashboards and canvas workpads.
|
||||||
|
|
||||||
|
|
||||||
|{kib-repo}blob/{branch}/x-pack/plugins/license_api_guard[licenseApiGuard]
|
|{kib-repo}blob/{branch}/x-pack/plugins/license_api_guard/README.md[licenseApiGuard]
|
||||||
|WARNING: Missing README.
|
|This plugin is used by ES UI plugins to reject API requests when the plugin is unsupported by the user's license.
|
||||||
|
|
||||||
|
|
||||||
|{kib-repo}blob/{branch}/x-pack/plugins/license_management/README.md[licenseManagement]
|
|{kib-repo}blob/{branch}/x-pack/plugins/license_management/README.md[licenseManagement]
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
# License API guard plugin
|
|
||||||
|
|
||||||
This plugin is used by ES UI plugins to reject API requests to plugins that are unsupported by the user's license.
|
|
3
x-pack/plugins/license_api_guard/README.md
Normal file
3
x-pack/plugins/license_api_guard/README.md
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# License API guard plugin
|
||||||
|
|
||||||
|
This plugin is used by ES UI plugins to reject API requests when the plugin is unsupported by the user's license.
|
|
@ -6,18 +6,38 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { of } from 'rxjs';
|
import { of } from 'rxjs';
|
||||||
import type { KibanaRequest, RequestHandlerContext } from 'src/core/server';
|
import type { Logger, KibanaRequest, RequestHandlerContext } from 'src/core/server';
|
||||||
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
|
import { httpServerMock } from 'src/core/server/mocks';
|
||||||
import { httpServerMock } from 'src/core/server/http/http_server.mocks';
|
|
||||||
|
|
||||||
import { License } from './license';
|
import { License } from './license';
|
||||||
import { LicenseCheckState, licensingMock } from './shared_imports';
|
import { LicenseCheckState, licensingMock, LicenseType } from './shared_imports';
|
||||||
|
|
||||||
describe('License API guard', () => {
|
describe('License API guard', () => {
|
||||||
const pluginName = 'testPlugin';
|
const pluginName = 'testPlugin';
|
||||||
const currentLicenseType = 'basic';
|
|
||||||
|
|
||||||
const testRoute = ({ licenseState }: { licenseState: string }) => {
|
const mockLicensingService = ({
|
||||||
|
licenseType,
|
||||||
|
licenseState,
|
||||||
|
}: {
|
||||||
|
licenseType: LicenseType;
|
||||||
|
licenseState: LicenseCheckState;
|
||||||
|
}) => {
|
||||||
|
const licenseMock = licensingMock.createLicenseMock();
|
||||||
|
licenseMock.type = licenseType;
|
||||||
|
licenseMock.check('test', 'gold'); // Flush default mocked state
|
||||||
|
licenseMock.check.mockReturnValue({ state: licenseState }); // Replace with new mocked state
|
||||||
|
|
||||||
|
return {
|
||||||
|
license$: of(licenseMock),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const testRoute = ({
|
||||||
|
licenseType,
|
||||||
|
licenseState,
|
||||||
|
}: {
|
||||||
|
licenseType: LicenseType;
|
||||||
|
licenseState: LicenseCheckState;
|
||||||
|
}) => {
|
||||||
const license = new License();
|
const license = new License();
|
||||||
|
|
||||||
const logger = {
|
const logger = {
|
||||||
|
@ -25,19 +45,11 @@ describe('License API guard', () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
license.setup({ pluginName, logger });
|
license.setup({ pluginName, logger });
|
||||||
|
const licensing = mockLicensingService({ licenseType, licenseState });
|
||||||
const licenseMock = licensingMock.createLicenseMock();
|
|
||||||
licenseMock.type = currentLicenseType;
|
|
||||||
licenseMock.check('test', 'basic'); // Flush default mocked state
|
|
||||||
licenseMock.check.mockReturnValue({ state: licenseState as LicenseCheckState }); // Replace with new mocked state
|
|
||||||
|
|
||||||
const licensing = {
|
|
||||||
license$: of(licenseMock),
|
|
||||||
};
|
|
||||||
|
|
||||||
license.start({
|
license.start({
|
||||||
pluginId: 'id',
|
pluginId: 'id',
|
||||||
minimumLicenseType: 'basic',
|
minimumLicenseType: 'gold',
|
||||||
licensing,
|
licensing,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -61,44 +73,67 @@ describe('License API guard', () => {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('valid license', () => {
|
describe('basic minimum license', () => {
|
||||||
it('the original route is called and nothing is logged', () => {
|
it('is rejected', () => {
|
||||||
const { errorResponse, logMesssage, route } = testRoute({ licenseState: 'valid' });
|
const license = new License();
|
||||||
|
license.setup({ pluginName, logger: {} as Logger });
|
||||||
expect(errorResponse).toBeUndefined();
|
expect(() => {
|
||||||
expect(logMesssage).toBeUndefined();
|
license.start({
|
||||||
expect(route).toHaveBeenCalled();
|
pluginId: pluginName,
|
||||||
|
minimumLicenseType: 'basic',
|
||||||
|
licensing: mockLicensingService({ licenseType: 'gold', licenseState: 'valid' }),
|
||||||
|
});
|
||||||
|
}).toThrowError(
|
||||||
|
`Basic licenses don't restrict the use of plugins. Please don't use license_api_guard in the ${pluginName} plugin, or provide a more restrictive minimumLicenseType.`
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
[
|
describe('non-basic minimum license', () => {
|
||||||
{
|
const licenseType = 'gold';
|
||||||
licenseState: 'invalid',
|
|
||||||
expectedMessage: `Your ${currentLicenseType} license does not support ${pluginName}. Please upgrade your license.`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
licenseState: 'expired',
|
|
||||||
expectedMessage: `You cannot use ${pluginName} because your ${currentLicenseType} license has expired.`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
licenseState: 'unavailable',
|
|
||||||
expectedMessage: `You cannot use ${pluginName} because license information is not available at this time.`,
|
|
||||||
},
|
|
||||||
].forEach(({ licenseState, expectedMessage }) => {
|
|
||||||
describe(`${licenseState} license`, () => {
|
|
||||||
it('replies with and logs the error message', () => {
|
|
||||||
const { errorResponse, logMesssage, route } = testRoute({ licenseState });
|
|
||||||
|
|
||||||
// We depend on the call to `response.forbidden()` to generate the 403 status code,
|
describe('when valid', () => {
|
||||||
// so we can't assert for it here.
|
it('the original route is called and nothing is logged', () => {
|
||||||
expect(errorResponse).toEqual({
|
const { errorResponse, logMesssage, route } = testRoute({
|
||||||
body: {
|
licenseType,
|
||||||
message: expectedMessage,
|
licenseState: 'valid',
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(logMesssage).toBe(expectedMessage);
|
expect(errorResponse).toBeUndefined();
|
||||||
expect(route).not.toHaveBeenCalled();
|
expect(logMesssage).toBeUndefined();
|
||||||
|
expect(route).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
[
|
||||||
|
{
|
||||||
|
licenseState: 'invalid' as LicenseCheckState,
|
||||||
|
expectedMessage: `Your ${licenseType} license does not support ${pluginName}. Please upgrade your license.`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
licenseState: 'expired' as LicenseCheckState,
|
||||||
|
expectedMessage: `You cannot use ${pluginName} because your ${licenseType} license has expired.`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
licenseState: 'unavailable' as LicenseCheckState,
|
||||||
|
expectedMessage: `You cannot use ${pluginName} because license information is not available at this time.`,
|
||||||
|
},
|
||||||
|
].forEach(({ licenseState, expectedMessage }) => {
|
||||||
|
describe(`when ${licenseState}`, () => {
|
||||||
|
it('replies with and logs the error message', () => {
|
||||||
|
const { errorResponse, logMesssage, route } = testRoute({ licenseType, licenseState });
|
||||||
|
|
||||||
|
// We depend on the call to `response.forbidden()` to generate the 403 status code,
|
||||||
|
// so we can't assert for it here.
|
||||||
|
expect(errorResponse).toEqual({
|
||||||
|
body: {
|
||||||
|
message: expectedMessage,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(logMesssage).toBe(expectedMessage);
|
||||||
|
expect(route).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -44,6 +44,12 @@ export class License {
|
||||||
}
|
}
|
||||||
|
|
||||||
start({ pluginId, minimumLicenseType, licensing }: StartSettings) {
|
start({ pluginId, minimumLicenseType, licensing }: StartSettings) {
|
||||||
|
if (minimumLicenseType === 'basic') {
|
||||||
|
throw Error(
|
||||||
|
`Basic licenses don't restrict the use of plugins. Please don't use license_api_guard in the ${pluginId} plugin, or provide a more restrictive minimumLicenseType.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
licensing.license$.subscribe((license: ILicense) => {
|
licensing.license$.subscribe((license: ILicense) => {
|
||||||
this.licenseType = license.type;
|
this.licenseType = license.type;
|
||||||
this.licenseCheckState = license.check(pluginId, minimumLicenseType!).state;
|
this.licenseCheckState = license.check(pluginId, minimumLicenseType!).state;
|
||||||
|
|
Loading…
Reference in a new issue