Device posture management
What is device posture?
Device posture lets you collect device properties and set device connectivity rules within your Tailscale network (known as a tailnet). You can use these rules to remove devices from your tailnet that do not meet security requirements, or limit their connectivity based on the properties such as operating system version or Tailscale client version.
Device attributes include pre-populated host information such as operating system version, as well as custom attributes from endpoint detection and response tools.
Authorize device API
If you have an endpoint device posture solution, you may already know which machines on your tailnet do and do not meet your device posture requirements.
One approach to ensuring devices on your network comply with your device posture policy is to use the Authorize device API. This allows you to only authorize devices that meet your requirements, de-authorize devices that do not meet your requirements, by temporarily disabling tailnet access until you determine that their posture has been resolved, at which point you can re-authorize the devices.
Device posture attributes
Device posture attributes are key-value pairs of data attached to devices that you can either read and write for your own use, or use in posture access rules. These attributes are in namespaces. For example, the attribute key node:os
is in the node
namespace, and the key custom:myAttribute
is in the custom
namespace.
The following posture attributes are currently available by default, for use in access rule postures, and via the node attribute API:
Attribute key | Description | Example |
---|---|---|
node:os |
The operating system the device is running | node:os == 'macos' |
node:osVersion |
The version of the operating system | node:osVersion == '13.4.0' |
node:tsReleaseTrack |
The release track the Tailscale client is on (“stable” or “unstable”) | node:tsReleaseTrack == 'stable' |
node:tsVersion |
The version of Tailscale the client is running | node:tsVersion == '1.40.0' |
Posture attributes bring together data from several different sources all in one place:
- Host information already available via the API such as OS version and Tailscale version in the
node
namespace. - Custom posture attributes set by you, or software you have integrated with our API, in the
custom
namespace.
nodeAttrs
. The existing nodeAttrs
are set as flags only, not as key-value pairs.Posture conditions in access rules
Postures and posture conditions let you create automated network access control rules based on device posture.
A posture is a set of assertions based on device posture attributes. For example, you might specify that the operating system needs to be newer than a particular version.
Posture conditions are a feature for access rules, allowing you to make them conditional on device posture in addition to source, destination, and protocol. This lets you write flexible and fine-grained access controls for your tailnet.
You can use posture conditions to create simple rules, such as denying all access to devices that don’t meet your posture requirements, or control access within your tailnet with far more granularity. For example, you can require devices to meet stricter security requirements in order to be able to connect to production. Or you can disallow access to most of your corporate network for devices that don’t meet your posture requirements, but still allow them to reach the IT help desk.
API and access rule posture reference
For general information about Tailscale API access and authentication, refer to our API documentation.
Deauthorize API
POST /api/v2/device/{deviceID}/authorized
This is an extension to the existing authorize device API endpoint.
Parameters
deviceID
(required in URL path)
The ID of the device to deauthorize.
authorized
(required in POST body)
Specify whether the device is authorized by indicating false
to deauthorize an authorized device, or true
to authorize a new device or to re-authorize a previously deauthorized device.
{
"authorized": false
}
Request example
curl "https://api.tailscale.com/api/v2/device/11055/authorized" \
-u "tskey-api-xxxxx:" \
--data-binary '{"authorized": false}'
Response
The response is 2xx on success. The response body is currently an empty JSON object.
Postures and posture conditions
Postures and posture conditions are an extension to the policy file syntax, and let you use device posture attributes as conditions in your access control rules.
Postures
A posture is a set of assertions made about posture attributes and only apply to devices initiating the connection. Each posture must start with posture:
followed by a name, and a set of posture attributes and their values, given as a list of strings.
"postures": {
"posture:latestMac": [
"node:os == 'macos'",
"node:osVersion == '13.4.0'",
"node:tsReleaseTrack == 'stable'",
],
},
Currently supported operators:
==
!=
For a posture to match a device, all posture attribute values must be met. In the above example:
- The operating system must be macOS
- macOS version must be 13.4.0
- The devices must use the stable release version of the Tailscale client
Posture conditions can be made against any posture attributes, default and custom.
If an attribute defined in the posture is unset for a particular device, the posture will not match that device, irrespective of the operator used. For example, a device that does not have the custom:tier
attribute assigned to it, will not match a posture that includes an attribute custom:tier
, even if that condition is negative (e.g. custom:tier != 'prod'
).
You can create multiple postures in one policy file:
"postures": {
"posture:latestMac": [
"node:os == 'macos'",
"node:osVersion == '13.4.0'",
"node:tsReleaseTrack == 'stable'",
],
"posture:anyMac": [
"node:os == 'macos'",
"node:tsReleaseTrack == 'stable'",
],
},
You can create up to 100 postures in your policy file.
Posture conditions
A posture condition is an extension to the existing tailnet policy file syntax, allowing you to define access rules dependent on device posture:
"acls": [
{
// Only requirement to access development servers is Mac + stable Tailscale
"action": "accept",
"src": ["autogroup:member"],
"dst": ["tag:development"],
"srcPosture": ["posture:anyMac"]
},{
// Only devs can access production
// and production access requires macOS is also up to date
"action": "accept",
"src": ["group:dev"],
"dst": ["tag:production"],
"srcPosture": ["posture:latestMac"]
},
],
Access rules can require that any of a list of postures is required for access to be permitted:
"acls": [
{
"action": "accept",
"src": ["group:dev"],
"dst": ["tag:production"],
"srcPosture": ["posture:approvedMacs", "posture:approvedWindows", "posture:approvedLinux"]
},
],
In this example, access is permitted to production if the connecting device meets any of the 3 specified postures.
Default source posture
If you want to apply a baseline posture that applies to all of your access rules, you can set a default source posture:
"defaultSrcPosture": [
"posture:basicWindows",
"posture:basicMac",
"posture:basicLinux",
],
As with srcPosture
in access rules, this permits access if any of the supplied postures are met.
If a default source posture is set, it will apply to any access rules that do not have a posture condition. Note that it is not additive, meaning if an access rule specifies a posture condition, only that condition will apply, and the default source posture condition will no longer apply. This can be used to create an access rule that is more permissive than the default:
"acls": [
{
// defaultSrcPosture applies to this rule
"action": "accept",
"src": ["autogroup:member"],
"dst": ["tag:intranet"],
},{
"action": "accept",
"src": ["group:dev", "group:sre"],
"dst": ["tag:production"],
// This posture condition is instead of, not in addition to, the default source posture
"srcPosture": ["posture:prodWin", "posture:prodMac"]
},
],
Get posture attributes via API
GET /api/v2/device/{deviceID}/attributes
Retrieve all posture attributes for the specified device. This returns a JSON object of all the key-value pairs of posture attributes for the device.
Parameters
deviceID
(required in URL path)
The ID of the device to fetch posture attributes for.
Request example
curl "https://api.tailscale.com/api/v2/device/11055/attributes" \
-u "tskey-api-xxxxx:"
Response
The response is 200 on success. The response body is a JSON object containing all the posture attributes.
{
"attributes": {
"custom:myAttribute": "my_value",
"node:os": "linux",
"node:osVersion": "5.19.0-42-generic",
"node:tsReleaseTrack": "stable",
"node:tsVersion": "1.40.0"
}
}
Set custom posture attributes via API
POST /api/v2/device/{deviceID}/attributes/{attributeKey}
Create or update a custom posture attribute on the specified device. User-managed attributes must be in the custom
namespace, which is indicated by prefixing the attribute key with custom:
.
Parameters
deviceID
(required in URL path)
The ID of the device on which to set the custom posture attribute.
attributeKey
(required in URL path)
The name of the posture attribute to set. This must be prefixed with custom:
.
Keys have a maximum length of 50 characters including the namespace, and can only contain letters, numbers, underscores, and colon.
Posture attribute value
(required in POST body)
{
"value": "foo"
}
Values have a maximum length of 50 characters, and can only contain letters, numbers, underscores, and periods.
Request example
curl "https://api.tailscale.com/api/v2/device/11055/attributes/custom:my_attribute" \
-u "tskey-api-xxxxx:" \
--data-binary '{"value": "my_value"}'
Response
The response is 2xx on success. The response body is currently an empty JSON object.
Delete custom posture attributes via API
DELETE /api/v2/device/{deviceID}/attributes/{attributeKey}
Delete a posture attribute from the specified device. This is only applicable to user-managed posture attributes in the custom
namespace, which is indicated by prefixing the attribute key with custom:
.
Parameters
deviceID
(required in URL path)
The ID of the device from which to delete the posture attribute.
attributeKey
(required in URL path)
The name of the posture attribute to delete. This must be prefixed with custom:
.
Keys have a maximum length of 50 characters including the namespace, and can only contain letters, numbers, underscores, and a delimiting colon.
Request example
curl -X DELETE "https://api.tailscale.com/api/v2/device/11055/attributes/custom:my_attribute" \
-u "tskey-api-xxxxx:"
Response
The response is 2xx on success. The response body is currently an empty JSON object.
Audit log events
The following audit log events are added for device posture.
Target | Action | Description |
---|---|---|
Node | Create new node attribute | Custom node attribute for device posture was created. |
Node | Update node attribute | Custom node attribute for device posture was updated. |
Node | Delete node attribute | Custom node attribute for device posture was deleted. |
Limitations
Compare operations for device posture rules are not currently supported.