diff --git a/.github/workflows/security-route-migration.yaml b/.github/workflows/security-route-migration.yaml new file mode 100644 index 0000000000000..93eb21191337f --- /dev/null +++ b/.github/workflows/security-route-migration.yaml @@ -0,0 +1,58 @@ +name: ESLint no_deprecated_authz_config + +on: + push: + branches: + - authz-migration-workflow + workflow_dispatch: + inputs: + route_type: + description: 'Choose route type (authorized/unauthorized)' + required: true + default: 'authorized' + type: choice + options: + - authorized + - unauthorized + +jobs: + eslint-autofix: + name: Run no_deprecated_authz_config rule + runs-on: ubuntu-latest + permissions: + actions: read + contents: write + security-events: write + + env: + ROUTE_TYPE: ${{ github.event.inputs.route_type }} + GH_TOKEN: ${{ secrets.KIBANAMACHINE_TOKEN }} + + steps: + - name: Checkout repository + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + with: + ref: ${{ matrix.branch }} + + - name: setup node + uses: actions/setup-node@v4 + with: + node-version-file: '.nvmrc' + + - name: Set GitHub name and email + run: | + git config --global user.name 'kibanamachine' + git config --global user.email '42973632+kibanamachine@users.noreply.github.com' + + - name: yarn kbn bootstrap + run: | + yarn kbn bootstrap --no-validate --no-vscode + + - name: Install GitHub CLI + run: sudo apt-get install gh -y + + # - name: Authenticate with GitHub CLI + # run: gh auth login + - name: Run ESLint Autofix Script + run: node scripts/eslint-security-route.js + diff --git a/packages/kbn-eslint-config/.eslintrc.js b/packages/kbn-eslint-config/.eslintrc.js index f241131cd6273..c41babbf47762 100644 --- a/packages/kbn-eslint-config/.eslintrc.js +++ b/packages/kbn-eslint-config/.eslintrc.js @@ -326,6 +326,7 @@ module.exports = { '@kbn/imports/uniform_imports': 'error', '@kbn/imports/no_unused_imports': 'error', '@kbn/imports/no_boundary_crossing': 'error', + 'kbn/eslint/no_deprecated_authz_config': 'off', 'no-new-func': 'error', 'no-implied-eval': 'error', diff --git a/packages/kbn-eslint-plugin-eslint/rules/no_deprecated_authz_config.js b/packages/kbn-eslint-plugin-eslint/rules/no_deprecated_authz_config.js index f6485d0914c15..088577582959f 100644 --- a/packages/kbn-eslint-plugin-eslint/rules/no_deprecated_authz_config.js +++ b/packages/kbn-eslint-plugin-eslint/rules/no_deprecated_authz_config.js @@ -72,7 +72,7 @@ const maybeReportDisabledSecurityConfig = (node, context, isVersionedRoute = fal ); const accessTagsFilter = (el) => isLiteralAccessTag(el) || isTemplateLiteralAccessTag(el); - const accessTags = tagsProperty.value.elements.filter(accessTagsFilter); + const accessTags = tagsProperty?.value.elements.filter(accessTagsFilter) ?? []; return accessTags.length > 0; } diff --git a/scripts/eslint-security-route.js b/scripts/eslint-security-route.js new file mode 100644 index 0000000000000..1671599cdbd70 --- /dev/null +++ b/scripts/eslint-security-route.js @@ -0,0 +1,143 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +/* eslint-disable no-restricted-syntax */ + +const { execSync } = require('child_process'); +const fs = require('fs'); +const path = require('path'); + +function runCommand(command) { + try { + return execSync(command, { encoding: 'utf8' }).trim(); + } catch (err) { + console.error(`Error running command: ${command}`); + console.error(err.stdout.toString()); + process.exit(1); + } +} + +function parseCodeOwners(codeownersPath) { + const codeowners = {}; + const content = fs.readFileSync(codeownersPath, 'utf8').split('\n'); + + content.forEach((line) => { + const trimmed = line.trim(); + if (!trimmed || trimmed.startsWith('#')) return; + + const [pattern, owner] = trimmed.split(/\s+/); + if (pattern && owner) { + codeowners[pattern] = owner; + } + }); + + return codeowners; +} + +function getChangedFiles() { + const diffOutput = runCommand('git diff --name-only --diff-filter=M'); + return diffOutput.split('\n').filter(Boolean); +} + +function groupFilesByOwners(files, codeowners) { + const ownerFilesMap = {}; + + files.forEach((file) => { + for (const [pattern, owner] of Object.entries(codeowners)) { + const regexPattern = pattern + .replace(/\*\*/g, '.*') + .replace(/\*/g, '[^/]*') + .replace(/\//g, '\\/'); + + const regex = new RegExp(`${regexPattern}`); + + if (regex.test(file)) { + if (!ownerFilesMap[owner]) ownerFilesMap[owner] = []; + ownerFilesMap[owner].push(file); + break; + } + } + }); + + return ownerFilesMap; +} + +// Create a branch, stage, and commit files for each owner +function processChangesByOwners(ownerFilesMap) { + const mainBranch = execSync('git rev-parse --abbrev-ref HEAD'); + + for (const [owner, files] of Object.entries(ownerFilesMap)) { + const branchName = `eslint/changes-by-${owner.replace('@elastic/', '')}`; + + console.log(`Owner: ${owner}`); + console.log(`Files: ${files.join(', ')} \n ----`); + console.log(`Creating branch: ${branchName}`); + + runCommand(`git checkout -b ${branchName}`); + + const fileList = files.join(' '); + runCommand(`git add ${fileList}`); + runCommand(`git commit -m "Changes for ${owner}"`); + + console.log(`Pushing branch: ${branchName}`); + runCommand(`git push -u origin ${branchName}`); + + console.log(`Creating pull request for branch: ${branchName}`); + runCommand( + `gh pr create --base main --head ${branchName} --title "ESLint fixes for ${owner}" --body "This PR contains ESLint fixes for files owned by ${owner}"` + ); + + runCommand(`git checkout ${mainBranch}`); + } +} + +function runESLint() { + console.log(`Running ESLint on ${process.env.ROUTE_TYPE} routes...`); + const eslintRuleFlag = + process.env.ROUTE_TYPE === 'authorized' + ? 'MIGRATE_DISABLED_AUTHZ=false' + : 'MIGRATE_DISABLED_AUTHZ=true'; + + try { + runCommand( + `${eslintRuleFlag} grep -rEl --include="*.ts" "router\.(get|post|delete|put)|router\.versioned\.(get|post|put|delete)" ./x-pack/plugins/security | xargs npx eslint --fix --rule "@kbn/eslint/no_deprecated_authz_config:error"` + ); + + // runCommand( + // `${eslintRuleFlag} grep -rEl --include="*.ts" "router\.(get|post|delete|put)|router\.versioned\.(get|post|put|delete)" ./x-pack/plugins/banners | xargs npx eslint --fix --rule "@kbn/eslint/no_deprecated_authz_config:error"` + // ); + console.log('ESLint autofix complete'); + } catch (error) { + console.error('Error running ESLint:', error); + } +} + +function main() { + const codeownersPath = path.resolve('.github', 'CODEOWNERS'); + if (!fs.existsSync(codeownersPath)) { + console.error('CODEOWNERS file not found'); + process.exit(1); + } + + const codeowners = parseCodeOwners(codeownersPath); + + runESLint(); + + const changedFiles = getChangedFiles(); + if (changedFiles.length === 0) { + console.log('No changes detected.'); + return; + } + + const ownerFilesMap = groupFilesByOwners(changedFiles, codeowners); + + processChangesByOwners(ownerFilesMap); +} + +main(); diff --git a/x-pack/plugins/security/server/authorization/api_authorization.ts b/x-pack/plugins/security/server/authorization/api_authorization.ts index ba38d9ca0aa20..8931418a563a0 100644 --- a/x-pack/plugins/security/server/authorization/api_authorization.ts +++ b/x-pack/plugins/security/server/authorization/api_authorization.ts @@ -87,17 +87,17 @@ export function initAPIAuthorization( const missingPrivileges = Object.keys(kibanaPrivileges).filter( (key) => !kibanaPrivileges[key] ); - logger.warn( - `User not authorized for "${request.url.pathname}${ - request.url.search - }", responding with 403: missing privileges: ${missingPrivileges.join(', ')}` - ); + const forbiddenMessage = `API [${request.route.method.toLocaleUpperCase('en')} ${ + request.url.pathname + }${ + request.url.search + }] is unauthorized for user, this action is granted by the Kibana privileges [${missingPrivileges}]`; + + logger.warn(`Responding with 403: ${forbiddenMessage}}`); return response.forbidden({ body: { - message: `User not authorized for ${request.url.pathname}${ - request.url.search - }, missing privileges: ${missingPrivileges.join(', ')}`, + message: forbiddenMessage, }, }); } diff --git a/x-pack/plugins/security/server/routes/analytics/authentication_type.ts b/x-pack/plugins/security/server/routes/analytics/authentication_type.ts index f2bf76c71b1ab..6c4f67f70cc58 100644 --- a/x-pack/plugins/security/server/routes/analytics/authentication_type.ts +++ b/x-pack/plugins/security/server/routes/analytics/authentication_type.ts @@ -31,6 +31,12 @@ export function defineRecordAnalyticsOnAuthTypeRoutes({ router.post( { path: '/internal/security/analytics/_record_auth_type', + security: { + authz: { + enabled: false, + reason: 'This route is opted out from authorization', + }, + }, validate: { body: schema.nullable( schema.object({ signature: schema.string(), timestamp: schema.number() }) diff --git a/x-pack/plugins/security/server/routes/analytics/record_violations.ts b/x-pack/plugins/security/server/routes/analytics/record_violations.ts index 826a304f1656e..cc1eb72c7fb55 100644 --- a/x-pack/plugins/security/server/routes/analytics/record_violations.ts +++ b/x-pack/plugins/security/server/routes/analytics/record_violations.ts @@ -135,6 +135,12 @@ export function defineRecordViolations({ router, analyticsService }: RouteDefini router.post( { path: '/internal/security/analytics/_record_violations', + security: { + authz: { + enabled: false, + reason: 'This route is opted out from authorization', + }, + }, validate: { /** * Chrome supports CSP3 spec and sends an array of reports. Safari only sends a single diff --git a/x-pack/plugins/security/server/routes/anonymous_access/get_capabilities.ts b/x-pack/plugins/security/server/routes/anonymous_access/get_capabilities.ts index 220fb1515df46..dbc52da0b8947 100644 --- a/x-pack/plugins/security/server/routes/anonymous_access/get_capabilities.ts +++ b/x-pack/plugins/security/server/routes/anonymous_access/get_capabilities.ts @@ -15,7 +15,16 @@ export function defineAnonymousAccessGetCapabilitiesRoutes({ getAnonymousAccessService, }: RouteDefinitionParams) { router.get( - { path: '/internal/security/anonymous_access/capabilities', validate: false }, + { + path: '/internal/security/anonymous_access/capabilities', + security: { + authz: { + enabled: false, + reason: 'This route is opted out from authorization', + }, + }, + validate: false, + }, async (_context, request, response) => { const anonymousAccessService = getAnonymousAccessService(); return response.ok({ body: await anonymousAccessService.getCapabilities(request) }); diff --git a/x-pack/plugins/security/server/routes/anonymous_access/get_state.ts b/x-pack/plugins/security/server/routes/anonymous_access/get_state.ts index 28745c80a5f44..1e544f19da2aa 100644 --- a/x-pack/plugins/security/server/routes/anonymous_access/get_state.ts +++ b/x-pack/plugins/security/server/routes/anonymous_access/get_state.ts @@ -18,7 +18,16 @@ export function defineAnonymousAccessGetStateRoutes({ getAnonymousAccessService, }: RouteDefinitionParams) { router.get( - { path: '/internal/security/anonymous_access/state', validate: false }, + { + path: '/internal/security/anonymous_access/state', + security: { + authz: { + enabled: false, + reason: 'This route is opted out from authorization', + }, + }, + validate: false, + }, async (_context, _request, response) => { const anonymousAccessService = getAnonymousAccessService(); const accessURLParameters = anonymousAccessService.accessURLParameters diff --git a/x-pack/plugins/security/server/routes/api_keys/create.ts b/x-pack/plugins/security/server/routes/api_keys/create.ts index 59d743e3726aa..b68163146e7b5 100644 --- a/x-pack/plugins/security/server/routes/api_keys/create.ts +++ b/x-pack/plugins/security/server/routes/api_keys/create.ts @@ -32,6 +32,12 @@ export function defineCreateApiKeyRoutes({ router.post( { path: '/internal/security/api_key', + security: { + authz: { + enabled: false, + reason: 'This route is opted out from authorization', + }, + }, validate: { body: schema.oneOf([ restApiKeySchema, diff --git a/x-pack/plugins/security/server/routes/api_keys/enabled.ts b/x-pack/plugins/security/server/routes/api_keys/enabled.ts index c94c8af61e24f..81c7a0d0c66d4 100644 --- a/x-pack/plugins/security/server/routes/api_keys/enabled.ts +++ b/x-pack/plugins/security/server/routes/api_keys/enabled.ts @@ -16,6 +16,12 @@ export function defineEnabledApiKeysRoutes({ router.get( { path: '/internal/security/api_key/_enabled', + security: { + authz: { + enabled: false, + reason: 'This route is opted out from authorization', + }, + }, validate: false, }, createLicensedRouteHandler(async (context, request, response) => { diff --git a/x-pack/plugins/security/server/routes/api_keys/has_active.ts b/x-pack/plugins/security/server/routes/api_keys/has_active.ts index bf432b1861045..5e9f377dc1cbc 100644 --- a/x-pack/plugins/security/server/routes/api_keys/has_active.ts +++ b/x-pack/plugins/security/server/routes/api_keys/has_active.ts @@ -22,6 +22,12 @@ export function defineHasApiKeysRoutes({ router.get( { path: '/internal/security/api_key/_has_active', + security: { + authz: { + enabled: false, + reason: 'This route is opted out from authorization', + }, + }, validate: false, options: { access: 'internal', diff --git a/x-pack/plugins/security/server/routes/api_keys/invalidate.ts b/x-pack/plugins/security/server/routes/api_keys/invalidate.ts index 1983dbf2344e0..818d137a495fd 100644 --- a/x-pack/plugins/security/server/routes/api_keys/invalidate.ts +++ b/x-pack/plugins/security/server/routes/api_keys/invalidate.ts @@ -21,6 +21,12 @@ export function defineInvalidateApiKeysRoutes({ router }: RouteDefinitionParams) router.post( { path: '/internal/security/api_key/invalidate', + security: { + authz: { + enabled: false, + reason: 'This route is opted out from authorization', + }, + }, validate: { body: schema.object({ apiKeys: schema.arrayOf(schema.object({ id: schema.string(), name: schema.string() })), diff --git a/x-pack/plugins/security/server/routes/api_keys/query.ts b/x-pack/plugins/security/server/routes/api_keys/query.ts index 9fe8fdbdc734b..6654a94957575 100644 --- a/x-pack/plugins/security/server/routes/api_keys/query.ts +++ b/x-pack/plugins/security/server/routes/api_keys/query.ts @@ -25,6 +25,12 @@ export function defineQueryApiKeysAndAggregationsRoute({ // on behalf of the user making the request and governed by the user's own cluster privileges. { path: '/internal/security/api_key/_query', + security: { + authz: { + enabled: false, + reason: 'This route is opted out from authorization', + }, + }, validate: { body: schema.object({ query: schema.maybe(schema.object({}, { unknowns: 'allow' })), diff --git a/x-pack/plugins/security/server/routes/api_keys/update.ts b/x-pack/plugins/security/server/routes/api_keys/update.ts index a7fe43c46e206..7f0e68aa50236 100644 --- a/x-pack/plugins/security/server/routes/api_keys/update.ts +++ b/x-pack/plugins/security/server/routes/api_keys/update.ts @@ -34,6 +34,12 @@ export function defineUpdateApiKeyRoutes({ router.put( { path: '/internal/security/api_key', + security: { + authz: { + enabled: false, + reason: 'This route is opted out from authorization', + }, + }, validate: { body: schema.oneOf([ updateRestApiKeySchema, diff --git a/x-pack/plugins/security/server/routes/authentication/common.ts b/x-pack/plugins/security/server/routes/authentication/common.ts index e54d6e35f1669..ddc670a782ca4 100644 --- a/x-pack/plugins/security/server/routes/authentication/common.ts +++ b/x-pack/plugins/security/server/routes/authentication/common.ts @@ -43,6 +43,12 @@ export function defineCommonRoutes({ router.get( { path, + security: { + authz: { + enabled: false, + reason: 'This route is opted out from authorization', + }, + }, // Allow unknown query parameters as this endpoint can be hit by the 3rd-party with any // set of query string parameters (e.g. SAML/OIDC logout request/response parameters). validate: { query: schema.object({}, { unknowns: 'allow' }) }, @@ -90,7 +96,16 @@ export function defineCommonRoutes({ ...(buildFlavor !== 'serverless' ? ['/api/security/v1/me'] : []), ]) { router.get( - { path, validate: false }, + { + path, + security: { + authz: { + enabled: false, + reason: 'This route is opted out from authorization', + }, + }, + validate: false, + }, createLicensedRouteHandler(async (context, request, response) => { if (path === '/api/security/v1/me') { logger.warn( @@ -137,6 +152,12 @@ export function defineCommonRoutes({ router.post( { path: '/internal/security/login', + security: { + authz: { + enabled: false, + reason: 'This route is opted out from authorization', + }, + }, validate: { body: schema.object({ providerType: schema.string(), @@ -181,7 +202,16 @@ export function defineCommonRoutes({ if (buildFlavor !== 'serverless') { // In the serverless offering, the access agreement functionality isn't available. router.post( - { path: '/internal/security/access_agreement/acknowledge', validate: false }, + { + path: '/internal/security/access_agreement/acknowledge', + security: { + authz: { + enabled: false, + reason: 'This route is opted out from authorization', + }, + }, + validate: false, + }, createLicensedRouteHandler(async (context, request, response) => { // If license doesn't allow access agreement we shouldn't handle request. if (!license.getFeatures().allowAccessAgreement) { diff --git a/x-pack/plugins/security/server/routes/authentication/oidc.ts b/x-pack/plugins/security/server/routes/authentication/oidc.ts index 2c4ab9de1491b..f4c04c63c6bc7 100644 --- a/x-pack/plugins/security/server/routes/authentication/oidc.ts +++ b/x-pack/plugins/security/server/routes/authentication/oidc.ts @@ -87,6 +87,12 @@ export function defineOIDCRoutes({ router.get( { path, + security: { + authz: { + enabled: false, + reason: 'This route is opted out from authorization', + }, + }, validate: { query: schema.object( { @@ -171,6 +177,12 @@ export function defineOIDCRoutes({ router.post( { path, + security: { + authz: { + enabled: false, + reason: 'This route is opted out from authorization', + }, + }, validate: { body: schema.object( { @@ -214,6 +226,12 @@ export function defineOIDCRoutes({ router.get( { path: '/api/security/oidc/initiate_login', + security: { + authz: { + enabled: false, + reason: 'This route is opted out from authorization', + }, + }, validate: { query: schema.object( { diff --git a/x-pack/plugins/security/server/routes/authentication/saml.ts b/x-pack/plugins/security/server/routes/authentication/saml.ts index ddc31fbc88b89..7d3e40303ffdd 100644 --- a/x-pack/plugins/security/server/routes/authentication/saml.ts +++ b/x-pack/plugins/security/server/routes/authentication/saml.ts @@ -30,6 +30,12 @@ export function defineSAMLRoutes({ router.post( { path, + security: { + authz: { + enabled: false, + reason: 'This route is opted out from authorization', + }, + }, validate: { body: schema.object( { SAMLResponse: schema.string(), RelayState: schema.maybe(schema.string()) }, diff --git a/x-pack/plugins/security/server/routes/authorization/privileges/get.ts b/x-pack/plugins/security/server/routes/authorization/privileges/get.ts index 1d278aa676ac3..eb884e141d953 100644 --- a/x-pack/plugins/security/server/routes/authorization/privileges/get.ts +++ b/x-pack/plugins/security/server/routes/authorization/privileges/get.ts @@ -14,6 +14,12 @@ export function defineGetPrivilegesRoutes({ router, authz }: RouteDefinitionPara router.get( { path: '/api/security/privileges', + security: { + authz: { + enabled: false, + reason: 'This route is opted out from authorization', + }, + }, validate: { query: schema.object({ // We don't use `schema.boolean` here, because all query string parameters are treated as diff --git a/x-pack/plugins/security/server/routes/authorization/privileges/get_builtin.ts b/x-pack/plugins/security/server/routes/authorization/privileges/get_builtin.ts index 9a9c2dd6fcc71..294d85b56b939 100644 --- a/x-pack/plugins/security/server/routes/authorization/privileges/get_builtin.ts +++ b/x-pack/plugins/security/server/routes/authorization/privileges/get_builtin.ts @@ -9,7 +9,16 @@ import type { RouteDefinitionParams } from '../..'; export function defineGetBuiltinPrivilegesRoutes({ router }: RouteDefinitionParams) { router.get( - { path: '/internal/security/esPrivileges/builtin', validate: false }, + { + path: '/internal/security/esPrivileges/builtin', + security: { + authz: { + enabled: false, + reason: 'This route is opted out from authorization', + }, + }, + validate: false, + }, async (context, request, response) => { const esClient = (await context.core).elasticsearch.client; const privileges = await esClient.asCurrentUser.security.getBuiltinPrivileges(); diff --git a/x-pack/plugins/security/server/routes/authorization/roles/get_all_by_space.ts b/x-pack/plugins/security/server/routes/authorization/roles/get_all_by_space.ts index 9cfdf3ba301ac..22ac069aad461 100644 --- a/x-pack/plugins/security/server/routes/authorization/roles/get_all_by_space.ts +++ b/x-pack/plugins/security/server/routes/authorization/roles/get_all_by_space.ts @@ -24,8 +24,10 @@ export function defineGetAllRolesBySpaceRoutes({ router.get( { path: '/internal/security/roles/{spaceId}', - options: { - tags: ['access:manageSpaces'], + security: { + authz: { + requiredPrivileges: ['manageSpaces'], + }, }, validate: { params: schema.object({ spaceId: schema.string({ minLength: 1 }) }), diff --git a/x-pack/plugins/security/server/routes/authorization/spaces/share_saved_object_permissions.ts b/x-pack/plugins/security/server/routes/authorization/spaces/share_saved_object_permissions.ts index 536220eff03da..99b8d24af632b 100644 --- a/x-pack/plugins/security/server/routes/authorization/spaces/share_saved_object_permissions.ts +++ b/x-pack/plugins/security/server/routes/authorization/spaces/share_saved_object_permissions.ts @@ -19,6 +19,12 @@ export function defineShareSavedObjectPermissionRoutes({ router.get( { path: '/internal/security/_share_saved_object_permissions', + security: { + authz: { + enabled: false, + reason: 'This route is opted out from authorization', + }, + }, validate: { query: schema.object({ type: schema.string() }) }, }, createLicensedRouteHandler(async (context, request, response) => { diff --git a/x-pack/plugins/security/server/routes/deprecations/kibana_user_role.ts b/x-pack/plugins/security/server/routes/deprecations/kibana_user_role.ts index 638a8f8a1bc7d..dde3fb1190c9e 100644 --- a/x-pack/plugins/security/server/routes/deprecations/kibana_user_role.ts +++ b/x-pack/plugins/security/server/routes/deprecations/kibana_user_role.ts @@ -23,6 +23,12 @@ export function defineKibanaUserRoleDeprecationRoutes({ router, logger }: RouteD router.post( { path: '/internal/security/deprecations/kibana_user_role/_fix_users', + security: { + authz: { + enabled: false, + reason: 'This route is opted out from authorization', + }, + }, validate: false, }, createLicensedRouteHandler(async (context, request, response) => { @@ -88,6 +94,12 @@ export function defineKibanaUserRoleDeprecationRoutes({ router, logger }: RouteD router.post( { path: '/internal/security/deprecations/kibana_user_role/_fix_role_mappings', + security: { + authz: { + enabled: false, + reason: 'This route is opted out from authorization', + }, + }, validate: false, }, createLicensedRouteHandler(async (context, request, response) => { diff --git a/x-pack/plugins/security/server/routes/feature_check/feature_check.ts b/x-pack/plugins/security/server/routes/feature_check/feature_check.ts index b256ee77e55ff..6048a1c606f48 100644 --- a/x-pack/plugins/security/server/routes/feature_check/feature_check.ts +++ b/x-pack/plugins/security/server/routes/feature_check/feature_check.ts @@ -43,6 +43,12 @@ export function defineSecurityFeatureCheckRoute({ router, logger }: RouteDefinit router.get( { path: '/internal/security/_check_security_features', + security: { + authz: { + enabled: false, + reason: 'This route is opted out from authorization', + }, + }, validate: false, }, createLicensedRouteHandler(async (context, request, response) => { diff --git a/x-pack/plugins/security/server/routes/indices/get_fields.ts b/x-pack/plugins/security/server/routes/indices/get_fields.ts index b0ec51339e080..4ce652053ed37 100644 --- a/x-pack/plugins/security/server/routes/indices/get_fields.ts +++ b/x-pack/plugins/security/server/routes/indices/get_fields.ts @@ -14,6 +14,12 @@ export function defineGetFieldsRoutes({ router }: RouteDefinitionParams) { router.get( { path: '/internal/security/fields/{query}', + security: { + authz: { + enabled: false, + reason: 'This route is opted out from authorization', + }, + }, validate: { params: schema.object({ query: schema.string() }) }, }, async (context, request, response) => { diff --git a/x-pack/plugins/security/server/routes/role_mapping/delete.ts b/x-pack/plugins/security/server/routes/role_mapping/delete.ts index e305de6e4fcb4..2fdc64e9a8329 100644 --- a/x-pack/plugins/security/server/routes/role_mapping/delete.ts +++ b/x-pack/plugins/security/server/routes/role_mapping/delete.ts @@ -15,6 +15,12 @@ export function defineRoleMappingDeleteRoutes({ router }: RouteDefinitionParams) router.delete( { path: '/internal/security/role_mapping/{name}', + security: { + authz: { + enabled: false, + reason: 'This route is opted out from authorization', + }, + }, validate: { params: schema.object({ name: schema.string(), diff --git a/x-pack/plugins/security/server/routes/role_mapping/get.ts b/x-pack/plugins/security/server/routes/role_mapping/get.ts index ac6e7efaa8b0a..57691b3407215 100644 --- a/x-pack/plugins/security/server/routes/role_mapping/get.ts +++ b/x-pack/plugins/security/server/routes/role_mapping/get.ts @@ -18,6 +18,12 @@ export function defineRoleMappingGetRoutes(params: RouteDefinitionParams) { router.get( { path: '/internal/security/role_mapping/{name?}', + security: { + authz: { + enabled: false, + reason: 'This route is opted out from authorization', + }, + }, validate: { params: schema.object({ name: schema.maybe(schema.string()), diff --git a/x-pack/plugins/security/server/routes/role_mapping/post.ts b/x-pack/plugins/security/server/routes/role_mapping/post.ts index a9a87d4b2be51..8ebca8720c86f 100644 --- a/x-pack/plugins/security/server/routes/role_mapping/post.ts +++ b/x-pack/plugins/security/server/routes/role_mapping/post.ts @@ -15,6 +15,12 @@ export function defineRoleMappingPostRoutes({ router }: RouteDefinitionParams) { router.post( { path: '/internal/security/role_mapping/{name}', + security: { + authz: { + enabled: false, + reason: 'This route is opted out from authorization', + }, + }, validate: { params: schema.object({ name: schema.string(), diff --git a/x-pack/plugins/security/server/routes/security_checkup/get_state.ts b/x-pack/plugins/security/server/routes/security_checkup/get_state.ts index 2946c3fa5dee3..b6b4f5e43d00b 100644 --- a/x-pack/plugins/security/server/routes/security_checkup/get_state.ts +++ b/x-pack/plugins/security/server/routes/security_checkup/get_state.ts @@ -29,7 +29,16 @@ export function defineSecurityCheckupGetStateRoutes({ const doesClusterHaveUserData = createClusterDataCheck(); router.get( - { path: '/internal/security/security_checkup/state', validate: false }, + { + path: '/internal/security/security_checkup/state', + security: { + authz: { + enabled: false, + reason: 'This route is opted out from authorization', + }, + }, + validate: false, + }, async (context, _request, response) => { const esClient = (await context.core).elasticsearch.client; let displayAlert = false; diff --git a/x-pack/plugins/security/server/routes/session_management/extend.ts b/x-pack/plugins/security/server/routes/session_management/extend.ts index b1626ba4660b3..10c109f36a83c 100644 --- a/x-pack/plugins/security/server/routes/session_management/extend.ts +++ b/x-pack/plugins/security/server/routes/session_management/extend.ts @@ -14,6 +14,12 @@ export function defineSessionExtendRoutes({ router, basePath }: RouteDefinitionP router.post( { path: '/internal/security/session', + security: { + authz: { + enabled: false, + reason: 'This route is opted out from authorization', + }, + }, validate: false, }, async (_context, _request, response) => { diff --git a/x-pack/plugins/security/server/routes/session_management/info.ts b/x-pack/plugins/security/server/routes/session_management/info.ts index 75fae27e8cb12..a349d2612c3de 100644 --- a/x-pack/plugins/security/server/routes/session_management/info.ts +++ b/x-pack/plugins/security/server/routes/session_management/info.ts @@ -14,7 +14,16 @@ import type { SessionInfo } from '../../../common/types'; */ export function defineSessionInfoRoutes({ router, getSession }: RouteDefinitionParams) { router.get( - { path: '/internal/security/session', validate: false }, + { + path: '/internal/security/session', + security: { + authz: { + enabled: false, + reason: 'This route is opted out from authorization', + }, + }, + validate: false, + }, async (_context, request, response) => { const { value: sessionValue } = await getSession().get(request); if (sessionValue) { diff --git a/x-pack/plugins/security/server/routes/session_management/invalidate.ts b/x-pack/plugins/security/server/routes/session_management/invalidate.ts index c7d27b835edf2..6963e064a706e 100644 --- a/x-pack/plugins/security/server/routes/session_management/invalidate.ts +++ b/x-pack/plugins/security/server/routes/session_management/invalidate.ts @@ -33,9 +33,14 @@ export function defineInvalidateSessionsRoutes({ router, getSession }: RouteDefi ), }), }, + security: { + authz: { + requiredPrivileges: ['sessionManagement'], + }, + }, options: { access: 'public', - tags: ['access:sessionManagement'], + summary: `Invalidate user sessions`, }, }, diff --git a/x-pack/plugins/security/server/routes/user_profile/bulk_get.ts b/x-pack/plugins/security/server/routes/user_profile/bulk_get.ts index 20da1d573901f..0ffe760d57d52 100644 --- a/x-pack/plugins/security/server/routes/user_profile/bulk_get.ts +++ b/x-pack/plugins/security/server/routes/user_profile/bulk_get.ts @@ -24,7 +24,11 @@ export function defineBulkGetUserProfilesRoute({ dataPath: schema.maybe(schema.string()), }), }, - options: { tags: ['access:bulkGetUserProfiles'] }, + security: { + authz: { + requiredPrivileges: ['bulkGetUserProfiles'], + }, + }, }, createLicensedRouteHandler(async (context, request, response) => { const userProfileServiceInternal = getUserProfileService(); diff --git a/x-pack/plugins/security/server/routes/user_profile/get_current.ts b/x-pack/plugins/security/server/routes/user_profile/get_current.ts index 9661570e36b4e..cfebc16e516a5 100644 --- a/x-pack/plugins/security/server/routes/user_profile/get_current.ts +++ b/x-pack/plugins/security/server/routes/user_profile/get_current.ts @@ -20,6 +20,12 @@ export function defineGetCurrentUserProfileRoute({ router.get( { path: '/internal/security/user_profile', + security: { + authz: { + enabled: false, + reason: 'This route is opted out from authorization', + }, + }, validate: { query: schema.object({ dataPath: schema.maybe(schema.string()) }), }, diff --git a/x-pack/plugins/security/server/routes/user_profile/update.ts b/x-pack/plugins/security/server/routes/user_profile/update.ts index 9a550ada52adc..4709861bc6912 100644 --- a/x-pack/plugins/security/server/routes/user_profile/update.ts +++ b/x-pack/plugins/security/server/routes/user_profile/update.ts @@ -27,6 +27,12 @@ export function defineUpdateUserProfileDataRoute({ router.post( { path: '/internal/security/user_profile/_data', + security: { + authz: { + enabled: false, + reason: 'This route is opted out from authorization', + }, + }, validate: { body: schema.recordOf(schema.string(), schema.any()), }, diff --git a/x-pack/plugins/security/server/routes/users/change_password.ts b/x-pack/plugins/security/server/routes/users/change_password.ts index bd71785ab9549..ec05a200c0f1e 100644 --- a/x-pack/plugins/security/server/routes/users/change_password.ts +++ b/x-pack/plugins/security/server/routes/users/change_password.ts @@ -24,6 +24,12 @@ export function defineChangeUserPasswordRoutes({ router.post( { path: '/internal/security/users/{username}/password', + security: { + authz: { + enabled: false, + reason: 'This route is opted out from authorization', + }, + }, validate: { params: schema.object({ username: schema.string({ minLength: 1, maxLength: 1024 }) }), body: schema.object({ diff --git a/x-pack/plugins/security/server/routes/users/create_or_update.ts b/x-pack/plugins/security/server/routes/users/create_or_update.ts index de6adad78b4e8..97789473851dd 100644 --- a/x-pack/plugins/security/server/routes/users/create_or_update.ts +++ b/x-pack/plugins/security/server/routes/users/create_or_update.ts @@ -15,6 +15,12 @@ export function defineCreateOrUpdateUserRoutes({ router }: RouteDefinitionParams router.post( { path: '/internal/security/users/{username}', + security: { + authz: { + enabled: false, + reason: 'This route is opted out from authorization', + }, + }, validate: { params: schema.object({ username: schema.string({ minLength: 1, maxLength: 1024 }) }), body: schema.object({ diff --git a/x-pack/plugins/security/server/routes/users/delete.ts b/x-pack/plugins/security/server/routes/users/delete.ts index 429adb368574a..b8844ee3047f7 100644 --- a/x-pack/plugins/security/server/routes/users/delete.ts +++ b/x-pack/plugins/security/server/routes/users/delete.ts @@ -15,6 +15,12 @@ export function defineDeleteUserRoutes({ router }: RouteDefinitionParams) { router.delete( { path: '/internal/security/users/{username}', + security: { + authz: { + enabled: false, + reason: 'This route is opted out from authorization', + }, + }, validate: { params: schema.object({ username: schema.string({ minLength: 1, maxLength: 1024 }) }), }, diff --git a/x-pack/plugins/security/server/routes/users/disable.ts b/x-pack/plugins/security/server/routes/users/disable.ts index 87f61daca8c95..9e1a678f17d14 100644 --- a/x-pack/plugins/security/server/routes/users/disable.ts +++ b/x-pack/plugins/security/server/routes/users/disable.ts @@ -15,6 +15,12 @@ export function defineDisableUserRoutes({ router }: RouteDefinitionParams) { router.post( { path: '/internal/security/users/{username}/_disable', + security: { + authz: { + enabled: false, + reason: 'This route is opted out from authorization', + }, + }, validate: { params: schema.object({ username: schema.string({ minLength: 1, maxLength: 1024 }) }), }, diff --git a/x-pack/plugins/security/server/routes/users/enable.ts b/x-pack/plugins/security/server/routes/users/enable.ts index a8a9d62bee938..69e10f9110b55 100644 --- a/x-pack/plugins/security/server/routes/users/enable.ts +++ b/x-pack/plugins/security/server/routes/users/enable.ts @@ -15,6 +15,12 @@ export function defineEnableUserRoutes({ router }: RouteDefinitionParams) { router.post( { path: '/internal/security/users/{username}/_enable', + security: { + authz: { + enabled: false, + reason: 'This route is opted out from authorization', + }, + }, validate: { params: schema.object({ username: schema.string({ minLength: 1, maxLength: 1024 }) }), }, diff --git a/x-pack/plugins/security/server/routes/users/get.ts b/x-pack/plugins/security/server/routes/users/get.ts index ed18c8437627d..8ec4c86c7d276 100644 --- a/x-pack/plugins/security/server/routes/users/get.ts +++ b/x-pack/plugins/security/server/routes/users/get.ts @@ -15,6 +15,12 @@ export function defineGetUserRoutes({ router }: RouteDefinitionParams) { router.get( { path: '/internal/security/users/{username}', + security: { + authz: { + enabled: false, + reason: 'This route is opted out from authorization', + }, + }, validate: { params: schema.object({ username: schema.string({ minLength: 1, maxLength: 1024 }) }), }, diff --git a/x-pack/plugins/security/server/routes/users/get_all.ts b/x-pack/plugins/security/server/routes/users/get_all.ts index eae0664189340..d0d7332ebda1e 100644 --- a/x-pack/plugins/security/server/routes/users/get_all.ts +++ b/x-pack/plugins/security/server/routes/users/get_all.ts @@ -11,7 +11,16 @@ import { createLicensedRouteHandler } from '../licensed_route_handler'; export function defineGetAllUsersRoutes({ router }: RouteDefinitionParams) { router.get( - { path: '/internal/security/users', validate: false }, + { + path: '/internal/security/users', + security: { + authz: { + enabled: false, + reason: 'This route is opted out from authorization', + }, + }, + validate: false, + }, createLicensedRouteHandler(async (context, request, response) => { try { const esClient = (await context.core).elasticsearch.client; diff --git a/x-pack/plugins/security/server/routes/views/access_agreement.ts b/x-pack/plugins/security/server/routes/views/access_agreement.ts index 3724892edd6df..dfbe673305f10 100644 --- a/x-pack/plugins/security/server/routes/views/access_agreement.ts +++ b/x-pack/plugins/security/server/routes/views/access_agreement.ts @@ -35,7 +35,16 @@ export function defineAccessAgreementRoutes({ ); router.get( - { path: '/internal/security/access_agreement/state', validate: false }, + { + path: '/internal/security/access_agreement/state', + security: { + authz: { + enabled: false, + reason: 'This route is opted out from authorization', + }, + }, + validate: false, + }, createLicensedRouteHandler(async (context, request, response) => { if (!canHandleRequest()) { return response.forbidden({ diff --git a/x-pack/plugins/security/server/routes/views/login.ts b/x-pack/plugins/security/server/routes/views/login.ts index 5d4468fcbba57..cd79c3692b7f4 100644 --- a/x-pack/plugins/security/server/routes/views/login.ts +++ b/x-pack/plugins/security/server/routes/views/login.ts @@ -57,7 +57,17 @@ export function defineLoginRoutes({ ); router.get( - { path: '/internal/security/login_state', validate: false, options: { authRequired: false } }, + { + path: '/internal/security/login_state', + security: { + authz: { + enabled: false, + reason: 'This route is opted out from authorization', + }, + }, + validate: false, + options: { authRequired: false }, + }, async (context, request, response) => { const { allowLogin, layout = 'form' } = license.getFeatures(); const { sortedProviders, selector } = config.authc;