Audit log

Last updated

Every organisation has an audit log: each change its people make, on the panel or with an API token, and each write Hetscale makes to its Hetzner projects. Within a minute every entry is sealed into the organisation’s SHA-256 hash chain, and an export lets you check that chain yourself.

What is recorded?

  • Every change a member makes to a node group, on the panel or with an API token, named after the member or the token’s name.
  • Every write Hetscale makes to your Hetzner project, with Hetzner’s action ids.
  • Outside the groups:
    • invitations sent, accepted, declined and revoked; members removed or leaving; role changes and the transfer of ownership;
    • API tokens issued and revoked;
    • integrations added, changed, removed and resumed, and their signing secret rotated;
    • projects connected, their token replaced or erased, archived and restored;
    • the organisation’s profile;
    • policy templates created, changed and deleted.
  • Hetscale’s own changes to the organisation, such as opening it for writes or moving it to Observe only when a plan lapses.

What is not recorded?

Reads, sign-ins, and the policy’s decisions that wrote nothing to Hetzner. Those stay on the group’s timeline.

Who reads it, and where?

The owner and the admins, on Activity → Audit log. It filters by who acted (Made by), by Member and by the Kind of change. Each entry’s View shows the details, Hetzner’s action ids, its place in the chain and the exact JSON that was hashed.

How far back does it go?

Starter shows 30 days, Growth 60 days, Pro 90 days, and Team a year. Every plan keeps a year, so a change of plan shows the whole year at once.

How is an entry sealed?

Within a minute each new entry gets the next sequence number n. Its hash is SHA-256 of the previous entry’s hash, a line feed, n, a line feed and the entry’s JSON, with its keys sorted and its times in UTC to the microsecond. The first entry follows 64 zeros.

The database refuses any other change to an entry, and any delete of an entry younger than a year. Every chain is checked daily.

How do I export it?

On Team:

  • Export JSON Lines gives every sealed entry of the year, one per line: {"hash": …, "payload": …, "prev_hash": …, "seq": …}, the payload being the exact JSON that was hashed.
  • Export CSV gives the same entries to read, in the columns seq, occurred_at, actor_kind, actor, action, subject_kind, subject_id, subject_name, details, hetzner_action_ids and hash. A cell that would start a spreadsheet formula starts with an apostrophe.

An entry sealed in the next minute is in the next export.

How do I check an export?

Run this Python script with the JSON Lines file as its argument:

import hashlib, json, sys

previous = None
for line in open(sys.argv[1], encoding='utf-8'):
    row = json.loads(line)
    if row['seq'] == 1 and row['prev_hash'] != '0' * 64:
        sys.exit('the first entry does not follow 64 zeros')
    if previous is not None and row['prev_hash'] != previous:
        sys.exit(f"the chain breaks at entry {row['seq']}")
    digest = hashlib.sha256(f"{row['prev_hash']}\n{row['seq']}\n{row['payload']}".encode('utf-8')).hexdigest()
    if digest != row['hash']:
        sys.exit(f"entry {row['seq']} was changed")
    previous = row['hash']
print('the chain holds')

It prints “the chain holds”, or names the first entry that does not.

What does it prove?

An entry changed or removed after it was sealed breaks the chain. Keep an export: a later one must contain it unchanged and extend it. The chain does not stop someone with full rights over the database from rewriting all of it; the export you kept is what shows that. The log is tamper-evident from your export on.

What happens after a year?

Entries older than a year leave every day. The oldest one kept anchors the chain with its own previous hash, which is then not 64 zeros.

What happens when an organisation is deleted?

When the owner asks us to delete the organisation, its audit log is deleted with the rest of its data, within the 30 days the privacy policy names. A member who leaves the organisation stays named in its audit log until those entries are a year old: the log is the organisation’s record of what was done.

See what Hetscale would have done with your real data — connect read-only, get your report in minutes.

Connect read-only