Zertifikat mit PHP-Skript beantragen
Unsere Zertifizierungsserver nehmen Zertifikatanträge nicht nur per WWW, sondern auch über eine SOAP-Schnittstelle entgegen.
Das folgende, für Linux-Systeme geschriebene PHP-Skript erstellt ein neues Schlüsselpaar und einen Zertifikatantrag für einen TLS-Server und verwendet diese Schnittstelle, um den Antrag an den Zertifizierungsserver zu übermitteln und die PDF-Datei abzurufen, die dann ausgedruckt, unterschrieben und beim Teilnehmerservice der CA abgegeben werden muss.
Das Skript ist bewusst simpel gehalten, damit jeder mit ausreichenden PHP-Kenntnissen es an seine Bedürfnisse anpassen kann, auch unter Windows oder Macintosh.
#!/usr/bin/php <?php # Folgende Angaben fuer jeden Zertifikatsantrag neu einstellen: # "Erlaubte" Zeichen sind: # A-Z a-z 0-9 ' ( ) + , - . / : = ? # und das Leerzeichen, aber keine Umlaute # Name des Antragstellers (nur erlaubte Zeichen) $name = 'Rainer Perske'; # E-Mail-Adresse des Antragstellers $mail = 'wwwadmin@uni-muenster.de'; # Organisationseinheit des Antragstellers (nur erlaubte Zeichen) $unit = 'IT'; # Pfad und Name der Datei mit dem PIN-Code des Antragsstellers # (für jeden Antrag darf eine andere PIN gewählt werden) $code = '/path/to/file/with/the/pin'; # RA-ID der zustaendigen Teilnehmerservice-Mitarbeiter # 4930=Universität # 5540=Kunstakademie $raid = 4930; # Gewünschtes Zertifikatprofil # Für aktuelle TLS-Server wählen Sie 'Webserver MustStaple' # (Aktuelle TLS-Server unterstützen OCSP Stapling) # Für alte TLS-Server wählen Sie 'Web Server' # Für TLS-Server+Clients wählen Sie 'Mail Server' # Lassen Sie sich bitte bei Bedarf von der CA beraten. $profil = 'Webserver MustStaple'; # Vollqualifizierter (Haupt-) Name des Servers $fqdn = 'hostname.uni-muenster.de'; # Gewünschter Distinguished Name des Servers im OpenSSL-Format # Vorkommende "/" müssen mit Backslash maskiert werden $subject = '/C=DE' . '/ST=Nordrhein-Westfalen' . '/L=Muenster' . '/O=Westfaelische Wilhelms-Universitaet Muenster' . '/CN=' . strtr($fqdn, array( '/' => '\\/' )); # Alle ins Zertifikat aufzunehmenden Subject Alternative Names # Der obige (Haupt-) Name muss immer enthalten sein $altnames = array( 'dns:' . $fqdn, 'dns:hostname2.uni-muenster.de', 'dns:hostname.wwu.de', 'dns:hostname2.wwu.de', ); # Pfad und Name der Datei mit den Wurzelzertifikaten im PEM-Format # Sie finden diese Wurzelzertifikate hier: # https://www.uni-muenster.de/CA/all-rootca.pem $root = '/path/to/file/with/root/certificate'; # Ende der Einstellungen # Schlüsselpaar und Request erzeugen # (Mit den OpenSSL-Funktionen von PHP wäre das sehr viel # komplizierter.) passthru('/usr/bin/openssl req -new -sha256 -newkey rsa:2048 -nodes' . ' -keyout ' . escapeshellarg( "$fqdn.key" ) . ' -out ' . escapeshellarg( "$fqdn.req" ) . ' -subj ' . escapeshellarg( $subject ) ); # Request und PIN aus den Dateien laden $req = file_get_contents("$fqdn.req") or die("Fehler beim Laden von $fqdn.req\n"); $pin = file_get_contents($code) or die("Fehler beim Laden von $code\n"); # SOAP-Verbindung aufbauen # Die Angaben mit (P) sind nur nötig, wenn der Zugriff auf den # Zertifizierungsserver über den Proxy-Server erfolgen muss. $soap = new SoapClient( 'https://pki.pca.dfn.de/dfn-ca-global-g2/cgi-bin/pub/soap?wsdl=1', array( 'trace' => false, 'exceptions' => false, 'features' => SOAP_SINGLE_ELEMENT_ARRAYS, 'cache_wsdl' => WSDL_CACHE_NONE, 'proxy_host' => 'wwwproxy.uni-muenster.de', # (P) 'proxy_port' => 3128, # (P) 'typemap' => array(), 'stream_context' => stream_context_create(array( 'http' => array( 'proxy' => 'tcp://wwwproxy.uni-muenster.de:3128', # (P) 'request_fulluri' => true, # (P) 'timeout' => 60, ), 'ssl' => array( 'verify_peer' => true, 'cafile' => $root, 'verify_depth' => 3, # RootCA > DFN-PCA > CA > Server ), # oder: RootCA > USERTrust CA > GÉANT TCS > Server )), ) ) or die("Fehler beim Aufbau der SOAP-Verbindung\n"); # Request absenden $soapdata = $soap->newRequest( $raid, # RA-ID $req, # Request im PEM-Format $altnames, # Array mit den Subject Alternative Names $profil, # Zertifikatprofil sha1($pin), # PIN $name, # Name des Antragstellers $mail, # E-Mail des Antragstellers $unit, # Organisationseinheit des Antragstellers true # Veröffentlichen des Zertifikats? ); if(is_soap_fault($soapdata)) die("Fehler beim Absenden des Antrags:\n" . "{$soapdata->faultcode}: {$soapdata->faultstring}\n"); if(!$soapdata) die("Fehler beim Absenden des Antrags\n"); $reqnum = intval($soapdata); # PDF-Datei abrufen $soapdata = $soap->getRequestPrintout( $raid, # RA-ID $reqnum, # Antragsnummer, wurde oben vergeben 'application/pdf', # keine andere Angabe erlaubt sha1($pin) # muss die gleiche PIN wie oben sein ); if(is_soap_fault($soapdata)) die("Fehler beim Abrufen der PDF-Datei:\n" . "{$soapdata->faultcode}: {$soapdata->faultstring}\n"); if(!$soapdata) die("Fehler beim Abrufen der PDF-Datei\n"); # PDF-Datei abspeichern file_put_contents("$fqdn.pdf",$soapdata) or die("Fehler beim Speichern der PDF-Datei nach $fqdn.pdf\n"); # SOAP-Verbindung abbauen unset($soap); ?>
Dieses Skript erzeugt folgende Dateien:
- hostname.uni-muenster.de.key
der private Schlüssel im PEM-Format (ungeschützt)
passend für die Apache-Anweisung SSLCertificateKeyFile- hostname.uni-muenster.de.req
der hochgeladene Zertifikatantrag im PEM-Format
- hostname.uni-muenster.de.pdf
die PDF-Datei
- hostname.uni-muenster.de.cert
das ausgestellte Zertifikat aus der E-Mail im PEM-Format
passend für die Apache-Anweisung SSLCertificateFile- hostname.uni-muenster.de.chain
Zwischen-CA-Zertifikate im PEM-Format
passend für die Apache-Anweisung SSLCertificateChainFile
Diese PDF-Datei muss jetzt ausgedruckt, unterschrieben und dem Teilnehmerservice-Mitarbeiter übergeben werden.
Sie werden dann das Zertifikat per E-Mail erhalten. Sie sollten die Anlage abspeichern:
Ebenfalls abspeichern sollten Sie diese Zertifikate der Zwischenzertifizierungsstellen:
Das ausgestellte Zertifikat kann auch per SOAP abgeholt werden. Dazu müssten Sie große Teile des obigen Skripts mit folgendem PHP-Fragment verbinden:
# Zertifikat abrufen $soapdata = $soap->getCertificateByRequestSerial( $raid, # RA-ID $reqnum, # Antragsnummer, wurde oben vergeben sha1($pin) # muss die gleiche PIN wie oben sein ); if(is_soap_fault($soapdata)) die("Fehler beim Abrufen des Zertifikats:\n" . "{$soapdata->faultcode}: {$soapdata->faultstring}\n"); if(!$soapdata) die("Fehler beim Abrufen des Zertifikats\n"); # Zertifikat abspeichern file_put_contents("$fqdn.cert",$soapdata) or die("Fehler beim Speichern des Zertifikats nach $fqdn.cert\n");