feat(pusher): add validated onion delegation for v2 pings
- Load WELIST_PING_DELEGATION_FILE into a typed OnionDelegation - Send the certificate only with v2 pings for onion hosts - Validate the onion host, expiry and delegated key against BAL_SERVER_URL and SSL_KEY_PATH at startup; disable delegation with a warning on any mismatch - Stop sending unsigned info/base_fee/version with v1 pings so v1 remains liveness-only - Document v1/v2 metadata handling and onion delegation implications - Add contrib/make_onion_delegation.py to issue certificates offline, with Ed25519 key validation and clean CLI error handling
This commit is contained in:
@@ -168,13 +168,32 @@ scheme is selected with `WELIST_PING_SIG_VERSION`:
|
||||
`_welist-key.<host>` TXT record (`v=we1; alg=ed25519; key=<base64 SPKI DER>`)
|
||||
or from a v3 `.onion` address. No HTTP callback to `/.pub_key.pem` is made.
|
||||
|
||||
For `.onion` URLs the pusher includes a `delegation` object when
|
||||
`WELIST_PING_DELEGATION_FILE` is set. The onion identity key signs that
|
||||
certificate offline; `SSL_KEY_PATH` is then the dedicated ping key, and the
|
||||
service verifies the certificate before checking the ping signature. The
|
||||
pusher validates the certificate at startup: `onion` must match the configured
|
||||
host, `valid_until` must be in the future, and `key` must match `SSL_KEY_PATH`.
|
||||
If the file is missing or malformed, or any check fails, the pusher logs a
|
||||
warning and sends no `delegation` object. It then signs with `SSL_KEY_PATH`
|
||||
directly, which works only when that key is the onion identity key.
|
||||
|
||||
The `url` is trimmed of surrounding whitespace and trailing slashes, and the
|
||||
`chain` is lowercase, matching the service-side canonicalization.
|
||||
|
||||
See [`10_dnssec_key_publishing.md`](10_dnssec_key_publishing.md) for the
|
||||
operator guide on publishing `_welist-key.<host>` and on onion delegation.
|
||||
|
||||
### Version 1 (legacy)
|
||||
|
||||
1. Concatenates `url + chain + height + median_time + last_block_hash`.
|
||||
2. Signs that string with the Ed25519 private key.
|
||||
3. POSTs the fields plus the base64 signature to `{WELIST_SERVER_URL}/ping`.
|
||||
3. POSTs those five fields plus the base64 signature to
|
||||
`{WELIST_SERVER_URL}/ping`. No `info`, `base_fee` or `version` is sent.
|
||||
4. The `welist` server verifies the signature with the public key served at
|
||||
`GET /.pub_key.pem`; this scheme only refreshes `last_update`.
|
||||
`GET /.pub_key.pem`.
|
||||
5. The v1 signature authenticates only liveness. The service refreshes
|
||||
`last_update` for an accepted ping but does not persist executor metadata.
|
||||
Because any metadata added to a v1 ping would be outside the signature, use
|
||||
v2 when `info`, `base_fee` and `version` must be published and
|
||||
authenticated.
|
||||
|
||||
Reference in New Issue
Block a user