Skip to content

Feature/federation v1 - #343

Open
fwromano wants to merge 14 commits into
brian7704:masterfrom
fwromano:feature/federation-v1
Open

Feature/federation v1#343
fwromano wants to merge 14 commits into
brian7704:masterfrom
fwromano:feature/federation-v1

Conversation

@fwromano

Copy link
Copy Markdown
Contributor

No description provided.

fwromano added 10 commits July 17, 2026 12:52
…truststore

- Vendor the federation protobuf definitions (fig.proto, binarypayload.proto)
  from the TAK Product Center's public TAK Server source (GPLv3), minus the
  gRPC service which federation v1 does not use. Field numbers unchanged, so
  the wire format is identical to official TAK Server federation.
- Frame codec for v1's length-prefixed FederatedEvent stream, with
  partial-frame buffering and a max-frame-size guard.
- CoT XML <-> FederatedEvent mapper mirroring TAK Server's ProtoBufHelper:
  track/status/precisionlocation/image extraction, opaque detail passthrough,
  and <marti><dest> to ptpCallsigns/ptpUids/missionNames mapping.
- Federation truststore: peer CAs live in a separate folder from the EUD CA
  so a federate's server can connect while its client certs cannot, with
  helpers for CA management and peer identity (SHA-256 cert fingerprint).
- FederationConnection bridges one TLS link to RabbitMQ: outbound consumes
  the firehose exchange, filters by the federate's outbound groups against
  the sender's group memberships, and streams frames; inbound converts
  received events to CoT and publishes them to cot_parser tagged with the
  federate's inbound groups. Contact announcements track local EUD presence.
- Loop prevention is structural: only EUD handlers publish to firehose and
  federated traffic enters via cot_parser, so federated events are never
  re-federated (point-to-point semantics, like TAK Server without a hub).
- FederationManager runs the v1 listener (mutual TLS against the federation
  truststore, auto-registering inbound federates with no groups) and dials
  enabled outbound federates with reconnect and certificate pinning on first
  connect.
- New federation_server console script following the eud_handler/cot_parser
  process model. Disabled by default (OTS_ENABLE_FEDERATION).
- Federation model + migration: peer address/port, direction, enable flag,
  reconnect interval, pinned certificate fingerprint, and inbound/outbound
  group lists (empty lists exchange nothing, matching TAK Server's default).
- /api/federation CRUD and /api/federation/ca truststore management,
  administrator-only.
An optional 'groups' list in the message envelope routes the event to those
group channels instead of the sender's memberships or __ANON__. Used by the
federation server to deliver inbound federated traffic into a federate's
configured inbound groups; any other non-user publisher can use it the same
way.
Unit tests for the frame codec, CoT mapper, and truststore, plus an
integration test federating two in-process engines over real mutually
authenticated TLS: SA and contacts flow both ways, outbound group filtering
blocks unshared groups, federates without groups exchange nothing, and
servers with untrusted CAs are rejected during the handshake.
The previous parent 6a7929c07690 already had a descendant
(00442761c803), producing two alembic heads and breaking
'flask db upgrade'. Caught by live two-server validation.
…ve validation

Validated end-to-end between two live OTS stacks (real eud_handler /
cot_parser / federation_server over RabbitMQ + Postgres, federated over
mutual TLS). Fixes surfaced there:

- Register a lightweight EUD row for each federated sender (from
  ContactListEntry announcements and from GeoEvents), so inbound federated
  CoT satisfies the cot->eud foreign key and remote units appear as
  federated contacts - mirrors TAK Server behavior. Chat is attributed to
  its sending EUD via sender_identity() rather than the GeoChat message uid.
- Carry the sender callsign across the wire in GeoEvent.screenName.
- Import all model modules in the federation_server process so SQLAlchemy
  can resolve cross-model relationships (Group <-> groups_missions).
- Use the update() construct instead of Query.update() wrapped in
  session.execute() (which raised 'Executable SQL construct expected, got 1'
  and dropped every federation connection before any event flowed).
Adds the official FederatedChannel gRPC service (v2, port 9001) alongside v1.
Both carry the same FederatedEvent and share the CoT mapper, group filtering,
loop guard, federated-EUD registration, and truststore - only the transport
differs, so the shared logic was factored into engine.build_outbound_event /
apply_inbound_event / contact_announcements and is used by both.

- fig.proto: restore the FederatedChannel service definition; generate grpc
  stubs. OTS serves the SA subset (getIdentity, HealthCheck,
  ClientEventStream, ServerEventStream); ROL and group-mapping RPCs are
  declared for wire compatibility but not served.
- grpc_engine.py: FederationServicer (inbound listener) and GrpcClient
  (outbound dialer), mutual TLS against the federation truststore, peer
  identified by client certificate.
- FederationManager runs both the v1 and v2 listeners; outbound dials route
  by the federate's protocol_version.
- New config: OTS_FEDERATION_ENABLE_V2, OTS_FEDERATION_V2_PORT,
  OTS_FEDERATION_V2_AUTHORITY. grpcio added as a dependency.
In-process gRPC integration tests over mutual TLS (getIdentity/HealthCheck +
inbound SA routing + federated-EUD registration, and untrusted-CA rejection).
Skipped under gevent monkey-patching (grpc deadlocks on patched sockets; the
production federation_server does not monkey-patch) - covered live by
fed_live_test.py --v2. README and FEDERATION.md updated for v2.
A scriptable front end over the Federation model and the federation
truststore: list/status (with --json), add/remove/enable/disable federates,
and ca import/export/list. Lets an operator manage federation without
hand-writing REST calls, and gives the HeartBeat 'heartbeat fed' wrapper and
dashboard a stable JSON interface (status --json).
@fwromano
fwromano marked this pull request as draft July 21, 2026 17:35
@fwromano
fwromano marked this pull request as ready for review July 21, 2026 21:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant