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

Provide options for storing secrets outside the Nix store #24288

Open
basvandijk opened this Issue Mar 24, 2017 · 53 comments

Comments

Projects
None yet
@basvandijk
Member

basvandijk commented Mar 24, 2017

Introduction

Dear module authors and maintainers,

We currently have many modules that force users to store their secrets in the world-readble Nix store. This is bad for security. We should give users the option of specifying their secrets in individual files which can be stored outside the Nix store with suitable ownership and permissions. Users could then also use nixops to manage their secret files.

There's still the convenient but unsafe option of storing the secret file in the Nix store using pkgs.writeTextFile. If NixOS/nix#8 gets resolved these files can be encrypted / made private. Also see: NixOS/rfcs#5.

Proposal

The list below contains all the options that force a secret being stored in the Nix store. I propose the following:

  1. Each option should get a warning in the documentation of the form: "Warning: this secret is stored in the world-readable Nix store!"

  2. Each option should get an alternative passwordFile option.

  3. For backwards compatibility the passwordFile option should get a default based on the password option:

{ config = {
    passwordFile = mkDefault (toString (pkgs.writeTextFile {
      name = "password-file";
      text = cfg.password;
    }));
  };
}
  1. Some upstream programs don't support setting a password using a file. In that case an issue should be created in the upstream issue-tracker asking for that feature. (See namecoin/namecoin-core#148 for example). A URL to the issue should be placed in the list below and in the documentation of the password option so that it's easier to track when it gets resolved.

  2. If after some time (lets use September 2017 for now) the upstream developers have not provided the feature to specify the password by file, the NixOS module should be changed such that the config file that contains the password is written to /run before the service starts up. So something like the following:

{
  systemd.services.my-service = {  
    preStart = ''
      cat > /run/my-service/config << EOF
      ...
      password = $(cat "${cfg.passwordFile}")
      ...
      EOF
    '';
    script = "${pkgs.myService}/bin/my-service --config=/run/my-service/config";
  };
}
  1. Lets use this issue for planning and to track progress. Please mention in the comments if you have provided a passwordFile option for one of the options below. Then I check the box to indicate it has been resolved. See PR #24146 for reference.

  2. If we make sure the new options are backwards compatible we could consider cherry-picking them onto release-17.03 making sure users get these security fixes ASAP.

Secret options

This list was compiled by running the following in <nixpkgs> and manually inspecting and processing the result:

find . -type f -exec grep --color -nH -i -E -e '(secret|pass|key)' {} +`
@ip1981

This comment has been minimized.

Show comment
Hide comment
@ip1981

ip1981 Mar 24, 2017

Contributor

FYI, check out how I handle secrets throughout all the apps here: https://github.com/ip1981/nixsap/tree/master/modules/apps

Especially, with Jenkins :)

Contributor

ip1981 commented Mar 24, 2017

FYI, check out how I handle secrets throughout all the apps here: https://github.com/ip1981/nixsap/tree/master/modules/apps

Especially, with Jenkins :)

@teh

This comment has been minimized.

Show comment
Hide comment
@teh

teh Mar 24, 2017

Contributor

I suspect @fpletz is now the maintainer for gitlab (sorry, I see you'r name is in this list a lot!)

Contributor

teh commented Mar 24, 2017

I suspect @fpletz is now the maintainer for gitlab (sorry, I see you'r name is in this list a lot!)

@edolstra

This comment has been minimized.

Show comment
Hide comment
@edolstra

edolstra Mar 24, 2017

Member

Wow, I didn't know the situation was this bad. All of these options should be removed really. It's almost as if people don't realize that the Nix store is world readable...

Member

edolstra commented Mar 24, 2017

Wow, I didn't know the situation was this bad. All of these options should be removed really. It's almost as if people don't realize that the Nix store is world readable...

@jml

This comment has been minimized.

Show comment
Hide comment
@jml

jml Mar 24, 2017

Contributor

@basvandijk — any plan for preventing future changes adding secrets to the Nix store, beyond eternal vigilance?

Contributor

jml commented Mar 24, 2017

@basvandijk — any plan for preventing future changes adding secrets to the Nix store, beyond eternal vigilance?

@Ekleog

This comment has been minimized.

Show comment
Hide comment
@Ekleog

Ekleog Mar 24, 2017

Contributor

Hmm, I didn't re-read NixOS/nix#8 completely, but it seemed to me last time that @edolstra 's solution using encryption in the store and decryption at startup time was working and there was mostly bikeshedding about encryption vs ACLs?

This would be much easier than trying to patch every single upstream program that does not accept password files, especially given that some may not be willing to do it as it adds quite a bit of complexity. Wouldn't it?

Contributor

Ekleog commented Mar 24, 2017

Hmm, I didn't re-read NixOS/nix#8 completely, but it seemed to me last time that @edolstra 's solution using encryption in the store and decryption at startup time was working and there was mostly bikeshedding about encryption vs ACLs?

This would be much easier than trying to patch every single upstream program that does not accept password files, especially given that some may not be willing to do it as it adds quite a bit of complexity. Wouldn't it?

@rnhmjoj

This comment has been minimized.

Show comment
Hide comment
@rnhmjoj

rnhmjoj Mar 24, 2017

Contributor

Besides being quite inconvenient, storing passwords/keys in a file with restricted access outside the store, may not solve the problem: they could end up in a systemd environment file or a unit file if you need to pass those as an command line argument.
Also expecting everyone upstream to comply seems incredibly too optimistic for me.

Contributor

rnhmjoj commented Mar 24, 2017

Besides being quite inconvenient, storing passwords/keys in a file with restricted access outside the store, may not solve the problem: they could end up in a systemd environment file or a unit file if you need to pass those as an command line argument.
Also expecting everyone upstream to comply seems incredibly too optimistic for me.

@basvandijk

This comment has been minimized.

Show comment
Hide comment
@basvandijk

basvandijk Mar 24, 2017

Member

any plan for preventing future changes adding secrets to the Nix store, beyond eternal vigilance?

@jml we could add something to the PULL_REQUEST_TEMPLATE.md instructing contributors to use passwordFile instead of password options.

Member

basvandijk commented Mar 24, 2017

any plan for preventing future changes adding secrets to the Nix store, beyond eternal vigilance?

@jml we could add something to the PULL_REQUEST_TEMPLATE.md instructing contributors to use passwordFile instead of password options.

@basvandijk

This comment has been minimized.

Show comment
Hide comment
@basvandijk

basvandijk Mar 24, 2017

Member

All of these options should be removed really...

@edolstra we could do that eventually but to ease the transition we should first provide a backwards compatible passwordFile option, then in a next release we could start throwing warnings when users use the password option and finally in a third release we can remove the password options.

Member

basvandijk commented Mar 24, 2017

All of these options should be removed really...

@edolstra we could do that eventually but to ease the transition we should first provide a backwards compatible passwordFile option, then in a next release we could start throwing warnings when users use the password option and finally in a third release we can remove the password options.

@basvandijk

This comment has been minimized.

Show comment
Hide comment
@basvandijk

basvandijk Mar 24, 2017

Member

@Ekleog regarding NixOS/nix#8, even if we have the ability to encrypt files in the Nix store I think it would be best to only encrypt files that should be encrypted. Currently we have big config files that somewhere contain a password. It would nicer if the config file remains unencrypted because then it can be shared and it makes debugging easier. Only the password needs to be encrypted. So having passwords in individual files would still be desirable.

Member

basvandijk commented Mar 24, 2017

@Ekleog regarding NixOS/nix#8, even if we have the ability to encrypt files in the Nix store I think it would be best to only encrypt files that should be encrypted. Currently we have big config files that somewhere contain a password. It would nicer if the config file remains unencrypted because then it can be shared and it makes debugging easier. Only the password needs to be encrypted. So having passwords in individual files would still be desirable.

@edolstra

This comment has been minimized.

Show comment
Hide comment
@edolstra

edolstra Mar 24, 2017

Member

@basvandijk The encryption stuff allows you to encrypt only the "secret" parts of a configuration file. See edolstra@4c82120#diff-6c3fcb531890fdce200531b9ac69e4f8R14 for an example.

Member

edolstra commented Mar 24, 2017

@basvandijk The encryption stuff allows you to encrypt only the "secret" parts of a configuration file. See edolstra@4c82120#diff-6c3fcb531890fdce200531b9ac69e4f8R14 for an example.

@rnhmjoj

This comment has been minimized.

Show comment
Hide comment
@rnhmjoj

rnhmjoj Mar 24, 2017

Contributor

@basvandijk Sometimes even the password stored in the configuration file needs to be readable. dnschain, for example, parses namecoin.conf to connect to the rpc server.

Contributor

rnhmjoj commented Mar 24, 2017

@basvandijk Sometimes even the password stored in the configuration file needs to be readable. dnschain, for example, parses namecoin.conf to connect to the rpc server.

@basvandijk

This comment has been minimized.

Show comment
Hide comment
@basvandijk

basvandijk Mar 24, 2017

Member

@rnhmjoj lets see how upstream reacts to a request for a rpcpasswordFile parameter...

Member

basvandijk commented Mar 24, 2017

@rnhmjoj lets see how upstream reacts to a request for a rpcpasswordFile parameter...

@basvandijk

This comment has been minimized.

Show comment
Hide comment
@basvandijk

basvandijk Mar 24, 2017

Member

The encryption stuff allows you to encrypt only the "secret" parts of a configuration file.

@edolstra that's great! What needs to be done to get this merged into Nix?

Member

basvandijk commented Mar 24, 2017

The encryption stuff allows you to encrypt only the "secret" parts of a configuration file.

@edolstra that's great! What needs to be done to get this merged into Nix?

@edolstra

This comment has been minimized.

Show comment
Hide comment
@edolstra

edolstra Mar 24, 2017

Member

Well, it's not clear whether this is the way to go. @kevincox listed the issues here: NixOS/nix#8 (comment)

Member

edolstra commented Mar 24, 2017

Well, it's not clear whether this is the way to go. @kevincox listed the issues here: NixOS/nix#8 (comment)

@basvandijk

This comment has been minimized.

Show comment
Hide comment
@basvandijk

basvandijk Mar 24, 2017

Member

@rnhmjoj regarding namecoind, would cookie based authentication work?

Member

basvandijk commented Mar 24, 2017

@rnhmjoj regarding namecoind, would cookie based authentication work?

@basvandijk

This comment has been minimized.

Show comment
Hide comment
@basvandijk

basvandijk Mar 24, 2017

Member

Besides being quite inconvenient, storing passwords/keys in a file with restricted access outside the store, may not solve the problem: they could end up in a systemd environment file or a unit file if you need to pass those as an command line argument.

@rnhmjoj regarding secrets in systemd unit files, we can always create a wrapper script that cats the password file and passes that on to the original script. I do something similar here.

Member

basvandijk commented Mar 24, 2017

Besides being quite inconvenient, storing passwords/keys in a file with restricted access outside the store, may not solve the problem: they could end up in a systemd environment file or a unit file if you need to pass those as an command line argument.

@rnhmjoj regarding secrets in systemd unit files, we can always create a wrapper script that cats the password file and passes that on to the original script. I do something similar here.

@basvandijk basvandijk changed the title from Provide options of storing secrets outside the Nix store to Provide options for storing secrets outside the Nix store Mar 24, 2017

@mbrgm

This comment has been minimized.

Show comment
Hide comment
@mbrgm

mbrgm Mar 24, 2017

Contributor

@basvandijk Regarding upstream changes for password file options: I think some cat/sed trickery, maybe creating a config file in /run from a template should also do the job for most cases where upstream doesn't have or doesn't want to add a password file, shouldn't it?

Contributor

mbrgm commented Mar 24, 2017

@basvandijk Regarding upstream changes for password file options: I think some cat/sed trickery, maybe creating a config file in /run from a template should also do the job for most cases where upstream doesn't have or doesn't want to add a password file, shouldn't it?

@basvandijk

This comment has been minimized.

Show comment
Hide comment
@basvandijk

basvandijk Mar 25, 2017

Member

@mbrgm sure and we should do that in case upstream doesn't provide a password file option.

Member

basvandijk commented Mar 25, 2017

@mbrgm sure and we should do that in case upstream doesn't provide a password file option.

basvandijk added a commit to LumiGuide/nixpkgs that referenced this issue Mar 25, 2017

ssmtp: use the authPassFile option instead of authPass
This gives users the option of storing the authPass outside the
world-readable Nix store.

Part of: NixOS#24288

basvandijk added a commit to LumiGuide/nixpkgs that referenced this issue Mar 25, 2017

ssmtp: use the authPassFile option instead of authPass
This gives users the option of storing the authPass outside the
world-readable Nix store.

Part of: NixOS#24288
@rasendubi

This comment has been minimized.

Show comment
Hide comment
@rasendubi

rasendubi Mar 25, 2017

Member

@basvandijk I would not tick the package until the PR is merged.

Member

rasendubi commented Mar 25, 2017

@basvandijk I would not tick the package until the PR is merged.

@rnhmjoj

This comment has been minimized.

Show comment
Hide comment
@rnhmjoj

rnhmjoj Mar 25, 2017

Contributor

@basvandijk That seems a valid alternative for authenticating to namecoind however dnschain does not support it, so it would break the service. Anyway, thank you for opening the issue.

Contributor

rnhmjoj commented Mar 25, 2017

@basvandijk That seems a valid alternative for authenticating to namecoind however dnschain does not support it, so it would break the service. Anyway, thank you for opening the issue.

@basvandijk

This comment has been minimized.

Show comment
Hide comment
@basvandijk

basvandijk Mar 25, 2017

Member

I would not tick the package until the PR is merged.

@rasendubi makes sense. I've unticked the wordpress checkbox.

Member

basvandijk commented Mar 25, 2017

I would not tick the package until the PR is merged.

@rasendubi makes sense. I've unticked the wordpress checkbox.

@edwtjo

This comment has been minimized.

Show comment
Hide comment
@edwtjo

edwtjo Mar 25, 2017

Contributor

Well for aiccu; SixXS is closing down its IPv6 tunnel in June so it doesn't seem worth the effort to create a patch for aiccu to support password files. Lets just remove the service in 0606.

Contributor

edwtjo commented Mar 25, 2017

Well for aiccu; SixXS is closing down its IPv6 tunnel in June so it doesn't seem worth the effort to create a patch for aiccu to support password files. Lets just remove the service in 0606.

@zimbatm

This comment has been minimized.

Show comment
Hide comment
@zimbatm

zimbatm Mar 26, 2017

Member

Nix encryption is going to take a while to get there given nix's release history speed. I don't think it should be a blocker for trying alternative implementations.

On the nixpkgs side, the protection would be based on unix file ACL. How about treating secrets like any other state? We could introduce a "mkState" interface that defines any kind of state reference on the filesystem.

let
  postgresState = mkState {
    type = "directory";
    name = "postgres";
    owner = "postgres";
    group = "postgres";
    mode = "0700";
    mustExist = false;
    # run a command if it's missing
    onMissing = "pg_init";
  };
  assert (toString postgresState) == "/var/lib/postgres";
  # mkSecret is a specialization of mkState with a default dir to /run/keys/${name}, mode = 0700 and mustExist = true  
  nginxSecret = mkSecret {
    owner = "nginx";
  };

This would translate to (1) some activation script actions like creating the state dir (2) systemd service to initialize and/or check the secret, which can then be used as a dependency for other services.

I know it's still pretty vague but hopefully enough to convey the idea.

Member

zimbatm commented Mar 26, 2017

Nix encryption is going to take a while to get there given nix's release history speed. I don't think it should be a blocker for trying alternative implementations.

On the nixpkgs side, the protection would be based on unix file ACL. How about treating secrets like any other state? We could introduce a "mkState" interface that defines any kind of state reference on the filesystem.

let
  postgresState = mkState {
    type = "directory";
    name = "postgres";
    owner = "postgres";
    group = "postgres";
    mode = "0700";
    mustExist = false;
    # run a command if it's missing
    onMissing = "pg_init";
  };
  assert (toString postgresState) == "/var/lib/postgres";
  # mkSecret is a specialization of mkState with a default dir to /run/keys/${name}, mode = 0700 and mustExist = true  
  nginxSecret = mkSecret {
    owner = "nginx";
  };

This would translate to (1) some activation script actions like creating the state dir (2) systemd service to initialize and/or check the secret, which can then be used as a dependency for other services.

I know it's still pretty vague but hopefully enough to convey the idea.

@moretea

This comment has been minimized.

Show comment
Hide comment
@moretea

moretea Mar 26, 2017

Contributor

@zimbatm that would be quite interesting. Especially how that could work together with NixOps.

We'd need:

  1. Generic mechanism to facilitate generating secrets .
  2. A way to expose how a secret must be created from a service.
  3. Make it possible for NixOps to manage those secrets (generating them on the deploying machine, then storing them in the statefile and on the necessary machines).

Your mkSecret function could be extended to take a nixpkgs provided method or generic command.

{  
  s1 = mkSecret {  owner = "nginx"; method = "sha256"; };
  secretGeneratorProgram = stdenv.mkDerivation { /* ... */ };
  s2 = mkSecret { owner = "nginx"; command = "${secretGeneratorProgram}/bin/gen > $out"; };
}
Contributor

moretea commented Mar 26, 2017

@zimbatm that would be quite interesting. Especially how that could work together with NixOps.

We'd need:

  1. Generic mechanism to facilitate generating secrets .
  2. A way to expose how a secret must be created from a service.
  3. Make it possible for NixOps to manage those secrets (generating them on the deploying machine, then storing them in the statefile and on the necessary machines).

Your mkSecret function could be extended to take a nixpkgs provided method or generic command.

{  
  s1 = mkSecret {  owner = "nginx"; method = "sha256"; };
  secretGeneratorProgram = stdenv.mkDerivation { /* ... */ };
  s2 = mkSecret { owner = "nginx"; command = "${secretGeneratorProgram}/bin/gen > $out"; };
}

rvl added a commit to rvl/nixpkgs that referenced this issue Mar 26, 2017

longview service: don't write passwords to nix store
Adds services.longview.{apiKeyFile,mysqlPasswordFile} options as
alternatives to apiKey and mysqlPassword, which still work, but are
deprecated with a warning message.

Related to #24288.
@joepie91

This comment has been minimized.

Show comment
Hide comment
@joepie91

joepie91 Apr 12, 2017

Contributor

Relevant nixops thread: NixOS/nixops#627

Contributor

joepie91 commented Apr 12, 2017

Relevant nixops thread: NixOS/nixops#627

@rvl

This comment has been minimized.

Show comment
Hide comment
@rvl

rvl Apr 22, 2017

Contributor
  1. Would anyone like to review my module PR #24366.
  2. If anyone has a module listed here and no time to fix it, I could do a couple.
Contributor

rvl commented Apr 22, 2017

  1. Would anyone like to review my module PR #24366.
  2. If anyone has a module listed here and no time to fix it, I could do a couple.
@basvandijk

This comment has been minimized.

Show comment
Hide comment
@basvandijk

basvandijk Apr 22, 2017

Member
  1. Would anyone like to review my module PR #24366.

LGTM (but I haven't tested it).

  1. If anyone has a module listed here and no time to fix it, I could do a couple.

That would be much appreciated. Thanks @rvl!

Member

basvandijk commented Apr 22, 2017

  1. Would anyone like to review my module PR #24366.

LGTM (but I haven't tested it).

  1. If anyone has a module listed here and no time to fix it, I could do a couple.

That would be much appreciated. Thanks @rvl!

@schneefux

This comment has been minimized.

Show comment
Hide comment
@schneefux

schneefux Apr 22, 2017

Contributor

If anyone has a module listed here and no time to fix it, I could do a couple.

Can you take a look at gogs' database configuration? Thanks 😃

Contributor

schneefux commented Apr 22, 2017

If anyone has a module listed here and no time to fix it, I could do a couple.

Can you take a look at gogs' database configuration? Thanks 😃

rvl added a commit to rvl/nixpkgs that referenced this issue Apr 22, 2017

@rvl rvl referenced this issue Apr 22, 2017

Merged

Gogs service password handling improvements #25116

5 of 6 tasks complete

schneefux added a commit to schneefux/nixpkgs that referenced this issue Oct 22, 2017

@domenkozar

This comment has been minimized.

Show comment
Hide comment
@domenkozar

domenkozar Nov 15, 2017

Member

@basvandijk in your 5 you have:

$(cat "${cfg.passwordFile}")

if cfg.passwordFile type is set to types.path and someone specifies a path instead of string, it would still get pulled into nix store.

I propose we create a type called types.nonStorePath that can be set to path or string, but the resolved value would be a string that's not in nix store.

Member

domenkozar commented Nov 15, 2017

@basvandijk in your 5 you have:

$(cat "${cfg.passwordFile}")

if cfg.passwordFile type is set to types.path and someone specifies a path instead of string, it would still get pulled into nix store.

I propose we create a type called types.nonStorePath that can be set to path or string, but the resolved value would be a string that's not in nix store.

@mbrgm

This comment has been minimized.

Show comment
Hide comment
@mbrgm

mbrgm Nov 15, 2017

Contributor

I propose we create a type called types.nonStorePath that can be set to path or string, but the resolved value would be a string that's not in nix store.

I like that idea. Sounds pragmatic and easy to understand (don't know about the implementation part though). Anyway, I think any solution to the problem would be welcome to most people. Imho secret management is one of NixOS' major weaknesses in practice.

Contributor

mbrgm commented Nov 15, 2017

I propose we create a type called types.nonStorePath that can be set to path or string, but the resolved value would be a string that's not in nix store.

I like that idea. Sounds pragmatic and easy to understand (don't know about the implementation part though). Anyway, I think any solution to the problem would be welcome to most people. Imho secret management is one of NixOS' major weaknesses in practice.

@domenkozar

This comment has been minimized.

Show comment
Hide comment
@domenkozar

domenkozar Nov 15, 2017

Member

Groundwork is in #31715

Member

domenkozar commented Nov 15, 2017

Groundwork is in #31715

@domenkozar

This comment has been minimized.

Show comment
Hide comment
@domenkozar

domenkozar Nov 15, 2017

Member

Implementation shouldn't be too difficult. I think we should have three types:

  • path: any kind of absolute path
  • nonStorePath: path that must NOT be in nix store
  • storePath: path that must be in nix store

Note: types.package means a derivation path, but not a path within it.

Member

domenkozar commented Nov 15, 2017

Implementation shouldn't be too difficult. I think we should have three types:

  • path: any kind of absolute path
  • nonStorePath: path that must NOT be in nix store
  • storePath: path that must be in nix store

Note: types.package means a derivation path, but not a path within it.

@CMCDragonkai

This comment has been minimized.

Show comment
Hide comment
@CMCDragonkai

CMCDragonkai Nov 16, 2017

Contributor

Suppose there are secrets that are only needed during the evaluation of configuration.nix (such as secrets required to download a particular package or install a particular package), then this can be done by passing in variables during invocation. Then there are secrets that are needed all the time by the services (and these have to be the plain text secret), then this would mean that these secrets exist as plain text on the filesystem. Is there a solution that allows the secrets to still be encrypted on disk, while the nixos system can still access them only when needed (possibly decrypting on the fly with an in-memory key).

Contributor

CMCDragonkai commented Nov 16, 2017

Suppose there are secrets that are only needed during the evaluation of configuration.nix (such as secrets required to download a particular package or install a particular package), then this can be done by passing in variables during invocation. Then there are secrets that are needed all the time by the services (and these have to be the plain text secret), then this would mean that these secrets exist as plain text on the filesystem. Is there a solution that allows the secrets to still be encrypted on disk, while the nixos system can still access them only when needed (possibly decrypting on the fly with an in-memory key).

@basvandijk

This comment has been minimized.

Show comment
Hide comment
@basvandijk

basvandijk Nov 16, 2017

Member

@domenkozar I like having those types.

However, setting the type of passwordFile to nonStorePath does mean we can't have backwards compatibility as described in point 3.

Member

basvandijk commented Nov 16, 2017

@domenkozar I like having those types.

However, setting the type of passwordFile to nonStorePath does mean we can't have backwards compatibility as described in point 3.

@Profpatsch

This comment has been minimized.

Show comment
Hide comment
@Profpatsch

Profpatsch Nov 16, 2017

Member

However, setting the type of passwordFile to nonStorePath does mean we can't have backwards compatibility as described in point 3.

How about just breaking it? As long as it’s not causing stuff to fail silently, that should be very much appropriate for a bad security issue like passwords in the store.
For stable users this will hit in the next release with a big notice. Unstable users will have to adjust, but that’s what they’re in for.

Member

Profpatsch commented Nov 16, 2017

However, setting the type of passwordFile to nonStorePath does mean we can't have backwards compatibility as described in point 3.

How about just breaking it? As long as it’s not causing stuff to fail silently, that should be very much appropriate for a bad security issue like passwords in the store.
For stable users this will hit in the next release with a big notice. Unstable users will have to adjust, but that’s what they’re in for.

@domenkozar

This comment has been minimized.

Show comment
Hide comment
@domenkozar

domenkozar Nov 16, 2017

Member

@basvandijk I think for sake of security we can change it to path and it will report an error. It will force the user to rethink how to set the passwords, which is a good thing.

Member

domenkozar commented Nov 16, 2017

@basvandijk I think for sake of security we can change it to path and it will report an error. It will force the user to rethink how to set the passwords, which is a good thing.

schneefux added a commit to schneefux/nixpkgs that referenced this issue Jan 4, 2018

schneefux added a commit to schneefux/nixpkgs that referenced this issue Jan 4, 2018

@volth

This comment has been minimized.

Show comment
Hide comment
@volth

volth Mar 21, 2018

Contributor

What about keeping secrets in world-readable nix-store - it simplifies build and deploy - but encrypt them with something like cryfs so the secrets to be encrypted on all the intermediate stages (and also exposed by nix-serve in encrypted form) ?

The decryption could be done using sshd hostkey (or yubikey/nitrokey where available, TPM on Lenovo Thinkpads, ...), which is generated on the target machine and the private part never leaves the machine, while the public key is known to the builders.

Contributor

volth commented Mar 21, 2018

What about keeping secrets in world-readable nix-store - it simplifies build and deploy - but encrypt them with something like cryfs so the secrets to be encrypted on all the intermediate stages (and also exposed by nix-serve in encrypted form) ?

The decryption could be done using sshd hostkey (or yubikey/nitrokey where available, TPM on Lenovo Thinkpads, ...), which is generated on the target machine and the private part never leaves the machine, while the public key is known to the builders.

@ip1981

This comment has been minimized.

Show comment
Hide comment
@ip1981

ip1981 Mar 21, 2018

Contributor

Software already sucks too much :) IOW, let's keep it simple. You need a key somewhere anyway outside the Nix store.

Contributor

ip1981 commented Mar 21, 2018

Software already sucks too much :) IOW, let's keep it simple. You need a key somewhere anyway outside the Nix store.

@mguentner

This comment has been minimized.

Show comment
Hide comment
@mguentner

mguentner Mar 21, 2018

Contributor

@volth

"We can solve any problem by introducing an extra level of indirection." -- Andrew Koenig

I am reminding people discussing this issue to reflect and meditate on the root issue that is causing this problem/concern. Encryption should not be used for fixing architectural flaws.

What are the assumptions of the nix store? What additional assumption should there be?
Please read my original rant on this topic.

Contributor

mguentner commented Mar 21, 2018

@volth

"We can solve any problem by introducing an extra level of indirection." -- Andrew Koenig

I am reminding people discussing this issue to reflect and meditate on the root issue that is causing this problem/concern. Encryption should not be used for fixing architectural flaws.

What are the assumptions of the nix store? What additional assumption should there be?
Please read my original rant on this topic.

@volth

This comment has been minimized.

Show comment
Hide comment
@volth

volth Mar 21, 2018

Contributor

My problem with secrets in nix store is a bit different - I am worrying about secrets of many machines are visible on the builders and also exposed to the public on my alternative to cache.nixos.org.

From another side - it is much convenient to deploy the secrets with the usual deployment machinery (nix-copy-closure) than to copy them into /run afterwards.

Contributor

volth commented Mar 21, 2018

My problem with secrets in nix store is a bit different - I am worrying about secrets of many machines are visible on the builders and also exposed to the public on my alternative to cache.nixos.org.

From another side - it is much convenient to deploy the secrets with the usual deployment machinery (nix-copy-closure) than to copy them into /run afterwards.

@ip1981

This comment has been minimized.

Show comment
Hide comment
@ip1981

ip1981 Mar 21, 2018

Contributor

How is storing secrets in the nix store different from hardcoding them into the binary? Or a library used by the binary? No difference to me.

Contributor

ip1981 commented Mar 21, 2018

How is storing secrets in the nix store different from hardcoding them into the binary? Or a library used by the binary? No difference to me.

@volth

This comment has been minimized.

Show comment
Hide comment
@volth

volth Mar 21, 2018

Contributor

How is storing secrets in the nix store different from hardcoding them into the binary? Or a library used by the binary? No difference to me.

Exactly. If the binary stored in the nix store :)

There is the second part - the private key which:

  1. is not in the nix store, but in /etc/sshd/ (or on a hardware token)
  2. is not part of any deployment, not the current one nor any deployment in the past. The keypair is generated on the target machine and public key is copied back or just published somewhere.
  3. will be needed to decrypt the secret stored in the nix store (embedded in the binary or as a separate file, this does not matter)

So copy of the nix store (or the whole cache) would not expose secrets; At the same time the new secrets could be deployed simple with nix-copy-closure

Contributor

volth commented Mar 21, 2018

How is storing secrets in the nix store different from hardcoding them into the binary? Or a library used by the binary? No difference to me.

Exactly. If the binary stored in the nix store :)

There is the second part - the private key which:

  1. is not in the nix store, but in /etc/sshd/ (or on a hardware token)
  2. is not part of any deployment, not the current one nor any deployment in the past. The keypair is generated on the target machine and public key is copied back or just published somewhere.
  3. will be needed to decrypt the secret stored in the nix store (embedded in the binary or as a separate file, this does not matter)

So copy of the nix store (or the whole cache) would not expose secrets; At the same time the new secrets could be deployed simple with nix-copy-closure

@mguentner

This comment has been minimized.

Show comment
Hide comment
@mguentner

mguentner Mar 21, 2018

Contributor

@volth Your problem is just a different manifestation of an architectural flaw.

I solution I came up with:
The /nix/store of an OS using Nix (e.g. NixOS) could check if the file / path requested is allowed for the caller environment, container or user. The store would be mounted using e.g. fuse or a custom kernel module which communicates with the nix daemon.
This would fix the information leak once an for all. Of course, a binary cache would still serve your plaintext files.

To supply secrets to a machine, I think that the method nixops send-keys demonstrates is perfect for online machines (VPS, Server etc.). For offsite, embedded, "install and forget" machines this could also be made permanent by doing scp -R secrets_of_machine machine:/etc/secrets and then on the machine creating a bootup systemd unit with cp -r /etc/secrets/ /run

Contributor

mguentner commented Mar 21, 2018

@volth Your problem is just a different manifestation of an architectural flaw.

I solution I came up with:
The /nix/store of an OS using Nix (e.g. NixOS) could check if the file / path requested is allowed for the caller environment, container or user. The store would be mounted using e.g. fuse or a custom kernel module which communicates with the nix daemon.
This would fix the information leak once an for all. Of course, a binary cache would still serve your plaintext files.

To supply secrets to a machine, I think that the method nixops send-keys demonstrates is perfect for online machines (VPS, Server etc.). For offsite, embedded, "install and forget" machines this could also be made permanent by doing scp -R secrets_of_machine machine:/etc/secrets and then on the machine creating a bootup systemd unit with cp -r /etc/secrets/ /run

@edolstra

This comment has been minimized.

Show comment
Hide comment
@edolstra

edolstra Mar 21, 2018

Member

@volth Regarding encryption, see NixOS/rfcs#5.

Member

edolstra commented Mar 21, 2018

@volth Regarding encryption, see NixOS/rfcs#5.

@Profpatsch

This comment has been minimized.

Show comment
Hide comment
@Profpatsch

Profpatsch Mar 21, 2018

Member

@volth @mguentner Another possible solution is to write configs with “holes”, by writing a template with interpolated variables where the passwords should be, e.g. in https://dhall-lang.org. Then you have a principled way to “fill in the holes” before giving the config to a process.

Member

Profpatsch commented Mar 21, 2018

@volth @mguentner Another possible solution is to write configs with “holes”, by writing a template with interpolated variables where the passwords should be, e.g. in https://dhall-lang.org. Then you have a principled way to “fill in the holes” before giving the config to a process.

@zimbatm

This comment has been minimized.

Show comment
Hide comment
@zimbatm

zimbatm Mar 21, 2018

Member

Secrets are traditionally very static and it's easy to think that they are configuration. I would like to argue that they should be treated as state instead.

Ideally we want to be in a place where they can be rotated dynamically with for example HashiCorp Vault. When there is a breach we want to be able to quickly rotate the keys. And during the investigation is helps if each machine has a unique key to figure out where the attack was coming from. It also discourages having the secrets stored in git since they are comming from another place. The nixops user should only have one secret, how to access HashiCorp Vault (and maybe a SSH key).

In that regard I think this initiative makes sense. Encourage upstream to provide paths to secrets instead of embedding them in configuration. And when not possible, generate the config at runtime with a template. At some point we'll figure out how to source those secrets from other places than the filesystem.

Member

zimbatm commented Mar 21, 2018

Secrets are traditionally very static and it's easy to think that they are configuration. I would like to argue that they should be treated as state instead.

Ideally we want to be in a place where they can be rotated dynamically with for example HashiCorp Vault. When there is a breach we want to be able to quickly rotate the keys. And during the investigation is helps if each machine has a unique key to figure out where the attack was coming from. It also discourages having the secrets stored in git since they are comming from another place. The nixops user should only have one secret, how to access HashiCorp Vault (and maybe a SSH key).

In that regard I think this initiative makes sense. Encourage upstream to provide paths to secrets instead of embedding them in configuration. And when not possible, generate the config at runtime with a template. At some point we'll figure out how to source those secrets from other places than the filesystem.

@Shados

This comment has been minimized.

Show comment
Hide comment
@Shados

Shados Mar 23, 2018

Contributor

@Profpatsch @zimbatm not all secrets are configuration and state, however. You may not want to have your system-wide config be effectively traceable by everyone -- security through obscurity does not do any good on its own, but that doesn't mean it isn't useful. You may very well want to keep source files or actual package derivations hidden from most users in a mixed public/private environment, if they are proprietary in nature.

Nix is based on the idea of 'deployment as memory management', but it is memory management as seen purely from a language or application perspective, with nothing from an OS perspective, where isolation and protection are the norm. This is perhaps an oversight.

Contributor

Shados commented Mar 23, 2018

@Profpatsch @zimbatm not all secrets are configuration and state, however. You may not want to have your system-wide config be effectively traceable by everyone -- security through obscurity does not do any good on its own, but that doesn't mean it isn't useful. You may very well want to keep source files or actual package derivations hidden from most users in a mixed public/private environment, if they are proprietary in nature.

Nix is based on the idea of 'deployment as memory management', but it is memory management as seen purely from a language or application perspective, with nothing from an OS perspective, where isolation and protection are the norm. This is perhaps an oversight.

@7c6f434c

This comment has been minimized.

Show comment
Hide comment
@7c6f434c

7c6f434c Mar 23, 2018

Member

@Shados maybe your case is better handled by running different things in different namespaces with only the allowed paths bind-mounted from the global store. In the OS RAM management terms, let the main store be like physical RAM and give the programs page tables according to their needs/access level.

Member

7c6f434c commented Mar 23, 2018

@Shados maybe your case is better handled by running different things in different namespaces with only the allowed paths bind-mounted from the global store. In the OS RAM management terms, let the main store be like physical RAM and give the programs page tables according to their needs/access level.

@zimbatm

This comment has been minimized.

Show comment
Hide comment
@zimbatm

zimbatm Mar 23, 2018

Member

@Shados these approaches are not mutually exclusive, even if paths are configurable it's still possible to point into the /nix/store. The difference is that path extractions is something we can do today without any changes to the nix language or runtime.

In Nix 2.0 and Linux it's also possible to maintain your own private nix store by passing the --store ~/your-store.

Member

zimbatm commented Mar 23, 2018

@Shados these approaches are not mutually exclusive, even if paths are configurable it's still possible to point into the /nix/store. The difference is that path extractions is something we can do today without any changes to the nix language or runtime.

In Nix 2.0 and Linux it's also possible to maintain your own private nix store by passing the --store ~/your-store.

gnidorah added a commit to gnidorah/nixpkgs that referenced this issue Mar 27, 2018

gnidorah added a commit to gnidorah/nixpkgs that referenced this issue Mar 27, 2018

gnidorah added a commit to gnidorah/nixpkgs that referenced this issue Mar 27, 2018

typetetris added a commit to typetetris/nixpkgs that referenced this issue Apr 23, 2018

typetetris added a commit to typetetris/nixpkgs that referenced this issue Apr 23, 2018

@Mic92 Mic92 referenced this issue May 20, 2018

Merged

meguca: init at 2018-05-17 #39482

6 of 8 tasks complete
@CMCDragonkai

This comment has been minimized.

Show comment
Hide comment
@CMCDragonkai

CMCDragonkai Jul 13, 2018

Contributor

@zimbatm About your last comment about nix 2.0, can you provide an example of how you use that to manage secrets from a private nix store?

Contributor

CMCDragonkai commented Jul 13, 2018

@zimbatm About your last comment about nix 2.0, can you provide an example of how you use that to manage secrets from a private nix store?

@ob7

This comment has been minimized.

Show comment
Hide comment
@ob7

ob7 Jul 13, 2018

So if someone puts a password in plain text in a .nix file, that password gets uploaded to somewhere online that could be accessed by anyone?

ob7 commented Jul 13, 2018

So if someone puts a password in plain text in a .nix file, that password gets uploaded to somewhere online that could be accessed by anyone?

@srhb

This comment has been minimized.

Show comment
Hide comment
@srhb

srhb Jul 13, 2018

Contributor

@ob7 "World readable" in this sense means that any user on your system can read the file. It does not mean that files included in the nix store are somehow uploaded elsewhere.

Contributor

srhb commented Jul 13, 2018

@ob7 "World readable" in this sense means that any user on your system can read the file. It does not mean that files included in the nix store are somehow uploaded elsewhere.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment