EDUCAÇÃO E TECNOLOGIA

Enable TLS for SAP Content Server 6.50 with Docker

For security reasons, in production environments all hypertext transfer communication should be encrypted, meaning you should use https instead of http.

This blog post will show how to enble TLS for SAP Content Server with Docker Image.

Therefore we need a X.509 certificate chain. The cheapest method is creating your own self-signed root certificate authority (root CA) and intermediate certificate authority (CA) to create server certificates.

More details about certificate chain can be found on https://en.wikipedia.org/wiki/Chain_of_trust

2.1 Prerequisites

If openssl is not already available you can install it on ubuntu with:

sudo apt-get install openssl

2.2 Main certificate directory

Create a main folder to manage your certificates.

2.3 Root CA certificate

Create a sub-folder for the root CA.

mkdir root-ca && cd $_

2.3.1 root-ca.conf

Create a root-ca.conf file and start VIM.

touch root-ca.conf && vi $_

Copy and paste the content of root-ca.conf.

# Simple Root CA # The [default] section contains global constants that can be referred to from # the entire configuration file. [ default ] ca = root-ca # CA name dir = . # Top dir # The next part of the configuration file is used by the openssl req command. # It defines the CA's key pair, its DN, and the desired extensions for the CA # certificate. [ req ] default_bits = 2048 # RSA key size encrypt_key = yes # Protect private key default_md = sha256 # MD to use utf8 = yes # Input is UTF-8 string_mask = utf8only # Emit UTF-8 strings prompt = no # Don't prompt for DN distinguished_name = ca_dn # DN section req_extensions = ca_reqext # Desired extensions [ ca_dn ] 0.domainComponent = "mydomain" countryName = "DE" localityName = "my city" organizationName = "my organization" commonName = "my Root CA" [ ca_reqext ] keyUsage = critical,keyCertSign,cRLSign basicConstraints = critical,CA:true subjectKeyIdentifier = hash # The remainder of the configuration file is used by the openssl ca command. # The CA section defines the locations of CA assets, as well as the policies # applying to the CA. [ ca ] default_ca = root_ca # The default CA section [ root_ca ] certificate = $dir/$ca/root-ca.crt # The CA cert private_key = $dir/$ca/private/$ca.key # CA private key new_certs_dir = $dir/$ca/certs # Certificate archive serial = $dir/$ca/db/serial # Serial number file crlnumber = $dir/$ca/db/crlnumber # CRL number file database = $dir/$ca/db/index # Index file unique_subject = no # Require unique subject default_days = 3652 # How long to certify for default_md = sha256 # MD to use policy = match_pol # Default naming policy email_in_dn = no # Add email to cert DN preserve = no # Keep passed DN ordering name_opt = ca_default # Subject DN display options cert_opt = ca_default # Certificate display options copy_extensions = none # Copy extensions from CSR x509_extensions = signing_ca_ext # Default cert extensions default_crl_days = 365 # How long before next CRL crl_extensions = crl_ext # CRL extensions # Naming policies control which parts of a DN end up in the certificate and # under what circumstances certification should be denied. [ match_pol ] #domainComponent = optional # Included if present organizationName = match # Must match 'Simple Inc' organizationalUnitName = optional # Included if present commonName = supplied # Must be present countryName = supplied [ any_pol ] domainComponent = optional countryName = supplied stateOrProvinceName = optional localityName = supplied organizationName = supplied organizationalUnitName = optional commonName = optional emailAddress = optional # Certificate extensions define what types of certificates the CA is able to # create. [ root_ca_ext ] keyUsage = critical,keyCertSign,cRLSign basicConstraints = critical,CA:true subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always [ signing_ca_ext ] keyUsage = critical,keyCertSign,cRLSign basicConstraints = critical,CA:true,pathlen:0 subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always # CRL extensions exist solely to point to the CA certificate that has issued # the CRL. [ crl_ext ] authorityKeyIdentifier = keyid:always

Maybe adapt the ca-dn part to more proper values.

When using your own values, make sure that the same values are always used in the following configurations, otherwise the certificate chain will be broken.

( Exit VIM with ESC and :wq )

2.3.2 Sub-directories & additional files for root CA

Create further needed sub-directories.

mkdir private && mkdir certs && mkdir db

Create a empty index file within db folder.

touch db/index

Create a serial number file containing a random number.

echo 08954571 > db/serial

Go back to certificate main folder.

cd ..

2.3.3 Create root CA certificate

Create root-ca.csr and root-ca.key file with openssl

openssl req -new -config root-ca/root-ca.conf -out root-ca/root-ca.csr -keyout root-ca/private/root-ca.key

Enter a PEM pass phrase (Make something up, but make sure you don’t forget)

2.3.4 Sign root CA certificate

Sign the root CA certificate

openssl ca -selfsign -config root-ca/root-ca.conf -in root-ca/root-ca.csr -out root-ca/root-ca.crt -extensions root_ca_ext

2.4 Intermediate CA certificate

Create a subfolder for signing CA.

mkdir signing-ca && cd $_

2.4.1 signing-ca.conf

Create a signing-ca.conf file and start VIM.

touch signing-ca.conf && vi $_

Content of signing-ca.conf

# Simple Signing CA # The [default] section contains global constants that can be referred to from # the entire configuration file. [ default ] ca = signing-ca # CA name dir = . # Top dir # The next part of the configuration file is used by the openssl req command. # It defines the CA's key pair, its DN, and the desired extensions for the CA # certificate. [ req ] default_bits = 2048 # RSA key size encrypt_key = yes # Protect private key default_md = sha256 # MD to use utf8 = yes # Input is UTF-8 string_mask = utf8only # Emit UTF-8 strings prompt = no # Don't prompt for DN distinguished_name = ca_dn # DN section req_extensions = ca_reqext # Desired extensions [ ca_dn ] 0.domainComponent = "mydomain" countryName = "DE" localityName = "my city" organizationName = "my organization" commonName = "my Signing CA" [ ca_reqext ] keyUsage = critical,keyCertSign,cRLSign basicConstraints = critical,CA:true,pathlen:0 subjectKeyIdentifier = hash # The remainder of the configuration file is used by the openssl ca command. # The CA section defines the locations of CA assets, as well as the policies # applying to the CA. [ ca ] default_ca = signing_ca # The default CA section [ signing_ca ] certificate = $dir/$ca/$ca.crt # The CA cert private_key = $dir/$ca/private/$ca.key # CA private key new_certs_dir = $dir/$ca/certs # Certificate archive serial = $dir/$ca/db/serial # Serial number file crlnumber = $dir/$ca/db/crlnumber # CRL number file database = $dir/$ca/db/index # Index file unique_subject = no # Require unique subject default_days = 3652 # How long to certify for default_md = sha256 # MD to use policy = match_pol # Default naming policy email_in_dn = no # Add email to cert DN preserve = no # Keep passed DN ordering name_opt = ca_default # Subject DN display options cert_opt = ca_default # Certificate display options copy_extensions = copy # Copy extensions from CSR x509_extensions = email_ext # Default cert extensions default_crl_days = 365 # How long before next CRL crl_extensions = crl_ext # CRL extensions # Naming policies control which parts of a DN end up in the certificate and # under what circumstances certification should be denied. [ match_pol ] #domainComponent = optional # Included if present organizationName = supplied # Must match organizationalUnitName = optional # Included if present commonName = supplied # Must be present countryName = match [ any_pol ] domainComponent = optional countryName = supplied stateOrProvinceName = optional localityName = supplied organizationName = supplied organizationalUnitName = optional commonName = optional emailAddress = optional # Certificate extensions define what types of certificates the CA is able to # create. [ email_ext ] keyUsage = critical,digitalSignature,keyEncipherment basicConstraints = CA:false extendedKeyUsage = emailProtection,clientAuth subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always [ server_ext ] keyUsage = critical,digitalSignature,keyEncipherment basicConstraints = CA:false extendedKeyUsage = serverAuth,clientAuth subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always # CRL extensions exist solely to point to the CA certificate that has issued # the CRL. [ crl_ext ] authorityKeyIdentifier = keyid:always

Maybe adapt the ca-dn part to more proper values.

2.4.2 Sub-directories & additional files for intermediate CA

mkdir private && mkdir certs && mkdir db

Create a empty index file within db folder.

touch db/index

Create a serial number file containing a random number.

echo 08954572 > db/serial

Go back to certificate main folder.

cd ..

2.4.3 Create intermediate CA certificate

openssl req -new -config signing-ca/signing-ca.conf -out signing-ca/signing-ca.csr -keyout signing-ca/private/signing-ca.key

Enter a PEM pass phrase

2.4.4 Sign intermediate CA certificate

openssl ca -config root-ca/root-ca.conf -in signing-ca/signing-ca.csr -out signing-ca/signing-ca.crt -extensions signing_ca_ext

2.5 SAP Content Server certificate

Create a subfolder for the server certificate

mkdir server && cd $_

2.5.1 server.conf

Create a server.conf file and start VIM.

touch server.conf && vi $_

Content of server.conf

[ req ] default_bits = 2048 distinguished_name = req_dn req_extensions = req_ext default_md = sha256 dirstring_type = nombstr prompt = no [ req_dn ] C = DE ST = my state L = my city O = my organization OU = my team CN = sapcs.mydomain.locl [req_ext] subjectAltName=@subject_alt_name [ subject_alt_name ] DNS.1=sapcs.mydomain.locl DNS.2=mydomain.locl

Go back to certificate main folder

cd ..

2.5.2 Create SAP Content Server certificate

openssl req -new -config server/server.conf -out server/server.csr -keyout server/server.key

2.5.3 Sign SAP Content Server certificate

openssl ca -config signing-ca/signing-ca.conf -in server/server.csr -out server/server.crt -extensions server_ext

2.5.4 Remove passphrase from private key

To enable Apache to start automatically without user interaction, we remove the passphrase from the private key of SAP Content Server certificate.

openssl rsa -in server/server.key -out server/server-wopass.key

It is important that no unauthorized person gets access to the file. Otherwise, together with the public certificate, he can pretend the identity of the SAP Content Server.

There is an alternative way to store the password in a bash file (e.g. PassPhrase.sh), which has to be included via SSLPassPhraseDialog exec:/etc/httpd/PassPhrase.sh into httpd.conf file. But in this case the PassPharase.sh file has to be kept safe. (Not much was gained)

2.6 Importing root CA certificates in certificate store

Because we use a self-signed certificate, we need to import the root-ca.crt into the certificate store in the right place. Otherwise we won’t get a trusted certificate chain.

With WSL2 you can use the Explorer from Windows OS together with the \\wls$ network share. In case using Ubuntu as a linux-sub-system you will find the main certificate directory at:

\\wsl$\Ubuntu-20.04\home\<user>\certificates

2.6.1 Import root CA certificate in Windows

Go into the root-ca folder and make a double-click on file root-ca.crt.

Press the marked button.

Choose local computer

and press the button “Continue”.

Now we have to select the proper store for root CAs.

Press “OK”,  “Continue” and “Complete”.

2.6.2 Import root CA certificate in Ubuntu

Go to root-ca directory.

cd root-ca

Copy root-ca.crt to /usr/share/ca-certificates/mozilla/.

sudo cp root-ca.crt /usr/share/ca-certificates/mozilla/

Update ca-certificates configuration.

sudo dpkg-reconfigure ca-certificates

Press Enter and follow the upcomming instructions.

2.7 Check certificate chain

openssl verify -CAfile signing-ca/signing-ca.crt -verify_hostname sapcs.mydomain.locl server/server.crt

2.8 Change Docker Image

2.8.1 Docker Image directory for certificates

Create a folder cert within the folder of the SAP Content Server Docker Image.

Copy server.crt into folder cert.

cp server/server.crt ../docker-images/sapcs/cert

Copy server-wopass.key into folder cert.

cp server/server-wopass.key ../docker-images/sapcs/cert

Copy signing-ca.crt into folder cert.

cp signing-ca/signing-ca.crt ../docker-images/sapcs/cert

2.8.2 Change httpd.conf

Open httpd.conf with VIM.

Part to be inserted

<VirtualHost *:80> DocumentRoot "/usr/local/apache2/htdocs" ServerName sapcs.mydomain.locl SSLEngine on SSLProtocol -all +TLSv1.2 SSLCertificateFile /usr/local/apache2/conf/server.crt SSLCertificateChainFile /usr/local/apache2/conf/signing-ca.crt SSLCertificateKeyFile /usr/local/apache2/conf/server-wopass.key </VirtualHost>

Insertion position

( Exit VIM with ESC and :wq )

2.8.3 Change Docker File

Open Docker file.

vi ../docker-images/sapcs/Dockerfile

Content of Docker file.

FROM httpd:2.2 COPY ./cs.conf /usr/local/apache2/ COPY ./httpd.conf /usr/local/apache2/conf COPY ./download/*.so /usr/local/apache2/modules/ COPY ./cert/ /usr/local/apache2/conf RUN chmod a+x /usr/local/apache2/modules/* RUN mkdir /usr/local/apache2/RepRoot

( Exit VIM with ESC and :wq )

2.9 Rebuild Image and start Docker Container

Go into main folder of SAP Content Server Docker Image.

cd ../docker-images/sapcs/

Build Docker Image.

docker-compose build

Start Docker Container.

docker-compose up -d

2.10 Check https connection

2.10.1 Change hosts file

So that localhost can be accessed via the FQDN sapcs.mydomain.locl, the hosts file must be adapted.

Open hosts file in editor (e.g. notepad++).

C:\Windows\System32\drivers\etc\hosts

Insert the marked line into hosts file.

2.10.2 Get ServerInfo

Open URL in browser.

https://sapcs.mydomain.locl:1090/ContentServer/ContentServer.dll?serverInfo

Now you should see a closed lock icon in your browser.

Click on the lock icon and you should see that the communication is now trusted.

If you use Firefox, you must first import the root CA certificate into the Firefox certificate store for the connection to be recognized as trusted.

As you have seen, most of the work involved in setting up TLS on the SAP Content Server is creating the appropriate certificates.

In a larger production environment, the creation of the root CA and intermediate certification authority may be omitted because they already exist, so that only the appropriate server certificate needs to be created.

But since the handling of certificates is new territory for someone, it was important to me to show how to create certificates from scratch, so that she or he could experiment a little bit with it.

The adaptation of the configuration files of the Content Server is no big effort, as is the renewal of the certificates. In this case, you only need to copy the new files into the corresponding directory of the Docker Image, rebuild the image and start it again.