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

Darwin module support #647

Merged
merged 1 commit into from
Nov 16, 2024
Merged

Darwin module support #647

merged 1 commit into from
Nov 16, 2024

Conversation

ianmurphy1
Copy link
Contributor

Seems like there's other PRs for this already so feel free to discard this one.

I've been trying to get this working locally on my macbook, using this branch of my own config for testing the secrets https://github.com/ianmurphy1/nixcfg/tree/darwin-sops-nix

There was a bug in it where if config.sops.secrets was empty then no secrets would be removed as the service would no longer be created due to the service being wrapped in a condition that there needs to be at least one secret to activate. Fixed it on darwin but this bug is present on my nixos too but I didn't touch that part as it's outside the scope of this PR.

The same bug happens with templates too which I still have to figure out so if you're ok with a bug for bug match with darwin then merge away, otherwise I'll keep working on it over the next few days as time allows to try and resolve it.

I haven't tested neededForUsers on darwin so I'll try and get that sorted too.

Comment on lines 1 to 25
from sys import argv


def substitute(target: str, subst: str) -> str:
with open(target) as f:
content = f.read()

with open(subst) as f:
subst_pairs = f.read().splitlines()

for pair in subst_pairs:
placeholder, path = pair.split()
with open(path) as f:
content = content.replace(placeholder, f.read())

return content


def main() -> None:
target = argv[1]
subst = argv[2]
print(substitute(target, subst))


main()
Copy link
Owner

Choose a reason for hiding this comment

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

Suggested change
from sys import argv
def substitute(target: str, subst: str) -> str:
with open(target) as f:
content = f.read()
with open(subst) as f:
subst_pairs = f.read().splitlines()
for pair in subst_pairs:
placeholder, path = pair.split()
with open(path) as f:
content = content.replace(placeholder, f.read())
return content
def main() -> None:
target = argv[1]
subst = argv[2]
print(substitute(target, subst))
main()

@Mic92
Copy link
Owner

Mic92 commented Nov 6, 2024

If this template changes are done, I think this good for another test run. Code-wise it looks good to me.

@ianmurphy1
Copy link
Contributor Author

Brought in latest code from sops-nix to change to golang templates instead of python. Messed it up by the looks of it as it's showing a lot of file changes.

No changes other than the merge and then the change to the templates to match current sops implementation. I'll have a chance later to test it out locally and see how the golang templates are working out.

@ianmurphy1
Copy link
Contributor Author

Rebased so now there's just my changes in the PR.

@ianmurphy1
Copy link
Contributor Author

Main thing of note from latest commit is using launchd to make secrets populate at boot time.

There's only a subset of activation scripts ran during boot: activate-system meaning secrets weren't there on initial boot, it needed a run of darwin-rebuild to populate them. Activation scripts are used thereafter.

@Keyruu
Copy link

Keyruu commented Nov 8, 2024

@Mic92 told me to test this, so I did and it works. Awesome work!

@khaneliman
Copy link

Been using this Pr myself and seen no issues, as well.

@ianmurphy1
Copy link
Contributor Author

I've squashed this into a single commit to avoid clobbering the commit history.

There's no support for setting user passwords in darwin from what I can see.

Might be worth keeping in for feature parity but could just not be imported until it is in nix-darwin and then allow it to be imported.

sshKeyPaths = cfg.gnupg.sshKeyPaths;
ageKeyFile = cfg.age.keyFile;
ageSshKeyPaths = cfg.age.sshKeyPaths;
useTmpfs = cfg.useTmpfs;
Copy link
Owner

Choose a reason for hiding this comment

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

Suggested change
useTmpfs = cfg.useTmpfs;
useTmpfs = false;

Hash of the sops file.
'';
};
neededForUsers = lib.mkOption {
Copy link
Owner

Choose a reason for hiding this comment

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

How far away from managing user passwords are we actually in macOS? Is this actually something that can be done from a CLI without user interaction?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's possible: mac user

nix-darwin doesn't implement it though.

postActivation.text = lib.mkAfter installScript;
};

launchd.daemons.sops-install-secrets-for-users = {
Copy link
Owner

Choose a reason for hiding this comment

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

Suggested change
launchd.daemons.sops-install-secrets-for-users = {
launchd.daemons.sops-install-secrets-for-users = lib.mkIf (secretsForUsers != []) {

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

Choose a reason for hiding this comment

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

Why is this this set twice?

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Was testing something locally, missed it in the cleanup, removed

@ianmurphy1
Copy link
Contributor Author

Pretty sure I've gotten all suggested changes in this latest push

@dudeofawesome
Copy link

I've been trying out this PR on one of my machines, and I'm seeing some issues with templates.

I've got a simple config here defining 2 secrets and merging them into a single config file for use with a gitlab-runner:

{ config, ... }:
let
  server_url = "hosts/lab-mac-mini/gitlab-runner/server_url";
  auth_token = "hosts/lab-mac-mini/gitlab-runner/auth_token";
in
{
  sops.secrets.${server_url}.sopsFile = ./secrets.yaml;
  sops.secrets.${auth_token}.sopsFile = ./secrets.yaml;

  sops.templates."gitlab-runner-registration.env".content = ''
    CI_SERVER_URL=${config.sops.placeholder.${server_url}}
    CI_SERVER_TOKEN=${config.sops.placeholder.${auth_token}}
  '';
}

The 1st time I try to darwin-rebuild switch to the flake including the sops.templates.…, I get this error at the end of the logs:

...
Activating setDarwinDefaults
Activating setupLaunchAgents
Setting up secrets...
sops-install-secrets: Imported /etc/ssh/ssh_host_rsa_key as GPG key with fingerprint 50fdf92d0f8e51cbe5546afb7b156a311e835379
sops-install-secrets: Imported /etc/ssh/ssh_host_ed25519_key as age key with fingerprint age1yrjflhg64fs9lt36qx8k96rjfyqvghrl4t5x6uwscg6umw4ev3qq4vpaku
Setting up secrets for users
sops-install-secrets: Imported /etc/ssh/ssh_host_rsa_key as GPG key with fingerprint 50fdf92d0f8e51cbe5546afb7b156a311e835379
sops-install-secrets: Imported /etc/ssh/ssh_host_ed25519_key as age key with fingerprint age1yrjflhg64fs9lt36qx8k96rjfyqvghrl4t5x6uwscg6umw4ev3qq4vpaku
adding rendered secret: gitlab-runner-registration.env
/nix/store/j4mb6a2d7q78mzza0lqprbq0h4jsaigk-sops-install-secrets-0.0.1/bin/sops-install-secrets: failed to prepare symlinks to secret store: failed to symlink template '/run/secrets/rendered/gitlab-runner-registration.env': cannot chown symlink '/run/secrets/rendered/gitlab-runner-registration.env': failed to open /run/secrets/rendered/gitlab-runner-registration.env: too many levels of symbolic links

If I try to the darwin-rebuild switch again, I get a different error:

...
Activating setDarwinDefaults
Activating setupLaunchAgents
Setting up secrets...
sops-install-secrets: Imported /etc/ssh/ssh_host_rsa_key as GPG key with fingerprint 50fdf92d0f8e51cbe5546afb7b156a311e835379
sops-install-secrets: Imported /etc/ssh/ssh_host_ed25519_key as age key with fingerprint age1yrjflhg64fs9lt36qx8k96rjfyqvghrl4t5x6uwscg6umw4ev3qq4vpaku
/nix/store/j4mb6a2d7q78mzza0lqprbq0h4jsaigk-sops-install-secrets-0.0.1/bin/sops-install-secrets: cannot request units to restart: lstat /private/var/run/secrets-for-users.d/7/rendered: no such file or directory

I also noticed that if /run/secrets/ already exists, but was not created by this project, I'll get this error message:

...
Activating setupLaunchAgents
Setting up secrets...
sops-install-secrets: Imported /etc/ssh/ssh_host_rsa_key as GPG key with fingerprint 8e3f62a2c899a48b38727f8068a031535b0a32b2
sops-install-secrets: Imported /etc/ssh/ssh_host_ed25519_key as age key with fingerprint age1rqjddanhdhc3gvj9mj9ez5cm492uqtcnj9elljpp4uy4hx4p3sgqyyfxa6
/nix/store/j4mb6a2d7q78mzza0lqprbq0h4jsaigk-sops-install-secrets-0.0.1/bin/sops-install-secrets: failed to prepare new secrets directory: cannot access /run/secrets: readlink /run/secrets: invalid argument

I was able to solve this issue by simply rm -rfing the pre-existing dir.


Other than those 2 issues though, it looks like the secrets themselves are working great!

@Mic92
Copy link
Owner

Mic92 commented Nov 16, 2024

@mergify queue

Copy link
Contributor

mergify bot commented Nov 16, 2024

queue

✅ The pull request has been merged automatically

The pull request has been merged automatically at d2bd7f4

@mergify mergify bot merged commit d2bd7f4 into Mic92:master Nov 16, 2024
6 checks passed
@Mic92
Copy link
Owner

Mic92 commented Nov 16, 2024

@ianmurphy1 @dudeofawesome Some documentation paragraph in the README would be nice. i.e. how to use this with flakes.

@ianmurphy1
Copy link
Contributor Author

@Mic92 I'll try and get something in Monday or Tuesday unless I get a spare moment over the weekend to do it.

@dudeofawesome Not sure about this as it's not something I've encountered as the only secrets I have are managed by sops-nix so there's no other tool using the /run/secrets dir to get in the way. Like above I'm not likely to get to this until early next week to try and replicate locally. Have you tried the same thing on NixOS and gotten similar errors or is it darwin specific?

@dudeofawesome
Copy link

I’d been messing around with manually placing secrets in that directory prior to this PR, which is why it existed at all. I don’t intend to do that going forward.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants