nixos_config/nixos/modules/services/oci-authorized-keys.nix

107 lines
3.6 KiB
Nix
Raw Permalink Normal View History

2026-05-29 19:30:07 +02:00
{ config, lib, pkgs, ... }:
let
cfg = config.alisceon.ociAuthorizedKeys;
home = config.users.users.${cfg.user}.home;
sshDir = "${home}/.ssh";
authorizedKeysFile = "${sshDir}/authorized_keys";
2026-05-30 09:38:41 +02:00
staticAuthorizedKeys = config.users.users.${cfg.user}.openssh.authorizedKeys.keys or [ ];
staticAuthorizedKeysText =
(lib.concatStringsSep "\n" staticAuthorizedKeys)
+ lib.optionalString (staticAuthorizedKeys != [ ]) "\n";
staticAuthorizedKeysFile = pkgs.writeText "static-authorized-keys-${cfg.user}" staticAuthorizedKeysText;
2026-05-29 19:30:07 +02:00
fetchOciAuthorizedKeys = pkgs.writeShellApplication {
name = "fetch-oci-authorized-keys";
runtimeInputs = [
pkgs.coreutils
pkgs.curl
2026-05-30 09:38:41 +02:00
pkgs.gnugrep
2026-05-29 19:30:07 +02:00
];
text = ''
install -d -m 0700 -o ${lib.escapeShellArg cfg.user} -g ${lib.escapeShellArg cfg.group} ${lib.escapeShellArg sshDir}
2026-05-30 09:38:41 +02:00
if [ ! -e ${lib.escapeShellArg authorizedKeysFile} ]; then
install -m 0600 -o ${lib.escapeShellArg cfg.user} -g ${lib.escapeShellArg cfg.group} /dev/null ${lib.escapeShellArg authorizedKeysFile}
2026-05-29 19:30:07 +02:00
fi
2026-05-30 09:38:41 +02:00
chown ${lib.escapeShellArg "${cfg.user}:${cfg.group}"} ${lib.escapeShellArg authorizedKeysFile}
chmod 0600 ${lib.escapeShellArg authorizedKeysFile}
append_keys() {
while IFS= read -r key; do
[ -n "$key" ] || continue
grep -qxF -- "$key" ${lib.escapeShellArg authorizedKeysFile} || printf '%s\n' "$key" >> ${lib.escapeShellArg authorizedKeysFile}
done < "$1"
}
append_keys ${lib.escapeShellArg staticAuthorizedKeysFile}
metadata_keys="$(mktemp)"
trap 'rm -f "$metadata_keys"' EXIT
2026-05-29 19:30:07 +02:00
curl --fail --silent --show-error --location \
2026-05-30 09:38:41 +02:00
--connect-timeout 3 \
--max-time 10 \
--retry 3 \
--retry-delay 2 \
2026-05-29 19:30:07 +02:00
--header ${lib.escapeShellArg "Authorization: Bearer Oracle"} \
2026-05-30 09:38:41 +02:00
--output "$metadata_keys" \
${lib.escapeShellArg cfg.metadataUrl} || {
echo "Unable to fetch OCI authorized_keys for ${cfg.user}; leaving existing keys unchanged"
exit 0
}
append_keys "$metadata_keys"
2026-05-29 19:30:07 +02:00
chown ${lib.escapeShellArg "${cfg.user}:${cfg.group}"} ${lib.escapeShellArg authorizedKeysFile}
chmod 0600 ${lib.escapeShellArg authorizedKeysFile}
'';
};
in
{
options.alisceon.ociAuthorizedKeys = {
enable = lib.mkEnableOption "fetching SSH authorized_keys from OCI metadata";
user = lib.mkOption {
type = lib.types.str;
default = "alisceon";
description = "User whose authorized_keys file should be populated.";
};
group = lib.mkOption {
type = lib.types.str;
default = "users";
description = "Group owner for the user's SSH files.";
};
metadataUrl = lib.mkOption {
type = lib.types.str;
default = "http://169.254.169.254/opc/v2/instance/metadata/ssh_authorized_keys";
description = "OCI metadata endpoint containing SSH authorized keys.";
};
};
config = lib.mkIf cfg.enable {
systemd.services.fetch-oci-authorized-keys = {
description = "Fetch OCI metadata authorized_keys for ${cfg.user}";
2026-05-30 16:54:22 +02:00
wantedBy = [
"sshd.service"
"multi-user.target"
];
before = [ "sshd.service" ];
2026-05-29 19:30:07 +02:00
after = [ "network-online.target" ];
wants = [ "network-online.target" ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
StandardError = "journal+console";
StandardOutput = "journal+console";
2026-05-30 09:38:41 +02:00
TimeoutStartSec = "30s";
2026-05-29 19:30:07 +02:00
};
script = lib.getExe fetchOciAuthorizedKeys;
};
systemd.services.fetch-ssh-keys.enable = false;
};
}