Files
CertScope-Public/lib/inspect/inspect.ts
T

48 lines
2.5 KiB
TypeScript

import { collectDns } from "./dns";
import { evaluateDiagnostics } from "./diagnostics";
import { collectTls } from "./tls";
import { collectHttp } from "./http";
import { normalizeHost, validateResolvedAddresses } from "./policy";
import { score } from "./score";
import type { Category, CollectorStatus, InspectionResult } from "./types";
function collectorStatus(value: Record<string, unknown>): CollectorStatus {
const meta = value._meta;
if (!meta || typeof meta !== "object" || typeof (meta as Record<string, unknown>).status !== "string") return "failed";
const status = String((meta as Record<string, unknown>).status);
return status === "ok" || status === "partial" || status === "failed" ? status : "failed";
}
export function buildCompleteness(dns: Record<string, unknown>, tls: Record<string, unknown>, http: Record<string, unknown>) {
const collectors: Record<Category, CollectorStatus> = {
dns: collectorStatus(dns),
tls: collectorStatus(tls),
http: collectorStatus(http),
};
const statuses = Object.values(collectors);
const complete = statuses.filter((status) => status === "ok").length;
const issues = [dns, tls, http].flatMap((collector) => {
const errors = collector._meta && typeof collector._meta === "object" ? (collector._meta as Record<string, unknown>).errors : [];
return Array.isArray(errors) ? errors.map((error) => typeof error === "object" && error !== null && "message" in error ? String((error as { message?: unknown }).message) : String(error)) : [];
});
return {
status: complete === statuses.length ? "complete" as const : complete === 0 ? "failed" as const : "partial" as const,
complete,
total: statuses.length,
collectors,
issues: [...new Set(issues)],
};
}
export async function inspectHost(rawHost: string): Promise<InspectionResult> {
const host = normalizeHost(rawHost);
const dns = await collectDns(host);
const addresses = validateResolvedAddresses([
...(Array.isArray(dns.a) ? dns.a.filter((value): value is string => typeof value === "string") : []),
...(Array.isArray(dns.aaaa) ? dns.aaaa.filter((value): value is string => typeof value === "string") : []),
]);
const [tls, http] = await Promise.all([collectTls(host, addresses), collectHttp(host)]);
const findings = evaluateDiagnostics(dns, tls, http);
return { host, inspectedAt: new Date().toISOString(), addresses, completeness: buildCompleteness(dns, tls, http), dns, tls, http, findings, score: score(findings) };
}