Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[8.x] Surface Kibana security route deprecations in Upgrade Assistant (#199656) #201320

Merged
merged 1 commit into from
Nov 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
60 changes: 48 additions & 12 deletions docs/upgrade-notes.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,54 @@ For Elastic Security release information, refer to {security-guide}/release-note
[float]
==== Kibana APIs

[discrete]
[[breaking-199656]]
.Removed all security v1 endpoints (9.0.0)
[%collapsible]
====
*Details* +
All `v1` Kibana security HTTP endpoints have been removed.

`GET /api/security/v1/logout` has been replaced by `GET /api/security/logout`
`GET /api/security/v1/oidc/implicit` has been replaced by `GET /api/security/oidc/implicit`
`GET /api/security/v1/oidc` has been replaced by GET `/api/security/oidc/callback`
`POST /api/security/v1/oidc` has been replaced by POST `/api/security/oidc/initiate_login`
`POST /api/security/v1/saml` has been replaced by POST `/api/security/saml/callback`
`GET /api/security/v1/me` has been removed with no replacement.

For more information, refer to {kibana-pull}199656[#199656].

*Impact* +
Any HTTP API calls to the `v1` Kibana security endpoints will fail with a 404 status code starting from version 9.0.0.
Third party OIDC and SAML identity providers configured with `v1` endpoints will no longer work.

*Action* +
Update any OIDC and SAML identity providers to reference the corresponding replacement endpoint listed above.
Remove references to the `/api/security/v1/me` endpoint from any automations, applications, tooling, and scripts.
====

[discrete]
[[breaking-193792]]
.Access to all internal APIs is blocked (9.0.0)
[%collapsible]
====
*Details* +
Access to internal Kibana HTTP APIs is restricted from version 9.0.0. This is to ensure
that HTTP API integrations with Kibana avoid unexpected breaking changes.
Refer to {kibana-pull}193792[#193792].

*Impact* +
Any HTTP API calls to internal Kibana endpoints will fail with a 400 status code starting
from version 9.0.0.

*Action* +
**Do not integrate with internal HTTP APIs**. They may change or be removed without notice,
and lead to unexpected behaviors. If you would like some capability to be exposed over an
HTTP API, https://github.com/elastic/kibana/issues/new/choose[create an issue].
We would love to discuss your use case.

====

[discrete]
[[breaking-162506]]
.Get case metrics APIs became internal. (8.10)
Expand Down Expand Up @@ -792,18 +840,6 @@ The legacy audit logger has been removed. For more information, refer to {kibana
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>>.
====

[discrete]
[[breaking-47929]]
.[Security] Removed `/api/security/v1/saml` route. (8.0)
[%collapsible]
====
*Details* +
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]

*Impact* +
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.
====

[discrete]
[[breaking-41700]]
.[Security] Legacy browsers rejected by default. (8.0)
Expand Down
1 change: 1 addition & 0 deletions packages/kbn-doc-links/src/get_doc_links.ts
Original file line number Diff line number Diff line change
Expand Up @@ -722,6 +722,7 @@ export const getDocLinks = ({ kibanaBranch, buildFlavor }: GetDocLinkOptions): D
mappingRoles: `${ELASTICSEARCH_DOCS}mapping-roles.html`,
mappingRolesFieldRules: `${ELASTICSEARCH_DOCS}role-mapping-resources.html#mapping-roles-rule-field`,
runAsPrivilege: `${ELASTICSEARCH_DOCS}security-privileges.html#_run_as_privilege`,
deprecatedV1Endpoints: `${KIBANA_DOCS}breaking-changes-summary.html#breaking-199656`,
},
spaces: {
kibanaLegacyUrlAliases: `${KIBANA_DOCS}legacy-url-aliases.html`,
Expand Down
1 change: 1 addition & 0 deletions packages/kbn-doc-links/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,7 @@ export interface DocLinks {
mappingRoles: string;
mappingRolesFieldRules: string;
runAsPrivilege: string;
deprecatedV1Endpoints: string;
}>;
readonly spaces: Readonly<{
kibanaLegacyUrlAliases: string;
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/security/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,7 @@ export class SecurityPlugin
getUserProfileService: this.getUserProfileService,
analyticsService: this.analyticsService.setup({ analytics: core.analytics }),
buildFlavor: this.initializerContext.env.packageInfo.buildFlavor,
docLinks: core.docLinks,
});

return Object.freeze<SecurityPluginSetup>({
Expand Down
43 changes: 38 additions & 5 deletions x-pack/plugins/security/server/routes/authentication/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import type { TypeOf } from '@kbn/config-schema';
import { schema } from '@kbn/config-schema';
import { i18n } from '@kbn/i18n';
import { parseNextURL } from '@kbn/std';

import type { RouteDefinitionParams } from '..';
Expand All @@ -33,13 +34,15 @@ export function defineCommonRoutes({
license,
logger,
buildFlavor,
docLinks,
}: RouteDefinitionParams) {
// Generate two identical routes with new and deprecated URL and issue a warning if route with deprecated URL is ever used.
// For a serverless build, do not register deprecated versioned routes
for (const path of [
'/api/security/logout',
...(buildFlavor !== 'serverless' ? ['/api/security/v1/logout'] : []),
]) {
const isDeprecated = path === '/api/security/v1/logout';
router.get(
{
path,
Expand All @@ -57,13 +60,29 @@ export function defineCommonRoutes({
excludeFromOAS: true,
authRequired: false,
tags: [ROUTE_TAG_CAN_REDIRECT, ROUTE_TAG_AUTH_FLOW],
...(isDeprecated && {
deprecated: {
documentationUrl: docLinks.links.security.deprecatedV1Endpoints,
severity: 'warning',
message: i18n.translate('xpack.security.deprecations.logoutRouteMessage', {
defaultMessage:
'The "{path}" URL is deprecated and will be removed in the next major version. Use "/api/security/logout" instead.',
values: { path },
}),
reason: {
type: 'migrate',
newApiMethod: 'GET',
newApiPath: '/api/security/logout',
},
},
}),
},
},
async (context, request, response) => {
const serverBasePath = basePath.serverBasePath;
if (path === '/api/security/v1/logout') {
if (isDeprecated) {
logger.warn(
`The "${serverBasePath}${path}" URL is deprecated and will stop working in the next major version, please use "${serverBasePath}/api/security/logout" URL instead.`,
`The "${serverBasePath}${path}" URL is deprecated and will stop working in the next major version. Use "${serverBasePath}/api/security/logout" URL instead.`,
{ tags: ['deprecation'] }
);
}
Expand Down Expand Up @@ -96,7 +115,7 @@ export function defineCommonRoutes({
'/internal/security/me',
...(buildFlavor !== 'serverless' ? ['/api/security/v1/me'] : []),
]) {
const deprecated = path === '/api/security/v1/me';
const isDeprecated = path === '/api/security/v1/me';
router.get(
{
path,
Expand All @@ -107,10 +126,24 @@ export function defineCommonRoutes({
},
},
validate: false,
options: { access: deprecated ? 'public' : 'internal' },
options: {
access: isDeprecated ? 'public' : 'internal',
...(isDeprecated && {
deprecated: {
documentationUrl: docLinks.links.security.deprecatedV1Endpoints,
severity: 'warning',
message: i18n.translate('xpack.security.deprecations.meRouteMessage', {
defaultMessage:
'The "{path}" endpoint is deprecated and will be removed in the next major version.',
values: { path },
}),
reason: { type: 'remove' },
},
}),
},
},
createLicensedRouteHandler(async (context, request, response) => {
if (deprecated) {
if (isDeprecated) {
logger.warn(
`The "${basePath.serverBasePath}${path}" endpoint is deprecated and will be removed in the next major version.`,
{ tags: ['deprecation'] }
Expand Down
71 changes: 63 additions & 8 deletions x-pack/plugins/security/server/routes/authentication/oidc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@ export function defineOIDCRoutes({
logger,
getAuthenticationService,
basePath,
docLinks,
}: RouteDefinitionParams) {
// Generate two identical routes with new and deprecated URL and issue a warning if route with deprecated URL is ever used.
for (const path of ['/api/security/oidc/implicit', '/api/security/v1/oidc/implicit']) {
const isDeprecated = path === '/api/security/v1/oidc/implicit';
/**
* The route should be configured as a redirect URI in OP when OpenID Connect implicit flow
* is used, so that we can extract authentication response from URL fragment and send it to
Expand All @@ -37,13 +39,32 @@ export function defineOIDCRoutes({
{
path,
validate: false,
options: { authRequired: false, excludeFromOAS: true },
options: {
authRequired: false,
excludeFromOAS: true,
...(isDeprecated && {
deprecated: {
documentationUrl: docLinks.links.security.deprecatedV1Endpoints,
severity: 'warning',
message: i18n.translate('xpack.security.deprecations.oidcImplicitRouteMessage', {
defaultMessage:
'The "{path}" URL is deprecated and will be removed in the next major version. Use "/api/security/oidc/implicit" instead.',
values: { path },
}),
reason: {
type: 'migrate',
newApiMethod: 'GET',
newApiPath: '/api/security/oidc/implicit',
},
},
}),
},
},
(context, request, response) => {
const serverBasePath = basePath.serverBasePath;
if (path === '/api/security/v1/oidc/implicit') {
if (isDeprecated) {
logger.warn(
`The "${serverBasePath}${path}" URL is deprecated and will stop working in the next major version, please use "${serverBasePath}/api/security/oidc/implicit" URL instead.`,
`The "${serverBasePath}${path}" URL is deprecated and will stop working in the next major version. Use "${serverBasePath}/api/security/oidc/implicit" URL instead.`,
{ tags: ['deprecation'] }
);
}
Expand Down Expand Up @@ -84,6 +105,7 @@ export function defineOIDCRoutes({

// Generate two identical routes with new and deprecated URL and issue a warning if route with deprecated URL is ever used.
for (const path of ['/api/security/oidc/callback', '/api/security/v1/oidc']) {
const isDeprecated = path === '/api/security/v1/oidc';
router.get(
{
path,
Expand Down Expand Up @@ -117,6 +139,22 @@ export function defineOIDCRoutes({
excludeFromOAS: true,
authRequired: false,
tags: [ROUTE_TAG_CAN_REDIRECT, ROUTE_TAG_AUTH_FLOW],
...(isDeprecated && {
deprecated: {
documentationUrl: docLinks.links.security.deprecatedV1Endpoints,
severity: 'warning',
message: i18n.translate('xpack.security.deprecations.oidcCallbackRouteMessage', {
defaultMessage:
'The "{path}" URL is deprecated and will be removed in the next major version. Use "/api/security/oidc/callback" instead.',
values: { path },
}),
reason: {
type: 'migrate',
newApiMethod: 'GET',
newApiPath: '/api/security/oidc/callback',
},
},
}),
},
},
createLicensedRouteHandler(async (context, request, response) => {
Expand All @@ -133,9 +171,9 @@ export function defineOIDCRoutes({
authenticationResponseURI: request.query.authenticationResponseURI,
};
} else if (request.query.code || request.query.error) {
if (path === '/api/security/v1/oidc') {
if (isDeprecated) {
logger.warn(
`The "${serverBasePath}${path}" URL is deprecated and will stop working in the next major version, please use "${serverBasePath}/api/security/oidc/callback" URL instead.`,
`The "${serverBasePath}${path}" URL is deprecated and will stop working in the next major version. Use "${serverBasePath}/api/security/oidc/callback" URL instead.`,
{ tags: ['deprecation'] }
);
}
Expand All @@ -150,7 +188,7 @@ export function defineOIDCRoutes({
};
} else if (request.query.iss) {
logger.warn(
`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.`,
`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.`,
{ tags: ['deprecation'] }
);
// An HTTP GET request with a query parameter named `iss` as part of a 3rd party initiated authentication.
Expand All @@ -175,6 +213,7 @@ export function defineOIDCRoutes({

// Generate two identical routes with new and deprecated URL and issue a warning if route with deprecated URL is ever used.
for (const path of ['/api/security/oidc/initiate_login', '/api/security/v1/oidc']) {
const isDeprecated = path === '/api/security/v1/oidc';
/**
* An HTTP POST request with the payload parameter named `iss` as part of a 3rd party initiated authentication.
* See more details at https://openid.net/specs/openid-connect-core-1_0.html#ThirdPartyInitiatedLogin
Expand Down Expand Up @@ -206,13 +245,29 @@ export function defineOIDCRoutes({
authRequired: false,
xsrfRequired: false,
tags: [ROUTE_TAG_CAN_REDIRECT, ROUTE_TAG_AUTH_FLOW],
...(isDeprecated && {
deprecated: {
documentationUrl: docLinks.links.security.deprecatedV1Endpoints,
severity: 'warning',
message: i18n.translate('xpack.security.deprecations.oidcInitiateRouteMessage', {
defaultMessage:
'The "{path}" URL is deprecated and will be removed in the next major version. Use "/api/security/oidc/initiate_login" instead.',
values: { path },
}),
reason: {
type: 'migrate',
newApiMethod: 'POST',
newApiPath: '/api/security/oidc/initiate_login',
},
},
}),
},
},
createLicensedRouteHandler(async (context, request, response) => {
const serverBasePath = basePath.serverBasePath;
if (path === '/api/security/v1/oidc') {
if (isDeprecated) {
logger.warn(
`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.`,
`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.`,
{ tags: ['deprecation'] }
);
}
Expand Down
23 changes: 21 additions & 2 deletions x-pack/plugins/security/server/routes/authentication/saml.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/

import { schema } from '@kbn/config-schema';
import { i18n } from '@kbn/i18n';

import type { RouteDefinitionParams } from '..';
import { SAMLAuthenticationProvider, SAMLLogin } from '../../authentication';
Expand All @@ -20,13 +21,15 @@ export function defineSAMLRoutes({
basePath,
logger,
buildFlavor,
docLinks,
}: RouteDefinitionParams) {
// Generate two identical routes with new and deprecated URL and issue a warning if route with deprecated URL is ever used.
// For a serverless build, do not register deprecated versioned routes
for (const path of [
'/api/security/saml/callback',
...(buildFlavor !== 'serverless' ? ['/api/security/v1/saml'] : []),
]) {
const isDeprecated = path === '/api/security/v1/saml';
router.post(
{
path,
Expand All @@ -48,14 +51,30 @@ export function defineSAMLRoutes({
authRequired: false,
xsrfRequired: false,
tags: [ROUTE_TAG_CAN_REDIRECT, ROUTE_TAG_AUTH_FLOW],
...(isDeprecated && {
deprecated: {
documentationUrl: docLinks.links.security.deprecatedV1Endpoints,
severity: 'warning',
message: i18n.translate('xpack.security.deprecations.samlPostRouteMessage', {
defaultMessage:
'The "{path}" URL is deprecated and will be removed in the next major version. Use "/api/security/saml/callback" instead.',
values: { path },
}),
reason: {
type: 'migrate',
newApiMethod: 'POST',
newApiPath: '/api/security/saml/callback',
},
},
}),
},
},
async (context, request, response) => {
if (path === '/api/security/v1/saml') {
if (isDeprecated) {
const serverBasePath = basePath.serverBasePath;
logger.warn(
// When authenticating using SAML we _expect_ to redirect to the SAML Identity provider.
`The "${serverBasePath}${path}" URL is deprecated and might stop working in a future release. Please use "${serverBasePath}/api/security/saml/callback" URL instead.`
`The "${serverBasePath}${path}" URL is deprecated and might stop working in a future release. Use "${serverBasePath}/api/security/saml/callback" URL instead.`
);
}

Expand Down
Loading