diff --git a/doc/manual/nixops.xml b/doc/manual/nixops.xml
index 75d03a431..5467b1045 100644
--- a/doc/manual/nixops.xml
+++ b/doc/manual/nixops.xml
@@ -1943,7 +1943,7 @@ input. See nixops export for examples.
Description
This command uploads the keys described in deployment.keys
- to remote machines in the /run/keys/ directory.
+ to remote machines in the /etc/nixops-keys/ directory.
Keys are not persisted across reboots by default.
diff --git a/doc/manual/overview.xml b/doc/manual/overview.xml
index 5170aad7c..c4574eb3e 100644
--- a/doc/manual/overview.xml
+++ b/doc/manual/overview.xml
@@ -1747,7 +1747,7 @@ deploy the new configuration.
}
- This will create a file /run/keys/my-secret
+ This will create a file /etc/nixops-keys/my-secret
with the specified contents, ownership, and permissions.
@@ -1786,7 +1786,7 @@ deploy the new configuration.
after = [ "my-secret-key.service" ];
wants = [ "my-secret-key.service" ];
script = ''
- export MY_SECRET=$(cat /run/keys/my-secret)
+ export MY_SECRET=$(cat /etc/nixops-keys/my-secret)
run-my-program
'';
};
diff --git a/nix/keys.nix b/nix/keys.nix
index b6a1e6b7e..d53a46918 100644
--- a/nix/keys.nix
+++ b/nix/keys.nix
@@ -11,7 +11,7 @@ let
The text the key should contain. So if the key name is
password and foobar
is set here, the contents of the file
- /run/keys/password
+ /etc/nixops-keys/password
will be foobar.
'';
};
@@ -62,6 +62,7 @@ let
inherit (keyOptionsType) getSubOptions;
};
+ keyDir = if config.deployment.storeKeysOnMachine then "/var/keys" else "/run/keys";
in
{
@@ -93,11 +94,11 @@ in
description = ''
The set of keys to be deployed to the machine. Each attribute
maps a key name to a file that can be accessed as
- /run/keys/name.
+ /etc/nixops-keys/name.
Thus, { password.text = "foobar"; } causes a
- file /run/keys/password to be created
+ file /etc/nixops-keys/password to be created
with contents foobar. The directory
- /run/keys is only accessible to root and
+ /etc/nixops-keys is only accessible to root and
the keys group, so keep in mind to add any
users that need to have access to a particular key to this group.
@@ -115,38 +116,17 @@ in
config = {
- warnings = mkIf config.deployment.storeKeysOnMachine [(
- "The use of `deployment.storeKeysOnMachine' imposes a security risk " +
- "because all keys will be put in the Nix store and thus are world-" +
- "readable. Also, this will have an impact on services like OpenSSH, " +
- "which require strict permissions to be set on key files, so expect " +
- "things to break."
- )];
-
system.activationScripts.nixops-keys = stringAfter [ "users" "groups" ]
''
- mkdir -p /run/keys -m 0750
- chown root:keys /run/keys
-
- ${optionalString config.deployment.storeKeysOnMachine
- (concatStrings (mapAttrsToList (name: value:
- let
- # FIXME: The key file should be marked as private once
- # https://github.com/NixOS/nix/issues/8 is fixed.
- keyFile = pkgs.writeText name value.text;
- in "ln -sfn ${keyFile} /run/keys/${name}\n")
- config.deployment.keys)
- + ''
- # FIXME: delete obsolete keys?
- touch /run/keys/done
- '')
- }
+ mkdir -p ${keyDir} -m 0750
+ chown root:keys ${keyDir}
+ ln -sfn ${keyDir} /etc/nixops-keys
${concatStringsSep "\n" (flip mapAttrsToList config.deployment.keys (name: value:
# Make sure each key has correct ownership, since the configured owning
# user or group may not have existed when first uploaded.
''
- [[ -f "/run/keys/${name}" ]] && chown '${value.user}:${value.group}' "/run/keys/${name}"
+ [[ -f "${keyDir}/${name}" ]] && chown '${value.user}:${value.group}' "${keyDir}/${name}"
''
))}
'';
@@ -162,7 +142,7 @@ in
serviceConfig.RemainAfterExit = true;
script =
''
- while ! [ -e /run/keys/done ]; do
+ while ! [ -e ${keyDir}/done ]; do
sleep 0.1
done
'';
@@ -178,9 +158,9 @@ in
path = [ pkgs.inotifyTools ];
preStart = ''
(while read f; do if [ "$f" = "${name}" ]; then break; fi; done \
- < <(inotifywait -qm --format '%f' -e create /run/keys) ) &
+ < <(inotifywait -qm --format '%f' -e create ${keyDir}) ) &
- if [[ -e "/run/keys/${name}" ]]; then
+ if [[ -e "${keyDir}/${name}" ]]; then
echo 'flapped down'
kill %1
exit 0
@@ -188,9 +168,9 @@ in
wait %1
'';
script = ''
- inotifywait -qq -e delete_self "/run/keys/${name}" &
+ inotifywait -qq -e delete_self "${keyDir}/${name}" &
- if [[ ! -e "/run/keys/${name}" ]]; then
+ if [[ ! -e "${keyDir}/${name}" ]]; then
echo 'flapped up'
exit 0
fi
diff --git a/nixops/backends/__init__.py b/nixops/backends/__init__.py
index 193bd7e8a..f2e08d9b4 100644
--- a/nixops/backends/__init__.py
+++ b/nixops/backends/__init__.py
@@ -199,6 +199,10 @@ def reboot_rescue(self, hard=False):
self.warn("machine ‘{0}’ doesn't have a rescue"
" system.".format(self.name))
+ @property
+ def key_dir(self):
+ return "/var/keys" if self.store_keys_on_machine else "/run/keys"
+
def send_keys(self):
if self.state == self.RESCUE:
# Don't send keys when in RESCUE state, because we're most likely
@@ -206,14 +210,13 @@ def send_keys(self):
# so keys will probably end up being written to DISK instead of
# into memory.
return
- if self.store_keys_on_machine: return
- self.run_command("mkdir -m 0750 -p /run/keys"
- " && chown root:keys /run/keys")
+ key_dir = self.key_dir
+ self.run_command("mkdir -pm 0750 {0} && chown root:keys {0}".format(key_dir))
for k, opts in self.get_keys().items():
self.log("uploading key ‘{0}’...".format(k))
tmp = self.depl.tempdir + "/key-" + self.name
f = open(tmp, "w+"); f.write(opts['text']); f.close()
- outfile = "/run/keys/" + k
+ outfile = os.path.join(key_dir, k)
outfile_esc = "'" + outfile.replace("'", r"'\''") + "'"
self.run_command("rm -f " + outfile_esc)
self.upload_file(tmp, outfile)
@@ -237,7 +240,7 @@ def send_keys(self):
)
)
os.remove(tmp)
- self.run_command("touch /run/keys/done")
+ self.run_command("touch {}/done".format(key_dir))
def get_keys(self):
return self.keys
diff --git a/tests/functional/single_machine_secret_key.nix b/tests/functional/single_machine_secret_key_disk.nix
similarity index 100%
rename from tests/functional/single_machine_secret_key.nix
rename to tests/functional/single_machine_secret_key_disk.nix
diff --git a/tests/functional/single_machine_secret_key_ram.nix b/tests/functional/single_machine_secret_key_ram.nix
new file mode 100644
index 000000000..6f0bfc722
--- /dev/null
+++ b/tests/functional/single_machine_secret_key_ram.nix
@@ -0,0 +1,7 @@
+{
+ machine.deployment = {
+ storeKeysOnMachine = false;
+
+ keys."secret.key" = "12345";
+ };
+}
diff --git a/tests/functional/test_send_keys_sends_keys.py b/tests/functional/test_send_keys_sends_keys.py
index 53d2a1f6c..89daa4950 100644
--- a/tests/functional/test_send_keys_sends_keys.py
+++ b/tests/functional/test_send_keys_sends_keys.py
@@ -5,18 +5,29 @@
parent_dir = path.dirname(__file__)
-secret_key_spec = '%s/single_machine_secret_key.nix' % (parent_dir)
+secret_key_ram_spec = '%s/single_machine_secret_key_ram.nix' % (parent_dir)
+secret_key_disk_spec = '%s/single_machine_secret_key_disk.nix' % (parent_dir)
class TestSendKeysSendsKeys(single_machine_test.SingleMachineTest):
_multiprocess_can_split_ = True
def setup(self):
super(TestSendKeysSendsKeys,self).setup()
- self.depl.nix_exprs = self.depl.nix_exprs + [ secret_key_spec ]
def run_check(self):
+ self.depl.nix_exprs = self.depl.nix_exprs + [ secret_key_ram_spec ]
+
self.depl.deploy()
self.check_command("test -f /run/keys/secret.key")
self.check_command("rm -f /run/keys/secret.key")
self.depl.send_keys()
self.check_command("test -f /run/keys/secret.key")
+
+ def run_check(self):
+ self.depl.nix_exprs = self.depl.nix_exprs + [ secret_key_disk_spec ]
+
+ self.depl.deploy()
+ self.check_command("test -f /var/keys/secret.key")
+ self.check_command("rm -f /var/keys/secret.key")
+ self.depl.send_keys()
+ self.check_command("test -f /var/keys/secret.key")