Server Installation/Opennet CA
Software für Betrieb der Opennet CA.
Inhaltsverzeichnis |
Überblick
Die Opennet CA Software besteht aus drei Bereichen:
- Backend (Bash Shell Scripte), enthält alle notwendige OpenSSL Wrapper Scripte
- Frontend Webinterface (Static HTML u. PHP), Arbeit mit CSR Dateien kombiniert mit JSON Metadaten Dateien
- Frontend Batchscripte (Bash Shell Scripte), Schnittstelle zwischen Frontend u. Backend, dient der Automatisierung
Abgebildeten Funktionen:
- Signieren von Zertifikatsanfragen
- Zurückziehen von Zertifikaten
- Erstellen der CRL Liste
- Download und CA Verifizierung einer CRL Liste
- Suchen von Zertifikaten über CN
- Logging und integriertes Backup
- automatischer Mailversand
- Erzeugen von Webübersicht
Notwendige Voraussetzungen:
- openssl - zum Betrieb der CA Funktionen
- bsd-mailx, mutt - zum Versand von E-Mails
- apache2 - für Webseiten
- jq - für JSON
- moreutils - zur atomaren Erzeugung von Dateien aus Cronjobs (sponge)
Die Software kann über Opennet ansible installiert werden.
Software Architektur
Überblick über die einzelnen Bausteine der Opennet CA bestehend aus Shell und PHP Scripten mit je ihren öffentlichen Funktionen sowie Abhängigkeiten.
State Maschine
Beschreibung der verschiedenen Zustände in dem sich eine CSR Anfrage befinden kann und mit welchen Methoden durch Nutzerinteraktion (upload und csr_approve bzw. revoke_approve) oder automatische Prozesse (signbatch bzw. revokebatch) der Zustand gewechselt wird.
Abläufe
Sign:
- Nutzer läd Zertfikatsantrag (CSR) hoch per CSR Webinterface
- eine E-Mail an die CSR-Mailadresse wird versendet, enthält den Approve-Link
- ein CA Admin prüft und bestätigt den Zertifikatsantrag (CSR-Approve)
- ein Cronjob sucht bestätigte CSR Anfragen und startet den CA Signaturprozess
- beim erfolgreichen Signieren wird das Zertifikat per Mail versendet
- bei Fehlern wird dieses protokolliert, muss händisch beseitigt werden
- danach kann ggf. wieder über den CSR-Approve-Link fortgefahren werden
Revoke:
- ein CA Admin kann das Zurückziehen von Zertifikaten anfordern (Revoke-Approve)
- ein Cronjob sucht bestätigte Revoke Anfragen und startet den CA Revokeprozess
- beim erfolgreichen Zurückziehen wird eine Mail versendet
- bei Fehlern wird dieses protokolliert, muss händisch beseitigt werden
- danach kann ggf. wieder über den Revoke-Approve-Link fortgefahren werden
User u. Verzeichnisse
- User "opennetca" mit Home /home/opennetca
- Gruppenmitgliedschaft www-data hinzufügen:
usermod -a -G www-data opennetca
- CA Verzeichnis einrichten:
mkdir cert mkdir crl mkdir csr mkdir .backup touch index.txt touch serial.txt cp <src>/README . cp <src>/opennetca.sh . cp <src>/opennetca.conf . cp <src>/sign.sh . cp <src>/revoke.sh . cp <src>/crl.sh . cp <src>/opennet-*.crt . cp <src>/opennet-*.key . cp <src>/opennet-*.conf . chown -R opennetca:opennetca * chmod 600 opennet-*.key
- Öffentliche Webseiten unter /var/www/htdocs/ca.opennet-initiative.de/
- Interne Webseiten unter /var/www/ca_internal/
- Upload Verzeichnis unter /var/www/csr_upload/ - Rechte setzen:
chown www-data:www-data csr_upload chmod g+w csr_upload
Config Files
- OpenSSL Konfiguration: opennet-<ca-name>.ca.on_<year>.conf, notwendige Anpassungen:
[ opennetca ] dir = /home/opennetca/ca/<capath> certificate = $dir/opennet-<caname>.crt private_key = $dir/opennet-<caname>.key [ opennetca_certsign ] nsComment = Opennet <caname-text> CA nsCaRevocationUrl = http://ca.opennet-initiative.de/<caname>.crl nsRevocationUrl = http://ca.opennet-initiative.de/<caname>.crl [ opennetca_crl ] fullname=URI:http://ca.opennet-initiative.de/<caname>.crl
- CA Script Konfiguration: opennetca.cfg, notwendige Anpassungen:
# variables global CA_CONFIG=opennet-<caname>.conf CA_MAILSUBJECT="Opennet CA (<caname>)" # variables sign CA_CSRCN="<cn-extension1> <cn-extension2> .." # variables crl CA_CRL=<caname>.crl
CA Scripts
Opennet DEV: https://dev.opennet-initiative.de/browser/on_opennetca
Git Repository: git clone https://dev.opennet-initiative.de/git/on_opennetca
- Opennet CA: opennetca.sh (Basisfunktionen, benötigt Konfiguration opennetca.conf)
- Zertifikat signieren: sign.sh (verwendet opennetca.sh sign Methode)
- Zertifikat zurückziehen: revoke.sh (verwendet opennetca.sh revoke Methode)
- CRL Liste erstellen: crl.sh (verwendet opennetca.sh crl Methode)
- Cert Suche: list.sh (verwendet opennetca.sh list Methode)
- Cert Liste in HTML: opennetca_htmlview.sh (eigenständiges Script)
- CRL Download: opennetca_crldownload.sh (eigenständiges Script, nur benötigt auf VPN Server)
- Zertifikat automatisch signieren: sign_batch.sh (verwendet opennetca.sh sign_batch Methode)
- Zertifikat automatisch zurückziehen: revoke_batch.sh (verwendet opennetca.sh revoke_batch Methode)
Diese Files für jede CA bereitstellen. Keine Anpassung notwendig.
CSR Scripts
Ergänzend zu den CA Scripts:
- CSR Upload: index.html und csr_upload.php (Hochladefunktion)
- CSR Liste in HTML: opennetcsr_htmlview.sh (Übersicht CSR Status und Approve Webinterface)
- CSR Sign Batch Prozess: opennetcsr_signbatch.sh (Approved CSRs anzeigen bzw. automatisch mit passender CA signieren)
- CSR Revoke Batch Prozess: opennetcsr_revokebatch.sh (Approved Revokes anzeigen bzw. automatisch mit passender CA zurückziehen)
- CSR Pending Batch Prozess: opennetcsr_pendingbatch.sh (Offene Signatur-/Revoke Anfragen anzeigen bzw. per Mail versenden)
CSR JSON
Zur Verwaltung des CSR Lebenszyklus:
{ "meta_type":"Opennet_CSR_JSON_v1", "meta_created":"<Timestamp>", "name":"<Filename>", "subject_o":"<Name>", "subject_cn":"<Node>", "subject_mail":"<Mail>", "digest":"<Digest>", "cn_filter":"<CN-Filter>", "upload_timestamp":"<Timestamp>", "upload_advisor":"<Advisor-Name>", "upload_ccmail":"<CC-Mail>", "status":"CSR|Approved|Signed|Error|RevokeApproved|Revoked|RevokeError", "approve_message":"<Message>", "approve_timestamp":"<Timestamp>", "sign_message":"<Message>", "sign_timestamp":"<Timestamp>", "revokeapprove_message":"<Message>", "revokeapprove_timestamp":"<Timestamp>", "revoke_message":"<Message>", "revoke_timestamp":"<Timestamp>", "error_message":"<Message>", "error_timestamp":"<Timestamp>", }
Cronjobs
Regelmäßige CRL Listen Erstellung und Bereitstellung:
# Opennet CA CRL Generator 15 1,13 * * * opennetca /home/opennetca/ca/root/crl.sh 2>/dev/null 15 1,13 * * * opennetca /home/opennetca/ca/vpnuser/crl.sh 2>/dev/null 15 1,13 * * * opennetca /home/opennetca/ca/vpnugw/crl.sh 2>/dev/null 15 1,13 * * * opennetca /home/opennetca/ca/client/crl.sh 2>/dev/null 15 1,13 * * * opennetca /home/opennetca/ca/server/crl.sh 2>/dev/null 25 1,13 * * * root cp /home/opennetca/ca/root/crl/*.crl /var/www/htdocs/ca.opennet-initiative.de/ 25 1,13 * * * root cp /home/opennetca/ca/vpnuser/crl/*.crl /var/www/htdocs/ca.opennet-initiative.de/ 25 1,13 * * * root cp /home/opennetca/ca/vpnugw/crl/*.crl /var/www/htdocs/ca.opennet-initiative.de/ 25 1,13 * * * root cp /home/opennetca/ca/client/crl/*.crl /var/www/htdocs/ca.opennet-initiative.de/ 25 1,13 * * * root cp /home/opennetca/ca/server/crl/*.crl /var/www/htdocs/ca.opennet-initiative.de/
Inhaltliche CRL Kontrolle per (u.a. Revoked Certificates):
openssl crl -text -in crl/<crlfile>.crl -CAfile <cafile>.crt
Öffentliche anonymisierte und geschütze private Zertifikatsliste bereitstellen:
# Opennet CA Cert List Generator 30 1,13 * * * root /home/opennetca/ca/root/opennetca_htmlview.sh --public | sponge /var/www/htdocs/ca.opennet-initiative.de/root.html 30 1,13 * * * root /home/opennetca/ca/root/opennetca_htmlview.sh --private | sponge /var/www/ca_internal/root.html */10 * * * * root /home/opennetca/ca/vpnuser/opennetca_htmlview.sh --public | sponge /var/www/htdocs/ca.opennet-initiative.de/vpnuser.html */10 * * * * root /home/opennetca/ca/vpnuser/opennetca_htmlview.sh --private | sponge /var/www/ca_internal/vpnuser.html */10 * * * * root /home/opennetca/ca/vpnugw/opennetca_htmlview.sh --public | sponge /var/www/htdocs/ca.opennet-initiative.de/vpnugw.html */10 * * * * root /home/opennetca/ca/vpnugw/opennetca_htmlview.sh --private | sponge /var/www/ca_internal/vpnugw.html */10 * * * * root /home/opennetca/ca/client/opennetca_htmlview.sh --public | sponge /var/www/htdocs/ca.opennet-initiative.de/client.html */10 * * * * root /home/opennetca/ca/client/opennetca_htmlview.sh --private | sponge /var/www/ca_internal/client.html */10 * * * * root /home/opennetca/ca/server/opennetca_htmlview.sh --public | sponge /var/www/htdocs/ca.opennet-initiative.de/server.html */10 * * * * root /home/opennetca/ca/server/opennetca_htmlview.sh --private | sponge /var/www/ca_internal/server.html
Öffentliche anonymisierte und geschütze private CSR Statusliste bereitstellen:
# Opennet CSR List Generator */5 * * * * root /home/opennetca/csr/opennetcsr_htmlview.sh --public | sponge /var/www/htdocs/ca.opennet-initiative.de/csr.html */5 * * * * root /home/opennetca/csr/opennetcsr_htmlview.sh --private | sponge /var/www/ca_internal/csr.html
Automatisches Zurückziehen von freigegebenen Revoke Anfragen (Status = RevokeApproved):
# Opennet CSR Revoke Batch Job */5 * * * * opennetca /home/opennetca/csr/opennetcsr_revokebatch.sh --revoke >/dev/null 2>&1
Automatisches Signieren von freigegebenen CSR Anfragen (Status = Approved):
# Opennet CSR Sign Batch Job */5 * * * * opennetca /home/opennetca/csr/opennetcsr_signbatch.sh --sign >/dev/null 2>&1
Automatische Erinnerung an offene Signatur-/Revoke Anfragen (Status != Signed/Revoked):
# Opennet CSR Pending Batch Job 30 7 * * * opennetca /home/opennetca/csr/opennetcsr_pendingbatch.sh --mail >/dev/null
Auf den Opennet VPN-Servern muss ebenfalls ein Cronjob angelegt werden, mm die CRLs regelmäßig zu aktualisieren. Details siehe Server Installation/OpenVPN.
Mailversand
Beim Hochladen über das CSR Webinterface csr_upload.php wird eine Benachrichtigung an die CSR-Mailadresse versendet. Empfänger und Absender sind im PHP-File konfigurierbar.
Beim Signieren und Revoken wird durch das opennetca.sh Script automatisch eine E-Mail generiert. Diese enthält stets das Zertifikat, einen kurzen Infotext sowie Metaangaben zum Zertifikat. Empfänger ist die Mailadresse im Zertifikat sowie die CSR-Mailadresse (konfigurierbar im Configfile) und die CC-Mailadresse (beim Hochladen des CSR festgelegt).
Als Absender der Mail wird der Username vom Server, unter dem die CA installiert ist, verwendet (hier: opennetca - AT - opennet-initiative.de). Zum Empfang von möglichen Rückantworten ist opennetca - AT - opennet-initiative.de daher mit Weiterleitung zu admin eingerichtet.
Common Name Filter
Mit folgender Zuordnung wird aus Basis des CSR Common Name Filter die passende Sub-CA herausgesucht und angesprochen.
Sub-CA | Common Name Filter |
---|---|
vpnuser | *.*.aps.on / *.mobile.on |
vpnugw | *.*.ugw.on |
client | *.client.on |
server | *.opennet-initiative.de |
Webserver
- HTTP (ca)
<VirtualHost *:80> ServerName ca.opennet-initiative.de ServerAlias ca.on-i.de ServerAlias ca.on ServerAdmin admin@opennet-initiative.de DocumentRoot /var/www/htdocs/ca.opennet-initiative.de RewriteEngine On RewriteRule ^/api/ /api/api.php <Directory /> Options FollowSymLinks AllowOverride AuthConfig </Directory> <Directory /var/www/htdocs/ca.opennet-initiative.de> Options Indexes FollowSymLinks MultiViews AllowOverride AuthConfig Order allow,deny allow from all </Directory> ErrorLog /var/log/apache2/error.log LogLevel warn CustomLog /var/log/apache2/ca.log combined </VirtualHost>
- HTTPS (ca-ssl)
<IfModule mod_ssl.c> <VirtualHost _default_:443> ServerName ca.opennet-initiative.de ServerAlias ca.on-i.de ServerAlias ca.on ServerAdmin admin@opennet-initiative.de SSLEngine on SSLCertificateFile /etc/ssl/heartofgold.opennet-initiative.de_certchain.crt SSLCertificateKeyFile /etc/ssl/private/heartofgold.opennet-initiative.de.key SSLCertificateChainFile /etc/ssl/certs/opennet-server_certchain.pem SSLCACertificateFile /etc/apache2/ssl/root.crt SSLCACertificatePath /etc/apache2/ssl/ SSLCARevocationPath /etc/apache2/ssl/ SSLCADNRequestPath /etc/apache2/ssl/ DocumentRoot /var/www/htdocs/ca.opennet-initiative.de RewriteEngine On RewriteRule ^/api/ /api/api.php Alias /internal /var/www/ca_internal <Directory /> Options FollowSymLinks #AllowOverride AuthConfig </Directory> <Directory /var/www/htdocs/ca.opennet-initiative.de> Options Indexes FollowSymLinks MultiViews #AllowOverride AuthConfig Order allow,deny allow from all </Directory> <Directory /var/www/ca_internal> Options Indexes FollowSymLinks MultiViews #AllowOverride AuthConfig Order allow,deny allow from all # client cert auth SSLVerifyClient optional SSLVerifyDepth 3 # forward auth to php SSLOptions +StdEnvVars # allow specific cert CN SSLRequire %{SSL_CLIENT_S_DN_CN} in {"xxx.client.on","yyy.client.on"} # client cert error handling RewriteEngine on RewriteCond %{SSL:SSL_CLIENT_VERIFY} !=SUCCESS RewriteRule .? - [F] ErrorDocument 403 "You need a certificate issued by Opennet Client Sub-CA to access this site." </Directory> ErrorLog /var/log/apache2/error.log LogLevel warn CustomLog /var/log/apache2/ca.log combined CustomLog /var/log/apache2/ca_clientcert.log \ "%t %h SSL_CLIENT_S_DN = %{SSL_CLIENT_S_DN}x | \ SSL_CLIENT_M_SERIAL = %{SSL_CLIENT_M_SERIAL}x | \ SSL_PROTOCOL = %{SSL_PROTOCOL}x | SSL_CIPHER = %{SSL_CIPHER}x \ %r %>s %b" </VirtualHost> </IfModule>
OpenSSL
- Konfigurationdatei CA/Sub-CA:
# # Opennet CA Sign OpenSSL Config File # [ ca ] default_ca = opennetca [ opennetca ] dir = /home/opennetca/ca/vpnuser certs = $dir/cert crl_dir = $dir/crl database = $dir/index.txt new_certs_dir = $dir/cert certificate = $dir/opennet-vpn-user.ca.on_2013.crt private_key = $dir/opennet-vpn-user.ca.on_2013.key serial = $dir/serial.txt crl = $dir/crl.pem #randfile = $dir/.rand default_days = 3650 default_crl_days= 30 default_md = sha256 preserve = no policy = opennetca_certpolicy x509_extensions = opennetca_certsign [ opennetca_certpolicy ] countryName = optional stateOrProvinceName = optional organizationName = optional organizationalUnitName = optional commonName = supplied emailAddress = supplied [ opennetca_certsign ] basicConstraints = CA:FALSE authorityKeyIdentifier = keyid, issuer subjectKeyIdentifier = hash nsComment = Opennet VPN User CA nsCaPolicyUrl = http://ca.opennet-initiative.de/ nsCaRevocationUrl = http://ca.opennet-initiative.de/vpnuser.crl nsRevocationUrl = http://ca.opennet-initiative.de/vpnuser.crl nsBaseUrl = http://ca.opennet-initiative.de/ crlDistributionPoints = opennetca_crl [ opennetca_crl ] fullname=URI:http://ca.opennet-initiative.de/vpnuser.crl
- Abweichung Server Sub-CA:
[ opennetca ] copy_extensions = copy
Notwendig, damit SubjectAltNames aus CSR in die Zertifikatserweiterungen (v3_ext) übernommen werden. Mit Vorsicht zu betrachten, da ohne Detailkontrolle übernommen wird.
- Abweichung Root CA:
[ opennetca_certsign ] #basicConstraints = CA:FALSE basicConstraints = CA:TRUE
Notwendig damit Sub-CA erstellen werden. Dies bedeutet, dass alle signierten CSRs dann stets eine CA werden.