diff --git a/dev-tools/build-packages/deb/deb-builder.sh b/dev-tools/build-packages/deb/deb-builder.sh index 581454128ede..1e9e302796ff 100755 --- a/dev-tools/build-packages/deb/deb-builder.sh +++ b/dev-tools/build-packages/deb/deb-builder.sh @@ -60,6 +60,11 @@ log "Extracting base tar.gz..." tar -zxf "${out_dir}/wazuh-dashboard-$version-$revision-linux-$architecture.tar.gz" log "Preparing the package..." jq '.wazuh.revision="'${revision}'"' package.json > pkgtmp.json && mv pkgtmp.json package.json +if [ "${is_production}" = "yes" ]; then + jq '.wazuh.isProduction = true' package.json > pkgtmp.json && mv pkgtmp.json package.json +else + jq '.wazuh.isProduction = false' package.json > pkgtmp.json && mv pkgtmp.json package.json +fi mkdir -p etc/services cp "${config_path}"/* etc/services jq '.version="'${version}'"' VERSION.json > VERSION.tmp && mv VERSION.tmp VERSION.json diff --git a/dev-tools/build-packages/rpm/rpm-builder.sh b/dev-tools/build-packages/rpm/rpm-builder.sh index 14f04422be93..99d16b3e67af 100644 --- a/dev-tools/build-packages/rpm/rpm-builder.sh +++ b/dev-tools/build-packages/rpm/rpm-builder.sh @@ -58,6 +58,11 @@ log "Extracting base tar.gz..." tar -zxf "${out_dir}/wazuh-dashboard-$version-$revision-linux-$architecture.tar.gz" log "Preparing the package..." jq '.wazuh.revision="'${revision}'"' package.json > pkgtmp.json && mv pkgtmp.json package.json +if [ "${is_production}" = "yes" ]; then + jq '.wazuh.isProduction = true' package.json > pkgtmp.json && mv pkgtmp.json package.json +else + jq '.wazuh.isProduction = false' package.json > pkgtmp.json && mv pkgtmp.json package.json +fi mkdir -p etc/services cp "${config_path}"/* etc/services jq '.version="'${version}'"' VERSION.json > VERSION.tmp && mv VERSION.tmp VERSION.json diff --git a/packages/osd-config/src/env.test.mocks.ts b/packages/osd-config/src/env.test.mocks.ts index 62ad59a444cd..8723dd6f11d0 100644 --- a/packages/osd-config/src/env.test.mocks.ts +++ b/packages/osd-config/src/env.test.mocks.ts @@ -44,6 +44,15 @@ export const mockPackage = { raw: {}, }; +export const mockVersionFile = { + raw: { stage: '' }, +}; + jest.doMock('load-json-file', () => ({ - sync: () => mockPackage.raw, + sync: (filePath: string) => { + if (filePath.endsWith('VERSION.json')) { + return mockVersionFile.raw; + } + return mockPackage.raw; + }, })); diff --git a/packages/osd-config/src/env.ts b/packages/osd-config/src/env.ts index e82355595e99..d9cad175a9ae 100644 --- a/packages/osd-config/src/env.ts +++ b/packages/osd-config/src/env.ts @@ -69,9 +69,25 @@ export interface RawPackageInfo { }; wazuh: { version: string; + revision?: string; + isProduction?: boolean; }; } +/** @internal */ +interface RawWazuhVersionFile { + version?: string; + stage?: string; +} + +function loadWazuhVersionFile(repoRoot: string): RawWazuhVersionFile { + try { + return loadJsonFile.sync(join(repoRoot, 'VERSION.json')) as RawWazuhVersionFile; + } catch { + return {}; + } +} + export class Env { /** * @internal @@ -154,6 +170,7 @@ export class Env { const isOpenSearchDashboardsDistributable = Boolean( pkg.build && pkg.build.distributable === true ); + const wazuhVersionFile = loadWazuhVersionFile(this.homeDir); this.packageInfo = Object.freeze({ branch: pkg.branch, buildNum: isOpenSearchDashboardsDistributable ? pkg.build.number : Number.MAX_SAFE_INTEGER, @@ -163,6 +180,9 @@ export class Env { version: pkg.version, dist: isOpenSearchDashboardsDistributable, wazuhVersion: pkg.wazuh.version, + wazuhRevision: pkg.wazuh.revision ?? '01', + wazuhStage: wazuhVersionFile.stage ?? '', + wazuhIsProduction: pkg.wazuh.isProduction ?? false, }); } } diff --git a/packages/osd-config/src/types.ts b/packages/osd-config/src/types.ts index 1a0927770d08..091635e31d47 100644 --- a/packages/osd-config/src/types.ts +++ b/packages/osd-config/src/types.ts @@ -38,6 +38,9 @@ export interface PackageInfo { buildSha: string; dist: boolean; wazuhVersion: string; + wazuhRevision: string; + wazuhStage: string; + wazuhIsProduction: boolean; } /** diff --git a/src/core/public/chrome/chrome_service.tsx b/src/core/public/chrome/chrome_service.tsx index 48d1cd2ce35f..80995154087f 100644 --- a/src/core/public/chrome/chrome_service.tsx +++ b/src/core/public/chrome/chrome_service.tsx @@ -401,7 +401,7 @@ export class ChromeService { homeHref={application.getUrlForApp('wz-home')} isVisible$={this.isVisible$} headerVariant$={this.headerVariant$} - opensearchDashboardsVersion={injectedMetadata.getWazuhVersion()} + opensearchDashboardsVersion={injectedMetadata.getWazuhBuildInfo().version} navLinks$={navLinks.getNavLinks$()} recentlyAccessed$={recentlyAccessed.get$()} navControlsLeft$={navControls.getLeft$()} diff --git a/src/core/public/core_system.ts b/src/core/public/core_system.ts index 21777edecf19..4edb690b0cd4 100644 --- a/src/core/public/core_system.ts +++ b/src/core/public/core_system.ts @@ -302,7 +302,11 @@ export class CoreSystem { docLinks, http, i18n, - injectedMetadata: pick(injectedMetadata, ['getInjectedVar', 'getBranding']), + injectedMetadata: pick(injectedMetadata, [ + 'getInjectedVar', + 'getBranding', + 'getWazuhBuildInfo', + ]), notifications, overlays, savedObjects, diff --git a/src/core/public/index.ts b/src/core/public/index.ts index aacd51deaceb..2b444199cd89 100644 --- a/src/core/public/index.ts +++ b/src/core/public/index.ts @@ -106,9 +106,11 @@ import { KeyboardShortcutSetup, KeyboardShortcutStart } from './keyboard_shortcu import { ChatServiceSetup, ChatServiceStart } from './chat'; import type { TelemetryServiceSetup, TelemetryServiceStart } from './telemetry'; import { HealthCheckServiceSetup, HealthCheckServiceStart } from './healthcheck'; +import type { WazuhBuildInfo } from '../types/wazuh_build_info'; export type { Logos } from '../common'; export { PackageInfo, EnvironmentMode } from '../server/types'; +export type { WazuhBuildInfo } from '../types/wazuh_build_info'; /** @interal */ export { CoreContext, CoreSystem } from './core_system'; export { @@ -288,6 +290,8 @@ export interface CoreSetup unknown; getBranding: () => Branding; + // Wazuh + getWazuhBuildInfo: () => WazuhBuildInfo; }; /** {@link StartServicesAccessor} */ getStartServices: StartServicesAccessor; @@ -355,6 +359,8 @@ export interface CoreStart { injectedMetadata: { getInjectedVar: (name: string, defaultValue?: any) => unknown; getBranding: () => Branding; + // Wazuh + getWazuhBuildInfo: () => WazuhBuildInfo; }; /** {@link WorkspacesStart} */ workspaces: WorkspacesStart; diff --git a/src/core/public/injected_metadata/injected_metadata_service.mock.ts b/src/core/public/injected_metadata/injected_metadata_service.mock.ts index 8f1c178bdc3b..768200af2110 100644 --- a/src/core/public/injected_metadata/injected_metadata_service.mock.ts +++ b/src/core/public/injected_metadata/injected_metadata_service.mock.ts @@ -29,8 +29,17 @@ */ import type { PublicMethodsOf } from '@osd/utility-types'; +import { healthCheckConfig } from 'src/core/server/healthcheck/healthcheck/health_check.mock'; +import { WazuhBuildInfo } from '../../types/wazuh_build_info'; import { InjectedMetadataService, InjectedMetadataSetup } from './injected_metadata_service'; +export const mockWazuhBuildInfo: WazuhBuildInfo = { + version: '4.x.x', + revision: '01', + stage: '', + isProduction: false, +}; + const createSetupContractMock = () => { const setupContract: jest.Mocked = { getBasePath: jest.fn(), @@ -47,7 +56,7 @@ const createSetupContractMock = () => { getBranding: jest.fn(), getSurvey: jest.fn(), getKeyboardShortcuts: jest.fn(), - getWazuhVersion: jest.fn(), + getWazuhBuildInfo: jest.fn(), getWazuhDocVersion: jest.fn(), // Wazuh getHealthCheck: jest.fn(), @@ -68,18 +77,27 @@ const createSetupContractMock = () => { } as any); setupContract.getPlugins.mockReturnValue([]); setupContract.getKeyboardShortcuts.mockReturnValue({ enabled: true }); - setupContract.getWazuhVersion.mockReturnValue('4.x.x'); + setupContract.getWazuhBuildInfo.mockReturnValue(mockWazuhBuildInfo); setupContract.getWazuhDocVersion.mockReturnValue('4.x'); + setupContract.getHealthCheck.mockReturnValue(healthCheckConfig); return setupContract; }; -const createStartContractMock = createSetupContractMock; - type InjectedMetadataServiceContract = PublicMethodsOf; -const createMock = (): jest.Mocked => ({ - setup: jest.fn().mockReturnValue(createSetupContractMock()), - start: jest.fn().mockReturnValue(createStartContractMock()), -}); + +const createStartContractMock = () => createSetupContractMock(); + +const createMock = () => { + const mocked: jest.Mocked = { + setup: jest.fn(), + start: jest.fn(), + }; + + mocked.setup.mockReturnValue(createSetupContractMock()); + mocked.start.mockReturnValue(createStartContractMock()); + + return mocked; +}; export const injectedMetadataServiceMock = { create: createMock, diff --git a/src/core/public/injected_metadata/injected_metadata_service.ts b/src/core/public/injected_metadata/injected_metadata_service.ts index 7cc01367398d..4f7c96e5bc4b 100644 --- a/src/core/public/injected_metadata/injected_metadata_service.ts +++ b/src/core/public/injected_metadata/injected_metadata_service.ts @@ -39,6 +39,7 @@ import { UserProvidedValues, } from '../../server/types'; import { AppCategory, Branding } from '../'; +import { WazuhBuildInfo } from '../../types/wazuh_build_info'; export interface InjectedPluginMetadata { id: PluginName; @@ -54,7 +55,7 @@ export interface InjectedMetadataParams { version: string; buildNumber: number; branch: string; - wazuhVersion: string; + wazuhBuildInfo: WazuhBuildInfo; basePath: string; serverBasePath: string; category?: AppCategory; @@ -166,13 +167,13 @@ export class InjectedMetadataService { }, // Wazuh - getWazuhVersion: () => { - return this.state.wazuhVersion; + getWazuhBuildInfo: () => { + return this.state.wazuhBuildInfo; }, // Wazuh getWazuhDocVersion: () => { - return this.state.wazuhVersion?.split('.').slice(0, 2).join('.') || 'current'; + return this.state.wazuhBuildInfo.version?.split('.').slice(0, 2).join('.') || 'current'; }, // Wazuh @@ -218,7 +219,7 @@ export interface InjectedMetadataSetup { enabled: boolean; }; // Wazuh - getWazuhVersion: () => string; + getWazuhBuildInfo: () => WazuhBuildInfo; getWazuhDocVersion: () => string; getHealthCheck: () => HealthCheckConfig; } diff --git a/src/core/public/mocks.ts b/src/core/public/mocks.ts index 4c820cb82cac..ec3b0a423859 100644 --- a/src/core/public/mocks.ts +++ b/src/core/public/mocks.ts @@ -59,7 +59,10 @@ export { docLinksServiceMock } from './doc_links/doc_links_service.mock'; export { fatalErrorsServiceMock } from './fatal_errors/fatal_errors_service.mock'; export { httpServiceMock } from './http/http_service.mock'; export { i18nServiceMock } from './i18n/i18n_service.mock'; -export { injectedMetadataServiceMock } from './injected_metadata/injected_metadata_service.mock'; +export { + injectedMetadataServiceMock, + mockWazuhBuildInfo, +} from './injected_metadata/injected_metadata_service.mock'; export { notificationServiceMock } from './notifications/notifications_service.mock'; export { overlayServiceMock } from './overlays/overlay_service.mock'; export { savedObjectsServiceMock } from './saved_objects/saved_objects_service.mock'; @@ -93,6 +96,7 @@ function createCoreSetupMock({ injectedMetadata: { getInjectedVar: injectedMetadataServiceMock.createSetupContract().getInjectedVar, getBranding: injectedMetadataServiceMock.createSetupContract().getBranding, + getWazuhBuildInfo: injectedMetadataServiceMock.createSetupContract().getWazuhBuildInfo, }, workspaces: workspacesServiceMock.createSetupContract(), keyboardShortcut: keyboardShortcutServiceMock.createSetup(), @@ -117,6 +121,7 @@ function createCoreStartMock({ basePath = '' } = {}) { injectedMetadata: { getInjectedVar: injectedMetadataServiceMock.createStartContract().getInjectedVar, getBranding: injectedMetadataServiceMock.createStartContract().getBranding, + getWazuhBuildInfo: injectedMetadataServiceMock.createStartContract().getWazuhBuildInfo, }, fatalErrors: fatalErrorsServiceMock.createStartContract(), workspaces: workspacesServiceMock.createStartContract(), @@ -144,6 +149,9 @@ function pluginInitializerContextMock() { buildSha: 'buildSha', dist: false, wazuhVersion: 'wazuhVersion', + wazuhRevision: '01', + wazuhStage: '', + wazuhIsProduction: false, }, }, config: { @@ -170,6 +178,9 @@ function createCoreContext(): CoreContext { buildSha: 'buildSha', dist: false, wazuhVersion: 'wazuhVersion', + wazuhRevision: '01', + wazuhStage: '', + wazuhIsProduction: false, }, }, }; diff --git a/src/core/public/plugins/plugin_context.ts b/src/core/public/plugins/plugin_context.ts index 83d0c0a48126..389922e8f707 100644 --- a/src/core/public/plugins/plugin_context.ts +++ b/src/core/public/plugins/plugin_context.ts @@ -120,6 +120,7 @@ export function createPluginSetupContext< injectedMetadata: { getInjectedVar: deps.injectedMetadata.getInjectedVar, getBranding: deps.injectedMetadata.getBranding, + getWazuhBuildInfo: deps.injectedMetadata.getWazuhBuildInfo, }, getStartServices: () => plugin.startDependencies, workspaces: deps.workspaces, @@ -179,6 +180,7 @@ export function createPluginStartContext< injectedMetadata: { getInjectedVar: deps.injectedMetadata.getInjectedVar, getBranding: deps.injectedMetadata.getBranding, + getWazuhBuildInfo: deps.injectedMetadata.getWazuhBuildInfo, }, fatalErrors: deps.fatalErrors, workspaces: deps.workspaces, diff --git a/src/core/public/plugins/plugins_service.test.ts b/src/core/public/plugins/plugins_service.test.ts index f5016c3e4ca9..f30c628a29ef 100644 --- a/src/core/public/plugins/plugins_service.test.ts +++ b/src/core/public/plugins/plugins_service.test.ts @@ -124,7 +124,12 @@ describe('PluginsService', () => { ...mockSetupDeps, application: expect.any(Object), getStartServices: expect.any(Function), - injectedMetadata: pick(mockSetupDeps.injectedMetadata, 'getInjectedVar', 'getBranding'), + injectedMetadata: pick( + mockSetupDeps.injectedMetadata, + 'getInjectedVar', + 'getBranding', + 'getWazuhBuildInfo' + ), }; mockStartDeps = { application: applicationServiceMock.createInternalStartContract(), @@ -148,7 +153,12 @@ describe('PluginsService', () => { ...mockStartDeps, application: expect.any(Object), chrome: omit(mockStartDeps.chrome, 'getComponent'), - injectedMetadata: pick(mockStartDeps.injectedMetadata, 'getInjectedVar', 'getBranding'), + injectedMetadata: pick( + mockStartDeps.injectedMetadata, + 'getInjectedVar', + 'getBranding', + 'getWazuhBuildInfo' + ), telemetry: expect.any(Object), }; diff --git a/src/core/server/mocks.ts b/src/core/server/mocks.ts index 1d6c53686321..707c87dd6066 100644 --- a/src/core/server/mocks.ts +++ b/src/core/server/mocks.ts @@ -129,6 +129,9 @@ function pluginInitializerContextMock(config: T = {} as T) { buildSha: 'buildSha', dist: false, wazuhVersion: 'wazuhVersion', + wazuhRevision: '01', + wazuhStage: '', + wazuhIsProduction: false, }, instanceUuid: 'instance-uuid', }, diff --git a/src/core/server/plugins/discovery/plugin_manifest_parser.test.ts b/src/core/server/plugins/discovery/plugin_manifest_parser.test.ts index 18e242133e9f..48a301c60d69 100644 --- a/src/core/server/plugins/discovery/plugin_manifest_parser.test.ts +++ b/src/core/server/plugins/discovery/plugin_manifest_parser.test.ts @@ -46,6 +46,9 @@ const packageInfo = { version: '7.0.0-alpha1', dist: false, wazuhVersion: '4.0.0', + wazuhRevision: '01', + wazuhStage: '', + wazuhIsProduction: false, }; afterEach(() => { diff --git a/src/core/server/rendering/rendering_service.test.ts b/src/core/server/rendering/rendering_service.test.ts index 025cbe6a21a9..33307e9010ba 100644 --- a/src/core/server/rendering/rendering_service.test.ts +++ b/src/core/server/rendering/rendering_service.test.ts @@ -72,8 +72,17 @@ const INJECTED_METADATA = { dist: expect.any(Boolean), version: expect.any(String), wazuhVersion: expect.any(String), + wazuhRevision: expect.any(String), + wazuhStage: expect.any(String), + wazuhIsProduction: expect.any(Boolean), }, }, + wazuhBuildInfo: { + version: expect.any(String), + revision: expect.any(String), + stage: expect.any(String), + isProduction: expect.any(Boolean), + }, }; const { createOpenSearchDashboardsRequest, createRawRequest } = httpServerMock; diff --git a/src/core/server/rendering/rendering_service.tsx b/src/core/server/rendering/rendering_service.tsx index 059e572d88f7..79813715ebdc 100644 --- a/src/core/server/rendering/rendering_service.tsx +++ b/src/core/server/rendering/rendering_service.tsx @@ -125,7 +125,12 @@ export class RenderingService { version: env.packageInfo.version, buildNumber: env.packageInfo.buildNum, branch: env.packageInfo.branch, - wazuhVersion: env.packageInfo.wazuhVersion, + wazuhBuildInfo: { + version: env.packageInfo.wazuhVersion, + revision: env.packageInfo.wazuhRevision, + stage: env.packageInfo.wazuhStage, + isProduction: env.packageInfo.wazuhIsProduction, + }, basePath, serverBasePath, env, diff --git a/src/core/server/rendering/types.ts b/src/core/server/rendering/types.ts index 31e588b47761..bc3695373707 100644 --- a/src/core/server/rendering/types.ts +++ b/src/core/server/rendering/types.ts @@ -53,7 +53,12 @@ export interface RenderingMetadata { version: string; buildNumber: number; branch: string; - wazuhVersion: string; + wazuhBuildInfo: { + version: string; + revision: string; + stage: string; + isProduction: boolean; + }; basePath: string; serverBasePath: string; env: { diff --git a/src/core/server/rendering/views/template.test.tsx b/src/core/server/rendering/views/template.test.tsx index 6145acf1c366..c04717869898 100644 --- a/src/core/server/rendering/views/template.test.tsx +++ b/src/core/server/rendering/views/template.test.tsx @@ -29,7 +29,7 @@ function mockProps() { version: injectedMetadata.getOpenSearchDashboardsVersion(), buildNumber: 1, branch: injectedMetadata.getBasePath(), - wazuhVersion: injectedMetadata.getWazuhVersion(), + wazuhBuildInfo: injectedMetadata.getWazuhBuildInfo(), basePath: '', serverBasePath: '', env: { @@ -40,6 +40,9 @@ function mockProps() { buildSha: '', dist: true, wazuhVersion: '', + wazuhRevision: '01', + wazuhStage: '', + wazuhIsProduction: false, }, mode: { name: 'production' as 'development' | 'production', diff --git a/src/core/server/status/routes/integration_tests/status.test.ts b/src/core/server/status/routes/integration_tests/status.test.ts index 1bb885e49257..df135b13e42d 100644 --- a/src/core/server/status/routes/integration_tests/status.test.ts +++ b/src/core/server/status/routes/integration_tests/status.test.ts @@ -81,6 +81,9 @@ describe('GET /api/status', () => { dist: true, version: '9.9.9-SNAPSHOT', wazuhVersion: '4.2.0', + wazuhRevision: '01', + wazuhStage: '', + wazuhIsProduction: false, }, serverName: 'xopensearchDashboards', uuid: 'xxxx-xxxxx', diff --git a/src/core/types/wazuh_build_info.ts b/src/core/types/wazuh_build_info.ts new file mode 100644 index 000000000000..5ed1df644b8c --- /dev/null +++ b/src/core/types/wazuh_build_info.ts @@ -0,0 +1,16 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * Wazuh build metadata exposed to plugins via injectedMetadata. + * + * @public + */ +export interface WazuhBuildInfo { + version: string; + revision: string; + stage: string; + isProduction: boolean; +}