Audit log

Comentario keeps a record of who did what, when, and to which object

The audit log is a record of administrative and security-relevant actions taken on a Comentario instance: who signed in, who changed a domain’s settings, who moderated a comment, who banned a user, and so on.

Every entry answers the same questions: what was done, by whom, to which object, when, and how it ended. It’s meant to help you investigate an incident (“who deleted that page?”), keep an eye on your account’s security (“was that sign-in me?”), and hold several administrators of a domain accountable to each other.

The audit log is append-only: entries can’t be edited or deleted through the Administration UI or the API. They’re removed automatically once they’ve reached the retention period, and the personal data of a user is scrubbed from them when their account is deleted.

What gets recorded

Comentario records actions that change something of consequence, as well as authentication activity. Routine content activity — posting, voting on, or editing one’s own comment — isn’t recorded: there are webhooks for reacting to that.

Sign-in and account security

ActionRecorded when
auth.loginA user signs in, to the Administration UI or on a website with comments. Details tell the authentication method (local, sso, or federated, with the provider).
auth.loginFailedA sign-in attempt fails or is refused. Details tell the reason, for instance unknownUser or wrongPassword (along with the number of failed attempts so far).
auth.logoutA user signs out.
auth.forgotPwdSomeone requests a password reset, whether or not an account with that email exists.
user.createA new account is registered, locally or via a federated identity provider or SSO.
user.confirmA user confirms their email address.
user.lockAn account gets locked after too many failed sign-in attempts (see Max. failed login attempts).
user.password.changeA user changes their password.
user.password.resetA user sets a new password using a reset link.
user.email.changeA user changes their email address.

User management

ActionRecorded when
user.updateA superuser edits a user’s properties, including granting or revoking the superuser privilege.
user.attrsA superuser edits a user’s attributes.
user.ban, user.unbanA superuser bans or unbans a user, optionally deleting their comments.
user.unlockA superuser unlocks a locked account.
user.sessions.expireA superuser expires all sessions of a user, signing them out everywhere.
user.deleteA user is deleted by a superuser, or deletes their own account.

Domains

ActionRecorded when
domain.create, domain.update, domain.deleteA domain is created, its settings are saved, or it’s deleted.
domain.readonlyA domain is frozen or unfrozen.
domain.ssoSecret.newA new SSO secret is generated.
domain.export, domain.importDomain data is exported or imported. An import entry also tells how many users, pages, and comments were added, and the error if it stopped halfway.
domain.clearAll pages and comments of a domain are removed.
domain.purgeDeleted comments are purged; the entry tells how many.
domain.attrsA superuser edits a domain’s attributes.
domain.user.update, domain.user.removeA domain user’s role or notification settings are changed, or the user is removed from the domain.
page.update, page.move, page.deleteA domain page’s properties are edited, its comments are moved to another page, or it’s deleted.
webhook.create, webhook.update, webhook.deleteA webhook is registered, changed, or removed. A token embedded in the webhook URL is never recorded.
webhook.secret.newA new webhook signing secret is generated.

Moderation

ActionRecorded when
comment.approve, comment.reject, comment.pendingA moderator approves or rejects a comment, or returns it to the moderation queue.
comment.edit, comment.deleteA moderator edits or deletes someone else’s comment. An author editing or deleting their own comment isn’t moderation, and isn’t recorded.
comment.sticky, comment.unstickyA comment is made sticky or non-sticky.

System configuration

ActionRecorded when
config.dynamic.updateA superuser changes the dynamic configuration; the entry lists every changed setting with its old and new value.
config.dynamic.resetA superuser resets the dynamic configuration to defaults.

Plugins may record actions of their own, in addition to the above.

Anatomy of an entry

Each entry shows a short, translated message (such as Banned user or Moved 12 comments to /blog/new-post) along with the time it was recorded. Clicking the message expands the entry’s details.

  • Actor — who performed the action:
    • a user, shown with their name and email as they were at the time;
    • Anonymous — someone not signed in, for example a person registering a new account or failing to sign in;
    • System — Comentario itself, for example when the --superuser command-line option turns a user into a superuser on startup.
  • Object — what the action was done to, with its type (User, Domain, Page, Comment, Webhook, or Configuration) and a label as it was at the time: an email, a host, a page path.
  • Outcome — entries for actions that went through carry no badge. The others are marked:
    • Denied — the action was refused by policy: the account is banned or locked, signups are disabled, and so on;
    • Failed — the action didn’t succeed for another reason: a wrong password, an unknown email, an identity provider error.
  • Changes — for edits, a table of the fields that actually changed, with their old and new values. A secret, such as a password, is listed as changed, not recorded: the entry tells it was changed, but never contains the value.
  • Action — the action’s technical name, such as user.ban, which you can use to filter the log.
  • Other details — anything else the action is about, for example the number of comments deleted along with a banned user, or the host of the website a user signed in on.
  • IP — the IP address of the request. Unless the server runs with the --log.full-ips option, only the first two bytes are stored (172.16.x.x).

Because an entry is a snapshot, it stays intact, and readable, after the domain, page, or comment it names has been deleted or renamed; a deleted user is the exception, see below. While an object still exists, its name in the entry is a link to it; once it’s gone, the name is shown as plain text.

Correlation ID

All entries recorded while handling a single request share a correlation ID, which superusers see in the entry details. For example, the failed sign-in attempt that locks an account out records both the attempt and the lockout, under the same correlation ID.

  • To see every entry of the same request, click the Related entries link next to the correlation ID in the entry details. This opens the log filtered by that correlation ID alone.
  • Every API response carries the correlation ID in the X-Comentario-Correlation-Id header. To find out what a particular request recorded, copy the header’s value from the browser’s developer tools, and filter the log by it.

Who sees what

Not every entry is meant for everyone. Each entry is recorded for an audience, which decides who can read it:

WhoWhat they seeWhere
SuperusersEvery entry of the instance, with all details, including the IP, the audience, and the correlation ID.Audit log in the sidebar; Activity in a domain’s and in a user’s properties
Domain ownersEntries about their domain: its settings, pages, comment moderation, domain users, webhooks, import and export. The IP address of the requester is never shown to them.Activity in the domain’s properties
Every userEntries about their own account: sign-ins, sign-outs, failed attempts to sign in, password and email changes.Security section of their Profile

A few consequences worth noting:

  • Moderators don’t have access to the log. Their moderation actions are visible to the domain owners, which is what makes the log useful for overseeing a moderation team.
  • Domain owners don’t see sign-ins of their domain’s users, nor the actions superusers take on user accounts (bans, deletions, edits): those concern the account, which spans all domains, not a particular domain.
  • Users don’t see actions a superuser took on their account, such as editing it. They do see all security-related activity on it, including failed sign-in attempts, so they can spot someone trying to break in.
  • Entries of a domain remain after the domain is deleted, but only superusers can see them then.
  • Failed attempts to sign in, or to reset the password, with an email that matches no account are visible to superusers only.

Using the log

Instance-wide log (superusers)

The Audit log item in the sidebar opens the log of the entire instance, newest entries first. Scroll down and click Load more to see older ones.

Filtering the log

Click Filter to narrow the log down by one or more criteria. Each criterion you add is shown as a tag above the list; click its to remove it, or Clear filter to remove them all.

  • Source — Comentario itself, or a specific plugin.
  • Action — an exact action name, such as auth.login, or a prefix ending with a dot, such as user., to match a whole group of actions.
  • Correlation ID — the entries recorded within a single request.
  • Object type — users, domains, pages, comments, webhooks, or configuration.
  • Outcome — succeeded, denied, or failed.
  • Authentication — the authentication method of sign-ins and sign-ups: local, Single Sign-On, or federated.
  • From, To — a date range, inclusive, in your local time.

A few recipes:

  • All failed sign-in attempts this week: Action auth.loginFailed, From set to Monday.
  • Who’s been changing the system configuration: Object type Configuration.
  • Everything denied: Outcome Denied, which reveals banned or locked users trying to sign in, and federated or SSO signups attempted while signups are disabled.

Activity of a user

A user’s properties page shows the latest entries about that user under Activity about user, with two buttons opening the full log:

  • About user — actions done to the user: sign-ins, edits, bans, failed attempts to sign in to their account.
  • By user — actions done by the user: their moderation, domain management, configuration changes, and so on.

Domain activity (owners and superusers)

The domain’s properties page shows its five most recent entries in the Activity section; Show all opens the whole list.

Your own account

The Security section of your Profile lists recent sign-ins and changes to your account, including failed sign-in attempts. If you see a sign-in you don’t recognise, change your password right away, and consider asking a superuser to expire all your sessions.

Bursts of failed attempts

Anybody can try signing in with a wrong password, or request password resets, over and over. To keep a flood of such requests — whether a brute-force attack or a misbehaving script — from bloating the database, failed sign-ins and password reset requests are throttled: within each 15-minute window, only the first 10 of them per IP address, and the first 100 in total, are recorded individually.

The ones beyond that aren’t lost: they’re counted, and every 15 minutes Comentario records a single summary entry per action and outcome, such as 37 more failed sign-in attempts not recorded individually, on behalf of System. Summaries are visible to superusers only.

The cap applies per Comentario process: if you run several instances, each records up to that many entries.

Successful sign-ins, and the locking of an account after too many wrong passwords, are always recorded individually.

Retention

Entries are kept for 365 days, after which a background job removes them. The job runs every 12 hours.

Plugin entries

Experimental
Plugin support in Comentario is experimental and unstable. It isn’t covered by any compatibility promise, and may change or be removed in any release without notice, along with the way plugins record audit log entries.

If your instance runs plugins, they may record entries of their own. These appear alongside Comentario’s with a badge showing the plugin ID, and can be selected with the Source filter.

A plugin provides the messages for its entries. If the plugin is later removed, its entries remain, but are shown by their action name instead of a message.

Reliability

With PostgreSQL, an action and its audit entry are saved together, in one transaction: if the entry can’t be recorded, the action is rolled back and the request fails. Thus, every successful action has an entry.

With SQLite, which Comentario runs without transactions, the audit log is best-effort: an action may succeed without its entry if recording it fails, in which case Comentario logs an error. See Requirements for details.

Privacy considerations

The audit log contains personal data: names, email addresses, and (masked) IP addresses of the users involved. As an instance owner, keep in mind that:

  • Entries outlive the accounts they mention, but not the personal data: when a user is deleted, their name, email, and IP addresses are removed from the entries, which remain until they reach the retention period.
  • The audit log isn’t included in a domain export, so it doesn’t travel with the domain’s data.
  • IP addresses are stored masked unless you pass --log.full-ips. Storing full addresses makes it easier to trace an attack, but they’re more sensitive personal data.

Deleted users

When a user account is deleted, whether by the user themselves or by a superuser, Comentario removes the user’s personal data from the audit log, in the same go:

  • their name and email, from the entries they made, and from those about them, the deletion’s own entry included;
  • the name and email from attempts made with their email address before the account existed, such as failed sign-ins;
  • the old and new values of their email, name, website, remarks, and custom names in domains from recorded changes, which then show as changed, not recorded;
  • the IP addresses of the requests they made.

The entries themselves stay, as does the ID of the account, so the log still tells what the account did and what was done to it, and which entries are about the same account; the Administration UI shows it as Deleted user. The IP of somebody else acting on the account, such as the superuser who deleted it, is kept.

Entries recorded by plugins are scrubbed of the user’s name and IP as well, but not their details, which only the plugin knows.

If you need to keep track of who an abusive user was, ban them instead of deleting: a banned account, and every entry about it, stays intact.

Disabling the audit log

Running Comentario with the --no-audit command-line option (or NO_AUDIT=true in the environment) stops recording entries, by Comentario and by plugins alike.

Entries recorded before are kept, can still be viewed, and are removed once they reach the retention period, just as they would be otherwise.

See also