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

feature: Secret generator/bootstrap options #236

Open
Lehmanator opened this issue Jan 8, 2024 · 0 comments
Open

feature: Secret generator/bootstrap options #236

Lehmanator opened this issue Jan 8, 2024 · 0 comments

Comments

@Lehmanator
Copy link

Make bootstrapping new NixOS systems using encrypted secrets less of a chore by creating options to generate new secrets for secrets specified in config that are missing their corresponding .age secret file.

Here's a quick-n-dirty set of NixOS/home-manager options to implement this:


# Enable automatic secret generation for missing secrets.
#   (disabled by default)
age.generate.enable = true;

# Bootstrap SSH key (if missing)
age.secrets.my-ssh-key.generate = rec {
  outputFile = "<path>";   # Use stdout when null
  command = ''
    ssh-keygen -t ed25519 -f ${outputFile}
  '';
};

# Bootstrap random key (if missing)
age.secrets.my-random-base64.generate.command = ''
  openssl rand -base64 64
'';

When a secret name cannot be found, these options would be run as a bash script to initialize the secret file with the stdout of the command or a file path to be generated by the command.

Additionally, other options could be used for common secret formats. e.g. age.secrets.<name>.type. Secrets could be declared as that type to reuse common secret generation commands or manually specify how they are to be generated.

# agenix could provide the most common type definitions, which users could extend
age.generate.types.ssh-rsa4096 = rec {
  commandOutput = "<path>"; # or stdout when null.
  command = ''
    ssh-keygen -t rsa -b 4096 -f ${commandOutput}
  '';
};

# Secrets could then use this by setting:
age.secrets.my-4096bit-ssh-key.type = "ssh-rsa4096";

Once all missing secrets are resolved, agenix could optionally do one of the following:

  • Mount the resulting age-encrypted secret .age files to a location on disk
  • Create an activation script to add & commit the changes to an upstream repo.
age.generate.push = {
  # Disabled by default
  enable = true;

  # Push directly to a branch, otherwise open new PR
  skipRequest = true;

  # Set remote. Could be filesystem directory, URL, or attrset specifying host, owner, repo, branch, rev, etc.
  repo = "https://github.com/<user>/my-nixos-configs.git";

  commitMessage = ''
    command to generate summary of secret changes.
    --- OR ---
    plain string interpolated with vars
  '';
  # ... whatever other options that might facilitate this. 
};

Might be a lot for this feature, but would simplify bootstrapping even further. This could also be done with generic hooks on the generation command or upon fully resolving all missing secrets.

Something like this would make bootstrapping NixOS with per-host or per-user secrets so much less of a pain, especially when you need a mixture of secrets that are unique per-host and shared between hosts.

Obviously, this would break reproducibility until all missing secrets are fully resolved, but would maintain reproducibility thereafter...which is not different from manually bootstrapping secrets, just with more automation.

Another (potentially) simpler implementation options could just be surfacing options to hook the various parts of the process

age.hooks = {
  missing.<type> = ''
    <secret generation command>
  '';
  missingResolved = ''
    cd /etc/nixos
    git add /tmp/agenix-new-secrets/*.age
    git commit -m "Generate secrets for host: ${config.networking.hostName}"
    git push origin develop
  '';

  activation = ''
  '';
  
}

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

No branches or pull requests

1 participant