Configuration audit logging

Configuration audit logs let you identify who did what, and when, in your tailnet. Configuration audit logs record actions that modify a tailnet’s configuration, including the type of action, the actor, the target resource, and the time. For changes to the tailnet policy file, the log includes a full diff of the previous and new files.

All users who have access to the admin console can view configuration audit logs in the Logs page of the admin console, and can filter these logs to find specific events.

Configuration audit logs are enabled by default for all tailnets, and are available for the most recent 90 days.

Configuration audit logging is currently in beta.

Log structure

Logs include several components:

  • Timestamp: When the event happened. This is displayed in your browser’s local time.
  • Action: What action happened. For example, approve a device, or modify the tailnet policy file.
  • Actor: Which user or process completed the action. If the action is made by a user, this value is the user’s name. The user’s email or GitHub username, as well as their name, is available in the events returned by the API. If the action is made by the Tailscale control plane, this value is the Tailscale service. For a list of actions made by the Tailscale control plane, see Service events.
  • Target: Which resource the action applied to. For example, for an action modifying a user’s role, the target is the user. For an action approving a device, the target is the device. Where the action is a tailnet-wide configuration, the target is the tailnet.
  • Diff: The old and the new values provided, if relevant. For example, if you renamed a node’s machine name, or updated a list of ACL tags, you will see both the old and new values. For ACL changes, you’ll see a full diff of the previous and updated versions, including non-substantive changes like comments. For re-authenticating a node, you’ll see the old node key expiry and the new key expiry.
A screenshot of the configuration audit log page

Enabling configuration audit logging

Configuration audit logs are always enabled for all tailnets and cannot be disabled.

Configuration audit logs are a subset of the logs that Tailscale uses to provide the service, in line with our privacy policy.

Accessing configuration audit logs

Configuration audit logs can be accessed in the Logs page of admin console or via API.

Viewing configuration audit logs in the admin console

All users who have access to the admin console can view configuration audit logs in the Logs page of the admin console, and can filter these logs to find specific events.

Logs are shown in the order that events occurred, starting with the most recent.

Filtering configuration audit logs

Events in the Logs page of the admin console can be filtered to more easily find events meeting certain criteria.

Filters can be used on time, action, and actor. Multiple filters can be applied simultaneously to find events meeting all the filtering criteria.

A screenshot of a configuration audit log filter
Time

Use the Timeframe filter to show only logs between two specified dates.

Type of action

Use the Action filter to show only logs that match the selected actions. For example, you can see all events that include an update to your tailnet policy file.

Actor

Use the Actor filter to show only logs where actions were taken by the selected users.

Accessing configuration audit logs via API

You can export configuration audit logs from the Tailscale API. You need an API key to access configuration audit logs.

The response to the logs API call is in the form of the TailnetLogsResponse struct:

type TailnetLogsResponse struct {
	Version string        `json:"version"`
	Tailnet dbx.TailnetID `json:"tailnetId"`

	Logs []Log `json:"logs"` // Ordered chronologically
}

You can use the following query parameters with the API:

  • start: Required. Start of the timeframe, in RFC3339 timestamp format, for the logs to retrieve. For example: 2022-07-20T00:00:00Z.
  • end: Required. End of the timeframe, in RFC3339 timestamp format, for the logs to retrieve. For example, 2022-07-21T00:00:00Z.

start and end times are inclusive within nanosecond resolution.

For example:

curl -u tskey-0123456789abcdef:  -X GET \
  "https://api.tailscale.com/api/v2/tailnet/{TAILNET}/logs?start=2022-07-20T00:00:00Z&end=2022-07-21T00:00:00Z"

Optionally, use json_pp to prettify the JSON output:

curl -u tskey-0123456789abcdef: -X GET \
  "https://api.tailscale.com/api/v2/tailnet/{TAILNET}/logs?start=2022-07-20T00:00:00Z&end=2022-07-21T00:00:00Z" \
  | json_pp

The output will look like:

{
   "logs" : [
      {
         "action" : "UPDATE",
         "actor" : {
            "displayName" : "Alice Architect",
            "id" : "123456CNTRL",
            "loginName" : "alice@example.com",
            "type" : "USER"
         },
         "deferredAt" : "0001-01-01T00:00:00Z",
         "eventGroupID" : "12345",
         "eventTime" : "2022-07-20T20:13:30.136022207Z",
         "new" : "2023-01-14T20:13:30.134350003Z",
         "old" : "0001-01-01T00:00:00Z",
         "origin" : "NODE",
         "target" : {
            "id" : "654321CNTRL",
            "name" : "node1.yak-bebop.ts.net",
            "property" : "KEY_EXPIRY_TIME",
            "type" : "NODE"
         },
         "type" : "CONFIG"
      },
      {
         "action" : "CREATE",
         "actor" : {
            "displayName" : "Alice Architect",
            "id" : "123456CNTRL",
            "loginName" : "alice@example.com",
            "type" : "USER"
         },
         "deferredAt" : "0001-01-01T00:00:00Z",
         "eventGroupID" : "23456",
         "eventTime" : "2022-07-20T18:40:58.838529518Z",
         "new" : {
            "capabilities" : [
               "CONTROL_API_SCOPE_ALL_READ",
               "CONTROL_API_SCOPE_ALL"
            ],
            "expires" : "2022-10-18 18:40:58.653877012 +0000 UTC"
         },
         "origin" : "ADMIN_UI",
         "target" : {
            "id" : "789123CNTRL",
            "name" : "Control API key",
            "type" : "API_KEY"
         },
         "type" : "CONFIG"
      },
      {
         "action" : "UPDATE",
         "actor" : {
            "displayName" : "Bob Builder",
            "id" : "987654CNTRL",
            "loginName" : "bob@example.com",
            "type" : "USER"
         },
         "deferredAt" : "0001-01-01T00:00:00Z",
         "eventGroupID" : "34567",
         "eventTime" : "2022-07-20T22:35:19.590021877Z",
         "new" : [
            "...",
            "...",
            "10.0.0.0/24",
            "10.0.1.0/24"
         ],
         "old" : [
            "...",
            "..."
         ],
         "origin" : "ADMIN_UI",
         "target" : {
            "id" : "876543CNTRL",
            "name" : "bob-workstation.yak-bebop.ts.net",
            "property" : "ALLOWED_IPS",
            "type" : "NODE"
         },
         "type" : "CONFIG"
      }
   ],
   "tailnetId" : "example.com",
   "version" : "1.1"
}

Currently, there is no pagination support and no maximum page size for the API. All events in the specified timeframe are returned.

When multiple events occur for a single operation, the actions have the same value for eventGroupID.

Events

Configuration audit logs include write actions that change the configuration of a tailnet, including changes that a user can make in the admin console or via API.

Any successfully completed event will create a corresponding log entry.

Events included in configuration audit logs are:

Target Action Description
Tailnet Create tailnet Tailnet was created.
Update policy file for tailnet Tailnet policy file was modified. This includes changes to tests, tagOwners, autoApprovers, and Tailscale SSH configurations.
Update max key duration for tailnet Key expiry was modified.
Update DNS configuration for tailnet DNS configuration was updated. This includes adding global or restricted nameservers (Split DNS) and changes to MagicDNS.
Enable device authorization for tailnet Device authorization was enabled.
Disable device authorization for tailnet Device authorization was disabled.
Enable MagicDNS for tailnet MagicDNS was enabled.
Disable MagicDNS for tailnet MagicDNS was disabled.
Enable Taildrop for tailnet Taildrop was enabled.
Disable Taildrop for tailnet Taildrop was disabled.
Enable services collection for tailnet Services collection was enabled.
Disable services collection for tailnet Services collection was disabled.
Enable HTTPS domain for tailnet HTTPS was enabled.
Disable HTTPS domain for tailnet HTTPS was disabled.
Update name for tailnet Tailnet name was changed.
Enable user and group provisioning for tailnet User and group provisioning was enabled.
Disable user and group provisioning for tailnet User and group provisioning was disabled.
Billing Create billing subscription for tailnet Subscription was created.
Update billing subscription for tailnet Subscription was modified. This includes changes to the selected plan and limits. Note that the log will not include diffs for subscriptions. Information on the current subscription is available on the Billing page of the admin console.
Cancel billing subscription for tailnet Subscription was canceled.
Update billing address for tailnet Billing address was modified. This includes physical address and name.
Update billing email for tailnet Billing email was modified.
Update billing payment information for tailnet Billing payment information was modified, including payment method and tax IDs.
Update billing owner for tailnet Billing owner was modified.
User Create user User joined the tailnet.
Update role for user User’s role was changed.
Suspend user User was suspended from the tailnet.
Restore user User was restored to the tailnet.
Delete user User was deleted from the tailnet.
Push user User attributes were updated for a user provisioned in Okta.
Group Push group A group was provisioned in Okta.
Node Create node Node was added. For tailnets with device authorization enabled, it may not yet be authorized.
Log in node User logged in to or re-authenticated on a node. This includes re-authentication as part of Tailscale SSH check mode.
Authorize node Node was authorized.
Update name for node Node name updated.
Enable key expiry for node Node key expiry was enabled.
Disable key expiry for node Node key expiry was disabled.
Update key expiry time for node User re-authenticated the node, extending the node key validity, or node key expiry was temporarily extended.
Expire node key Node key expired.
Update advertised routes for node Routes advertised by the node updated.
Update exit settings for node Exit node advertised by the node updated.
Update ACL tags for node Node ACL tags updated.
Log out node User logged out of node.
Delete node Node was deleted.
Admin Console Log in to admin console User logged in to the admin console.
Log out of admin console User logged out of admin console.
Invite Create invite for node share Node share invite was created by sharer tailnet. The invite target is the label entered when creating the invite.
Accept invite for node share Node share invite was accepted by sharee tailnet.
Delete invite for node share Node share invite was revoked by sharer tailnet.
Share Create node share Shared node was added to sharee’s tailnet.
Update node share Shared node was updated. This occurs when a shared node is shared with a sharee who already has the shared node.
Delete node share Shared node was deleted from sharee’s tailnet. This could be an action by either the sharer (to revoke access to the shared node) or the sharee (to remove the shared node from their tailnet).
API Failed request API call attempted with insufficient permission.
API key Create API key API key was generated.
Revoke API key API key was revoked.
API key expired API key expired.
Auth key Create API key Auth key was generated. This includes tags and if the key is reusable, ephemeral, pre-authorized.
Revoke API key Auth key was revoked.
API key expired Auth key expired.

Note that failed login attempts are not included in Tailscale events—these should be seen in your identity provider logs, not Tailscale logs.

Multiple events for a single operation

Multiple events that occur as part of the same operation are logged individually. For example, when a user is deleted, there are log entries for deleting each of their nodes and each of their API keys, as well as deleting the user themselves. When a node is added to your tailnet, there are log entries for updating the name for a node, creating a node, updating the key expiry time for a node, logging into a node, and if applicable, authorizing the node.

Operation Events
A user is deleted
  • Delete node, for each node
  • Revoke API key, for each API or auth key
  • Delete user
A node is added to the tailnet
  • Update name for node (name set from blank to node name)
  • Create node
  • Update key expiry time for node (key expiry set for current time + expiry period)
  • Log in node

Shortly afterwards, if device authorization is enabled:
  • Authorize node
A node is logged out
  • Enable key expiry for node (key expiry is enabled)
  • Update key expiry time for node (key expiry is set to the current time)
  • Log out node
A node is re-authenticated
  • Update key expiry time for node
  • Log in node
MagicDNS is enabled
  • Enable MagicDNS for tailnet
  • Update DNS configuration for telnet
MagicDNS is disabled
  • Disable MagicDNS for tailnet
  • Update DNS configuration for tailnet

Events for shared nodes

When using shared nodes, some events are logged in both the sharer and sharee tailnets. Events related to invites are only logged in the sharer tailnet, and events related to the shared node are logged in both the sharer and sharee tailnets.

Target Action Actor Logged by sharer tailnet? Logged by sharee tailnet?
Invite Create invite for node share Sharer admin
Accept invite for node share Sharee admin
Delete invite for node share Sharer admin
Share Create node share Sharee admin
Update node share Sharee admin
Delete node share Sharer admin or Sharee admin

Service events

The log includes service events, which are actions performed by the Tailscale service, not performed by users directly. Service events include:

Target Action Actor Description
Tailnet Suspend user Tailscale service: user and group provisioning User deactivated or unassigned from the Tailscale app for tailnets using user & group provisioning
Tailnet Restore user Tailscale service: user and group provisioning User reactivated or assigned the Tailscale app for tailnets using user & group provisioning
Node Delete node Tailscale service: remove ephemeral node Remove inactive ephemeral node
API key or Auth key API key expired Tailscale service: expire API key Expire key after 90 days

Events not included

Changes to a tailnet that were initiated by a request to Tailscale’s support team are currently not included. This includes:

Changes that would have been included if performed by a user, but were instead initiated by a Support request are also not included:

  • Update role for user
  • Delete user
  • Update billing customer ID for tailnet
  • Update key expiry time for node
  • Enable device authorization for tailnet
  • Disable device authorization for tailnet

Limitations

  • Logs only include actions that modify a tailnet’s configurations. Read-only actions, such as a user viewing the admin console, are not included.
  • Changes to a tailnet that were initiated by Tailscale’s support team are not currently included.
  • Logs only include changes to configuration of a tailnet. Information about connections within a tailnet (data plane audit logs), such as network flow logs, are not included.
  • Configuration audit logs are currently only available as part of the admin console, and exported via API. Configuration audit logs cannot currently be streamed.
  • There is currently no guarantee for a maximum delay between an event taking place and its inclusion in the audit logs. In practice, this occurs within seconds.
  • The period of time that logs are stored cannot be configured. Logs are stored for 90 days.
  • Logs for events that occurred on or before 2022/10/12 may be incomplete.
  • Devices with the same node key will appear in logs as the same node target.
  • When a user is suspended, the suspension of the user’s nodes, API keys, and auth keys are not logged.
  • When a user is deleted, the deletion of the user’s API keys and auth keys are not logged.

Last updated

WireGuard is a registered
trademark of Jason A. Donenfeld.

© 2022 Tailscale Inc.

Privacy & Terms