GitHub Enterprise Serverの証明書をAPIで設定する

2021/05/13に公開

はじめに

GitHub Enterprise Server の証明書を Management Console API で更新する方法のメモです。
(ドキュメントのリンクは GitHub Enterpise Server 3.0 のものとしています)。

Let's Encryptのサポートについて に書かれているように GitHub Enterprise Server 3.0 は Let's Encrypt の HTTP-01 チャレンジはサポートしていますが、 DNS-01 チャレンジはサポートしていません。

GitHub Enterprise Server をインターネットからアクセスできない場所で稼働している場合は HTTP-01 チャレンジは使えず DNS-01 チャレンジを使うことになります。

go-acme/lego: Let's Encrypt client and ACME library written in Go などで発行した証明書を GitHub Enterprise Server に反映するのに Management Console API が使用できるとサポートの方から教えて頂きました。

2021-05-12 時点では証明書設定 Set settings など Management Console API の curl のサンプルが紛らわしいですが、正しくは application/x-www-form-urlencoded 形式でボディを設定し、パスは /api/v3 が無いものを指定する必要があります。ドキュメントチームに依頼されたとのことなので今後改善されると思います。

2021-07-07 追記。その後証明書設定 Set settings のドキュメントが --data-urlencode を使うように更新されていました。また GitHub Enterprise Server 3.1 の Set settings ではパスも /api/v3 無しになっていました。

Management Conosle API の認証

認証 に説明されています。

この記事のスクリプトでは Basic 認証を使っています。

使用するAPI

Set settings で証明書と鍵を設定し、Start a configuration process で設定プロセスを開始(管理コンソールの Save Settings ボタンに相当)し、Get the configuration status で設定プロセスの状態を繰り返し確認してプロセスが終了するまで待ちます。

証明書を設定するスクリプト

下記のスクリプト github_es_set.cert.sh 内の ghes_host, cert_path, key_path の値を環境に応じて適宜変更します。

#!/bin/sh
# github_es_set_cert.sh
# Set SSL certificate and key to GitHub Enterprise Server

# Modify following variables below for your environment.
ghes_host=ghes.example.jp
cert_path=/etc/letsencrypt/certificates/_.ghes.example.jp.crt
key_path=/etc/letsencrypt/certificates/_.ghes.example.jp.key

ghes_mgmt_port=8443
ghes_origin=https://$ghes_host:$ghes_mgmt_port
config_path=/tmp/ghes_set_cert.config.$$.json

if [ -z "$MGMT_PASSWORD" ]; then
  echo "Please set MGMT_PASSWORD environment vairable." 1>&2
  exit 2
fi

# Create settings value json file
printf '{"enterprise":{"github_ssl":{"enabled":true,"cert":%s,"key":%s}}}' \
  "$(jq --raw-input --slurp '. |= tostring' $cert_path)" \
  "$(jq --raw-input --slurp '. |= tostring' $key_path)" \
  > $config_path
trap "rm $config_path" EXIT

# Set settings
status=$(curl -sSi -X PUT -u "api_key:$MGMT_PASSWORD" \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -H 'Accept: application/vnd.github.v3+json' \
  --data-urlencode settings@$config_path \
  $ghes_origin/setup/api/settings \
  | grep ^Status: | awk '{print $2}')
if [ x$status != x204 ]; then
  echo "Unexpected status: $status for setting certificate." 1>&2
  exit 2
fi
echo $(date +%Y-%m-%dT%H:%M:%S) set settings for certificate

# Start a configuration process
status=$(curl -sSi -X POST -u "api_key:$MGMT_PASSWORD" \
  -H 'Accept: application/vnd.github.v3+json' \
  $ghes_origin/setup/api/configure \
  | grep ^Status: | awk '{print $2}')
if [ x$status != x202 ]; then
  echo "Unexpected status: $status for starting a configuration process." 1>&2
  exit 2
fi
echo $(date +%Y-%m-%dT%H:%M:%S) started a configuration process

# Wait for the configuration process to finish
while :; do
  status=$(curl -sS -u "api_key:$MGMT_PASSWORD" \
    -H 'Accept: application/vnd.github.v3+json' \
    $ghes_origin/setup/api/configcheck \
    | jq -r .status)
  echo $(date +%Y-%m-%dT%H:%M:%S) $status
  if [ _$status = _success ]; then break; fi
  sleep 60
done

# Print the start and expiry dates of the certificate set in the server.
echo | openssl s_client -connect $ghes_host:$ghes_mgmt_port 2> /dev/null \
  | openssl x509 -noout -dates

証明書を設定するスクリプトの実行手順

以下のように Management Console のパスワード を環境変数に設定しておきます。

export MGMT_PASSWORD=マネージメントコンソールのパスワード

あとはスクリプトを実行するだけです。

./github_es_set_cert.sh

実行例は以下のとおりです。最後にサーバーに設定された証明書の有効期限を出力しています。

$ ./github_es_set_cert.sh
2021-05-13T19:01:35 set settings for certificate
2021-05-13T19:01:36 started a configuration process
2021-05-13T19:01:36 running
2021-05-13T19:02:37 running
2021-05-13T19:03:37 running
2021-05-13T19:04:38 running
2021-05-13T19:05:38 running
2021-05-13T19:06:39 running
2021-05-13T19:07:39 running
2021-05-13T19:08:40 success
notBefore=May 11 09:04:30 2021 GMT
notAfter=Aug  9 09:04:30 2021 GMT

Discussion