Author : MD TAREQ HASSAN | Updated : 2021/06/09

Lets Encrypt For AGIC

Lets Encrypt For Nginx

Lets Encrypt For Traefik

Self Signed Certicate For Http Application Routing

Creating Self Signed SSL Certicate

Method-1: quickly create self signed certificate

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -out demo-ingress-tls.crt -keyout demo-ingress-tls.key -subj "/CN=api.xxxxxxx.japaneast.aksapp.io/O=demo-ingress-tls"

Note: CN must match with host url in K8s ingress that will serve our app, otherwise browser will consider it fake certificate.

Method-2: Become self proclaimed Certificate Authority (CA)

Way-1: see https://gist.github.com/fntlnz/cf14feb5a46b2eda428e000157447309

Excerpt

crt.config
[ v3_ca ]
basicConstraints = critical,CA:TRUE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
[req]
req_extensions = v3_req
distinguished_name = req_distinguished_name
[req_distinguished_name]
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1 = org



openssl req -x509 -new -nodes -extensions v3_ca -key rootCA.key -sha256 -days 1024 -out rootCA.crt

openssl x509 -req -extfile <(printf "subjectAltName=DNS:YOUR_DOMAIN_NAME") -days 120 -in SERVER.csr -CA rootCA.crt -CAkey root_rsa.key -CAcreateserial -out SERVER.crt -sha256

$ openssl req -new -sha256 \
    -key SERVER.key \
    -subj "/C=US/ST=North Carolina/O=ORG/OU=ORG_UNIT/CN=YOUR_DOMAIN_NAME" \
    -reqexts SAN \
    -config <(cat /etc/ssl/openssl.cnf <(printf "\n[SAN]\nsubjectAltName=DNS:YOUR_DOMAIN_NAME")) \
    -out SERVER.csr

Way-2

openssl genrsa -des3 -out root_ca_private_key.key 2048

Now generate root ca (.pem) using your private key. You will be promted for pass phrase for private key.

openssl req -x509 -new -nodes -key root_ca_private_key.key -sha256 -days 1825 -out root_ca.pem

So, we got the followings

From now we can use our private key and root ca to sign certificates as a CA. We can manually import our root ca to our PC/browser so that we become valid CA to our PC/browser and PC/browser will trust certificate we sign.

Allow third party root CAs in windows

Placeholder image

Import our root ca (.pem)

cd <path-to-certificate-file>

#
# For current user only
# 
# 'f' flag to force (will override previously imported certificate)
#
certutil –addstore –f "Root" root_ca.pem

#
# For PC
#
certutil –addstore -enterprise –f "Root" root_ca.pem

Now we are Certificate Authority on our own PC and we can sign certificate for our website.

Create private key for our website certificate

openssl genrsa -out api.xxxxxxx.japaneast.aksapp.io.key 2048

Create Certificate Signing Request (CSR) using private key

openssl req -new -key api.xxxxxxx.japaneast.aksapp.io.key -out api.xxxxxxx.japaneast.aksapp.io.csr

Create extra parameter for openssl command: api.xxxxxxx.japaneast.aksapp.io.ext

authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1 = api.xxxxxxx.japaneast.aksapp.io

Now sign certificate for website using CSR and extra parameters

openssl x509 -req -in api.xxxxxxx.japaneast.aksapp.io.csr -CA root_ca.pem -CAkey root_ca_private_key.key -CAcreateserial -out api.xxxxxxx.japaneast.aksapp.io.crt -days 30 -sha256 -extfile api.xxxxxxx.japaneast.aksapp.io.ext

api.xxxxxxx.japaneast.aksapp.io.crt’ will be generated and that will be used to create K8s secret (SSL certificate for our app)

Using Self Signed SSL Certicate

Create namesapce for demo if needed

kubectl create namespace demo

Now trust those self signed certificates manually

Create K8s secret using TLS cert and key (use either of the followings):

yaml manifest: demo-tls-secret.yaml

apiVersion: v1
kind: Secret
metadata:
  name: demo-tls-secret
  namespace: demo
type: kubernetes.io/tls
data:
  tls.crt: <base64 encoded cert>
  tls.key: <base64 encoded key>

Example ingress with TLS

... ... ...
  annotations:
    kubernetes.io/ingress.class: addon-http-application-routing
spec:
  tls: # Ingress with TLS
    - hosts:
      - aks-helloworld-one.xxxxxxxx.japaneast.aksapp.io
    secretName: example-tls
... ... ...

Now deploy 2 applications:

aks-helloworld-one.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: aks-helloworld-one
spec:
  replicas: 1
  selector:
    matchLabels:
      app: aks-helloworld-one
  template:
    metadata:
      labels:
        app: aks-helloworld-one
    spec:
      containers:
      - name: aks-helloworld-one
        image: mcr.microsoft.com/azuredocs/aks-helloworld:v1
        ports:
        - containerPort: 80
        env:
        - name: TITLE
          value: "AKS TLS (https) - Hello World 1"
          
---

apiVersion: v1
kind: Service
metadata:
  name: aks-helloworld-one  
spec:
  type: ClusterIP
  ports:
  - port: 80
  selector:
    app: aks-helloworld-one
    
---

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: aks-helloworld-one
  annotations:
    kubernetes.io/ingress.class: addon-http-application-routing
spec:
  tls:
  - hosts:
    - aks-helloworld-one.xxxxxxx.japaneast.aksapp.io
    secretName: demo-tls-secret
  rules:
  - host: aks-helloworld-one.xxxxxxx.japaneast.aksapp.io
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service: 
            name: aks-helloworld-one
            port: 
              number: 80

aks-helloworld-two.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: aks-helloworld-two
spec:
  replicas: 1
  selector:
    matchLabels:
      app: aks-helloworld-two
  template:
    metadata:
      labels:
        app: aks-helloworld-two
    spec:
      containers:
      - name: aks-helloworld-two
        image: mcr.microsoft.com/azuredocs/aks-helloworld:v1
        ports:
        - containerPort: 80
        env:
        - name: TITLE
          value: "AKS TLS (https) - Hello World 2"
          
---

apiVersion: v1
kind: Service
metadata:
  name: aks-helloworld-two  
spec:
  type: ClusterIP
  ports:
  - port: 80
  selector:
    app: aks-helloworld-two
    
---

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: aks-helloworld-two
  annotations:
    kubernetes.io/ingress.class: addon-http-application-routing
spec:
  tls:
  - hosts:
    - aks-helloworld-two.xxxxxxxx.japaneast.aksapp.io
    secretName: demo-tls-secret
  rules:
  - host: aks-helloworld-two.xxxxxxxx.japaneast.aksapp.io
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service: 
            name: aks-helloworld-two
            port: 
              number: 80

Check that 2 apps are available with those URLs