1
0
Fork 0
mirror of https://github.com/Mic92/sops-nix.git synced 2025-03-16 05:28:15 +00:00

Re-add service restarts

We also have service reloads now, so add them as well
This commit is contained in:
Janne Heß 2022-03-14 17:30:56 +01:00
parent 4e21493d34
commit 5e2f743edd
No known key found for this signature in database
GPG key ID: 69165158F05265DF
5 changed files with 135 additions and 90 deletions

View file

@ -562,6 +562,20 @@ the service needs a token and a SSH private key to function.</summary>
</details> </details>
## Restarting/reloading systemd units on secret change
**With NixOS 22.05**, it is possible to restart or reload units when a secret changes or is newly initialized.
This behavior can be configured per-secret:
```nix
{
sops.secrets."home-assistant-secrets.yaml" = {
restartUnits = [ "home-assistant.service" ];
# there is also `reloadUnits` which acts like a `reloadTrigger` in a NixOS systemd service
};
}
```
## Symlinks to other directories ## Symlinks to other directories
Some services might expect files in certain locations. Some services might expect files in certain locations.

View file

@ -92,6 +92,15 @@ let
This works the same way as <xref linkend="opt-systemd.services._name_.restartTriggers" />. This works the same way as <xref linkend="opt-systemd.services._name_.restartTriggers" />.
''; '';
}; };
reloadUnits = mkOption {
type = types.listOf types.str;
default = [ ];
example = [ "sshd.service" ];
description = ''
Names of units that should be reloaded when this secret changes.
This works the same way as <xref linkend="opt-systemd.services._name_.reloadTriggers" />.
'';
};
neededForUsers = mkOption { neededForUsers = mkOption {
type = types.bool; type = types.bool;
default = false; default = false;

View file

@ -36,6 +36,7 @@ type secret struct {
Format FormatType `json:"format"` Format FormatType `json:"format"`
Mode string `json:"mode"` Mode string `json:"mode"`
RestartUnits []string `json:"restartUnits"` RestartUnits []string `json:"restartUnits"`
ReloadUnits []string `json:"reloadUnits"`
value []byte value []byte
mode os.FileMode mode os.FileMode
owner int owner int
@ -679,6 +680,7 @@ func symlinkWalk(filename string, linkDirname string, walkFn filepath.WalkFunc)
func handleModifications(isDry bool, logcfg loggingConfig, symlinkPath string, secretDir string, secrets []secret) error { func handleModifications(isDry bool, logcfg loggingConfig, symlinkPath string, secretDir string, secrets []secret) error {
var restart []string var restart []string
var reload []string
newSecrets := make(map[string]bool) newSecrets := make(map[string]bool)
modifiedSecrets := make(map[string]bool) modifiedSecrets := make(map[string]bool)
@ -702,6 +704,7 @@ func handleModifications(isDry bool, logcfg loggingConfig, symlinkPath string, s
if os.IsNotExist(err) { if os.IsNotExist(err) {
// File did not exist before // File did not exist before
restart = append(restart, secret.RestartUnits...) restart = append(restart, secret.RestartUnits...)
reload = append(reload, secret.ReloadUnits...)
newSecrets[secret.Name] = true newSecrets[secret.Name] = true
continue continue
} }
@ -716,6 +719,7 @@ func handleModifications(isDry bool, logcfg loggingConfig, symlinkPath string, s
if !bytes.Equal(oldData, newData) { if !bytes.Equal(oldData, newData) {
restart = append(restart, secret.RestartUnits...) restart = append(restart, secret.RestartUnits...)
reload = append(reload, secret.ReloadUnits...)
modifiedSecrets[secret.Name] = true modifiedSecrets[secret.Name] = true
} }
} }
@ -744,6 +748,9 @@ func handleModifications(isDry bool, logcfg loggingConfig, symlinkPath string, s
if err := writeLines(restart, dryPrefix+"-restart-list"); err != nil { if err := writeLines(restart, dryPrefix+"-restart-list"); err != nil {
return err return err
} }
if err := writeLines(reload, dryPrefix+"-reload-list"); err != nil {
return err
}
// Do not output changes if not requested // Do not output changes if not requested
if !logcfg.SecretChanges { if !logcfg.SecretChanges {

View file

@ -107,6 +107,7 @@ func testGPG(t *testing.T) {
Path: path.Join(testdir.path, "test-target"), Path: path.Join(testdir.path, "test-target"),
Mode: "0400", Mode: "0400",
RestartUnits: []string{"affected-service"}, RestartUnits: []string{"affected-service"},
ReloadUnits: []string{"affected-reload-service"},
} }
var jsonSecret, binarySecret secret var jsonSecret, binarySecret secret
@ -205,6 +206,7 @@ func testSSHKey(t *testing.T) {
Path: target, Path: target,
Mode: "0400", Mode: "0400",
RestartUnits: []string{"affected-service"}, RestartUnits: []string{"affected-service"},
ReloadUnits: []string{"affected-reload-service"},
} }
m := manifest{ m := manifest{
@ -237,6 +239,7 @@ func TestAge(t *testing.T) {
Path: target, Path: target,
Mode: "0400", Mode: "0400",
RestartUnits: []string{"affected-service"}, RestartUnits: []string{"affected-service"},
ReloadUnits: []string{"affected-reload-service"},
} }
m := manifest{ m := manifest{
@ -269,6 +272,7 @@ func TestAgeWithSSH(t *testing.T) {
Path: target, Path: target,
Mode: "0400", Mode: "0400",
RestartUnits: []string{"affected-service"}, RestartUnits: []string{"affected-service"},
ReloadUnits: []string{"affected-reload-service"},
} }
m := manifest{ m := manifest{
@ -302,6 +306,7 @@ func TestValidateManifest(t *testing.T) {
Path: path.Join(testdir.path, "test-target"), Path: path.Join(testdir.path, "test-target"),
Mode: "0400", Mode: "0400",
RestartUnits: []string{}, RestartUnits: []string{},
ReloadUnits: []string{},
} }
m := manifest{ m := manifest{

View file

@ -204,109 +204,119 @@
inherit (pkgs) system; inherit (pkgs) system;
}; };
} // pkgs.lib.optionalAttrs (pkgs.lib.versionAtLeast (pkgs.lib.versions.majorMinor pkgs.lib.version) "21.11") { } // pkgs.lib.optionalAttrs (pkgs.lib.versionAtLeast (pkgs.lib.versions.majorMinor pkgs.lib.version) "22.05") {
# This feature got reverted in nixpkgs... restart-and-reload = makeTest {
#restart-and-reload = makeTest { name = "sops-restart-and-reload";
# name = "sops-restart-and-reload"; machine = { pkgs, lib, config, ... }: {
# machine = { pkgs, lib, config, ... }: { imports = [
# imports = [ ../../modules/sops
# ../../modules/sops ];
# ];
# sops = { sops = {
# age.keyFile = ./test-assets/age-keys.txt; age.keyFile = ./test-assets/age-keys.txt;
# defaultSopsFile = ./test-assets/secrets.yaml; defaultSopsFile = ./test-assets/secrets.yaml;
# secrets.test_key = { secrets.test_key = {
# restartUnits = [ "restart-unit.service" "reload-unit.service" ]; restartUnits = [ "restart-unit.service" "reload-unit.service" ];
# }; reloadUnits = [ "reload-trigger.service" ];
# }; };
};
# systemd.services."restart-unit" = { systemd.services."restart-unit" = {
# description = "Restart unit"; description = "Restart unit";
# # not started on boot # not started on boot
# serviceConfig = { serviceConfig = {
# ExecStart = "/bin/sh -c 'echo ok > /restarted'"; ExecStart = "/bin/sh -c 'echo ok > /restarted'";
# }; };
# }; };
# systemd.services."reload-unit" = { systemd.services."reload-unit" = {
# description = "Restart unit"; description = "Reload unit";
# wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
# reloadIfChanged = true; reloadIfChanged = true;
# serviceConfig = { serviceConfig = {
# Type = "oneshot"; Type = "oneshot";
# RemainAfterExit = true; RemainAfterExit = true;
# ExecStart = "/bin/sh -c true"; ExecStart = "/bin/sh -c true";
# ExecReload = "/bin/sh -c 'echo ok > /reloaded'"; ExecReload = "/bin/sh -c 'echo ok > /reloaded'";
# }; };
# }; };
# }; systemd.services."reload-trigger" = {
# testScript = '' description = "Reload trigger unit";
# machine.wait_for_unit("multi-user.target") wantedBy = [ "multi-user.target" ];
# machine.fail("test -f /restarted") serviceConfig = {
# machine.fail("test -f /reloaded") Type = "oneshot";
RemainAfterExit = true;
ExecStart = "/bin/sh -c true";
ExecReload = "/bin/sh -c 'echo ok > /reloaded'";
};
};
};
testScript = ''
machine.wait_for_unit("multi-user.target")
machine.fail("test -f /restarted")
machine.fail("test -f /reloaded")
# # Nothing is to be restarted after boot # Nothing is to be restarted after boot
# machine.fail("ls /run/nixos/*-list") machine.fail("ls /run/nixos/*-list")
# # Nothing happens when the secret is not changed # Nothing happens when the secret is not changed
# machine.succeed("/run/current-system/bin/switch-to-configuration test") machine.succeed("/run/current-system/bin/switch-to-configuration test")
# machine.fail("test -f /restarted") machine.fail("test -f /restarted")
# machine.fail("test -f /reloaded") machine.fail("test -f /reloaded")
# # Ensure the secret is changed # Ensure the secret is changed
# machine.succeed(": > /run/secrets/test_key") machine.succeed(": > /run/secrets/test_key")
# # The secret is changed, now something should happen # The secret is changed, now something should happen
# machine.succeed("/run/current-system/bin/switch-to-configuration test") machine.succeed("/run/current-system/bin/switch-to-configuration test")
# # Ensure something happened # Ensure something happened
# machine.succeed("test -f /restarted") machine.succeed("test -f /restarted")
# machine.succeed("test -f /reloaded") machine.succeed("test -f /reloaded")
# with subtest("change detection"): with subtest("change detection"):
# machine.succeed("rm /run/secrets/test_key") machine.succeed("rm /run/secrets/test_key")
# out = machine.succeed("/run/current-system/bin/switch-to-configuration test") out = machine.succeed("/run/current-system/bin/switch-to-configuration test")
# if "adding secret" not in out: if "adding secret" not in out:
# raise Exception("Addition detection does not work") raise Exception("Addition detection does not work")
# machine.succeed(": > /run/secrets/test_key") machine.succeed(": > /run/secrets/test_key")
# out = machine.succeed("/run/current-system/bin/switch-to-configuration test") out = machine.succeed("/run/current-system/bin/switch-to-configuration test")
# if "modifying secret" not in out: if "modifying secret" not in out:
# raise Exception("Modification detection does not work") raise Exception("Modification detection does not work")
# machine.succeed(": > /run/secrets/another_key") machine.succeed(": > /run/secrets/another_key")
# out = machine.succeed("/run/current-system/bin/switch-to-configuration test") out = machine.succeed("/run/current-system/bin/switch-to-configuration test")
# if "removing secret" not in out: if "removing secret" not in out:
# raise Exception("Removal detection does not work") raise Exception("Removal detection does not work")
# with subtest("dry activation"): with subtest("dry activation"):
# machine.succeed("rm /run/secrets/test_key") machine.succeed("rm /run/secrets/test_key")
# machine.succeed(": > /run/secrets/another_key") machine.succeed(": > /run/secrets/another_key")
# out = machine.succeed("/run/current-system/bin/switch-to-configuration dry-activate") out = machine.succeed("/run/current-system/bin/switch-to-configuration dry-activate")
# if "would add secret" not in out: if "would add secret" not in out:
# raise Exception("Dry addition detection does not work") raise Exception("Dry addition detection does not work")
# if "would remove secret" not in out: if "would remove secret" not in out:
# raise Exception("Dry removal detection does not work") raise Exception("Dry removal detection does not work")
# machine.fail("test -f /run/secrets/test_key") machine.fail("test -f /run/secrets/test_key")
# machine.succeed("test -f /run/secrets/another_key") machine.succeed("test -f /run/secrets/another_key")
# machine.succeed("/run/current-system/bin/switch-to-configuration test") machine.succeed("/run/current-system/bin/switch-to-configuration test")
# machine.succeed("test -f /run/secrets/test_key") machine.succeed("test -f /run/secrets/test_key")
# machine.succeed("rm /restarted /reloaded") machine.succeed("rm /restarted /reloaded")
# machine.fail("test -f /run/secrets/another_key") machine.fail("test -f /run/secrets/another_key")
# machine.succeed(": > /run/secrets/test_key") machine.succeed(": > /run/secrets/test_key")
# out = machine.succeed("/run/current-system/bin/switch-to-configuration dry-activate") out = machine.succeed("/run/current-system/bin/switch-to-configuration dry-activate")
# if "would modify secret" not in out: if "would modify secret" not in out:
# raise Exception("Dry modification detection does not work") raise Exception("Dry modification detection does not work")
# machine.succeed("[ $(cat /run/secrets/test_key | wc -c) = 0 ]") machine.succeed("[ $(cat /run/secrets/test_key | wc -c) = 0 ]")
# machine.fail("test -f /restarted") # not done in dry mode machine.fail("test -f /restarted") # not done in dry mode
# machine.fail("test -f /reloaded") # not done in dry mode machine.fail("test -f /reloaded") # not done in dry mode
# ''; '';
#} { } {
# inherit pkgs; inherit pkgs;
# inherit (pkgs) system; inherit (pkgs) system;
#}; };
} }