Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support private files in the Nix store #8

Open
edolstra opened this issue Apr 23, 2012 · 66 comments
Open

Support private files in the Nix store #8

edolstra opened this issue Apr 23, 2012 · 66 comments
Assignees
Labels

Comments

@edolstra
Copy link
Member

@edolstra edolstra commented Apr 23, 2012

Sometimes it's desirable to have files in the Nix store that are not world-readable, such as configuration files containing passwords. This could be implemented as follows:

  • Private files are marked as such by giving them a certain magic prefix to the name, e.g. p:. When these are registered, Nix should make them readable only to root (permission 0700) and the calling user (using an ACL). (The Nix daemon knows the uid of the caller.)
  • The permissions on a derivation should be propagated to the output paths. Also, private derivations should be run with a umask of 0077.
  • If another user attempts to register an already valid private file, then its uid should be added to the ACL of the file. If it's a derivation, then the uid should also be added to the ACLs of any valid outputs.
  • Store operations that read files from the store (such as exportPath()) should check that the caller is in the ACL of the file.

So, for instance, if the root user builds a NixOS configuration containing some private files, then those files are only readable as root. If Alice builds the same configuration, then those files will be readable by root and Alice. If Alice then uses Charon to copy the configuration to a remote machine (i.e. nix-copy-closure --to root@remote ...), then the files on the remote machine will only be readable by root.

This model only allows files that are private to the instantiating user and root. So it doesn't support specifying a file that is readable only to the sshd user. But that's probably not necessary.

@ghost ghost assigned edolstra Apr 23, 2012
@shlevy
Copy link
Member

@shlevy shlevy commented May 10, 2012

A few questions:

  • Does this potentially break nixos-rebuild build as non-root?
  • Is there any way to tell as a user that I've attempted to register an already-valid file? For example, if root and I both use the same password file for a particular program, will I be able to tell when I add that file to the store that root has the same one?
  • Would there be a reasonable way for a NixOS-managed service to know how to find per-user private files?
@edolstra
Copy link
Member Author

@edolstra edolstra commented May 16, 2012

  • It shouldn't break non-root nixos-rebuilds since any private files would be owned by (or accessible to) the calling user.
  • If a user attempts to register an already-valid file, he would be added to the ACL to the file. So he could conclude from this that root needed the same file.
  • What kind of service, and why would it need to do that?
@viric
Copy link
Member

@viric viric commented May 31, 2012

What about the build users? Should they be in the ACLs?

@chaoflow
Copy link
Member

@chaoflow chaoflow commented Jul 26, 2012

Being able to tell that somebody else generated the same private file sounds like a no-go for me.

What do you think about including the user the file is private to, i.e. the one who created it, to be included in the hashing (for example an empty file with the user's name in the output)? So even if root, Alice and Charon all want a file with the same content, they would end up with 3 different files.

@shlevy
Copy link
Member

@shlevy shlevy commented Jul 26, 2012

The problem with including the user in the hashing is you may eventually share stores, but it's better than nothing. Maybe a wrapper function in nixpkgs that hashed in a GUID read from some personal file? So I have ~/.nixpkgs/guid and when I run pkgs.lib.privateFile 'mypass' "passw0rd" it creates a file whose first line is passw0rd and the second line is the guid?

@edolstra
Copy link
Member Author

@edolstra edolstra commented Jul 26, 2012

Why is this a problem? If the secret stored in the file is sufficiently secure (i.e. random), then this won't happen. I mean, if your login password is "foobar", then other people may be able to find out. So just don't do that.

@shlevy
Copy link
Member

@shlevy shlevy commented Jul 26, 2012

Eh, it's not really a problem, at least not for nix itself. The security-paranoid folk can just make sure all of their private files have some unique identifier included.

@mornfall
Copy link

@mornfall mornfall commented Mar 31, 2013

Unless I am mistaken, private files in the store are sensitive to offline dictionary attacks, since you can learn the hash and you have a procedure to check your guesses. It is also conceivable, that a rainbow attack could be mounted against a particular version of nixpkgs. It would be advisable that any such private files contain significant salting, regardless of the "learn a secret by random collision" problem. A hypothetical lib.privateFile could then enforce that salting by taking a template string and substituting in the salt (which makes it possible to hide that salt in comments or other such convenient places).

@viric
Copy link
Member

@viric viric commented Mar 31, 2013

Yes, the sysadmin could care storing the salt somewhere only readable by the root user.

@domenkozar
Copy link
Member

@domenkozar domenkozar commented May 27, 2013

There is a use case for pkgs.bacula that bacula user needs access to a configuration file with passwords (so non-root).

@MarcWeber
Copy link
Contributor

@MarcWeber MarcWeber commented Nov 30, 2013

Alternative quick & dirty solution which may be useful for some use cases: https://github.com/MarcWeber/nix/blob/experimental/write-file-hashed/.topmsg

@domenkozar
Copy link
Member

@domenkozar domenkozar commented Feb 22, 2014

Better link to see @MarcWeber diff: https://github.com/MarcWeber/nix/compare/experimental;write-file-hashed

What's the current workaround for this if a config file includes a password?

@MarcWeber
Copy link
Contributor

@MarcWeber MarcWeber commented Feb 23, 2014

My version allows storing passwords in config, but instead of writing it to the store a path to a file containing it will be written to the store. The containing file can be read only by root. The complicated piece is that you have to write code which has to be run as root (eg when preparing config files for services) - but its very easy to review (eg in contrast to patching nix store allowing paths to be readable by some users only requires to think about many issues such as copying store paths - preserving privileges thereby etc). State is "I don't use my patch but it should be working".

@edolstra edolstra added bug and removed bug labels Feb 26, 2014
@domenkozar
Copy link
Member

@domenkozar domenkozar commented Mar 9, 2014

What about a function with signature:

pkgs.lib.privateFile "my.conf" "user" "secret content";

And only user would have read permissions to that file? That solves the use cases I've been seeing on daily basis. Many services require to specify an user and thus we can pass that user to privateFile function.

No idea how that would work with nix-copy-closure, but we could just preserve the uid/gid.

@edolstra
Copy link
Member Author

@edolstra edolstra commented Mar 10, 2014

One problem with that is that user may not exist yet, since it might be created at activation time.

However, for the most common case (root), it would be fine. And if the service needs to be readable by a non-root service, you could always copy it to some private location in /run in the service's preStart script.

@domenkozar
Copy link
Member

@domenkozar domenkozar commented Mar 10, 2014

Now that our users require an uid, we could use that instead of the username. That would work then right?

aszlig added a commit to aszlig/nixops that referenced this issue Jun 24, 2014
This however only implements setting permissions if "storeKeysOnMachine" is
set to false right now, because if the value is set to true the keys are
symlinked from the store and we actually have to find a way to control
permisions on it, which for the store is only possible if NixOS/nix#8 is
implemented.

Also, this ensures that the key filename is properly escaped.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
aszlig added a commit to aszlig/nixops that referenced this issue Jul 4, 2014
This however only implements setting permissions if "storeKeysOnMachine" is
set to false right now, because if the value is set to true the keys are
symlinked from the store and we actually have to find a way to control
permisions on it, which for the store is only possible if NixOS/nix#8 is
implemented.

Also, this ensures that the key filename is properly escaped.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
@nbp
Copy link
Member

@nbp nbp commented Oct 18, 2014

@edolstra , with the test cases I made in #329, I am confident that the current proposal is secure enough to handle secret files for the owner of the nix store. When would you be able to review it?

This branch does not use ACL, it only remove the read/execute access for the group and others. Still, the implementation is made such as we can extend it with ACL later. I think it would be good to have a first iteration of NixOS with this branch before adding ACL.

atsukotakahashi pushed a commit to atsukotakahashi/ops that referenced this issue Nov 1, 2014
This however only implements setting permissions if "storeKeysOnMachine" is
set to false right now, because if the value is set to true the keys are
symlinked from the store and we actually have to find a way to control
permisions on it, which for the store is only possible if NixOS/nix#8 is
implemented.

Also, this ensures that the key filename is properly escaped.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
@wmertens
Copy link
Contributor

@wmertens wmertens commented Jan 5, 2015

I just thought of another use-case of @MarcWeber's patch: setuid binaries.

As a reminder, MarcWeber/nix@master...experimental/write-file-hashed shows how nix can write content with special permissions outside of the store. It's a very minimal patch compared to #329. (what it is missing is that the hash needs to include the permissions and ownership as well for security)

Using this, you can either sideload secret files, generated them from an expression or have them be copied on package install from a specific directory under /nix-support.

Files can be secrets or simply regular files that need special permissions, like setuid binaries.

@edolstra @nbp?

@domenkozar
Copy link
Member

@domenkozar domenkozar commented Mar 10, 2015

How can I help make this happen? NixOS is getting used more and more and this may lead to bad PR in the future since it's indeed a big issue (the biggest?).

@lethalman
Copy link
Contributor

@lethalman lethalman commented Mar 10, 2015

Personally I overcome this problem by providing files as strings instead of a nix store path. Yes that means the configuration is not deployable/reproducible, but perhaps I don't want my passwords to be deployable/reproducible?

@wmertens
Copy link
Contributor

@wmertens wmertens commented Mar 11, 2015

@lethalman can you give an example? I don't understand what you're doing when providing a private file as a string.

@7c6f434c
Copy link
Member

@7c6f434c 7c6f434c commented Apr 23, 2018

I wanted to experiment with a non-world-enmuratable Nix store and see if there are any drawbacks/unexpected problems, but apparently the local store constructor enforces the 0o1775 mode (and I wanted to use mainline Nix). Is there a specific well-known reason for that?

aszlig pushed a commit to aszlig/nix that referenced this issue Aug 18, 2018
johnalotoski pushed a commit to input-output-hk/nixops-aws that referenced this issue Jul 12, 2019
This however only implements setting permissions if "storeKeysOnMachine" is
set to false right now, because if the value is set to true the keys are
symlinked from the store and we actually have to find a way to control
permisions on it, which for the store is only possible if NixOS/nix#8 is
implemented.

Also, this ensures that the key filename is properly escaped.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
johnalotoski pushed a commit to input-output-hk/nixops-hetzner that referenced this issue Jul 13, 2019
This however only implements setting permissions if "storeKeysOnMachine" is
set to false right now, because if the value is set to true the keys are
symlinked from the store and we actually have to find a way to control
permisions on it, which for the store is only possible if NixOS/nix#8 is
implemented.

Also, this ensures that the key filename is properly escaped.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
johnalotoski pushed a commit to input-output-hk/nixops-hetzner that referenced this issue Aug 7, 2019
This however only implements setting permissions if "storeKeysOnMachine" is
set to false right now, because if the value is set to true the keys are
symlinked from the store and we actually have to find a way to control
permisions on it, which for the store is only possible if NixOS/nix#8 is
implemented.

Also, this ensures that the key filename is properly escaped.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
johnalotoski pushed a commit to input-output-hk/nixops-aws that referenced this issue Aug 7, 2019
This however only implements setting permissions if "storeKeysOnMachine" is
set to false right now, because if the value is set to true the keys are
symlinked from the store and we actually have to find a way to control
permisions on it, which for the store is only possible if NixOS/nix#8 is
implemented.

Also, this ensures that the key filename is properly escaped.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
@Infinisil Infinisil mentioned this issue Feb 4, 2020
0 of 5 tasks complete
@domenkozar domenkozar removed the triaged label Apr 30, 2020
@veprbl veprbl mentioned this issue May 6, 2020
5 of 10 tasks complete
meditans pushed a commit to Ericson2314/nix that referenced this issue Aug 28, 2020
Add test for fetchTree
@rycee rycee mentioned this issue Aug 29, 2020
6 of 7 tasks complete
edolstra added a commit that referenced this issue Dec 22, 2020
This deadlocks ProgressBar, e.g.

  # nix run --impure --no-substitute --store '/tmp/nix2?store=/foo' --expr 'derivation { builder = /nix/store/zi90rxslsm4mlr46l2xws1rm94g7pk8p-busybox-1.31.1-x86_64-unknown-linux-musl/bin/busybox; }'

leads to

  Thread 1 (Thread 0x7ffff6126e80 (LWP 12250)):
  #0  0x00007ffff7215d62 in __lll_lock_wait () from /nix/store/9df65igwjmf2wbw0gbrrgair6piqjgmi-glibc-2.31/lib/libpthread.so.0
  #1  0x00007ffff720e721 in pthread_mutex_lock () from /nix/store/9df65igwjmf2wbw0gbrrgair6piqjgmi-glibc-2.31/lib/libpthread.so.0
  #2  0x00007ffff7ad17fa in __gthread_mutex_lock (__mutex=0x6c5448) at /nix/store/h31cy7jm6g7cfqbhc5pm4rf9c53i3qfb-gcc-9.3.0/include/c++/9.3.0/x86_64-unknown-linux-gnu/bits/gthr-default.h:749
  #3  std::mutex::lock (this=0x6c5448) at /nix/store/h31cy7jm6g7cfqbhc5pm4rf9c53i3qfb-gcc-9.3.0/include/c++/9.3.0/bits/std_mutex.h:100
  #4  std::unique_lock<std::mutex>::lock (this=0x7fffffff09a8, this=0x7fffffff09a8) at /nix/store/h31cy7jm6g7cfqbhc5pm4rf9c53i3qfb-gcc-9.3.0/include/c++/9.3.0/bits/unique_lock.h:141
  #5  std::unique_lock<std::mutex>::unique_lock (__m=..., this=0x7fffffff09a8) at /nix/store/h31cy7jm6g7cfqbhc5pm4rf9c53i3qfb-gcc-9.3.0/include/c++/9.3.0/bits/unique_lock.h:71
  #6  nix::Sync<nix::ProgressBar::State, std::mutex>::Lock::Lock (s=0x6c5448, this=0x7fffffff09a0) at src/libutil/sync.hh:45
  #7  nix::Sync<nix::ProgressBar::State, std::mutex>::lock (this=0x6c5448) at src/libutil/sync.hh:85
  #8  nix::ProgressBar::logEI (this=0x6c5440, ei=...) at src/libmain/progress-bar.cc:131
  #9  0x00007ffff7608cfd in nix::Logger::logEI (ei=..., lvl=nix::lvlError, this=0x6c5440) at src/libutil/logging.hh:88
  #10 nix::getCodeLines (errPos=...) at src/libutil/error.cc:66
  #11 0x00007ffff76073f2 in nix::showErrorInfo (out=..., einfo=..., showTrace=<optimized out>) at /nix/store/h31cy7jm6g7cfqbhc5pm4rf9c53i3qfb-gcc-9.3.0/include/c++/9.3.0/optional:897
  #12 0x00007ffff7ad19e7 in nix::ProgressBar::logEI (this=0x6c5440, ei=...) at src/libmain/progress-bar.cc:134
  #13 0x00007ffff7ab9d10 in nix::Logger::logEI (ei=..., lvl=nix::lvlError, this=0x6c5440) at src/libutil/logging.hh:88
  #14 nix::handleExceptions(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::function<void ()>) (programName="/home/eelco/Dev/nix/outputs/out/bin/nix", fun=...) at src/libmain/shared.cc:328
  #15 0x000000000046226b in main (argc=<optimized out>, argv=<optimized out>) at /nix/store/h31cy7jm6g7cfqbhc5pm4rf9c53i3qfb-gcc-9.3.0/include/c++/9.3.0/ext/new_allocator.h:80
@ajs124 ajs124 mentioned this issue Feb 8, 2021
@stale
Copy link

@stale stale bot commented Feb 16, 2021

I marked this as stale due to inactivity. → More info

@stale stale bot added stale and removed stale labels Feb 16, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet