diff --git a/x-pack/plugins/fleet/server/routes/package_policy/index.ts b/x-pack/plugins/fleet/server/routes/package_policy/index.ts index 893eb37a9b1bc4..d28709eebaac3d 100644 --- a/x-pack/plugins/fleet/server/routes/package_policy/index.ts +++ b/x-pack/plugins/fleet/server/routes/package_policy/index.ts @@ -4,6 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ +import { schema } from '@kbn/config-schema'; import { getRouteRequiredAuthz } from '../../services/security'; @@ -22,9 +23,15 @@ import { DryRunPackagePoliciesRequestSchema, DeleteOnePackagePolicyRequestSchema, BulkGetPackagePoliciesRequestSchema, + PackagePolicyPackageSchema, + PackagePolicyResponseSchema, + PackagePolicyStatusResponseSchema, + DryRunPackagePolicySchema, } from '../../types'; import { calculateRouteAuthz } from '../../services/security/security'; +import { genericErrorResponse, notFoundResponse } from '../schema/errors'; + import { getPackagePoliciesHandler, getOnePackagePolicyHandler, @@ -48,11 +55,31 @@ export const registerRoutes = (router: FleetAuthzRouter) => { fleetAuthz, getRouteRequiredAuthz('get', PACKAGE_POLICY_API_ROUTES.LIST_PATTERN) ).granted, + description: 'List package policies', + options: { + tags: ['oas-tag:Fleet package policies'], + }, }) .addVersion( { version: API_VERSIONS.public.v1, - validate: { request: GetPackagePoliciesRequestSchema }, + validate: { + request: GetPackagePoliciesRequestSchema, + response: { + 200: { + body: () => + schema.object({ + items: schema.arrayOf(PackagePolicyResponseSchema), + total: schema.number(), + page: schema.number(), + perPage: schema.number(), + }), + }, + 400: { + body: genericErrorResponse, + }, + }, + }, }, getPackagePoliciesHandler ); @@ -66,11 +93,31 @@ export const registerRoutes = (router: FleetAuthzRouter) => { fleetAuthz, getRouteRequiredAuthz('post', PACKAGE_POLICY_API_ROUTES.BULK_GET_PATTERN) ).granted, + description: 'Bulk get package policies', + options: { + tags: ['oas-tag:Fleet package policies'], + }, }) .addVersion( { version: API_VERSIONS.public.v1, - validate: { request: BulkGetPackagePoliciesRequestSchema }, + validate: { + request: BulkGetPackagePoliciesRequestSchema, + response: { + 200: { + body: () => + schema.object({ + items: schema.arrayOf(PackagePolicyResponseSchema), + }), + }, + 400: { + body: genericErrorResponse, + }, + 404: { + body: notFoundResponse, + }, + }, + }, }, bulkGetPackagePoliciesHandler ); @@ -84,11 +131,31 @@ export const registerRoutes = (router: FleetAuthzRouter) => { fleetAuthz, getRouteRequiredAuthz('get', PACKAGE_POLICY_API_ROUTES.INFO_PATTERN) ).granted, + description: 'Get package policy by ID', + options: { + tags: ['oas-tag:Fleet package policies'], + }, }) .addVersion( { version: API_VERSIONS.public.v1, - validate: { request: GetOnePackagePolicyRequestSchema }, + validate: { + request: GetOnePackagePolicyRequestSchema, + response: { + 200: { + body: () => + schema.object({ + item: PackagePolicyResponseSchema, + }), + }, + 400: { + body: genericErrorResponse, + }, + 404: { + body: notFoundResponse, + }, + }, + }, }, getOnePackagePolicyHandler ); @@ -109,14 +176,35 @@ export const registerRoutes = (router: FleetAuthzRouter) => { ); // Create + // Authz check moved to service here: https://github.com/elastic/kibana/pull/140458 router.versioned .post({ path: PACKAGE_POLICY_API_ROUTES.CREATE_PATTERN, + description: 'Create package policy', + options: { + tags: ['oas-tag:Fleet package policies'], + }, }) .addVersion( { version: API_VERSIONS.public.v1, - validate: { request: CreatePackagePolicyRequestSchema }, + validate: { + request: CreatePackagePolicyRequestSchema, + response: { + 200: { + body: () => + schema.object({ + item: PackagePolicyResponseSchema, + }), + }, + 400: { + body: genericErrorResponse, + }, + 409: { + body: genericErrorResponse, + }, + }, + }, }, createPackagePolicyHandler ); @@ -130,11 +218,32 @@ export const registerRoutes = (router: FleetAuthzRouter) => { fleetAuthz, getRouteRequiredAuthz('put', PACKAGE_POLICY_API_ROUTES.UPDATE_PATTERN) ).granted, + description: 'Update package policy by ID', + options: { + tags: ['oas-tag:Fleet package policies'], + }, }) .addVersion( { version: API_VERSIONS.public.v1, - validate: { request: UpdatePackagePolicyRequestSchema }, + validate: { + request: UpdatePackagePolicyRequestSchema, + response: { + 200: { + body: () => + schema.object({ + item: PackagePolicyResponseSchema, + success: schema.boolean(), + }), + }, + 400: { + body: genericErrorResponse, + }, + 403: { + body: genericErrorResponse, + }, + }, + }, }, updatePackagePolicyHandler @@ -147,11 +256,42 @@ export const registerRoutes = (router: FleetAuthzRouter) => { fleetAuthz: { integrations: { writeIntegrationPolicies: true }, }, + description: 'Bulk delete package policies', + options: { + tags: ['oas-tag:Fleet package policies'], + }, }) .addVersion( { version: API_VERSIONS.public.v1, - validate: { request: DeletePackagePoliciesRequestSchema }, + validate: { + request: DeletePackagePoliciesRequestSchema, + response: { + 200: { + body: () => + schema.arrayOf( + PackagePolicyStatusResponseSchema.extends({ + policy_id: schema.nullable( + schema.maybe( + schema.string({ + meta: { + description: 'Use `policy_ids` instead', + deprecated: true, + }, + }) + ) + ), + policy_ids: schema.arrayOf(schema.string()), + output_id: schema.nullable(schema.maybe(schema.string())), + package: PackagePolicyPackageSchema, + }) + ), + }, + 400: { + body: genericErrorResponse, + }, + }, + }, }, deletePackagePolicyHandler ); @@ -162,11 +302,28 @@ export const registerRoutes = (router: FleetAuthzRouter) => { fleetAuthz: { integrations: { writeIntegrationPolicies: true }, }, + description: 'Delete package policy by ID', + options: { + tags: ['oas-tag:Fleet package policies'], + }, }) .addVersion( { version: API_VERSIONS.public.v1, - validate: { request: DeleteOnePackagePolicyRequestSchema }, + validate: { + request: DeleteOnePackagePolicyRequestSchema, + response: { + 200: { + body: () => + schema.object({ + id: schema.string(), + }), + }, + 400: { + body: genericErrorResponse, + }, + }, + }, }, deleteOnePackagePolicyHandler ); @@ -178,11 +335,25 @@ export const registerRoutes = (router: FleetAuthzRouter) => { fleetAuthz: { integrations: { writeIntegrationPolicies: true }, }, + description: 'Upgrade package policy to a newer package version', + options: { + tags: ['oas-tag:Fleet package policies'], + }, }) .addVersion( { version: API_VERSIONS.public.v1, - validate: { request: UpgradePackagePoliciesRequestSchema }, + validate: { + request: UpgradePackagePoliciesRequestSchema, + response: { + 200: { + body: () => PackagePolicyStatusResponseSchema, + }, + 400: { + body: genericErrorResponse, + }, + }, + }, }, upgradePackagePolicyHandler ); @@ -194,11 +365,100 @@ export const registerRoutes = (router: FleetAuthzRouter) => { fleetAuthz: { integrations: { readIntegrationPolicies: true }, }, + description: 'Dry run package policy upgrade', + options: { + tags: ['oas-tag:Fleet package policies'], + }, }) .addVersion( { version: API_VERSIONS.public.v1, - validate: { request: DryRunPackagePoliciesRequestSchema }, + validate: { + request: DryRunPackagePoliciesRequestSchema, + response: { + 200: { + body: () => + schema.arrayOf( + schema.object({ + name: schema.maybe(schema.string()), + statusCode: schema.maybe(schema.number()), + body: schema.maybe(schema.object({ message: schema.string() })), + hasErrors: schema.boolean(), + diff: schema.maybe( + schema.arrayOf( + schema.oneOf([PackagePolicyResponseSchema, DryRunPackagePolicySchema]) + ) + ), + agent_diff: schema.maybe( + schema.arrayOf( + schema.arrayOf( + schema + .object({ + id: schema.string(), + name: schema.string(), + revision: schema.number(), + type: schema.string(), + data_stream: schema.object({ + namespace: schema.string(), + }), + use_output: schema.string(), + package_policy_id: schema.string(), + meta: schema.maybe( + schema.object({ + package: schema + .object({ + name: schema.string(), + version: schema.string(), + }) + .extendsDeep({ + // equivalent of allowing extra keys like `[key: string]: any;` + unknowns: 'allow', + }), + }) + ), + streams: schema.maybe( + schema.arrayOf( + schema + .object({ + id: schema.string(), + data_stream: schema.object({ + dataset: schema.string(), + type: schema.string(), + }), + }) + .extendsDeep({ + unknowns: 'allow', + }) + ) + ), + processors: schema.maybe( + schema.arrayOf( + schema.object({ + add_fields: schema.object({ + target: schema.string(), + fields: schema.recordOf( + schema.string(), + schema.oneOf([schema.string(), schema.number()]) + ), + }), + }) + ) + ), + }) + .extendsDeep({ + unknowns: 'allow', + }) + ) + ) + ), + }) + ), + }, + 400: { + body: genericErrorResponse, + }, + }, + }, }, dryRunUpgradePackagePolicyHandler ); diff --git a/x-pack/plugins/fleet/server/routes/schema/errors.ts b/x-pack/plugins/fleet/server/routes/schema/errors.ts new file mode 100644 index 00000000000000..1d8f0f5d5b92d3 --- /dev/null +++ b/x-pack/plugins/fleet/server/routes/schema/errors.ts @@ -0,0 +1,33 @@ +/* + * 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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { schema } from '@kbn/config-schema'; + +export const genericErrorResponse = () => + schema.object( + { + statusCode: schema.number(), + error: schema.string(), + message: schema.string(), + }, + { + meta: { description: 'Generic Error' }, + } + ); + +export const notFoundResponse = () => + schema.object({ + message: schema.string(), + }); + +export const internalErrorResponse = () => + schema.object( + { + message: schema.string(), + }, + { meta: { description: 'Internal Server Error' } } + ); diff --git a/x-pack/plugins/fleet/server/routes/settings/index.ts b/x-pack/plugins/fleet/server/routes/settings/index.ts index b9f672627daa7d..31bbf61db2a51b 100644 --- a/x-pack/plugins/fleet/server/routes/settings/index.ts +++ b/x-pack/plugins/fleet/server/routes/settings/index.ts @@ -4,6 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ +import { schema } from '@kbn/config-schema'; import { parseExperimentalConfigValue } from '../../../common/experimental_features'; import { API_VERSIONS } from '../../../common/constants'; @@ -18,6 +19,8 @@ import { } from '../../types'; import type { FleetConfigType } from '../../config'; +import { genericErrorResponse, notFoundResponse } from '../schema/errors'; + import { getEnrollmentSettingsHandler } from './enrollment_settings_handler'; import { @@ -27,6 +30,36 @@ import { putSpaceSettingsHandler, } from './settings_handler'; +const spaceSettingsResponse = () => + schema.object({ + item: schema.object({ + managed_by: schema.maybe(schema.string()), + allowed_namespace_prefixes: schema.arrayOf(schema.string()), + }), + }); + +const settingsResponse = () => + schema.object({ + item: schema.object({ + has_seen_add_data_notice: schema.maybe(schema.boolean()), + fleet_server_hosts: schema.maybe(schema.arrayOf(schema.string())), + prerelease_integrations_enabled: schema.boolean(), + id: schema.string(), + version: schema.maybe(schema.string()), + preconfigured_fields: schema.maybe(schema.arrayOf(schema.literal('fleet_server_hosts'))), + secret_storage_requirements_met: schema.maybe(schema.boolean()), + output_secret_storage_requirements_met: schema.maybe(schema.boolean()), + use_space_awareness_migration_status: schema.maybe( + schema.oneOf([ + schema.literal('pending'), + schema.literal('success'), + schema.literal('error'), + ]) + ), + use_space_awareness_migration_started_at: schema.maybe(schema.string()), + }), + }); + export const registerRoutes = (router: FleetAuthzRouter, config: FleetConfigType) => { const experimentalFeatures = parseExperimentalConfigValue(config.enableExperimental); if (experimentalFeatures.useSpaceAwareness) { @@ -45,7 +78,14 @@ export const registerRoutes = (router: FleetAuthzRouter, config: FleetConfigType .addVersion( { version: API_VERSIONS.public.v1, - validate: { request: GetSpaceSettingsRequestSchema }, + validate: { + request: GetSpaceSettingsRequestSchema, + response: { + 200: { + body: spaceSettingsResponse, + }, + }, + }, }, getSpaceSettingsHandler ); @@ -61,7 +101,14 @@ export const registerRoutes = (router: FleetAuthzRouter, config: FleetConfigType .addVersion( { version: API_VERSIONS.public.v1, - validate: { request: PutSpaceSettingsRequestSchema }, + validate: { + request: PutSpaceSettingsRequestSchema, + response: { + 200: { + body: spaceSettingsResponse, + }, + }, + }, }, putSpaceSettingsHandler ); @@ -74,11 +121,27 @@ export const registerRoutes = (router: FleetAuthzRouter, config: FleetConfigType fleet: { readSettings: true }, }, description: `Get settings`, + options: { + tags: ['oas-tag:Fleet internals'], + }, }) .addVersion( { version: API_VERSIONS.public.v1, - validate: { request: GetSettingsRequestSchema }, + validate: { + request: GetSettingsRequestSchema, + response: { + 200: { + body: settingsResponse, + }, + 400: { + body: genericErrorResponse, + }, + 404: { + body: notFoundResponse, + }, + }, + }, }, getSettingsHandler ); @@ -89,11 +152,27 @@ export const registerRoutes = (router: FleetAuthzRouter, config: FleetConfigType fleet: { allSettings: true }, }, description: `Update settings`, + options: { + tags: ['oas-tag:Fleet internals'], + }, }) .addVersion( { version: API_VERSIONS.public.v1, - validate: { request: PutSettingsRequestSchema }, + validate: { + request: PutSettingsRequestSchema, + response: { + 200: { + body: settingsResponse, + }, + 400: { + body: genericErrorResponse, + }, + 404: { + body: notFoundResponse, + }, + }, + }, }, putSettingsHandler ); @@ -104,11 +183,87 @@ export const registerRoutes = (router: FleetAuthzRouter, config: FleetConfigType return authz.fleet.addAgents || authz.fleet.addFleetServers; }, description: `Get enrollment settings`, + options: { + tags: ['oas-tag:Fleet internals'], + }, }) .addVersion( { version: API_VERSIONS.public.v1, - validate: { request: GetEnrollmentSettingsRequestSchema }, + validate: { + request: GetEnrollmentSettingsRequestSchema, + response: { + 200: { + body: () => + schema.object({ + fleet_server: schema.object({ + policies: schema.arrayOf( + schema.object({ + id: schema.string(), + name: schema.string(), + is_managed: schema.boolean(), + is_default_fleet_server: schema.maybe(schema.boolean()), + has_fleet_server: schema.maybe(schema.boolean()), + fleet_server_host_id: schema.nullable(schema.maybe(schema.string())), + download_source_id: schema.nullable(schema.maybe(schema.string())), + space_ids: schema.maybe(schema.arrayOf(schema.string())), + }) + ), + has_active: schema.boolean(), + host: schema.maybe( + schema.object({ + id: schema.string(), + name: schema.string(), + host_urls: schema.arrayOf(schema.string()), + is_default: schema.boolean(), + is_preconfigured: schema.boolean(), + is_internal: schema.maybe(schema.boolean()), + proxy_id: schema.nullable(schema.maybe(schema.string())), + }) + ), + host_proxy: schema.maybe( + schema.object({ + id: schema.string(), + proxy_headers: schema.maybe( + schema.recordOf( + schema.string(), + schema.oneOf([schema.string(), schema.number(), schema.boolean()]) + ) + ), + name: schema.string(), + url: schema.string(), + certificate_authorities: schema.nullable(schema.maybe(schema.string())), + certificate: schema.nullable(schema.maybe(schema.string())), + certificate_key: schema.nullable(schema.maybe(schema.string())), + is_preconfigured: schema.boolean(), + }) + ), + }), + download_source: schema.maybe( + schema.object({ + id: schema.string(), + name: schema.string(), + host: schema.string(), + is_default: schema.boolean(), + proxy_id: schema.nullable( + schema.maybe( + schema.string({ + meta: { + description: + 'The ID of the proxy to use for this download source. See the proxies API for more information.', + }, + }) + ) + ), + }) + ), + }), + }, + 400: { + body: genericErrorResponse, + }, + }, + }, }, getEnrollmentSettingsHandler ); diff --git a/x-pack/plugins/fleet/server/routes/setup/index.ts b/x-pack/plugins/fleet/server/routes/setup/index.ts index 7052aacfc329d0..e465ca4d9ec1dc 100644 --- a/x-pack/plugins/fleet/server/routes/setup/index.ts +++ b/x-pack/plugins/fleet/server/routes/setup/index.ts @@ -4,6 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ +import { schema } from '@kbn/config-schema'; import type { FleetAuthzRouter } from '../../services/security'; @@ -12,8 +13,29 @@ import { API_VERSIONS } from '../../../common/constants'; import type { FleetConfigType } from '../../../common/types'; +import { genericErrorResponse, internalErrorResponse } from '../schema/errors'; + import { getFleetStatusHandler, fleetSetupHandler } from './handlers'; +const fleetSetupResponseBody = () => + schema.object( + { + isInitialized: schema.boolean(), + nonFatalErrors: schema.arrayOf( + schema.object({ + name: schema.string(), + message: schema.string(), + }) + ), + }, + { + meta: { + description: + "A summary of the result of Fleet's `setup` lifecycle. If `isInitialized` is true, Fleet is ready to accept agent enrollment. `nonFatalErrors` may include useful insight into non-blocking issues with Fleet setup.", + }, + } + ); + export const registerFleetSetupRoute = (router: FleetAuthzRouter) => { router.versioned .post({ @@ -22,11 +44,27 @@ export const registerFleetSetupRoute = (router: FleetAuthzRouter) => { fleet: { setup: true }, }, description: `Initiate Fleet setup`, + options: { + tags: ['oas-tag:Fleet internals'], + }, }) .addVersion( { version: API_VERSIONS.public.v1, - validate: false, + validate: { + request: {}, + response: { + 200: { + body: fleetSetupResponseBody, + }, + 400: { + body: genericErrorResponse, + }, + 500: { + body: internalErrorResponse, + }, + }, + }, }, fleetSetupHandler ); @@ -40,11 +78,25 @@ export const registerCreateFleetSetupRoute = (router: FleetAuthzRouter) => { fleetAuthz: { fleet: { setup: true }, }, + description: `Initiate agent setup`, + options: { + tags: ['oas-tag:Elastic Agents'], + }, }) .addVersion( { version: API_VERSIONS.public.v1, - validate: false, + validate: { + request: {}, + response: { + 200: { + body: fleetSetupResponseBody, + }, + 400: { + body: genericErrorResponse, + }, + }, + }, }, fleetSetupHandler ); @@ -57,11 +109,53 @@ export const registerGetFleetStatusRoute = (router: FleetAuthzRouter) => { fleetAuthz: { fleet: { setup: true }, }, + description: `Get agent setup info`, + options: { + tags: ['oas-tag:Elastic Agents'], + }, }) .addVersion( { version: API_VERSIONS.public.v1, - validate: false, + validate: { + request: {}, + response: { + 200: { + body: () => + schema.object( + { + isReady: schema.boolean(), + missing_requirements: schema.arrayOf( + schema.oneOf([ + schema.literal('security_required'), + schema.literal('tls_required'), + schema.literal('api_keys'), + schema.literal('fleet_admin_user'), + schema.literal('fleet_server'), + ]) + ), + missing_optional_features: schema.arrayOf( + schema.oneOf([ + schema.literal('encrypted_saved_object_encryption_key_required'), + ]) + ), + package_verification_key_id: schema.maybe(schema.string()), + is_space_awareness_enabled: schema.maybe(schema.boolean()), + is_secrets_storage_enabled: schema.maybe(schema.boolean()), + }, + { + meta: { + description: + 'A summary of the agent setup status. `isReady` indicates whether the setup is ready. If the setup is not ready, `missing_requirements` lists which requirements are missing.', + }, + } + ), + }, + 400: { + body: genericErrorResponse, + }, + }, + }, }, getFleetStatusHandler ); diff --git a/x-pack/plugins/fleet/server/routes/standalone_agent_api_key/index.ts b/x-pack/plugins/fleet/server/routes/standalone_agent_api_key/index.ts index 9255f058aee462..15e823d02cd2ac 100644 --- a/x-pack/plugins/fleet/server/routes/standalone_agent_api_key/index.ts +++ b/x-pack/plugins/fleet/server/routes/standalone_agent_api_key/index.ts @@ -4,6 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ +import { schema } from '@kbn/config-schema'; import type { FleetAuthzRouter } from '../../services/security'; @@ -27,7 +28,23 @@ export const registerRoutes = (router: FleetAuthzRouter) => { .addVersion( { version: API_VERSIONS.internal.v1, - validate: { request: PostStandaloneAgentAPIKeyRequestSchema }, + validate: { + request: PostStandaloneAgentAPIKeyRequestSchema, + response: { + 200: { + body: () => + schema.object({ + item: schema.object({ + id: schema.string(), + api_key: schema.string(), + name: schema.string(), + encoded: schema.string(), + expiration: schema.maybe(schema.number()), + }), + }), + }, + }, + }, }, createStandaloneAgentApiKeyHandler ); diff --git a/x-pack/plugins/fleet/server/routes/uninstall_token/index.ts b/x-pack/plugins/fleet/server/routes/uninstall_token/index.ts index 9fb91b45fa3735..21b69adb0d4b23 100644 --- a/x-pack/plugins/fleet/server/routes/uninstall_token/index.ts +++ b/x-pack/plugins/fleet/server/routes/uninstall_token/index.ts @@ -4,6 +4,8 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ +import { schema } from '@kbn/config-schema'; + import { UNINSTALL_TOKEN_ROUTES, API_VERSIONS } from '../../../common/constants'; import type { FleetConfigType } from '../../config'; @@ -14,6 +16,8 @@ import { } from '../../types/rest_spec/uninstall_token'; import { parseExperimentalConfigValue } from '../../../common/experimental_features'; +import { genericErrorResponse } from '../schema/errors'; + import { getUninstallTokenHandler, getUninstallTokensMetadataHandler } from './handlers'; export const registerRoutes = (router: FleetAuthzRouter, config: FleetConfigType) => { @@ -26,11 +30,39 @@ export const registerRoutes = (router: FleetAuthzRouter, config: FleetConfigType fleetAuthz: { fleet: { allAgents: true }, }, + description: 'List metadata for latest uninstall tokens per agent policy', + options: { + tags: ['oas-tag:Fleet uninstall tokens'], + }, }) .addVersion( { version: API_VERSIONS.public.v1, - validate: { request: GetUninstallTokensMetadataRequestSchema }, + validate: { + request: GetUninstallTokensMetadataRequestSchema, + response: { + 200: { + body: () => + schema.object({ + items: schema.arrayOf( + schema.object({ + id: schema.string(), + policy_id: schema.string(), + policy_name: schema.maybe(schema.string()), + created_at: schema.string(), + namespaces: schema.maybe(schema.arrayOf(schema.string())), + }) + ), + total: schema.number(), + page: schema.number(), + perPage: schema.number(), + }), + }, + 400: { + body: genericErrorResponse, + }, + }, + }, }, getUninstallTokensMetadataHandler ); @@ -41,11 +73,35 @@ export const registerRoutes = (router: FleetAuthzRouter, config: FleetConfigType fleetAuthz: { fleet: { allAgents: true }, }, + description: 'Get one decrypted uninstall token by its ID', + options: { + tags: ['oas-tag:Fleet uninstall tokens'], + }, }) .addVersion( { version: API_VERSIONS.public.v1, - validate: { request: GetUninstallTokenRequestSchema }, + validate: { + request: GetUninstallTokenRequestSchema, + response: { + 200: { + body: () => + schema.object({ + item: schema.object({ + id: schema.string(), + token: schema.string(), + policy_id: schema.string(), + policy_name: schema.maybe(schema.string()), + created_at: schema.string(), + namespaces: schema.maybe(schema.arrayOf(schema.string())), + }), + }), + }, + 400: { + body: genericErrorResponse, + }, + }, + }, }, getUninstallTokenHandler ); diff --git a/x-pack/plugins/fleet/server/types/models/package_policy.ts b/x-pack/plugins/fleet/server/types/models/package_policy.ts index e105bc82b27db1..3b41b80efe42c5 100644 --- a/x-pack/plugins/fleet/server/types/models/package_policy.ts +++ b/x-pack/plugins/fleet/server/types/models/package_policy.ts @@ -16,15 +16,24 @@ export const PackagePolicyNamespaceSchema = schema.string({ return namespaceValidation.error; } }, + meta: { + description: + "The package policy namespace. Leave blank to inherit the agent policy's namespace.", + }, }); -const ConfigRecordSchema = schema.recordOf( +export const ConfigRecordSchema = schema.recordOf( schema.string(), schema.object({ type: schema.maybe(schema.string()), value: schema.maybe(schema.any()), frozen: schema.maybe(schema.boolean()), - }) + }), + { + meta: { + description: 'Package variable (see integration documentation for more information)', + }, + } ); const PackagePolicyStreamsSchema = { @@ -62,7 +71,7 @@ const PackagePolicyStreamsSchema = { compiled_stream: schema.maybe(schema.any()), }; -const PackagePolicyInputsSchema = { +export const PackagePolicyInputsSchema = { type: schema.string(), policy_template: schema.maybe(schema.string()), enabled: schema.boolean(), @@ -92,43 +101,88 @@ const ExperimentalDataStreamFeatures = schema.arrayOf( }) ); -const PackagePolicyBaseSchema = { - name: schema.string(), - description: schema.maybe(schema.string()), +export const PackagePolicyPackageSchema = schema.object({ + name: schema.string({ + meta: { + description: 'Package name', + }, + }), + title: schema.maybe(schema.string()), + version: schema.string({ + meta: { + description: 'Package version', + }, + }), + experimental_data_stream_features: schema.maybe(ExperimentalDataStreamFeatures), + requires_root: schema.maybe(schema.boolean()), +}); + +export const PackagePolicyBaseSchema = { + name: schema.string({ + meta: { + description: 'Package policy name (should be unique)', + }, + }), + description: schema.maybe( + schema.string({ + meta: { + description: 'Package policy description', + }, + }) + ), namespace: schema.maybe(PackagePolicyNamespaceSchema), - policy_id: schema.nullable(schema.maybe(schema.string())), - policy_ids: schema.maybe(schema.arrayOf(schema.string())), + policy_id: schema.nullable( + schema.maybe( + schema.string({ + meta: { + description: 'Agent policy ID where that package policy will be added', + deprecated: true, + }, + }) + ) + ), + policy_ids: schema.maybe( + schema.arrayOf( + schema.string({ + meta: { + description: 'Agent policy IDs where that package policy will be added', + }, + }) + ) + ), output_id: schema.nullable(schema.maybe(schema.string())), enabled: schema.boolean(), is_managed: schema.maybe(schema.boolean()), - package: schema.maybe( - schema.object({ - name: schema.string(), - title: schema.string(), - version: schema.string(), - experimental_data_stream_features: schema.maybe(ExperimentalDataStreamFeatures), - requires_root: schema.maybe(schema.boolean()), - }) - ), + package: schema.maybe(PackagePolicyPackageSchema), + inputs: schema.arrayOf(schema.object(PackagePolicyInputsSchema)), vars: schema.maybe(ConfigRecordSchema), overrides: schema.maybe( schema.nullable( - schema.object({ - inputs: schema.maybe( - schema.recordOf(schema.string(), schema.any(), { - validate: (val) => { - if ( - Object.keys(val).some( - (key) => key.match(/^compiled_inputs(\.)?/) || key.match(/^compiled_stream(\.)?/) - ) - ) { - return 'Overrides of compiled_inputs and compiled_stream are not allowed'; - } - }, - }) - ), - }) + schema.object( + { + inputs: schema.maybe( + schema.recordOf(schema.string(), schema.any(), { + validate: (val) => { + if ( + Object.keys(val).some( + (key) => + key.match(/^compiled_inputs(\.)?/) || key.match(/^compiled_stream(\.)?/) + ) + ) { + return 'Overrides of compiled_inputs and compiled_stream are not allowed'; + } + }, + }) + ), + }, + { + meta: { + description: + 'Override settings that are defined in the package policy. The override option should be used only in unusual circumstances and not as a routine procedure.', + }, + } + ) ) ), }; @@ -142,15 +196,7 @@ export const NewPackagePolicySchema = schema.object({ const CreatePackagePolicyProps = { ...PackagePolicyBaseSchema, enabled: schema.maybe(schema.boolean()), - package: schema.maybe( - schema.object({ - name: schema.string(), - title: schema.maybe(schema.string()), - version: schema.string(), - experimental_data_stream_features: schema.maybe(ExperimentalDataStreamFeatures), - requires_root: schema.maybe(schema.boolean()), - }) - ), + package: schema.maybe(PackagePolicyPackageSchema), inputs: schema.arrayOf( schema.object({ ...PackagePolicyInputsSchema, @@ -161,11 +207,24 @@ const CreatePackagePolicyProps = { export const CreatePackagePolicyRequestBodySchema = schema.object({ ...CreatePackagePolicyProps, - id: schema.maybe(schema.string()), - force: schema.maybe(schema.boolean()), + id: schema.maybe( + schema.string({ + meta: { + description: 'Package policy unique identifier', + }, + }) + ), + force: schema.maybe( + schema.boolean({ + meta: { + description: + 'Force package policy creation even if package is not verified, or if the agent policy is managed.', + }, + }) + ), }); -const SimplifiedVarsSchema = schema.recordOf( +export const SimplifiedVarsSchema = schema.recordOf( schema.string(), schema.nullable( schema.oneOf([ @@ -180,6 +239,55 @@ const SimplifiedVarsSchema = schema.recordOf( isSecretRef: schema.boolean(), }), ]) + ), + { + meta: { + description: + 'Input/stream level variable (see integration documentation for more information)', + }, + } +); + +export const SimplifiedPackagePolicyInputsSchema = schema.maybe( + schema.recordOf( + schema.string(), + schema.object({ + enabled: schema.maybe( + schema.boolean({ + meta: { + description: 'enable or disable that input, (default to true)', + }, + }) + ), + vars: schema.maybe(SimplifiedVarsSchema), + streams: schema.maybe( + schema.recordOf( + schema.string(), + schema.object({ + enabled: schema.maybe( + schema.boolean({ + meta: { + description: 'enable or disable that stream, (default to true)', + }, + }) + ), + vars: schema.maybe(SimplifiedVarsSchema), + }), + { + meta: { + description: + 'Input streams (see integration documentation to know what streams are available)', + }, + } + ) + ), + }), + { + meta: { + description: + 'Package policy inputs (see integration documentation to know what inputs are available)', + }, + } ) ); @@ -190,24 +298,7 @@ export const SimplifiedPackagePolicyBaseSchema = schema.object({ namespace: schema.maybe(schema.string()), output_id: schema.nullable(schema.maybe(schema.string())), vars: schema.maybe(SimplifiedVarsSchema), - inputs: schema.maybe( - schema.recordOf( - schema.string(), - schema.object({ - enabled: schema.maybe(schema.boolean()), - vars: schema.maybe(SimplifiedVarsSchema), - streams: schema.maybe( - schema.recordOf( - schema.string(), - schema.object({ - enabled: schema.maybe(schema.boolean()), - vars: schema.maybe(SimplifiedVarsSchema), - }) - ) - ), - }) - ) - ), + inputs: SimplifiedPackagePolicyInputsSchema, }); export const SimplifiedPackagePolicyPreconfiguredSchema = SimplifiedPackagePolicyBaseSchema.extends( @@ -224,12 +315,7 @@ export const SimplifiedCreatePackagePolicyRequestBodySchema = policy_id: schema.nullable(schema.maybe(schema.string())), policy_ids: schema.maybe(schema.arrayOf(schema.string())), force: schema.maybe(schema.boolean()), - package: schema.object({ - name: schema.string(), - version: schema.string(), - experimental_data_stream_features: schema.maybe(ExperimentalDataStreamFeatures), - requires_root: schema.maybe(schema.boolean()), - }), + package: PackagePolicyPackageSchema, }); export const UpdatePackagePolicyRequestBodySchema = schema.object({ @@ -284,3 +370,38 @@ export const PackagePolicySchema = schema.object({ ) ), }); + +export const PackagePolicyResponseSchema = PackagePolicySchema.extends({ + vars: schema.maybe(schema.oneOf([ConfigRecordSchema, schema.maybe(SimplifiedVarsSchema)])), + inputs: schema.oneOf([ + schema.arrayOf( + schema.object({ + ...PackagePolicyInputsSchema, + compiled_input: schema.maybe(schema.any()), + }) + ), + SimplifiedPackagePolicyInputsSchema, + ]), +}); + +export const DryRunPackagePolicySchema = schema.object({ + ...PackagePolicyBaseSchema, + id: schema.maybe(schema.string()), + force: schema.maybe(schema.boolean()), + errors: schema.maybe( + schema.arrayOf( + schema.object({ + message: schema.string(), + key: schema.maybe(schema.string()), + }) + ) + ), +}); + +export const PackagePolicyStatusResponseSchema = schema.object({ + id: schema.string(), + success: schema.boolean(), + name: schema.maybe(schema.string()), + statusCode: schema.maybe(schema.number()), + body: schema.maybe(schema.object({ message: schema.string() })), +}); diff --git a/x-pack/plugins/fleet/server/types/rest_spec/common.ts b/x-pack/plugins/fleet/server/types/rest_spec/common.ts index 0c5f16ff87f90f..2be083d677dd3b 100644 --- a/x-pack/plugins/fleet/server/types/rest_spec/common.ts +++ b/x-pack/plugins/fleet/server/types/rest_spec/common.ts @@ -23,7 +23,10 @@ export const ListWithKuerySchema = schema.object({ }); export const BulkRequestBodySchema = schema.object({ - ids: schema.arrayOf(schema.string(), { minSize: 1 }), + ids: schema.arrayOf(schema.string(), { + minSize: 1, + meta: { description: 'list of package policy ids' }, + }), ignoreMissing: schema.maybe(schema.boolean()), }); diff --git a/x-pack/plugins/fleet/server/types/rest_spec/package_policy.ts b/x-pack/plugins/fleet/server/types/rest_spec/package_policy.ts index 88b4452a5fe7a1..3b6fcbef345021 100644 --- a/x-pack/plugins/fleet/server/types/rest_spec/package_policy.ts +++ b/x-pack/plugins/fleet/server/types/rest_spec/package_policy.ts @@ -71,10 +71,14 @@ export const GetOnePackagePolicyRequestSchema = { }; export const CreatePackagePolicyRequestSchema = { - body: schema.oneOf([ - CreatePackagePolicyRequestBodySchema, - SimplifiedCreatePackagePolicyRequestBodySchema, - ]), + body: schema.oneOf( + [CreatePackagePolicyRequestBodySchema, SimplifiedCreatePackagePolicyRequestBodySchema], + { + meta: { + description: 'You should use inputs as an object and not use the deprecated inputs array.', + }, + } + ), query: schema.object({ format: schema.maybe( schema.oneOf([schema.literal(inputsFormat.Simplified), schema.literal(inputsFormat.Legacy)]) diff --git a/x-pack/plugins/fleet/server/types/rest_spec/uninstall_token.ts b/x-pack/plugins/fleet/server/types/rest_spec/uninstall_token.ts index 924e1da2cb9e85..010b3731776f81 100644 --- a/x-pack/plugins/fleet/server/types/rest_spec/uninstall_token.ts +++ b/x-pack/plugins/fleet/server/types/rest_spec/uninstall_token.ts @@ -8,9 +8,20 @@ import { schema } from '@kbn/config-schema'; export const GetUninstallTokensMetadataRequestSchema = { query: schema.object({ - policyId: schema.maybe(schema.string({ maxLength: 50 })), + policyId: schema.maybe( + schema.string({ + maxLength: 50, + meta: { description: 'Partial match filtering for policy IDs' }, + }) + ), search: schema.maybe(schema.string({ maxLength: 50 })), - perPage: schema.maybe(schema.number({ defaultValue: 20, min: 5 })), + perPage: schema.maybe( + schema.number({ + defaultValue: 20, + min: 5, + meta: { description: 'The number of items to return' }, + }) + ), page: schema.maybe(schema.number({ defaultValue: 1, min: 1 })), }), };