Tradução automática, não revista por um falante nativo. O inglês é a referência.

Confiança do receptor e marítimoEditar no GitHubFonte: docs/TRUST-TELEMETRY.md

Confiança no GNSS como telemetria de segurança

kshana trust-telemetry transforma o fluxo de confiança no GNSS por época (pontuação 0-100, faixa, motivos) em sinais que um centro de operações ou de segurança já ingere: métricas Prometheus, eventos syslog em CEF ou LEEF para um SIEM e, opcionalmente, OpenTelemetry. Ele lê o fluxo; nunca altera a avaliação de confiança e não transmite nada além de telemetria.

Um resultado de confiança em três formatos de exportação, a partir de execuções reais do motor v0.40.0 (`kshana trust-telemetry`) sobre examples/maritime-trust: exposição em texto Prometheus (a pontuação de confiança mais recente é 5,9 e a faixa não confiável é a que está ativada) e as últimas mensagens CEF e LEEF. O comando não publica nada a menos que receba um destino, não guarda credenciais e não transmite nenhum sinal de rádio. Software de caráter consultivo, não um equipamento de navegação homologado (IEC 61108, IEC 61162): o operador continua responsável pela navegação da embarcação.Um resultado de confiança em três formatos de exportação, a partir de execuções reais do motor v0.40.0 (`kshana trust-telemetry`) sobre examples/maritime-trust: exposição em texto Prometheus (a pontuação de confiança mais recente é 5,9 e a faixa não confiável é a que está ativada) e as últimas mensagens CEF e LEEF. O comando não publica nada a menos que receba um destino, não guarda credenciais e não transmite nenhum sinal de rádio. Software de caráter consultivo, não um equipamento de navegação homologado (IEC 61108, IEC 61162): o operador continua responsável pela navegação da embarcação.

Execute#

# 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

A entrada é o esquema JSON-lines ao vivo v1.1 documentado em docs/MARITIME-TRUST.md. Lê: t_s; state (calibrating|nominal|degraded|untrusted, a faixa); score (0-100 ou nulo); time (o tempo da época como declarado); gate (off|passed|withheld); position (lat_deg, lon_deg, height_m, ou nulo); os motivos são os monitores em deductions, depois quaisquer outros em alarms; a partir do esquema 1,3, geometry (status, hdop, pdop, n_used) e o class de cada dedução. Outras chaves são ignoradas, já que o esquema só cresce por chaves acrescentadas. Uma linha que não é interpretada é contada em kshana_trust_input_errors_total e descartada; pontuações fora de 0-100 são rejeitadas, não truncadas, para que uma mudança de formato seja notada. O único código que conhece esse formato é src/telemetry/sample.rs.

/metrics é servido sem autenticação e tem por padrão 127.0.0.1:9464. Vincular a outro endereço imprime um aviso; coloque-o atrás do seu próprio controle de acesso. O endpoint atende uma conexão por vez com limite de leitura de 2 s, de modo que um cliente ocioso pode atrasar uma coleta em até esse tempo; destina-se a um único coletor, não à rede aberta.

Home Assistant e dispositivos NTP (MQTT)#

--print-mqtt imprime, e --mqtt-tcp <host:port> publica, um documento de estado JSON e mensagens de descoberta MQTT do Home Assistant. A descoberta (retida, sob homeassistant/...) cria três entidades: pontuação de confiança, faixa de confiança (com os motivos como atributos) e um sensor de problema untrusted. O documento de estado vai para <prefix>/state (padrão kshana/trust/state, retido): state, score (nulo enquanto não há), untrusted, t_s, time, reasons, gate e a declaração consultiva; a posição nunca é incluída. Opções: --mqtt-prefix, --mqtt-node, --mqtt-discovery.

O publicador fala MQTT 3.1.1 com QoS 0 e lê apenas o CONNACK do broker. Não tem credenciais nem TLS, portanto use um broker na rede local (ou um retransmissor local que as acrescente). A entrega roda em sua própria thread, atrás de uma fila de 1024: um broker morto descarta mensagens, contadas e informadas no final, e nunca trava o fluxo. Um dispositivo NTP ou qualquer outro consumidor que queira JSON simples pode ler a mesma linha de estado. Nada é escrito em um receptor ou em um relógio. Python, WebAssembly e MCP recebem format = "mqtt" e devolvem as mesmas linhas topic<TAB>payload (nada é publicado ali).

Pelo Python, WebAssembly e MCP#

Os codificadores também estão disponíveis como chamadas de texto de entrada e texto de saída, sem processo, soquete ou relógio: Python kshana.trust_telemetry(input, format, host="", input_kind="jsonl", expose_position=False, syslog_all=False, unix_nano=0), a exportação WebAssembly trust_telemetry(input, format, host, input_kind, options_json) e a ferramenta MCP trust_telemetry (comando de plugin /kshana-trust-telemetry). format é prometheus, cef, leef ou otlp; input_kind é jsonl (o fluxo) ou result (um resultado em lote). Devolvem o mesmo texto que a linha de comando imprime (--print-metrics, --print-syslog), com os mesmos limites: as linhas syslog não trazem marca de tempo, host tem no máximo 255 caracteres ASCII imprimíveis sem espaços (recusado caso contrário, aqui e na linha de comando), e uma resposta maior que o limite da superfície (4 MiB no MCP) é recusada, porque CEF e LEEF com syslog_all escrevem um evento por época. Nada é enviado, servido ou gravado; os exportadores em execução continuam sendo um processo na linha de comando.

A entrega nunca trava a avaliação#

A entrega por syslog e OpenTelemetry roda em threads próprias. O laço de ingestão apenas lhes entrega uma mensagem ou um instantâneo e nunca espera, de modo que um coletor morto, lento ou que não lê não consegue pressionar o fluxo ao vivo nem congelar /metrics:

  • toda conexão e toda escrita têm um limite de 2 s; uma conexão que falha é descartada e refeita de forma preguiçosa, com recuo exponencial de 1 s até 60 s;
  • uma mensagem que não pode ser entregue (coletor fora do ar, escrita expirou, fila de 1024 cheia) é descartada e contada em kshana_trust_syslog_send_failures_total; alerte sobre sua taxa;
  • o exportador OpenTelemetry recebe uma cópia do registro, de modo que nenhum bloqueio é mantido durante a E/S de rede; se uma exportação ainda estiver em andamento, o novo instantâneo é ignorado (o seguinte traz os mesmos totais cumulativos).

No fim da entrada, as threads de envio recebem seus limites de tempo restantes para terminar.

Métricas Prometheus#

Métrica Tipo Rótulos Significado
kshana_build_info gauge version constante 1
kshana_trust_score gauge pontuação mais recente 0-100; ausente se a fonte não fornece
kshana_trust_band gauge band 1 para a faixa atual, 0 para as demais
kshana_trust_gate gauge gate off, passed, withheld, unknown: 1 para o estado atual, 0 para os demais; ausente sem uma comporta (gate)
kshana_trust_position_latitude_degrees, ..._longitude_degrees, ..._height_meters gauge posição informada pelo receptor; somente com --expose-position (o endpoint não tem autenticação e uma posição pode identificar um local ou embarcação)
kshana_trust_reason_active gauge reason 1 se presente na época mais recente
kshana_trust_epochs_total contador band épocas recebidas
kshana_trust_reason_epochs_total contador reason épocas em que o motivo estava presente
kshana_trust_input_errors_total contador linhas de entrada não interpretáveis
kshana_trust_reason_overflow_total contador ocorrências de motivo reunidas em reason="other" (veja abaixo)
kshana_trust_syslog_send_failures_total contador eventos syslog não entregues
kshana_trust_epoch_offset_seconds gauge deslocamento da época mais recente em relação ao início do fluxo
kshana_trust_last_sample_timestamp_seconds gauge hora de recebimento no relógio de parede; alerte sobre sua idade
kshana_trust_geometry gauge status geometria dos satélites na época mais recente, good, degraded, unknown: 1 para a atual (entradas do esquema 1,3)
kshana_trust_geometry_degraded gauge 1 degradada, 0 boa; ausente quando a geometria é desconhecida (1.3)
kshana_trust_geometry_signal_loss gauge 1 quando satélites à vista não são rastreados embora sua geometria seja boa (o sinal foi perdido, não o céu; geometry_degraded ainda indica 1), senão 0; ausente quando a geometria é desconhecida ou a entrada não informa (1.3)
kshana_trust_geometry_hdop, ..._pdop, ..._used_satellites gauge HDOP, PDOP e satélites usados na época mais recente; cada um ausente quando não há (1.3)
kshana_trust_geometry_epochs_total contador status épocas por status de geometria (1.3)
kshana_trust_geometry_label gauge label rótulo de geometria na época mais recente, good, fair, poor, unknown: 1 para o atual; nunca pontuado (a pontuação deduz apenas por poor); a partir de entradas que trazem o rótulo (0,36)
kshana_trust_geometry_vdop gauge VDOP na época mais recente; ausente quando não há (0.36)

O rótulo de geometria é o destaque. Faça gráficos e alertas sobre kshana_trust_geometry_label (OTLP kshana.geometry.label, CEF o terceiro campo cs6, LEEF geoLabel): poor é o único rótulo pelo qual a pontuação deduz. O status de geometria é descritivo: degraded inclui o caso informativo sky-blocked, que pode vir com DOP bom ou razoável, portanto não acione plantão só por kshana_trust_geometry_degraded.

A partir de entradas do esquema 1,3, kshana_trust_reason_active também traz um rótulo class (geometry, environment, inconsistency) em cada motivo que veio com um: a classe da dedução na época mais recente. As séries de geometria vêm depois de todas as outras e somente quando uma época de entrada traz geometry (esquema ao vivo 1,3, um resultado do mecanismo 0,36 ou posterior), de modo que um fluxo ou resultado 0,35 é renderizado byte a byte como antes. Os valores dos rótulos são conjuntos fixos (um status desconhecido aparece como unknown; uma classe desconhecida é descartada). Alerte sobre kshana_trust_reason_active{class="inconsistency"} e não apenas sobre a faixa, para que um céu ruim não dispare plantão como se fosse um ataque; uma classe geometry é uma afirmação sobre o céu, não uma constatação de que nenhum ataque ocorreu (veja docs/RECEIVER-TRUST.md).

O rótulo class faz parte da identidade de uma série: quando a classe de um motivo muda entre épocas (loss-of-lock de environment para geometry quando os satélites perdidos eram baixos, ou geometry para inconsistency quando o HDOP declarado discorda do céu declarado), a série antiga deixa de ser exportada e uma nova começa. Consulte por reason com max by (reason) quando a classe não importa, e espere que essa troca pareça uma série terminando e outra começando. As séries do esquema 1,3, o rótulo class e os campos de geometria de CEF/LEEF são verificados pelos testes do próprio mecanismo e pelas referências independentes de CEF (pycef, Logstash); as referências independentes externas de Prometheus e OTLP ainda não têm fluxo 1,3.

Os nomes de motivo são cortados em 128 caracteres, e no máximo 64 motivos distintos recebem série própria; os posteriores são contados em reason="other" e em kshana_trust_reason_overflow_total, de modo que uma entrada hostil ou com defeito não consegue criar cardinalidade ilimitada de rótulos.

band é um entre calibrating, nominal, degraded, untrusted, unknown. Os nomes de motivo são os nomes dos monitores do fluxo (kinematic, heading-course, ...; para o resultado em lote, cn0-drop, agc, raim).

Um painel de exemplo está em deploy/grafana/kshana-gnss-trust.json (importe-o e escolha sua fonte de dados Prometheus).

Syslog: CEF and LEEF#

Os eventos são enviados em um envelope RFC 5424 (facility local0, app kshana, id de mensagem GNSSTRUST) sobre UDP (um datagrama cada; IPv4 ou IPv6) ou TCP, terminados em nova linha por padrão ou, com --syslog-octet-counting, com enquadramento <length> <message> como na RFC 6587. Por padrão um evento é enviado a cada mudança de faixa; --syslog-all envia um por época. O fornecedor é escrito Ashforde OU (ASCII) para que nenhum SIEM o decodifique errado.

Conceito Severidade do syslog Severidade do CEF LEEF sev
calibrating 6 info 0 1
nominal 6 info 1 1
degraded 4 warning 5 5
untrusted 2 critical 9 9
unknown 5 notice 3 3

Mapeamento de campos (o id do evento é gnss-trust.<band>):

Significado CEF LEEF 2,0 (delimitador ^)
categoria cat=gnss-trust cat
host de envio dvchost devHost
faixa cs1 (rótulo band) band
motivos, separados por vírgula cs2 (reasons) reasons
faixa anterior cs3 (previousBand) previousBand
pontuação cfp1 (trustScore), omitido se não houver trustScore
deslocamento da época, s cfp2 (epochOffsetSeconds) epochOffsetSeconds
rótulo de tempo do registro cs4 (logTime) logTime
estado da comporta (gate) cs5 (gate) gate
status de geometria, depois ; e as classes das deduções da época, separadas por vírgula (por exemplo degraded;environment,geometry) (entradas 1,3); a partir de entradas que trazem o rótulo (0,36), um terceiro campo, ; e o rótulo, com o campo de classes então sempre presente (por exemplo degraded;;poor, good;;fair) cs6 (geometry) geoStatus (somente status), geoClass (classes) e geoLabel (rótulo)
HDOP (1.3) cfp3 (geometryHdop) geoHdop
PDOP (1.3) cfp4 (geometryPdop) geoPdop (0,36, com o rótulo)
VDOP (0,36, com o rótulo) não transportado: os quatro campos personalizados de ponto flutuante já estão ocupados geoVdop
satélites usados (0,36, com o rótulo) cn1 (geometryUsedSatellites), um inteiro geoUsed
perda de sinal: satélites à vista não rastreados enquanto sua geometria é boa (1.3) não transportado como campo (nenhuma chave do dicionário CEF está livre para isso): o status aparece como degraded e a classe da dedução de geometria environment em cs6 geoSignalLoss=1, somente enquanto vale

Em CEF, a geometria usa apenas campos personalizados do dicionário (sem chaves inventadas); o rótulo viaja em cs6 em vez de flexString1 porque o codec CEF do Logstash não mapeia os campos flexString. Os eventos de geometria 1,3, inclusive os casos de rótulo, fazem parte da linha CEF VALIDATED: ambos os analisadores usados como referência independente os leem de volta como foram escritos (tests/cef_reference.rs, emendas 4 e 5, cada uma registrada antes de qualquer analisador ser executado em seus casos). Os campos de rótulo, VDOP e contagem de satélites são acrescentados após todo campo e série anteriores, e somente para entradas que trazem o rótulo, de modo que uma entrada sem rótulo é renderizada exatamente como antes.

Campos vazios são omitidos (sem cs2= quando não há motivos). O nome do host é cortado em 255 caracteres. Os valores de cabeçalho CEF escapam \ e |; os valores de extensão escapam \, = e quebras de linha. Nos valores LEEF, ^ e quebras de linha são substituídos por espaços.

OpenTelemetry (desativado por padrão)#

Compile com --features otlp e passe --otlp http://host:4318/v1/metrics. O exportador envia por POST JSON OTLP/HTTP (kshana.trust.score, kshana.trust.band, kshana.trust.epochs, kshana.trust.reason.epochs, e para entradas do esquema 1,3 kshana.geometry.status, kshana.geometry.degraded, kshana.geometry.signal_loss, kshana.geometry.hdop, kshana.geometry.pdop, kshana.geometry.used_satellites e, a partir de entradas que trazem o rótulo (0,36), kshana.geometry.label (atributo label) e kshana.geometry.vdop; as somas cumulativas trazem startTimeUnixNano) a cada --otlp-every épocas (padrão 10) e no fim da entrada. Não acrescenta dependência e não tem TLS: envie a um coletor no mesmo host ou em um segmento confiável, que repassa adiante por TLS. Endpoints https:// são recusados.