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)
- Generate “Root CA” private key that will be used to sign SSL certificate as a CA
- Use passphrase to protect your private key so that only you can sign certificate as 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
- Private key:
root_ca_private_key.key
- Root certificate:
root_ca.pem
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
- Ctrl + R >
secpol.msc
> enter - Select Public key policies > Double click on “Certificate path validation settings”
- Check: “Define these policy setting” > apply > ok
Import our root ca (.pem
)
- Using command:
certutil –addstore –f "Root" <path-to-certificate-file>
- More on importing certificate:
- Using
certmgr.msc
andmmc
: https://windowsreport.com/install-windows-10-root-certificates/ - StackOverflow question: https://superuser.com/questions/1031444/importing-pem-certificates-on-windows-7-on-the-command-line/1032179
- Using
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
- Assuming you enabled ‘http-application-routing’ add-on in AKS
- Find out url for DNS zone (something like:
xxxxxxx.japaneast.aksapp.io
) - We are gonna use ‘
api.xxxxxxx.japaneast.aksapp.io
’ as base url to serve our application
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
- Windows:
certutil -addstore -f /path/to/cert.crt
- Chrome:
- Go to:
chrome://settings/privacy
- Security > Manage certificates
- Import certificate
- Go to:
Create K8s secret using TLS cert and key (use either of the followings):
- kubectl command:
kubectl create secret tls demo-ingress-tls --namespace demo --key demo-ingress-tls.key --cert demo-ingress-tls.crt
- yaml manifest:
kubectl apply -f demo-tls-secret.yaml -n demo
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:
- Both service of type ClusterIP
- Both will use TLS secret
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
Links
- https://docs.microsoft.com/en-us/azure/aks/http-application-routing
- https://docs.microsoft.com/en-us/azure/aks/ingress-internal-ip#create-an-ingress-controller
- https://docs.microsoft.com/en-us/azure/aks/ingress-tls
- https://carlos.mendible.com/2019/01/10/aks-configure-tls-termination-with-the-http-application-routing-addon/