Skip to Content
Technical Articles

Enable TLS for SAP Content Server 6.50 with Docker

1 Introduction

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 Main Part

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 request

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 request

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 request

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.

3 Conclusion

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.

Be the first to leave a comment
You must be Logged on to comment or reply to a post.