nvieville / rpms / akmods

Forked from rpms/akmods 6 years ago
Clone
Blob Blame History Raw
#!/bin/bash
#
# kmodgenca - Helper script to create CA/Keypair to sign modules.
# Copyright (c) 2017 Stanislas Leduc <stanislas.leduc@balinor.net>
# Copyright (c) 2018-2019 Nicolas ViƩville <nicolas.vieville@uphf.fr>
#
# 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