Skip to content

Commit 1887f29

Browse files
authored
Merge branch 'main' into disable_scripted_fields_serverless
2 parents 3480c52 + 9cff5fc commit 1887f29

123 files changed

Lines changed: 1284 additions & 957 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.backportrc.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"repoName": "kibana",
44
"targetBranchChoices": [
55
"main",
6+
"8.10",
67
"8.9",
78
"8.8",
89
"8.7",
@@ -46,7 +47,7 @@
4647
"backport"
4748
],
4849
"branchLabelMapping": {
49-
"^v8.10.0$": "main",
50+
"^v8.11.0$": "main",
5051
"^v(\\d+).(\\d+).\\d+$": "$1.$2"
5152
},
5253
"autoMerge": true,

docs/CHANGELOG.asciidoc

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,6 @@ Review important information about the {kib} 8.x releases.
4949
[[release-notes-8.9.1]]
5050
== {kib} 8.9.1
5151

52-
coming::[8.9.1]
53-
5452
Review the following information about the {kib} 8.9.1 release.
5553

5654
[float]

docs/api-generated/connectors/connector-apis-passthru.asciidoc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2475,15 +2475,15 @@ Any modifications made to this file will be overwritten.
24752475
<div class='model-description'></div>
24762476
<div class="field-items">
24772477
<div class="param">name </div><div class="param-desc"><span class="param-type"><a href="#string">String</a></span> The display name for the connector. </div>
2478-
<div class="param">secrets </div><div class="param-desc"><span class="param-type"><a href="#">secrets_properties_slack_api</a></span> </div>
2478+
<div class="param">secrets </div><div class="param-desc"><span class="param-type"><a href="#secrets_properties_slack_api">secrets_properties_slack_api</a></span> </div>
24792479
</div> <!-- field-items -->
24802480
</div>
24812481
<div class="model">
24822482
<h3><a name="update_connector_request_slack_webhook"><code>update_connector_request_slack_webhook</code> - Update Slack connector request</a> <a class="up" href="#__Models">Up</a></h3>
24832483
<div class='model-description'></div>
24842484
<div class="field-items">
24852485
<div class="param">name </div><div class="param-desc"><span class="param-type"><a href="#string">String</a></span> The display name for the connector. </div>
2486-
<div class="param">secrets </div><div class="param-desc"><span class="param-type"><a href="#">secrets_properties_slack_webhook</a></span> </div>
2486+
<div class="param">secrets </div><div class="param-desc"><span class="param-type"><a href="#secrets_properties_slack_webhook">secrets_properties_slack_webhook</a></span> </div>
24872487
</div> <!-- field-items -->
24882488
</div>
24892489
<div class="model">

docs/user/ml/index.asciidoc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,3 +223,11 @@ point type selector to filter the results by specific types of change points.
223223

224224
[role="screenshot"]
225225
image::user/ml/images/ml-change-point-detection-selected.png[Selected change points]
226+
227+
228+
You can attach change point charts to a dashboard or a case by using the context
229+
menu. If the split field is selected, you can either select specific charts
230+
(partitions) or set the maximum number of top change points to plot. It's
231+
possible to preserve the applied time range or use the time bound from the page
232+
date picker. You can also add or edit change point charts directly from the
233+
**Dashboard** app.

packages/core/http/core-http-common/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@ export type { ApiVersion } from './src/versioning';
1212
export {
1313
ELASTIC_HTTP_VERSION_HEADER,
1414
ELASTIC_HTTP_VERSION_QUERY_PARAM,
15+
ELASTIC_INTERNAL_ORIGIN_QUERY_PARAM,
1516
X_ELASTIC_INTERNAL_ORIGIN_REQUEST,
1617
} from './src/constants';

packages/core/http/core-http-common/src/constants.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@
99
/** @public */
1010
export const ELASTIC_HTTP_VERSION_HEADER = 'elastic-api-version' as const;
1111
export const ELASTIC_HTTP_VERSION_QUERY_PARAM = 'apiVersion' as const;
12-
12+
export const ELASTIC_INTERNAL_ORIGIN_QUERY_PARAM = 'elasticInternalOrigin' as const;
1313
export const X_ELASTIC_INTERNAL_ORIGIN_REQUEST = 'x-elastic-internal-origin' as const;

packages/core/http/core-http-router-server-internal/src/request.test.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ import { hapiMocks } from '@kbn/hapi-mocks';
1515
import type { FakeRawRequest } from '@kbn/core-http-server';
1616
import { CoreKibanaRequest } from './request';
1717
import { schema } from '@kbn/config-schema';
18+
import {
19+
ELASTIC_INTERNAL_ORIGIN_QUERY_PARAM,
20+
X_ELASTIC_INTERNAL_ORIGIN_REQUEST,
21+
} from '@kbn/core-http-common';
1822

1923
describe('CoreKibanaRequest', () => {
2024
describe('using real requests', () => {
@@ -145,6 +149,58 @@ describe('CoreKibanaRequest', () => {
145149
});
146150
});
147151

152+
describe('isInternalApiRequest property', () => {
153+
it('is true when header is set', () => {
154+
const request = hapiMocks.createRequest({
155+
headers: { [X_ELASTIC_INTERNAL_ORIGIN_REQUEST]: 'true' },
156+
});
157+
const kibanaRequest = CoreKibanaRequest.from(request);
158+
expect(kibanaRequest.isInternalApiRequest).toBe(true);
159+
});
160+
it('is true when query param is set', () => {
161+
const request = hapiMocks.createRequest({
162+
query: { [ELASTIC_INTERNAL_ORIGIN_QUERY_PARAM]: 'true' },
163+
});
164+
const kibanaRequest = CoreKibanaRequest.from(request);
165+
expect(kibanaRequest.isInternalApiRequest).toBe(true);
166+
});
167+
it('is true when both header and query param is set', () => {
168+
const request = hapiMocks.createRequest({
169+
headers: { [X_ELASTIC_INTERNAL_ORIGIN_REQUEST]: 'true' },
170+
query: { [ELASTIC_INTERNAL_ORIGIN_QUERY_PARAM]: 'true' },
171+
});
172+
const kibanaRequest = CoreKibanaRequest.from(request);
173+
expect(kibanaRequest.isInternalApiRequest).toBe(true);
174+
});
175+
it('is false when neither header nor query param is set', () => {
176+
const request = hapiMocks.createRequest();
177+
const kibanaRequest = CoreKibanaRequest.from(request);
178+
expect(kibanaRequest.isInternalApiRequest).toBe(false);
179+
});
180+
});
181+
182+
describe('sanitize input', () => {
183+
it('does not pass the reserved query parameter to consumers', () => {
184+
const request = hapiMocks.createRequest({
185+
query: { [ELASTIC_INTERNAL_ORIGIN_QUERY_PARAM]: 'true', myCoolValue: 'cool!' },
186+
});
187+
const kibanaRequest = CoreKibanaRequest.from(request, {
188+
query: schema.object({ myCoolValue: schema.string() }),
189+
});
190+
expect(kibanaRequest.query).toEqual({ myCoolValue: 'cool!' });
191+
});
192+
it('pass nothing if only the reserved query param is present', () => {
193+
const request = hapiMocks.createRequest({
194+
query: { [ELASTIC_INTERNAL_ORIGIN_QUERY_PARAM]: 'true' },
195+
});
196+
expect(() =>
197+
CoreKibanaRequest.from(request, {
198+
query: schema.object({}, { unknowns: 'forbid' }), // we require an empty object
199+
})
200+
).not.toThrow();
201+
});
202+
});
203+
148204
describe('route.options.authRequired property', () => {
149205
it('handles required auth: undefined', () => {
150206
const auth: RouteOptions['auth'] = undefined;

packages/core/http/core-http-router-server-internal/src/request.ts

Lines changed: 47 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ import {
2929
RawRequest,
3030
FakeRawRequest,
3131
} from '@kbn/core-http-server';
32+
import {
33+
ELASTIC_INTERNAL_ORIGIN_QUERY_PARAM,
34+
X_ELASTIC_INTERNAL_ORIGIN_REQUEST,
35+
} from '@kbn/core-http-common';
3236
import { RouteValidator } from './validator';
3337
import { isSafeMethod } from './route';
3438
import { KibanaSocket } from './socket';
@@ -59,7 +63,13 @@ export class CoreKibanaRequest<
5963
withoutSecretHeaders: boolean = true
6064
) {
6165
const routeValidator = RouteValidator.from<P, Q, B>(routeSchemas);
62-
const requestParts = CoreKibanaRequest.validate(req, routeValidator);
66+
let requestParts: { params: P; query: Q; body: B };
67+
if (isFakeRawRequest(req)) {
68+
requestParts = { query: {} as Q, params: {} as P, body: {} as B };
69+
} else {
70+
const rawParts = CoreKibanaRequest.sanitizeRequest(req);
71+
requestParts = CoreKibanaRequest.validate(rawParts, routeValidator);
72+
}
6373
return new CoreKibanaRequest(
6474
req,
6575
requestParts.params,
@@ -69,50 +79,65 @@ export class CoreKibanaRequest<
6979
);
7080
}
7181

82+
/**
83+
* We have certain values that may be passed via query params that we want to
84+
* exclude from further processing like validation. This method removes those
85+
* internal values.
86+
*/
87+
private static sanitizeRequest<P, Q, B>(
88+
req: Request
89+
): { query: unknown; params: unknown; body: unknown } {
90+
const { [ELASTIC_INTERNAL_ORIGIN_QUERY_PARAM]: __, ...query } = req.query ?? {};
91+
return {
92+
query,
93+
params: req.params,
94+
body: req.payload,
95+
};
96+
}
97+
7298
/**
7399
* Validates the different parts of a request based on the schemas defined for
74100
* the route. Builds up the actual params, query and body object that will be
75101
* received in the route handler.
76102
* @internal
77103
*/
78104
private static validate<P, Q, B>(
79-
req: RawRequest,
105+
raw: { params: unknown; query: unknown; body: unknown },
80106
routeValidator: RouteValidator<P, Q, B>
81107
): {
82108
params: P;
83109
query: Q;
84110
body: B;
85111
} {
86-
if (isFakeRawRequest(req)) {
87-
return { query: {} as Q, params: {} as P, body: {} as B };
88-
}
89-
const params = routeValidator.getParams(req.params, 'request params');
90-
const query = routeValidator.getQuery(req.query, 'request query');
91-
const body = routeValidator.getBody(req.payload, 'request body');
112+
const params = routeValidator.getParams(raw.params, 'request params');
113+
const query = routeValidator.getQuery(raw.query, 'request query');
114+
const body = routeValidator.getBody(raw.body, 'request body');
92115
return { query, params, body };
93116
}
94117

95-
/** {@inheritDoc IKibanaRequest.id} */
118+
/** {@inheritDoc KibanaRequest.id} */
96119
public readonly id: string;
97-
/** {@inheritDoc IKibanaRequest.uuid} */
120+
/** {@inheritDoc KibanaRequest.uuid} */
98121
public readonly uuid: string;
99-
/** {@inheritDoc IKibanaRequest.url} */
122+
/** {@inheritDoc KibanaRequest.url} */
100123
public readonly url: URL;
101-
/** {@inheritDoc IKibanaRequest.route} */
124+
/** {@inheritDoc KibanaRequest.route} */
102125
public readonly route: RecursiveReadonly<KibanaRequestRoute<Method>>;
103-
/** {@inheritDoc IKibanaRequest.headers} */
126+
/** {@inheritDoc KibanaRequest.headers} */
104127
public readonly headers: Headers;
105-
/** {@inheritDoc IKibanaRequest.isSystemRequest} */
128+
/** {@inheritDoc KibanaRequest.isSystemRequest} */
106129
public readonly isSystemRequest: boolean;
107-
/** {@inheritDoc IKibanaRequest.socket} */
130+
/** {@inheritDoc KibanaRequest.socket} */
108131
public readonly socket: IKibanaSocket;
109-
/** {@inheritDoc IKibanaRequest.events} */
132+
/** {@inheritDoc KibanaRequest.events} */
110133
public readonly events: KibanaRequestEvents;
111-
/** {@inheritDoc IKibanaRequest.auth} */
134+
/** {@inheritDoc KibanaRequest.auth} */
112135
public readonly auth: KibanaRequestAuth;
113-
/** {@inheritDoc IKibanaRequest.isFakeRequest} */
136+
/** {@inheritDoc KibanaRequest.isFakeRequest} */
114137
public readonly isFakeRequest: boolean;
115-
/** {@inheritDoc IKibanaRequest.rewrittenUrl} */
138+
/** {@inheritDoc KibanaRequest.isInternalApiRequest} */
139+
public readonly isInternalApiRequest: boolean;
140+
/** {@inheritDoc KibanaRequest.rewrittenUrl} */
116141
public readonly rewrittenUrl?: URL;
117142

118143
/** @internal */
@@ -139,7 +164,9 @@ export class CoreKibanaRequest<
139164
this.headers = isRealRawRequest(request) ? deepFreeze({ ...request.headers }) : request.headers;
140165
this.isSystemRequest = this.headers['kbn-system-request'] === 'true';
141166
this.isFakeRequest = isFakeRawRequest(request);
142-
167+
this.isInternalApiRequest =
168+
X_ELASTIC_INTERNAL_ORIGIN_REQUEST in this.headers ||
169+
Boolean(this.url?.searchParams?.has(ELASTIC_INTERNAL_ORIGIN_QUERY_PARAM));
143170
// prevent Symbol exposure via Object.getOwnPropertySymbols()
144171
Object.defineProperty(this, requestSymbol, {
145172
value: request,

packages/core/http/core-http-server-internal/src/lifecycle_handlers.test.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,18 +39,21 @@ const createToolkit = (): ToolkitMock => {
3939

4040
const forgeRequest = ({
4141
headers = {},
42+
query = {},
4243
path = '/',
4344
method = 'get',
4445
kibanaRouteOptions,
4546
}: Partial<{
4647
headers: Record<string, string>;
48+
query: Record<string, string>;
4749
path: string;
4850
method: RouteMethod;
4951
kibanaRouteOptions: KibanaRouteOptions;
5052
}>): KibanaRequest => {
5153
return mockRouter.createKibanaRequest({
5254
headers,
5355
path,
56+
query,
5457
method,
5558
kibanaRouteOptions,
5659
});
@@ -259,11 +262,13 @@ describe('restrictInternal post-auth handler', () => {
259262
});
260263
const createForgeRequest = (
261264
access: 'internal' | 'public',
262-
headers: Record<string, string> | undefined = {}
265+
headers: Record<string, string> | undefined = {},
266+
query: Record<string, string> | undefined = {}
263267
) => {
264268
return forgeRequest({
265269
method: 'get',
266270
headers,
271+
query,
267272
path: `/${access}/some-path`,
268273
kibanaRouteOptions: {
269274
xsrfRequired: false,
@@ -318,6 +323,24 @@ describe('restrictInternal post-auth handler', () => {
318323
const request = createForgeRequest('public');
319324
createForwardSuccess(handler, request);
320325
});
326+
327+
it('forward the request to the next interceptor if called with internal origin query param for internal API', () => {
328+
const handler = createRestrictInternalRoutesPostAuthHandler(config as HttpConfig);
329+
const request = createForgeRequest('internal', undefined, { elasticInternalOrigin: 'true' });
330+
createForwardSuccess(handler, request);
331+
});
332+
333+
it('forward the request to the next interceptor if called with internal origin query param for public APIs', () => {
334+
const handler = createRestrictInternalRoutesPostAuthHandler(config as HttpConfig);
335+
const request = createForgeRequest('internal', undefined, { elasticInternalOrigin: 'true' });
336+
createForwardSuccess(handler, request);
337+
});
338+
339+
it('forward the request to the next interceptor if called without internal origin query param for public APIs', () => {
340+
const handler = createRestrictInternalRoutesPostAuthHandler(config as HttpConfig);
341+
const request = createForgeRequest('public');
342+
createForwardSuccess(handler, request);
343+
});
321344
});
322345

323346
describe('when restriction is not enabled', () => {

packages/core/http/core-http-server-internal/src/lifecycle_handlers.ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88

99
import type { OnPostAuthHandler, OnPreResponseHandler } from '@kbn/core-http-server';
1010
import { isSafeMethod } from '@kbn/core-http-router-server-internal';
11-
import { X_ELASTIC_INTERNAL_ORIGIN_REQUEST } from '@kbn/core-http-common/src/constants';
1211
import { HttpConfig } from './http_config';
1312

1413
const VERSION_HEADER = 'kbn-version';
@@ -45,11 +44,7 @@ export const createRestrictInternalRoutesPostAuthHandler = (
4544

4645
return (request, response, toolkit) => {
4746
const isInternalRoute = request.route.options.access === 'internal';
48-
49-
// only check if the header is present, not it's content.
50-
const hasInternalKibanaRequestHeader = X_ELASTIC_INTERNAL_ORIGIN_REQUEST in request.headers;
51-
52-
if (isRestrictionEnabled && isInternalRoute && !hasInternalKibanaRequestHeader) {
47+
if (isRestrictionEnabled && isInternalRoute && !request.isInternalApiRequest) {
5348
// throw 400
5449
return response.badRequest({
5550
body: `uri [${request.url}] with method [${request.route.method}] exists but is not available with the current configuration`,
@@ -75,7 +70,6 @@ export const createVersionCheckPostAuthHandler = (kibanaVersion: string): OnPost
7570
},
7671
});
7772
}
78-
7973
return toolkit.next();
8074
};
8175
};

0 commit comments

Comments
 (0)