관리 메뉴

Jacob Baek's home

Make a free certification using certbot on kubernetes 본문

Cloud/Private Cloud

Make a free certification using certbot on kubernetes

jacobbaek Jacob_baek 2020. 8. 12. 14:45

certbot을 이용한 무료 certification 생성하여 적용하는 과정에 대해 알아보자.
해당 내용은 아래와 같은 환경이 마련된 상태에서 진행되었다.

  • kubernetes
  • AWS route53 dns 등록 : example.com(가정사항)
  • nginx-ingress : abc.example.com

실제 동작될 환경은 kubernetes 상에 동작되는 pod이며 해당 pod는 ingress로 외부에서 연결이 가능하다.
ingress의 tls 항목에 secretName에서 사용할 인증서를 아래와 같은 과정을 통해 생성 및 적용해보자.

certbot 준비

CentOS7 기준으로 아래와 같은 순서로 인증서 생성을 진행한다.

yum install epel-release -y
yum install certbot python2-certbot-nginx -y

certbot을 이용한 인증서 생성

아래와 같은 명령을 수행하여 인증서 생성과정을 수동으로 진행해보자.

certbot certonly --manual -d "*.example.com" -d "example.com"

DNS TXT record 인증

수행과정중 다음과 같은 TXT record에 대한 검증과정을 요구한다.

Please deploy a DNS TXT record under the name
_acme-challenge.example.com with the following value:

XxxXx9Xx9XX6X8xXxXxxxxXX6xXXxxxxxxx-XX7XxxX

Before continuing, verify the record is deployed.

앞서 가정이 DNS 서비스를 관리하는 주체가 AWS route53이기에 route53에 hosted zone 중에
앞서 생성한 example.com에 TXT Record를 생성해주자.

kubernetes상에서 app/service/ingress생성하여 특정 페이지의 데이터 호출을 통한 인증

Create a file containing just this data:

XxXx9XxXXXxx9xxxxxXxxXX_XxxX9Xx-XxXxxX9_9xX.XxXXX999xxxXXxxxX9xXxX_XxX-X9XXXXXxxX9XxXx9

And make it available on your web server at this URL:

http://example.com/.well-known/acme-challenge/XxXx9XxXXXxx9xxxxxXxxXX_XxxX9Xx-XxXxxX9_9xX

(This must be set up in addition to the previous challenges; do not remove,
replace, or undo the previous challenge tasks yet.)

인증서 생성과정을 거치다보면 특정 페이지의 접속 및 지정된 데이터 출력을 요구하는 과정이 막바지에 있다.
이를 위해 kubernetes에서 해당 과정을 pass할수 있도록 pod/service/ingress를 추가해 인증서 생성이 정상적으로 이루어질수 있도록 한다.

kind: Pod
apiVersion: v1
metadata:
  name: certbot-app
  labels:
    app: certbot
spec:
  containers:
    - name: certbot-app
      image: hashicorp/http-echo
      args:
        - "-text=XxXx9XxXXXxx9xxxxxXxxXX_XxxX9Xx-XxXxxX9_9xX.XxXXX999xxxXXxxxX9xXxX_XxX-X9XXXXXxxX9XxXx9"

---

kind: Service
apiVersion: v1
metadata:
  name: certbot-service
spec:
  selector:
    app: certbot
  ports:
    - port: 5678 # Default port for image

---

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: certbot-ingress
  annotations:
    ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - http:
      paths:
        - path: /.well-known/acme-challenge/XxXx9XxXXXxx9xxxxxXxxXX_XxxX9Xx-XxXxxX9_9xX
          backend:
            serviceName: certbot-service
            servicePort: 5678

위와 같이 생성후 example.com/.well-known/acme-challenge/XxXx9XxXXXxx9xxxxxXxxXX_XxxX9Xx-XxXxxX9_9xX 로 접속해보면 text로 추가된 데이터가 확인된다.

위 과정을 다 거치고 나면 완료가 되면서 아래와 같은 메세지가 출력된다.

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/example.com/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/example.com/privkey.pem
   Your cert will expire on 2020-11-10. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot
   again. To non-interactively renew *all* of your certificates, run
   "certbot renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

즉, 인증서생성이 완료되었고 해당 경로는 /etc/letsencrypt/live/example.com/ 이라는것이다.

실제 해당 경로를 확인해보면 다음과 같은 private key 부터 chain pem까지 존재하는것을 확인할수 있다.

[root@deploy nginx-ingress]# ls -al /etc/letsencrypt/live/example.com/
total 4
drwxr-xr-x. 2 root root  93  8월 12 06:00 .
drwx------. 3 root root  38  8월 12 06:00 ..
lrwxrwxrwx. 1 root root  34  8월 12 06:00 cert.pem -> ../../archive/example.com/cert1.pem
lrwxrwxrwx. 1 root root  35  8월 12 06:00 chain.pem -> ../../archive/example.com/chain1.pem
lrwxrwxrwx. 1 root root  39  8월 12 06:00 fullchain.pem -> ../../archive/example.com/fullchain1.pem
lrwxrwxrwx. 1 root root  37  8월 12 06:00 privkey.pem -> ../../archive/example.com/privkey1.pem
-rw-r--r--. 1 root root 692  8월 12 06:00 README

생성된 cert가 입력한 내용과 동일한지 openssl을 통해 확인해보자.

[root@deploy certs]# openssl x509 -text -noout -in /etc/letsencrypt/live/example.com/cert.pem 
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            99:99:x9:99:xx:x9:99:x9:99:99:99:99:99:e2:a6:5b:xx:xx
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=US, O=Let's Encrypt, CN=Let's Encrypt Authority X3
        Validity
            Not Before: Aug 12 05:00:47 2020 GMT
            Not After : Nov 10 05:00:47 2020 GMT
        Subject: CN=*.example.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)

kubernetes ingress에 적용하기

ingress에서 사용할 tls 인증서를 secret으로 생성해보자.

kubectl create secret tls example-certs --key /etc/letsencrypt/live/example.com/privkey.pem --cert /etc/letsencrypt/live/example.com/fullchain.pem --namespace default

이제 생성된 secret을 사용하는 ingress 를 생성한다.

kind: Ingress
metadata:
  name: abc
  namespace: abc
spec:
  rules:
  - host: abc.example.com
    http:
      paths:
      - backend:
          serviceName: abc
          servicePort: 8888
        path: /
  tls:
  - hosts:
    - abc.example.com
    secretName: example-certs

이제 valid한 인증서를 통해 서비스되는 환경 구성이 완료되었다.
생성된 ingress 주소인 abc.example.com으로 접속해보면 다음과 같이 인증서가 valid 한것으로 확인된다.

만약 self-signed certification을 가지고 적용하고자 한다면 openssl 명령을 통해 생성하여 적용할수 있다.
간단히 생성한 shell script을 사용해볼것을 권장한다.

#!/bin/bash

NAME='abc'
DOMAIN='example.com'
NAMESPACE='abc'

openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout $NAME-tls.key -out $NAME-tls.crt -subj "/CN=*.${DOMAIN}"
kubectl create secret tls $NAME-secret --key $NAME-tls.key --cert $NAME-tls.crt -n $NAMESPACE

참고사이트

0 Comments
댓글쓰기 폼