2022-02-14 12:54:44 +00:00
# ACLs use case example
Let's build an example use case for a small business (It may be the place where
ACL's are the most useful).
We have a small company with a boss, an admin, two developers and an intern.
2022-03-17 22:23:37 +00:00
The boss should have access to all servers but not to the user's hosts. Admin
2022-02-14 12:54:44 +00:00
should also have access to all hosts except that their permissions should be
limited to maintaining the hosts (for example purposes). The developers can do
2022-03-17 22:23:37 +00:00
anything they want on dev hosts but only watch on productions hosts. Intern
2022-02-14 12:54:44 +00:00
can only interact with the development servers.
2022-03-17 22:23:37 +00:00
There's an additional server that acts as a router, connecting the VPN users
2022-03-17 22:58:34 +00:00
to an internal network `10.20.0.0/16` . Developers must have access to those
internal resources.
2022-03-17 22:23:37 +00:00
2022-02-14 12:54:44 +00:00
Each user have at least a device connected to the network and we have some
servers.
- database.prod
- database.dev
- app-server1.prod
- app-server1.dev
- billing.internal
2022-03-17 22:23:37 +00:00
- router.internal
2022-02-14 12:54:44 +00:00
2022-03-17 22:58:34 +00:00
![ACL implementation example ](images/headscale-acl-network.png )
2022-02-14 12:54:44 +00:00
2022-03-17 22:58:34 +00:00
## ACL setup
2023-01-17 18:03:40 +00:00
Note: Users will be created automatically when users authenticate with the
2022-03-17 22:24:39 +00:00
Headscale server.
2022-03-17 22:58:34 +00:00
ACLs could be written either on [huJSON ](https://github.com/tailscale/hujson )
2022-06-08 16:12:47 +00:00
or YAML. Check the [test ACLs ](../tests/acls ) for further information.
2022-03-17 22:58:34 +00:00
2022-03-17 22:24:39 +00:00
When registering the servers we will need to add the flag
2023-01-17 18:03:40 +00:00
`--advertise-tags=tag:<tag1>,tag:<tag2>` , and the user that is
2022-02-14 12:54:44 +00:00
registering the server should be allowed to do it. Since anyone can add tags to
a server they can register, the check of the tags is done on headscale server
2023-01-17 18:03:40 +00:00
and only valid tags are applied. A tag is valid if the user that is
2022-02-14 12:54:44 +00:00
registering it is allowed to do it.
2023-03-28 16:41:23 +00:00
To use ACLs in headscale, you must edit your config.yaml file. In there you will find a `acl_policy_path: ""` parameter. This will need to point to your ACL file. More info on how these policies are written can be found [here ](https://tailscale.com/kb/1018/acls/ ).
2023-03-27 09:25:55 +00:00
2022-02-14 12:54:44 +00:00
Here are the ACL's to implement the same permissions as above:
```json
{
2022-02-14 14:54:51 +00:00
// groups are collections of users having a common scope. A user can be in multiple groups
// groups cannot be composed of groups
"groups": {
"group:boss": ["boss"],
"group:dev": ["dev1", "dev2"],
"group:admin": ["admin1"],
"group:intern": ["intern1"]
},
// tagOwners in tailscale is an association between a TAG and the people allowed to set this TAG on a server.
// This is documented [here ](https://tailscale.com/kb/1068/acl-tags#defining-a-tag )
// and explained [here ](https://tailscale.com/blog/rbac-like-it-was-meant-to-be/ )
"tagOwners": {
// the administrators can add servers in production
"tag:prod-databases": ["group:admin"],
"tag:prod-app-servers": ["group:admin"],
// the boss can tag any server as internal
"tag:internal": ["group:boss"],
// dev can add servers for dev purposes as well as admins
"tag:dev-databases": ["group:admin", "group:dev"],
"tag:dev-app-servers": ["group:admin", "group:dev"]
// interns cannot add servers
},
2022-03-17 22:58:34 +00:00
// hosts should be defined using its IP addresses and a subnet mask.
// to define a single host, use a /32 mask. You cannot use DNS entries here,
// as they're prone to be hijacked by replacing their IP addresses.
// see https://github.com/tailscale/tailscale/issues/3800 for more information.
"Hosts": {
"postgresql.internal": "10.20.0.2/32",
"webservers.internal": "10.20.10.1/29"
},
2022-02-14 14:54:51 +00:00
"acls": [
// boss have access to all servers
{
"action": "accept",
2022-06-08 16:12:47 +00:00
"src": ["group:boss"],
"dst": [
2022-02-14 14:54:51 +00:00
"tag:prod-databases:*",
"tag:prod-app-servers:*",
"tag:internal:*",
"tag:dev-databases:*",
"tag:dev-app-servers:*"
]
},
2022-06-08 16:15:38 +00:00
// admin have only access to administrative ports of the servers, in tcp/22
2022-02-14 14:54:51 +00:00
{
"action": "accept",
2022-06-08 16:12:47 +00:00
"src": ["group:admin"],
2022-06-08 16:15:38 +00:00
"proto": "tcp",
2022-06-08 16:12:47 +00:00
"dst": [
2022-02-14 14:54:51 +00:00
"tag:prod-databases:22",
"tag:prod-app-servers:22",
"tag:internal:22",
"tag:dev-databases:22",
"tag:dev-app-servers:22"
]
2022-02-14 12:54:44 +00:00
},
2022-02-14 14:54:51 +00:00
2022-06-08 16:15:38 +00:00
// we also allow admin to ping the servers
{
"action": "accept",
"src": ["group:admin"],
"proto": "icmp",
"dst": [
"tag:prod-databases:*",
"tag:prod-app-servers:*",
"tag:internal:*",
"tag:dev-databases:*",
"tag:dev-app-servers:*"
]
},
2022-02-14 14:54:51 +00:00
// developers have access to databases servers and application servers on all ports
// they can only view the applications servers in prod and have no access to databases servers in production
{
"action": "accept",
2022-06-08 16:12:47 +00:00
"src": ["group:dev"],
"dst": [
2022-02-14 14:54:51 +00:00
"tag:dev-databases:*",
"tag:dev-app-servers:*",
"tag:prod-app-servers:80,443"
]
},
2022-03-17 22:58:34 +00:00
// developers have access to the internal network through the router.
// the internal network is composed of HTTPS endpoints and Postgresql
// database servers. There's an additional rule to allow traffic to be
// forwarded to the internal subnet, 10.20.0.0/16. See this issue
// https://github.com/juanfont/headscale/issues/502
{
"action": "accept",
2022-06-08 16:12:47 +00:00
"src": ["group:dev"],
"dst": ["10.20.0.0/16:443,5432", "router.internal:0"]
2022-03-17 22:58:34 +00:00
},
2022-02-14 14:54:51 +00:00
2022-06-08 16:15:38 +00:00
// servers should be able to talk to database in tcp/5432. Database should not be able to initiate connections to
2022-02-14 14:54:51 +00:00
// applications servers
{
"action": "accept",
2022-06-08 16:12:47 +00:00
"src": ["tag:dev-app-servers"],
2022-06-08 16:15:38 +00:00
"proto": "tcp",
2022-06-08 16:12:47 +00:00
"dst": ["tag:dev-databases:5432"]
2022-02-14 12:54:44 +00:00
},
2022-02-14 14:54:51 +00:00
{
"action": "accept",
2022-06-08 16:12:47 +00:00
"src": ["tag:prod-app-servers"],
"dst": ["tag:prod-databases:5432"]
2022-02-14 14:54:51 +00:00
},
// interns have access to dev-app-servers only in reading mode
{
"action": "accept",
2022-06-08 16:12:47 +00:00
"src": ["group:intern"],
"dst": ["tag:dev-app-servers:80,443"]
2022-02-14 14:54:51 +00:00
},
2023-01-17 18:03:40 +00:00
// We still have to allow internal users communications since nothing guarantees that each user have
// their own users.
2022-06-08 16:12:47 +00:00
{ "action": "accept", "src": ["boss"], "dst": ["boss:*"] },
{ "action": "accept", "src": ["dev1"], "dst": ["dev1:*"] },
{ "action": "accept", "src": ["dev2"], "dst": ["dev2:*"] },
{ "action": "accept", "src": ["admin1"], "dst": ["admin1:*"] },
{ "action": "accept", "src": ["intern1"], "dst": ["intern1:*"] }
2022-02-14 14:54:51 +00:00
]
2022-02-14 12:54:44 +00:00
}
```