From a708e4fa6e3e46a170d719036a4b8a904b114bf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20unbrot=20P=C3=A4tzold?= Date: Wed, 17 Jun 2026 13:13:30 +0200 Subject: [PATCH 1/2] 0060_ssh_key: add private key escrow via IPA vault and README Provisions ~/.ssh/id_ed25519 once and stores it in the FreeIPA KRA vault so the key persists across reinstalls/new machines instead of being regenerated each time. Guards against silently overwriting an existing vault key on transient failures (missing ~/.ssh, vault-add errors, ssh-keygen failures) before archiving. Co-Authored-By: Claude Sonnet 4.6 --- client_software/0060_ssh_key/README.md | 20 ++++++++ client_software/0060_ssh_key/user_run.sh | 59 ++++++++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 client_software/0060_ssh_key/README.md create mode 100755 client_software/0060_ssh_key/user_run.sh diff --git a/client_software/0060_ssh_key/README.md b/client_software/0060_ssh_key/README.md new file mode 100644 index 0000000..a7c2708 --- /dev/null +++ b/client_software/0060_ssh_key/README.md @@ -0,0 +1,20 @@ +# 0060_ssh_key + +Provisions a per-user `~/.ssh/id_ed25519` key and escrows it in the FreeIPA +KRA vault (`SSH_PRIV_KEY`), so the same key is reused across machines instead +of generating a new one on every install. + +Run as the logged-in user via `client_software/user_run.sh` (needs the +`DAVTOKEN_USER` environment prepared by `sync_client_software.sh`). + +Behavior: +- If `~/.ssh/id_ed25519` already exists locally, it's left untouched. +- Otherwise, tries `ipa vault-retrieve` for `SSH_PRIV_KEY`: + - found → key is fetched, permissions fixed to `0600`, public key derived. + - not found → a new vault is created, a new key pair is generated, and the + private key is archived to the vault. +- Requires `IPAVAULTUSE=true` (KRA available); otherwise the script is a + no-op. + +Note: this only handles private-key escrow. Publishing the public key to the +user's FreeIPA entry (`ipa user-mod --sshpubkey`) is not done by this script. diff --git a/client_software/0060_ssh_key/user_run.sh b/client_software/0060_ssh_key/user_run.sh new file mode 100755 index 0000000..47749da --- /dev/null +++ b/client_software/0060_ssh_key/user_run.sh @@ -0,0 +1,59 @@ +#!/usr/bin/env sh +# SPDX-FileCopyrightText: Daniel Pätzold +# SPDX-License-Identifier: AGPL-3.0-or-later +# +# If IPA-KRA is available, use it to store or retrieve personal private ssh key, so that the key won't change every time on new installs +# + +#Check Token +if [ "${DAVTOKEN_USER}." == "." ]; then + echo "Error: Script cannot be executed standalone and needs a prereserved environment from sync_client_software.sh. Quit." + exit 1 +fi + +KEYFILE="${HOME}/.ssh/id_ed25519" +SSHVAULTNAME="SSH_PRIV_KEY" +if [ ${IPAVAULTUSE} = "false" ]; then + echo "No IPA- KRA service configured, SSH Key provisioning to and from IPA is not available." +else + if [ -f ${KEYFILE} ]; then + echo "SSH Key already present at ${KEYFILE}. Leaving it untouched." + else + mkdir -p "${HOME}/.ssh" + echo "SSH Key ${KEYFILE} not found. Getting Key from IPA- Vault" + ipa vault-retrieve "${SSHVAULTNAME}" --out ${KEYFILE} + if [ $? -ne 0 ]; then + echo "Seems there is no key yet on IPA, creating it new." + ipa vault-add "${SSHVAULTNAME}" --desc "SSH private key (Stored by OEMDRV autoinstall Modules)" --type=standard + if [ $? -ne 0 ]; then + echo "Error creating the new Vault named ${SSHVAULTNAME} on IPA. This should not happen, aborting. Please check." + exit 1 + else + ssh-keygen -t ed25519 -C "$(whoami)" -f ${KEYFILE} + if [ $? -ne 0 ]; then + echo "Error generating the new SSH key at ${KEYFILE}. Aborting without touching the Vault. Please check." + exit 1 + fi + ipa vault-archive "${SSHVAULTNAME}" --in ${KEYFILE} + if [ $? -ne 0 ]; then + echo "Error storing the Key to the created Vault ${SSHVAULTNAME}. This should not happen, aborting. Please check." + exit 1 + else + echo "Sucessfully created SSH Key and stored it in IPAs KRA Vault named ${SSHVAULTNAME}." + fi + fi + else + # derive public key from private key when enrolling to new system + ssh-keygen -y -f "${KEYFILE}" > "${KEYFILE}.pub" + if [ $? -eq 0 ]; then + chmod 0600 "${KEYFILE}" "${KEYFILE}.pub" + echo "Sucessfully fetched SSH Key from IPA." + else + echo "Something went wrong with Key provisioning, please check." + exit 1 + fi + fi + fi +fi + +exit 0 -- 2.52.0 From 6fe96f82fd775c4fc18b62eaf59e70be366e687c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20unbrot=20P=C3=A4tzold?= Date: Wed, 17 Jun 2026 13:49:33 +0200 Subject: [PATCH 2/2] 0060_ssh_key: relocate ~/.ssh into encrypted data dir, generate non-interactively Symlinks ~/.ssh to ${DECRYPTEDDATADIR}/ssh_keys (migrating any existing content once) so the key lives in the gocryptfs-encrypted area instead of the plain home directory. Also passes -N "" to ssh-keygen so key generation no longer prompts for a passphrase. Co-Authored-By: Claude Sonnet 4.6 --- client_software/0060_ssh_key/README.md | 6 ++++- client_software/0060_ssh_key/user_run.sh | 28 +++++++++++++++++++++--- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/client_software/0060_ssh_key/README.md b/client_software/0060_ssh_key/README.md index a7c2708..16fb9f3 100644 --- a/client_software/0060_ssh_key/README.md +++ b/client_software/0060_ssh_key/README.md @@ -8,7 +8,11 @@ Run as the logged-in user via `client_software/user_run.sh` (needs the `DAVTOKEN_USER` environment prepared by `sync_client_software.sh`). Behavior: -- If `~/.ssh/id_ed25519` already exists locally, it's left untouched. +- `~/.ssh` is relocated to `${DECRYPTEDDATADIR}/ssh_keys` (the user's + gocryptfs-encrypted data dir) on first run: any existing content is moved + there once, then `~/.ssh` becomes a symlink to it. Subsequent runs detect + the symlink and skip this step. +- If `~/.ssh/id_ed25519` already exists, it's left untouched. - Otherwise, tries `ipa vault-retrieve` for `SSH_PRIV_KEY`: - found → key is fetched, permissions fixed to `0600`, public key derived. - not found → a new vault is created, a new key pair is generated, and the diff --git a/client_software/0060_ssh_key/user_run.sh b/client_software/0060_ssh_key/user_run.sh index 47749da..3cc1a21 100755 --- a/client_software/0060_ssh_key/user_run.sh +++ b/client_software/0060_ssh_key/user_run.sh @@ -11,15 +11,37 @@ if [ "${DAVTOKEN_USER}." == "." ]; then exit 1 fi -KEYFILE="${HOME}/.ssh/id_ed25519" +SSHDIR="${HOME}/.ssh" +SSHDIR_REAL="${DECRYPTEDDATADIR}/ssh_keys" +KEYFILE="${SSHDIR}/id_ed25519" SSHVAULTNAME="SSH_PRIV_KEY" + +#Relocate ~/.ssh into the encrypted data directory, migrating any existing content once +if [ ! -L "${SSHDIR}" ]; then + mkdir -p "${SSHDIR_REAL}" + chmod 0700 "${SSHDIR_REAL}" + if [ -d "${SSHDIR}" ]; then + echo "Migrating existing ${SSHDIR} contents to ${SSHDIR_REAL}." + cp -a "${SSHDIR}/." "${SSHDIR_REAL}/" + if [ $? -ne 0 ]; then + echo "Error migrating ${SSHDIR} contents to ${SSHDIR_REAL}. Aborting, please check." + exit 1 + fi + rm -rf "${SSHDIR}" + fi + ln -s "${SSHDIR_REAL}" "${SSHDIR}" + if [ $? -ne 0 ]; then + echo "Error creating symlink ${SSHDIR} -> ${SSHDIR_REAL}. Aborting, please check." + exit 1 + fi +fi + if [ ${IPAVAULTUSE} = "false" ]; then echo "No IPA- KRA service configured, SSH Key provisioning to and from IPA is not available." else if [ -f ${KEYFILE} ]; then echo "SSH Key already present at ${KEYFILE}. Leaving it untouched." else - mkdir -p "${HOME}/.ssh" echo "SSH Key ${KEYFILE} not found. Getting Key from IPA- Vault" ipa vault-retrieve "${SSHVAULTNAME}" --out ${KEYFILE} if [ $? -ne 0 ]; then @@ -29,7 +51,7 @@ else echo "Error creating the new Vault named ${SSHVAULTNAME} on IPA. This should not happen, aborting. Please check." exit 1 else - ssh-keygen -t ed25519 -C "$(whoami)" -f ${KEYFILE} + ssh-keygen -t ed25519 -C "$(whoami)" -N "" -f ${KEYFILE} if [ $? -ne 0 ]; then echo "Error generating the new SSH key at ${KEYFILE}. Aborting without touching the Vault. Please check." exit 1 -- 2.52.0