Document TAK authentication flows

This commit is contained in:
Valmo Trindade
2026-08-07 14:06:49 -03:00
parent d35ccd58e1
commit 6dee1987bb
+188
View File
@@ -0,0 +1,188 @@
# TAK authentication flows
This document describes the authentication and transport flows implemented by the ArmaTAK Rust extension. It is development documentation, not end-user documentation.
## Security model
ArmaTAK currently exposes three TCP connection modes:
| Mode | ArmaTAK entry point | Authentication | Transport protection | Intended use |
| --- | --- | --- | --- | --- |
| Plain TCP | `tcp_socket.start` | None | None | Local development or explicitly trusted isolated networks only |
| Manual mTLS | `tcp_socket.start_mtls` | Client X.509 certificate | TLS with server certificate validation | Production-compatible secure connection |
| Credential enrollment followed by mTLS | `tcp_socket.start_enroll_mtls` | HTTP Basic credentials during enrollment, then client X.509 certificate | Enrollment HTTPS currently skips certificate validation; the resulting TAK stream uses validated mTLS | Transitional/bootstrap flow; do not treat the enrollment phase as secure until server verification is enabled |
The official TAK Server example enables a TLS input on port `8089`. Its plaintext TCP/streaming examples are anonymous and are shown on ports `8087` and `8088`. ArmaTAK must not infer security from a port number; the selected connection mode controls the client-side security properties.
## Insecure flow: plain TCP
The plain flow is deliberately simple:
```text
Arma/SQF
|
| tcp_socket.start("host:port")
v
ConnectionConfig::Plain
|
v
TCP connect
|
| unencrypted CoT bytes
v
TAK Server plaintext/anonymous input
```
`ConnectionConfig::Plain` resolves the supplied address and opens a normal `TcpStream`. No TLS handshake occurs, there is no server identity verification, and no client identity is established by ArmaTAK.
Consequences:
- CoT payloads can be observed or modified by an on-path attacker.
- ArmaTAK cannot prove that it connected to the intended TAK Server.
- The server cannot authenticate ArmaTAK by certificate.
- Plain TCP must never be the production default.
The official TAK Server `CoreConfig.example.xml` keeps anonymous TCP inputs commented out and enables the TLS input instead. Use plain TCP only when a developer intentionally configures a corresponding non-TLS server input.
## Secure flow: manual mTLS
The manual mTLS flow uses pre-provisioned certificate material:
```text
Arma/SQF
|
| tcp_socket.start_mtls(
| address,
| server_name,
| ca_cert_path,
| client_cert_path,
| client_key_path
| )
v
ConnectionConfig::Mtls
|
+--> load trusted CA certificate(s)
+--> load client certificate chain
+--> load client private key
|
v
rustls client configuration
|
+--> validate server certificate chain
+--> validate TLS server name
+--> present client certificate
v
Authenticated mTLS TAK stream
```
The CA file is loaded into a dedicated `rustls::RootCertStore`; the client certificate and private key are used for client authentication. When `server_name` is empty, ArmaTAK derives a name from the target address. A non-empty `server_name` should be preferred when DNS and certificate names are known.
This is the preferred production flow when certificate provisioning is handled outside ArmaTAK.
## Enrollment flow: credentials to client certificate
TAK enrollment converts a username/password bootstrap credential into a short- or medium-lived client certificate, then reconnects using mTLS.
### Protocol contract
ArmaTAK follows the contract visible in the official TAK Server and ATAK implementations:
1. `GET https://HOST:ENROLL_PORT/Marti/api/tls/config`
2. Authenticate the request with HTTP Basic credentials.
3. Read `serverPort` and `enrollPath` from the TAK certificate configuration. If the fields are absent, ArmaTAK currently falls back to `8089` and `/Marti/api/tls/signClient/v2`.
4. Generate a local RSA key pair and PKCS#10 CSR. The private key never needs to be sent to the server.
5. `POST https://HOST:ENROLL_PORT{enrollPath}?clientUid=CLIENT_UID`
6. Authenticate the signing request with HTTP Basic credentials, send the CSR as `application/pkcs10`, and request JSON.
7. Parse `signedCert` and `ca0` from the enrollment response.
8. Build an in-memory client identity from the returned certificate plus the locally generated private key.
9. Connect to `HOST:serverPort` with mTLS and validate the TAK streaming server against the returned CA.
The official TAK Server exposes `/tls/config`, `/tls/signClient`, and `/tls/signClient/v2`. The v2 endpoint can return JSON containing `signedCert` plus `ca0`, `ca1`, and additional CA-chain entries. The current ArmaTAK implementation consumes `signedCert` and `ca0`.
### Current ArmaTAK enrollment security caveat
`enrollment_http_client()` currently uses `danger_accept_invalid_certs(true)`. Therefore the HTTPS bootstrap does **not** authenticate the enrollment server certificate.
That means the current enrollment phase is vulnerable to an active man-in-the-middle attacker who can impersonate the HTTPS enrollment endpoint and receive the submitted Basic credentials. The private key remains local, but the username/password bootstrap secret is still exposed to the impersonating endpoint.
The connection established *after* enrollment is mTLS and uses the returned CA, but that does not retroactively secure the bootstrap exchange. Consequently:
- `start_enroll_mtls` is a transitional flow, not the preferred production-secure flow in its current form.
- `start_mtls` with a trusted CA and pre-provisioned client certificate is the secure production path today.
- A future secure enrollment implementation must validate the HTTPS server with a trusted CA, certificate pin, or equivalent authenticated trust bootstrap.
- An explicit insecure/development enrollment switch is preferable to silently disabling verification.
The official ATAK enrollment manager exposes a `verifyHost` choice and records whether host verification is on or off. ArmaTAK should converge on the same explicit distinction.
## Target secure enrollment design
The intended production enrollment flow is:
```text
username/password
|
v
HTTPS enrollment endpoint
(server certificate MUST validate)
|
+--> GET /Marti/api/tls/config
+--> generate local private key + CSR
+--> POST configured signClient endpoint
v
signed client certificate + trusted CA
|
v
mTLS TAK streaming connection
|
+--> server authenticated by CA/name
+--> client authenticated by certificate
v
CoT traffic
```
The development-only insecure variant should be explicit:
```text
username/password
|
v
HTTPS enrollment endpoint
(certificate verification explicitly disabled)
|
v
WARNING / development-only path
```
Do not silently fall back from verified enrollment to unverified enrollment after a certificate validation failure.
## Secret-handling requirements
- Never include passwords, private keys, certificate payloads, or Authorization headers in logs.
- `ConnectionConfig::describe()` may include the username and client UID for diagnostics, but it must never include the password.
- Keep generated private keys in memory unless a future feature explicitly requires persistence.
- Do not commit development certificates or credentials to the repository.
- Treat enrollment credentials as bootstrap secrets and rotate/revoke them according to the TAK Server deployment policy.
## Test contract
Unit tests should lock down the protocol-level behavior that does not require a live TAK Server:
- official endpoint paths and default mTLS port;
- trimming and construction of enrollment URLs;
- parsing TAK enrollment configuration with explicit values and fallback defaults;
- PEM normalization;
- absence of passwords from diagnostic descriptions;
- TLS server-name derivation and PEM parsing where deterministic;
- CoT and MAVLink pure serialization logic.
Live certificate signing, TLS handshake behavior, socket reconnect behavior, mDNS, video processes, and Arma callback behavior belong in integration/E2E tests because they depend on operating-system or external-server state.
## Upstream references
The tests and protocol assumptions in this repository are based on these upstream implementations:
- TAK Server, `CertManagerApi.java`: <https://github.com/TAK-Product-Center/Server/blob/5187abd46d827d37cfc5708805eced197a837e49/src/takserver-core/takserver-war/src/main/java/com/bbn/tak/tls/CertManagerApi.java>
- TAK Server, `CoreConfig.example.xml`: <https://github.com/TAK-Product-Center/Server/blob/5187abd46d827d37cfc5708805eced197a837e49/src/takserver-core/example/CoreConfig.example.xml>
- ATAK/CommonCommo, `enrollmentmanager.cpp`: <https://github.com/TAK-Product-Center/atak-civ/blob/9f6893dd657feacc35ec5de03dad721c2e44170e/commoncommo/core/impl/enrollmentmanager.cpp>
Pinning the source revisions in this document keeps the development contract reproducible. When the upstream protocol changes, update both the implementation/tests and these references together.