Skip to content

Commit d8f8a0c

Browse files
authored
Fix anonymous access to status page (#24706)
* fix status.allowAnonymous * address PR feedback
1 parent c26dc55 commit d8f8a0c

File tree

10 files changed

+128
-6
lines changed

10 files changed

+128
-6
lines changed

src/core_plugins/status_page/public/status_page.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*/
1919

2020
import 'ui/autoload/styles';
21+
import 'ui/i18n';
2122
import { uiModules } from 'ui/modules';
2223
import chrome from 'ui/chrome';
2324
import { destroyStatusPage, renderStatusPage } from './components/render';

src/server/status/routes/page/register_status.js

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,21 @@
2020
import { wrapAuthConfig } from '../../wrap_auth_config';
2121

2222
export function registerStatusPage(kbnServer, server, config) {
23-
const wrapAuth = wrapAuthConfig(config.get('status.allowAnonymous'));
23+
const allowAnonymous = config.get('status.allowAnonymous');
24+
const wrapAuth = wrapAuthConfig(allowAnonymous);
2425

2526
server.decorate('toolkit', 'renderStatusPage', async function () {
2627
const app = server.getHiddenUiAppById('status_page');
2728
const h = this;
28-
const response = app
29-
? await h.renderApp(app)
30-
: h.response(kbnServer.status.toString());
29+
30+
let response;
31+
// An unauthenticated (anonymous) user may not have access to the customized configuration.
32+
// For this scenario, render with the default config.
33+
if (app) {
34+
response = allowAnonymous ? await h.renderAppWithDefaultConfig(app) : await h.renderApp(app);
35+
} else {
36+
h.response(kbnServer.status.toString());
37+
}
3138

3239
if (response) {
3340
return response.code(kbnServer.status.isGreen() ? 200 : 503);

x-pack/plugins/spaces/public/views/nav_control/nav_control.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import { SpacesManager } from 'plugins/spaces/lib/spaces_manager';
99
// @ts-ignore
1010
import template from 'plugins/spaces/views/nav_control/nav_control.html';
1111
import { NavControlPopover } from 'plugins/spaces/views/nav_control/nav_control_popover';
12+
// @ts-ignore
13+
import { PathProvider } from 'plugins/xpack_main/services/path';
1214
import { UserProfileProvider } from 'plugins/xpack_main/services/user_profile';
1315
import React from 'react';
1416
import ReactDOM from 'react-dom';
@@ -45,6 +47,7 @@ module.controller(
4547
'spacesNavController',
4648
($scope: any, $http: any, chrome: any, Private: any, activeSpace: any) => {
4749
const userProfile = Private(UserProfileProvider);
50+
const pathProvider = Private(PathProvider);
4851

4952
const domNode = document.getElementById(`spacesNavReactRoot`);
5053
const spaceSelectorURL = chrome.getInjected('spaceSelectorURL');
@@ -54,7 +57,7 @@ module.controller(
5457
let mounted = false;
5558

5659
$scope.$parent.$watch('isVisible', function isVisibleWatcher(isVisible: boolean) {
57-
if (isVisible && !mounted) {
60+
if (isVisible && !mounted && !pathProvider.isUnauthenticated()) {
5861
render(
5962
<NavControlPopover
6063
spacesManager={spacesManager}
@@ -99,6 +102,11 @@ chromeHeaderNavControlsRegistry.register(
99102
side: NavControlSide.Left,
100103
render(el: HTMLElement) {
101104
const userProfile = Private(UserProfileProvider);
105+
const pathProvider = Private(PathProvider);
106+
107+
if (pathProvider.isUnauthenticated()) {
108+
return;
109+
}
102110

103111
const spaceSelectorURL = chrome.getInjected('spaceSelectorURL');
104112

x-pack/plugins/xpack_main/public/services/path.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export function PathProvider($window) {
1010
const path = chrome.removeBasePath($window.location.pathname);
1111
return {
1212
isUnauthenticated() {
13-
return path === '/login' || path === '/logout' || path === '/logged_out';
13+
return path === '/login' || path === '/logout' || path === '/logged_out' || path === '/status';
1414
}
1515
};
1616
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
import { TestInvoker } from './lib/types';
7+
8+
// tslint:disable:no-default-export
9+
export default function statusPage({ loadTestFile }: TestInvoker) {
10+
describe('Status page', function statusPageTestSuite() {
11+
loadTestFile(require.resolve('./status_page'));
12+
});
13+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
export type DescribeFn = (text: string, fn: () => void) => void;
8+
9+
export interface TestDefinitionAuthentication {
10+
username?: string;
11+
password?: string;
12+
}
13+
14+
export type LoadTestFileFn = (path: string) => string;
15+
16+
export type GetServiceFn = (service: string) => any;
17+
18+
export type ReadConfigFileFn = (path: string) => any;
19+
20+
export type GetPageObjectsFn = (pageObjects: string[]) => any;
21+
22+
export interface TestInvoker {
23+
getService: GetServiceFn;
24+
getPageObjects: GetPageObjectsFn;
25+
loadTestFile: LoadTestFileFn;
26+
readConfigFile: ReadConfigFileFn;
27+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
import { TestInvoker } from './lib/types';
7+
8+
// tslint:disable:no-default-export
9+
export default function statusPageFunctonalTests({ getService, getPageObjects }: TestInvoker) {
10+
const esArchiver = getService('esArchiver');
11+
const PageObjects = getPageObjects(['security', 'statusPage', 'home']);
12+
13+
describe('Status Page', () => {
14+
before(async () => await esArchiver.load('empty_kibana'));
15+
after(async () => await esArchiver.unload('empty_kibana'));
16+
17+
it('allows user to navigate without authentication', async () => {
18+
await PageObjects.statusPage.navigateToPage();
19+
await PageObjects.statusPage.expectStatusPage();
20+
});
21+
});
22+
}

x-pack/test/functional/config.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
SpaceSelectorPageProvider,
2020
AccountSettingProvider,
2121
InfraHomePageProvider,
22+
StatusPagePageProvider,
2223
} from './page_objects';
2324

2425
import {
@@ -71,6 +72,7 @@ export default async function ({ readConfigFile }) {
7172
resolve(__dirname, './apps/logstash'),
7273
resolve(__dirname, './apps/grok_debugger'),
7374
resolve(__dirname, './apps/infra'),
75+
resolve(__dirname, './apps/status_page'),
7476
],
7577

7678
// define the name and providers for services that should be
@@ -121,6 +123,7 @@ export default async function ({ readConfigFile }) {
121123
reporting: ReportingPageProvider,
122124
spaceSelector: SpaceSelectorPageProvider,
123125
infraHome: InfraHomePageProvider,
126+
statusPage: StatusPagePageProvider,
124127
},
125128

126129
servers: kibanaFunctionalConfig.get('servers'),
@@ -138,6 +141,7 @@ export default async function ({ readConfigFile }) {
138141
...kibanaCommonConfig.get('kbnTestServer'),
139142
serverArgs: [
140143
...kibanaCommonConfig.get('kbnTestServer.serverArgs'),
144+
'--status.allowAnonymous=true',
141145
'--server.uuid=5b2de169-2785-441b-ae8c-186a1936b17d',
142146
'--xpack.xpack_main.telemetry.enabled=false',
143147
'--xpack.security.encryptionKey="wuGNaIhoMpk5sO4UBxgr3NyW1sFcLgIf"', // server restarts should not invalidate active sessions

x-pack/test/functional/page_objects/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ export { ReportingPageProvider } from './reporting_page';
1414
export { SpaceSelectorPageProvider } from './space_selector_page';
1515
export { AccountSettingProvider } from './accountsetting_page';
1616
export { InfraHomePageProvider } from './infra_home_page';
17+
export { StatusPagePageProvider } from './status_page';
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import expect from 'expect.js';
8+
9+
export function StatusPagePageProvider({ getService, getPageObjects }) {
10+
const retry = getService('retry');
11+
const log = getService('log');
12+
const remote = getService('remote');
13+
const PageObjects = getPageObjects(['common', 'home', 'security']);
14+
15+
class StatusPage {
16+
async initTests() {
17+
log.debug('StatusPage:initTests');
18+
}
19+
20+
async navigateToPage() {
21+
return await retry.try(async () => {
22+
const url = PageObjects.common.getHostPort() + '/status';
23+
log.info(`StatusPage:navigateToPage(): ${url}`);
24+
await remote.get(url);
25+
});
26+
}
27+
28+
async expectStatusPage() {
29+
return await retry.try(async () => {
30+
log.debug(`expectStatusPage()`);
31+
await remote.setFindTimeout(20000).findByCssSelector('[data-test-subj="kibanaChrome"] nav:not(.ng-hide) ');
32+
const url = await remote.getCurrentUrl();
33+
expect(url).to.contain(`/status`);
34+
});
35+
}
36+
}
37+
38+
return new StatusPage();
39+
}

0 commit comments

Comments
 (0)