ESXi Let’s Encrypt 자동 renewal

ESXi 호스트에서 Let’s Encrypt를 자동으로 renewal 하는 방법이다. 지금까지 살펴본 결과 AWS Route 53를 통하여 DNS 서비스를 제공받는 경우에는 방법이 있으나1) 그 외의 경우에는 ESXi 호스트 자체적으로 Let’s Encrypt 인증서를 생성하고 renewal 하는 방법이 없어 강좌를 작성한다.

If you find english lecture, please visit ‘ESXi Let’s Encrypt auto renewal in ESXi host

  • 볼드체는 직접 입력해야하는 명령을 의미합니다.
  • 이탤릭체는 본인의 상황에 맞추어 바꿔서 입력해야할 수도 있는 것을 의미합니다.

준비물

  • ACME-tiny
    diafygi라는 유저가 만든 acme-tiny를 직접 사용할 수 있으나 (https://github.com/diafygi/acme-tiny) esxi 에서 https를 접속할 때 인증서 오류가 발생한다. 따라서 이 git을 fork 하여 인증서 오류를 무시할 수 있는 수정 버전을 미리 만들어 두었다.2)
    ESXi는 git을 지원하지 않는다. 따라서, https://github.com/dmc31a42/acme-tiny 에서 ‘Clone or download’->’Download ZIP’으로 프로젝트를 다운받고 내용물을 SSH(SCP)를 통하여 ESXi Host의 /etc/vmware/ssl/acme-tiny 폴더에 넣어둔다.(/etc/vmware/ssl/acme-tiny/acme_tiny.py 의 경로가 될 수 있도록 내용물을 옮겨둔다.)
  • 방화벽(httpClient) 예외 처리
    VMWare Host Client에 접속하여(Web UI) ‘네트워킹’->’방화벽 규칙’->’httpClient’ 규칙을 ‘사용’으로 설정한다. acme 절차 상 특정 페이지에 접속을 해야하는 경우가 있는데 80 송신 포트의 경우 ‘dynamicruleset’, ‘Fault Tolerance’, ‘vCenter Update Manager’ 규칙에 의하여 이미 예외 처리가 되어있는 상태이나 443 포트는 어느 규칙에 의해서도 예외 처리 되어있지 않다. 그래서 https 접속을 위해서는 443 송신 포트를 포함하고 있는 ‘httpClient’ 규칙을 사용으로 설정해주어야 한다.

절차

Let’s Encrypt 키 수동으로 생성하기

(아래의 절차는 대부분 https://github.com/diafygi/acme-tiny 의 안내를 따릅니다)

Step 1: Let’s Encrypt account private key를 생성

본래의 설명에도 나와있다싶이 account private key에 대한 것을 안다면 이 스크립트는 필요없다고 나와있습니다. 저도 잘 이해를 못하기에 그냥 그대로 따라할 것입니다. 여기서 사용하는 모든 키 파일들은 ‘/etc/vmware/ssl’ 경로에 저장하는 것을 전제로 강좌를 작성했습니다.

[root@esxi:~] cd /etc/vmware/ssl/
[root@esxi:/etc/vmware/ssl] openssl genrsa 4096 > account.key
Generating RSA private key, 4096 bit long modulus
…………………………………………………………………………………..++
……………………………….++
e is 65537 (0x10001)

이미 Let’s Encrypt key가 있을때는 github에서 직접 확인해보고 진행해주세요.

Step 2: Certificate signing request (CSR) 생성하기

HTTPS의 인증서 중 비밀키에 해당하는 인증서와 공개키 인증서 생성을 요구하는 파일을 생성함.

[root@esxi:/etc/vmware/ssl] openssl genrsa 4096 > letsencrypt.key
Generating RSA private key, 4096 bit long modulus
………………………………….++
……………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………..++
e is 65537 (0x10001)

git의 설명대로 csr을 생성하려하면 오류가 나타날 것이다.

[root@esxi:/etc/vmware/ssl] openssl req -new -sha256 -key letsencrypt.key -subj “/CN=yourdomain.com” > letsencrypt.csr
unable to find ‘distinguished_name’ in config problems making Certificate Request 145401271976:error:0E06D06C:configuration file routines:NCONF_get_string:no value:conf_lib.c:324:group=req name=distinguished_name

이는 openssl.cnf 파일에 필요한 내용이 없어서 그런 것이므로, /etc/vmware/ssl/openssl.cnf 파일에 아래와 같은 내용을 추가하고 저장한다.3)

#
# OpenSSL example configuration file.
#

# This definition stops the following lines choking if HOME isn’t
# defined.
HOME = .
RANDFILE = $ENV::HOME/.rnd

####################################################################
[ req ]
default_bits = 4096
default_md = sha256
default_keyfile = letsencrypt.key
distinguished_name = req_distinguished_name
extensions = v3_ca
req_extensions = v3_ca

[ v3_ca ]
basicConstraints = critical, CA:TRUE, pathlen:0
subjectKeyIdentifier = hash
##authorityKeyIdentifier = keyid:always, issuer:always
keyUsage = keyCertSign, cRLSign
nsCertType = sslCA, emailCA, objCA

[req_distinguished_name ]
countryName = KR
countryName_default = KR
countryName_min = 2
countryName_max = 2

# 회사명 입력
organizationName = nakwonelec
organizationName_default = nakwonelec

# 부서 입력
#organizationalUnitName = development
#organizationalUnitName_default = development

# SSL 서비스할 domain 명 입력
commonName = esxi.nakwonelec.com
commonName_default = lesstif’s Self Signed CA
commonName_max = 64

openssl.cnf를 수정한 후 다시 csr 생성 명령어를 실행하면 오류 없이 실행될 것이다.

Step 3: challenge files을 Let’s Encrypt에서 확인할 수 있게 설정하기

인증서를 발급할 도메인이 본인의 도메인이 맞는지 확인할 수 있도록 challenge files을 이 도메인에 연결된 사이트에서 제공할 수 있게 설정해야한다. ESXi 웹 서버의 기본 경로는 ‘/usr/lib/vmware/hostd/docroot’ 이므로 이 위치 아래에 ‘.well-known/acme-challenge/’ 폴더를 만들 것이다.

[root@esxi:/etc/vmware/ssl] mkdir -p /usr/lib/vmware/hostd/docroot/.well-known/acme-challenge/

원 글에 있는 location 설정은 별도로 해줄 필요는 없다. try_files는 무슨설정인지 명확히 모르고 어디서 설정해줘야 하는지 몰라서 신경 안썼는데 제대로 작동은 하는것 같다.

Step 4: 서명된 인증서를 얻기!

acme_tiny.py와 준비한 파일들로 서명된 인증서를 얻을 수 있다.

[root@esxi:/etc/vmware/ssl] /usr/bin/python /etc/vmware/ssl/acme-tiny/acme_tiny.py –account-key /etc/vmware/ssl/account.key –csr /etc/vmware/ssl/letsencrypt.csr –acme-dir /usr/lib/vmware/hostd/docroot/.well-known/acme-challenge > /etc/vmware/ssl/letsencrypt.crt
Parsing account key…
Parsing CSR…
Found domains: esxitest.nakwonelec.com
Getting directory…
Directory found!
Registering account…
Registered!
Creating new order…
Order created!
Verifying esxitest.nakwonelec.com…
esxitest.nakwonelec.com verified!
Signing certificate…
Certificate signed!

Step 5: 인증서를 설치하기

인증서를 오류없이 얻었다면 기존의 인증서를 백업해두고 새로 받은 인증서를 원래 있던 인증서 위치에 복사해둔다.

[root@esxi:/etc/vmware/ssl] cp -f /etc/vmware/ssl/rui.key /etc/vmware/ssl/orig.rui.key
[root@esxi:/etc/vmware/ssl] cp -f /etc/vmware/ssl/rui.crt /etc/vmware/ssl/orig.rui.crt
[root@esxi:/etc/vmware/ssl] cp -f /etc/vmware/ssl/letsencrypt.key /etc/vmware/ssl/rui.key
[root@esxi:/etc/vmware/ssl] cp -f /etc/vmware/ssl/letsencrypt.crt /etc/vmware/ssl/rui.crt

발급받은 인증서를 rui.crt, rui.key로 복사해두었으면 매니지먼트 에이전트를 재시작하여 인증서를 적용한다.4)

[root@esxi:/etc/vmware/ssl] /etc/init.d/hostd restart
watchdog-hostd: Terminating watchdog process with PID 90365
hostd stopped.
hostd started.
[root@esxi:/etc/vmware/ssl] /etc/init.d/vpxa restart
watchdog-vpxa: Terminating watchdog process with PID 90405
vpxa stopped.
[root@esxi:/etc/vmware/ssl] /etc/init.d/vpxa start
vpxa is running

cron으로 이러한 작업을 자동으로 수행하게 만들기

서명된 인증서를 발급받는 과정부터 발급받은 인증서가 정상일 때 이를 적용하는 과정까지를 스크립트로 짜서 cron에 등록하면 된다. 아래의 스크립트는 이 스크립트를 처음으로 실행했을 때 기존의 인증서를 백업 해두는 기능과, 인증서 받아오기가 실패를 했다면 인증서 적용을 하지 않는 기능이 추가되어있다.5) 아래의 스크립트를 원하는 경로에 생성한다. 나의 경우는 ‘/etc/vmware/ssl/letsencrypt_renewal.sh’ 로 저장하였다.

#!/usr/bin/sh
/usr/bin/python /etc/vmware/ssl/acme-tiny/acme_tiny.py –account-key /etc/vmware/ssl/account.key –csr /etc/vmware/ssl/letsencrypt.csr –acme-dir /usr/lib/vmware/hostd/docroot/.well-known/acme-challenge > /etc/vmware/ssl/letsencrypt.crt
if [ -s “/etc/vmware/ssl/orig.rui.key” ]; then
else
cp -f /etc/vmware/ssl/rui.key /etc/vmware/ssl/orig.rui.key
cp -f /etc/vmware/ssl/rui.crt /etc/vmware/ssl/orig.rui.crt
fi
if [ -s “/etc/vmware/ssl/letsencrypt.crt” ]; then
cp -f /etc/vmware/ssl/letsencrypt.key /etc/vmware/ssl/rui.key
cp -f /etc/vmware/ssl/letsencrypt.crt /etc/vmware/ssl/rui.crt
/etc/init.d/hostd restart
/etc/init.d/vpxa restart
/etc/init.d/vpxa start
else
echo “letsencrypt.crt file is not correct”
fi

그리고 이 스크립트를 실행할 수 있게 cron에 등록해야한다. 하지만 ESXi에는 crontab이 없기 때문에 직접 cron 파일을 수정해야한다. 아래의 명령어는 /etc/vmware/ssl/letsencrypt_renewal.sh 라는 명령어를 매월 1일 0시 0분(UTC 기준이다)에 실행하고 실행하는 도중에 출력되는 것을 /etc/vmware/ssl/letsencrypt.log 에 저장한다는 내용이다.

#min  hour  day  mon  dow  command
0 0 1 * * /etc/vmware/ssl/letsencrypt_renewal.sh >> /etc/vmware/ssl/letsencrypt.log 2>&1

이를 cron에 적용하려면 아래와 같이 입력한다.

[root@esxi:/etc/vmware/ssl] echo ‘0 0 1 * *
/etc/vmware/ssl/letsencrypt_renewal.sh >> /etc/vmware/ssl/letsencrypt.log 2>&1′ >> /var/spool/cron/crontabs/root

여기서 쓰기 금지가 걸려서 ‘/var/spool/cron/crontabs/root’ 파일을 수정할 수 없다면 cron 파일의 내용물을 다른곳에 복사해두고 파일을 지운 다음 새 파일을 만든 후 기존 내용을 복구하면 된다.6)

그리고 cron 서비스를 재시작 하여준다.

[root@esxi:/etc/vmware/ssl] /bin/kill $(cat /var/run/crond.pid)
[root@esxi:/etc/vmware/ssl] /usr/lib/vmware/busybox/bin/busybox crond

현 상태에서는 설정이 잘 되었지만, ESXi는 부팅시에 cron을 수정한다. ESXi가 부팅될 때 cron에 방금 추가한 내용이 자동으로 추가되게 하려면 ‘/etc/rc.local.d/local.sh’에 cron을 수정하는 내용을 등록해두어야 한다.7)

‘/etc/rc.local.d/local.sh’를 본인이 주로 사용하는 에디터로 열어서 아래와 같이 수정한다. ‘exit 0’ 이전 줄에 위에서 입력햇던 내용을 (약간 변형하여) 입력하면 된다. 수정하고 저장한다.

#!/bin/sh

# local configuration options

# Note: modify at your own risk! If you do/use anything in this
# script that is not part of a stable API (relying on files to be in
# specific places, specific tools, specific output, etc) there is a
# possibility you will end up with a broken system after patching or
# upgrading. Changes are not supported unless under direction of
# VMware support.

# Note: This script will not be run when UEFI secure boot is enabled.

/bin/kill $(cat /var/run/crond.pid) # Gets the cron service pid and simply kills it.
/bin/echo ‘0 0 1 * * /etc/vmware/ssl/letsencrypt_renewal.sh >> /etc/vmware/ssl/letsencrypt.log 2>&1’ >> /var/spool/cron/crontabs/root
/usr/lib/vmware/busybox/bin/busybox crond
exit 0

이제 1개월마다 자동으로 ESXi에서 사용되는 인증서를 갱신할 것이다.

Footnote

  1. https://wiki.9r.com.au/display/9R/LetsEncrypt+Certificates+for+vCenter+and+PSC
  2. http://multifrontgarden.tistory.com/219
  3. https://www.lesstif.com/pages/viewpage.action?pageId=6979614
  4. https://kb.vmware.com/s/article/1003490
  5. http://foris.tistory.com/256 shell
  6. https://communities.vmware.com/thread/332790
  7. https://www.gotelsolutions.com/billing/ext.php?m=faq&h=public&i=1&hash=4a6e4ae063deaf91be0a772897fedcd9&&faq_product_id=

 

Advertisements

답글 남기기

아래 항목을 채우거나 오른쪽 아이콘 중 하나를 클릭하여 로그 인 하세요:

WordPress.com 로고

WordPress.com의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Google+ photo

Google+의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Twitter 사진

Twitter의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Facebook 사진

Facebook의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

%s에 연결하는 중