GNSS-tillit som sikkerhetstelemetri
kshana trust-telemetry gjør om tillitsstrømmen per epoke for GNSS (score 0-100, bånd, årsaker) til signaler som en drifts- eller sikkerhetssentral allerede tar inn: Prometheus-metrikker, syslog-hendelser i CEF eller LEEF for et SIEM, og eventuelt OpenTelemetry. Den leser strømmen; den endrer aldri tillitsvurderingen og sender ikke noe annet enn telemetri.
Kjør den#
# live stream on stdin -> /metrics on localhost:9464
kshana receiver-trust live <args> | kshana trust-telemetry
# replay a batch result (the score is the epoch's own for a vessel platform, absent otherwise)
kshana trust-telemetry --result session.result.json --print-metrics
kshana trust-telemetry --result session.result.json --print-syslog --format leef
# SIEM over UDP, one event per band change
kshana trust-telemetry --input stream.jsonl --syslog-udp siem.example:514 --format cef --host ops-gw1
Inndata er det levende JSON-lines-skjemaet v1.1 som er dokumentert i docs/MARITIME-TRUST.md. Leser: t_s; state (calibrating|nominal|degraded|untrusted, båndet); score (0-100 eller null); time (epokens tid som oppgitt); gate (off|passed|withheld); position (lat_deg, lon_deg, height_m eller null); årsakene er monitorene i deductions, deretter eventuelle flere i alarms; fra skjema 1,3, geometry (status, hdop, pdop, n_used) og hver fradrags class. Andre nøkler ignoreres, siden skjemaet bare vokser ved at nøkler legges til på slutten. En linje som ikke lar seg tolke, telles i kshana_trust_input_errors_total og hoppes over; skårer utenfor 0-100 avvises, ikke avkortes, slik at en formatendring blir lagt merke til. Den eneste koden som kjenner dette formatet, er src/telemetry/sample.rs.
/metrics serveres uten autentisering og bruker 127.0.0.1:9464 som standard. Å binde til en annen adresse skriver ut en advarsel; sett det bak din egen tilgangskontroll. Endepunktet håndterer én tilkobling om gangen med en leitegrense på 2 s, så en inaktiv klient kan forsinke en innhenting med opptil så lenge; det er ment for én innhenter, ikke for det åpne nettet.
Home Assistant og NTP-apparater (MQTT)#
--print-mqtt skriver ut, og --mqtt-tcp <host:port> publiserer, et JSON-tilstandsdokument og Home Assistant MQTT-oppdagelsesmeldinger. Oppdagelsen (beholdt, under homeassistant/...) lager tre entiteter: tillitsscore, tillitsbånd (med årsakene som attributter) og en untrusted-problemsensor. Tilstandsdokumentet går til <prefix>/state (standard kshana/trust/state, beholdt): state, score (null så lenge det ikke finnes noen), untrusted, t_s, time, reasons, gate og den veiledende erklæringen; posisjonen tas aldri med. Alternativer: --mqtt-prefix, --mqtt-node, --mqtt-discovery.
Utgiveren snakker MQTT 3.1.1 med QoS 0 og leser bare meglerens CONNACK. Den har ingen legitimasjon og ingen TLS, så bruk en megler på det lokale nettverket (eller et lokalt relé som legger dem til). Leveringen kjører på sin egen tråd bak en kø på 1024: en død megler gjør at meldinger forkastes, telles og rapporteres på slutten, og stanser aldri strømmen. Et NTP-apparat eller en annen forbruker som vil ha ren JSON, kan lese den samme tilstandslinjen. Ingenting skrives til en mottaker eller en klokke. Python, WebAssembly og MCP tar format = "mqtt" og returnerer de samme topic<TAB>payload-linjene (ingenting publiseres der).
Fra Python, WebAssembly og MCP#
Koderne er også tilgjengelige som kall med tekst inn og tekst ut, uten prosess, socket eller klokke: Python kshana.trust_telemetry(input, format, host="", input_kind="jsonl", expose_position=False, syslog_all=False, unix_nano=0), WebAssembly-eksporten trust_telemetry(input, format, host, input_kind, options_json) og MCP-verktøyet trust_telemetry (plugin-kommando /kshana-trust-telemetry). format er prometheus, cef, leef eller otlp; input_kind er jsonl (strømmen) eller result (et batchresultat). De returnerer den samme teksten kommandolinjen skriver ut (--print-metrics, --print-syslog), med de samme grensene: syslog-linjer har ingen tidsstempel, host er høyst 255 skrivbare ASCII-tegn uten mellomrom (avvises ellers, her og på kommandolinjen), og et svar som er større enn flatens grense (4 MiB på MCP) avvises, fordi CEF og LEEF med syslog_all skriver én hendelse per epoke. Ingenting sendes, serveres eller skrives; de kjørende eksportørene forblir en prosess på kommandolinjen.
Levering stanser aldri vurderingen#
Syslog- og OpenTelemetry-levering kjører på egne tråder. Inntakssløyfen gir dem bare en melding eller et øyeblikksbilde og venter aldri, så en død, treg eller ikke-lesende innsamler kan ikke lage mottrykk på den levende strømmen eller fryse /metrics:
- hver tilkobling og skriving har en grense på 2 s; en mislykket tilkobling droppes og kobles opp igjen ved behov, med eksponentiell tilbakeholdelse fra 1 s opptil 60 s;
- en melding som ikke kan leveres (innsamler nede, skriving fikk tidsavbrudd, køen på 1024 full) forkastes og telles i
kshana_trust_syslog_send_failures_total; varsle på raten; - OpenTelemetry-eksportøren får en kopi av registeret, så ingen lås holdes under nettverks-I/O; hvis en eksport fortsatt pågår, hoppes det nye øyeblikksbildet over (det neste har de samme kumulative summene).
Ved slutten av inndata får sendertrådene den gjenværende tiden til å bli ferdige.
Prometheus-metrikker#
| Metrikk | Type | Etiketter | Betydning |
|---|---|---|---|
kshana_build_info |
måler | version |
konstant 1 |
kshana_trust_score |
måler | siste score 0-100; mangler hvis kilden ikke gir noen | |
kshana_trust_band |
måler | band |
1 for det gjeldende båndet, 0 for de andre |
kshana_trust_gate |
måler | gate |
off, passed, withheld, unknown: 1 for den gjeldende tilstanden, 0 for de andre; mangler uten gate |
kshana_trust_position_latitude_degrees, ..._longitude_degrees, ..._height_meters |
måler | posisjon rapportert av mottakeren; bare med --expose-position (endepunktet er uautentisert, og en posisjon kan identifisere et sted eller et fartøy) |
|
kshana_trust_reason_active |
måler | reason |
1 hvis til stede ved siste epoke |
kshana_trust_epochs_total |
teller | band |
mottatte epoker |
kshana_trust_reason_epochs_total |
teller | reason |
epoker der årsaken var til stede |
kshana_trust_input_errors_total |
teller | inndatalinjer som ikke lar seg tolke | |
kshana_trust_reason_overflow_total |
teller | årsaksforekomster samlet i reason="other" (se nedenfor) |
|
kshana_trust_syslog_send_failures_total |
teller | syslog-hendelser som ikke er levert | |
kshana_trust_epoch_offset_seconds |
måler | siste epokes forskyvning fra strømstart | |
kshana_trust_last_sample_timestamp_seconds |
måler | mottakstidspunkt etter veggklokke; varsle på alderen | |
kshana_trust_geometry |
måler | status |
satellittgeometri ved siste epoke, good, degraded, unknown: 1 for den gjeldende (inndata med skjema 1,3) |
kshana_trust_geometry_degraded |
måler | 1 degraded, 0 good; mangler når geometrien er ukjent (1.3) | |
kshana_trust_geometry_signal_loss |
måler | 1 når satellitter i sikte ikke spores mens geometrien deres er god (signalet gikk tapt, ikke himmelen; geometry_degraded viser fortsatt 1), ellers 0; mangler når geometrien er ukjent eller inndataene ikke sier noe (1.3) |
|
kshana_trust_geometry_hdop, ..._pdop, ..._used_satellites |
måler | HDOP, PDOP og brukte satellitter ved siste epoke; hver mangler når ingen finnes (1.3) | |
kshana_trust_geometry_epochs_total |
teller | status |
epoker etter geometristatus (1.3) |
kshana_trust_geometry_label |
måler | label |
geometrietikett ved siste epoke, good, fair, poor, unknown: 1 for den gjeldende; skåres aldri (skåren trekker bare for poor); fra inndata som har etiketten (0,36) |
kshana_trust_geometry_vdop |
måler | VDOP ved siste epoke; mangler når ingen finnes (0.36) |
Geometrietiketten er hovedsaken. Lag graf og varsler på kshana_trust_geometry_label (OTLP kshana.geometry.label, CEF det tredje cs6-feltet, LEEF geoLabel): poor er den eneste etiketten skåren trekker for. Geometristatusen er beskrivende: degraded omfatter det informative tilfellet sky-blocked, som kan komme med god eller middels DOP, så ikke send sentralt varsel bare på kshana_trust_geometry_degraded.
Fra inndata med skjema 1,3 har kshana_trust_reason_active også en class-etikett (geometry, environment, inconsistency) på hver årsak som kom med en: fradragets klasse ved siste epoke. Geometriseriene kommer etter alle de andre, og bare når en inndataepoke har geometry (levende skjema 1,3, et resultat fra motor 0,36 eller senere), så en strøm eller et resultat fra 0,35 gjengis byte for byte som før. Etikettverdiene er faste mengder (en ukjent status leses som unknown; en ukjent klasse forkastes). Varsle på kshana_trust_reason_active{class="inconsistency"} i stedet for på båndet alene, slik at en dårlig himmel ikke utløser varsel som om det var et angrep; en geometry-klasse er en erklæring om himmelen, ikke en konklusjon om at ingen angrep fant sted (se docs/RECEIVER-TRUST.md).
Etiketten class er en del av en series identitet: når en årsaks klasse endres mellom epoker (loss-of-lock fra environment til geometry når de tapte satellittene sto lavt, eller geometry til inconsistency når oppgitt HDOP er uenig med oppgitt himmel), eksporteres den gamle serien ikke lenger og en ny starter. Spør etter reason med max by (reason) når klassen ikke spiller noen rolle, og regn med at en slik overgang ser ut som at én serie slutter og en annen begynner. Serien for skjema 1,3, etiketten class og CEF/LEEF-geometrifeltene kontrolleres av motorens egne tester og av CEF-referansene (pycef, Logstash); de eksterne Prometheus- og OTLP-referansene har ingen strøm for 1,3 ennå.
Årsaksnavn kuttes til 128 tegn, og høyst 64 ulike årsaker får sin egen serie; senere telles under reason="other" og i kshana_trust_reason_overflow_total, slik at en fiendtlig eller feilaktig inndata ikke kan skape ubegrenset etikettkardinalitet.
band er én av calibrating, nominal, degraded, untrusted, unknown. Årsaksnavn er strømmens monitornavn (kinematic, heading-course, ...; for batchresultatet cn0-drop, agc, raim).
Et eksempeldashbord finnes i deploy/grafana/kshana-gnss-trust.json (importer det og velg din Prometheus-datakilde).
Syslog: CEF og LEEF#
Hendelser sendes i en RFC 5424-konvolutt (facility local0, app kshana, meldings-id GNSSTRUST) over UDP (ett datagram hver; IPv4 eller IPv6) eller TCP, avsluttet med linjeskift som standard eller, med --syslog-octet-counting, innrammet <length> <message> som i RFC 6587. Som standard sendes én hendelse per båndendring; --syslog-all sender én per epoke. Leverandøren skrives Ashforde OU (ASCII) slik at ingen SIEM dekoder den feil.
| Begrep | Syslog-alvorlighet | CEF-alvorlighet | LEEF sev |
|---|---|---|---|
| calibrating | 6 info | 0 | 1 |
| nominal | 6 info | 1 | 1 |
| degradert | 4 warning | 5 | 5 |
| untrusted | 2 critical | 9 | 9 |
| unknown | 5 notice | 3 | 3 |
Feltkartlegging (hendelses-id er gnss-trust.<band>):
| Betydning | CEF | LEEF 2,0 (skilletegn ^) |
|---|---|---|
| kategori | cat=gnss-trust |
cat |
| sendende vert | dvchost |
devHost |
| bånd | cs1 (etikett band) |
band |
| årsaker, kommaseparert | cs2 (reasons) |
reasons |
| forrige bånd | cs3 (previousBand) |
previousBand |
| score | cfp1 (trustScore), utelatt hvis ingen |
trustScore |
| epokeforskyvning, s | cfp2 (epochOffsetSeconds) |
epochOffsetSeconds |
| etikett for logg-tid | cs4 (logTime) |
logTime |
| gate-tilstand | cs5 (gate) |
gate |
geometristatus, deretter ; og klassene til epokens fradrag, kommaseparert (for eksempel degraded;environment,geometry) (inndata med 1,3); fra inndata som har etiketten (0,36) et tredje felt, ; og etiketten, der klassefeltet da alltid er til stede (for eksempel degraded;;poor, good;;fair) |
cs6 (geometry) |
geoStatus (bare status), geoClass (klasser) og geoLabel (etikett) |
| HDOP (1.3) | cfp3 (geometryHdop) |
geoHdop |
| PDOP (1.3) | cfp4 (geometryPdop) |
geoPdop (0,36, med etiketten) |
| VDOP (0,36, med etiketten) | ikke med: de fire egendefinerte flyttallsfeltene er tatt | geoVdop |
| brukte satellitter (0,36, med etiketten) | cn1 (geometryUsedSatellites), et heltall |
geoUsed |
| signaltap: satellitter i sikte som ikke spores mens geometrien deres er god (1.3) | ikke med som felt (ingen CEF-ordboknøkkel er ledig til det): statusen leses som degraded og geometrifradragets klasse som environment i cs6 |
geoSignalLoss=1, bare mens det gjelder |
I CEF bruker geometrien bare egendefinerte ordbokfelt (ingen oppfunnede nøkler); etiketten ligger i cs6 i stedet for flexString1 fordi Logstash CEF-kodeken ikke tilordner flexString-feltene. Geometrihendelsene for 1,3, etikettilfellene inkludert, er en del av CEF-raden som er VALIDATED: begge referanseparserne leser dem tilbake som skrevet (tests/cef_reference.rs, endringene 4 og 5, hver registrert før noen av parserne ble kjørt på tilfellene sine). Feltene for etikett, VDOP og antall satellitter legges til etter alle tidligere felt og serier, og bare for inndata som har etiketten, så en inndata uten en gjengis nøyaktig som før.
Tomme felt utelates (ingen cs2= uten årsaker). Vertsnavnet kuttes til 255 tegn. CEF-hodeverdier escaper \ og |; utvidelsesverdier escaper \, = og linjeskift. I LEEF-verdier erstattes ^ og linjeskift med mellomrom.
OpenTelemetry (av som standard)#
Bygg med --features otlp og oppgi --otlp http://host:4318/v1/metrics. Eksportøren poster OTLP/HTTP JSON (kshana.trust.score, kshana.trust.band, kshana.trust.epochs, kshana.trust.reason.epochs, og for inndata med skjema 1,3 kshana.geometry.status, kshana.geometry.degraded, kshana.geometry.signal_loss, kshana.geometry.hdop, kshana.geometry.pdop, kshana.geometry.used_satellites og, fra inndata som har etiketten (0,36), kshana.geometry.label (attributt label) og kshana.geometry.vdop; de kumulative summene har startTimeUnixNano) hver --otlp-every epoke (standard 10) og ved slutten av inndata. Den legger ikke til noen avhengighet og har ingen TLS: send til en innsamler på samme vert eller et pålitelig segment, som sender videre over TLS. Endepunkter med https:// avvises.