{ config, lib, pkgs, ... }: let cfg = config.alisceon.ociAuthorizedKeys; home = config.users.users.${cfg.user}.home; sshDir = "${home}/.ssh"; authorizedKeysFile = "${sshDir}/authorized_keys"; 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; fetchOciAuthorizedKeys = pkgs.writeShellApplication { name = "fetch-oci-authorized-keys"; runtimeInputs = [ pkgs.coreutils pkgs.curl pkgs.gnugrep ]; text = '' install -d -m 0700 -o ${lib.escapeShellArg cfg.user} -g ${lib.escapeShellArg cfg.group} ${lib.escapeShellArg sshDir} if [ ! -e ${lib.escapeShellArg authorizedKeysFile} ]; then install -m 0600 -o ${lib.escapeShellArg cfg.user} -g ${lib.escapeShellArg cfg.group} /dev/null ${lib.escapeShellArg authorizedKeysFile} fi 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 curl --fail --silent --show-error --location \ --connect-timeout 3 \ --max-time 10 \ --retry 3 \ --retry-delay 2 \ --header ${lib.escapeShellArg "Authorization: Bearer Oracle"} \ --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" 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}"; wantedBy = [ "sshd.service" "multi-user.target" ]; before = [ "sshd.service" ]; after = [ "network-online.target" ]; wants = [ "network-online.target" ]; serviceConfig = { Type = "oneshot"; RemainAfterExit = true; StandardError = "journal+console"; StandardOutput = "journal+console"; TimeoutStartSec = "30s"; }; script = lib.getExe fetchOciAuthorizedKeys; }; systemd.services.fetch-ssh-keys.enable = false; }; }