Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion libs/i18n/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -1089,6 +1089,8 @@
"Dependency sync probe failed": "Dependency sync probe failed",
"Dependency change detected": "Dependency change detected",
"Application lifecycle changed": "Application lifecycle changed",
"Preparing delta updates": "Preparing delta updates",
"Delta updates generation complete": "Delta updates generation complete",
"Resource": "Resource",
"Edit fleet": "Edit fleet",
"Create fleet": "Create fleet",
Expand Down Expand Up @@ -1850,8 +1852,8 @@
"Find by name": "Find by name",
"Vulnerabilities table": "Vulnerabilities table",
"Show more": "Show more",
"Published: {{ date }}": "Published: {{ date }}",
"Scanner name": "Scanner name",
"Published: {{ date }}": "Published: {{ date }}",
"<0>{deviceCount}</0> devices in this fleet are running images affected by this vulnerability. Update or replace the affected images to remediate._one": "<0>{deviceCount}</0> device in this fleet is running images affected by this vulnerability. Update or replace the affected images to remediate.",
"<0>{deviceCount}</0> devices in this fleet are running images affected by this vulnerability. Update or replace the affected images to remediate._other": "<0>{deviceCount}</0> devices in this fleet are running images affected by this vulnerability. Update or replace the affected images to remediate.",
"<0>{deviceCount}</0> devices are running images affected by this vulnerability. Update or replace the affected images to remediate._one": "<0>{deviceCount}</0> device is running an image affected by this vulnerability. Update or replace the affected image to remediate.",
Expand Down
13 changes: 12 additions & 1 deletion libs/types/alpha/models/Vulnerability.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
/* eslint-disable */
import type { ApiVersion } from './ApiVersion';
/**
* A single vulnerability (CVE) finding. Vulnerabilities are global CVE records from Trustify; they are not tenant-owned resources. Tenancy is determined by the device or fleet context through which they are queried.
* A single vulnerability (CVE) finding. Vulnerabilities are global CVE records produced by the configured vulnerability scanner; they are not tenant-owned resources. Tenancy is determined by the device or fleet context through which they are queried.
*/
export type Vulnerability = {
apiVersion: ApiVersion;
Expand Down Expand Up @@ -44,6 +44,10 @@ export type Vulnerability = {
* Advisory publish time when known.
*/
publishedAt?: string;
/**
* The vulnerability backend that produced this finding.
*/
source?: Vulnerability.source;
/**
* Image reference (name or URL) from the device context.
*/
Expand All @@ -69,5 +73,12 @@ export namespace Vulnerability {
NONE = 'None',
UNKNOWN = 'Unknown',
}
/**
* The vulnerability backend that produced this finding.
*/
export enum source {
Trustify = 'trustify',
Quay = 'quay',
}
}

5 changes: 4 additions & 1 deletion libs/types/imagebuilder/models/ImageBuildSpec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ export type ImageBuildSpec = {
source: ImageBuildSource;
destination: ImageBuildDestination;
binding: ImageBuildBinding;
onboarding?: boolean;
userConfiguration?: ImageBuildUserConfiguration;
/**
* When true, installs the flightctl-onboarding RPM and enables flightctl-onboarding-setup.service for first-boot device configuration via a Cockpit-based onboarding wizard. Compatible with both early and late binding. Defaults to false.
*/
onboarding?: boolean;
};

2 changes: 2 additions & 0 deletions libs/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ export type { DeviceConfigStatus } from './models/DeviceConfigStatus';
export type { DeviceConsole } from './models/DeviceConsole';
export type { DeviceDecommission } from './models/DeviceDecommission';
export { DeviceDecommissionTargetType } from './models/DeviceDecommissionTargetType';
export type { DeviceDeltaApplyStatus } from './models/DeviceDeltaApplyStatus';
export type { DeviceIntegrityCheckStatus } from './models/DeviceIntegrityCheckStatus';
export { DeviceIntegrityCheckStatusType } from './models/DeviceIntegrityCheckStatusType';
export type { DeviceIntegrityStatus } from './models/DeviceIntegrityStatus';
Expand Down Expand Up @@ -182,6 +183,7 @@ export type { PatchRequest } from './models/PatchRequest';
export type { Percentage } from './models/Percentage';
export type { Permission } from './models/Permission';
export type { PermissionList } from './models/PermissionList';
export type { PrepareDeltasDetails } from './models/PrepareDeltasDetails';
export type { QuadletApplication } from './models/QuadletApplication';
export type { ReferencedRepositoryUpdatedDetails } from './models/ReferencedRepositoryUpdatedDetails';
export type { RelativePath } from './models/RelativePath';
Expand Down
2 changes: 2 additions & 0 deletions libs/types/models/DeviceApplicationStatus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import type { ApplicationStatusType } from './ApplicationStatusType';
import type { ApplicationVolumeStatus } from './ApplicationVolumeStatus';
import type { AppType } from './AppType';
import type { DeviceDeltaApplyStatus } from './DeviceDeltaApplyStatus';
export type DeviceApplicationStatus = {
/**
* Human readable name of the application.
Expand Down Expand Up @@ -32,5 +33,6 @@ export type DeviceApplicationStatus = {
* Status of volumes used by this application.
*/
volumes?: Array<ApplicationVolumeStatus>;
lastDelta?: DeviceDeltaApplyStatus;
};

18 changes: 18 additions & 0 deletions libs/types/models/DeviceDeltaApplyStatus.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
/**
* Result of the most recent delta apply attempt for this update target.
*/
export type DeviceDeltaApplyStatus = {
/**
* Set when the most recent update attempt fell back from a delta to a full image pull. Absent if no delta was attempted or the delta succeeded. Cleared when the next update attempt for this target starts.
*/
fallbackReason?: string;
/**
* Expected delta size in IEC units (KiB, MiB, GiB, or TiB). Absent when the size is not yet known.
*/
size?: string;
};

2 changes: 2 additions & 0 deletions libs/types/models/DeviceLifecycleHookType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@ export enum DeviceLifecycleHookType {
DeviceLifecycleHookAfterUpdating = 'AfterUpdating',
DeviceLifecycleHookBeforeRebooting = 'BeforeRebooting',
DeviceLifecycleHookAfterRebooting = 'AfterRebooting',
DeviceLifecycleHookBeforeEnrolling = 'BeforeEnrolling',
DeviceLifecycleHookAfterEnrolling = 'AfterEnrolling',
}
11 changes: 10 additions & 1 deletion libs/types/models/DeviceOsSpec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,13 @@
/* tslint:disable */
/* eslint-disable */
import type { ImageOrCatalogItemRefSpec } from './ImageOrCatalogItemRefSpec';
export type DeviceOsSpec = ImageOrCatalogItemRefSpec;
/**
* Either a specific OCI image reference, or a reference to a catalog item version that can be resolved to an OCI image ref.
*/
export type DeviceOsSpec = (ImageOrCatalogItemRefSpec & {
/**
* Optional hint: a reference to a delta artifact the control plane's generation records indicate may be applicable to reach `image` from this device's current image. Absent does not imply no delta exists — the device independently discovers candidate delta artifacts (e.g. deltas published by a customer's own CI) regardless of this field, and falls back to a full pull only if none is usable.
*/
deltaImage?: string;
});

2 changes: 2 additions & 0 deletions libs/types/models/DeviceOsStatus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import type { DeviceDeltaApplyStatus } from './DeviceDeltaApplyStatus';
/**
* Current status of the device OS.
*/
Expand All @@ -14,5 +15,6 @@ export type DeviceOsStatus = {
* The digest of the OS image (e.g. sha256:a0...).
*/
imageDigest: string;
lastDelta?: DeviceDeltaApplyStatus;
};

2 changes: 2 additions & 0 deletions libs/types/models/Event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ export namespace Event {
ENCRYPTION_MIGRATION_STARTED = 'EncryptionMigrationStarted',
ENCRYPTION_MIGRATION_COMPLETED = 'EncryptionMigrationCompleted',
APPLICATION_LIFECYCLE_CHANGED = 'ApplicationLifecycleChanged',
PREPARE_DELTAS = 'PrepareDeltas',
DELTA_GENERATION_COMPLETED = 'DeltaGenerationCompleted',
}
/**
* The type of the event. One of Normal, Warning.
Expand Down
3 changes: 2 additions & 1 deletion libs/types/models/EventDetails.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@ import type { FleetRolloutFailedDetails } from './FleetRolloutFailedDetails';
import type { FleetRolloutStartedDetails } from './FleetRolloutStartedDetails';
import type { InternalTaskFailedDetails } from './InternalTaskFailedDetails';
import type { InternalTaskPermanentlyFailedDetails } from './InternalTaskPermanentlyFailedDetails';
import type { PrepareDeltasDetails } from './PrepareDeltasDetails';
import type { ReferencedRepositoryUpdatedDetails } from './ReferencedRepositoryUpdatedDetails';
import type { ResourceSyncCompletedDetails } from './ResourceSyncCompletedDetails';
import type { ResourceUpdatedDetails } from './ResourceUpdatedDetails';
/**
* Event-specific details, structured based on event type.
*/
export type EventDetails = (ResourceUpdatedDetails | DeviceOwnershipChangedDetails | DeviceMultipleOwnersDetectedDetails | DeviceMultipleOwnersResolvedDetails | InternalTaskFailedDetails | InternalTaskPermanentlyFailedDetails | ResourceSyncCompletedDetails | ReferencedRepositoryUpdatedDetails | FleetRolloutStartedDetails | FleetRolloutFailedDetails | FleetRolloutCompletedDetails | FleetRolloutBatchDispatchedDetails | FleetRolloutBatchCompletedDetails | FleetRolloutDeviceSelectedDetails | DeviceVulnerabilityCveDetails | DependencyChangeDetectedDetails | DependencySyncProbeFailedDetails | ApplicationLifecycleChangedDetails);
export type EventDetails = (ResourceUpdatedDetails | DeviceOwnershipChangedDetails | DeviceMultipleOwnersDetectedDetails | DeviceMultipleOwnersResolvedDetails | InternalTaskFailedDetails | InternalTaskPermanentlyFailedDetails | ResourceSyncCompletedDetails | ReferencedRepositoryUpdatedDetails | FleetRolloutStartedDetails | FleetRolloutFailedDetails | FleetRolloutCompletedDetails | FleetRolloutBatchDispatchedDetails | FleetRolloutBatchCompletedDetails | FleetRolloutDeviceSelectedDetails | DeviceVulnerabilityCveDetails | DependencyChangeDetectedDetails | DependencySyncProbeFailedDetails | ApplicationLifecycleChangedDetails | PrepareDeltasDetails);

12 changes: 12 additions & 0 deletions libs/types/models/OciRepoSpec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,18 @@ export type OciRepoSpec = {
* Skip remote server verification.
*/
skipServerVerification?: boolean;
/**
* Optional OCI repository path under spec.registry (e.g. my-org/diffs). When set, this object is that repo (`my-registry.com/my-org/diffs`), not only a registry. Mutually exclusive with namespace. ImageBuild destination imageName must equal this value.
*/
repository?: string;
/**
* Optional org/subpath under spec.registry (e.g. my-org). Concrete names are spec.registry/namespace/<name>. Mutually exclusive with repository. Used by delta push (`{registry}/{namespace}/{imageName}`). Invalid on an ImageBuild or ImageExport destination Repository.
*/
namespace?: string;
/**
* When true, generated deltas are pushed to this object (at most one per org). Auth is the existing ociAuth / accessMode. Placement follows repository / namespace / registry-only as above.
*/
deltaStorageTarget?: boolean;
/**
* Curated list of trusted base images available in this registry. When present, the Image Builder source picker surfaces these entries as selectable options.
*/
Expand Down
18 changes: 18 additions & 0 deletions libs/types/models/PrepareDeltasDetails.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
/**
* Structured details for PrepareDeltas events.
*/
export type PrepareDeltasDetails = {
/**
* The type of detail for discriminator purposes.
*/
detailType: 'PrepareDeltas';
/**
* Fleet only. The TemplateVersion this prepare is for. Required when involvedObject.kind is Fleet; omitted for Device.
*/
templateVersion?: string;
};

3 changes: 3 additions & 0 deletions libs/ui-components/src/components/Events/useEvents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,9 @@ const getEventReasonTitles = (t: TFunction, kindType: string): Record<Event.reas
[Event.reason.DEPENDENCY_CHANGE_DETECTED]: t('Dependency change detected'),
// Application lifecycle events
[Event.reason.APPLICATION_LIFECYCLE_CHANGED]: t('Application lifecycle changed'),
// Delta updates events
[Event.reason.PREPARE_DELTAS]: t('Preparing delta updates'),
[Event.reason.DELTA_GENERATION_COMPLETED]: t('Delta updates generation complete'),
};
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import * as React from 'react';
import { type Vulnerability, type VulnerabilityGroup, type VulnerabilityGroupItem } from '@flightctl/types/alpha';
import { getPrimaryVulnerabilityGroupFinding, isRedHatIssuer, isVulnerabilityGroup } from '../../utils/vulnerabilities';
import type { Vulnerability, VulnerabilityGroup, VulnerabilityGroupItem } from '@flightctl/types/alpha';
import {
getPrimaryVulnerabilityGroupFinding,
getVulnerabilitySource,
isRedHatIssuer,
isVulnerabilityGroup,
} from '../../utils/vulnerabilities';

import {
Content,
Expand All @@ -21,6 +26,7 @@ import {
import { VulnerabilitySeverityBadge, VulnerabilitySeverityDetails } from '../Status/VulnerabilitySeverityStatus';
import { getDateDisplay } from '../../utils/dates';
import { useTranslation } from '../../hooks/useTranslation';
import { useAppContext } from '../../hooks/useAppContext';

import VulnerabilityImpact, { VulnerabilityImpactMessageSingleDevice } from './VulnerabilityImpact';
import VulnerabilityDescription from './VulnerabilityDescription';
Expand All @@ -34,6 +40,19 @@ type VulnerabilityDetailsDrawerProps = {
onClose: VoidFunction;
};

const VulnerabilitySource = ({ vulnerability }: { vulnerability: Vulnerability }) => {
const { t } = useTranslation();
const { settings } = useAppContext();

const source = getVulnerabilitySource(vulnerability, settings.isRHEM ?? false);
return (
<DescriptionListGroup>
<DescriptionListTerm>{t('Scanner name')}</DescriptionListTerm>
<DescriptionListDescription>{source}</DescriptionListDescription>
</DescriptionListGroup>
);
};

const VulnerabilityDetailsDrawer = ({
vulnerability,
isSingleDevice,
Expand Down Expand Up @@ -86,7 +105,7 @@ const VulnerabilityDetailsDrawer = ({
</StackItem>
)}
<StackItem>
<DescriptionList columnModifier={{ lg: '3Col' }} className="pf-v6-u-mt-lg">
<DescriptionList columnModifier={{ lg: isGrouped ? '1Col' : '2Col' }} className="pf-v6-u-mt-lg">
<DescriptionListGroup>
<DescriptionListTerm>{t('Severity')}</DescriptionListTerm>
<DescriptionListDescription>
Expand All @@ -97,10 +116,8 @@ const VulnerabilityDetailsDrawer = ({
)}
</DescriptionListDescription>
</DescriptionListGroup>
<DescriptionListGroup>
<DescriptionListTerm>{t('Scanner name')}</DescriptionListTerm>
<DescriptionListDescription>Trustify</DescriptionListDescription>
</DescriptionListGroup>
{/* API does not return the source for grouped vulnerabilities */}
{!isGrouped && <VulnerabilitySource vulnerability={vulnerability} />}
</DescriptionList>
</StackItem>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export const VulnerabilitySeverityDetails = ({ severity, cvssScore }: Vulnerabil
const { t } = useTranslation();

return (
<Flex gap={{ default: 'gapSm' }} alignItems={{ default: 'alignItemsCenter' }} flexWrap={{ default: 'wrap' }}>
<Flex gap={{ default: 'gapSm' }} alignItems={{ default: 'alignItemsCenter' }} flexWrap={{ default: 'nowrap' }}>
<FlexItem>
<VulnerabilitySeverityBadge severity={severity} />
</FlexItem>
Expand Down
19 changes: 19 additions & 0 deletions libs/ui-components/src/utils/vulnerabilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,25 @@ export const getPrimaryVulnerabilityGroupFinding = (
return findingsWithLink.find((finding) => isRedHatIssuer(finding.issuer)) || findingsWithLink[0] || findings[0];
};

const DEFAULT_VULNERABILITY_SOURCE_US = 'Trustify';
const DEFAULT_VULNERABILITY_SOURCE_DS = 'Red Hat Trusted Profile Analyzer';
const QUAY_VULNERABILITY_SOURCE = 'Quay';

export const getVulnerabilitySource = (vulnerability: Vulnerability, isRHEM: boolean) => {
switch (vulnerability.source) {
case Vulnerability.source.Trustify:
return isRHEM ? DEFAULT_VULNERABILITY_SOURCE_DS : DEFAULT_VULNERABILITY_SOURCE_US;
case Vulnerability.source.Quay:
return QUAY_VULNERABILITY_SOURCE;
case undefined:
// Source is missing, fallback to the default backend.
return DEFAULT_VULNERABILITY_SOURCE_US;
default:
// Source is unknown to the UI, return it as is.
return vulnerability.source;
}
};

export const getSeverityCountValue = (severity: Severity, counts: CveCountsBySeverity) => {
switch (severity) {
case Vulnerability.severity.CRITICAL:
Expand Down
Loading