Skip to content

Commit 8bf9487

Browse files
jeramysoucykibanamachine
authored andcommitted
Surface Kibana security route deprecations in Upgrade Assistant (elastic#199656)
Closes elastic#197389 ## Summary Uses the `deprecated` route configuration option on all Kibana Security "v1" endpoints. This will surface deprecation information in the Upgrade Assistant. ## Related PRs - elastic#50695 - `7.6.0`, deprecated - `/api/security/v1/me` - `/api/security/v1/logout` - `/api/security/v1/oidc/implicit` - `/api/security/v1/oidc` (POST) - elastic#53886 - `7.6.0`, deprecated `/api/security/v1/oidc` (GET) - elastic#47929 - `8.0.0`, dropped `/api/security/v1/saml` (`breaking` release note) - elastic#106665 - restored `/api/security/v1/saml` but warned as deprecated (no release note) ## Testing 1. Start ES & Kibana in trial license mode 2. Make several calls to one or more of the deprecated endpoints 3. Navigate to `Stack Management`->`Upgrade Assistant` 4. Click on Kibana warnings <img width="1003" alt="Screenshot 2024-11-18 at 10 01 10 AM" src="https://github.com/user-attachments/assets/da44af13-57eb-4ffd-a507-e423eb767a11"> 5. Confirm the called endpoints are displayed as warnings in the Upgrade Assistant <img width="1274" alt="Screenshot 2024-11-18 at 9 59 34 AM" src="https://github.com/user-attachments/assets/4c054fbe-6838-48cf-8b1b-8c161252db0f"> ## Previous release notes ### v7.6.0 https://www.elastic.co/guide/en/kibana/7.6/release-notes-7.6.0.html#deprecation-7.6.0 https://www.elastic.co/guide/en/kibana/7.6/breaking-changes-7.6.html The deprecations are not listed in the release notes or breaking changes notes. ### v8.0.0 https://www.elastic.co/guide/en/kibana/current/release-notes-8.0.0-alpha1.html#rest-api-changes SAML endpoint deprecation only appears in the 8.0.0-alpha1 release notes, and was reverted in 8.0.0-alpha2 # Release note See `docs/upgrade-notes.asciidoc` in file changes # Follow-up A follow-up PR must be created to create and backfill the docLinks. --------- Co-authored-by: kibanamachine <[email protected]>
1 parent 7c4e25e commit 8bf9487

File tree

10 files changed

+157
-28
lines changed

10 files changed

+157
-28
lines changed

docs/upgrade-notes.asciidoc

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,32 @@ For Elastic Security release information, refer to {security-guide}/release-note
4949
[float]
5050
==== Kibana APIs
5151

52+
[discrete]
53+
[[breaking-199656]]
54+
.Removed all security v1 endpoints (9.0.0)
55+
[%collapsible]
56+
====
57+
*Details* +
58+
All `v1` Kibana security HTTP endpoints have been removed.
59+
60+
`GET /api/security/v1/logout` has been replaced by `GET /api/security/logout`
61+
`GET /api/security/v1/oidc/implicit` has been replaced by `GET /api/security/oidc/implicit`
62+
`GET /api/security/v1/oidc` has been replaced by GET `/api/security/oidc/callback`
63+
`POST /api/security/v1/oidc` has been replaced by POST `/api/security/oidc/initiate_login`
64+
`POST /api/security/v1/saml` has been replaced by POST `/api/security/saml/callback`
65+
`GET /api/security/v1/me` has been removed with no replacement.
66+
67+
For more information, refer to {kibana-pull}199656[#199656].
68+
69+
*Impact* +
70+
Any HTTP API calls to the `v1` Kibana security endpoints will fail with a 404 status code starting from version 9.0.0.
71+
Third party OIDC and SAML identity providers configured with `v1` endpoints will no longer work.
72+
73+
*Action* +
74+
Update any OIDC and SAML identity providers to reference the corresponding replacement endpoint listed above.
75+
Remove references to the `/api/security/v1/me` endpoint from any automations, applications, tooling, and scripts.
76+
====
77+
5278
[discrete]
5379
[[breaking-193792]]
5480
.Access to all internal APIs is blocked (9.0.0)
@@ -814,18 +840,6 @@ The legacy audit logger has been removed. For more information, refer to {kibana
814840
Audit logs will be written to the default location in the new ECS format. To change the output file, filter events, and more, use the <<audit-logging-settings, audit logging settings>>.
815841
====
816842

817-
[discrete]
818-
[[breaking-47929]]
819-
.[Security] Removed `/api/security/v1/saml` route. (8.0)
820-
[%collapsible]
821-
====
822-
*Details* +
823-
The `/api/security/v1/saml` route has been removed and is reflected in the kibana.yml `server.xsrf.whitelist` setting, {es}, and the Identity Provider SAML settings. For more information, refer to {kibana-pull}47929[#47929]
824-
825-
*Impact* +
826-
Use the `/api/security/saml/callback` route, or wait to upgrade to 8.0.0-alpha2 when the `/api/security/saml/callback` route breaking change is reverted.
827-
====
828-
829843
[discrete]
830844
[[breaking-41700]]
831845
.[Security] Legacy browsers rejected by default. (8.0)

packages/kbn-doc-links/src/get_doc_links.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -717,6 +717,7 @@ export const getDocLinks = ({ kibanaBranch, buildFlavor }: GetDocLinkOptions): D
717717
mappingRoles: `${ELASTICSEARCH_DOCS}mapping-roles.html`,
718718
mappingRolesFieldRules: `${ELASTICSEARCH_DOCS}role-mapping-resources.html#mapping-roles-rule-field`,
719719
runAsPrivilege: `${ELASTICSEARCH_DOCS}security-privileges.html#_run_as_privilege`,
720+
deprecatedV1Endpoints: `${KIBANA_DOCS}breaking-changes-summary.html#breaking-199656`,
720721
},
721722
spaces: {
722723
kibanaLegacyUrlAliases: `${KIBANA_DOCS}legacy-url-aliases.html`,

packages/kbn-doc-links/src/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,7 @@ export interface DocLinks {
505505
mappingRoles: string;
506506
mappingRolesFieldRules: string;
507507
runAsPrivilege: string;
508+
deprecatedV1Endpoints: string;
508509
}>;
509510
readonly spaces: Readonly<{
510511
kibanaLegacyUrlAliases: string;

x-pack/plugins/security/server/plugin.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,7 @@ export class SecurityPlugin
338338
getUserProfileService: this.getUserProfileService,
339339
analyticsService: this.analyticsService.setup({ analytics: core.analytics }),
340340
buildFlavor: this.initializerContext.env.packageInfo.buildFlavor,
341+
docLinks: core.docLinks,
341342
});
342343

343344
return Object.freeze<SecurityPluginSetup>({

x-pack/plugins/security/server/routes/authentication/common.ts

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import type { TypeOf } from '@kbn/config-schema';
99
import { schema } from '@kbn/config-schema';
10+
import { i18n } from '@kbn/i18n';
1011
import { parseNextURL } from '@kbn/std';
1112

1213
import type { RouteDefinitionParams } from '..';
@@ -33,13 +34,15 @@ export function defineCommonRoutes({
3334
license,
3435
logger,
3536
buildFlavor,
37+
docLinks,
3638
}: RouteDefinitionParams) {
3739
// Generate two identical routes with new and deprecated URL and issue a warning if route with deprecated URL is ever used.
3840
// For a serverless build, do not register deprecated versioned routes
3941
for (const path of [
4042
'/api/security/logout',
4143
...(buildFlavor !== 'serverless' ? ['/api/security/v1/logout'] : []),
4244
]) {
45+
const isDeprecated = path === '/api/security/v1/logout';
4346
router.get(
4447
{
4548
path,
@@ -57,13 +60,29 @@ export function defineCommonRoutes({
5760
excludeFromOAS: true,
5861
authRequired: false,
5962
tags: [ROUTE_TAG_CAN_REDIRECT, ROUTE_TAG_AUTH_FLOW],
63+
...(isDeprecated && {
64+
deprecated: {
65+
documentationUrl: docLinks.links.security.deprecatedV1Endpoints,
66+
severity: 'warning',
67+
message: i18n.translate('xpack.security.deprecations.logoutRouteMessage', {
68+
defaultMessage:
69+
'The "{path}" URL is deprecated and will be removed in the next major version. Use "/api/security/logout" instead.',
70+
values: { path },
71+
}),
72+
reason: {
73+
type: 'migrate',
74+
newApiMethod: 'GET',
75+
newApiPath: '/api/security/logout',
76+
},
77+
},
78+
}),
6079
},
6180
},
6281
async (context, request, response) => {
6382
const serverBasePath = basePath.serverBasePath;
64-
if (path === '/api/security/v1/logout') {
83+
if (isDeprecated) {
6584
logger.warn(
66-
`The "${serverBasePath}${path}" URL is deprecated and will stop working in the next major version, please use "${serverBasePath}/api/security/logout" URL instead.`,
85+
`The "${serverBasePath}${path}" URL is deprecated and will stop working in the next major version. Use "${serverBasePath}/api/security/logout" URL instead.`,
6786
{ tags: ['deprecation'] }
6887
);
6988
}
@@ -96,7 +115,7 @@ export function defineCommonRoutes({
96115
'/internal/security/me',
97116
...(buildFlavor !== 'serverless' ? ['/api/security/v1/me'] : []),
98117
]) {
99-
const deprecated = path === '/api/security/v1/me';
118+
const isDeprecated = path === '/api/security/v1/me';
100119
router.get(
101120
{
102121
path,
@@ -107,10 +126,24 @@ export function defineCommonRoutes({
107126
},
108127
},
109128
validate: false,
110-
options: { access: deprecated ? 'public' : 'internal' },
129+
options: {
130+
access: isDeprecated ? 'public' : 'internal',
131+
...(isDeprecated && {
132+
deprecated: {
133+
documentationUrl: docLinks.links.security.deprecatedV1Endpoints,
134+
severity: 'warning',
135+
message: i18n.translate('xpack.security.deprecations.meRouteMessage', {
136+
defaultMessage:
137+
'The "{path}" endpoint is deprecated and will be removed in the next major version.',
138+
values: { path },
139+
}),
140+
reason: { type: 'remove' },
141+
},
142+
}),
143+
},
111144
},
112145
createLicensedRouteHandler(async (context, request, response) => {
113-
if (deprecated) {
146+
if (isDeprecated) {
114147
logger.warn(
115148
`The "${basePath.serverBasePath}${path}" endpoint is deprecated and will be removed in the next major version.`,
116149
{ tags: ['deprecation'] }

x-pack/plugins/security/server/routes/authentication/oidc.ts

Lines changed: 63 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,11 @@ export function defineOIDCRoutes({
2525
logger,
2626
getAuthenticationService,
2727
basePath,
28+
docLinks,
2829
}: RouteDefinitionParams) {
2930
// Generate two identical routes with new and deprecated URL and issue a warning if route with deprecated URL is ever used.
3031
for (const path of ['/api/security/oidc/implicit', '/api/security/v1/oidc/implicit']) {
32+
const isDeprecated = path === '/api/security/v1/oidc/implicit';
3133
/**
3234
* The route should be configured as a redirect URI in OP when OpenID Connect implicit flow
3335
* is used, so that we can extract authentication response from URL fragment and send it to
@@ -37,13 +39,32 @@ export function defineOIDCRoutes({
3739
{
3840
path,
3941
validate: false,
40-
options: { authRequired: false, excludeFromOAS: true },
42+
options: {
43+
authRequired: false,
44+
excludeFromOAS: true,
45+
...(isDeprecated && {
46+
deprecated: {
47+
documentationUrl: docLinks.links.security.deprecatedV1Endpoints,
48+
severity: 'warning',
49+
message: i18n.translate('xpack.security.deprecations.oidcImplicitRouteMessage', {
50+
defaultMessage:
51+
'The "{path}" URL is deprecated and will be removed in the next major version. Use "/api/security/oidc/implicit" instead.',
52+
values: { path },
53+
}),
54+
reason: {
55+
type: 'migrate',
56+
newApiMethod: 'GET',
57+
newApiPath: '/api/security/oidc/implicit',
58+
},
59+
},
60+
}),
61+
},
4162
},
4263
(context, request, response) => {
4364
const serverBasePath = basePath.serverBasePath;
44-
if (path === '/api/security/v1/oidc/implicit') {
65+
if (isDeprecated) {
4566
logger.warn(
46-
`The "${serverBasePath}${path}" URL is deprecated and will stop working in the next major version, please use "${serverBasePath}/api/security/oidc/implicit" URL instead.`,
67+
`The "${serverBasePath}${path}" URL is deprecated and will stop working in the next major version. Use "${serverBasePath}/api/security/oidc/implicit" URL instead.`,
4768
{ tags: ['deprecation'] }
4869
);
4970
}
@@ -84,6 +105,7 @@ export function defineOIDCRoutes({
84105

85106
// Generate two identical routes with new and deprecated URL and issue a warning if route with deprecated URL is ever used.
86107
for (const path of ['/api/security/oidc/callback', '/api/security/v1/oidc']) {
108+
const isDeprecated = path === '/api/security/v1/oidc';
87109
router.get(
88110
{
89111
path,
@@ -117,6 +139,22 @@ export function defineOIDCRoutes({
117139
excludeFromOAS: true,
118140
authRequired: false,
119141
tags: [ROUTE_TAG_CAN_REDIRECT, ROUTE_TAG_AUTH_FLOW],
142+
...(isDeprecated && {
143+
deprecated: {
144+
documentationUrl: docLinks.links.security.deprecatedV1Endpoints,
145+
severity: 'warning',
146+
message: i18n.translate('xpack.security.deprecations.oidcCallbackRouteMessage', {
147+
defaultMessage:
148+
'The "{path}" URL is deprecated and will be removed in the next major version. Use "/api/security/oidc/callback" instead.',
149+
values: { path },
150+
}),
151+
reason: {
152+
type: 'migrate',
153+
newApiMethod: 'GET',
154+
newApiPath: '/api/security/oidc/callback',
155+
},
156+
},
157+
}),
120158
},
121159
},
122160
createLicensedRouteHandler(async (context, request, response) => {
@@ -133,9 +171,9 @@ export function defineOIDCRoutes({
133171
authenticationResponseURI: request.query.authenticationResponseURI,
134172
};
135173
} else if (request.query.code || request.query.error) {
136-
if (path === '/api/security/v1/oidc') {
174+
if (isDeprecated) {
137175
logger.warn(
138-
`The "${serverBasePath}${path}" URL is deprecated and will stop working in the next major version, please use "${serverBasePath}/api/security/oidc/callback" URL instead.`,
176+
`The "${serverBasePath}${path}" URL is deprecated and will stop working in the next major version. Use "${serverBasePath}/api/security/oidc/callback" URL instead.`,
139177
{ tags: ['deprecation'] }
140178
);
141179
}
@@ -150,7 +188,7 @@ export function defineOIDCRoutes({
150188
};
151189
} else if (request.query.iss) {
152190
logger.warn(
153-
`The "${serverBasePath}${path}" URL is deprecated and will stop working in the next major version, please use "${serverBasePath}/api/security/oidc/initiate_login" URL for Third-Party Initiated login instead.`,
191+
`The "${serverBasePath}${path}" URL is deprecated and will stop working in the next major version. Use "${serverBasePath}/api/security/oidc/initiate_login" URL for Third-Party Initiated login instead.`,
154192
{ tags: ['deprecation'] }
155193
);
156194
// An HTTP GET request with a query parameter named `iss` as part of a 3rd party initiated authentication.
@@ -175,6 +213,7 @@ export function defineOIDCRoutes({
175213

176214
// Generate two identical routes with new and deprecated URL and issue a warning if route with deprecated URL is ever used.
177215
for (const path of ['/api/security/oidc/initiate_login', '/api/security/v1/oidc']) {
216+
const isDeprecated = path === '/api/security/v1/oidc';
178217
/**
179218
* An HTTP POST request with the payload parameter named `iss` as part of a 3rd party initiated authentication.
180219
* See more details at https://openid.net/specs/openid-connect-core-1_0.html#ThirdPartyInitiatedLogin
@@ -206,13 +245,29 @@ export function defineOIDCRoutes({
206245
authRequired: false,
207246
xsrfRequired: false,
208247
tags: [ROUTE_TAG_CAN_REDIRECT, ROUTE_TAG_AUTH_FLOW],
248+
...(isDeprecated && {
249+
deprecated: {
250+
documentationUrl: docLinks.links.security.deprecatedV1Endpoints,
251+
severity: 'warning',
252+
message: i18n.translate('xpack.security.deprecations.oidcInitiateRouteMessage', {
253+
defaultMessage:
254+
'The "{path}" URL is deprecated and will be removed in the next major version. Use "/api/security/oidc/initiate_login" instead.',
255+
values: { path },
256+
}),
257+
reason: {
258+
type: 'migrate',
259+
newApiMethod: 'POST',
260+
newApiPath: '/api/security/oidc/initiate_login',
261+
},
262+
},
263+
}),
209264
},
210265
},
211266
createLicensedRouteHandler(async (context, request, response) => {
212267
const serverBasePath = basePath.serverBasePath;
213-
if (path === '/api/security/v1/oidc') {
268+
if (isDeprecated) {
214269
logger.warn(
215-
`The "${serverBasePath}${path}" URL is deprecated and will stop working in the next major version, please use "${serverBasePath}/api/security/oidc/initiate_login" URL for Third-Party Initiated login instead.`,
270+
`The "${serverBasePath}${path}" URL is deprecated and will stop working in the next major version. Use "${serverBasePath}/api/security/oidc/initiate_login" URL for Third-Party Initiated login instead.`,
216271
{ tags: ['deprecation'] }
217272
);
218273
}

x-pack/plugins/security/server/routes/authentication/saml.ts

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77

88
import { schema } from '@kbn/config-schema';
9+
import { i18n } from '@kbn/i18n';
910

1011
import type { RouteDefinitionParams } from '..';
1112
import { SAMLAuthenticationProvider, SAMLLogin } from '../../authentication';
@@ -20,13 +21,15 @@ export function defineSAMLRoutes({
2021
basePath,
2122
logger,
2223
buildFlavor,
24+
docLinks,
2325
}: RouteDefinitionParams) {
2426
// Generate two identical routes with new and deprecated URL and issue a warning if route with deprecated URL is ever used.
2527
// For a serverless build, do not register deprecated versioned routes
2628
for (const path of [
2729
'/api/security/saml/callback',
2830
...(buildFlavor !== 'serverless' ? ['/api/security/v1/saml'] : []),
2931
]) {
32+
const isDeprecated = path === '/api/security/v1/saml';
3033
router.post(
3134
{
3235
path,
@@ -48,14 +51,30 @@ export function defineSAMLRoutes({
4851
authRequired: false,
4952
xsrfRequired: false,
5053
tags: [ROUTE_TAG_CAN_REDIRECT, ROUTE_TAG_AUTH_FLOW],
54+
...(isDeprecated && {
55+
deprecated: {
56+
documentationUrl: docLinks.links.security.deprecatedV1Endpoints,
57+
severity: 'warning',
58+
message: i18n.translate('xpack.security.deprecations.samlPostRouteMessage', {
59+
defaultMessage:
60+
'The "{path}" URL is deprecated and will be removed in the next major version. Use "/api/security/saml/callback" instead.',
61+
values: { path },
62+
}),
63+
reason: {
64+
type: 'migrate',
65+
newApiMethod: 'POST',
66+
newApiPath: '/api/security/saml/callback',
67+
},
68+
},
69+
}),
5170
},
5271
},
5372
async (context, request, response) => {
54-
if (path === '/api/security/v1/saml') {
73+
if (isDeprecated) {
5574
const serverBasePath = basePath.serverBasePath;
5675
logger.warn(
5776
// When authenticating using SAML we _expect_ to redirect to the SAML Identity provider.
58-
`The "${serverBasePath}${path}" URL is deprecated and might stop working in a future release. Please use "${serverBasePath}/api/security/saml/callback" URL instead.`
77+
`The "${serverBasePath}${path}" URL is deprecated and might stop working in a future release. Use "${serverBasePath}/api/security/saml/callback" URL instead.`
5978
);
6079
}
6180

x-pack/plugins/security/server/routes/index.mock.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
httpServiceMock,
1414
loggingSystemMock,
1515
} from '@kbn/core/server/mocks';
16+
import { getDocLinks } from '@kbn/doc-links';
1617
import { licensingMock } from '@kbn/licensing-plugin/server/mocks';
1718
import type { DeeplyMockedKeys } from '@kbn/utility-types-jest';
1819

@@ -50,6 +51,8 @@ export const routeDefinitionParamsMock = {
5051
getAnonymousAccessService: jest.fn(),
5152
getUserProfileService: jest.fn().mockReturnValue(userProfileServiceMock.createStart()),
5253
analyticsService: analyticsServiceMock.createSetup(),
54+
buildFlavor: 'traditional',
55+
docLinks: { links: getDocLinks({ kibanaBranch: 'main', buildFlavor: 'traditional' }) },
5356
} as unknown as DeeplyMockedKeys<RouteDefinitionParams>;
5457
},
5558
};

x-pack/plugins/security/server/routes/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import type { Observable } from 'rxjs';
99

1010
import type { BuildFlavor } from '@kbn/config/src/types';
11-
import type { HttpResources, IBasePath, Logger } from '@kbn/core/server';
11+
import type { DocLinksServiceSetup, HttpResources, IBasePath, Logger } from '@kbn/core/server';
1212
import type { KibanaFeature } from '@kbn/features-plugin/server';
1313
import type { SubFeaturePrivilegeIterator } from '@kbn/features-plugin/server/feature_privilege_iterator';
1414
import type { PublicMethodsOf } from '@kbn/utility-types';
@@ -59,6 +59,7 @@ export interface RouteDefinitionParams {
5959
getAnonymousAccessService: () => AnonymousAccessServiceStart;
6060
analyticsService: AnalyticsServiceSetup;
6161
buildFlavor: BuildFlavor;
62+
docLinks: DocLinksServiceSetup;
6263
}
6364

6465
export function defineRoutes(params: RouteDefinitionParams) {

0 commit comments

Comments
 (0)