#!/bin/bash # # kmodgenca - Helper script to create CA/Keypair to sign modules. # Copyright (c) 2017 Stanislas Leduc # Copyright (c) 2018-2019 Nicolas ViƩville # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # MYPROG="kmodgenca" MYVER="0.5.7" FORCE_BUILD=0 AUTOMATIC_BUILD=0 AUTOMATIC_BUILD_OPTION="" myprog_help () { echo "Build CA/Keypair to sign modules" echo $'\n'"Usage: ${MYPROG} [OPTIONS]" echo $'\n'"Options:" echo " -a, --auto -- generate default values for cacert.config file without prompt" echo " -f, --force -- build CA/Keypair even if there is already ones" echo " -h, --help -- print usage" echo " -V, --version -- show version" } # Parse command line options. # while [ "${1}" ] ; do case "${1}" in -a|--auto) AUTOMATIC_BUILD=1 shift ;; -f|--force) FORCE_BUILD=1 shift ;; -h|--help) myprog_help exit 0 ;; -V|--version) echo "${MYPROG} ${MYVER}" exit 0 ;; *) echo "Error: Unknown option '${1}'." >&2 myprog_help >&2 exit 2 ;; esac done # Exit early if cert and private key already exist and if FORCE_BUILD # is not equal to 1. # if $(readlink -e /etc/pki/akmods/certs/public_key.der &>/dev/null) && \ $(readlink -e /etc/pki/akmods/private/private_key.priv &>/dev/null) && \ [ ${FORCE_BUILD} -eq 0 ] ; then exit 0 fi CACERT_CONFIG="/etc/pki/akmods/cacert.config" KEYNAME="$(hostname)"-"$(od -vAn -N4 -tu4 < /dev/urandom | awk '{print $1}')" # Create cacert.config file with local values if AUTOMATIC_BUILD is set # or ask for values manually. # echo "Update cacert.config..." if [ ${AUTOMATIC_BUILD} -eq 1 ] ; then # Set OpenSSL fields values, comment default values and min/max ones. sed -e "s#\(0.organizationName *= \).*#\1$(hostname)#" \ -e "s#\(organizationalUnitName *= \).*#\1$(hostname)#" \ -e "s#\(emailAddress *= \).*#\1akmods@$(hostname)#" \ -e "s#\(localityName *= \).*#\1None#" \ -e "s#\(stateOrProvinceName *= \).*#\1None#" \ -e "s#\(countryName *= \).*#\1$(locale country_ab2)#" \ -e "s#\(commonName *= \).*#\1$(hostname)"-"$(od -vAn -N4 -tu4 < /dev/urandom | awk '{print $1}')#" \ -e "s/^[^#]*_default *= /#&/" \ -e "s/^[^#]*_min/#&/" \ -e "s/^[^#]*_max/#&/" ${CACERT_CONFIG}.in > ${CACERT_CONFIG} AUTOMATIC_BUILD_OPTION=" -batch" else # Activate prompt directive. sed -e "s#\(prompt *= \).*#\1yes#" ${CACERT_CONFIG}.in > ${CACERT_CONFIG} fi KEY_SUFF="$(date "+%F_%T_%N")" # If cert and private key files names already exists, do not overwrite # them but save them. # if [[ -e /etc/pki/akmods/certs/${KEYNAME}.der ]] ; then # If the cert has already been loaded in MOK, add "already_enrolled" # to the suffix of the backup file. # `mokutil --help` fails if EFI variables are not supported on the # system. It is therefore impossible to test the presence of the key # in MOK, and then do not add special suffix to the backup file. # if $(which mokutil &> /dev/null) && $(mokutil --help &> /dev/null) && $(mokutil --test-key /etc/pki/akmods/certs/${KEYNAME}.der &> /dev/null) ; then KEY_SUFF="${KEY_SUFF}_already_enrolled" fi mv /etc/pki/akmods/certs/${KEYNAME}.der /etc/pki/akmods/certs/${KEYNAME}.der.${KEY_SUFF}.bak if [[ -e /etc/pki/akmods/private/${KEYNAME}.priv ]] ; then mv /etc/pki/akmods/private/${KEYNAME}.priv /etc/pki/akmods/private/${KEYNAME}.priv.${KEY_SUFF}.bak fi fi echo "Generate new keypair..." sg akmods -c " umask 037 openssl req -x509 -new -nodes -utf8 -sha256 -days 3650${AUTOMATIC_BUILD_OPTION} \ -config ${CACERT_CONFIG} -outform DER \ -out /etc/pki/akmods/certs/${KEYNAME}.der \ -keyout /etc/pki/akmods/private/${KEYNAME}.priv " # Ensure that akmods group can read keys. # chmod g+r /etc/pki/akmods/certs/${KEYNAME}.* chmod g+r /etc/pki/akmods/private/${KEYNAME}.* # Sanitize permissions. # if [[ -x /usr/sbin/restorecon ]] ; then /usr/sbin/restorecon /etc/pki/akmods/certs/${KEYNAME}.der /usr/sbin/restorecon /etc/pki/akmods/private/${KEYNAME}.priv fi # Update symlink to use new keypair. # ln -nsf /etc/pki/akmods/certs/${KEYNAME}.der /etc/pki/akmods/certs/public_key.der ln -nsf /etc/pki/akmods/private/${KEYNAME}.priv /etc/pki/akmods/private/private_key.priv exit 0