github fabriziosalmi/certmate v2.45.1
v2.45.1 (random tokens are no longer refused for repeating by chance)

3 hours ago

v2.45.1 (random tokens are no longer refused for repeating by chance)

A patch release for two things found after 2.45.0. The check on API_BEARER_TOKEN refused tokens that the documentation tells you to generate, which stops the service from starting, and the deploy history recorded a failed target batch as a success. The API contract stays at 2.34.


Read this before upgrading

The token rules changed; one direction can matter

Almost every change makes the check accept more: the tokens that openssl rand -hex and a UUID v4 make are no longer refused for repeating, or for having few distinct characters, by chance (see below; a separate rule, left as it was, can still refuse a random token by chance, about 1 in 12,000 for 64 hex characters). One change is a tightening. The repetition check used to refuse a token in which some 3-character window occurs three times, and it now refuses one in which too few of the 3-character windows are different. A token that repeats a long part of itself, such as a 16-character unit written twice, passed before and is refused now, and a refused API_BEARER_TOKEN stops the service from starting.

That should not describe a token made by a generator. To be sure about yours before upgrading, with the new image and without putting the token on the command line (the variable is passed through, not typed):

docker run --rm -e API_BEARER_TOKEN --entrypoint python fabriziosalmi/certmate:2.45.1 \
  -c "import os; from modules.core.utils import validate_api_token as v; ok, why = v(os.environ['API_BEARER_TOKEN']); print('ok' if ok else why)"

It prints ok, or the reason. If it prints a reason, set a new token (openssl rand -hex 32) before pulling the new image.


Fixed

  • A token made the way the documentation says was refused at startup, and the service did not come up. Measured on 100,000 samples of each generator, before (20,000 for the UUID): openssl rand -hex 32 was refused 0.19% of the time (a 3-character window turned up three times by chance), openssl rand -hex 16, the shortest token the length floor allows, 1.7% (fewer than 12 distinct characters, by chance: exactly 1.70% for 32 random hex characters), and a UUID v4 0.2%. The repetition check now measures how few windows differ (a random token never fell below 82.6% different in 200,000 samples of each generator; a repeated unit is under 60%), and the floor of distinct characters is 8 instead of 12 (3.6e-8 for the same 32 hex characters). Tokens from openssl rand -base64, token_urlsafe and the other documented generators were never refused, and still are not.
    • Not changed: the list of weak patterns (12345, qwerty, password...). It exists to refuse a value copied out of the documentation, and a random token contains 12345 by chance about once in 12,000 (8 in 100,000 for 64 hex characters). That residue remains.
  • A deploy-target batch that failed was recorded as a success. The record that closes a batch of target deliveries said success whatever the targets did, so a failed delivery was followed by a green batch beside its own red record, and an exception while delivering was closed as a success as well. The batch is now a success only if every target succeeded, counting a target refused up front (a keyed target on a certificate issued from a CSR), and an exception leaves it a failure.

How it was checked

  • The same tokens, the two versions. One token for each rule that refused it before (a 32-character hex token with 11 distinct characters, and a 64-character one with a repeated window). With the published 2.45.0 image, the log says API_BEARER_TOKEN is set but not usable and nothing answers on /health. With the build of this release, the service starts healthy, the token authenticates (200), and the same token with a character added is refused (401).
  • Tests. 19 for the token check: 20,000 random tokens per documented generator from a fixed seed (the same on every run) with no structural refusal; the tokens the rules are for still refused; a margin test that the threshold sits at least 0.05 from both groups; and a check that each generator the test names is, whole, in the file that tells users to run it. Seven deliberate breakages were each caught by the intended test: five of the validator (the old rule back, the floor back at 12, the threshold too high, too low, and the check removed) and two of the check on the generators (a changed cut stage and a changed tr stage in the documented pipeline). 5 for the batch record, with 4 deliberate breakages each caught.

Don't miss a new certmate release

NewReleases is sending notifications on new releases.