Skip to content

Commit

Permalink
Refactored, renamed, and added (placeholder) options
Browse files Browse the repository at this point in the history
  • Loading branch information
jordanisaacs committed Nov 11, 2021
1 parent 13cd57d commit af04491
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 105 deletions.
126 changes: 86 additions & 40 deletions module/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@ with lib;
let
cfg = config.homeage;

# All files are decrypted to /run/user and cleaned up when rebooted
runtimeDecryptFolder = cfg.mount;

ageBin = if cfg.isRage then "${cfg.pkg}/bin/rage" else "${cfg.pkg}/bin/age";
startupDecryptPath = path: cfg.startupMount + "/" + path;
activationDecryptPath = path: cfg.activationMount + "/" + path;

runtimeDecryptPath = path: runtimeDecryptFolder + "/" + path;

identities = builtins.concatStringsSep " " (map (path: "-i ${path}") cfg.identityPaths);

Expand All @@ -18,11 +16,11 @@ let
${command} ${runtimepath} ${dest}
'')) destinations);

decryptSecret = name: { source, path, symlinks, cpOnService, mode, owner, group, ... }:
decryptSecret = name: { source, decryptPath, mode, owner, group, lnOnStartup, cpOnStartup, ... }:
let
runtimepath = runtimeDecryptPath path;
linksCmds = createFiles "ln -sf" runtimepath symlinks;
copiesCmds = createFiles "cp -f" runtimepath cpOnService;
runtimepath = startupDecryptPath decryptPath;
linksCmds = createFiles "ln -sf" runtimepath lnOnStartup;
copiesCmds = createFiles "cp -f" runtimepath cpOnStartup;
in
pkgs.writeShellScriptBin "${name}-decrypt" ''
set -euo pipefail
Expand Down Expand Up @@ -64,85 +62,133 @@ let
cfg.file;

# Options for a secret file
# Based on https://github.com/ryantm/agenix/pull/58
secretFile = types.submodule ({ name, ... }: {
options = {
path = mkOption {
description = "Relative path of where the file will be saved in /run";
type = types.str;
};

source = mkOption {
description = "Path to the age encrypted file";
type = types.path;
};

decryptPath = mkOption {
description = "Relative path (to startupMount and activationMount) where the decrypted file will be saved";
type = types.str;
};

mode = mkOption {
type = types.str;
default = "0400";
description = "Permissions mode of the decrypted file";
};

owner = mkOption {
type = types.str;
default = "$UID";
description = "User of the decrypted file";
};

group = mkOption {
type = types.str;
default = "$(id -g)";
description = "Group of the decrypted file";
};

symlinks = mkOption {
lnOnStartup = mkOption {
type = types.listOf types.str;
default = [ ];
description = "Symbolically link decrypted file to absolute paths";
description = "Symbolically link on startup decrypted file to absolute paths";
};

cpOnService = mkOption {
lnOnActivation = mkOption {
type = types.listOf types.str;
default = [ ];
description = "Copy decrypted file to absolute paths";
description = "Symbolically link on activation decrypted file to absolute paths";
};

cpOnStartup = mkOption {
type = types.listOf types.str;
description = "Copy decrypted file on startup to absolute paths";
};

cpOnActivation = mkOption {
type = types.listOf types.str;
description = "Copy decrypted file on activation to absolute paths";
};
};

config = {
path = mkDefault name;
decryptPath = mkDefault name;

mode = mkDefault "0400";
owner = mkDefault "$UID";
group = mkDefault "$(id -g)";

lnOnStartup = mkDefault [ ];
lnOnActivation = mkDefault [ ];

cpOnStartup = mkDefault [ ];
cpOnActivation = mkDefault [ ];
};
});
in
{
options.homeage = {
file = mkOption {
description = "Attrset of secret files";
default = { };
type = types.attrsOf secretFile;
};

pkg = mkOption {
description = "(R)age package to use";
default = pkgs.age;
type = types.package;
description = "(R)age package to use";
};

isRage = mkOption {
description = "Is rage package";
default = false;
type = types.bool;
description = "Whether homeage.pkg is rage package";
};

startupMount = mkOption {
type = types.nullOr types.str;
description = ''
Absolute path to folder where startup decrypted files are stored.
Defaults to /run which is a tmpfs. tmpfs still loads secrets to disk if using swap.
Recommended to mount a ramfs (requires sudo) as it doesn't use swap and change the path to point there.
'';
};

mount = mkOption {
description = "Absolute path to folder where decrypted files are stored. Files are decrypted on login. Defaults to /run which is a tmpfs.";
default = "/run/user/$UID/secrets";
type = types.str;
activationMount = mkOption {
type = types.nullOr types.str;
description = "Absolute path to folder where activation decrypted files are stored.";
};

identityPaths = mkOption {
description = "Absolute path to identity files used for age decryption. Must provide at least one path";
default = [ ];
type = types.listOf types.str;
description = "Absolute path to identity files used for age decryption. Must provide at least one path";
};

file = mkOption {
description = ''
Attribute set of secret files
Activation vs. Startup Secrets:
- Use activation if don't care about secrets being written to disk as they will only be decrypted once on activation.
- Use startup if care about secrets being written to disk (see startupMount for filesystem info). It creates a systemd service/decryption script that runs on startup.
Source decrypted file:
- A source decrypted file (stored in appropriate mount folder) exists only if symlinks are used. Copies won't create a source file.
Symlink vs. copy:
- Use symbolic link as it ensures the secret is read only. ONLY use copy if a program doesn't allow for symlinked files. There are fewer checks on copied files.
Activation Checks:
- Activation succeeds if can successfully decrypt file
- No paths interfere with other declared paths in current generation
- No newly declared paths interfere with existing files
- No files exist at declared symlinks
Activation Cleanup:
- Copies always ask for deletion (hence their discouraged use)
- Links are only unlinked if point to declared path
- Source files are deleted without asking
Activation Startup:
- Copies and symlinks overwrites existing files/links at destination
- Note: the new path activation check prevents previously existing files/links from being overwritten
- Systemd units and activation decryption runs if the attribute set has changed
'';
default = { };
type = types.attrsOf secretFile;
};
};

Expand Down
65 changes: 0 additions & 65 deletions options.md

This file was deleted.

0 comments on commit af04491

Please sign in to comment.