Fix anonymous access to status page (#24706)
* fix status.allowAnonymous * address PR feedback
This commit is contained in:
parent
c26dc55759
commit
d8f8a0c26d
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
import 'ui/autoload/styles';
|
||||
import 'ui/i18n';
|
||||
import { uiModules } from 'ui/modules';
|
||||
import chrome from 'ui/chrome';
|
||||
import { destroyStatusPage, renderStatusPage } from './components/render';
|
||||
|
|
|
@ -20,14 +20,21 @@
|
|||
import { wrapAuthConfig } from '../../wrap_auth_config';
|
||||
|
||||
export function registerStatusPage(kbnServer, server, config) {
|
||||
const wrapAuth = wrapAuthConfig(config.get('status.allowAnonymous'));
|
||||
const allowAnonymous = config.get('status.allowAnonymous');
|
||||
const wrapAuth = wrapAuthConfig(allowAnonymous);
|
||||
|
||||
server.decorate('toolkit', 'renderStatusPage', async function () {
|
||||
const app = server.getHiddenUiAppById('status_page');
|
||||
const h = this;
|
||||
const response = app
|
||||
? await h.renderApp(app)
|
||||
: h.response(kbnServer.status.toString());
|
||||
|
||||
let response;
|
||||
// An unauthenticated (anonymous) user may not have access to the customized configuration.
|
||||
// For this scenario, render with the default config.
|
||||
if (app) {
|
||||
response = allowAnonymous ? await h.renderAppWithDefaultConfig(app) : await h.renderApp(app);
|
||||
} else {
|
||||
h.response(kbnServer.status.toString());
|
||||
}
|
||||
|
||||
if (response) {
|
||||
return response.code(kbnServer.status.isGreen() ? 200 : 503);
|
||||
|
|
|
@ -9,6 +9,8 @@ import { SpacesManager } from 'plugins/spaces/lib/spaces_manager';
|
|||
// @ts-ignore
|
||||
import template from 'plugins/spaces/views/nav_control/nav_control.html';
|
||||
import { NavControlPopover } from 'plugins/spaces/views/nav_control/nav_control_popover';
|
||||
// @ts-ignore
|
||||
import { PathProvider } from 'plugins/xpack_main/services/path';
|
||||
import { UserProfileProvider } from 'plugins/xpack_main/services/user_profile';
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
|
@ -45,6 +47,7 @@ module.controller(
|
|||
'spacesNavController',
|
||||
($scope: any, $http: any, chrome: any, Private: any, activeSpace: any) => {
|
||||
const userProfile = Private(UserProfileProvider);
|
||||
const pathProvider = Private(PathProvider);
|
||||
|
||||
const domNode = document.getElementById(`spacesNavReactRoot`);
|
||||
const spaceSelectorURL = chrome.getInjected('spaceSelectorURL');
|
||||
|
@ -54,7 +57,7 @@ module.controller(
|
|||
let mounted = false;
|
||||
|
||||
$scope.$parent.$watch('isVisible', function isVisibleWatcher(isVisible: boolean) {
|
||||
if (isVisible && !mounted) {
|
||||
if (isVisible && !mounted && !pathProvider.isUnauthenticated()) {
|
||||
render(
|
||||
<NavControlPopover
|
||||
spacesManager={spacesManager}
|
||||
|
@ -99,6 +102,11 @@ chromeHeaderNavControlsRegistry.register(
|
|||
side: NavControlSide.Left,
|
||||
render(el: HTMLElement) {
|
||||
const userProfile = Private(UserProfileProvider);
|
||||
const pathProvider = Private(PathProvider);
|
||||
|
||||
if (pathProvider.isUnauthenticated()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const spaceSelectorURL = chrome.getInjected('spaceSelectorURL');
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ export function PathProvider($window) {
|
|||
const path = chrome.removeBasePath($window.location.pathname);
|
||||
return {
|
||||
isUnauthenticated() {
|
||||
return path === '/login' || path === '/logout' || path === '/logged_out';
|
||||
return path === '/login' || path === '/logout' || path === '/logged_out' || path === '/status';
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
13
x-pack/test/functional/apps/status_page/index.ts
Normal file
13
x-pack/test/functional/apps/status_page/index.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import { TestInvoker } from './lib/types';
|
||||
|
||||
// tslint:disable:no-default-export
|
||||
export default function statusPage({ loadTestFile }: TestInvoker) {
|
||||
describe('Status page', function statusPageTestSuite() {
|
||||
loadTestFile(require.resolve('./status_page'));
|
||||
});
|
||||
}
|
27
x-pack/test/functional/apps/status_page/lib/types.ts
Normal file
27
x-pack/test/functional/apps/status_page/lib/types.ts
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export type DescribeFn = (text: string, fn: () => void) => void;
|
||||
|
||||
export interface TestDefinitionAuthentication {
|
||||
username?: string;
|
||||
password?: string;
|
||||
}
|
||||
|
||||
export type LoadTestFileFn = (path: string) => string;
|
||||
|
||||
export type GetServiceFn = (service: string) => any;
|
||||
|
||||
export type ReadConfigFileFn = (path: string) => any;
|
||||
|
||||
export type GetPageObjectsFn = (pageObjects: string[]) => any;
|
||||
|
||||
export interface TestInvoker {
|
||||
getService: GetServiceFn;
|
||||
getPageObjects: GetPageObjectsFn;
|
||||
loadTestFile: LoadTestFileFn;
|
||||
readConfigFile: ReadConfigFileFn;
|
||||
}
|
22
x-pack/test/functional/apps/status_page/status_page.ts
Normal file
22
x-pack/test/functional/apps/status_page/status_page.ts
Normal file
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import { TestInvoker } from './lib/types';
|
||||
|
||||
// tslint:disable:no-default-export
|
||||
export default function statusPageFunctonalTests({ getService, getPageObjects }: TestInvoker) {
|
||||
const esArchiver = getService('esArchiver');
|
||||
const PageObjects = getPageObjects(['security', 'statusPage', 'home']);
|
||||
|
||||
describe('Status Page', () => {
|
||||
before(async () => await esArchiver.load('empty_kibana'));
|
||||
after(async () => await esArchiver.unload('empty_kibana'));
|
||||
|
||||
it('allows user to navigate without authentication', async () => {
|
||||
await PageObjects.statusPage.navigateToPage();
|
||||
await PageObjects.statusPage.expectStatusPage();
|
||||
});
|
||||
});
|
||||
}
|
|
@ -19,6 +19,7 @@ import {
|
|||
SpaceSelectorPageProvider,
|
||||
AccountSettingProvider,
|
||||
InfraHomePageProvider,
|
||||
StatusPagePageProvider,
|
||||
} from './page_objects';
|
||||
|
||||
import {
|
||||
|
@ -71,6 +72,7 @@ export default async function ({ readConfigFile }) {
|
|||
resolve(__dirname, './apps/logstash'),
|
||||
resolve(__dirname, './apps/grok_debugger'),
|
||||
resolve(__dirname, './apps/infra'),
|
||||
resolve(__dirname, './apps/status_page'),
|
||||
],
|
||||
|
||||
// define the name and providers for services that should be
|
||||
|
@ -121,6 +123,7 @@ export default async function ({ readConfigFile }) {
|
|||
reporting: ReportingPageProvider,
|
||||
spaceSelector: SpaceSelectorPageProvider,
|
||||
infraHome: InfraHomePageProvider,
|
||||
statusPage: StatusPagePageProvider,
|
||||
},
|
||||
|
||||
servers: kibanaFunctionalConfig.get('servers'),
|
||||
|
@ -138,6 +141,7 @@ export default async function ({ readConfigFile }) {
|
|||
...kibanaCommonConfig.get('kbnTestServer'),
|
||||
serverArgs: [
|
||||
...kibanaCommonConfig.get('kbnTestServer.serverArgs'),
|
||||
'--status.allowAnonymous=true',
|
||||
'--server.uuid=5b2de169-2785-441b-ae8c-186a1936b17d',
|
||||
'--xpack.xpack_main.telemetry.enabled=false',
|
||||
'--xpack.security.encryptionKey="wuGNaIhoMpk5sO4UBxgr3NyW1sFcLgIf"', // server restarts should not invalidate active sessions
|
||||
|
|
|
@ -14,3 +14,4 @@ export { ReportingPageProvider } from './reporting_page';
|
|||
export { SpaceSelectorPageProvider } from './space_selector_page';
|
||||
export { AccountSettingProvider } from './accountsetting_page';
|
||||
export { InfraHomePageProvider } from './infra_home_page';
|
||||
export { StatusPagePageProvider } from './status_page';
|
||||
|
|
39
x-pack/test/functional/page_objects/status_page.js
Normal file
39
x-pack/test/functional/page_objects/status_page.js
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import expect from 'expect.js';
|
||||
|
||||
export function StatusPagePageProvider({ getService, getPageObjects }) {
|
||||
const retry = getService('retry');
|
||||
const log = getService('log');
|
||||
const remote = getService('remote');
|
||||
const PageObjects = getPageObjects(['common', 'home', 'security']);
|
||||
|
||||
class StatusPage {
|
||||
async initTests() {
|
||||
log.debug('StatusPage:initTests');
|
||||
}
|
||||
|
||||
async navigateToPage() {
|
||||
return await retry.try(async () => {
|
||||
const url = PageObjects.common.getHostPort() + '/status';
|
||||
log.info(`StatusPage:navigateToPage(): ${url}`);
|
||||
await remote.get(url);
|
||||
});
|
||||
}
|
||||
|
||||
async expectStatusPage() {
|
||||
return await retry.try(async () => {
|
||||
log.debug(`expectStatusPage()`);
|
||||
await remote.setFindTimeout(20000).findByCssSelector('[data-test-subj="kibanaChrome"] nav:not(.ng-hide) ');
|
||||
const url = await remote.getCurrentUrl();
|
||||
expect(url).to.contain(`/status`);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return new StatusPage();
|
||||
}
|
Loading…
Reference in a new issue