第4章 証明書と鍵のローテーション
システム管理者は、Red Hat OpenShift 上で実行されている Red Hat Trusted Artifact Signer (RHTAS) サービスで使用される証明書と署名者鍵をプロアクティブにローテーションできます。定期的に鍵をローテーションすることで、鍵の改ざんや盗難を防ぐことができます。これらの手順では、古い証明書と署名者鍵を期限切れにし、RHTAS を設定する基盤となるサービス用の新しい証明書と署名者鍵に置き換える手順を説明します。次のサービスの鍵と証明書をローテーションできます。
- Rekor
- Certificate Transparency ログ
- Fulcio
- タイムスタンプ機関
4.1. Rekor 署名者鍵のローテーション
シャーディング機能を使用してログツリーをフリーズし、新しい署名者鍵を使用して新しいログツリーを作成することで、Rekor の署名者鍵を積極的にローテーションできます。この手順では、古い Rekor 署名者鍵を期限切れにし、Red Hat Trusted Artifact Signer (RHTAS) が使用する新しい署名者鍵に置き換える手順を説明します。古い Rekor 署名者鍵の有効期限が切れても、古い鍵で署名されたアーティファクトを検証することは可能です。
この手順では、Rekor サービスを停止する必要があります。
前提条件
- Red Hat OpenShift Container Platform 上で実行される RHTAS Operator をインストールする。
- Securesign インスタンスを実行する。
-
oc
、openssl
、cosign
バイナリーがインストールされたワークステーション。
手順
OpenShift クラスターからワークステーションに
tuftool
バイナリーをダウンロードします。重要tuftool
バイナリーは Linux オペレーティングシステムでのみ使用できます。- ホームページから ? アイコンをクリックして、Command line tools をクリックし、tuftool ダウンロードセクションに移動し、プラットフォームのリンクをクリックします。
ワークステーションでターミナルから、バイナリー
.gz
ファイルを展開し、実行ビットを設定します。例
$ gunzip tuftool-amd64.gz $ chmod +x tuftool-amd64
バイナリーを
$PATH
環境内の場所に移動し、名前を変更します。例
$ sudo mv tuftool-amd64 /usr/local/bin/tuftool
コマンドラインから OpenShift にログインします。
構文
oc login --token=TOKEN --server=SERVER_URL_AND_PORT
例
$ oc login --token=sha256~ZvFDBvoIYAbVECixS4-WmkN4RfnNd8Neh3y1WuiFPXC --server=https://example.com:6443
注記OpenShift Web コンソールからコマンドラインで使用するログイントークンと URL を確認できます。OpenShift Web コンソールにログインします。ユーザー名をクリックし、Copy login command をクリックします。入力を求められた場合はユーザー名とパスワードをもう一度入力し、Display Token をクリックしてコマンドを表示します。
RHTAS プロジェクトに切り替えます。
例
$ oc project trusted-artifact-signer
Rekor URL を取得します。
例
$ export REKOR_URL=$(oc get rekor -o jsonpath='{.items[0].status.url}')
アクティブシャードのログツリー識別子を取得します。
例
$ export OLD_TREE_ID=$(rekor-cli loginfo --rekor_server $REKOR_URL --format json | jq -r .TreeID)
Rekor インスタンスをスケールダウンし、ログツリーを
DRAINING
状態に設定します。例
$ oc run --image registry.redhat.io/rhtas/updatetree-rhel9:1.1.0 --restart=Never --attach=true --rm=true -q -- updatetree --admin_server=trillian-logserver:8091 --tree_id=${OLD_TREE_ID} --tree_state=DRAINING
ツリーログは、ドレイン中に新しいエントリーを受け入れません。キューが空になるまで待ちます。
重要次のステップに進む前に、キューが空になるまで待つ必要があります。ドレイン中にリーフがまだ統合中の場合、このプロセス中にログツリーをフリーズすると、ログパスが最大マージ遅延 (MMD) を超える可能性があります。
ログツリーをフリーズします。
例
$ oc run --image registry.redhat.io/rhtas/updatetree-rhel9:1.1.0 --restart=Never --attach=true --rm=true -q -- updatetree --admin_server=trillian-logserver:8091 --tree_id=${OLD_TREE_ID} --tree_state=FROZEN
フリーズしたログツリーの長さを取得します。
例
$ export OLD_SHARD_LENGTH=$(rekor-cli loginfo --rekor_server $REKOR_URL --format json | jq -r .ActiveTreeSize)
古いシャードの Rekor の公開鍵を取得します。
例
$ export OLD_PUBLIC_KEY=$(curl -s $REKOR_URL/api/v1/log/publicKey | base64 | tr -d '\n')
新しいログツリーを作成します。
例
$ export NEW_TREE_ID=$(oc run createtree --image registry.redhat.io/rhtas/createtree-rhel9:1.1.0 --restart=Never --attach=true --rm=true -q -- -logtostderr=false --admin_server=trillian-logserver:8091 --display_name=rekor-tree)
これで、ログツリーが 2 つ、フリーズしたツリーが 1 つ、およびアクティブなシャードになる新しいツリーが 1 つできました。
新しい秘密鍵を作成します。
例
$ openssl ecparam -genkey -name secp384r1 -noout -out new-rekor.pem
重要新しい鍵には一意のファイル名が必要です。
新しい署名者鍵を使用して新しいシークレットリソースを作成します。
例
$ oc create secret generic rekor-signer-key --from-file=private=new-rekor.pem
新しいツリー識別子と古いシャーディング情報を使用して、Securesign Rekor 設定を更新します。
例
$ read -r -d '' SECURESIGN_PATCH_1 <<EOF [ { "op": "replace", "path": "/spec/rekor/treeID", "value": $NEW_TREE_ID }, { "op": "add", "path": "/spec/rekor/sharding/-", "value": { "treeID": $OLD_TREE_ID, "treeLength": $OLD_SHARD_LENGTH, "encodedPublicKey": "$OLD_PUBLIC_KEY" } }, { "op": "replace", "path": "/spec/rekor/signer/keyRef", "value": {"name": "rekor-signer-key", "key": "private"} } ] EOF
注記/spec/rekor/signer/keyPasswordRef
に値が設定されている場合は、それを削除する新しい個別の更新を作成します。例
$ read -r -d '' SECURESIGN_PATCH_2 <<EOF [ { "op": "remove", "path": "/spec/rekor/signer/keyPasswordRef" } ] EOF
最初の更新を適用した後、この更新を適用します。
Securesign インスタンスを更新します。
例
$ oc patch Securesign securesign-sample --type='json' -p="$SECURESIGN_PATCH_1"
Rekor サーバーが新しい署名者鍵で再デプロイされるのを待ちます。
例
$ oc wait pod -l app.kubernetes.io/name=rekor-server --for=condition=Ready
新しい公開鍵を取得します。
例
$ export NEW_KEY_NAME=new-rekor.pub $ curl $(oc get rekor -o jsonpath='{.items[0].status.url}')/api/v1/log/publicKey -o $NEW_KEY_NAME
新しい Rekor 公開鍵を使用するように The Update Framework (TUF) サービスを設定します。
シェル環境を設定します。
例
$ export WORK="${HOME}/trustroot-example" $ export ROOT="${WORK}/root/root.json" $ export KEYDIR="${WORK}/keys" $ export INPUT="${WORK}/input" $ export TUF_REPO="${WORK}/tuf-repo" $ export TUF_SERVER_POD="$(oc get pod --selector=app.kubernetes.io/component=tuf --no-headers -o custom-columns=":metadata.name")"
一時的な TUF ディレクトリー構造を作成します。
例
$ mkdir -p "${WORK}/root/" "${KEYDIR}" "${INPUT}" "${TUF_REPO}"
TUF コンテンツを一時的な TUF ディレクトリー構造にダウンロードします。
例
$ oc extract --to "${KEYDIR}/" secret/tuf-root-keys $ oc cp "${TUF_SERVER_POD}:/var/www/html" "${TUF_REPO}" $ cp "${TUF_REPO}/root.json" "${ROOT}"
アクティブな Rekor 署名者鍵ファイル名を見つけます。ローカル TUF リポジトリー内の最新のターゲットファイル (例:
1.target.json
) を開きます。このファイルには、アクティブな Rekor 署名者鍵ファイル名 (例:rekor.pub)
が記載されています。次のアクティブな Rekor 署名者鍵ファイル名で環境変数を設定します。例
$ export ACTIVE_KEY_NAME=rekor.pub
古い公開鍵を使用して Rekor 署名者鍵を更新します。
例
$ echo $OLD_PUBLIC_KEY | base64 -d > $ACTIVE_KEY_NAME
古い Rekor 署名者鍵を期限切れにします。
例
$ tuftool rhtas \ --root "${ROOT}" \ --key "${KEYDIR}/snapshot.pem" \ --key "${KEYDIR}/targets.pem" \ --key "${KEYDIR}/timestamp.pem" \ --set-rekor-target "${ACTIVE_KEY_NAME}" \ --rekor-uri "https://rekor.rhtas" \ --rekor-status "Expired" \ --outdir "${TUF_REPO}" \ --metadata-url "file://${TUF_REPO}"
新しい Rekor 署名者鍵を追加します。
例
$ tuftool rhtas \ --root "${ROOT}" \ --key "${KEYDIR}/snapshot.pem" \ --key "${KEYDIR}/targets.pem" \ --key "${KEYDIR}/timestamp.pem" \ --set-rekor-target "${NEW_KEY_NAME}" \ --rekor-uri "https://rekor.rhtas" \ --outdir "${TUF_REPO}" \ --metadata-url "file://${TUF_REPO}"
これらの変更を TUF サーバーにアップロードします。
例
$ oc rsync "${TUF_REPO}/" "${TUF_SERVER_POD}:/var/www/html"
作業ディレクトリーを削除します。
例
$ rm -r $WORK
更新された TUF 設定で
cosign
設定を更新します。例
$ cosign initialize --mirror=$TUF_URL --root=$TUF_URL/root.json
これで、新しい Rekor 署名者鍵を使用してアーティファクトに署名し、検証する準備が整いました。