Skip to main content
Version: v0.1.0-rc.1

📄 Machine config: TSA

The pki.tsa block of the machine config: the node's RFC 3161 time-stamp authority. The how-to is Serve RFC 3161 timestamps.

The TSA is off unless the block is present, and it follows the same switching rules as ACME and EST: Switching a protocol on or off. enabled: false switches it off and keeps the settings, an ApplyConfig that leaves the block out keeps what the node has, and every change takes effect at the next reboot.

A Root never serves a TSA

A config that switches pki.tsa on at a Root is refused, and nothing is stored. A block with enabled: false is accepted and never served.

pki:
tsa:
http_port: 318
policy_oid: "1.3.6.1.4.1.32473.1.1"
accuracy_ms: 1000
rate_limit:
requests_per_minute: 60
burst: 60
allowed_networks: [10.20.0.0/16, "2001:db8:20::/48", 192.0.2.44]
certificate:
validity_days: 365
rotation_overlap_days: 30
max_sync_age_seconds: 3600
max_drift_ppm: 100
max_clock_error_ms: 1000
FieldTypeDefaultMeaning
enabledbooltrue when the block is presentfalse switches the TSA off and keeps the other settings.
http_portint318 (0 means the default)TCP port of the plain-HTTP listener. Requests are POSTed to its root path.
policy_oidstringnone, requiredThe TSA policy every token names, in dotted form, under your own enterprise number: Get a TSA policy OID. At least two decimal arcs without leading zeros, a first arc of 0, 1 or 2, and a second arc below 40 when the first is 0 or 1. A request for another policy is refused with unacceptedPolicy.
accuracy_msint1000 (0 means the default)The accuracy every token claims, in milliseconds either side of its time. At most 60000. It is also the ceiling for max_clock_error_ms: see The clock grace window.
rate_limit.requests_per_minuteint60 (0 means the default)The steady rate one client may sustain. A client is its IPv4 address, or its IPv6 /64. The limit cannot be switched off.
rate_limit.burstintrequests_per_minuteHow many requests a client may make at once before the rate applies. Over the limit a client gets HTTP 429 with Retry-After.
allowed_networkslistempty: anyoneIPv4 or IPv6 CIDR prefixes, or bare addresses for one host. Anyone else gets HTTP 403 before the request is read.
certificate.validity_daysint365 (0 means the default)Lifetime of the TSA certificate, at most 365, and never past the CA certificate's own expiry.
certificate.rotation_overlap_daysint30 (0 means the default)How long before the TSA certificate expires the node issues its successor and signs with it. Must be shorter than validity_days.
max_sync_age_secondsint3600 (0 means the default)How long after the last good time sync the TSA keeps stamping while later polls fail. At most 86400.
max_drift_ppmint100 (0 means the default)The clock drift rate, in parts per million, assumed since the last good sync when estimating the clock error. At most 500, the NTP frequency tolerance.
max_clock_error_msintaccuracy_ms (0 means the default)The largest estimated clock error the TSA accepts, in milliseconds. Never larger than accuracy_ms.

Errors you may see from cryptosctl config apply:

Message starts withCause
config: pki.tsa.policy_oid: requiredThe block is enabled without a policy OID.
config: pki.tsa.policy_oid: "..."The OID breaks one of the rules above.
config: pki.tsa: must not be enabled on a root nodeThe node is a Root.
config: pki.tsa.accuracy_msMore than 60000.
config: pki.tsa.max_sync_age_secondsMore than 86400.
config: pki.tsa.max_drift_ppmMore than 500.
config: pki.tsa.max_clock_error_msLarger than the effective accuracy_ms (1000 when accuracy_ms is 0).
config: pki.tsa.allowed_networks[N]Entry N is not an address or a CIDR prefix.
config: pki.tsa.certificate.validity_daysMore than 365.
config: pki.tsa.certificate.rotation_overlap_daysThe overlap is not shorter than the validity. With the default overlap of 30 days, that includes any validity_days of 30 or less.

🕑 The clock grace window​

A timestamp is only a claim about the time, so the TSA fails closed on its clock. It trusts the clock for a grace window after the last good time sync, so one unanswered NTP poll does not stop it. Every request is refused with timeNotAvailable while any of these limits is hit:

LimitRefused whenDefault
no_good_syncNo time sync has succeeded this boot. A node with no time source never syncs, so its TSA refuses every request.
adjustment_refusedThe servers answered the latest round but the clock was not adjusted: they disagreed, or a step was refused. The next good sync clears it.
max_sync_ageThe last good sync is older than max_sync_age_seconds.1 hour
max_clock_errorThe estimated clock error is larger than max_clock_error_ms.accuracy_ms (1 second)

The estimated clock error is the offset measured at the last good sync plus max_drift_ppm parts per million of the time since. At the defaults, a sync that measured 20 ms gives 20 ms + 360 ms = 380 ms an hour later, inside the 1 second bound; a sync that measured 700 ms crosses it after 50 minutes.

The accuracy rule

max_clock_error_ms may not be larger than accuracy_ms, and config apply refuses a config that sets it so. A token must never claim more accuracy than the clock is trusted to have. Set it lower to stop stamping before the clock reaches the claimed accuracy.

The refusal's status string names the limit and its value, for example:

the TSA time source is not available: max_sync_age=1h0m0s exceeded (1h12m3s)
the TSA time source is not available: max_clock_error=1s exceeded (1.02s)
the TSA time source is not available: no_good_sync

The full reason, with the server and the time-sync error, is in the node log. NodeStatus.time_sync.adjustment_refused shows a refused round, and cryptosctl status shows the Clock: line.

🔌 API​

In the API's MachineConfig the block is Pki.tsa (Tsa, TsaRateLimit, TsaCertificateSettings). NodeService.ListTsaCertificates returns every TSA certificate the node has signed with, and NodeStatus.protocols reports SERVICE_PROTOCOL_TSA.