Skip to content

Commit

Permalink
Migrate /bootstrap.js endpoint to core (elastic#92784)
Browse files Browse the repository at this point in the history
* move bootstrap endpoint to core

* some initial cleanup

* hack around the 'try' auth status

* some UT

* more UT

* add try/catch around uISettings access

* add 'auth.isEnabled'

* remove dead files

* use `try` authent mode

* adapt UT

* revert themeTag movearound

* migrate apps route to core

* some cleanup

* nit

* add integration tests

* update generated doc

* add UT for /app route

* add etag IT

* nits

* remove auth.isEnabled API

* add tests on get_apm_config

* use string template instead of handlebars for bootstrap template

* improve plugin bundle tests

* update generated doc

* remove response.etag API

* update generated doc

* update generated doc

* update generated doc again

* extract getThemeTag

* add more unit tests
  • Loading branch information
pgayvallet committed Mar 10, 2021
1 parent fa11006 commit 6651446
Show file tree
Hide file tree
Showing 53 changed files with 1,697 additions and 521 deletions.
1 change: 0 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -576,7 +576,6 @@ module.exports = {
{
files: [
'test/functional/services/lib/web_element_wrapper/scroll_into_view_if_necessary.js',
'src/legacy/ui/ui_render/bootstrap/kbn_bundles_loader_source.js',
'**/browser_exec_scripts/**/*.js',
],
rules: {
Expand Down
4 changes: 2 additions & 2 deletions api_docs/core.json
Original file line number Diff line number Diff line change
Expand Up @@ -10346,7 +10346,7 @@
],
"source": {
"path": "src/core/server/rendering/types.ts",
"lineNumber": 72
"lineNumber": 73
},
"signature": [
"boolean | undefined"
Expand All @@ -10355,7 +10355,7 @@
],
"source": {
"path": "src/core/server/rendering/types.ts",
"lineNumber": 67
"lineNumber": 68
},
"initialIsOpen": false
},
Expand Down
24 changes: 12 additions & 12 deletions api_docs/core_http.json
Original file line number Diff line number Diff line change
Expand Up @@ -2887,7 +2887,7 @@
"type": "Function",
"label": "notHandled",
"description": [
"\nUser has no credentials.\nAllows user to access a resource when authRequired: 'optional'\nRejects a request when authRequired: true"
"\nUser has no credentials.\nAllows user to access a resource when authRequired is 'optional' or 'try'\nRejects a request when authRequired: true"
],
"source": {
"path": "src/core/server/http/lifecycle/auth.ts",
Expand Down Expand Up @@ -4648,7 +4648,7 @@
],
"source": {
"path": "src/core/server/http/router/route.ts",
"lineNumber": 171
"lineNumber": 173
}
},
{
Expand All @@ -4661,7 +4661,7 @@
],
"source": {
"path": "src/core/server/http/router/route.ts",
"lineNumber": 229
"lineNumber": 231
},
"signature": [
"false | ",
Expand All @@ -4685,7 +4685,7 @@
],
"source": {
"path": "src/core/server/http/router/route.ts",
"lineNumber": 234
"lineNumber": 236
},
"signature": [
{
Expand All @@ -4701,7 +4701,7 @@
],
"source": {
"path": "src/core/server/http/router/route.ts",
"lineNumber": 157
"lineNumber": 159
},
"initialIsOpen": false
},
Expand Down Expand Up @@ -4732,14 +4732,14 @@
"type": "CompoundType",
"label": "authRequired",
"description": [
"\nDefines authentication mode for a route:\n- true. A user has to have valid credentials to access a resource\n- false. A user can access a resource without any credentials.\n- 'optional'. A user can access a resource if has valid credentials or no credentials at all.\nCan be useful when we grant access to a resource but want to identify a user if possible.\n\nDefaults to `true` if an auth mechanism is registered."
"\nDefines authentication mode for a route:\n- true. A user has to have valid credentials to access a resource\n- false. A user can access a resource without any credentials.\n- 'optional'. A user can access a resource if has valid credentials or no credentials at all.\n Can be useful when we grant access to a resource but want to identify a user if possible.\n- 'try'. A user can access a resource with valid, invalid or without any credentials.\n Users with valid credentials will be authenticated\n\nDefaults to `true` if an auth mechanism is registered."
],
"source": {
"path": "src/core/server/http/router/route.ts",
"lineNumber": 116
"lineNumber": 118
},
"signature": [
"boolean | \"optional\" | undefined"
"boolean | \"optional\" | \"try\" | undefined"
]
},
{
Expand All @@ -4752,7 +4752,7 @@
],
"source": {
"path": "src/core/server/http/router/route.ts",
"lineNumber": 125
"lineNumber": 127
},
"signature": [
"(Method extends \"get\" ? never : boolean) | undefined"
Expand All @@ -4768,7 +4768,7 @@
],
"source": {
"path": "src/core/server/http/router/route.ts",
"lineNumber": 130
"lineNumber": 132
},
"signature": [
"readonly string[] | undefined"
Expand All @@ -4784,7 +4784,7 @@
],
"source": {
"path": "src/core/server/http/router/route.ts",
"lineNumber": 135
"lineNumber": 137
},
"signature": [
"(Method extends ",
Expand Down Expand Up @@ -4816,7 +4816,7 @@
],
"source": {
"path": "src/core/server/http/router/route.ts",
"lineNumber": 140
"lineNumber": 142
},
"signature": [
"{ payload?: (Method extends ",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ export interface AuthToolkit
| Property | Type | Description |
| --- | --- | --- |
| [authenticated](./kibana-plugin-core-server.authtoolkit.authenticated.md) | <code>(data?: AuthResultParams) =&gt; AuthResult</code> | Authentication is successful with given credentials, allow request to pass through |
| [notHandled](./kibana-plugin-core-server.authtoolkit.nothandled.md) | <code>() =&gt; AuthResult</code> | User has no credentials. Allows user to access a resource when authRequired: 'optional' Rejects a request when authRequired: true |
| [notHandled](./kibana-plugin-core-server.authtoolkit.nothandled.md) | <code>() =&gt; AuthResult</code> | User has no credentials. Allows user to access a resource when authRequired is 'optional' or 'try' Rejects a request when authRequired: true |
| [redirected](./kibana-plugin-core-server.authtoolkit.redirected.md) | <code>(headers: {</code><br/><code> location: string;</code><br/><code> } &amp; ResponseHeaders) =&gt; AuthResult</code> | Redirects user to another location to complete authentication when authRequired: true Allows user to access a resource without redirection when authRequired: 'optional' |

Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

## AuthToolkit.notHandled property

User has no credentials. Allows user to access a resource when authRequired: 'optional' Rejects a request when authRequired: true
User has no credentials. Allows user to access a resource when authRequired is 'optional' or 'try' Rejects a request when authRequired: true

<b>Signature:</b>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@

## RouteConfigOptions.authRequired property

Defines authentication mode for a route: - true. A user has to have valid credentials to access a resource - false. A user can access a resource without any credentials. - 'optional'. A user can access a resource if has valid credentials or no credentials at all. Can be useful when we grant access to a resource but want to identify a user if possible.
Defines authentication mode for a route: - true. A user has to have valid credentials to access a resource - false. A user can access a resource without any credentials. - 'optional'. A user can access a resource if has valid credentials or no credentials at all. Can be useful when we grant access to a resource but want to identify a user if possible. - 'try'. A user can access a resource with valid, invalid or without any credentials. Users with valid credentials will be authenticated

Defaults to `true` if an auth mechanism is registered.

<b>Signature:</b>

```typescript
authRequired?: boolean | 'optional';
authRequired?: boolean | 'optional' | 'try';
```
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export interface RouteConfigOptions<Method extends RouteMethod>

| Property | Type | Description |
| --- | --- | --- |
| [authRequired](./kibana-plugin-core-server.routeconfigoptions.authrequired.md) | <code>boolean &#124; 'optional'</code> | Defines authentication mode for a route: - true. A user has to have valid credentials to access a resource - false. A user can access a resource without any credentials. - 'optional'. A user can access a resource if has valid credentials or no credentials at all. Can be useful when we grant access to a resource but want to identify a user if possible.<!-- -->Defaults to <code>true</code> if an auth mechanism is registered. |
| [authRequired](./kibana-plugin-core-server.routeconfigoptions.authrequired.md) | <code>boolean &#124; 'optional' &#124; 'try'</code> | Defines authentication mode for a route: - true. A user has to have valid credentials to access a resource - false. A user can access a resource without any credentials. - 'optional'. A user can access a resource if has valid credentials or no credentials at all. Can be useful when we grant access to a resource but want to identify a user if possible. - 'try'. A user can access a resource with valid, invalid or without any credentials. Users with valid credentials will be authenticated<!-- -->Defaults to <code>true</code> if an auth mechanism is registered. |
| [body](./kibana-plugin-core-server.routeconfigoptions.body.md) | <code>Method extends 'get' &#124; 'options' ? undefined : RouteConfigOptionsBody</code> | Additional body options [RouteConfigOptionsBody](./kibana-plugin-core-server.routeconfigoptionsbody.md)<!-- -->. |
| [tags](./kibana-plugin-core-server.routeconfigoptions.tags.md) | <code>readonly string[]</code> | Additional metadata tag strings to attach to the route. |
| [timeout](./kibana-plugin-core-server.routeconfigoptions.timeout.md) | <code>{</code><br/><code> payload?: Method extends 'get' &#124; 'options' ? undefined : number;</code><br/><code> idleSocket?: number;</code><br/><code> }</code> | Defines per-route timeouts. |
Expand Down
17 changes: 17 additions & 0 deletions src/core/server/core_app/core_app.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,21 @@ describe('CoreApp', () => {
);
});
});

describe('`/app/{id}/{any*}` route', () => {
it('is registered with the correct parameters', () => {
coreApp.setup(internalCoreSetup);

expect(httpResourcesRegistrar.register).toHaveBeenCalledWith(
{
path: '/app/{id}/{any*}',
validate: false,
options: {
authRequired: true,
},
},
expect.any(Function)
);
});
});
});
23 changes: 21 additions & 2 deletions src/core/server/core_app/core_app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@ import { Logger } from '../logging';
/** @internal */
export class CoreApp {
private readonly logger: Logger;

constructor(core: CoreContext) {
this.logger = core.logger.get('core-app');
}

setup(coreSetup: InternalCoreSetup) {
this.logger.debug('Setting up core app.');
this.registerDefaultRoutes(coreSetup);
Expand All @@ -27,7 +29,9 @@ export class CoreApp {

private registerDefaultRoutes(coreSetup: InternalCoreSetup) {
const httpSetup = coreSetup.http;
const router = httpSetup.createRouter('/');
const router = httpSetup.createRouter('');
const resources = coreSetup.httpResources.createRegistrar(router);

router.get({ path: '/', validate: false }, async (context, req, res) => {
const defaultRoute = await context.core.uiSettings.client.get<string>('defaultRoute');
const basePath = httpSetup.basePath.get(req);
Expand All @@ -39,12 +43,26 @@ export class CoreApp {
},
});
});

router.get({ path: '/core', validate: false }, async (context, req, res) =>
res.ok({ body: { version: '0.0.1' } })
);

resources.register(
{
path: '/app/{id}/{any*}',
validate: false,
options: {
authRequired: true,
},
},
async (context, request, response) => {
return response.renderCoreApp();
}
);

const anonymousStatusPage = coreSetup.status.isStatusPageAnonymous();
coreSetup.httpResources.createRegistrar(router).register(
resources.register(
{
path: '/status',
validate: false,
Expand All @@ -61,6 +79,7 @@ export class CoreApp {
}
);
}

private registerStaticDirs(coreSetup: InternalCoreSetup) {
coreSetup.http.registerStaticDir('/ui/{path*}', Path.resolve(__dirname, './assets'));

Expand Down
14 changes: 7 additions & 7 deletions src/core/server/http/http_server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ import {
SessionStorageCookieOptions,
createCookieSessionStorageFactory,
} from './cookie_session_storage';
import { IsAuthenticated, AuthStateStorage, GetAuthState } from './auth_state_storage';
import { AuthStateStorage } from './auth_state_storage';
import { AuthHeadersStorage, GetAuthHeaders } from './auth_headers_storage';
import { BasePath } from './base_path_service';
import { getEcsResponseLog } from './logging';
import { HttpServiceSetup, HttpServerInfo } from './types';
import { HttpServiceSetup, HttpServerInfo, HttpAuth } from './types';

/** @internal */
export interface HttpServerSetup {
Expand All @@ -54,10 +54,7 @@ export interface HttpServerSetup {
registerOnPostAuth: HttpServiceSetup['registerOnPostAuth'];
registerOnPreResponse: HttpServiceSetup['registerOnPreResponse'];
getAuthHeaders: GetAuthHeaders;
auth: {
get: GetAuthState;
isAuthenticated: IsAuthenticated;
};
auth: HttpAuth;
getServerInfo: () => HttpServerInfo;
}

Expand Down Expand Up @@ -228,7 +225,7 @@ export class HttpServer {

private getAuthOption(
authRequired: RouteConfigOptions<any>['authRequired'] = true
): undefined | false | { mode: 'required' | 'optional' } {
): undefined | false | { mode: 'required' | 'optional' | 'try' } {
if (this.authRegistered === false) return undefined;

if (authRequired === true) {
Expand All @@ -237,6 +234,9 @@ export class HttpServer {
if (authRequired === 'optional') {
return { mode: 'optional' };
}
if (authRequired === 'try') {
return { mode: 'try' };
}
if (authRequired === false) {
return false;
}
Expand Down
35 changes: 33 additions & 2 deletions src/core/server/http/integration_tests/core_services.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ describe('http service', () => {
const { http } = await root.setup();
const { registerAuth, createRouter, auth } = http;

await registerAuth((req, res, toolkit) => toolkit.authenticated());
registerAuth((req, res, toolkit) => toolkit.authenticated());

const router = createRouter('');
router.get({ path: '/is-auth', validate: false }, (context, req, res) =>
Expand Down Expand Up @@ -136,6 +136,37 @@ describe('http service', () => {
await root.start();
await kbnTestServer.request.get(root, '/is-auth').expect(200, { isAuthenticated: false });
});

it('returns true if authenticated on a route with "try" auth', async () => {
const { http } = await root.setup();
const { createRouter, auth, registerAuth } = http;

registerAuth((req, res, toolkit) => toolkit.authenticated());
const router = createRouter('');
router.get(
{ path: '/is-auth', validate: false, options: { authRequired: 'try' } },
(context, req, res) => res.ok({ body: { isAuthenticated: auth.isAuthenticated(req) } })
);

await root.start();
await kbnTestServer.request.get(root, '/is-auth').expect(200, { isAuthenticated: true });
});

it('returns false if not authenticated on a route with "try" auth', async () => {
const { http } = await root.setup();
const { createRouter, auth, registerAuth } = http;

registerAuth((req, res, toolkit) => toolkit.notHandled());

const router = createRouter('');
router.get(
{ path: '/is-auth', validate: false, options: { authRequired: 'try' } },
(context, req, res) => res.ok({ body: { isAuthenticated: auth.isAuthenticated(req) } })
);

await root.start();
await kbnTestServer.request.get(root, '/is-auth').expect(200, { isAuthenticated: false });
});
});
describe('#get()', () => {
it('returns authenticated status and allow associate auth state with request', async () => {
Expand Down Expand Up @@ -179,7 +210,7 @@ describe('http service', () => {

const { http } = await root.setup();
const { createRouter, registerAuth, auth } = http;
await registerAuth(authenticate);
registerAuth(authenticate);
const router = createRouter('');
router.get(
{ path: '/get-auth', validate: false, options: { authRequired: false } },
Expand Down
Loading

0 comments on commit 6651446

Please sign in to comment.