FortiGateでDNS-01なLet's Encryptの証明書を使う


FortiGate では一部の古い OS を除き、管理画面などに利用する SSL 証明書を簡単に Let’s Encrypt で発行出来る。

設定したいだけであれば上記の画面からポチポチと設定すれば良いが、 HTTP-01 チャレンジを利用したくない場合もある。

FortiGate には REST API が用意されているので、それを利用して適当な環境から証明書を生成して、インポートすることで対応が出来る。

ステップとしては以下。

  1. certbot で DNS-01 チャレンジを利用して証明書をリクエストする
  2. openssl コマンドを利用して、 PKCS12 形式に変換する
  3. ペイロードを組み立て、 FortiGate にリクエストを送信する

具体的なスクリプトは以下になる。 ForiGate の API キーの発行に関してはググれば出てくるのでそれを参考に作る。

#!/bin/sh
set -ex

sudo certbot certonly \
  --agree-tos \
  -m [email protected] \
  --rsa-key-size=4096 \
  --key-type rsa \
  --dns-cloudflare \
  --dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \
  --dns-cloudflare-propagation-seconds 60 \
  -d router.example.ne.jp

sudo openssl pkcs12 \
  -export \
  -in /etc/letsencrypt/live/router.example.ne.jp/fullchain.pem \
  -inkey /etc/letsencrypt/live/router.example.ne.jp/privkey.pem \
  -out cert.pfx \
  -passout pass:

KEY=$(sudo base64 -w 0 cert.pfx)
PAYLOAD=$(printf '{"type": "pkcs12","certname": "router.example.ne.jp","password": "","file_content": "%s","scope": "global"}' $KEY)

curl -k \
  -H "Content-Type:application/json" \
  -H "Authorization: Bearer [API KEY]" \
  -d "$PAYLOAD" \
 'https://10.0.0.254/api/v2/monitor/vpn-certificate/local/import'

sudo rm cert.pfx

なお、機種により微妙に認証方法が異なった。

検証に利用したのは FortiGate 50E と 60F を利用したが、 50E の場合は認証が Bearer Token ではなく、以下のようにクエリパラメータでキーを指定する必要がある。

curl -k \
  -H "Content-Type:application/json" \
  -d "$PAYLOAD" \
 'https://10.0.0.254/api/v2/monitor/vpn-certificate/local/import?access_token=[API KEY]'

インポートが出来たら、 [System] -> [Settings] -> [HTTPS server certificate] から該当の証明書を選んで保存。

FortiGate の FQDN にアクセスして、指定した証明書が利用されていれば成功。簡単だったね。


comments powered by Disqus