mirror of
https://github.com/juanfont/headscale.git
synced 2026-01-12 04:10:32 +01:00
Add ACL management via API #267
Closed
opened 2025-12-29 01:25:20 +01:00 by adam
·
34 comments
No Branch/Tag Specified
main
update_flake_lock_action
gh-pages
kradalby/release-v0.27.2
dependabot/go_modules/golang.org/x/crypto-0.45.0
dependabot/go_modules/github.com/opencontainers/runc-1.3.3
copilot/investigate-headscale-issue-2788
copilot/investigate-visibility-issue-2788
copilot/investigate-issue-2833
copilot/debug-issue-2846
copilot/fix-issue-2847
dependabot/go_modules/github.com/go-viper/mapstructure/v2-2.4.0
dependabot/go_modules/github.com/docker/docker-28.3.3incompatible
kradalby/cli-experiement3
doc/0.26.1
doc/0.25.1
doc/0.25.0
doc/0.24.3
doc/0.24.2
doc/0.24.1
doc/0.24.0
kradalby/build-docker-on-pr
topic/docu-versioning
topic/docker-kos
juanfont/fix-crash-node-id
juanfont/better-disclaimer
update-contributors
topic/prettier
revert-1893-add-test-stage-to-docs
add-test-stage-to-docs
remove-node-check-interval
fix-empty-prefix
fix-ephemeral-reusable
bug_report-debuginfo
autogroups
logs-to-stderr
revert-1414-topic/fix_unix_socket
rename-machine-node
port-embedded-derp-tests-v2
port-derp-tests
duplicate-word-linter
update-tailscale-1.36
warn-against-apache
ko-fi-link
more-acl-tests
fix-typo-standalone
parallel-nolint
tparallel-fix
rerouting
ssh-changelog-docs
oidc-cleanup
web-auth-flow-tests
kradalby-gh-runner
fix-proto-lint
remove-funding-links
go-1.19
enable-1.30-in-tests
0.16.x
cosmetic-changes-integration
tmp-fix-integration-docker
fix-integration-docker
configurable-update-interval
show-nodes-online
hs2021
acl-syntax-fixes
ts2021-implementation
fix-spurious-updates
unstable-integration-tests
mandatory-stun
embedded-derp
prtemplate-fix
v0.28.0-beta.1
v0.27.2-rc.1
v0.27.1
v0.27.0
v0.27.0-beta.2
v0.27.0-beta.1
v0.26.1
v0.26.0
v0.26.0-beta.2
v0.26.0-beta.1
v0.25.1
v0.25.0
v0.25.0-beta.2
v0.24.3
v0.25.0-beta.1
v0.24.2
v0.24.1
v0.24.0
v0.24.0-beta.2
v0.24.0-beta.1
v0.23.0
v0.23.0-rc.1
v0.23.0-beta.5
v0.23.0-beta.4
v0.23.0-beta3
v0.23.0-beta2
v0.23.0-beta1
v0.23.0-alpha12
v0.23.0-alpha11
v0.23.0-alpha10
v0.23.0-alpha9
v0.23.0-alpha8
v0.23.0-alpha7
v0.23.0-alpha6
v0.23.0-alpha5
v0.23.0-alpha4
v0.23.0-alpha4-docker-ko-test9
v0.23.0-alpha4-docker-ko-test8
v0.23.0-alpha4-docker-ko-test7
v0.23.0-alpha4-docker-ko-test6
v0.23.0-alpha4-docker-ko-test5
v0.23.0-alpha-docker-release-test-debug2
v0.23.0-alpha-docker-release-test-debug
v0.23.0-alpha4-docker-ko-test4
v0.23.0-alpha4-docker-ko-test3
v0.23.0-alpha4-docker-ko-test2
v0.23.0-alpha4-docker-ko-test
v0.23.0-alpha3
v0.23.0-alpha2
v0.23.0-alpha1
v0.22.3
v0.22.2
v0.23.0-alpha-docker-release-test
v0.22.1
v0.22.0
v0.22.0-alpha3
v0.22.0-alpha2
v0.22.0-alpha1
v0.22.0-nfpmtest
v0.21.0
v0.20.0
v0.19.0
v0.19.0-beta2
v0.19.0-beta1
v0.18.0
v0.18.0-beta4
v0.18.0-beta3
v0.18.0-beta2
v0.18.0-beta1
v0.17.1
v0.17.0
v0.17.0-beta5
v0.17.0-beta4
v0.17.0-beta3
v0.17.0-beta2
v0.17.0-beta1
v0.17.0-alpha4
v0.17.0-alpha3
v0.17.0-alpha2
v0.17.0-alpha1
v0.16.4
v0.16.3
v0.16.2
v0.16.1
v0.16.0
v0.16.0-beta7
v0.16.0-beta6
v0.16.0-beta5
v0.16.0-beta4
v0.16.0-beta3
v0.16.0-beta2
v0.16.0-beta1
v0.15.0
v0.15.0-beta6
v0.15.0-beta5
v0.15.0-beta4
v0.15.0-beta3
v0.15.0-beta2
v0.15.0-beta1
v0.14.0
v0.14.0-beta2
v0.14.0-beta1
v0.13.0
v0.13.0-beta3
v0.13.0-beta2
v0.13.0-beta1
upstream/v0.12.4
v0.12.4
v0.12.3
v0.12.2
v0.12.2-beta1
v0.12.1
v0.12.0-beta2
v0.12.0-beta1
v0.11.0
v0.10.8
v0.10.7
v0.10.6
v0.10.5
v0.10.4
v0.10.3
v0.10.2
v0.10.1
v0.10.0
v0.9.3
v0.9.2
v0.9.1
v0.9.0
v0.8.1
v0.8.0
v0.7.1
v0.7.0
v0.6.1
v0.6.0
v0.5.2
v0.5.1
v0.5.0
v0.4.0
v0.3.6
v0.3.5
v0.3.4
v0.3.3
v0.3.2
v0.3.1
v0.3.0
v0.2.2
v0.2.1
v0.2.0
v0.1.1
v0.1.0
Labels
Clear labels
CLI
DERP
DNS
Nix
OIDC
SSH
bug
database
documentation
duplicate
enhancement
faq
good first issue
grants
help wanted
might-come
needs design doc
needs investigation
no-stale-bot
out of scope
performance
policy 📝
pull-request
question
regression
routes
stale
tags
tailscale-feature-gap
well described ❤️
wontfix
Mirrored from GitHub Pull Request
Milestone
No items
No Milestone
Projects
Clear projects
No project
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: starred/headscale#267
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @samson4649 on GitHub (May 12, 2022).
Feature request
Add management of the headscale ACLs via the API. This will allow for ACLs to be updated and current ACLS to be fetched from the headscale instance during runtime.
Aiming to get this started with JSON input and output to start.z
As well as making this a programmable interface for automating ACLs, this will also make integration tests for PR #581 easier to achieve.
@restanrm commented on GitHub (May 14, 2022):
Hello ! I love this idea and also wanted to work on this. I tried to make a proposal doc to describe this feature but didn't release it. As discussed in #492 it's not easy. We want to keep config as code principle as much as possible, but if the ACLs are in DB it's not the case. Also, the API modifying files on system is not ideal and would not work on k8s…
@samson4649 commented on GitHub (Jun 20, 2022):
I've implemented a working update mechanism however im waiting merge for pr #581 (issue #492)
@routerino commented on GitHub (Aug 3, 2022):
Any word on what needs to happen to progress now that 16.0 is out? I'm waiting on API access to progress work on an ACL management interface.
@restanrm commented on GitHub (Aug 8, 2022):
I think the PR #581 is ready to be merged. Someon needs to take the update ACL subject. If I find some time I'll try to tackle it. I still have some issues on the ACL's that I need to handle. Time is hard to find. If someone else want to try on this please do !
@kradalby commented on GitHub (Sep 8, 2022):
While this is making good progress with a proposal, I will push it to 0.19.0 as a target, we have a lot of stuff for 0.17.0 and want to do a code reorg for 0.18.0.
@VaalaCat commented on GitHub (May 20, 2023):
Is there any progress on this?
@kradalby commented on GitHub (May 20, 2023):
There is currently no planned work to implement this.
Might happen in the future, but we have a lot planned for the time being.
@github-actions[bot] commented on GitHub (Nov 17, 2023):
This issue is stale because it has been open for 180 days with no activity.
@github-actions[bot] commented on GitHub (Dec 1, 2023):
This issue was closed because it has been inactive for 14 days since being marked as stale.
@PizzaProgram commented on GitHub (Dec 29, 2023):
At the end did someone merged this?
Or still waiting after 1.5 years?
@samson4649 commented on GitHub (Jan 27, 2024):
Nope.
@pallabpain commented on GitHub (Jan 27, 2024):
I believe we can write a much simpler implementation by following what Tailscale is doing. https://github.com/tailscale/tailscale/blob/main/api.md#policy-file
The APIs can directly deal with the policy JSON structure and expect the user to fetch and modify it. All we will need to do is store is as
jsonbin the DB somewhere and that's it.If no one is working on this, I'd like to give this a try since it'd be a pretty useful feature for many.
@mathmaniac43 commented on GitHub (Feb 20, 2024):
@juanfont I think this issue was automatically closed by the bot by mistake. It seems to me like it should be re-opened since there is still interest in this feature and it looks like @pallabpain wants to take a swing at it. Thanks!
@pallabpain commented on GitHub (Feb 24, 2024):
I have a draft PR out at the moment which only introduces the bare minimum APIs. I'm still working on it at the moment.
https://github.com/juanfont/headscale/pull/1792
While it is rather simple to set and get the policy via the APIs, we currently can load the ACLs using a file. I don't know how to handle both cases where it may be possible to load the ACL from the file, store it in the DB, and serve it to the API consumers. However, changes made to the policy via the APIs may not be written back to the file (if the policy was initially loaded from a file). This will make things inconsistent.
Considering restarts, it may be possible to refer to the policy stored in the db as the source of truth. But let's say the users update the policy file and expect headscale to use that. Then it will again make things inconsistent.
@kradalby What do you think? Does it make sense to have only one way of updating the policy, i.e. via the API?
@PizzaProgram commented on GitHub (Feb 26, 2024):
... some ideas:
1. IMHO it would not be a big problem, if the ACL changes would be accepted only by the API.
acl2024-02-26_112233.oldI know, docker is not officially supported, still many sysadmins are using it.
Editing files inside a docker container is a pain anyway, so it's safer to store in the DB, which would be preserved even if the image gets replaced / updated.
2. Lock
_But in case really considering allowing modifying it via files, HeadScale could:
Store the ACL in a simple JSON file, which would be locked during run
3. In case it would accept a new file edited manually:
There would be an ACL directory, containing 3 files:
Readme_ACL.mdacl.conf.new.sampleacl.conf(Locked)The Readme would explain everything, including how to rename the
.samlefile into:acl.conf.newHS would check for this file once every 10 seconds, or watch for "file-change event" on Linux.
acl.conf.newfile present,acl.conftoacl2024-02-26_112233.oldacl.conf.newtoacl.conf+ Lock it (so it becomes read-only)error2024-02-26_112233.log4. Security / important:
@pallabpain commented on GitHub (Feb 26, 2024):
@PizzaProgram Here's how I have thought about the ACL management, so far:
APIS
The input payload shall be parsed using the existing helper function such that it undergoes the required set of parsing for it to be valid. Only a valid payload will be admitted and it shall overwrite the existing payload. This will ensure that the existing working copy is not corrupted by an invalid payload.
In addition to that, since we are storing it in the DB, we will have access to the
updated_attimestamp.I think we can also incorporate the suggestion of storing the update counter if it'd be helpful.
I think one way to allow file-based configs may be to have commands to get and set the policy which effectively stores it in the DB, thus making the DB the source of truth at all times.
These APIs are very much in-line with the original issue description.
https://github.com/juanfont/headscale/issues/582#issue-1233829545
@PizzaProgram commented on GitHub (Feb 26, 2024):
As far as I can tell, this sounds perfect.
Although I still recommend strongly to:
Keep a previous version of the ACL in DB too !
It would allow to:
There are millions of cases, where something can go wrong. So keeping at least "one backup" would be crucial.
I'm sure these 2 little words could save someone from a disaster, undoing an error with one easy command.
(Imagine a 1000+ client config and 1 tiny typing error, or a wrong API-call miss-click. )
Summarized:
So instead of overwrite, I recommend to simply:
It is nearly the same amount of work, but opens up many possibilities to work with ACLs in a much safer way.
For example:
@kradalby commented on GitHub (Feb 26, 2024):
I think this discussion is going in a generally positive direction, I have not yet had any time to look at the PR, so apologise if this is addressed already, but I would like to add that the current read-from-disk-on-startup behaviour must be preserved. It is a non-negotiable, that does not mean that this feature cannot be added, it just need to find a way to work together with the current behaviour.
@PizzaProgram commented on GitHub (Feb 26, 2024):
I do not think that a Database open / read would affect this in any way at startup.
We are talking about a "secondary" / optional possibility to save/push an ACL config:
instead of just by "virtual / API" payload only.
The config will be loaded from the database during startup. No actual "files" involved.
@pallabpain Am I summarizing it correctly ?
@pallabpain commented on GitHub (Feb 26, 2024):
@kradalby The PR is still a work in progress. However, I intend to reach a point where both read-from-disk and APIs exist at the same time and that reading from disk too updates the ACLs in the database. That should give us a working prototype to discuss further.
The only thing that bothers me is the co-existence of two update mechanisms that might lead to inconsistencies due to either human error or incorrect usage.
Here's what I aim to achieve in the PR:
@PizzaProgram Yes, storing every modification as an entry is something that we can easily achieve. My only concern with such an implementation is what makes a particular config the last working config. Since the last working config is subjective to headscale users' intended usage we are already making sure that the input payloads are at least validated for correctness.
I believe that instead of storing history in the DB, users can employ any means for maintaining histories and versions, Gitops, etc.
What do you think?
@yoshino-s commented on GitHub (Mar 4, 2024):
Maybe add a new configuration like
If
acl_policy_modeisfile, all behaviors will keep same as the old version, and the acl api will be unavailable.If
acl_policy_modeisdb, more new feature can be introduced, including acl api and other cli options?so we can keep the the current read-from-disk-on-startup behaviour and also add what we want now
@pallabpain commented on GitHub (Mar 4, 2024):
@Yoshino-s This can be one way to solve this. We can still let the GET API open which will return the policy. But in
filemode, the PUT API will not set anything.Or we can simply add a disclaimer saying that when there's an ACL file specified in the config, it will override the ACL in the DB on every startup. What do you think?
@yoshino-s commented on GitHub (Mar 4, 2024):
@pallabpain Maybe simply ignoring it is a more logical option for users, thinking about
dbmeans data is from db, so the file is nothing about.I made a draft implement at https://github.com/yoshino-s/headscale . Feel free to use it to merge into your pr, or just do your own :P
@evenh commented on GitHub (Mar 4, 2024):
I think that the proposed
acl_policy_modeshould be respected with regards to the principle of least surprise. Having that befileby default means that one can maintain backwards compatibility.Exposing the current ACL (backed by file or database) in the API and blocking modification when backed by file sounds like a good idea.
@kradalby commented on GitHub (Mar 4, 2024):
I agree with Even on this one, having it go back to file everytime might be quite confusing, a solid toggle doing on or the other makes sense to me.
Making the file available with GET API also sounds reasonable.
@pallabpain commented on GitHub (Mar 4, 2024):
Collecting everyone's inputs,
ACL APIs:
Configuration:
CLI:
@pallabpain commented on GitHub (Mar 5, 2024):
@Yoshino-s @kradalby @evenh I have updated my PR considering the above requirements. Please take a look. Thanks. 🙇🏼
@kradalby commented on GitHub (Mar 6, 2024):
Will take a look tomorrow.
@almereyda commented on GitHub (Mar 26, 2024):
After reviewing the ongoing discussion on #1792, I am left with wondering if the implementation could be (optionally) made wire-compatible with the upstream without too much effort.
gitops-pusher.gohas a client implementation that pushes HuJSON files to upstream and is used in CI for implementing the GitOps pattern.It appears this even accepts a custom
apiServerimplementing the expected endpoints.apiServerflaghttps://%s/api/v2/oauth/tokenapplyNewACLcreating aNewRequestWithContexttohttps://%s/api/v2/tailnet/%s/aclfor a giventailnet, invoked by theapplyfunction.testNewACLstalking to a validation endpoint athttps://%s/api/v2/tailnet/%s/acl/validateapplyfunction also invokesgetACLETag, requested fromGETtingHuJSONfromhttps://%s/api/v2/tailnet/%s/aclWould the
gitops-pushermaybe provide enough documentation of a suitable API surface for more generic upstream compatibility?We would probably only have to agree on a default string for the
tailnetvariable or make it configurable, e.g. ifdns_config.magic_dns: trueis set throughdns_config.base_domain.This compatibility work could also provide the foundation to implementing a more complete set of endpoints from the Tailscale HTTP v2 API, eventually providing OAuth compatibility for fine-grained access control, as suggested in the previously rejected #1202.
@github-actions[bot] commented on GitHub (Aug 8, 2024):
This issue is stale because it has been open for 90 days with no activity.
@github-actions[bot] commented on GitHub (Aug 16, 2024):
This issue was closed because it has been inactive for 14 days since being marked as stale.
@PizzaProgram commented on GitHub (Aug 16, 2024):
Where are we now at this progress?
Can someone please REOPEN this?
@vbrandl commented on GitHub (Aug 16, 2024):
I also have a feeling, the stale bot is doing more harm than good...
@kradalby commented on GitHub (Aug 16, 2024):
I dont think it needs to be reopened, it has been resolved and the code is going into 0.23.0