
Vsak validator OSCAL trdi, da »validira OSCAL«. Skoraj noben pa vam ne zna povedati, kaj ta stavek pomeni.
Modeli OSCAL organizacije NIST so napisani v jeziku Metaschema: osem korenskih modulov in skupni uvozi, tisoče vrstic XML, ki ne opredeljujejo le oblike dokumentov, temveč tudi semantiko: dovoljene besednjake vrednosti, pravila enoličnosti, indekse navzkrižnih sklicev, zahteve glede kardinalnosti. JSON Schema ujame obliko. Semantika pa je tisto mesto, kjer gre pri dokumentih o skladnosti dejansko kaj narobe, in tisto mesto, kjer se »validiramo OSCAL« tiho spremeni v »validiramo del OSCAL, nismo pa prepričani, kateri del«.
Mi smo želeli biti prepričani, kateri del. Zato smo svoj validator zgradili tako, kot bi presojali sistem: začeti pri virih, našteti vse in upoštevati vsako posamezno postavko.
Prva odločitev je bila ključna: avtoriteta so viri NIST, ne referenčna izvedba. Repozitorij usnistgov/OSCAL smo pripeli na commit 21403b4a… (v1.2.2), vsak bajt Metaschema natančno shranili v predpomnilnik z zgoščenimi vrednostmi SHA-256, častitljivi Java OSCAL CLI pa obravnavali kot to, kar dejansko je: primerjalnik za navzkrižno zasliševanje, ne resnico za prepisovanje. (Med drugim vgrajuje povezave za OSCAL 1.2.1: dokumente 1.2.2 lahko obdela, ne zna pa govoriti 1.2.2.)
Nato smo leksikalno popisali vsako pojavitev omejitve v pripetih virih. Ne vrst omejitev, temveč pojavitve, identificirane po datoteki in vrstici, da se dve omejitvi, ki slučajno delita ID, nikoli ne strneta v eno. Število je naneslo 348.
Za vsako pojavitev mora naša gradnja imeti natanko eno od treh sodb, kar uveljavlja generator, ki evidenco ob vsakem zagonu izračuna znova:
Neupoštevanih: nič.
Prav zadnja skupina, izključitve, je postala zanimiva.
Ko 348 omejitev preverite eno za drugo, kaj najdete. Tri naše izključitve so napake v samih virih NIST:
oscal_mapping-common_metaschema.xml v vrstici 657 omejuje zastavico, ki je opredeljena pet vrstic prej, nato pa se nanjo nič ne sklicuje. Noben dokument, ki lahko obstaja, te zastavice ne nosi. Omejitve ni mogoče izpolniti.inventory-item velja le, ko je @type enak software, hardware ali service, vendar inventory-item zastavice type sploh ne deklarira. (Njegov sosed, asset-id, je v viru sam zakomentiran.) Predikat se nikoli ne more ujemati.with-child-controls. Človek, ki bere vir, jih vidi; prevedena shema jih nikoli ne uveljavlja. Vse tri ugotovitve smo prijavili vzdrževalcem: usnistgov/OSCAL#2254, #2255, #2256.In presoja je rezala v obe smeri: naš lastni ocenjevalnik je imel napako, zaradi katere so se omejitve, usmerjene na zastavice (kot so dovoljene vrednosti action/@type), prevedle v popis, a se tiho nikoli niso sprožile. Nismo je našli po sreči: vrata zaprtja so zavrnila dokaze za ti dve pojavitvi, kar je natanko način odpovedi, ki ga je ves sistem zasnovan razkriti.
Trditev, da »referenčna izvedba nekaj spregleda«, zgolj na podlagi pregleda virov je natanko takšna nedokazana trditev, ki jo ta projekt želi odpraviti. Zato smo z Maven Central prenesli Java OSCAL CLI 3.2.0, preverili njegovo zgoščeno vrednost in oba validatorja pognali nad družino testnih primerov, katerih izhodiščni dokumenti brez napak prestanejo preverjanje na obeh straneh, tako da je vsako nestrinjanje mogoče pripisati eni vneseni spremembi.
OSCAL 1.2.2 je poleg povišanj različic spremenil natanko dve omejitvi (obe v modelu SSP). Java CLI, ki vgrajuje povezave 1.2.1, je na napačni strani vsake opazne posledice:
rel="validation" krši 1.2.2. Java: veljavno, izhodna koda 0.rel="validated-by" je po 1.2.2 v redu (omejitev je bila izbrisana). Java: neveljavno.responsible-role brez neobveznega party-uuid je po 1.2.2 v redu; NIST je predikat dodal prav zato, da bi to popravil. Java javi napako, dobesedno Key reference [null] not found.Nato primer, ki sploh ni povezan z razliko različic: katalog, katerega metapodatkovni action deklarira "type": "invented-type", kar je prepovedano v vrstici 877 metapodatkovne Metaschema tako v 1.2.2 kot v virih 1.2.1, ki jih vgrajuje Java. Java ga razglasi za veljavnega, v JSON in XML. Omejitev cilja zastavico; tiho nesprožene omejitve, usmerjene na zastavice, so natanko razred napak, ki so ga naša vrata popolnosti ujela v našem lastnem ocenjevalniku. Referenčna izvedba ima isti razred napak, a nima vrat zaprtja, ki bi ga ujela. Vzdrževalcem smo ga prijavili kot metaschema-framework/oscal-cli#279. (Razred smo preslikali mehansko: natanko 2 od 200 pojavitev dovoljenih vrednosti ciljata zastavice, edini član, ki sproži napako, pa je tisti, ki smo ga preizkusili v živo. Nepreizkušenega ostanka ni.)
In še trenutek poštenosti, ker je preizkus rezal v obe smeri: naš validator je zavrnil NIST-ov lastni katalog SP 800-53 rev5. Dvajset napak, vse ena sama pomanjkljivost: naš ocenjevalnik indeksov je manjkajoče neobvezno polje ključa obravnaval kot kršitev, kjer specifikacija Metaschema pravi, da gre za ničelni ključ. Java je datoteko sprejela; mi smo se motili; popravili smo isti dan in 800-53 se zdaj validira brez napak. Preizkus je pozneje ujel še drugo: besednjak vrst dejanj OSCAL smo še naprej uveljavljali tudi, ko je action/@system deklariral URI po meri, kar je natanko segmentacija po organizacijah, ki jo zahtevajo NIST-ove lastne opombe. Tudi to je popravljeno. Diferencialno ogrodje, ki vedno najde le napake druge strani, ni ogrodje, temveč trženje.
(Prav tako pod »obe strani«: noben razreševalnik ni semantično validiral lastnega izhoda. Javin resolve-profile bo brez pomislekov zapisal katalog, ki ga Javin lastni validate nato zavrne, in naš je počel enako, varovan s shemo, ne pa s semantiko. Naš zdaj zavrne zapis semantično neveljavnih razrešitev; Java tega še vedno ne zmore, ker zapolnitev te luknje zahteva semantično plast, ki ji zaupate.)
Druga stvar, ki manjka obstoječim orodjem: dokumenti OSCAL ne živijo sami. Rezultat ocene uvozi načrt ocene, ta uvozi SSP, ta uvozi profil, ki se razreši glede na kataloge. Dokumentacija modela je polna razmerij, ki jih noben validator posamezne datoteke ne more preveriti: »cilj te ugotovitve se mora razrešiti v izjavo v izhodišču«, »ta POA&M mora identificirati svoj sistem«.
Zato smo zgradili validacijo med dokumenti, ki ta razmerja zares razreši. Če jo prosite, naj preveri SSP, razreši uvoženo izhodišče skozi celoten cevovod razreševanja profilov (po osnutku specifikacije) vse do katalogov, izračuna izbrani nabor kontrol in vam pove:
{
"ruleId": "SSP-003.b",
"severity": "warning",
"path": "/…/implemented-requirements/1/control-id",
"message": "implemented control 'ac-99' is not supplied by the resolved import-profile 'file:///…/baseline.json'"
}
Z enim ključnim načelom zasnove: ta preverjanja razmerij so razlage dokumentirane proze in tako jih tudi obravnavamo: privzeto so izklopljena, so opozorila in ne napake, obseg razrešitve vsakega polja je pripet na izvorno vrstico, vse, kar je zgolj izpeljivo, pa je poimensko izključeno. Kjer je standard zadržan, validator ne bi smel blefirati. (Naš najljubši primer: specifikacija POA&M pravi, da je potreben uvoz SSP ali system-id: »Both may be present.« Zato opozorimo le, kadar ne obstaja nobeden. Brez izmišljenega izključujočega ali.)
Ker dokumenti živijo v brskalnikih, brezstrežniških funkcijah, CLI-jih in podatkovnih bazah, mi pa smo želeli en validator v vseh njih, ne pa stranskega procesa JVM ob vsakem. Validatorji so vnaprej prevedeni samostojni moduli Ajv: navaden generiran JavaScript, brez prevajanja shem med izvajanjem, z bajtno stabilnim izhodom. Ista koda, ki poganja naše validacijske površine, nespremenjena teče v zavihku vašega brskalnika in v našem CLI. Determinizem pa ni le operativna ugodnost: šele on sploh omogoča dokaze, pripete z zgoščeno vrednostjo.
import { createDiagnosticsOscalProcessor } from "@secani/oscal/diagnostics";
const result = createDiagnosticsOscalProcessor({ maxIssues: 50 }).validate(doc);
validate --resolve-imports --interpretive all)Celotno tehnično poročilo (model avtoritete, zaprtje popolnosti, tabela diferencialnih potrdil in kaj namenoma ne trdimo) je v dokumentaciji validatorja. Validator je v zasebnem predprodukcijskem okolju pred odprtokodno izdajo; gostovani API za validacijo že danes izpostavlja raven sheme, semantična plast pa bo sledila.
Secani povezuje obsege, dokazila, naloge in agente UI v enem skupnem delovnem prostoru.
OLIR zagotavlja vsebino preslikav in njihovo upravljanje. OSCAL zagotavlja strojno berljivo strukturo za uporabo teh preslikav pri analizi vrzeli, ponovni uporabi dokazil in potekih dela za vpliv sprememb.
OSCAL dokumente o skladnosti spremeni v strukturirane podatke: osem modelov dokumentov, trije formati in ekosistem, ki postaja standard za regulativo.
Z RFC-0024 in Consolidated Rules 2026 FedRAMP strukturirane podatke za avtorizacijo spreminja v obveznost. Roki so postopni, smer pa je nedvoumna.