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

Demonstration of how system activation fails if the template path is not "external" #660

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
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
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
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