From 85cf443ac6290022edd688e579d954516d0e3ec6 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Tue, 8 Feb 2022 16:59:35 +0100 Subject: [PATCH 1/7] docs(acls): Issues with ACL and proposition --- docs/acls.md | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 docs/acls.md diff --git a/docs/acls.md b/docs/acls.md new file mode 100644 index 0000000..d070811 --- /dev/null +++ b/docs/acls.md @@ -0,0 +1,55 @@ + +# ACLs + +A key component of tailscale is the notion of Tailnet. This notion is hidden but the implications that it have on how to use tailscale are not. + +For tailscale an [tailnet](https://tailscale.com/kb/1136/tailnet/) is the following: + +> For personal users, you are a tailnet of many devices and one person. Each device gets a private Tailscale IP address in the CGNAT range and every device can talk directly to every other device, wherever they are on the internet. +> +> For businesses and organizations, a tailnet is many devices and many users. It can be based on your Microsoft Active Directory, your Google Workspace, a GitHub organization, Okta tenancy, or other identity provider namespace. All of the devices and users in your tailnet can be seen by the tailnet administrators in the Tailscale admin console. There you can apply tailnet-wide configuration, such as ACLs that affect visibility of devices inside your tailnet, DNS settings, and more. + +## Current implementation and issues + +Currently in headscale, the namespaces are used both as tailnet and users. The issue is that if we want to use the ACL's we can't use both at the same time. + +Tailnet's cannot communicate with each others. So we can't have an ACL that authorize tailnet (namespace) A to talk to tailnet (namespace) B. + +We also can't write ACLs based on the users (namespaces in headscale) since all devices belong to the same user. + +With the current implementation the only ACL that we can user is to associate each headscale IP to a host manually then write the ACLs according to this manual mapping. + +```json +{ + "hosts":{ + "host1": "100.64.0.1", + "server": "100.64.0.2" + }, + "acls": [ + {"action": "accept", "users":["host1"], "ports":["host2:80,443"]} + ] +} +``` + +While this works, it requires a lot of manual editing on the configuration and to keep track of all devices IP address. + +## Proposition for a next implementation + +In order to ease the use of ACL's we need to split the tailnet and users notion. + +A solution could be to consider a headscale server (in it's entirety) as a tailnet. + +For personal users the default behavior could either allow all communications between all namespaces (like tailscale) or dissallow all communications between namespaces (current behavior). + +For businesses and organisations, viewing a headscale instance a single tailnet would allow users (namespace) to talk to each other with the ACLs. As described in tailscale's documentation [[1]], a server should be tagged and personnal devices should be tied to a user. Translated in headscale's terms each user can have multiple devices and all those devices should be in the same namespace. The servers should be tagged and used as such. + +This implementation would render useless the sharing feature that is currently implemented since an ACL could do the same. + +What could be improved would be to peer different headscale installation and allow `sharing`. This would raises issues about compatible network IPs range. + +[1]: https://tailscale.com/kb/1068/acl-tags/ + + +## Get the better of both worlds + +If the current behavior has a lot of use cases we could maybe have a flag to trigger one behavior or the other. Or enabling the ACL's behavior if an ACL file is defined. From 04262123483f1294d52d22f0451c9d05a4b753f9 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Thu, 10 Feb 2022 10:42:26 +0100 Subject: [PATCH 2/7] docs(acls): add example use case --- docs/acls.md | 228 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 226 insertions(+), 2 deletions(-) diff --git a/docs/acls.md b/docs/acls.md index d070811..1d1c56d 100644 --- a/docs/acls.md +++ b/docs/acls.md @@ -49,7 +49,231 @@ What could be improved would be to peer different headscale installation and all [1]: https://tailscale.com/kb/1068/acl-tags/ +## Example -## Get the better of both worlds +Let's build an example use case for a small business (It may be the place where +ACL's are the most useful). -If the current behavior has a lot of use cases we could maybe have a flag to trigger one behavior or the other. Or enabling the ACL's behavior if an ACL file is defined. +We have a small company with a boss, an admin, two developper and an intern. + +The boss should have access to all servers but not to the users hosts. Admin +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 +anything they want on dev hosts, but only watch on productions hosts. Intern +can only interact with the development servers. + +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 + +### Current headscale implementation + +Let's create some namespaces + +```bash +headscale namespaces create prod +headscale namespaces create dev +headscale namespaces create internal +headscale namespaces create users + +headscale nodes register -n users boss-computer +headscale nodes register -n users admin1-computer +headscale nodes register -n users dev1-computer +headscale nodes register -n users dev1-phone +headscale nodes register -n users dev2-computer +headscale nodes register -n users intern1-computer + +headscale nodes register -n prod database +headscale nodes register -n prod app-server1 + +headscale nodes register -n dev database +headscale nodes register -n dev app-server1 + +headscale nodes register -n internal billing + +headscale nodes list +ID | Name | Namespace | IP address +1 | boss-computer | users | 100.64.0.1 +2 | admin1-computer | users | 100.64.0.2 +3 | dev1-computer | users | 100.64.0.3 +4 | dev1-phone | users | 100.64.0.4 +5 | dev2-computer | users | 100.64.0.5 +6 | intern1-computer | users | 100.64.0.6 +7 | database | prod | 100.64.0.7 +8 | app-server1 | prod | 100.64.0.8 +9 | database | dev | 100.64.0.9 +10 | app-server1 | dev | 100.64.0.10 +11 | internal | internal | 100.64.0.11 +``` + +In order to only allow the communications related to our description above we +need to add the following ACLs + +```json +{ + "hosts":{ + "boss-computer": "100.64.0.1", + "admin1-computer": "100.64.0.2", + "dev1-computer": "100.64.0.3", + "dev1-phone": "100.64.0.4", + "dev2-computer": "100.64.0.5", + "intern1-computer": "100.64.0.6", + "prod-app-server1": "100.64.0.8", + }, + "groups":{ + "group:dev": ["dev1-computer", "dev1-phone", "dev2-computer"], + "group:admin": ["admin1-computer"], + "group:boss": ["boss-computer"], + "group:intern": ["intern1-computer"], + }, + "acls":[ + // boss have access to all servers but no users hosts + {"action":"accept", "users":["group:boss"], "ports":["prod:*","dev:*","internal:*"]}, + + // admin have access to adminstration port (lets only consider port 22 here) + {"action":"accept", "users":["group:admin"], "ports":["prod:22","dev:22","internal:22"]}, + + // dev can do anything on dev servers and check access on prod servers + {"action":"accept", "users":["group:dev"], "ports":["dev:*","prod-app-server1:80,443"]}, + + // interns only have access to port 80 and 443 on dev servers (lame internship) + {"action":"accept", "users":["group:intern"], "ports":["dev:80,443"]}, + + // users can access their own devices + {"action":"accept", "users":["dev1-computer"], "ports":["dev1-phone:*"]}, + {"action":"accept", "users":["dev1-phone"], "ports":["dev1-computer:*"]}, + ] +} +``` + +Since communications between namespace isn't possible we also have to share the +devices between the namespaces. + +```bash + +// add boss host to prod, dev and internal network +headscale nodes share -i 1 -n prod +headscale nodes share -i 1 -n dev +headscale nodes share -i 1 -n internal + +// add admin computer to prod, dev and internal network +headscale nodes share -i 2 -n prod +headscale nodes share -i 2 -n dev +headscale nodes share -i 2 -n internal + +// add all dev to prod and dev network +headscale nodes share -i 3 -n dev +headscale nodes share -i 4 -n dev +headscale nodes share -i 3 -n prod +headscale nodes share -i 4 -n prod +headscale nodes share -i 5 -n dev +headscale nodes share -i 5 -n prod + +headscale nodes share -i 6 -n dev +``` + +This fake network have not been tested but it should work. Operating it could +be quite tedious if the company grows. Each time a new user join we have to add +it to a group, and share it to the correct namespaces. If the user want +multiple devices we have to allow communication to each of them one by one. If +business conduct a change in the organisations we may have to rewrite all acls +and reorganise all namespaces. + +If we add servers in production we should also update the ACLs to allow dev access to certain category of them (only app servers for example). + +### example based on the proposition in this document + +Let's create the namespaces + +```bash +headscale namespaces create boss +headscale namespaces create admin1 +headscale namespaces create dev1 +headscale namespaces create dev2 +headscale namespaces create intern1 +``` + +We don't need to create namespaces for the servers because the servers will be +tagged. When registering the servers we will need to add the flag +`--advertised-tags=tag:,tag:`, and the user (namespace) that is +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 +and only valid tags are applied. A tag is valid if the namespace that is +registering it is allowed to do it. + +Here are the ACL's to implement the same permissions as above: + +```json +{ + // groups are simpler and only list the namespaces name + "groups": { + "group:boss": ["boss"], + "group:dev": ["dev1","dev2"], + "group:admin": ["admin1"], + "group:intern": ["intern1"], + }, + "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 + }, + "acls": [ + // boss have access to all servers + {"action":"accept", + "users":["group:boss"], + "ports":[ + "tag:prod-databases:*", + "tag:prod-app-servers:*", + "tag:internal:*", + "tag:dev-databases:*", + "tag:dev-app-servers:*", + ] + }, + + // admin have only access to administrative ports of the servers + {"action":"accept", + "users":["group:admin"], + "ports":[ + "tag:prod-databases:22", + "tag:prod-app-servers:22", + "tag:internal:22", + "tag:dev-databases:22", + "tag:dev-app-servers:22", + ] + }, + + {"action":"accept", "users":["group:dev"], "ports":[ + "tag:dev-databases:*", + "tag:dev-app-servers:*", + "tag:prod-app-servers:80,443", + ] + }, + + // interns have access to dev-app-servers only in reading mode + {"action":"accept", "users":["group:intern"], "ports":["tag:dev-app-servers:80,443"]}, + + // we still have to allow internal namespaces communications since nothing guarantees that each user have their own namespaces. This could be talked over. + {"action":"accept", "users":["boss"], "ports":["boss:*"]}, + {"action":"accept", "users":["dev1"], "ports":["dev1:*"]}, + {"action":"accept", "users":["dev2"], "ports":["dev2:*"]}, + {"action":"accept", "users":["admin1"], "ports":["admin1:*"]}, + {"action":"accept", "users":["intern1"], "ports":["intern1:*"]}, + ] +} +``` + +With this implementation, the sharing step is not necessary. Maintenance cost of the ACL file is lower and less tedious (no need to map hostname and IP's into it). From 7bdd7748e4cec82206369d972240363bca644527 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Thu, 10 Feb 2022 12:03:03 +0100 Subject: [PATCH 3/7] fix(acl): add missing internal namespace communications --- docs/acls.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/acls.md b/docs/acls.md index 1d1c56d..31b1c8a 100644 --- a/docs/acls.md +++ b/docs/acls.md @@ -147,6 +147,11 @@ need to add the following ACLs // users can access their own devices {"action":"accept", "users":["dev1-computer"], "ports":["dev1-phone:*"]}, {"action":"accept", "users":["dev1-phone"], "ports":["dev1-computer:*"]}, + + // internal namespace communications should still be allowed within the namespace + {"action":"accept", "users":["dev"], "ports":["dev:*"]}, + {"action":"accept", "users":["prod"], "ports":["prod:*"]}, + {"action":"accept", "users":["internal"], "ports":["internal:*"]}, ] } ``` @@ -263,6 +268,10 @@ Here are the ACL's to implement the same permissions as above: ] }, + // servers should be able to talk to database. Database should not be able to initiate connections to server + {"action":"accept", "users":["tag:dev-app-servers"], "ports":["tag:dev-databases:5432"]}, + {"action":"accept", "users":["tag:prod-app-servers"], "ports":["tag:prod-databases:5432"]}, + // interns have access to dev-app-servers only in reading mode {"action":"accept", "users":["group:intern"], "ports":["tag:dev-app-servers:80,443"]}, From 86b329d8bfeb5af56d847b3085ac286cbf935676 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Tue, 15 Feb 2022 09:27:33 +0100 Subject: [PATCH 4/7] chore(docs): create proposals directory --- docs/{acls.md => proposals/001-acls.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docs/{acls.md => proposals/001-acls.md} (100%) diff --git a/docs/acls.md b/docs/proposals/001-acls.md similarity index 100% rename from docs/acls.md rename to docs/proposals/001-acls.md From e540679dbd6d4d9d11d9838ecf6e522d3d8a9a04 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Tue, 15 Feb 2022 09:52:05 +0100 Subject: [PATCH 5/7] docs(acl-proposals): integrate comments --- docs/proposals/001-acls.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/proposals/001-acls.md b/docs/proposals/001-acls.md index 31b1c8a..92e000a 100644 --- a/docs/proposals/001-acls.md +++ b/docs/proposals/001-acls.md @@ -43,9 +43,12 @@ For personal users the default behavior could either allow all communications be For businesses and organisations, viewing a headscale instance a single tailnet would allow users (namespace) to talk to each other with the ACLs. As described in tailscale's documentation [[1]], a server should be tagged and personnal devices should be tied to a user. Translated in headscale's terms each user can have multiple devices and all those devices should be in the same namespace. The servers should be tagged and used as such. -This implementation would render useless the sharing feature that is currently implemented since an ACL could do the same. +This implementation would render useless the sharing feature that is currently +implemented since an ACL could do the same. Simplifying to only one user +interface to do one thing is easier and less confusing for the users. -What could be improved would be to peer different headscale installation and allow `sharing`. This would raises issues about compatible network IPs range. +As a sidenote, users would like to write ACLs as YAML. We should offer users +the ability to rules in either format (HuJSON or YAML). [1]: https://tailscale.com/kb/1068/acl-tags/ From c364c2a38206855ad8bbf7264d687cf09c0c40cd Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Tue, 15 Feb 2022 09:53:22 +0100 Subject: [PATCH 6/7] chore(acl-proposals): apply prettier --- docs/proposals/001-acls.md | 293 ++++++++++++++++++++++--------------- 1 file changed, 179 insertions(+), 114 deletions(-) diff --git a/docs/proposals/001-acls.md b/docs/proposals/001-acls.md index 92e000a..23435a2 100644 --- a/docs/proposals/001-acls.md +++ b/docs/proposals/001-acls.md @@ -1,47 +1,72 @@ - # ACLs -A key component of tailscale is the notion of Tailnet. This notion is hidden but the implications that it have on how to use tailscale are not. +A key component of tailscale is the notion of Tailnet. This notion is hidden +but the implications that it have on how to use tailscale are not. -For tailscale an [tailnet](https://tailscale.com/kb/1136/tailnet/) is the following: +For tailscale an [tailnet](https://tailscale.com/kb/1136/tailnet/) is the +following: -> For personal users, you are a tailnet of many devices and one person. Each device gets a private Tailscale IP address in the CGNAT range and every device can talk directly to every other device, wherever they are on the internet. +> For personal users, you are a tailnet of many devices and one person. Each +> device gets a private Tailscale IP address in the CGNAT range and every +> device can talk directly to every other device, wherever they are on the +> internet. > -> For businesses and organizations, a tailnet is many devices and many users. It can be based on your Microsoft Active Directory, your Google Workspace, a GitHub organization, Okta tenancy, or other identity provider namespace. All of the devices and users in your tailnet can be seen by the tailnet administrators in the Tailscale admin console. There you can apply tailnet-wide configuration, such as ACLs that affect visibility of devices inside your tailnet, DNS settings, and more. +> For businesses and organizations, a tailnet is many devices and many users. +> It can be based on your Microsoft Active Directory, your Google Workspace, a +> GitHub organization, Okta tenancy, or other identity provider namespace. All +> of the devices and users in your tailnet can be seen by the tailnet +> administrators in the Tailscale admin console. There you can apply +> tailnet-wide configuration, such as ACLs that affect visibility of devices +> inside your tailnet, DNS settings, and more. ## Current implementation and issues -Currently in headscale, the namespaces are used both as tailnet and users. The issue is that if we want to use the ACL's we can't use both at the same time. +Currently in headscale, the namespaces are used both as tailnet and users. The +issue is that if we want to use the ACL's we can't use both at the same time. -Tailnet's cannot communicate with each others. So we can't have an ACL that authorize tailnet (namespace) A to talk to tailnet (namespace) B. +Tailnet's cannot communicate with each others. So we can't have an ACL that +authorize tailnet (namespace) A to talk to tailnet (namespace) B. -We also can't write ACLs based on the users (namespaces in headscale) since all devices belong to the same user. +We also can't write ACLs based on the users (namespaces in headscale) since all +devices belong to the same user. -With the current implementation the only ACL that we can user is to associate each headscale IP to a host manually then write the ACLs according to this manual mapping. +With the current implementation the only ACL that we can user is to associate +each headscale IP to a host manually then write the ACLs according to this +manual mapping. ```json { - "hosts":{ - "host1": "100.64.0.1", - "server": "100.64.0.2" - }, - "acls": [ - {"action": "accept", "users":["host1"], "ports":["host2:80,443"]} - ] + "hosts": { + "host1": "100.64.0.1", + "server": "100.64.0.2" + }, + "acls": [ + { "action": "accept", "users": ["host1"], "ports": ["host2:80,443"] } + ] } ``` -While this works, it requires a lot of manual editing on the configuration and to keep track of all devices IP address. +While this works, it requires a lot of manual editing on the configuration and +to keep track of all devices IP address. ## Proposition for a next implementation -In order to ease the use of ACL's we need to split the tailnet and users notion. +In order to ease the use of ACL's we need to split the tailnet and users +notion. -A solution could be to consider a headscale server (in it's entirety) as a tailnet. +A solution could be to consider a headscale server (in it's entirety) as a +tailnet. -For personal users the default behavior could either allow all communications between all namespaces (like tailscale) or dissallow all communications between namespaces (current behavior). +For personal users the default behavior could either allow all communications +between all namespaces (like tailscale) or dissallow all communications between +namespaces (current behavior). -For businesses and organisations, viewing a headscale instance a single tailnet would allow users (namespace) to talk to each other with the ACLs. As described in tailscale's documentation [[1]], a server should be tagged and personnal devices should be tied to a user. Translated in headscale's terms each user can have multiple devices and all those devices should be in the same namespace. The servers should be tagged and used as such. +For businesses and organisations, viewing a headscale instance a single tailnet +would allow users (namespace) to talk to each other with the ACLs. As described +in tailscale's documentation [[1]], a server should be tagged and personnal +devices should be tied to a user. Translated in headscale's terms each user can +have multiple devices and all those devices should be in the same namespace. +The servers should be tagged and used as such. This implementation would render useless the sharing feature that is currently implemented since an ACL could do the same. Simplifying to only one user @@ -119,43 +144,63 @@ need to add the following ACLs ```json { - "hosts":{ - "boss-computer": "100.64.0.1", - "admin1-computer": "100.64.0.2", - "dev1-computer": "100.64.0.3", - "dev1-phone": "100.64.0.4", - "dev2-computer": "100.64.0.5", - "intern1-computer": "100.64.0.6", - "prod-app-server1": "100.64.0.8", + "hosts": { + "boss-computer": "100.64.0.1", + "admin1-computer": "100.64.0.2", + "dev1-computer": "100.64.0.3", + "dev1-phone": "100.64.0.4", + "dev2-computer": "100.64.0.5", + "intern1-computer": "100.64.0.6", + "prod-app-server1": "100.64.0.8" + }, + "groups": { + "group:dev": ["dev1-computer", "dev1-phone", "dev2-computer"], + "group:admin": ["admin1-computer"], + "group:boss": ["boss-computer"], + "group:intern": ["intern1-computer"] + }, + "acls": [ + // boss have access to all servers but no users hosts + { + "action": "accept", + "users": ["group:boss"], + "ports": ["prod:*", "dev:*", "internal:*"] }, - "groups":{ - "group:dev": ["dev1-computer", "dev1-phone", "dev2-computer"], - "group:admin": ["admin1-computer"], - "group:boss": ["boss-computer"], - "group:intern": ["intern1-computer"], + + // admin have access to adminstration port (lets only consider port 22 here) + { + "action": "accept", + "users": ["group:admin"], + "ports": ["prod:22", "dev:22", "internal:22"] }, - "acls":[ - // boss have access to all servers but no users hosts - {"action":"accept", "users":["group:boss"], "ports":["prod:*","dev:*","internal:*"]}, - // admin have access to adminstration port (lets only consider port 22 here) - {"action":"accept", "users":["group:admin"], "ports":["prod:22","dev:22","internal:22"]}, + // dev can do anything on dev servers and check access on prod servers + { + "action": "accept", + "users": ["group:dev"], + "ports": ["dev:*", "prod-app-server1:80,443"] + }, - // dev can do anything on dev servers and check access on prod servers - {"action":"accept", "users":["group:dev"], "ports":["dev:*","prod-app-server1:80,443"]}, + // interns only have access to port 80 and 443 on dev servers (lame internship) + { "action": "accept", "users": ["group:intern"], "ports": ["dev:80,443"] }, - // interns only have access to port 80 and 443 on dev servers (lame internship) - {"action":"accept", "users":["group:intern"], "ports":["dev:80,443"]}, + // users can access their own devices + { + "action": "accept", + "users": ["dev1-computer"], + "ports": ["dev1-phone:*"] + }, + { + "action": "accept", + "users": ["dev1-phone"], + "ports": ["dev1-computer:*"] + }, - // users can access their own devices - {"action":"accept", "users":["dev1-computer"], "ports":["dev1-phone:*"]}, - {"action":"accept", "users":["dev1-phone"], "ports":["dev1-computer:*"]}, - - // internal namespace communications should still be allowed within the namespace - {"action":"accept", "users":["dev"], "ports":["dev:*"]}, - {"action":"accept", "users":["prod"], "ports":["prod:*"]}, - {"action":"accept", "users":["internal"], "ports":["internal:*"]}, - ] + // internal namespace communications should still be allowed within the namespace + { "action": "accept", "users": ["dev"], "ports": ["dev:*"] }, + { "action": "accept", "users": ["prod"], "ports": ["prod:*"] }, + { "action": "accept", "users": ["internal"], "ports": ["internal:*"] } + ] } ``` @@ -192,7 +237,8 @@ multiple devices we have to allow communication to each of them one by one. If business conduct a change in the organisations we may have to rewrite all acls and reorganise all namespaces. -If we add servers in production we should also update the ACLs to allow dev access to certain category of them (only app servers for example). +If we add servers in production we should also update the ACLs to allow dev +access to certain category of them (only app servers for example). ### example based on the proposition in this document @@ -218,74 +264,93 @@ Here are the ACL's to implement the same permissions as above: ```json { - // groups are simpler and only list the namespaces name - "groups": { - "group:boss": ["boss"], - "group:dev": ["dev1","dev2"], - "group:admin": ["admin1"], - "group:intern": ["intern1"], + // groups are simpler and only list the namespaces name + "groups": { + "group:boss": ["boss"], + "group:dev": ["dev1", "dev2"], + "group:admin": ["admin1"], + "group:intern": ["intern1"] + }, + "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 + }, + "acls": [ + // boss have access to all servers + { + "action": "accept", + "users": ["group:boss"], + "ports": [ + "tag:prod-databases:*", + "tag:prod-app-servers:*", + "tag:internal:*", + "tag:dev-databases:*", + "tag:dev-app-servers:*" + ] }, - "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 + // admin have only access to administrative ports of the servers + { + "action": "accept", + "users": ["group:admin"], + "ports": [ + "tag:prod-databases:22", + "tag:prod-app-servers:22", + "tag:internal:22", + "tag:dev-databases:22", + "tag:dev-app-servers:22" + ] }, - "acls": [ - // boss have access to all servers - {"action":"accept", - "users":["group:boss"], - "ports":[ - "tag:prod-databases:*", - "tag:prod-app-servers:*", - "tag:internal:*", - "tag:dev-databases:*", - "tag:dev-app-servers:*", - ] - }, - // admin have only access to administrative ports of the servers - {"action":"accept", - "users":["group:admin"], - "ports":[ - "tag:prod-databases:22", - "tag:prod-app-servers:22", - "tag:internal:22", - "tag:dev-databases:22", - "tag:dev-app-servers:22", - ] - }, + { + "action": "accept", + "users": ["group:dev"], + "ports": [ + "tag:dev-databases:*", + "tag:dev-app-servers:*", + "tag:prod-app-servers:80,443" + ] + }, - {"action":"accept", "users":["group:dev"], "ports":[ - "tag:dev-databases:*", - "tag:dev-app-servers:*", - "tag:prod-app-servers:80,443", - ] - }, + // servers should be able to talk to database. Database should not be able to initiate connections to server + { + "action": "accept", + "users": ["tag:dev-app-servers"], + "ports": ["tag:dev-databases:5432"] + }, + { + "action": "accept", + "users": ["tag:prod-app-servers"], + "ports": ["tag:prod-databases:5432"] + }, - // servers should be able to talk to database. Database should not be able to initiate connections to server - {"action":"accept", "users":["tag:dev-app-servers"], "ports":["tag:dev-databases:5432"]}, - {"action":"accept", "users":["tag:prod-app-servers"], "ports":["tag:prod-databases:5432"]}, + // interns have access to dev-app-servers only in reading mode + { + "action": "accept", + "users": ["group:intern"], + "ports": ["tag:dev-app-servers:80,443"] + }, - // interns have access to dev-app-servers only in reading mode - {"action":"accept", "users":["group:intern"], "ports":["tag:dev-app-servers:80,443"]}, - - // we still have to allow internal namespaces communications since nothing guarantees that each user have their own namespaces. This could be talked over. - {"action":"accept", "users":["boss"], "ports":["boss:*"]}, - {"action":"accept", "users":["dev1"], "ports":["dev1:*"]}, - {"action":"accept", "users":["dev2"], "ports":["dev2:*"]}, - {"action":"accept", "users":["admin1"], "ports":["admin1:*"]}, - {"action":"accept", "users":["intern1"], "ports":["intern1:*"]}, - ] + // we still have to allow internal namespaces communications since nothing guarantees that each user have their own namespaces. This could be talked over. + { "action": "accept", "users": ["boss"], "ports": ["boss:*"] }, + { "action": "accept", "users": ["dev1"], "ports": ["dev1:*"] }, + { "action": "accept", "users": ["dev2"], "ports": ["dev2:*"] }, + { "action": "accept", "users": ["admin1"], "ports": ["admin1:*"] }, + { "action": "accept", "users": ["intern1"], "ports": ["intern1:*"] } + ] } ``` -With this implementation, the sharing step is not necessary. Maintenance cost of the ACL file is lower and less tedious (no need to map hostname and IP's into it). +With this implementation, the sharing step is not necessary. Maintenance cost +of the ACL file is lower and less tedious (no need to map hostname and IP's +into it). From 55d746d3f5323f661238db9ecb2da93ad95e7430 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Wed, 16 Feb 2022 09:16:25 +0100 Subject: [PATCH 7/7] docs(acls-proposal): wording comment A hidden thing was implied in this document is that each person should have his own namespace. Hidden information in spicification isn't good. Thank's @kradalby for pointing it out. --- docs/proposals/001-acls.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/proposals/001-acls.md b/docs/proposals/001-acls.md index 23435a2..8a02e83 100644 --- a/docs/proposals/001-acls.md +++ b/docs/proposals/001-acls.md @@ -72,6 +72,12 @@ This implementation would render useless the sharing feature that is currently implemented since an ACL could do the same. Simplifying to only one user interface to do one thing is easier and less confusing for the users. +To better suit the ACLs in this proposition, it's advised to consider that each +namespaces belong to one person. This person can have multiple devices, they +will all be considered as the same user in the ACLs. OIDC feature wouldn't need +to map people to namespace, just create a namespace if the person isn't +registered yet. + As a sidenote, users would like to write ACLs as YAML. We should offer users the ability to rules in either format (HuJSON or YAML).