Conversation
|
|
||
| template<typename T> | ||
| std::optional<T> readOptional(const StoreDirConfig & store, WorkerProto::ReadConn conn) | ||
| { | ||
| auto tag = readNum<uint8_t>(conn.from); | ||
| switch (tag) { | ||
| case 0: | ||
| return std::nullopt; | ||
| case 1: | ||
| return WorkerProto::Serialise<T>::read(store, conn); | ||
| default: | ||
| throw Error("Invalid optional tag from remote"); | ||
| } | ||
| } | ||
|
|
||
|
|
||
| template<typename T> | ||
| void writeOptional(const StoreDirConfig & store, WorkerProto::WriteConn conn, const std::optional<T> & x) | ||
| { | ||
| if (!x.has_value()) { | ||
| conn.to << uint8_t{0}; | ||
| } else { | ||
| conn.to << uint8_t{1}; | ||
| WorkerProto::Serialise<T>::write(store, conn, *x); | ||
| } | ||
| } | ||
|
|
||
|
|
There was a problem hiding this comment.
Looks like you have the same code in serialize.hh?
| template<typename T> | ||
| DECLARE_WORKER_SERIALISER(std::vector<T>); |
There was a problem hiding this comment.
I think you can make a partial template specialization like this for std::optional, and then you won't need the std::optional<auth::AuthData> instance. (Can also turn std::optional<TrustedFlag> into one for just TrustedFlag too.)
I used to have that but I removed it because I only had the special-cases instances at the time, but now we do have a use case for it.
|
Separate from the low level protocol minutiae, I think I've considered solving the same problem in a different way, which is having a user-specific remote builder for fixed output derivations. See #9344 |
|
Client-side building would be great but is a much bigger project (and probably wouldn't work on platforms like macOS). |
|
I don't think it's that big of a project. It's just a client side build + use daemon to add to store. (And the current I think for fixed-output derivations without references it should work on macOS just fine. Since there are no references, there is no need to do fake roots / make |
3487e19 to
703871a
Compare
601d98e to
e1143f1
Compare
Nix can now read authentication data from ~/.local/share/nix/auth/*. The files in that directory have the format: protocol=https host=my-cache.example.org username=alice password=blabla Also, the Nix daemon can now call back to the client to get authentication data from the client (if it's trusted). This makes it possible to have the daemon substitute from an authenticated binary cache, with the authentication coming from the client. Issue NixOS#8635.
This is similar to 'git credential fill', i.e. it tries to fill an authentication request using the configured authentication sources. Mostly useful for testing.
|
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: |
Forwarding can now be disabled entirely, enabled for trusted users, or enabled for all users.
|
Some status updates:
|
|
Some thoughts:
|
|
IMO this goes in the wrong direction. Introduces lots of complexity to the Nix codebase. Instead, I suggest working on making fetchers as a whole pluggable. The complexity around I comment motivated by the exchange in #10567. cc @roberth |
I'm sympathetic to that.
This has security implications; any Nixpkgs package (or otherwise) could then steal credentials, by doing a builtin fetch with a malicious fetching plugin. The beauty of fixed-output derivations is that they sandbox the fetching logic, preventing this. |
| /* Set up authentication tunneling for builtin:fetchurl. FIXME: | ||
| maybe we want to support this for arbitrary fixed-output | ||
| derivations. */ |
There was a problem hiding this comment.
| /* Set up authentication tunneling for builtin:fetchurl. FIXME: | |
| maybe we want to support this for arbitrary fixed-output | |
| derivations. */ | |
| /* Set up authentication tunneling for builtin:fetchurl. | |
| We generally do not want to pass credentials to arbitrary | |
| fixed output derivations, because that makes it possible | |
| for any dependency (however deep down) to steal them. */ |
We'd need to come up with a scheme to safely pass authorization (with letter z) to specific derivations in such a way that the user controls where their credentials go; perhaps through some sort of unforgeable token that's passed around explicitly in expressions? Something for another day.
There was a problem hiding this comment.
OT: notably we can't store the unforgeable token in the drv itself, because that would expose it to be read with readFile foo.drvPath.
This seems to be another instance where we should be tracking transient derivation metadata, just like we should have been doing with meta.timeout or perhaps the licenses.
| [the same protocol as Git's credential | ||
| helpers](https://git-scm.com/docs/gitcredentials#_custom_helpers), |
There was a problem hiding this comment.
| [the same protocol as Git's credential | |
| helpers](https://git-scm.com/docs/gitcredentials#_custom_helpers), | |
| a protocol compatible with that of [Git's credential | |
| helper programs](https://git-scm.com/docs/gitcredentials#_custom_helpers), |
There was a problem hiding this comment.
How are these strings resolved?
Any other differences? This deserves its own page in the protocols sections of the manual.
| a username and password for `cache.example.org`: | ||
|
|
||
| ``` | ||
| # cat <<EOF > ~/.local/share/nix/auth/my-cache |
There was a problem hiding this comment.
What's the relevance of my-cache?
| username=alice | ||
| password=foobar | ||
| EOF | ||
| ``` |
There was a problem hiding this comment.
This should have a page in the config files section of the manual.
| * `false`: Forwarding is disabled. | ||
| * `trusted-users`: Forwarding is only supported for [trusted users](#conf-trusted-users). | ||
| * `all-users`: Forwarding is supported for all users. |
There was a problem hiding this comment.
What happens to the daemon's own config? Is it ignored completely or merged? If so, how?
Thought:
It's unfortunate that we can't seem to just enable this for all users by default. (Or am I wrong to think I shouldn't make myself trusted user? Cachix has certainly normalized it...)
Receiving auth data seems pretty harmless on the face of it, but I suppose attack vectors may involve:
- Implementation errors in our protocol clients
- Bugs in remotes that cause them to misbehave while we trust them
- Remotes that behave differently depending on user name
I wonder if there's any mitigations we could apply? Perhaps a scenario like this:
- a cache
https://fooexists https://foo/nix-cache-infohas a header that declares that its happy-path behavior is not auth-dependent (e.g. doesn't select a cache based on username)nix daemonhastrusted-substituters = https://foo- trusted substituter + header allow credential forwarding
Also the retrieval of content addressed paths seems pretty safe, because misbehaving remotes are not much of an issue.
There was a problem hiding this comment.
Receiving auth data seems pretty harmless on the face of it
Yeah, this is not harmless because we do indeed have substituters that return different data depending on the auth data, e.g. cache.flakehub.com (which is based on Attic) does that.
https://foo/nix-cache-info has a header that declares that its happy-path behavior is not auth-dependent (e.g. doesn't select a cache based on username)
Yeah that sounds like a good idea. Probably for a future PR though. There's a bit of a chicken/egg problem with that since to fetch nix-cache-info, we may already need to know the auth data.
There was a problem hiding this comment.
What happens to the daemon's own config?
The daemon will try its own authentication sources and those forwarded by the client.
| Whether to support pluggable authentication via external credential helpers. | ||
| )", | ||
| .trackingUrl = "https://github.com/NixOS/nix/pull/9857", | ||
| }, |
There was a problem hiding this comment.
It'd be helpful to refer to the options here.
Currently, the worker protocol has a version number that we increment whenever we change something in the protocol. However, this can cause a collision between Nix PRs / forks that make protocol changes (e.g. PR NixOS#9857 increments the version, which could collide with another PR). So instead, the client and daemon now exchange a set of protocol features (such as `auth-forwarding`). They will use the intersection of the sets of features, i.e. the features they both support. Note that protocol features are completely distinct from `ExperimentalFeature`s.
Currently, the worker protocol has a version number that we increment whenever we change something in the protocol. However, this can cause a collision between Nix PRs / forks that make protocol changes (e.g. PR NixOS#9857 increments the version, which could collide with another PR). So instead, the client and daemon now exchange a set of protocol features (such as `auth-forwarding`). They will use the intersection of the sets of features, i.e. the features they both support. Note that protocol features are completely distinct from `ExperimentalFeature`s.
Currently, the worker protocol has a version number that we increment whenever we change something in the protocol. However, this can cause a collision between Nix PRs / forks that make protocol changes (e.g. PR NixOS#9857 increments the version, which could collide with another PR). So instead, the client and daemon now exchange a set of protocol features (such as `auth-forwarding`). They will use the intersection of the sets of features, i.e. the features they both support. Note that protocol features are completely distinct from `ExperimentalFeature`s.
|
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: |
Motivation
This PR makes several improvements to HTTP authentication in Nix:
auth-sourcessetting. For instance, addingextra-auth-sources = git-credential-libsecretallows Nix to obtain usernames/passwords from the KDE/Gnome keyrings.builtin:nixtoauth-sources), which reads usernames/passwords from files in~/.local/share/nix/auth. The advantage over thenetrcauthentication source (now known asbuiltin:netrc) is that it has a file per secret, which makes it easier for scripts/installers to add authentication data.$SSH_ASKPASS) and store this in the configuredauth-sourcesfor future use.--substituters http://my-cache, the daemon will trigger the client to ask the user for the username/password for that cache.builtin:fetchurlrequests authentication from the parent (outside of the sandbox), so e.g.Context
Priorities and Process
Add 👍 to pull requests you find important.
The Nix maintainer team uses a GitHub project board to schedule and track reviews.