« Security/sevices/SSLCertificate/Apache » : différence entre les versions
| (25 versions intermédiaires par le même utilisateur non affichées) | |||
| Ligne 1 : | Ligne 1 : | ||
== Introduction == | |||
Cette page explique les opérations nécessaires pour la configuration d'un serveur Apache v2 utilisant des certificats utilisateurs. Ces certificats pourront être révoqués facilement. | |||
== Pré-requis == | |||
*Le module ssl doit être activé dans la configuration d'Apache et la configuration ssl est incluse : | |||
:* Le module est chargé :<pre>LoadModule ssl_module modules/mod_ssl.so</pre> | |||
:* La configuration ssl est incluse :<pre>Include conf.d/ssl.conf</pre> | |||
* Le firewall est ouvert pour une connection '''https''' sur le port '''443''' en '''TCP'''<pre>iptables -I INPUT -p tcp --dport 443 -j ACCEPT</pre><pre>iptables -I OUTPUT -p tcp -m tcp --dport 443 -j ACCEPT</pre> | |||
== Préparation == | == Préparation == | ||
| Ligne 12 : | Ligne 22 : | ||
<pre> | <pre> | ||
HOME = | HOME = /etc/pki/httpd | ||
RANDFILE = .rand | RANDFILE = /etc/pki/httpd/.rand | ||
[ca] | [ca] | ||
default_ca = ca_default | default_ca = ca_default | ||
[ca_default] | [ca_default] | ||
dir = | dir = /etc/pki/httpd | ||
certs = $dir/certs | certs = $dir/certs | ||
crl_dir = $dir/crl | crl_dir = $dir/crl | ||
database = $dir/index.txt | database = $dir/index.txt | ||
new_certs_dir = $dir/newcerts | new_certs_dir = $dir/newcerts | ||
certificate = $dir/httpd_ca.crt | certificate = $dir/httpd_ca.crt | ||
private_key = $dir/private/httpd_ca.key | private_key = $dir/private/httpd_ca.key | ||
serial = $dir/serial | serial = $dir/serial | ||
crl = $dir/crl | crl = $dir/ca.crl | ||
crlnumber = $dir/crlnumber | crlnumber = $dir/crlnumber | ||
crl_extensions = crl_ext | crl_extensions = crl_ext | ||
x509_extensions = usr_cert | x509_extensions = usr_cert | ||
name_opt = ca_default | name_opt = ca_default | ||
cert_opt = ca_default | cert_opt = ca_default | ||
| Ligne 52 : | Ligne 62 : | ||
distinguished_name = req_distinguished_name | distinguished_name = req_distinguished_name | ||
attributes = req_attributes | attributes = req_attributes | ||
x509_extensions = v3_ca | x509_extensions = v3_ca | ||
string_mask = MASK:0x2002 | string_mask = MASK:0x2002 | ||
| Ligne 89 : | Ligne 99 : | ||
basicConstraints = CA:true | basicConstraints = CA:true | ||
[ crl_ext ] | [crl_ext] | ||
authorityKeyIdentifier=keyid:always,issuer:always | |||
[OCSP] | |||
authorityKeyIdentifier=keyid:always,issuer:always | basicConstraints = CA:FALSE | ||
keyUsage = digitalSignature | |||
extendedKeyUsage = OCSPSigning | |||
issuerAltName = issuer:copy | |||
subjectKeyIdentifier = hash | |||
authorityKeyIdentifier = keyid:always,issuer:always | |||
authorityInfoAccess = OCSP;URI:http://didier.domicile.org/ | |||
[OCSP_SERVER] | |||
nsComment = "OpenSSL Generated Server Certificate" | |||
subjectKeyIdentifier = hash | |||
authorityKeyIdentifier = keyid,issuer:always | |||
issuerAltName = issuer:copy | |||
basicConstraints = critical,CA:FALSE | |||
keyUsage = digitalSignature, nonRepudiation, keyEncipherment | |||
nsCertType = server | |||
extendedKeyUsage = serverAuth | |||
authorityInfoAccess = OCSP;URI:http://didier.domicile.org/ | |||
[OCSP_CLIENT] | |||
nsComment = "OpenSSL Generated Client Certificate" | |||
subjectKeyIdentifier = hash | |||
authorityKeyIdentifier = keyid,issuer:always | |||
issuerAltName = issuer:copy | |||
basicConstraints = critical,CA:FALSE | |||
keyUsage = digitalSignature, nonRepudiation | |||
nsCertType = client | |||
extendedKeyUsage = clientAuth | |||
authorityInfoAccess = OCSP;URI:http://didier.domicile.org/ | |||
</pre> | </pre> | ||
| Ligne 147 : | Ligne 186 : | ||
echo "Generate web certificates for \"${user}\"" | echo "Generate web certificates for \"${user}\"" | ||
openssl pkcs12 -export -inkey certs/${user}.key -in certs/${user} | openssl pkcs12 -export -inkey certs/${user}.key -in certs/${user}.crt \ | ||
-out certs/${user}_browser_cert.p12 | -out certs/${user}_browser_cert.p12 | ||
| Ligne 179 : | Ligne 218 : | ||
# Regen CRL list | # Regen CRL list | ||
openssl ca -gencrl -config ssl.cnf -out crl | openssl ca -gencrl -config ssl.cnf -out ca.crl | ||
</syntaxhighlight> | </syntaxhighlight> | ||
| Ligne 238 : | Ligne 277 : | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
cd /etc/pki/httpd/ | cd /etc/pki/httpd/ | ||
ln crl | ln ca.crl crl/ | ||
cd crl | cd crl | ||
ln -s crl | ln -s ca.crl `openssl crl -hash -noout -in ca.crl`.r0 | ||
</syntaxhighlight> | </syntaxhighlight> | ||
| Ligne 277 : | Ligne 316 : | ||
SSLEngine on | SSLEngine on | ||
SSLProtocol all -SSLv2 | SSLProtocol all -SSLv2 | ||
SSLCipherSuite RC4-SHA:AES128-SHA:ALL:!ADH:!EXP:!LOW:!MD5:!SSLV2:!NULL | SSLCipherSuite RC4-SHA:AES128-SHA:ALL:!ADH:!EXP:!LOW:!MD5:!SSLV2:!NULL | ||
SSLHonorCipherOrder on | |||
SSLHonorCipherOrder on | |||
SSLCertificateFile /etc/pki/httpd/certs/httpd.crt | SSLCertificateFile /etc/pki/httpd/certs/httpd.crt | ||
SSLCertificateKeyFile /etc/pki/httpd/certs/httpd.key | SSLCertificateKeyFile /etc/pki/httpd/certs/httpd.key | ||
SSLCACertificateFile /etc/pki/httpd/httpd_ca.crt | SSLCACertificateFile /etc/pki/httpd/httpd_ca.crt | ||
SSLCARevocationPath /etc/pki/httpd/crl/ | SSLCARevocationPath /etc/pki/httpd/crl/ | ||
SSLVerifyClient require | SSLVerifyClient require | ||
SSLVerifyDepth 2 | SSLVerifyDepth 2 | ||
| Ligne 311 : | Ligne 342 : | ||
</VirtualHost> | </VirtualHost> | ||
</syntaxhighlight> | </syntaxhighlight> | ||
{{Admon/ | {{Admon/important|Redémarrage du service web|Il faut redémarrer Apache pour que les nouveaux paramètres soient pris en compte. | ||
Avec '''sysVinit''' | Avec '''sysVinit''' | ||
<pre>service httpd restart</pre> | <pre>service httpd restart</pre> | ||
| Ligne 376 : | Ligne 407 : | ||
TransferLog logs/ssl_access_log | TransferLog logs/ssl_access_log | ||
LogLevel warn | LogLevel warn | ||
SSLEngine on | SSLEngine on | ||
SSLProtocol all -SSLv2 | SSLProtocol all -SSLv2 | ||
SSLCipherSuite RC4-SHA:AES128-SHA:ALL:!ADH:!EXP:!LOW:!MD5:!SSLV2:!NULL | SSLCipherSuite RC4-SHA:AES128-SHA:ALL:!ADH:!EXP:!LOW:!MD5:!SSLV2:!NULL | ||
SSLHonorCipherOrder on | |||
SSLHonorCipherOrder on | |||
SSLCertificateFile /etc/pki/httpd/certs/httpd.crt | SSLCertificateFile /etc/pki/httpd/certs/httpd.crt | ||
SSLCertificateKeyFile /etc/pki/httpd/certs/httpd.key | SSLCertificateKeyFile /etc/pki/httpd/certs/httpd.key | ||
SSLCACertificateFile /etc/pki/httpd/httpd_ca.crt | SSLCACertificateFile /etc/pki/httpd/httpd_ca.crt | ||
SSLCARevocationPath /etc/pki/httpd/crl/ | SSLCARevocationPath /etc/pki/httpd/crl/ | ||
SSLVerifyClient require | SSLVerifyClient require | ||
SSLVerifyDepth 2 | SSLVerifyDepth 2 | ||
| Ligne 411 : | Ligne 434 : | ||
</VirtualHost> | </VirtualHost> | ||
NameVirtualHost 192.168.0.100:443 | |||
<VirtualHost 192.168.0.100:443> | <VirtualHost 192.168.0.100:443> | ||
| Ligne 441 : | Ligne 466 : | ||
</VirtualHost> | </VirtualHost> | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== Répartition de charge == | |||
Il sera de la responsabilité de l'administrateur de recopier ( ou de mettre en place une réplication Raid sur IP, une tâche {{app|cron}} ) le répertoire <path>/etc/pki/httpd</path> sur tous les noeuds du cluster à chaque modification ( ajout, révocation, renouvellement, etc... ) | |||
Exemple d'ajout d'une grappe à un cluster ( ipvsadm ) dont l'IP WAN est 1.2.3.4: | |||
ipvsadm -A -t 1.2.3.4:443 -s lc | |||
ipvsadm -a -t 1.2.3.4:443 -r 192.168.0.1:443 -m | |||
ipvsadm -a -t 1.2.3.4:443 -r 192.168.0.2:443 -m | |||
ipvsadm -a -t 1.2.3.4:443 -r 192.168.0.3:443 -m | |||
Destruction du cluster | |||
ipvsadm -d -t 1.2.3.4:443 -r 192.168.0.1:443 -m | |||
ipvsadm -d -t 1.2.3.4:443 -r 192.168.0.2:443 -m | |||
ipvsadm -d -t 1.2.3.4:443 -r 192.168.0.3:443 -m | |||
ipvsadm -D -t 1.2.3.4:443 -s lc | |||
== Utilisation avec PHP == | == Utilisation avec PHP == | ||
| Ligne 465 : | Ligne 506 : | ||
Dans le cas qui nous intéresse, on vérifie le nom en lisant la varible '''SSL_CLIENT_S_DN_CN''' et l'email associé avec '''SSL_CLIENT_S_DN_Email'''. | Dans le cas qui nous intéresse, on vérifie le nom en lisant la varible '''SSL_CLIENT_S_DN_CN''' et l'email associé avec '''SSL_CLIENT_S_DN_Email'''. | ||
Exemple de script PHP affichant le tableau suivant | |||
{| class="wikitable" | |||
! Clé de $_SERVER | |||
! Valeur | |||
! Commentaires | |||
|- | |||
| SSL_CLIENT_VERIFY | |||
| SUCCESS | |||
| Client utilisant un certificat valide si égal à SUCCESS | |||
|- | |||
| SSL_CLIENT_S_DN_CN | |||
| didier | |||
| Utilisateur (CN) | |||
|- | |||
| SSL_CLIENT_S_DN_Email | |||
| didier@localhost | |||
| Email | |||
|- | |||
| SSL_SERVER_S_DN_C | |||
| FR | |||
| Code pays | |||
|- | |||
| SSL_SERVER_S_DN_ST | |||
| Languedoc-Roussillon | |||
| Etat ou région | |||
|- | |||
| SSL_SERVER_S_DN_O | |||
| Home | |||
| Organisation | |||
|} | |||
<syntaxhighlight lang="html4strict"> | |||
<!DOCTYPE html> | |||
<html> | |||
<head> | |||
<title>Test</title> | |||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> | |||
<style> | |||
th, td, table { | |||
border:1px black solid; | |||
border-collapse:collapse; | |||
padding: 5px; | |||
text-align:left; | |||
} | |||
th { background-color:lightgrey;} | |||
</style> | |||
</head> | |||
<body> | |||
<table> | |||
<tr> | |||
<th>Clé de $_SERVER</th> | |||
<th>Valeur</th> | |||
<th>Commentaires</th> | |||
</tr> | |||
<tr> | |||
<td>SSL_CLIENT_VERIFY</td> | |||
<td><?php echo $_SERVER['SSL_CLIENT_VERIFY'];?></td> | |||
<td>Client utilisant un certificat valide si égal à SUCCESS</td> | |||
</tr> | |||
<tr> | |||
<td>SSL_CLIENT_S_DN_CN</td> | |||
<td><?php echo $_SERVER['SSL_CLIENT_S_DN_CN'];?></td> | |||
<td>Utilisateur (CN)</td> | |||
</tr> | |||
<tr> | |||
<td>SSL_CLIENT_S_DN_Email</td> | |||
<td><?php echo $_SERVER['SSL_CLIENT_S_DN_Email'];?></td> | |||
<td>Email</td> | |||
</tr> | |||
<tr> | |||
<td>SSL_SERVER_S_DN_C</td> | |||
<td><?php echo $_SERVER['SSL_SERVER_S_DN_C'];?></td> | |||
<td>Code pays</td> | |||
</tr> | |||
<tr> | |||
<td>SSL_SERVER_S_DN_ST</td> | |||
<td><?php echo $_SERVER['SSL_SERVER_S_DN_ST'];?></td> | |||
<td>Etat ou région</td> | |||
</tr> | |||
<tr> | |||
<td>SSL_SERVER_S_DN_O</td> | |||
<td><?php echo $_SERVER['SSL_SERVER_S_DN_O'];?></td> | |||
<td>Organisation</td> | |||
</tr> | |||
</table> | |||
</body> | |||
</html> | |||
</syntaxhighlight> | |||
== All in one script == | |||
[[Scripts/manageCA| manageCA Script]] | |||
{{:Scripts/manageCA}} | |||
== Références == | == Références == | ||
<references/> | <references/> | ||
Dernière version du 7 janvier 2013 à 17:52
Introduction
Cette page explique les opérations nécessaires pour la configuration d'un serveur Apache v2 utilisant des certificats utilisateurs. Ces certificats pourront être révoqués facilement.
Pré-requis
- Le module ssl doit être activé dans la configuration d'Apache et la configuration ssl est incluse :
- Le module est chargé :
LoadModule ssl_module modules/mod_ssl.so
- La configuration ssl est incluse :
Include conf.d/ssl.conf
- Le module est chargé :
- Le firewall est ouvert pour une connection https sur le port 443 en TCP
iptables -I INPUT -p tcp --dport 443 -j ACCEPT
iptables -I OUTPUT -p tcp -m tcp --dport 443 -j ACCEPT
Préparation
Création du répertoire des certificats
mkdir /etc/pki/httpd && cd /etc/pki/httpd
Création du fichier de configuration de nos futurs certificats
On créer le fichier <path>/etc/pki/httpd/ssl.cnf</path>
HOME = /etc/pki/httpd RANDFILE = /etc/pki/httpd/.rand [ca] default_ca = ca_default [ca_default] dir = /etc/pki/httpd certs = $dir/certs crl_dir = $dir/crl database = $dir/index.txt new_certs_dir = $dir/newcerts certificate = $dir/httpd_ca.crt private_key = $dir/private/httpd_ca.key serial = $dir/serial crl = $dir/ca.crl crlnumber = $dir/crlnumber crl_extensions = crl_ext x509_extensions = usr_cert name_opt = ca_default cert_opt = ca_default default_days = 365 default_crl_days = 30 default_md = md5 preserve = no policy = policy_match [policy_match] countryName = match stateOrProvinceName = match organizationName = match organizationalUnitName = optional commonName = supplied emailAddress = optional [req] default_bits = 1024 default_keyfile = privkey.pem distinguished_name = req_distinguished_name attributes = req_attributes x509_extensions = v3_ca string_mask = MASK:0x2002 [req_distinguished_name] countryName = Country Name (2 letter code) countryName_default = FR countryName_min = 2 countryName_max = 2 stateOrProvinceName = State or Province Name (full name) stateOrProvinceName_default = Languedoc-Roussillon localityName = Locality Name (eg, city) localityName_default = Beaucaire 0.organizationName = Organization Name (eg, company) 0.organizationName_default = Home organizationalUnitName = Organizational Unit Name (eg, section) commonName = Common Name (eg, your name or your server\'s hostname) commonName_max = 64 emailAddress = Email Address emailAddress_max = 64 [req_attributes] challengePassword = A challenge password challengePassword_min = 4 challengePassword_max = 20 unstructuredName = An optional company name [usr_cert] basicConstraints = CA:FALSE nsComment = "OpenSSL Generated Certificate" subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer:always [v3_ca] subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always,issuer:always basicConstraints = CA:true [crl_ext] authorityKeyIdentifier=keyid:always,issuer:always [OCSP] basicConstraints = CA:FALSE keyUsage = digitalSignature extendedKeyUsage = OCSPSigning issuerAltName = issuer:copy subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always,issuer:always authorityInfoAccess = OCSP;URI:http://didier.domicile.org/ [OCSP_SERVER] nsComment = "OpenSSL Generated Server Certificate" subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer:always issuerAltName = issuer:copy basicConstraints = critical,CA:FALSE keyUsage = digitalSignature, nonRepudiation, keyEncipherment nsCertType = server extendedKeyUsage = serverAuth authorityInfoAccess = OCSP;URI:http://didier.domicile.org/ [OCSP_CLIENT] nsComment = "OpenSSL Generated Client Certificate" subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer:always issuerAltName = issuer:copy basicConstraints = critical,CA:FALSE keyUsage = digitalSignature, nonRepudiation nsCertType = client extendedKeyUsage = clientAuth authorityInfoAccess = OCSP;URI:http://didier.domicile.org/
Création des scripts de gestion de certificats
Par simplicité, on va se servir de ces scripts pour générer les certificats des utilisateurs.
Script de génération des certificats
Fichier <path>/etc/pki/httpd/generate-certificate.sh</path>
#!/bin/bash
# user is equal to parameter one or the first argument when you actually run the script
user=$1
if [[ "$user" == "" ]]
then
echo "Usage: $(basename $0) USER"
exit
fi
echo "Generate certificates for \"${user}\""
openssl genrsa -out certs/${user}.key 2048
cat ssl.cnf | sed 's/insert_hostname/'${user}'/'> ssl2.cnf
openssl req -config ssl2.cnf -new -nodes -out certs/${user}.csr -key certs/${user}.key
openssl ca -config ssl2.cnf \
-out certs/${user}.crt -outdir certs -infiles certs/${user}.csr
cat certs/${user}.crt certs/${user}.key > pem/${user}.pem
mv ssl2.cnf confs/${user}-ssl.cnf
Fichier <path>/etc/pki/httpd/generate-web-certificate.sh</path>
#!/bin/bash
# user is equal to parameter one or the first argument when you actually run the script
user=$1
if [[ "$user" == "" ]]
then
echo "Usage: $(basename $0) USER"
exit
fi
echo "Generate web certificates for \"${user}\""
openssl pkcs12 -export -inkey certs/${user}.key -in certs/${user}.crt \
-out certs/${user}_browser_cert.p12
Script de revocation de certificats
Fichier <path>/etc/pki/httpd/revoke-certificate.sh</path>
#!/bin/bash
# user is equal to parameter one or the first argument when you actually run the script
user=$1
if [[ "$user" == "" ]]
then
echo "Usage: $(basename $0) USER"
exit
fi
echo "Revoke certificates for \"${user}\""
openssl ca -revoke certs/${user}.crt -config ssl.cnf
# Save old certificate
x=1
while [ -f "certs/${user}.revoked.$x.crt" ]
do
x=$(( $x + 1 ))
done
mv certs/${user}.crt certs/${user}.revoked.$x.crt
# Regen CRL list
openssl ca -gencrl -config ssl.cnf -out ca.crl
Script de renouvellement de certificats
Fichier <path>/etc/pki/httpd/renew-certificate.sh</path>
Il faut révoquer l'ancien certificat et signer la demande de certificat créée initialement, basée sur sa clef privée.
L'ancien certificat se retrouve en cherchant dans le fichier index.txt le nom qualifié (DN) qui correspond à la requête. La procédure de révocation s'effectue ensuite avec le numéro de série <xx> et le fichier de certificat cert/<xx>.pem.
La signature de la nouvelle requête peut être manuelle pour s'assurer que les dates de validité du certificat seront correctes.
#!/bin/bash
# user is equal to parameter one or the first argument when you actually run the script
user=$1
if [[ "$user" == "" ]]
then
echo "Usage: $(basename $0) USER"
exit
fi
echo "Renew certificates for \"${user}\""
./revoke-certificate.sh ${user}
openssl ca -config confs/${user}-ssl.cnf \
-out certs/${user}.crt -outdir certs -infiles certs/${user}.csr
cat certs/${user}.crt certs/${user}.key > ${user}.pem
Mise en place
Génération de l'autorité de certification
Toujours depuis le répertoire /etc/pki/httpd, on initialise notre générateur et on génère l’autorité de certification. Celle-ci se compose d'une paire clé/certificat qui servira à signer tous les autres certificats.
Ici, le CN sera obligatoirement le nom d'hôte du serveur (FQDN), les autres renseignements ne sont pas bloquants pour la suite.
cd /etc/pki/httpd/
mkdir {certs,newcerts,private,confs,crl,pem}
touch index.txt
echo 01 > serial
echo 01 > crlnumber
openssl genrsa -out private/httpd_ca.key 2048
openssl req -config ssl.cnf -new -x509 -days 3650 -key private/httpd_ca.key \
-out httpd_ca.crt -extensions v3_ca
Activation de la Liste des certificats révoqués : Certificate Revocation Lists (CRL)
On active la CRL en deux temps [1]
- création d'un lien en dur ( ou copie ) du fichier crl dans le répertoire crl
- création d'un lien symbolique de celui-ci en le nommant avec un hash ( donné par openssl )
cd /etc/pki/httpd/
ln ca.crl crl/
cd crl
ln -s ca.crl `openssl crl -hash -noout -in ca.crl`.r0
Génération du certificat pour Apache
Il faut créer un certificat valide pour le serveur
cd /etc/pki/httpd/
./generate-certificate.sh httpd
Configuration d'Apache
Fichier <path>/etc/httpd/conf.d/ssl.conf</path>
LoadModule ssl_module modules/mod_ssl.so
Listen 443
SSLPassPhraseDialog exec:/usr/libexec/httpd-ssl-pass-dialog
SSLSessionCache shmcb:/var/cache/mod_ssl/scache(512000)
SSLSessionCacheTimeout 300
SSLMutex default
SSLRandomSeed startup file:/dev/urandom 256
SSLRandomSeed connect builtin
SSLCryptoDevice builtin
<VirtualHost _default_:443>
ErrorLog logs/ssl_error_log
TransferLog logs/ssl_access_log
LogLevel warn
SSLEngine on
SSLProtocol all -SSLv2
SSLCipherSuite RC4-SHA:AES128-SHA:ALL:!ADH:!EXP:!LOW:!MD5:!SSLV2:!NULL
SSLHonorCipherOrder on
SSLCertificateFile /etc/pki/httpd/certs/httpd.crt
SSLCertificateKeyFile /etc/pki/httpd/certs/httpd.key
SSLCACertificateFile /etc/pki/httpd/httpd_ca.crt
SSLCARevocationPath /etc/pki/httpd/crl/
SSLVerifyClient require
SSLVerifyDepth 2
<Files ~ "\.(cgi|shtml|phtml|php3?)$">
SSLOptions +StdEnvVars +ExportCertData
</Files>
<Directory "/var/www/cgi-bin">
SSLOptions +StdEnvVars +ExportCertData
</Directory>
SetEnvIf User-Agent ".*MSIE.*" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
CustomLog logs/ssl_request_log \
"%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
</VirtualHost>
Gérer les certificats des utilisateurs
Cette partie est la seule qui peut être exécuter plusieurs fois. Elle est très amplement facilitée par les scripts de gestion édités auparavant.
Ajout d'un utilisateur
L'autorisation d'accès d'un utilisateur est conditionné par un certificat web qui doit être importer dans le navigateur de celui-ci. Ce certificat web est une simple traduction du certificat openssl à qui il est étroitement associé. Le certificat web ne peut exister sans lui.
Généreration des certificats
cd /etc/pki/httpd/
./generate-certificate.sh <USER>
./generate-web-certificate.sh <USER>
Il ne reste plus qu'à donner de manière sécurisée le certificat web à l'utilisateur le fichier <path>/etc/pki/httpd/certs/<USER>_browser_cert.p12</path>, ainsi que le mot de passe associé.
Celui-ci devra l'importer dans son navigateur :
Révocation d'utilisateur
On révoque son certificat et celui-ci ne peut plus accéder au site.
cd /etc/pki/httpd/
./revoke-certificate.sh <USER>
Virtualhosts
Apache ne supporte pas le multi virtualhost de but en blanc sur une connection https, mais cela est toutefois possible sous certaines conditions :
- Les certificats et les clés sont partagées par tous les virtualhosts ( y compris le default ) et ceux-ci doivent être recopiés à chaque définition de virtualhost. De plus celles-ci doivent comporter le port :
<VirtualHost 192.168.0.100:443>
- Utilisation de la directive NameVirtualHost avec spécification du port :
NameVirtualHost 192.168.0.100:443
- Les autres définitions des virtualhosts accessibles en http doivent mentionner le port ( httpd-vhosts.conf ) :
<VirtualHost 192.168.0.100:80>
Fichier <path>/etc/httpd/conf.d/ssl.conf</path>
LoadModule ssl_module modules/mod_ssl.so
Listen 443
SSLPassPhraseDialog exec:/usr/libexec/httpd-ssl-pass-dialog
SSLSessionCache shmcb:/var/cache/mod_ssl/scache(512000)
SSLSessionCacheTimeout 300
SSLMutex default
SSLRandomSeed startup file:/dev/urandom 256
SSLRandomSeed connect builtin
SSLCryptoDevice builtin
<VirtualHost _default_:443>
ErrorLog logs/ssl_error_log
TransferLog logs/ssl_access_log
LogLevel warn
SSLEngine on
SSLProtocol all -SSLv2
SSLCipherSuite RC4-SHA:AES128-SHA:ALL:!ADH:!EXP:!LOW:!MD5:!SSLV2:!NULL
SSLHonorCipherOrder on
SSLCertificateFile /etc/pki/httpd/certs/httpd.crt
SSLCertificateKeyFile /etc/pki/httpd/certs/httpd.key
SSLCACertificateFile /etc/pki/httpd/httpd_ca.crt
SSLCARevocationPath /etc/pki/httpd/crl/
SSLVerifyClient require
SSLVerifyDepth 2
<Files ~ "\.(cgi|shtml|phtml|php3?)$">
SSLOptions +StdEnvVars +ExportCertData
</Files>
<Directory "/var/www/cgi-bin">
SSLOptions +StdEnvVars +ExportCertData
</Directory>
SetEnvIf User-Agent ".*MSIE.*" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
CustomLog logs/ssl_request_log \
"%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
</VirtualHost>
NameVirtualHost 192.168.0.100:443
<VirtualHost 192.168.0.100:443>
SSLEngine on
SSLProtocol all -SSLv2
SSLCipherSuite RC4-SHA:AES128-SHA:ALL:!ADH:!EXP:!LOW:!MD5:!SSLV2:!NULL
SSLHonorCipherOrder on
SSLCertificateFile /etc/pki/httpd/certs/httpd.crt
SSLCertificateKeyFile /etc/pki/httpd/certs/httpd.key
SSLCACertificateFile /etc/pki/httpd/httpd_ca.crt
SSLCARevocationPath /etc/pki/httpd/crl/
SSLVerifyClient require
SSLVerifyDepth 2
ServerAdmin root@localhost
DocumentRoot "/home/ssl-vhost"
ServerName ssl-vhost.localdomain
<Directory "/home/ssl-vhost">
AllowOverride none
Allow from all
Order allow,deny
</Directory>
LogLevel warn
ErrorLog "logs/ssl-vhost-error.log"
CustomLog "logs/ssl-vhost-access.log" common
TransferLog logs/ssl-vhost-access.log
</VirtualHost>
Répartition de charge
Il sera de la responsabilité de l'administrateur de recopier ( ou de mettre en place une réplication Raid sur IP, une tâche cron ) le répertoire <path>/etc/pki/httpd</path> sur tous les noeuds du cluster à chaque modification ( ajout, révocation, renouvellement, etc... )
Exemple d'ajout d'une grappe à un cluster ( ipvsadm ) dont l'IP WAN est 1.2.3.4:
ipvsadm -A -t 1.2.3.4:443 -s lc ipvsadm -a -t 1.2.3.4:443 -r 192.168.0.1:443 -m ipvsadm -a -t 1.2.3.4:443 -r 192.168.0.2:443 -m ipvsadm -a -t 1.2.3.4:443 -r 192.168.0.3:443 -m
Destruction du cluster
ipvsadm -d -t 1.2.3.4:443 -r 192.168.0.1:443 -m ipvsadm -d -t 1.2.3.4:443 -r 192.168.0.2:443 -m ipvsadm -d -t 1.2.3.4:443 -r 192.168.0.3:443 -m ipvsadm -D -t 1.2.3.4:443 -s lc
Utilisation avec PHP
Il faut activer la passation des paramètres SSL à PHP en rajoutant l'option ExportCertData[2]
Fichier <path>/etc/httpd/conf.d/ssl.conf</path>
<Files ~ "\.(cgi|shtml|phtml|php3?)$">
SSLOptions +StdEnvVars +ExportCertData
</Files>
<Directory "/var/www/cgi-bin">
SSLOptions +StdEnvVars +ExportCertData
</Directory>
Quand un certificat d'un client est disponible, la variable globale $_SERVER contient beaucoup plus d'information, toutes préfixées avec SSL_CLIENT_.
- SSL_CLIENT_VERIFY est très importante et les information du certificat ne doivent pas être utilisées si cette variable n'est pas égale à SUCCESS. Cette variable est passée à NONE si il n'y a pas de certificat.
- SSL_CLIENT_M_SERIAL contient le numéro de série qui identifie le certificat unique associé depuis l'autorité de certification.
- Toutes les variables SSL_CLIENT_I_* sont à propos de l'autorité de certification.
- Toutes les variables SSL_CLIENT_S_* sont à propos de l'utilisateur.
Dans le cas qui nous intéresse, on vérifie le nom en lisant la varible SSL_CLIENT_S_DN_CN et l'email associé avec SSL_CLIENT_S_DN_Email.
Exemple de script PHP affichant le tableau suivant
| Clé de $_SERVER | Valeur | Commentaires |
|---|---|---|
| SSL_CLIENT_VERIFY | SUCCESS | Client utilisant un certificat valide si égal à SUCCESS |
| SSL_CLIENT_S_DN_CN | didier | Utilisateur (CN) |
| SSL_CLIENT_S_DN_Email | didier@localhost | |
| SSL_SERVER_S_DN_C | FR | Code pays |
| SSL_SERVER_S_DN_ST | Languedoc-Roussillon | Etat ou région |
| SSL_SERVER_S_DN_O | Home | Organisation |
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<style>
th, td, table {
border:1px black solid;
border-collapse:collapse;
padding: 5px;
text-align:left;
}
th { background-color:lightgrey;}
</style>
</head>
<body>
<table>
<tr>
<th>Clé de $_SERVER</th>
<th>Valeur</th>
<th>Commentaires</th>
</tr>
<tr>
<td>SSL_CLIENT_VERIFY</td>
<td><?php echo $_SERVER['SSL_CLIENT_VERIFY'];?></td>
<td>Client utilisant un certificat valide si égal à SUCCESS</td>
</tr>
<tr>
<td>SSL_CLIENT_S_DN_CN</td>
<td><?php echo $_SERVER['SSL_CLIENT_S_DN_CN'];?></td>
<td>Utilisateur (CN)</td>
</tr>
<tr>
<td>SSL_CLIENT_S_DN_Email</td>
<td><?php echo $_SERVER['SSL_CLIENT_S_DN_Email'];?></td>
<td>Email</td>
</tr>
<tr>
<td>SSL_SERVER_S_DN_C</td>
<td><?php echo $_SERVER['SSL_SERVER_S_DN_C'];?></td>
<td>Code pays</td>
</tr>
<tr>
<td>SSL_SERVER_S_DN_ST</td>
<td><?php echo $_SERVER['SSL_SERVER_S_DN_ST'];?></td>
<td>Etat ou région</td>
</tr>
<tr>
<td>SSL_SERVER_S_DN_O</td>
<td><?php echo $_SERVER['SSL_SERVER_S_DN_O'];?></td>
<td>Organisation</td>
</tr>
</table>
</body>
</html>
All in one script
Version potentiellement plus à jour sur https://github.com/didier13150/manageCA
#!/bin/bash
################################################################################
# Author: Didier Fabert
# Rev 0.4
################################################################################
COUNTRYNAME="FR"
STATE="Languedoc-Roussillon"
CITY="Beaucaire"
COMPANY="Home"
OCSP_URL="http://didier.domicile.org/"
PKI_PATH="/etc/pki"
NAME=""
CFG_FILE="/etc/manageCA.conf"
function printUsage() {
echo "$(basename $0)"
}
function printHelp() {
echo
echo "Options:"
echo -e "\t-c <NAME> Config File [${CFG_FILE}]"
echo -e "\t-p <PATH> Path for PKI [/etc/pki]"
echo -e "\t-n <NAME> CA Name [None]"
}
function printMenu() {
clear
echo "====================================================================="
echo " ${COMPANY} Certificate Management System"
echo "====================================================================="
echo
echo " 1) Create a Client/Server/OCSP certificate"
echo " 2) Create a Client Certificate for Web (PKCS#12)"
echo " 3) Renew a Certificate"
echo " 4) Revoke a Certificate"
echo " 5) List Certificates"
echo
echo " i) Initialize Root Certificate Authority (CA)"
echo " d) Delete CA"
echo " o) Show/Modify/Save CA Options"
echo " q) Quit"
echo
echo " Options available before init"
echo " p) Change PKI default path [${PKI_PATH}]"
echo " n) Change CA name [${NAME}]"
echo
}
function printSubMenu {
clear
echo "-----------------------------------------------------------------"
echo ${1}
echo "-----------------------------------------------------------------"
echo
}
function manageOptions() {
local buffer
while true;
do
printSubMenu "CA Options"
echo " 1) Country Name [${COUNTRYNAME}]"
echo " 2) State Name [${STATE}]"
echo " 3) City Name [${CITY}]"
echo " 4) Company Name [${COMPANY}]"
echo " 5) OCSP URL [${OCSP_URL}]"
echo
echo " s) Save Options"
echo " p) Previous menu"
echo
read -p " ==> Make your choice [none]: " -n 1 CHOICE
echo
echo
case ${CHOICE} in
1)
read -p " ==> New Country Name [${COUNTRYNAME}]: " buffer
[ ! -z ${buffer} ] && COUNTRYNAME=${buffer}
;;
2)
read -p " ==> New State Name [${STATE}]: " buffer
[ ! -z ${buffer} ] && STATE=${buffer}
;;
3)
read -p " ==> New City Name [${CITY}]: " buffer
[ ! -z ${buffer} ] && CITY=${buffer}
;;
4)
read -p " ==> New Company Name [${COMPANY}]: " buffer
[ ! -z ${buffer} ] && COMPANY=${buffer}
;;
5)
read -p " ==> New OCSP URL [${OCSP_URL}]: " buffer
[ ! -z ${buffer} ] && OCSP_URL=${buffer}
;;
s)
saveCfg
;;
p)
return
;;
esac
done
}
function saveCfg() {
local buffer=$1
if [ -z ${buffer} ]
then
echo
read -p " ==> File to save [${CFG_FILE}]: " buffer
[ ! -z ${buffer} ] && CFG_FILE=${buffer}
fi
touch ${CFG_FILE}
if [ -w ${CFG_FILE} ]
then
echo "## Configuration file for manageCA.sh script" > ${CFG_FILE}
echo >> ${CFG_FILE}
echo "# Country Code for certificate" >> ${CFG_FILE}
echo "COUNTRYNAME=\"${COUNTRYNAME}\"" >> ${CFG_FILE}
echo >> ${CFG_FILE}
echo "# State Name for certificate" >> ${CFG_FILE}
echo "STATE=\"${STATE}\"" >> ${CFG_FILE}
echo >> ${CFG_FILE}
echo "# City Name for certificate" >> ${CFG_FILE}
echo "CITY=\"${CITY}\"" >> ${CFG_FILE}
echo >> ${CFG_FILE}
echo "# Company Name for certificate" >> ${CFG_FILE}
echo "COMPANY=\"${COMPANY}\"" >> ${CFG_FILE}
echo >> ${CFG_FILE}
echo "# OCSP URL for certificate" >> ${CFG_FILE}
echo "OCSP_URL=\"${OCSP_URL}\"" >> ${CFG_FILE}
echo >> ${CFG_FILE}
echo "# PKI Default Path" >> ${CFG_FILE}
echo "PKI_PATH=\"${PKI_PATH}\"" >> ${CFG_FILE}
echo >> ${CFG_FILE}
else
echo
echo "Error: ${CFG_FILE} is not writable for you"
read -p "Press [enter] to continue" DUMMY
fi
}
function addUser() {
local user
local email
local usage="client"
local buffer
local userdata
printSubMenu "Create a client certificate"
read -p " ==> User name [NONE]: " user
if [[ "${user}" == "" ]]
then
return
fi
echo
read -p " ==> User email [NONE]: " email
if [[ "${email}" == "" ]]
then
return
fi
echo
read -p " ==> Select Usage Key (server, client or ocsp) [client]: " buffer
[ -z ${buffer} ] || usage=${buffer}
echo
if [[ "${usage}" == "ocsp" ]]
then
extension="-extensions OCSP"
else
read -p "Add OCSP Extension to Certificate ? [Y/n]: " buffer
[ -z ${buffer} ] && buffer="y"
if [[ "${buffer}" == "y" ]]
then
if [[ "${usage}" == "server" ]]
then
extension="-extensions OCSP_SERVER"
else
extension="-extensions OCSP_CLIENT"
fi
else
extension=""
fi
fi
openssl genrsa -out ${PKI_PATH}/${NAME}/certs/${user}.key 2048 \
1>/dev/null 2>&1
if [[ "${usage}" == "server" ]]
then
userdata="organizationalUnitName_default = User\n"
else
userdata="organizationalUnitName_default = Admin\n"
fi
userdata="${userdata}commonName_default = ${user}\n"
userdata="${userdata}emailAddress_default = ${email}"
cat ${PKI_PATH}/${NAME}/ssl.cnf | tr -d '#' | \
sed -e "s/@USERDATA@/${userdata}/" \
> ${PKI_PATH}/${NAME}/ssl2.cnf
openssl req -config ${PKI_PATH}/${NAME}/ssl2.cnf -new -nodes -batch \
-out ${PKI_PATH}/${NAME}/certs/${user}.csr \
-key ${PKI_PATH}/${NAME}/certs/${user}.key
openssl ca -config ${PKI_PATH}/${NAME}/ssl2.cnf \
-cert ${PKI_PATH}/${NAME}/${NAME}_ca.crt ${extension} \
-out ${PKI_PATH}/${NAME}/certs/${user}.crt \
-outdir ${PKI_PATH}/${NAME}/certs \
-infiles ${PKI_PATH}/${NAME}/certs/${user}.csr
cat ${PKI_PATH}/${NAME}/certs/${user}.crt \
${PKI_PATH}/${NAME}/certs/${user}.key \
> ${PKI_PATH}/${NAME}/pem/${user}.pem
mv ${PKI_PATH}/${NAME}/ssl2.cnf ${PKI_PATH}/${NAME}/confs/${user}-ssl.cnf
read -p "Press [enter] to continue" DUMMY
}
function webUser() {
local user
printSubMenu "Create a Client Certificate for Web"
printUserList
read -p " ==> User name [NONE]: " user
if [[ "${user}" == "" ]]
then
return
fi
echo
if [ -f ${PKI_PATH}/${NAME}/certs/${user}.crt ]
then
openssl pkcs12 -export -inkey ${PKI_PATH}/${NAME}/certs/${user}.key \
-in ${PKI_PATH}/${NAME}/certs/${user}.crt \
-CAfile ${PKI_PATH}/${NAME}/${NAME}_ca.crt \
-out ${PKI_PATH}/${NAME}/certs/${user}_browser_cert.p12
fi
echo
[ -f ${PKI_PATH}/${NAME}/certs/${user}_browser_cert.p12 ] \
&& echo "Web certificate: ${PKI_PATH}/${NAME}/certs/${user}_browser_cert.p12" \
|| echo "Error encoured"
echo
read -p "Press [enter] to continue" DUMMY
}
function renewUser() {
local user
printSubMenu "Renew a Server Certificate"
printUserList
read -p " ==> User name [NONE]: " user
if [[ "${user}" == "" ]]
then
echo "Error: Name cannot be empty"
read -p "Press [enter] to continue" DUMMY
return
fi
revokeUser ${user}
openssl ca -config ${PKI_PATH}/${NAME}/confs/${user}-ssl.cnf \
-out ${PKI_PATH}/${NAME}/certs/${user}.crt \
-outdir ${PKI_PATH}/${NAME}/certs \
-infiles ${PKI_PATH}/${NAME}/certs/${user}.csr
cat ${PKI_PATH}/${NAME}/certs/${user}.crt \
${PKI_PATH}/${NAME}/certs/${user}.key \
> ${PKI_PATH}/${NAME}/pem/${user}.pem
echo
read -p "Press [enter] to continue" DUMMY
}
function revokeUser() {
local user=$1
printSubMenu "Revoke a Client Certificate"
printUserList
[ -z ${user} ] && read -p " ==> User name [NONE]: " user
if [[ "${user}" == "" ]]
then
return
fi
openssl ca -revoke ${PKI_PATH}/${NAME}/certs/${user}.crt \
-config ${PKI_PATH}/${NAME}/ssl.cnf
# Save old certificate
x=1
while [ -f "${PKI_PATH}/${NAME}/certs/${user}.revoked.$x.crt" ]
do
x=$(( $x + 1 ))
done
mv ${PKI_PATH}/${NAME}/certs/${user}.crt ${PKI_PATH}/${NAME}/certs/${user}.revoked.$x.crt
x=1
while [ -f "${PKI_PATH}/${NAME}/pem/${user}.revoked.$x.pem" ]
do
x=$(( $x + 1 ))
done
mv ${PKI_PATH}/${NAME}/pem/${user}.pem ${PKI_PATH}/${NAME}/pem/${user}.revoked.$x.pem
# Regen CRL
openssl ca -gencrl -config ${PKI_PATH}/${NAME}/ssl.cnf \
-out ${PKI_PATH}/${NAME}/${NAME}_ca.crl
echo
echo "Don't forget to reload Apache"
echo
[ -z ${1} ] read -p "Press [enter] to continue" DUMMY
}
function listUser() {
printSubMenu "List Client Certificates"
while [ 1 ]
do
read LINE || break
LISTNUM=`echo ${LINE} | grep -v "^R" | awk '{ print $3 }'`
LISTCN=`echo ${LINE} | grep -v "^R" | awk -F CN= '{ print $2 }' | cut -d '/' -f1`
[ -z ${LISTNUM} ] || echo " ${LISTNUM} ${LISTCN}"
done < ${PKI_PATH}/${NAME}/index.txt
echo
read -p "Press [enter] to continue" DUMMY
}
function printUserList() {
while [ 1 ]
do
read LINE || break
LISTCN=`echo ${LINE} | grep -v "^R" | awk -F CN= '{ print $2 }' | cut -d '/' -f1`
[ -z ${LISTCN} ] || echo "- ${LISTCN}"
done < ${PKI_PATH}/${NAME}/index.txt
}
function changeDefaultPath() {
local buffer
read -p " ==> Select New path for CA [${PKI_PATH}]: " buffer
if [ ! -z ${buffer} ]; then PKI_PATH=${buffer} ; fi
}
function changeName() {
read -p " ==> Select New CA name [NONE]: " NAME
}
function initCA() {
printSubMenu "CA Initialisation"
if [ -f ${PKI_PATH}/${NAME}/ssl.cnf ]
then
read -p "!!! Already initalized !!!"
return
fi
read -p " ==> Fully qualified Hostname [NONE]: " hostname
if [[ "$hostname" == "" ]]
then
echo "Error: Fully qualified Hostname cannot be empty"
read -p "Press [enter] to continue" DUMMY
return
fi
echo
read -p " ==> Admin email [NONE]: " email
if [[ "$email" == "" ]]
then
echo "Error: email cannot be empty"
read -p "Press [enter] to continue" DUMMY
return
fi
mkdir -p ${PKI_PATH}/${NAME}/{certs,newcerts,private,confs,crl,pem}
initConfig
touch ${PKI_PATH}/${NAME}/index.txt
[ -f ${PKI_PATH}/${NAME}/serial ] || echo 01 > ${PKI_PATH}/${NAME}/serial
[ -f ${PKI_PATH}/${NAME}/crlnumber ] || echo 01 > ${PKI_PATH}/${NAME}/crlnumber
[ -f ${PKI_PATH}/${NAME}/private/${NAME}_ca.key ] || \
openssl genrsa -out ${PKI_PATH}/${NAME}/private/${NAME}_ca.key 2048 \
1>/dev/null 2>&1
local userdata="organizationalUnitName_default = Admin\n"
userdata="${userdata}commonName_default = ${hostname}\n"
userdata="${userdata}emailAddress_default = ${email}"
cat ${PKI_PATH}/${NAME}/ssl.cnf | tr -d '#' | \
sed -e "s/@USERDATA@/${userdata}/" \
> ${PKI_PATH}/${NAME}/ssl2.cnf
openssl req -config ${PKI_PATH}/${NAME}/ssl2.cnf -new -x509 -days 3650 -batch \
-key ${PKI_PATH}/${NAME}/private/${NAME}_ca.key \
-out ${PKI_PATH}/${NAME}/${NAME}_ca.crt -extensions v3_ca
mv ${PKI_PATH}/${NAME}/ssl2.cnf ${PKI_PATH}/${NAME}/confs/ca.cnf
[ -f ${PKI_PATH}/${NAME}/${NAME}_ca.crl ] || openssl ca -gencrl \
-config ${PKI_PATH}/${NAME}/ssl.cnf -out ${PKI_PATH}/${NAME}/${NAME}_ca.crl
ln ${PKI_PATH}/${NAME}/${NAME}_ca.crl ${PKI_PATH}/${NAME}/crl/
local hash=`openssl crl -hash -noout -in ${PKI_PATH}/${NAME}/crl/${NAME}_ca.crl`
ln -s ${PKI_PATH}/${NAME}/crl/${NAME}_ca.crl ${PKI_PATH}/${NAME}/crl/$hash.r0
echo
echo "CA initialized"
echo
read -p "Press [enter] to continue" DUMMY
}
function deleteCA() {
printSubMenu "Deleting CA"
read -p " ==> Are you sure ? Type uppercase YES to confirm: " CONFIRM
if [[ "${CONFIRM}" == "YES" ]]
then
rm -rf ${PKI_PATH}/${NAME}
echo
echo "CA completely deleted"
echo
read -p "Press [enter] to continue" DUMMY
fi
}
function initConfig() {
cat << 'EOF' > ${PKI_PATH}/${NAME}/ssl.cnf
HOME = @HOME@
RANDFILE = @HOME@/.rand
[ca]
default_ca = ca_default
[ca_default]
dir = @HOME@
certs = $dir/certs
crl_dir = $dir/crl
database = $dir/index.txt
new_certs_dir = $dir/newcerts
certificate = $dir/@NAME@_ca.crt
private_key = $dir/private/@NAME@_ca.key
serial = $dir/serial
crl = $dir/@NAME@_ca.crl
crlnumber = $dir/crlnumber
crl_extensions = crl_ext
x509_extensions = usr_cert
name_opt = ca_default
cert_opt = ca_default
default_days = 365
default_crl_days = 30
default_md = md5
preserve = no
policy = policy_match
[policy_match]
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[req]
default_bits = 1024
default_keyfile = privkey.pem
distinguished_name = req_distinguished_name
attributes = req_attributes
x509_extensions = v3_ca
string_mask = MASK:0x2002
[req_distinguished_name]
countryName = Country Name (2 letter code)
countryName_default = @COUNTRYNAME@
countryName_min = 2
countryName_max = 2
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = @STATE@
localityName = Locality Name (eg, city)
localityName_default = @CITY@
0.organizationName = Organization Name (eg, company)
0.organizationName_default = @ORGANISATION@
organizationalUnitName = Organizational Unit Name (eg, section)
commonName = Common Name (eg, your name or your server\'s hostname)
commonName_max = 64
emailAddress = Email Address
emailAddress_max = 64
##@USERDATA@
[req_attributes]
challengePassword = A challenge password
challengePassword_min = 4
challengePassword_max = 20
unstructuredName = An optional company name
[usr_cert]
basicConstraints = CA:FALSE
nsComment = "OpenSSL Generated Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
[v3_ca]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
basicConstraints = CA:true
[crl_ext]
authorityKeyIdentifier=keyid:always,issuer:always
[OCSP]
basicConstraints = CA:FALSE
keyUsage = digitalSignature
extendedKeyUsage = OCSPSigning
issuerAltName = issuer:copy
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
authorityInfoAccess = OCSP;URI:@OCSPURL@
[OCSP_SERVER]
nsComment = "OpenSSL Generated Server Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
issuerAltName = issuer:copy
basicConstraints = critical,CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment
nsCertType = server
extendedKeyUsage = serverAuth
authorityInfoAccess = OCSP;URI:@OCSPURL@
[OCSP_CLIENT]
nsComment = "OpenSSL Generated Client Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
issuerAltName = issuer:copy
basicConstraints = critical,CA:FALSE
keyUsage = digitalSignature, nonRepudiation
nsCertType = client
extendedKeyUsage = clientAuth
authorityInfoAccess = OCSP;URI:@OCSPURL@
EOF
sed -i \
-e "s#@HOME@#${PKI_PATH}/${NAME}#g" \
-e "s#@NAME@#${NAME}#g" \
-e "s#@COUNTRYNAME@#${COUNTRYNAME}#g" \
-e "s#@STATE@#${STATE}#g" \
-e "s#@CITY@#${CITY}#g" \
-e "s#@ORGANISATION@#${COMPANY}#g" \
-e "s#@OCSPURL@#${OCSP_URL}#g" \
${PKI_PATH}/${NAME}/ssl.cnf
}
#Main program
# process command line arguments
while getopts "?hup:n:c:" opt
do
case "${opt}" in
u)
printUsage
exit 0
;;
h|\?)
printUsage
printHelp
exit 0
;;
c)
CFG_FILE=$OPTARG
;;
p)
PKI_PATH=$OPTARG
;;
n)
NAME=$OPTARG
;;
esac
done
# Load config
[ -f ${CFG_FILE} ] && source ${CFG_FILE} || saveCfg ${CFG_FILE}
clear
[ -z ${NAME} ] && changeName
while true;
do
printMenu
# CheckOpenSSLConfig
read -p " ==> Make your choice [none]: " -n 1 CHOICE
case ${CHOICE} in
1)
addUser
;;
2)
webUser
;;
3)
renewUser
;;
4)
revokeUser
;;
5)
listUser
;;
I|i)
initCA
;;
Q|q)
echo
break
;;
P|p)
echo
changeDefaultPath
;;
N|n)
echo
changeName
;;
D|d)
deleteCA
;;
O|o)
manageOptions
;;
esac
done