🐙

GCPでIP制限しているVMインスタンスのSSL証明書自動更新

2022/07/24に公開

前提

  • Dockerを使用してアプリ構築している
  • docker、docker-composeコマンドが使用できる
  • すでにLet's Encryptから証明書を発行している
  • OS:Ubuntu20.04LTS

仕組み

IP制限をしていると、証明書を更新できないので更新する前に80番ポートからの通信を許可するファイヤーウォールを作成し、VMインスタンスに割り当てる。更新が終わったらファイヤーウォールを削除するようにする。

手順

VMインスタンス側の設定

  • Google Cloud コンソール画面> Compute Engine> VMインスタンス>設定するVMインスタンスの編集画面を開く
  • ネットワークタグに任意のタグを登録する
    • http通信を一時的にアクセスするために使用するので、このタグをターゲットタグとしたファイヤーウォールは作成しない
  • アクセススコープで「すべてのCloud APIに完全アクセス権を許可」にチェックをつける
  • 保存ボタンを押下して設定を保存する

VMインスタンス内でgcloudコマンドを使用できるようにする

  • Google Cloud コンソール画面> Compute Engine> VMインスタンス>設定するVMインスタンスのSSHを押下してVMインスタンス内に入る
  • インスタンス内で以下のコマンド実行
sudo gcloud init
  • 以下のようなログが出てきたら1を押下
Your current configuration has been set to: [default]

You can skip diagnostics next time by using the following flag:
  gcloud init --skip-diagnostics

Network diagnostic detects and fixes local network connection issues.
Checking network connection...done.                                                                                                                        
Reachability Check passed.
Network diagnostic passed (1/1 checks passed).

Choose the account you would like to use to perform operations for this configuration:
 [1] XXXXXXXXXXX-compute@developer.gserviceaccount.com
 [2] Log in with a new account
  • Cloud resource manager APIをGCPのプロジェクトで有効にしていない場合は以下のように有効にするか質問されるが、今回は使用しなくてもよいのでNを押下
API [cloudresourcemanager.googleapis.com] not enabled on project [XXXXXXXXXXX]. Would you like to enable and 
retry (this will take a few minutes)? (y/N)?  
  • 以下のようなWarningが出てくるが今回の作業には支障ない
WARNING: Listing available projects failed: PERMISSION_DENIED: Cloud Resource Manager API has not been used in project XXXXXXXXXXX before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/cloudresourcemanager.googleapis.com/overview?project=XXXXXXXXXXX then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.
- '@type': type.googleapis.com/google.rpc.Help
  links:
  - description: Google developers console API activation
    url: https://console.developers.google.com/apis/api/cloudresourcemanager.googleapis.com/overview?project=XXXXXXXXXXX
- '@type': type.googleapis.com/google.rpc.ErrorInfo
  domain: googleapis.com
  metadata:
    consumer: projects/XXXXXXXXXXX
    service: cloudresourcemanager.googleapis.com
  reason: SERVICE_DISABLED
  • プロジェクトIDを入力するように求められるので入力する
  • 以下の質問が聞かれたらYを押下
Do you want to configure a default Compute Region and Zone? (Y/n)?  
  • RegionとZoneの一覧が表示されるので任意のものを選択
  • 以下のコマンドを実行してエラーにならなければgcloudコマンドの初期設定完了
gcloud compute firewall-rules list

cronファイルを作成する

  • cronに登録する用のファイルを作成する(ファイル名は任意だが、拡張子は不要)
  • firewallnameは任意のファイヤーウォール名にする
  • --target-tags=tagnameのtagnameの部分はVMインスタンスに登録したネットワークタグ名と合わせる
  • cd /docker/app/は環境に合わせてdocker-compose.ymlファイルがある場所に変更する
  • /snap/bin/gcloudwhich cloudをVMインスタンス内で実行して、gcloudコマンドのパスを調べて、それに合わせて変更する
    • ユーザーがgcloudコマンドを実行する際にはコマンドのパスは不要だが、cronから実行する場合はパスがないとnot foundエラーになる
cronファイル
#!/bin/sh

{
    echo "---- start renew-cert $(date '+%Y-%m-%d %H:%M:%S')"

    /snap/bin/gcloud compute firewall-rules create firewallname --direction=INGRESS \
  --action=ALLOW --rules=tcp:80 --source-ranges=0.0.0.0/0 \
  --target-tags=tagname

    cd /docker/app/ || exit 1

    gjdipuzmwd=$(docker-compose run --rm certbot renew --verbose --post-hook='echo gjdipuzmwd' 2>&1)

    echo "${gjdipuzmwd}"

    if echo "${gjdipuzmwd}" | grep -q "gjdipuzmwd"; then
        docker-compose exec -T proxyserver nginx -s reload
    fi


    /snap/bin/gcloud compute firewall-rules delete certbot --quiet
} > /var/log/renew-cert.log 2>&1
  • ファイルをVMインスタンス内の/etc/cron.weekly/に配置
  • 以下のコマンドを実行してファイルに実行権限を付ける
chmod 755 /etc/cron.weekly/ファイル名
  • /etc/crontabに記載されている実行タイミングで定期実行されるようになる

参考

Discussion