Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
ea8e82c
[feat] [wip] start proxy implementation
toddself May 9, 2019
be11ce9
Refactor clientDoc handler from proxy logic
toddself Jun 7, 2019
e406184
Use POJOs instead of Map for simplification
toddself Jun 7, 2019
8804a84
Switch over to KibanaRequest and allow headers/other methods to be pa…
toddself Jun 7, 2019
2c1244c
[fix] drop lastChangedTime
toddself Jun 10, 2019
9ec607a
Starting tests
toddself Jun 10, 2019
862b6fd
Why must you mock me
toddself Jun 10, 2019
e2bbcbb
got one
toddself Jun 11, 2019
1eb2e9b
mock es
toddself Jun 12, 2019
9d8773f
Adding mutual TLS
toddself Jun 12, 2019
f3808ac
SSL configuration
toddself Jun 12, 2019
c604078
Update mocks, verify dataClient gets called
toddself Jun 13, 2019
12363ad
Add basic clusterdoc tests
toddself Jun 13, 2019
54166b1
setup testing for proxy itself
toddself Jun 13, 2019
8868076
renovate
toddself Jun 14, 2019
ef010b4
for those about to mock
toddself Jun 15, 2019
834a9b1
we salute you
toddself Jun 15, 2019
e3edaae
mock and roll all night
toddself Jun 15, 2019
d871b11
i wanna mock!
toddself Jun 15, 2019
c7b41c4
mock you like a hurricane
toddself Jun 15, 2019
b47c28c
mock and roll killing machine
toddself Jun 17, 2019
18a76fb
Use seq_no and primary_term
toddself Jun 17, 2019
594588d
M.O.C.K. in the U.S.A.
toddself Jun 17, 2019
1d41802
crocodile mock
toddself Jun 17, 2019
c618da6
mock and roll all night, party every day
toddself Jun 17, 2019
b5fcf67
we built this city on mock and roll
toddself Jun 18, 2019
d7170ac
Add event interface for error handling
toddself Jun 18, 2019
e329b43
let there be mock
toddself Jun 19, 2019
1eb3bf4
syncing strat
toddself Jun 20, 2019
1414812
Add handshake and node adding
toddself Jun 20, 2019
c884a92
update docs
toddself Jun 21, 2019
7960a0b
this'll break those tests alright
toddself Jun 21, 2019
0f1ddd3
Remove extraneous exports
toddself Jun 21, 2019
2ad5ce6
only cull every 2x times, add closing state
toddself Jun 21, 2019
ffaf4c9
update docs
toddself Jun 21, 2019
04fb2e4
Update sync doc
toddself Jun 24, 2019
ad0abae
jest timers are weird
toddself Jun 24, 2019
0ba5107
update tests for new logic
toddself Jun 24, 2019
a3c3d8f
update proxy tests
toddself Jun 24, 2019
14b6344
remove subs
toddself Jun 24, 2019
83d3082
Fix test errors
toddself Jun 24, 2019
770d8e0
variable naming
toddself Jun 24, 2019
a4b8b27
fix proxy interface for allocation table
toddself Jun 24, 2019
df149c0
update tsconf
toddself Jun 25, 2019
3774527
satisfy the type gods
toddself Jul 3, 2019
fa2ccc2
respond to feedback
toddself Jul 3, 2019
ed6ab30
Fix rebase
toddself Jul 8, 2019
dd0e207
SSL config working
toddself Jul 8, 2019
a416ea1
make path better
toddself Jul 8, 2019
f60d054
fix errant keys
toddself Jul 8, 2019
7de61d5
omfg linters
toddself Jul 10, 2019
31713ee
fix docs
toddself Jul 10, 2019
f7b0062
fix mock
toddself Jul 15, 2019
6dcefb6
lol source control
toddself Jul 15, 2019
8f449b6
SSL is required to be optional
toddself Jul 17, 2019
ec49124
proxy.start can be undefined
toddself Jul 18, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [HttpServerSetup](./kibana-plugin-server.httpserversetup.md) &gt; [auth](./kibana-plugin-server.httpserversetup.auth.md)

## HttpServerSetup.auth property

<b>Signature:</b>

```typescript
auth: {
get: AuthStateStorage['get'];
isAuthenticated: AuthStateStorage['isAuthenticated'];
getAuthHeaders: AuthHeadersStorage['get'];
};
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [HttpServerSetup](./kibana-plugin-server.httpserversetup.md) &gt; [basePath](./kibana-plugin-server.httpserversetup.basepath.md)

## HttpServerSetup.basePath property

<b>Signature:</b>

```typescript
basePath: {
get: (request: KibanaRequest | Request) => string;
set: (request: KibanaRequest | Request, basePath: string) => void;
prepend: (url: string) => string;
remove: (url: string) => string;
};
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [HttpServerSetup](./kibana-plugin-server.httpserversetup.md) &gt; [isTlsEnabled](./kibana-plugin-server.httpserversetup.istlsenabled.md)

## HttpServerSetup.isTlsEnabled property

<b>Signature:</b>

```typescript
isTlsEnabled: boolean;
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [HttpServerSetup](./kibana-plugin-server.httpserversetup.md)

## HttpServerSetup interface

<b>Signature:</b>

```typescript
export interface HttpServerSetup
```

## Properties

| Property | Type | Description |
| --- | --- | --- |
| [auth](./kibana-plugin-server.httpserversetup.auth.md) | <code>{</code><br/><code> get: AuthStateStorage['get'];</code><br/><code> isAuthenticated: AuthStateStorage['isAuthenticated'];</code><br/><code> getAuthHeaders: AuthHeadersStorage['get'];</code><br/><code> }</code> | |
| [basePath](./kibana-plugin-server.httpserversetup.basepath.md) | <code>{</code><br/><code> get: (request: KibanaRequest &#124; Request) =&gt; string;</code><br/><code> set: (request: KibanaRequest &#124; Request, basePath: string) =&gt; void;</code><br/><code> prepend: (url: string) =&gt; string;</code><br/><code> remove: (url: string) =&gt; string;</code><br/><code> }</code> | |
| [isTlsEnabled](./kibana-plugin-server.httpserversetup.istlsenabled.md) | <code>boolean</code> | |
| [registerAuth](./kibana-plugin-server.httpserversetup.registerauth.md) | <code>&lt;T&gt;(handler: AuthenticationHandler, cookieOptions: SessionStorageCookieOptions&lt;T&gt;) =&gt; Promise&lt;{</code><br/><code> sessionStorageFactory: SessionStorageFactory&lt;T&gt;;</code><br/><code> }&gt;</code> | To define custom authentication and/or authorization mechanism for incoming requests. A handler should return a state to associate with the incoming request. The state can be retrieved later via http.auth.get(..) Only one AuthenticationHandler can be registered. |
| [registerOnPostAuth](./kibana-plugin-server.httpserversetup.registeronpostauth.md) | <code>(handler: OnPostAuthHandler) =&gt; void</code> | To define custom logic to perform for incoming requests. Runs the handler after Auth hook did make sure a user has access to the requested resource. The auth state is available at stage via http.auth.get(..) Can register any number of registerOnPreAuth, which are called in sequence (from the first registered to the last). |
| [registerOnPreAuth](./kibana-plugin-server.httpserversetup.registeronpreauth.md) | <code>(handler: OnPreAuthHandler) =&gt; void</code> | To define custom logic to perform for incoming requests. Runs the handler before Auth hook performs a check that user has access to requested resources, so it's the only place when you can forward a request to another URL right on the server. Can register any number of registerOnPostAuth, which are called in sequence (from the first registered to the last). |
| [registerRouter](./kibana-plugin-server.httpserversetup.registerrouter.md) | <code>(router: Router) =&gt; void</code> | |
| [server](./kibana-plugin-server.httpserversetup.server.md) | <code>Server</code> | |

Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [HttpServerSetup](./kibana-plugin-server.httpserversetup.md) &gt; [registerAuth](./kibana-plugin-server.httpserversetup.registerauth.md)

## HttpServerSetup.registerAuth property

To define custom authentication and/or authorization mechanism for incoming requests. A handler should return a state to associate with the incoming request. The state can be retrieved later via http.auth.get(..) Only one AuthenticationHandler can be registered.

<b>Signature:</b>

```typescript
registerAuth: <T>(handler: AuthenticationHandler, cookieOptions: SessionStorageCookieOptions<T>) => Promise<{
sessionStorageFactory: SessionStorageFactory<T>;
}>;
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [HttpServerSetup](./kibana-plugin-server.httpserversetup.md) &gt; [registerOnPostAuth](./kibana-plugin-server.httpserversetup.registeronpostauth.md)

## HttpServerSetup.registerOnPostAuth property

To define custom logic to perform for incoming requests. Runs the handler after Auth hook did make sure a user has access to the requested resource. The auth state is available at stage via http.auth.get(..) Can register any number of registerOnPreAuth, which are called in sequence (from the first registered to the last).

<b>Signature:</b>

```typescript
registerOnPostAuth: (handler: OnPostAuthHandler) => void;
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [HttpServerSetup](./kibana-plugin-server.httpserversetup.md) &gt; [registerOnPreAuth](./kibana-plugin-server.httpserversetup.registeronpreauth.md)

## HttpServerSetup.registerOnPreAuth property

To define custom logic to perform for incoming requests. Runs the handler before Auth hook performs a check that user has access to requested resources, so it's the only place when you can forward a request to another URL right on the server. Can register any number of registerOnPostAuth, which are called in sequence (from the first registered to the last).

<b>Signature:</b>

```typescript
registerOnPreAuth: (handler: OnPreAuthHandler) => void;
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [HttpServerSetup](./kibana-plugin-server.httpserversetup.md) &gt; [registerRouter](./kibana-plugin-server.httpserversetup.registerrouter.md)

## HttpServerSetup.registerRouter property

<b>Signature:</b>

```typescript
registerRouter: (router: Router) => void;
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [HttpServerSetup](./kibana-plugin-server.httpserversetup.md) &gt; [server](./kibana-plugin-server.httpserversetup.server.md)

## HttpServerSetup.server property

<b>Signature:</b>

```typescript
server: Server;
```
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
<b>Signature:</b>

```typescript
createNewServer: (cfg: Partial<HttpConfig>) => Promise<HttpServerSetup>;
createNewServer: (port: number, ssl: SslConfigType) => Promise<HttpServerSetup>;
```
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ export interface HttpServiceSetup extends HttpServerSetup

| Property | Type | Description |
| --- | --- | --- |
| [createNewServer](./kibana-plugin-server.httpservicesetup.createnewserver.md) | <code>(cfg: Partial&lt;HttpConfig&gt;) =&gt; Promise&lt;HttpServerSetup&gt;</code> | |
| [createNewServer](./kibana-plugin-server.httpservicesetup.createnewserver.md) | <code>(port: number, ssl: SslConfigType) =&gt; Promise&lt;HttpServerSetup&gt;</code> | |

1 change: 1 addition & 0 deletions docs/development/core/server/kibana-plugin-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ The plugin integrates with the core system via lifecycle events: `setup`<!-- -->
| [ElasticsearchError](./kibana-plugin-server.elasticsearcherror.md) | |
| [ElasticsearchServiceSetup](./kibana-plugin-server.elasticsearchservicesetup.md) | |
| [FakeRequest](./kibana-plugin-server.fakerequest.md) | Fake request object created manually by Kibana plugins. |
| [HttpServerSetup](./kibana-plugin-server.httpserversetup.md) | |
| [HttpServiceSetup](./kibana-plugin-server.httpservicesetup.md) | |
| [HttpServiceStart](./kibana-plugin-server.httpservicestart.md) | |
| [InternalCoreStart](./kibana-plugin-server.internalcorestart.md) | |
Expand Down
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@
"@types/lodash.clonedeep": "^4.5.4",
"@types/react-grid-layout": "^0.16.7",
"@types/recompose": "^0.30.5",
"@types/wreck": "^14.0.0",
"JSONStream": "1.3.5",
"abortcontroller-polyfill": "^1.1.9",
"angular": "1.6.9",
Expand Down Expand Up @@ -300,6 +301,7 @@
"@types/graphql": "^0.13.1",
"@types/hapi": "^17.0.18",
"@types/hapi-auth-cookie": "^9.1.0",
"@types/hapi__wreck": "^15.0.0",
"@types/has-ansi": "^3.0.0",
"@types/hoek": "^4.1.3",
"@types/humps": "^1.1.2",
Expand Down Expand Up @@ -425,6 +427,7 @@
"regenerate": "^1.4.0",
"sass-lint": "^1.12.1",
"selenium-webdriver": "^4.0.0-alpha.4",
"selfsigned": "^1.10.4",
"simple-git": "1.116.0",
"sinon": "^7.2.2",
"strip-ansi": "^3.0.1",
Expand Down
8 changes: 8 additions & 0 deletions renovate.json5
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,14 @@
'@types/lodash.clonedeep',
],
},
{
groupSlug: 'wreck',
groupName: 'wreck related packages',
packageNames: [
'wreck',
'@types/wreck',
],
},
{
groupSlug: 'bluebird',
groupName: 'bluebird related packages',
Expand Down
10 changes: 5 additions & 5 deletions src/core/server/elasticsearch/elasticsearch_service.mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,15 @@ const createClusterClientMock = (): jest.Mocked<PublicMethodsOf<ClusterClient>>
close: jest.fn(),
});

const createSetupContractMock = () => {
const setupContract: jest.Mocked<ElasticsearchServiceSetup> = {
const createSetupContractMock = (clients = { adminClient: {}, dataClient: {} }) => {
const setupContract: ElasticsearchServiceSetup = {
legacy: {
config$: new BehaviorSubject({} as ElasticsearchConfig),
},

createClient: jest.fn().mockImplementation(createClusterClientMock),
adminClient$: new BehaviorSubject((createClusterClientMock() as unknown) as ClusterClient),
dataClient$: new BehaviorSubject((createClusterClientMock() as unknown) as ClusterClient),
createClient: jest.fn(),
adminClient$: new BehaviorSubject(clients.adminClient as ClusterClient),
dataClient$: new BehaviorSubject(clients.dataClient as ClusterClient),
};
return setupContract;
};
Expand Down
46 changes: 35 additions & 11 deletions src/core/server/http/http_service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@

import { mockHttpServer } from './http_service.test.mocks';

import crypto from 'crypto';
import { tmpdir } from 'os';
import { writeFileSync, unlinkSync } from 'fs';
import { join } from 'path';
import selfsigned from 'selfsigned';
import { noop } from 'lodash';
import { BehaviorSubject } from 'rxjs';
import { HttpService, Router } from '.';
Expand All @@ -28,6 +33,9 @@ import { Config, ConfigService, Env, ObjectToConfigAdapter } from '../config';
import { loggingServiceMock } from '../logging/logging_service.mock';
import { getEnvOptions } from '../config/__mocks__/env';

// `crypto` type definitions doesn't currently include `crypto.constants`, see
// https://github.com/DefinitelyTyped/DefinitelyTyped/blob/fa5baf1733f49cf26228a4e509914572c1b74adf/types/node/v6/index.d.ts#L3412
const cryptoConstants = (crypto as any).constants;
const logger = loggingServiceMock.create();
const env = Env.createDefault(getEnvOptions());

Expand Down Expand Up @@ -135,6 +143,13 @@ test('spins up notReady server until started if configured with `autoListen:true

// this is an integration test!
test('creates and sets up second http server', async () => {
const tmp = tmpdir();
const keyFile = join(tmp, 'tmp-key');
const certFile = join(tmp, 'tmp-cert');
const attrs = [{ name: 'commonName', value: 'kibana.dev' }];
const pems = selfsigned.generate(attrs, { days: 365 });
writeFileSync(keyFile, pems.private, 'utf8');
writeFileSync(certFile, pems.cert, 'utf8');
const configService = createConfigService({
host: 'localhost',
port: 1234,
Expand All @@ -145,32 +160,41 @@ test('creates and sets up second http server', async () => {

const service = new HttpService({ configService, env, logger });
const serverSetup = await service.setup();
const cfg = { port: 2345 };
await serverSetup.createNewServer(cfg);
const port = 2345;
const ssl = {
enabled: true,
redirectHttpFromPort: port,
certificate: certFile,
key: keyFile,
certificateAuthorities: undefined,
cipherSuites: cryptoConstants.defaultCoreCipherList.split(':'),
keyPassphrase: undefined,
supportedProtocols: ['TLSv1.1', 'TLSv1.2'],
requestCert: true,
};

await serverSetup.createNewServer(port, ssl);
const server = await service.start();
expect(server.isListening()).toBeTruthy();
expect(server.isListening(cfg.port)).toBeTruthy();
expect(server.isListening(port)).toBeTruthy();

try {
await serverSetup.createNewServer(cfg);
await serverSetup.createNewServer(port, ssl);
} catch (err) {
expect(err.message).toBe('port 2345 is already in use');
}

try {
await serverSetup.createNewServer({ port: 1234 });
await serverSetup.createNewServer(1234, ssl);
} catch (err) {
expect(err.message).toBe('port 1234 is already in use');
}

try {
await serverSetup.createNewServer({ host: 'example.org' });
} catch (err) {
expect(err.message).toBe('port must be defined');
}
await service.stop();
expect(server.isListening()).toBeFalsy();
expect(server.isListening(cfg.port)).toBeFalsy();
expect(server.isListening(port)).toBeFalsy();
unlinkSync(certFile);
unlinkSync(keyFile);
});

test('logs error if already set up', async () => {
Expand Down
16 changes: 8 additions & 8 deletions src/core/server/http/http_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,14 @@ import { LoggerFactory } from '../logging';
import { CoreService } from '../../types';
import { Logger } from '../logging';
import { CoreContext } from '../core_context';
import { HttpConfig, HttpConfigType, config as httpConfig } from './http_config';
import { HttpConfig, HttpConfigType } from './http_config';
import { HttpServer, HttpServerSetup } from './http_server';
import { HttpsRedirectServer } from './https_redirect_server';
import { SslConfig, SslConfigType } from './ssl_config';

/** @public */
export interface HttpServiceSetup extends HttpServerSetup {
createNewServer: (cfg: Partial<HttpConfig>) => Promise<HttpServerSetup>;
createNewServer: (port: number, ssl: SslConfigType) => Promise<HttpServerSetup>;
}
/** @public */
export interface HttpServiceStart {
Expand Down Expand Up @@ -129,8 +130,7 @@ export class HttpService implements CoreService<HttpServiceSetup, HttpServiceSta
return !this.coreContext.env.isDevClusterMaster && config.autoListen;
}

private async createServer(cfg: Partial<HttpConfig>) {
const { port } = cfg;
private async createServer(port: number, ssl: SslConfigType) {
const config = await this.config$.pipe(first()).toPromise();

if (!port) {
Expand All @@ -141,10 +141,10 @@ export class HttpService implements CoreService<HttpServiceSetup, HttpServiceSta
if (this.secondaryServers.has(port) || config.port === port) {
throw new Error(`port ${port} is already in use`);
}

for (const [key, val] of Object.entries(cfg)) {
httpConfig.schema.validateKey(key, val);
}
const cfg: Partial<HttpConfig> = {
port,
ssl: new SslConfig(ssl),
};

const baseConfig = await this.config$.pipe(first()).toPromise();
const finalConfig = { ...baseConfig, ...cfg };
Expand Down
26 changes: 26 additions & 0 deletions src/core/server/http/selfsigned.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

declare module 'selfsigned' {
export function generate(
attrs: any[],
options: { [key: string]: any },
done?: (err: Error, certs: any) => void
): any;
}
2 changes: 1 addition & 1 deletion src/core/server/http/ssl_config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export const sslSchema = schema.object(
}
);

type SslConfigType = TypeOf<typeof sslSchema>;
export type SslConfigType = TypeOf<typeof sslSchema>;

export class SslConfig {
public enabled: boolean;
Expand Down
1 change: 1 addition & 0 deletions src/core/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ export {
SessionStorageFactory,
SessionStorage,
} from './http';
export { HttpServerSetup } from './http/http_server';
export { Logger, LoggerFactory, LogMeta, LogRecord, LogLevel } from './logging';

export {
Expand Down
Loading