Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion modules/sops/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ in {

sops.environment.SOPS_GPG_EXEC = lib.mkIf (cfg.gnupg.home != null || cfg.gnupg.sshKeyPaths != []) (lib.mkDefault "${pkgs.gnupg}/bin/gpg");

# When using sysusers we no longer be started as an activation script because those are started in initrd while sysusers is started later.
# When using sysusers we no longer are started as an activation script because those are started in initrd while sysusers is started later.
systemd.services.sops-install-secrets = lib.mkIf (regularSecrets != { } && useSystemdActivation) {
wantedBy = [ "sysinit.target" ];
after = [ "systemd-sysusers.service" ];
Expand Down
10 changes: 5 additions & 5 deletions pkgs/sops-install-secrets/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ func linksAreEqual(linkTarget, targetFile string, info os.FileInfo, owner int, g
return linkTarget == targetFile && validUG
}

func symlinkSecret(targetFile string, path string, owner int, group int, userMode bool) error {
func createSymlink(targetFile string, path string, owner int, group int, userMode bool) error {
for {
stat, err := os.Lstat(path)
if os.IsNotExist(err) {
Expand Down Expand Up @@ -217,7 +217,7 @@ func symlinkSecret(targetFile string, path string, owner int, group int, userMod
}
}

func symlinkSecrets(targetDir string, secrets []secret, templates map[string]*template, userMode bool) error {
func symlinkSecretsAndTemplates(targetDir string, secrets []secret, templates map[string]*template, userMode bool) error {
for _, secret := range secrets {
targetFile := filepath.Join(targetDir, secret.Name)
if targetFile == secret.Path {
Expand All @@ -227,7 +227,7 @@ func symlinkSecrets(targetDir string, secrets []secret, templates map[string]*te
if err := os.MkdirAll(parent, os.ModePerm); err != nil {
return fmt.Errorf("cannot create parent directory of '%s': %w", secret.Path, err)
}
if err := symlinkSecret(targetFile, secret.Path, secret.owner, secret.group, userMode); err != nil {
if err := createSymlink(targetFile, secret.Path, secret.owner, secret.group, userMode); err != nil {
return fmt.Errorf("failed to symlink secret '%s': %w", secret.Path, err)
}
}
Expand All @@ -241,7 +241,7 @@ func symlinkSecrets(targetDir string, secrets []secret, templates map[string]*te
if err := os.MkdirAll(parent, os.ModePerm); err != nil {
return fmt.Errorf("cannot create parent directory of '%s': %w", template.Path, err)
}
if err := symlinkSecret(targetFile, template.Path, template.owner, template.group, userMode); err != nil {
if err := createSymlink(targetFile, template.Path, template.owner, template.group, userMode); err != nil {
return fmt.Errorf("failed to symlink template '%s': %w", template.Path, err)
}
}
Expand Down Expand Up @@ -1302,7 +1302,7 @@ func installSecrets(args []string) error {
if isDry {
return nil
}
if err := symlinkSecrets(manifest.SymlinkPath, manifest.Secrets, manifest.Templates, manifest.UserMode); err != nil {
if err := symlinkSecretsAndTemplates(manifest.SymlinkPath, manifest.Secrets, manifest.Templates, manifest.UserMode); err != nil {
return fmt.Errorf("failed to prepare symlinks to secret store: %w", err)
}
if err := atomicSymlink(*secretDir, manifest.SymlinkPath); err != nil {
Expand Down
37 changes: 37 additions & 0 deletions pkgs/sops-install-secrets/nixos-test.nix
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,43 @@ in {
'';
};

template-path-not-external = testers.runNixOSTest {
name = "sops-template-path-not-external";
nodes.machine = {config, ...}: {
imports = [ ../../modules/sops ];
sops = {
age.keyFile = "/run/age-keys.txt";
defaultSopsFile = ./test-assets/secrets.yaml;
secrets.test_key = { };
};

# Must run before sops sets up keys.
boot.initrd.postDeviceCommands = ''
cp -r ${./test-assets/age-keys.txt} /run/age-keys.txt
chmod -R 700 /run/age-keys.txt
'';

sops.templates.test_template = {
content = ''
Test value: ${config.sops.placeholder.test_key}
'';
# This path is inside of `/run/secrets`, which isn't allowed.
path = "/run/secrets/foo-bar";

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's inside /run/secrets maybe it should name the template differently rather than doing the symlink? Alternative would be not allow this behavior and make it an eval error.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ooh, I like the "name it differently" idea. I think that'll actually clean up the implementation a bit, as it currently deals carefully (and verbosely) with the "rendered" subdir.

I'll give this a shot later today.

};

system.switch.enable = true;
};

testScript = ''
start_all()
machine.wait_for_unit("multi-user.target")
# TODO: is there some way to assert that system activation worked during
# the initial boot? We don't actually have to try activating again
# here...
machine.succeed("/run/current-system/bin/switch-to-configuration test")
'';
};

restart-and-reload = testers.runNixOSTest {
name = "sops-restart-and-reload";
nodes.machine = {config, ...}: {
Expand Down