Add ssl_mgmt script
This commit is contained in:
parent
6c5525185c
commit
2b6d07e80b
|
@ -0,0 +1,70 @@
|
|||
ssl_mgmt is a helper to manage ssl certificate: creation, renewal and removal.
|
||||
So far, only renewal is supported.
|
||||
|
||||
ssl_mgmt refers to certificates through the service they are associated with.
|
||||
|
||||
*** EXAMPLES ***
|
||||
|
||||
To renew the certificate associated to https, the command line is:
|
||||
ssl_mgmt renew https
|
||||
|
||||
If you want to renew certificates of all services, you should do:
|
||||
ssl_mgmt renew all
|
||||
|
||||
Note: This suppose that
|
||||
* all services are listed in /root/homemade_certs;
|
||||
* directories have special rights so that newly created certificates
|
||||
automatically get proper rights;
|
||||
* Root CA is already created
|
||||
* openssl.cnf.in is copied at the root of the CA hierarchy
|
||||
|
||||
The file system hierarchy assumed is:
|
||||
lrwxrwxrwx 1 root root 14 6 janv. 2010 certs -> /etc/ssl/certs
|
||||
drws--S---+ 2 root ssl-cert 4096 23 janv. 2011 csr
|
||||
-rw------- 1 root ssl-cert 1937 20 févr. 16:38 index.txt
|
||||
-rw------- 1 root ssl-cert 20 20 févr. 16:38 index.txt.attr
|
||||
drwSr-Sr--+ 2 root ssl-cert 4096 20 févr. 16:38 newcerts
|
||||
drwSr-S---+ 2 root ssl-cert 4096 20 févr. 16:38 newkeys
|
||||
-rw-r--r-- 1 root ssl-cert 1546 20 févr. 14:24 openssl.cnf.in
|
||||
lrwxrwxrwx 1 root root 16 6 janv. 2010 private -> /etc/ssl/private
|
||||
-rw------- 1 root ssl-cert 3 20 févr. 16:38 serial
|
||||
|
||||
About csr, newcerts and newkeys:
|
||||
|
||||
# file: usr/lib/ssl/CA/csr
|
||||
# owner: root
|
||||
# group: ssl-cert
|
||||
# flags: ss-
|
||||
user::rwx
|
||||
group::---
|
||||
other::---
|
||||
default:user::rw-
|
||||
default:group::r--
|
||||
default:other::---
|
||||
|
||||
# file: usr/lib/ssl/CA/newcerts
|
||||
# owner: root
|
||||
# group: ssl-cert
|
||||
# flags: ss-
|
||||
user::rw-
|
||||
group::r--
|
||||
other::r--
|
||||
default:user::rw-
|
||||
default:group::r--
|
||||
default:other::r--
|
||||
|
||||
# file: usr/lib/ssl/CA/newkeys
|
||||
# owner: root
|
||||
# group: ssl-cert
|
||||
# flags: ss-
|
||||
user::rw-
|
||||
group::r--
|
||||
other::---
|
||||
default:user::rw-
|
||||
default:group::r--
|
||||
default:other::---
|
||||
|
||||
To use this script, you have to be root, or to be able to execute
|
||||
commands with root privileges through sudo.
|
||||
You should install it in a directory within the PATH of the root user,
|
||||
such as /usr/local/sbin.
|
|
@ -0,0 +1,62 @@
|
|||
#
|
||||
# OpenSSL configuration file.
|
||||
#
|
||||
|
||||
# Establish working directory
|
||||
dir = .
|
||||
|
||||
[ ca ]
|
||||
default_ca = CA_Default
|
||||
|
||||
[ CA_Default ]
|
||||
serial = $dir/serial
|
||||
database = $dir/index.txt
|
||||
new_certs_dir = $dir/newcerts
|
||||
certificate = $dir/certs/ca-cert.pem
|
||||
private_key = $dir/private/ca-key.pem
|
||||
default_days = #LENGTH# # Certificates are signed for default_days days
|
||||
default_md = md5
|
||||
preserve = no
|
||||
email_in_dn = no
|
||||
nameopt = default_ca
|
||||
certopt = default_ca
|
||||
policy = policy_match
|
||||
copy_extensions = copy
|
||||
|
||||
[ policy_match ]
|
||||
countryName = match
|
||||
stateOrProvinceName = match
|
||||
organizationName = match
|
||||
organizationalUnitName = optional
|
||||
commonName = supplied
|
||||
emailAddress = optional
|
||||
|
||||
[ req ]
|
||||
default_bits = 2048 # Taille des clés
|
||||
default_keyfile = newkeys/key.pem # Nom de la clé généré (à spécifier en ligne de commande si différent)
|
||||
default_md = md5 # Algorithme de résumé (hash)
|
||||
string_mask = nombstr # Caractères authorisés
|
||||
prompt = no
|
||||
distinguished_name = req_distinguished_name
|
||||
req_extensions = v3_req
|
||||
# On ne veut ces extensions que pour générer les certificats racines
|
||||
# donc on le spécifie sur la ligne de commande
|
||||
x509_extensions = v3_ca
|
||||
|
||||
[ req_distinguished_name ]
|
||||
organizationName = #ORG#
|
||||
organizationalUnitName = #ORGUNIT#
|
||||
localityName = #LOCALITY#
|
||||
stateOrProvinceName = #STATE#
|
||||
countryName = #COUNTRY#
|
||||
commonName = #COMMONNAME#
|
||||
|
||||
[ v3_ca ]
|
||||
basicConstraints = CA:TRUE
|
||||
subjectKeyIdentifier = hash
|
||||
authorityKeyIdentifier = keyid:always,issuer:always
|
||||
|
||||
[ v3_req ]
|
||||
basicConstraints = CA:FALSE
|
||||
subjectKeyIdentifier = hash
|
||||
subjectAltName = #ALTNAME#
|
|
@ -0,0 +1,253 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# ssl_mgmt, Copyright © 2012 Thomas Preud'homme
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# email_account is a helper to create e-mail accounts in a configuration
|
||||
# using Postfix mail transport agent with vhosts and Cyrus IMAP server,
|
||||
# in a Debian environment.
|
||||
|
||||
set -u
|
||||
|
||||
confFile=openssl.cnf
|
||||
|
||||
# Display usage.
|
||||
usage ()
|
||||
{
|
||||
local - progname
|
||||
progname=$1
|
||||
echo "Usage :"
|
||||
echo
|
||||
echo "$progname renew <service>"
|
||||
echo "$progname -h"
|
||||
echo
|
||||
echo "First form renew the certificate of the given service"
|
||||
echo
|
||||
echo "Second form prints this help."
|
||||
}
|
||||
|
||||
# @param question Question to ask
|
||||
# @return 0 if answer is positive, 1 else
|
||||
#
|
||||
# Ask question to the user with a default choice set to no.
|
||||
ask_user_default_no ()
|
||||
{
|
||||
local - answer
|
||||
answer="unset"
|
||||
echo -n "$1 [y/N] "
|
||||
while [ -n "$answer" -a "$answer" != "y" -a "$answer" != "Y" -a "$answer" != "n" -a "$answer" != "N" ]
|
||||
do
|
||||
read answer
|
||||
if [ -z "$answer" -o "$answer" = "n" -o "$answer" = "N" ]
|
||||
then
|
||||
return 1
|
||||
fi
|
||||
if [ "$answer" = "y" -o "$answer" = "Y" ]
|
||||
then
|
||||
break
|
||||
fi
|
||||
echo -n "$2 [y/N] "
|
||||
done
|
||||
return 0
|
||||
}
|
||||
|
||||
# Test number of argument is correct and their value are correct also.
|
||||
test_args ()
|
||||
{
|
||||
local - user domain
|
||||
while getopts "h" opt
|
||||
do
|
||||
case $opt in
|
||||
"h")
|
||||
if [ $# -gt 1 ]
|
||||
then
|
||||
echo "Error! Too many arguments." >&2
|
||||
exit 1
|
||||
fi
|
||||
usage $(basename "$0")
|
||||
exit 0 ;;
|
||||
esac
|
||||
done
|
||||
if [ $# -ne 2 -o "$1" != "renew" ]
|
||||
then
|
||||
usage $(basename "$0")
|
||||
exit 0
|
||||
fi
|
||||
eval service="\$$((OPTIND+1))"
|
||||
}
|
||||
|
||||
# Are we root?
|
||||
must_sudo ()
|
||||
{
|
||||
uid="$(id -u)"
|
||||
[ ! $uid -eq 0 ]
|
||||
return $?
|
||||
}
|
||||
|
||||
# This function tries to become root with sudo and execute this script.
|
||||
# NB: This function doesn't return.
|
||||
try_sudo ()
|
||||
{
|
||||
local - ret
|
||||
echo "You aren't root. Trying to use sudo to become root…"
|
||||
sudo $0 "$@" # Try to execute the script with sudo
|
||||
ret=$?
|
||||
if [ ! $ret -eq 0 ]
|
||||
then
|
||||
echo "Error! You must be root or being able to become root by sudo without password to create an email account or add an email alias." >&2
|
||||
fi
|
||||
exit $ret
|
||||
}
|
||||
|
||||
get_field_from_line ()
|
||||
{
|
||||
local - line field result
|
||||
|
||||
line="$1"
|
||||
field="$2"
|
||||
result="${line#*$field=}"
|
||||
echo "${result%%/*}"
|
||||
}
|
||||
|
||||
get_cert_params ()
|
||||
{
|
||||
local - subject issuer dates ext fromDate toDate
|
||||
|
||||
certFile="/etc/ssl/certs/${service}-cert.pem"
|
||||
subject="$(openssl x509 -in "$certFile" -noout -subject)"
|
||||
dates="$(openssl x509 -in "$certFile" -noout -dates)"
|
||||
exclNoExt="-certopt no_header,no_version,no_serial,no_signame"
|
||||
exclNoExt="$exclNoExt,no_validity,no_subject,no_issuer,no_pubkey"
|
||||
exclNoExt="$exclNoExt,no_sigdump,no_aux"
|
||||
altName="$(openssl x509 -in "$certFile" -text $exclNoExt | while read ext
|
||||
do
|
||||
if [ "$ext" = "X509v3 Subject Alternative Name:" ]
|
||||
then
|
||||
read altName
|
||||
echo $altName
|
||||
break
|
||||
fi
|
||||
done)"
|
||||
country=$(get_field_from_line "$subject" "C")
|
||||
state=$(get_field_from_line "$subject" "ST")
|
||||
city=$(get_field_from_line "$subject" "L")
|
||||
organization=$(get_field_from_line "$subject" "O")
|
||||
unit=$(get_field_from_line "$subject" "OU")
|
||||
commonName=$(get_field_from_line "$subject" "CN")
|
||||
fromDate=${dates#*notBefore=}
|
||||
fromDate=${fromDate%notAfter*}
|
||||
fromDate=$(date -d "$fromDate" "+%s")
|
||||
toDate=${dates#*notAfter=}
|
||||
toDate=$(date -d "$toDate" "+%s")
|
||||
days=$(($toDate-$fromDate))
|
||||
days=$(($days/86400))
|
||||
}
|
||||
|
||||
add_to_replace_cmd ()
|
||||
{
|
||||
local - replaceCmd key value
|
||||
|
||||
replaceCmd="$1"
|
||||
key="$2"
|
||||
value="$3"
|
||||
if [ -n "$value" ]
|
||||
then
|
||||
echo "$replaceCmd${replaceCmd:+;}s/$key/$value/"
|
||||
fi
|
||||
}
|
||||
|
||||
generate_config ()
|
||||
{
|
||||
local - replaceCmd cnfTmpFile
|
||||
|
||||
replaceCmd="$(add_to_replace_cmd "${replaceCmd:-}" "#LENGTH#" "${days:-}")"
|
||||
replaceCmd="$(add_to_replace_cmd "$replaceCmd" "#ORG#" "${organization:-}")"
|
||||
replaceCmd="$(add_to_replace_cmd "$replaceCmd" "#ORGUNIT#" "${unit:-}")"
|
||||
replaceCmd="$(add_to_replace_cmd "$replaceCmd" "#LOCALITY#" "${city:-}")"
|
||||
replaceCmd="$(add_to_replace_cmd "$replaceCmd" "#STATE#" "${state:-}")"
|
||||
replaceCmd="$(add_to_replace_cmd "$replaceCmd" "#COUNTRY#" "${country:-}")"
|
||||
replaceCmd="$(add_to_replace_cmd "$replaceCmd" "#COMMONNAME#" "${commonName:-}")"
|
||||
replaceCmd="$(add_to_replace_cmd "$replaceCmd" "#ALTNAME#" "${altName:-}")"
|
||||
sed "$replaceCmd" $confFile.in > $confFile
|
||||
if ask_user_default_no "Do you want to edit the openssl configuration file?"
|
||||
then
|
||||
if [ -z "${EDITOR:-}" ]
|
||||
then
|
||||
$EDITOR $confFile
|
||||
else
|
||||
editor $confFile
|
||||
fi
|
||||
fi
|
||||
cnfTmpFile="$(mktemp --tmpdir=. openssl.cnf.XXXXXXXXXX)"
|
||||
mv $confFile $cnfTmpFile
|
||||
grep -v "#[A-Z]\+#" $cnfTmpFile > $confFile
|
||||
rm $cnfTmpFile
|
||||
}
|
||||
|
||||
generate_cert ()
|
||||
{
|
||||
openssl req -new -nodes -out csr/${service}-req.pem -keyout newkeys/${service}-key.pem -config $confFile
|
||||
openssl req -in csr/${service}-req.pem -text -verify -noout
|
||||
if ! ask_user_default_no "Is the Certificate Signing Request correct?"
|
||||
then
|
||||
return 1
|
||||
fi
|
||||
mv newkeys/${service}-key.pem private
|
||||
openssl ca -batch -out newcerts/${service}-cert.pem -config $confFile -passin file:/root/passwords/root_ca -infiles csr/${service}-req.pem
|
||||
mv newcerts/${service}-cert.pem certs
|
||||
cat private/${service}-key.pem certs/${service}-cert.pem > private/${service}-keycert.pem
|
||||
return 0
|
||||
}
|
||||
|
||||
main ()
|
||||
{
|
||||
local - ret servicesok
|
||||
ret=0
|
||||
test_args "$@"
|
||||
# This test should be useless if rights on this file are corrects
|
||||
# (that is 770 for root:gt owner)
|
||||
if must_sudo
|
||||
then
|
||||
try_sudo "$@"
|
||||
fi
|
||||
cd /usr/lib/ssl/CA/
|
||||
if [ "${service}" = "all" ]
|
||||
then
|
||||
services=""
|
||||
while read service
|
||||
do
|
||||
services="$services $service"
|
||||
done </root/homemade-certs
|
||||
else
|
||||
services=${service}
|
||||
fi
|
||||
for service in $services
|
||||
do
|
||||
servicesok=""
|
||||
get_cert_params
|
||||
generate_config
|
||||
if ! generate_cert
|
||||
then
|
||||
ret=1
|
||||
else
|
||||
servicesok="$servicesok${servicesok:+ }$service"
|
||||
fi
|
||||
done
|
||||
echo "You should restart the following services: $servicesok"
|
||||
return $ret
|
||||
}
|
||||
|
||||
main "${@:-""}"
|
||||
exit $?
|
Loading…
Reference in New Issue