Zertifikate

Mit Zertifikaten wird die Kommunikation zwischen Rechnern abgesichert. Bildlich gesprochen bestätigen sie, dass der Rechner auch der ist, für den er sich ausgibt. Die Echtheit von Zertifikaten wird typischerweise von einem weiteren Zertifikat bestätigt. Das Ganze bildet eine Kette von Vertrauen (Chain of Trust), die in sogenannten Root-Zertifikaten gründet, denen von vornherein vertraut wird. Diese Root-Zertifikate stammen normalerweise von großen Firmen und man muss in aller Regel dafür bezahlen, wenn einem diese Firmen bestätigen sollen, dass der Rechner ‚testserver.meine-domain.de‘ eine bestimmte Adresse hat. Diese Root-Zertifikate sind selbst unterzeichnet und begründen das Vertrauen, das in sie gesetzt wird eigentlich durch das Renommé, das deren Aussteller geniessen.

Es gibt mit Openssl aber auch die Möglichkeit, selbst ein Zertifikat auszustellen – im einfachsten Fall ebenfalls selbst unterzeichnet. Man kann mit so einem Zertifikat dann ein ganzes Netz von Vertrauensbeziehungen selbst erstellen. Für die Kommunikation von Rechnern in einem internen Netzwerk ist das vollkommen in Ordnung. Damit das funktioniert, muss das selbst erstelle Root-Zertifikat von den Rechnern des internen Netzwerks als gültig angesehen werden, dann sind Zertifikate, die davon unterzeichnet wurden, genauso gut verwendbar wie kommerziell erstellte Zertifikate.

Wenn man das in die Tat umsetzen möchte, steht hier, wie man das machen kann. Diese Installation verlangt, dass die Datei /etc/ssl/openssl.cnf bestimmte Inhalte hat. Damit lassen sich dann Zertifikate für bestimmte Zweck erstellen.

Das Erstellen von Zertifikaten umfasst 3 Schritte – zunächst einen Schlüssel erstellen, dann einen Request erstellen und zuletzt das Unterzeichnen des Zertifikats durch das Root-Zertifikat.

In dem Zertifikat steht der CommonName – das ist der Name, für den es gilt,
der Zweck (wofür es benutzt werden kann)
die Gültigkeitsdauer (von-bis)
und der Verweis auf das Root-Zertifikat – also wer das Zertifikat ausgestellt hat bzw. die Richtigkeit garantiert.

In der Praxis empfiehlt sich, den commonName auszuweiten; Apple hat seit 2019 sogar die Erfordernis, dass der Name, für den das Zertifikat gelten soll auch in den sogenannten SANs (Subject Alternate Names) aufgeführt wird.(https://support.apple.com/de-de/HT210176).

Soweit so gut – aber: wie macht man das konkret?

Zunächst der Inhalt der Datei /etc/ssl/openssl.cnf:


# OpenSSL example configuration file.
# This is mostly being used for generation of certificate requests.
#

# This definition stops the following lines choking if HOME isn't
# defined.
HOME			= .
RANDFILE		= $ENV::HOME/.rnd

# Extra OBJECT IDENTIFIER info:
#oid_file		= $ENV::HOME/.oid
oid_section		= new_oids

# To use this configuration file with the "-extfile" option of the
# "openssl x509" utility, name here the section containing the
# X.509v3 extensions to use:
# extensions		= 
# (Alternatively, use a configuration file that has only
# X.509v3 extensions in its main [= default] section.)

[ new_oids ]

# We can add new OIDs in here for use by 'ca', 'req' and 'ts'.
# Add a simple OID like this:
# testoid1=1.2.3.4
# Or use config file substitution like this:
# testoid2=${testoid1}.5.6

# Policies used by the TSA examples.
tsa_policy1 = 1.2.3.4.1
tsa_policy2 = 1.2.3.4.5.6
tsa_policy3 = 1.2.3.4.5.7
# 1.3.6.1.5.5.7.3.1 für mac ios etc - id-kp-serverAuth OID
# das ist extendedKeyUsage = serverAuth
####################################################################
[ ca ]
default_ca	= CA_default		# The default ca section

####################################################################
[ CA_default ]

dir	            = /root/ca              # Where everything is kept
certs           = $dir/certs            # Where the issued certs are kept
crl_dir         = $dir/crl              # Where the issued crl are kept
new_certs_dir   = $dir/newcerts         # default place for new certs.
database        = $dir/index.txt        # database index file.
serial          = $dir/serial           # The current serial number
RANDFILE        = $dir/private/.rand	# private random number file
#unique_subject	= no                    # Set to 'no' to allow creation of
                                        # several certs with same subject.
######  the root key and root certificate #################################
private_key     = $dir/private/myca.key    # The private key
certificate     = $dir/certs/myca.crt      # The CA certificate
#### obiges ist root zertifikat - zu dem gehen wir jetzt wieder zurück - keine 2stufige CA mehr
#private_key     = $dir/private/wil.key.pem  # The private key
#certificate     = $dir/certs/wil.crt    # The CA certificate
######  For certificate revocation lists  ##################################
crlnumber       = $dir/crlnumber        # the current crl number
                                        # must be commented out to leave a V1 CRL
crl             = $dir/crl.pem          # The current CRL
crl_extensions   = crl_ext
default_crl_days = 30

######################################################################
default_md      = sha256                # use SHA-2
name_opt        = ca_default		    # Subject Name options
cert_opt        = ca_default		    # Certificate field options
default_days	= 1461                  # how long to certify for
preserve	    = no			        # keep passed DN ordering
copy_extensions = copy
# A few difference way of specifying how similar the request should look
# For type CA, the listed attributes must be the same, and the optional
# and supplied fields are just that :-)
policy		    = policy_match
#policy		    = policy_strict
#####################################################
################# strict ############################
[ policy_strict ]
# The root CA should only sign intermediate certificates that match.
# See the POLICY FORMAT section of `man ca`.
countryName            = match
stateOrProvinceName    = match
organizationName       = match
organizationalUnitName = optional
commonName             = supplied
emailAddress           = optional
################## match ###########################
[ policy_match ]
countryName		       = optional
stateOrProvinceName	   = optional
organizationName	   = match
organizationalUnitName = optional
commonName		       = supplied
emailAddress		   = optional
################## loose #############################
[ policy_loose ]
# Allow the intermediate CA to sign a more diverse range of certificates.
# See the POLICY FORMAT section of the `ca` man page.
countryName            = optional
stateOrProvinceName    = optional
localityName           = optional
organizationName       = optional
organizationalUnitName = optional
commonName             = supplied
emailAddress           = optional
################## anything #########################
# For the 'anything' policy
# At this point in time, you must list all acceptable 'object'
# types.
[ policy_anything ]
countryName		       = optional
stateOrProvinceName	   = optional
localityName		   = optional
organizationName	   = optional
organizationalUnitName = optional
commonName		       = supplied
emailAddress		   = optional

####################################################################
[ req ]
default_bits		   = 2048
#default_keyfile 	   = privkey.pem
distinguished_name	   = req_distinguished_name
string_mask            = utf8only
#attributes		       = req_attributes
x509_extensions	       = v3_ca	# The extensions to add to the self signed cert

# Passwords for private keys if not present they will be prompted for
# input_password = secret
# output_password = secret
###################################################################
[ req_distinguished_name ]
# See <https://en.wikipedia.org/wiki/Certificate_signing_request>.
countryName                     = Country Name (2 letter code)
stateOrProvinceName             = State or Province Name
localityName                    = Locality Name
0.organizationName              = Organization Name
organizationalUnitName          = Organizational Unit Name
emailAddress                    = Email Address
commonName                      = Common Name

############# defaults for the above ################
countryName_default             = DE
stateOrProvinceName_default	    = BaWue
localityName_default            = Ellwangen
0.organizationName_default	    = myorg
organizationalUnitName_default  = IT
emailAddress_default            = webmaster@myxy.de
####################### optional #####################
# we can do this but it is not needed normally :-)
#1.organizationName		= Second Organization Name (eg, company)
#1.organizationName_default	= World Wide Web Pty Ltd
#commonName_max			= 64
#emailAddress_max		= 64
######################## schrott ############################
#[ req_attributes ]
#challengePassword		= A challenge password
#challengePassword_min	= 4
#challengePassword_max	= 20
#unstructuredName		= An optional company name

########################################################################
# The next few sections are extensions that can be applied when
# signing certificates. For example, passing the -extensions
# v3_ca command-line argument will apply the options set in [ v3_ca ]
########################################################################
[ v3_ca ]
# Extensions for a typical CA
# PKIX recommendation.
subjectKeyIdentifier            = hash
authorityKeyIdentifier          = keyid:always,issuer
basicConstraints                = critical,CA:true
keyUsage                        = critical, digitalSignature, cRLSign, keyCertSign
# Some might want this also
# nsCertType = sslCA, emailCA
# Include email address in subject alt name: another PKIX recommendation
# subjectAltName=email:copy
# Copy issuer details
# issuerAltName=issuer:copy
# DER hex encoding of an extension: beware experts only!
# obj=DER:02:03
# Where 'obj' is a standard or added object
# You can even override a supported extension:
# basicConstraints= critical, DER:30:03:01:01:FF

########################################################################
[ v3_intermediate_ca ]
# Extensions for a typical intermediate CA (`man x509v3_config`).
subjectKeyIdentifier            = hash
authorityKeyIdentifier          = keyid:always,issuer
basicConstraints                = critical, CA:true, pathlen:0
keyUsage                        = critical, digitalSignature, cRLSign, keyCertSign

##########################################################################
[ usr_cert ]
# These extensions are added when 'ca' signs a request.
# This goes against PKIX guidelines but some CAs do it and some software
# requires this to avoid interpreting an end user certificate as a CA.
basicConstraints                = CA:FALSE
nsCertType                      = client, email
nsComment			            = "OpenSSL Generated Certificate"
# PKIX recommendations harmless if included in all certificates.
subjectKeyIdentifier            = hash
authorityKeyIdentifier          = keyid,issuer
keyUsage                        = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage                = clientAuth, emailProtection
##########################################################################
[ server_cert ]
# Extensions for server certificates (`man x509v3_config`).
basicConstraints                = CA:FALSE
nsCertType                      = server
nsComment                       = "OpenSSL Generated Server Certificate"
subjectKeyIdentifier            = hash
authorityKeyIdentifier          = keyid,issuer:always
keyUsage                        = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage                = serverAuth

#subjectAltName = @alt_names
[ alt_names ]
DNS.1          = www.myxy.de
DNS.2          = cms.myxy.de
DNS.3          = server.myxy.de
DNS.4          = server.myxz.de
IP.1           = 10.36.16.10
IP.2           = 10.37.18.10
##########################################################################
[ crl_ext ]
# CRL extensions.
# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
# issuerAltName=issuer:copy
authorityKeyIdentifier=keyid:always
##########################################################################
[ ocsp ]
# Extension for OCSP signing certificates (`man ocsp`).
basicConstraints       = CA:FALSE
subjectKeyIdentifier   = hash
authorityKeyIdentifier = keyid,issuer
keyUsage               = critical, digitalSignature
extendedKeyUsage       = critical, OCSPSigning


Darin ist auch eine intermediate CA enthalten, also eine Zwischen CA, die dann die eigentlichen Zertifikate unterzeichnet und von der Root-CA bestätigt ist. Das habe ich der Einfachheit halber weggelassen. Zum Verständnis der Syntax dieser Konfigurationsdatei: die Begriffe in [ eckigen Klammern ] fassen bestimmte Funktionen zusammen. Sie werden wirksam, dadurch dass man beim Aufruf der Zertifikatsunterzeichnung diesen Abschnitt mit -extensions = server_cert aktiviert. Unter dem gerade geenannten Abschnitt gibt es einen weiteren Abschnitt [ alt_names ]. Der würde aktiviert werden, wenn man das Kommentarzeichen vor ’subjectAltName = @alt_names‘ entfernt – dann würde @alt_names wirksam werden und den Block einbinden. Das ist die erste Möglichkeit, wie man solche SANs einbinden kann – dazu müsste man natürlich den Inhalt in der Konfigurationsdatei entsprechend anpassen.

Umzug WordPress

Das Bessere ist der Feind des Guten – und ein Anbieter, mit dem man lange Zeit zufrieden war, bietet manchmal nicht mehr den Service und die Leistung, für den man ihn eigentlich mal ausgesucht hatte. Aber so ein Umzug ist auch ein ziemlicher Aufwand – und den schiebt man auf, bis der Leidensdruck zu groß wird.

So war es jetzt an der Zeit, einen neuen Webprovider zu suchen.

Umzug von WordPress – wie bei allen Webprojekten sind das 3 Schritte:
1. Sichern
das sind die statischen Daten (also den Inhalt der Webseite, vermutlich am Besten mit einem FTP-Programm) und die Datenbank – in aller Regel ist das eine MySQL (oder neu eine MariaDB) Datenbank, deren Daten kann man mit PhpmyAdmin in einem sog. Dump sichern und auf eine lokale Maschine übertragen kann. Es empfiehlt sich, den kompletten Verzeichnisbaum zu sichern – dann kann man später nachsehen, wie das genau war, auch wenn der Zugriff zum alten Provider dann schon nicht mehr besteht.

2. Installation der gewünschten Software auf dem neuen Server.
Das dafür nötige Verfahren unterscheidet sich je nach Provider, für grundlegende Pakete wie WordPress gibt es meist einen vorgegebene Installationsmethode; damit wird das PHP-Paket ausgerollt und auf dem Webspace installiert. Falls man Plugins benutzt, sollte man sich auf der noch funktionierenden Installation genau notieren, wie die heissen und in welcher Version sie verwendet werden – und kann sie bei der Gelegenheit auch auf den neuesten Stand bringen.

3. Daten einspielen
Zunächst werden die statischen Daten mittels FTP auf den Webspace eingespielt. Wenn die Versionen des Programms auf dem alten und Server gleich sind, kann das gesamte Verzeichnis überspielt werden – damit werden aber Daten überschrieben, die gerade erst in Schritt 2 neu installiert wurden und man übernimmt Altlasten.
Die eigentlichen Daten bei WordPress stehen in wp-content/uploads. Darin sind als Vorgabe Verzeichnisse mit den Jahrezahlen als Namen, und darin wiederum Verzeichnisse mit den Monatsnummer 01-12. Es genügt, diesen kompletten Baum zu übertragen. Wenn man noch Plugins installiert hat, können diese auch noch weitere Daten angelegt haben – die muss man dann natürlich auch übertragen.
Dann kommt die Datenbank – am einfachsten ist es, eine neue Datenbank zu erstellen und dorthinein die gesicherten Daten zu importieren.
Die Verknüpfung zwischen statischen Daten und Datenbank geschieht über eine Konfigurationsdatei; im Fall von WordPress ist das die Datei wp-config.php. Diese lädt man mit FTP herunter und speichert sie lokal und führt dann die notwendigen Änderungen darin durch.

Dann muss die geänderte Datei hochgeladen werden – und die bereits vorhandene Datei überschrieben werden – dabei Sicherstellen, daß das auch wirklich geschieht!
Damit sollte alles bereits funktionieren – aber es gibt da ein Problem – nämlich einen weiteren Parameter in der wp-config.php: table-prefix:

table_prefix

Und der kann sich unterscheiden – meine ältere Datenbank hatte noch wpw_ und in der neuen Installation war das eine zufällige Folge von 5 Zeichen und der Unterstrich – hier ’59uwr_‘. Im Kommentar darüber steht so harmlos, dass man damit mehrere Installationen in einer Datenbank haben kann – es ist aber zunächst verblüffend, wenn man glaubt, eine leere Datenbank zu haben – alles weg! – aber des Rätsels Lösung ist dieser Parameter – den entsprechend anpassen, und alles ist wieder da.