3 ヶ月前に Let’s Encrypt の証明書の更新を依存関係の多い certbot から dehydrated に移行した時に、アカウントも移行したので、その手順を残しておきます。

確認環境

  • Ubuntu 18.04.2 LTS (bionic)
  • letsencrypt-auto (certbot-auto) 0.35.1
  • dehydrated 0.6.1-2

移行元のアカウント

/etc/letsencrypt/accounts/accounts/acme-v01.api.letsencrypt.org/directory/ハッシュ値(?) の中に private_key.json, regr.json, meta.json があります。 秘密鍵などがあるので、ほとんどのところを伏せていますが、内容の構造は以下のような感じです。

  % sudo jq . accounts/acme-staging.api.letsencrypt.org/directory/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/private_key.json
  {
    "e": "AQAB",
    "d": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    "n": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    "q": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    "p": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    "kty": "RSA",
    "qi": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    "dp": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    "dq": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  }
  % sudo jq . accounts/acme-staging.api.letsencrypt.org/directory/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/regr.json
  {
    "body": {
      "contact": [
        "mailto:root@example.com"
      ],
      "agreement": "https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf",
      "key": {
        "e": "AQAB",
        "kty": "RSA",
        "n": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
      }
    },
    "uri": "https://acme-staging.api.letsencrypt.org/acme/reg/142119",
    "new_authzr_uri": "https://acme-staging.api.letsencrypt.org/acme/new-authz",
    "terms_of_service": "https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf"
  }
  % sudo jq . accounts/acme-staging.api.letsencrypt.org/directory/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/meta.json
  {
    "creation_host": "host.example.jp",
    "creation_dt": "2016-03-06T06:36:36Z"
  }

dehydrated の accounts ディレクトリ作成

/var/lib/dehydrated/accounts/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX が作成されます。 ディレクトリ名のハッシュ値のような部分は伏字にしています。

  % dehydrated --env
  # dehydrated configuration
  # INFO: Using main config file /etc/dehydrated/config
  mkdir: ディレクトリ `/var/lib/dehydrated/accounts' を作成できません: 許可がありません
  zsh: exit 1     dehydrated --env
  % sudo dehydrated --env
  # dehydrated configuration
  # INFO: Using main config file /etc/dehydrated/config
  declare -- CA="https://acme-v02.api.letsencrypt.org/directory"
  declare -- CERTDIR="/var/lib/dehydrated/certs"
  declare -- CHALLENGETYPE="http-01"
  declare -- DOMAINS_D=""
  declare -- DOMAINS_TXT="/etc/dehydrated/domains.txt"
  declare -- HOOK=""
  declare -- HOOK_CHAIN="no"
  declare -- RENEW_DAYS="30"
  declare -- ACCOUNT_KEY="/var/lib/dehydrated/accounts/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/account_key.pem"
  declare -- ACCOUNT_KEY_JSON="/var/lib/dehydrated/accounts/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/registration_info.json"
  declare -- KEYSIZE="4096"
  declare -- WELLKNOWN="/var/lib/dehydrated/acme-challenges"
  declare -- PRIVATE_KEY_RENEW="yes"
  declare -- OPENSSL_CNF="/usr/lib/ssl/openssl.cnf"
  declare -- CONTACT_EMAIL=""
  declare -- LOCKFILE="/var/lib/dehydrated/lock"

インポート失敗

Import account key にある Perl スクリプトは必要なモジュールが入っていなかったので、以下のように動きませんでした。

  Can't locate File/Slurp.pm in @INC (you may need to install the File::Slurp module) (@INC contains: /etc/perl /usr/local/lib/x86_64-linux-gnu/perl/5.26.1 /usr/local/share/perl/5.26.1 /usr/lib/x86_64-linux-gnu/perl5/5.26 /usr/share/perl5 /usr/lib/x86_64-linux-gnu/perl/5.26 /usr/share/perl/5.26 /usr/local/lib/site_perl /usr/lib/x86_64-linux-gnu/perl-base) at /tmp/import-account-key.pl line 8.
  BEGIN failed--compilation aborted at /tmp/import-account-key.pl line 8.

ruby で変換

以下のスクリプトを private_key.json の場所で実行するか、 File.read している部分を書き換えて変換します。

試してから時間がたってしまって、具体的なバージョンをメモしていなくて確認できないのですが、 ruby が古すぎると Ruby/OpenSSL が古くてメソッド不足でエラーになった覚えがあるので、 その場合は private_key.json から account_key.pem への変換だけ新しい ruby が入っている環境を使ってみてください。

  require 'json'
  require 'openssl'
  require 'base64'

  json_content = File.read('private_key.json')
  json_content.tr!('-_', '+/')
  json = JSON.parse(json_content)
  rsa = OpenSSL::PKey::RSA.new
  # 2 is from binary
  n = OpenSSL::BN.new(Base64.decode64(json['n']), 2)
  e = OpenSSL::BN.new(Base64.decode64(json['e']), 2)
  d = OpenSSL::BN.new(Base64.decode64(json['d']), 2)
  p = OpenSSL::BN.new(Base64.decode64(json['p']), 2)
  q = OpenSSL::BN.new(Base64.decode64(json['q']), 2)
  qi = OpenSSL::BN.new(Base64.decode64(json['qi']), 2)
  dp = OpenSSL::BN.new(Base64.decode64(json['dp']), 2)
  dq = OpenSSL::BN.new(Base64.decode64(json['dq']), 2)
  rsa.set_factors(p, q)
  rsa.set_key(n, e, d)
  rsa.set_crt_params(dp, dq, qi)
  puts rsa.to_pem

表示された pem を /var/lib/dehydrated/accounts/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/account_key.pem に書き込んでパーミッションを 600 にして移行完了です。

動作確認

dehydrated --cron --domain foo.example.jp --hook /etc/dehydrated/hook.sh --challenge dns-01 などの普通の実行方法で更新されることを確認します。

accounts ディレクトリの中に /var/lib/dehydrated/accounts/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/registration_info.pem が自動で作成されていました。

まとめ

certbot から dehydrated に移行した時にアカウントも移行したのに、 移行方法を公開し忘れていたので公開しました。

Disqus Comments

Kazuhiro NISHIYAMA

Ruby のコミッターとかやってます。 フルスタックエンジニア(って何?)かもしれません。 About znzに主なアカウントをまとめました。

znz znz


Published