P0 regression — production zara-server must expose opt-in authenticated CURVE/ZAP listener for Android #173 #355

Closed
opened 2026-09-08 02:03:38 +00:00 by nsaspy · 0 comments
Owner

Parent: #127 / #152
Blocks: #173 end-to-end Android authentication
Regression against completed contract: #130

Finding

While implementing Android #173 authentication in PR #322, the production daemon path on current master da515c80a2ba18e889f62dc8f1816c8c95249f43 was re-audited.

zara/security_gateway.py contains the tested SecureZaraZmqGateway / CURVE+ZAP implementation, but zara/server.py production construction still:

  • validates only ipc:// endpoints in _validate_ipc_endpoint() and rejects TCP with TCP and non-IPC endpoints require authentication from issue #130;
  • constructs ordinary ZaraZmqGateway in ZaraServer._build_default_gateway();
  • exposes no production CLI/config path for long-term daemon CURVE keys, a persistent enrolled SecurityRegistry, or an opt-in authenticated TCP listener;
  • still describes auth as future work in its module/parser text.

That means Android can generate/store a real CURVE device credential and pin the daemon key, but cannot authenticate to the shipped zara-server process without a test/custom gateway factory. That does not satisfy #130's accepted safe-listener contract or #173's end-to-end acceptance.

Required behavior

TDD/RAGE recovery should wire the already-existing security primitives into production without weakening local IPC:

  • keep owner-private local IPC as the safe default;
  • add an explicit opt-in authenticated TCP listener/config path;
  • load/generate a long-term daemon CURVE keypair from owner-only state;
  • load a durable enrolled-key registry with principal/device/capability bindings;
  • construct SecureZaraZmqGateway for TCP, never ordinary ZaraZmqGateway;
  • expose safe operator enrollment/revoke/list commands or an equivalent owner-local management path;
  • publish the server public key for out-of-band Android pinning without exposing the secret;
  • fail closed on missing/insecure key files, unknown/revoked clients, malformed registry state, or unauthenticated wildcard bind;
  • revocation must take effect without daemon restart where the existing live registry contract supports it;
  • no private CURVE key or client secret in logs/diagnostics.

Tests

  • production zara-server secure TCP start with exact configured server key;
  • ordinary TCP start without CURVE/ZAP configuration rejected;
  • enrolled Android-compatible/JeroMQ CURVE client -> ZARA/1 hello.ok;
  • unknown/revoked client denied;
  • wrong server pin fails;
  • restart persists server identity and enrollment registry;
  • owner-private file permissions and symlink rejection;
  • local IPC default remains unchanged;
  • exact-head Android #173 interoperability fixture after PR #322 auth foundation.

Acceptance

A stock zara-server invocation/configuration can opt into a secure TCP listener using the already-shipped CURVE/ZAP security boundary, and an enrolled Android #173 client can authenticate and complete hello without custom test-only construction.

Parent: #127 / #152 Blocks: #173 end-to-end Android authentication Regression against completed contract: #130 ## Finding While implementing Android #173 authentication in PR #322, the production daemon path on current master `da515c80a2ba18e889f62dc8f1816c8c95249f43` was re-audited. `zara/security_gateway.py` contains the tested `SecureZaraZmqGateway` / CURVE+ZAP implementation, but `zara/server.py` production construction still: - validates only `ipc://` endpoints in `_validate_ipc_endpoint()` and rejects TCP with `TCP and non-IPC endpoints require authentication from issue #130`; - constructs ordinary `ZaraZmqGateway` in `ZaraServer._build_default_gateway()`; - exposes no production CLI/config path for long-term daemon CURVE keys, a persistent enrolled `SecurityRegistry`, or an opt-in authenticated TCP listener; - still describes auth as future work in its module/parser text. That means Android can generate/store a real CURVE device credential and pin the daemon key, but cannot authenticate to the shipped `zara-server` process without a test/custom gateway factory. That does not satisfy #130's accepted safe-listener contract or #173's end-to-end acceptance. ## Required behavior TDD/RAGE recovery should wire the already-existing security primitives into production without weakening local IPC: - keep owner-private local IPC as the safe default; - add an explicit opt-in authenticated TCP listener/config path; - load/generate a long-term daemon CURVE keypair from owner-only state; - load a durable enrolled-key registry with principal/device/capability bindings; - construct `SecureZaraZmqGateway` for TCP, never ordinary `ZaraZmqGateway`; - expose safe operator enrollment/revoke/list commands or an equivalent owner-local management path; - publish the server public key for out-of-band Android pinning without exposing the secret; - fail closed on missing/insecure key files, unknown/revoked clients, malformed registry state, or unauthenticated wildcard bind; - revocation must take effect without daemon restart where the existing live registry contract supports it; - no private CURVE key or client secret in logs/diagnostics. ## Tests - production `zara-server` secure TCP start with exact configured server key; - ordinary TCP start without CURVE/ZAP configuration rejected; - enrolled Android-compatible/JeroMQ CURVE client -> ZARA/1 `hello.ok`; - unknown/revoked client denied; - wrong server pin fails; - restart persists server identity and enrollment registry; - owner-private file permissions and symlink rejection; - local IPC default remains unchanged; - exact-head Android #173 interoperability fixture after PR #322 auth foundation. ## Acceptance A stock `zara-server` invocation/configuration can opt into a secure TCP listener using the already-shipped CURVE/ZAP security boundary, and an enrolled Android #173 client can authenticate and complete `hello` without custom test-only construction.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
nsaspy/zara#355
No description provided.