Get started
Login
© 2024

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.

You can export logs for long-term storage and/or for security analysis, threat detection, and incident investigation. You can also stream logs to a security information and event management (SIEM) system.

For changes to the tailnet policy file, the log includes a full diff of the previous and new files.

Configuration audit logs are available for all plans.

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.

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 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 access token with the logs:read scope 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.

This example assumes you have set up the following variables to use for your API call:

  • $ACCESS_TOKEN: An API access token to use when calling the Tailscale API. You can create an API access token in the Keys page of the admin console.
  • $TAILNET_ID: The organization name for the tailnet whose logs are being retrieved. You can view your organization name in the General settings page of the admin console.
  • $START: The start of the timeframe for the logs to retrieve.
  • $END: The end of the timeframe for the logs to retrieve.
export ACCESS_TOKEN=tskey-api-k123456CNTRL-0123456789abcdef
export TAILNET_ID=example.com
export START=2022-07-20T00:00:00Z
export END=2022-07-21T00:00:00Z
curl -u  $ACCESS_TOKEN:  -X GET \
  "https://api.tailscale.com/api/v2/tailnet/{$TAILNET_ID}/logging/configuration?start={$START}&end={$END}"

Optionally, use json_pp to prettify the JSON output:

curl -u  $ACCESS_TOKEN: -X GET \
  "https://api.tailscale.com/api/v2/tailnet/{$TAILNET_ID}/logging/configuration?start={$START}&end={$END}" \
  | 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.

Reverting ACLs from audit logs

This option is not available if you are using GitOps for Tailscale ACLs.

You need to be an Owner, Admin, or IT admin of a tailnet in order to revert a tailnet policy file from audit logs.

You can revert your tailnet policy file from a previous date and time.

  1. Open the Configuration logs page of the admin console.

  2. Locate and expand the log entry containing the policy file change you want to revert to, then select Revert to previous version. In the confirmation dialog, select Revert.

    A screenshot of the tailnet policy file revert option in the logs
  3. Open the Access controls page of the admin console and verify the policy file was reverted with the expected changes.

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:

TargetActionDescription
TailnetCreate tailnetTailnet was created.
Update policy file for tailnetTailnet policy file was modified. This includes changes to tests, tagOwners, autoApprovers, and Tailscale SSH configurations.
Update max key duration for tailnetKey expiry was modified.
Update DNS configuration for tailnetDNS configuration was updated. This includes adding global or restricted nameservers (Split DNS) and changes to MagicDNS.
Enable device approval for tailnetDevice approval was enabled.
Disable device approval for tailnetDevice approval was disabled.
Enable user approval for tailnetUser approval was enabled.
Disable user approval for tailnetUser approval was disabled.
User joined external tailnetA user in your tailnet joined another tailnet.
User left external tailnetA user in your tailnet left another tailnet.
Enable MagicDNS for tailnetMagicDNS was enabled.
Disable MagicDNS for tailnetMagicDNS was disabled.
Enable Mullvad VPN for tailnetMullvad Exit Nodes were enabled.
Disable Mullvad VPN for tailnetMullvad Exit Nodes were disabled.
Enable Taildrop for tailnetTaildrop was enabled.
Disable Taildrop for tailnetTaildrop was disabled.
Enable services collection for tailnetServices collection was enabled.
Disable services collection for tailnetServices collection was disabled.
Enable HTTPS domain for tailnetHTTPS was enabled.
Disable HTTPS domain for tailnetHTTPS was disabled.
Update name for tailnetTailnet name was changed.
Enable user and group provisioning for tailnetUser and group provisioning was enabled.
Disable user and group provisioning for tailnetUser and group provisioning was disabled.
Update account email for tailnetAccount email was updated.
Verify account email for tailnetAccount email was verified.
Update configuration email for tailnetConfiguration email was updated.
Verify configuration email for tailnetConfiguration email was verified.
Update security email for tailnetSecurity email was updated.
Verify security email for tailnetSecurity email was verified.
Join waitlist for featureA waitlist for an invite only feature was joined.
Accept invite for featureAn invitation to an invite only feature was accepted.
Create logstream endpoint for tailnetA log streaming endpoint was created.
Update logstream endpoint for tailnetA log streaming endpoint destination was updated.
Delete logstream endpoint for tailnetA log streaming endpoint was deleted.
Enable network flow logging for tailnetNetwork flow logs were enabled.
Disable network flow logging for tailnetNetwork flow logs were disabled.
Enable tailnet lockTailnet lock was enabled.
Disable tailnet lockTailnet lock was disabled.
Sign node key for tailnet lockA node's key was signed by a trusted tailnet lock key.
Add trusted key to tailnet lockA trusted key was added to tailnet lock.
Remove trusted key from tailnet lockA trusted key was removed from tailnet lock.
Update tailnet lock trusted keyA trusted tailnet lock key was updated.
Create webhook endpointA webhook was created.
Delete webhook endpointA webhook was deleted.
Update secret for webhook endpointThe secret for a webhook was updated.
Update subscribed events for webhook endpointThe set of subscribed events for a webhook was updated.
Enable posture identity collectionCollection of device posture identifiers (for example, serial numbers) was enabled.
Disable posture identity collectionCollection of device posture identifiers was disabled.
Create posture integrationA new device posture integration was added.
Update posture integrationA device posture integration was updated.
Remove posture integrationA device posture integration was removed.
BillingCreate billing subscription for tailnetSubscription was created.
Update billing subscription for tailnetSubscription 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 tailnetSubscription was canceled.
Update billing address for tailnetBilling address was modified. This includes physical address and name.
Update billing email for tailnetBilling email was modified.
Update billing payment information for tailnetBilling payment information was modified, including payment method and tax IDs.
UserCreate userUser joined the tailnet.
Invite user to join tailnetUser is either sent or resent an invite to join a tailnet.
Approve userUser was approved.
Update role for userUser’s role was changed.
Suspend userUser was suspended from the tailnet.
Restore userUser was restored to the tailnet.
Delete userUser was deleted from the tailnet.
Push userUser attributes were updated for a user provisioned in a SCIM-integrated identity provider.
GroupPush groupA group was provisioned in a SCIM-integrated identity provider.
NodeCreate nodeNode was added. For tailnets with device approval enabled, it may not yet be approved.
Log in nodeUser logged in to or re-authenticated on a node. This includes re-authentication as part of Tailscale SSH check mode.
Approve nodeNode was approved.
Update name for nodeNode name updated.
Enable key expiry for nodeNode key expiry was enabled.
Disable key expiry for nodeNode key expiry was disabled.
Update key expiry time for nodeUser re-authenticated the node, extending the node key validity, or node key expiry was temporarily extended.
Expire node keyNode key expired.
Update approved routes for nodeRoutes for this node were manually updated.
Update auto approved routes for nodeRoutes for this node were automatically updated based on auto approvers.
Update exit settings for nodeExit node advertised by the node updated.
Update tags for nodeNode tags updated.
Update node attributeA device posture attribute was changed on the node.
Update node posture identityDevice posture identity for the node was changed.
Log out nodeUser logged out of node.
Delete nodeNode was deleted.
Admin ConsoleLog in to admin consoleAuthorized user logged in to the admin console.
Log out of admin consoleAuthorized user logged out of the admin console.
login.tailscale.comLog in using web interfaceMember user logged in to the web interface.
Log out using web interfaceMember user logged out of the web interface.
InviteCreate invite for node shareNode share invite was created by sharer tailnet. The invite target is the label entered when creating the invite.
Accept invite for node shareNode share invite was accepted by sharee tailnet.
Delete invite for node shareNode share invite was revoked by sharer tailnet.
ShareCreate node shareShared node was added to sharee's tailnet.
Update node shareShared node was updated. This occurs when a shared node is shared with a sharee who already has the shared node.
Delete node shareShared 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).
APIFailed requestAPI call attempted with insufficient permission.
API keyCreate API keyAPI access token was generated.
Revoke API keyAPI access token was revoked.
API key expiredAPI access token expired.
Auth keyCreate API keyAuth key was generated. This includes tags and if the key is reusable, ephemeral, pre-approved.
Revoke API keyAuth key was revoked.
API key expiredAuth 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 access tokens, 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, approving the node.

OperationEvents
A user is added to the tailnet
A user is deleted
  • Delete node, for each node
  • 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 approval is enabled:
  • Approve 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 tailnet
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.

TargetActionActorLogged by sharer tailnet?Logged by sharee tailnet?
InviteCreate invite for node shareSharer admin
Accept invite for node shareSharee admin
Delete invite for node shareSharer admin
ShareCreate node shareSharee admin
Update node shareSharee admin
Delete node shareSharer 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:

TargetActionActorDescription
TailnetSuspend userTailscale service: user and group provisioningUser deactivated or unassigned from the Tailscale app for tailnets using user & group provisioning
TailnetRestore userTailscale service: user and group provisioningUser reactivated or assigned the Tailscale app for tailnets using user & group provisioning
NodeDelete nodeTailscale service: remove ephemeral nodeRemove inactive ephemeral node
API key or Auth keyAPI key expiredTailscale service: expire API keyExpire 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 name for tailnet
  • Update role for user
  • Delete user
  • Create billing subscription for tailnet
  • Update billing subscription for tailnet
  • Cancel billing subscription for tailnet
  • Update billing address for tailnet
  • Update billing email for tailnet
  • Update billing payment information for tailnet
  • Update key expiry time for node
  • Enable device approval for tailnet
  • Disable device approval for tailnet

Configuration audit logs streaming

Log streaming lets you stream network flow logs into a security information and event management (SIEM) system. For more information, see Log streaming.

Limitations

  • Configuration audit 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.
  • Configuration audit 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 in configuration logs. You can use Network flow logs to log information about connections with a tailnet.
  • Configuration audit logs are available as part of the admin console, exportable via API, and as a streaming source for SIEM systems.
  • 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 configuration logs are stored cannot be configured. Configuration logs are stored for 90 days.
  • 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 access tokens, and auth keys are not logged.
  • When a user is deleted, the deletion of the user's API access tokens and auth keys are not logged.