Files
prowler/ui/lib/lighthouse/context/schema.ts
T

201 lines
7.1 KiB
TypeScript

import { z } from "zod";
import { ATTACK_PATH_QUERY_KIND } from "@/types/attack-paths";
import {
LIGHTHOUSE_COMPLIANCE_CONTEXT_MODE,
LIGHTHOUSE_CONTEXT_KIND,
LIGHTHOUSE_CONTEXT_LIMIT,
LIGHTHOUSE_CONTEXT_SOURCE,
LIGHTHOUSE_CONTEXT_TRANSPORT,
} from "./constants";
const boundedStringSchema = z
.string()
.max(LIGHTHOUSE_CONTEXT_LIMIT.STRING_LENGTH);
const boundedCountSchema = z.number().int().nonnegative();
export const lighthouseContextSourceSchema = z.enum(LIGHTHOUSE_CONTEXT_SOURCE);
export const lighthouseContextTransportSchema = z.literal(
LIGHTHOUSE_CONTEXT_TRANSPORT.INLINE,
);
export const lighthouseContextFiltersSchema = z
.record(boundedStringSchema, z.array(boundedStringSchema))
.refine(
(filters) =>
Object.values(filters).reduce(
(total, values) => total + values.length,
0,
) <= LIGHTHOUSE_CONTEXT_LIMIT.FILTER_VALUES,
{
error: `Filters may contain at most ${LIGHTHOUSE_CONTEXT_LIMIT.FILTER_VALUES} values.`,
},
);
export const lighthouseAttackPathTypeCountsSchema = z
.record(boundedStringSchema, boundedCountSchema)
.refine(
(counts) =>
Object.keys(counts).length <=
LIGHTHOUSE_CONTEXT_LIMIT.ATTACK_PATH_TYPE_COUNTS,
{
error: `Attack Path type counts may contain at most ${LIGHTHOUSE_CONTEXT_LIMIT.ATTACK_PATH_TYPE_COUNTS} entries.`,
},
);
export const lighthouseFindingSeverityCountsSchema = z
.record(boundedStringSchema, boundedCountSchema)
.refine(
(counts) =>
Object.keys(counts).length <= LIGHTHOUSE_CONTEXT_LIMIT.SEVERITY_COUNTS,
{
error: `Severity counts may contain at most ${LIGHTHOUSE_CONTEXT_LIMIT.SEVERITY_COUNTS} entries.`,
},
);
export const lighthouseContextItemBaseSchema = z.object({
id: boundedStringSchema,
source: lighthouseContextSourceSchema,
scopeKey: boundedStringSchema,
label: boundedStringSchema,
});
export const lighthousePageContextItemSchema =
lighthouseContextItemBaseSchema.extend({
kind: z.literal(LIGHTHOUSE_CONTEXT_KIND.PAGE),
path: boundedStringSchema,
filters: lighthouseContextFiltersSchema.optional(),
});
export const lighthouseFindingContextItemSchema =
lighthouseContextItemBaseSchema.extend({
kind: z.literal(LIGHTHOUSE_CONTEXT_KIND.FINDING),
findingId: boundedStringSchema,
checkId: boundedStringSchema.optional(),
severity: boundedStringSchema.optional(),
status: boundedStringSchema.optional(),
providerUid: boundedStringSchema.optional(),
resourceUid: boundedStringSchema.optional(),
region: boundedStringSchema.optional(),
total: boundedCountSchema.optional(),
passed: boundedCountSchema.optional(),
failed: boundedCountSchema.optional(),
newPassed: boundedCountSchema.optional(),
newFailed: boundedCountSchema.optional(),
severityCounts: lighthouseFindingSeverityCountsSchema.optional(),
});
export const lighthouseResourceContextItemSchema =
lighthouseContextItemBaseSchema.extend({
kind: z.literal(LIGHTHOUSE_CONTEXT_KIND.RESOURCE),
resourceId: boundedStringSchema,
resourceUid: boundedStringSchema.optional(),
providerUid: boundedStringSchema.optional(),
service: boundedStringSchema.optional(),
region: boundedStringSchema.optional(),
resourceType: boundedStringSchema.optional(),
failedFindingsCount: boundedCountSchema.optional(),
total: boundedCountSchema.optional(),
});
export const lighthouseComplianceTotalsSchema = z.object({
passed: boundedCountSchema.optional(),
failed: boundedCountSchema.optional(),
total: boundedCountSchema.optional(),
});
export const lighthouseComplianceContextItemSchema =
lighthouseContextItemBaseSchema.extend({
kind: z.literal(LIGHTHOUSE_CONTEXT_KIND.COMPLIANCE),
framework: boundedStringSchema,
version: boundedStringSchema.optional(),
scanId: boundedStringSchema.optional(),
providerUid: boundedStringSchema.optional(),
mode: z.enum(LIGHTHOUSE_COMPLIANCE_CONTEXT_MODE).optional(),
section: boundedStringSchema.optional(),
region: boundedStringSchema.optional(),
score: z.number().min(0).max(100).optional(),
scoreDelta: z.number().min(-100).max(100).optional(),
criticalRequirementsCount: boundedCountSchema.optional(),
worstSection: boundedStringSchema.optional(),
worstSectionScore: z.number().min(0).max(100).optional(),
totals: lighthouseComplianceTotalsSchema.optional(),
});
export const lighthouseAttackPathParameterSchema = z.union([
boundedStringSchema,
z.number(),
z.boolean(),
]);
export const lighthouseAttackPathParametersSchema = z.record(
boundedStringSchema,
lighthouseAttackPathParameterSchema,
);
export const lighthouseAttackPathContextItemSchema =
lighthouseContextItemBaseSchema.extend({
kind: z.literal(LIGHTHOUSE_CONTEXT_KIND.ATTACK_PATH),
scanId: boundedStringSchema.optional(),
queryId: boundedStringSchema.optional(),
queryKind: z.enum(ATTACK_PATH_QUERY_KIND).optional(),
canReplayQuery: z.boolean().optional(),
parameters: lighthouseAttackPathParametersSchema.optional(),
redactedParameters: z
.array(boundedStringSchema)
.max(LIGHTHOUSE_CONTEXT_LIMIT.ATTACK_PATH_REDACTED_PARAMETERS)
.optional(),
nodeCount: boundedCountSchema.optional(),
edgeCount: boundedCountSchema.optional(),
connectedComponentCount: boundedCountSchema.optional(),
nodeTypeCounts: lighthouseAttackPathTypeCountsSchema.optional(),
relationshipTypeCounts: lighthouseAttackPathTypeCountsSchema.optional(),
selectedNodeId: boundedStringSchema.optional(),
selectedNodeType: boundedStringSchema.optional(),
});
export const lighthouseScanContextItemSchema =
lighthouseContextItemBaseSchema.extend({
kind: z.literal(LIGHTHOUSE_CONTEXT_KIND.SCAN),
scanId: boundedStringSchema.optional(),
state: boundedStringSchema.optional(),
providerUid: boundedStringSchema.optional(),
total: boundedCountSchema.optional(),
});
export const lighthouseProviderContextItemSchema =
lighthouseContextItemBaseSchema.extend({
kind: z.literal(LIGHTHOUSE_CONTEXT_KIND.PROVIDER),
providerId: boundedStringSchema.optional(),
providerUid: boundedStringSchema.optional(),
providerType: boundedStringSchema.optional(),
total: boundedCountSchema.optional(),
});
export const lighthouseAlertContextItemSchema =
lighthouseContextItemBaseSchema.extend({
kind: z.literal(LIGHTHOUSE_CONTEXT_KIND.ALERT),
alertId: boundedStringSchema.optional(),
trigger: boundedStringSchema.optional(),
enabled: z.boolean().optional(),
total: boundedCountSchema.optional(),
enabledCount: boundedCountSchema.optional(),
});
export const lighthouseContextItemSchema = z.discriminatedUnion("kind", [
lighthousePageContextItemSchema,
lighthouseFindingContextItemSchema,
lighthouseResourceContextItemSchema,
lighthouseComplianceContextItemSchema,
lighthouseAttackPathContextItemSchema,
lighthouseScanContextItemSchema,
lighthouseProviderContextItemSchema,
lighthouseAlertContextItemSchema,
]);
export const lighthouseContextEnvelopeSchema = z.object({
schemaVersion: z.literal(1),
transport: lighthouseContextTransportSchema,
items: z
.array(lighthouseContextItemSchema)
.max(LIGHTHOUSE_CONTEXT_LIMIT.ITEMS),
});