ssh: migrate to using ssh-agent

this provides better security, and the possibility of easier dependency injecting (e.g. coercing a program to use some _specific_ ssh key, even when not designed for it)'
This commit is contained in:
2025-06-05 19:09:30 +00:00
parent d4c576c2ae
commit 19a14cc8ad
5 changed files with 63 additions and 3 deletions

View File

@@ -186,6 +186,7 @@ in
"snapper"
"sops" # for manually viewing secrets; outside `sane-secrets` (TODO: improve sane-secrets!)
"speedtest-cli"
"ssh" # specified as a user program, to enable ssh-agent service
"ssh-to-age" # used when provisioning a new nixos host
"strings"
"sudo"

View File

@@ -18,6 +18,9 @@ in
rm "$out/bin/git-jump"
'';
});
suggestedPrograms = [
"ssh"
];
sandbox.net = "clearnet";
sandbox.whitelistPwd = true;
sandbox.autodetectCliPaths = "parent"; # autodetection is necessary for git-upload-pack; "parent" so that `git mv` works
@@ -27,8 +30,8 @@ in
"knowledge"
"nixos"
"ref"
".ssh/id_ed25519" # for ssh-auth'd remotes
];
sandbox.whitelistSsh = true;
fs.".config/git/config".symlink.text = mkCfg {
# top-level options documented:
# - <https://git-scm.com/docs/git-config#_variables>

View File

@@ -3,7 +3,7 @@
sane.programs."sane-secrets-unlock" = {
packageUnwrapped = pkgs.sane-scripts.secrets-unlock;
sandbox.extraHomePaths = [
".ssh/id_ed25519"
".ssh/id_ed25519" #< XXX: the the age key is derived from the *private* key: we can't use ssh-agent for this.
".ssh/id_ed25519.pub"
".config/sops"
];

View File

@@ -5,7 +5,53 @@ in
{
sane.programs.ssh = {
packageUnwrapped = pkgs.linkBinIntoOwnPackage pkgs.openssh "ssh";
sandbox.method = null; #< TODO: sandbox
sandbox.net = "all";
sandbox.whitelistSsh = true;
suggestedPrograms = [ "ssh-agent" ];
};
sane.programs.ssh-agent = {
packageUnwrapped = pkgs.linkBinIntoOwnPackage pkgs.openssh "ssh-agent";
suggestedPrograms = [ "ssh-add" ];
sandbox.net = "clearnet";
sandbox.extraRuntimePaths = [
"ssh-agent"
];
env.SSH_AUTH_SOCK = "/run/user/colin/ssh-agent/agent";
services.ssh-agent = {
description = "ssh-agent authentication agent";
command = pkgs.writeShellScript "ssh-agent-start" ''
mkdir -p "$XDG_RUNTIME_DIR/ssh-agent"
# -D = Don't fork
# -d = dont fork, *and*, write debug info to standard eror
# (only one of -D|-d may be specified)
exec ssh-agent -d -a "$XDG_RUNTIME_DIR/ssh-agent/agent"
'';
readiness.waitExists = [
"$SSH_AUTH_SOCK"
];
partOf = [ "default" ];
};
};
sane.programs.ssh-add = {
packageUnwrapped = pkgs.linkBinIntoOwnPackage pkgs.openssh "ssh-add";
sandbox.extraHomePaths = [
".ssh/id_ed25519"
];
sandbox.whitelistSsh = true;
services.ssh-add = {
description = "import keys to ssh-agent";
startCommand = "ssh-add";
cleanupCommand = "ssh-add -d"; # `ssh-add -d` undo's `ssh-add`, but leaves keys added to the agent through other means still available
depends = [
"gocryptfs-private"
"ssh-agent"
];
partOf = [ "private-storage" ];
};
};
programs.ssh = lib.mkIf cfg.enabled {

View File

@@ -304,6 +304,8 @@ let
"sound"
] ++ lib.optionals (builtins.elem "gnome-keyring" config.suggestedPrograms) [
"gnome-keyring"
] ++ lib.optionals config.sandbox.whitelistSsh [
"ssh-agent"
];
}
);
@@ -592,6 +594,13 @@ let
typically works via dbus.
'';
};
sandbox.whitelistSsh = mkOption {
type = types.bool;
default = false;
description = ''
allow the program to communicate with ssh-agent.
'';
};
sandbox.whitelistSystemctl = mkOption {
type = types.bool;
default = false;
@@ -869,6 +878,7 @@ let
++ lib.optionals config.sandbox.whitelistDbus.user.all [ "dbus" ]
++ lib.optionals config.sandbox.whitelistWayland [ "wl" ] # app can still communicate with wayland server w/o this, if it has net access
++ lib.optionals config.sandbox.whitelistS6 [ "s6" ] # TODO: this allows re-writing the services themselves: don't allow that!
++ lib.optionals config.sandbox.whitelistSsh [ "ssh-agent" ]
;
sandbox.extraHomePaths = let
whitelistDir = dir: lib.optionals (lib.any (p: lib.hasPrefix "${dir}/" p) (builtins.attrNames config.fs)) [