#!/usr/bin/env bash # vim:syntax=sh:ts=4 # Small helper to import new keyrings to /etc/apt/keyrings, i.e. to replace # "apt-key add" by something that does adhere to the new standard. # This requires ln-initfunctions, see: # - https://git.lirion.de/lirion-initfunctions/ # - https://packages.lirion.de/deb/pool/utils/l/ln-initfunctions/ # - https://packages.lirion.de/rpm/all/Packages/ # - https://packages.lirion.de/arch/ # shellcheck disable=SC1091 source '/usr/lib/lirion/ln-initfunctions' || exit 1 DEFKS='keyserver.ubuntu.com' KRDIR='/etc/apt/keyrings' GPGBIN='/usr/bin/gpg' # being more defensive here - there are still a number of raging old systems # running out there like SUSE's SLE 12 - /bin should be linked on any others, # so let's use the old path for the time being: SUDOBIN='/bin/sudo' # TOUCHBIN='/bin/touch' INSTBIN='/bin/install' RMBIN='/bin/rm' function hayulp { printf '\033[1mUSAGE:\033[0m \033[3m%b\033[0m -i KEYID -k KEYRING_SHORT [ -s KEYSERVER ]\n' "$(basename "$0")" printf '\n' printf 'Import GPG keys from GPG key servers.\n' printf '\n' printf 'This is meant as a helper replacing "apt-key add" which does not adhere to current standards.\n' printf 'Effectively, it uses gpg --recv-keys and keyring imports to place files in /etc/apt/keyrings.\n' printf 'Mind you if your IT dept. in 2025 still does not offer a GPG route, you have to use other means.\n' printf '\n' ( printf -- '--help,\n' printf -- '-h;This help\n;\n' printf -- '--key-id,\n' printf -- '-i;ID of key to be fetched from the public and imported\n;\n' printf -- '--keyring-short,\n' printf -- '-k;Name of the keyring file to save, without directory or\n' printf ';file extension (/etc/apt/keyrings/my-moniker.gpg becomes my-moniker)\n;\n' printf -- '--keyserver,\n' printf -- '-s;HKPS key server to use (Default: %b)\n' "$DEFKS" ) | column -ts\; } if [ -z "$1" ]; then hayulp printf '\n\033[1m\033[3mNo option given, aborting!\033[0m\n' >&2 exit 101 fi declare KID KRING KSRV while [[ $# -gt 0 ]]; do case "$1" in '-h'|'--help') hayulp exit 0 ;; '-i'|'--key-id') shift KID="$1" shift ;; '-k'|'--keyring-short') shift KRING="$1" shift ;; '-s'|'--keyserver') shift KSRV="$1" shift ;; *) hayulp printf '\n\033[1m\033[3mNot a valid option: "%b"\033[0m\n' "$1" >&2 exit 102 ;; esac done if [ -z "$KID" ]; then hayulp printf '\n\033[1;3mNo key ID specified, aborting.\033[0m\n' >&2 exit 103 fi if [ -z "$KRING" ]; then hayulp printf '\n\033[3;1mNo keyring shortname specified, aborting.\033[0m\n' >&2 exit 104 fi if printf '%b' "$KRING" | grep '/' > /dev/null; then hayulp printf '\n\033[3;1mDo not specify the full path for the keyring file.\033[0m\n' >&2 exit 105 elif printf '%b' "$KRING" | grep -P '\.gpg$' > /dev/null; then hayulp printf '\n\033[3;1mOnly specify the file name without .gpg extension.\033[0m\n' >&2 exit 106 fi if ! printf '%b' "$KID" | grep -P '^([0-9A-Fa-f]{8}){1,2}$|^[0-9A-Fa-f]{40}$' > /dev/null; then hayulp printf '\n\033[3;1mNot a valid key ID: "%b"\033[0m\n' "$KID" >&2 exit 107 fi if [ -z "$KSRV" ]; then KSRV="$DEFKS" else KSRV="$(printf '%b' "$KSRV" | sed 's#^[a-z]\+://##')" fi lnbegin "Using keyserver: $KSRV"; lninfo KID="$(printf '%b' "$KID" | tr '[:lower:]' '[:upper:]')" lnbegin "Creating temporary keyring file" if KRTMP="$(mktemp -p /tmp apt-keyring.XXXXXX 2>/dev/null)"; then lnok else lnfail exit 110 fi lnbegin "Importing key ID \"$KID\" to temporary file" if myout="$("$GPGBIN" --no-default-keyring --keyserver "$KSRV" --keyring "$KRTMP" --recv-keys "$KID" 2>&1)"; then lnok else lnfail printf '\n%b\n' "$myout" >&2 exit 111 fi lnbegin "Importing new/updated key to ${KRING}.gpg" # Ensure the file exists prior to importing - otherwise the result may not be the desired # OpenPGP v4 keyring. If it does exist before, even if empty, that will be the case. if [ ! -e "${KRDIR}/${KRING}.gpg" ]; then if myout="$("$SUDOBIN" "$INSTBIN" -oroot -groot -vm0644 /dev/null "${KRDIR}/${KRING}.gpg" 2>&1)"; then lnprog 'file created' else lnfail "file cannot be created" printf '\n%b\n' "$myout" >&2 exit 112 fi fi # Actual import to the target file: if myout="$("$SUDOBIN" "$GPGBIN" --no-default-keyring --keyring "${KRDIR}/${KRING}.gpg" --import "$KRTMP" 2>&1)"; then lnok else lnfail "import failed" printf '\n%b\n' "$myout" >&2 exit 113 fi lnbegin "Removing GPG temporary file" if myout="$("$SUDOBIN" "$RMBIN" -f "${KRDIR}/${KRING}.gpg~" 2>&1)"; then lnok else lnfail "removal failed" printf '\n%b\n' "$myout" >&2 exit 120 fi lnbegin "Removing temporary keyring" if myout="$("$RMBIN" -f "$KRTMP" "${KRTMP}~" 2>/dev/null)"; then lnok else lnfail printf '\n%b\n' "$myout" >&2 exit 121 fi printf '\033[3mListing keyring content:\033[0m\n' "$GPGBIN" --no-default-keyring --keyring "${KRDIR}/${KRING}.gpg" --list-keys