Using self-signed tls SAN certificates for nginx-ingress and SUSE Cloud Application Platform 1.4 deployed on CaasP

A lot of people want to try out SUSE CAP and CaasP in order to get a first-touch impression. With that people would need tls certificate for the needed DNS names e.g. in order to connect to cloud foundry api. Often the first choice is using self-signed tls certificates in the lab environment. This guide should reflect the steps I used to create rootCa + self-signed san certificate for the requested DNS names for using with SUSE Cloud Application Platform which is Cloud Foundry platform in depth.

Because only an X.509 v3 certificate carries SAN information it requires a little more work than when creating an X.509 v1 certificate.

If you want to read and understand more about TLS SAN certificate go here.

Step 1 – create a private key for my own root CA.

openssl genrsa -out ca.key 2048

Step 2 – create a root CA certificate file

openssl req -x509 -new -nodes -key ca.key -sha256 -days 1024 -out ca.crt

Step 3 – create a private key for to be later used to create a tls SAN certificate

openssl genrsa -out 2048

Step 4 - create an V3 extension config file with SAN DNS names (oats.conf)

[ req ]

default_bits = 2048

default_keyfile = oats.key

encrypt_key = no

default_md = sha1

prompt = no

distinguished_name = my_req_distinguished_name

req_extensions = my_extensions

[ my_req_distinguished_name ]

C = CH

ST = Zurich

L = Zurich

O = mycompany

CN =

[ my_extensions ]



subjectKeyIdentifier = hash

[ my_subject_alt_names ]

DNS.1 =

DNS.2 = *

DNS.3 =

DNS.4 = *

Step 4 – create a tls certificate signing request (csr) file using a oats config file.

openssl req -new -key -out -config oats.conf

To verify the just created :

openssl req -in -noout –text

Step 5 – sign the certificate.

I created a config file that called oats.extensions.cnf. The oats.conf was created to create the csr with this config but for signing the csr with an extension V3 for SAN I would create a new conf file just to make it more clear and separated..

The oats.extensions.cnf is needed because I need a SAN certificate covering all needed DNS hostnames in one certificate and this extension need to be passed to the certificate when it gets signed.

Important: follow this link and create the ca.cnf and oats.extensions.cnf prior signing the csr file.

In your working directory create files and subdir as explained in the link above. The root CA file need to be ca.crt and the private key file name is ca.key. If you use different file names then you have to either modify it in the ca.cnf file to fit your needs or change the file names to ca.crt and ca.key accordingly.

Additionally don't forget to issue below commands from your working directory as these steps are needed by our ca.conf specifications.

$ mkdir newcerts

$ touch index.txt

$ echo '01' > serial

Important: stay in our current working directory and do not change to subdirector “newcerts”.

Sample oats.extensions.cnf:



subjectKeyIdentifier = hash

[ my_subject_alt_names ]

DNS.1 =

DNS.2 = *

DNS.3 =

DNS.4 = *

Now we sign the csr:

openssl ca -config ca.cnf -out -extfile oats.extensions.cnf -in

To verify the certificate:

openssl x509 -in -noout –text

Now we finished the tsl SAN certificate creation part.

Let’s move on to use the certs and deploy CAP using nginx-ingress.

Fortunately, SUSE documentation greatly explains the steps to deploy CAP with nginx-ingress and the only thing you need to do is to read and follow the instruction in the SUSE Cap 1.4 official documentation - chapter Using an Ingress Controller with Cloud Application Platform

Step 9 in the documentation is to test either you could reach with your rootCA file. This step is very important and shows if the tls handshake is working and uaa is running well.


The correct result should look like followings: (curl command without -k)

curl --cacert ./k8s/cap/ca.crt

{"issuer":"","authorization_endpoint":"","token_endpoint":"","token_endpoint_auth_methods_supported":["client_secret_basic","client_secret_post"],"token_endpoint_auth_signing_alg_values_supported":["RS256","HS256"],"userinfo_endpoint":"","jwks_uri":"","scopes_supported":["openid","profile","email","phone","roles","user_attributes"],"response_types_supported":["code","code id_token","id_token","token id_token"],"subject_types_supported":["public"],"id_token_signing_alg_values_supported":["RS256","HS256"],"id_token_encryption_alg_values_supported":["none"],"claim_types_supported":["normal"],"claims_supported":["sub","user_name","origin","iss","auth_time","amr","acr","client_id","aud","zid","grant_type","user_id","azp","scope","exp","iat","jti","rev_sig","cid","given_name","family_name","phone_number","email"],"claims_parameter_supported":false,"service_documentation":"","ui_locales_supported":["en-US"]}

Once this step is successful you can move one to deploy SUSE Cloud foundry (scf).

Step 11 in the documentation is another critical point where you have to generate an environment variable with content from your rootCA file. Our self generated root CA needs to be passed to cloud foundry deployment as the router pod need to communicate to and will need our CA to trust the domain.

export INGRESS_CA_CERT=$(cat ca.crt)

Make sure you took the correct rootCA file. In my case it is the file "ca.crt"

You can verify it by:






One mechanism I learned from developers to get a log collection is using klog provided by SUSE Development.

Run below command on your linux client from where you use kubectl and cf commands. The output will be a tar.gz file with logs and information collected.

wget "" && bash ./

You can use this script and read the log files and descriptions about the entire SUSE CAP deployment or send it to somebody else or SUSE Support requesting help.

Good Luck!

Diese Webseite verwendet Cookies. Durch die weitere Nutzung stimmen Sie der Verwendung von Cookies zu.