此内容没有您所选择的语言版本。
Chapter 4. Rotate your certificates and keys
As a systems administrator, you can proactively rotate the certificates and signer keys used by the Red Hat Trusted Artifact Signer (RHTAS) service running on Red Hat OpenShift. Rotating your keys regularly can prevent key tampering, and theft. These procedures guide you through expiring your old certificates and signer keys, and replacing them with a new certificate and signer key for the underlying services that make up RHTAS. You can rotate keys and certificates for the following services:
- Rekor
- Certificate Transparency log
- Fulcio
- Timestamp Authority
4.1. Rotating the Rekor signer key 复制链接链接已复制到粘贴板!
You can proactively rotate Rekor’s signer key by using the sharding feature to freeze the log tree, and create a new log tree with a new signer key. This procedure walks you through expiring your old Rekor signer key, and replacing it with a new signer key for Red Hat Trusted Artifact Signer (RHTAS) to use. Expiring your old Rekor signer key still allows you to verify artifacts signed by the old key.
This procedure requires downtime to the Rekor service.
Prerequisites
- Installation of the RHTAS operator running on Red Hat OpenShift Container Platform.
- A running Securesign instance.
-
A workstation with the
oc,openssl, andcosignbinaries installed.
Procedure
Download the
rekor-clibinary from the OpenShift cluster to your workstation.- Login to the OpenShift web console. From the home page, click the ? icon, click Command line tools, go to the rekor-cli download section, and click the link for your platform.
Open a terminal on your workstation, decompress the binary
.gzfile, and set the execute bit:Example
$ gunzip rekor-cli-amd64.gz $ chmod +x rekor-cli-amd64Move and rename the binary to a location within your
$PATHenvironment:Example
$ sudo mv rekor-cli-amd64 /usr/local/bin/rekor-cli
Download the
tuftoolbinary from the OpenShift cluster to your workstation.ImportantThe
tuftoolbinary is only available for Linux operating systems.- From the home page, click the ? icon, click Command line tools, go to the tuftool download section, and click the link for your platform.
From a terminal on your workstation, decompress the binary
.gzfile, and set the execute bit:Example
$ gunzip tuftool-amd64.gz $ chmod +x tuftool-amd64Move and rename the binary to a location within your
$PATHenvironment:Example
$ sudo mv tuftool-amd64 /usr/local/bin/tuftool
Log in to OpenShift from the command line:
Syntax
oc login --token=TOKEN --server=SERVER_URL_AND_PORTExample
$ oc login --token=sha256~ZvFDBvoIYAbVECixS4-WmkN4RfnNd8Neh3y1WuiFPXC --server=https://example.com:6443NoteYou can find your login token and URL for use on the command line from the OpenShift web console. Log in to the OpenShift web console. Click your user name, and click Copy login command. Offer your user name and password again, if asked, and click Display Token to view the command.
Switch to the RHTAS project:
Example
$ oc project trusted-artifact-signerGet the Rekor URL:
Example
$ export REKOR_URL=$(oc get rekor -o jsonpath='{.items[0].status.url}')Get the log tree identifier for the active shard:
Example
$ export OLD_TREE_ID=$(rekor-cli loginfo --rekor_server $REKOR_URL --format json | jq -r .TreeID)Scale down the Rekor instance, and set the log tree to the
DRAININGstate:Example
$ 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=DRAININGWhile draining, the tree log will not accept any new entries. Watch and wait for the queue to empty.
ImportantYou must wait for the queues to be empty before proceeding to the next step. If leaves are still integrating while draining, then freezing the log tree during this process can cause the log path to exceed the maximum merge delay (MMD).
Freeze the log tree:
Example
$ 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=FROZENGet the length of the frozen log tree:
Example
$ export OLD_SHARD_LENGTH=$(rekor-cli loginfo --rekor_server $REKOR_URL --format json | jq -r .ActiveTreeSize)Get Rekor’s public key for the old shard:
Example
$ export OLD_PUBLIC_KEY=$(curl -s $REKOR_URL/api/v1/log/publicKey | base64 | tr -d '\n')Create a new log tree:
Example
$ 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)Now you have two log trees, one frozen tree, and a new tree that will become the active shard.
Create a new private key:
Example
$ openssl ecparam -genkey -name secp384r1 -noout -out new-rekor.pemImportantThe new key must have a unique file name.
Create a new secret resource with the new signer key:
Example
$ oc create secret generic rekor-signer-key --from-file=private=new-rekor.pemUpdate the Securesign Rekor configuration with the new tree identifier and the old sharding information:
Example
$ 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"} } ] EOFNoteIf you have
/spec/rekor/signer/keyPasswordRefset with a value, then create a new separate update to remove it:Example
$ read -r -d '' SECURESIGN_PATCH_2 <<EOF [ { "op": "remove", "path": "/spec/rekor/signer/keyPasswordRef" } ] EOFApply this update after applying the first update.
Update the Securesign instance:
Example
$ oc patch Securesign securesign-sample --type='json' -p="$SECURESIGN_PATCH_1"Wait for the Rekor server to redeploy with the new signer key:
Example
$ oc wait pod -l app.kubernetes.io/name=rekor-server --for=condition=ReadyGet the new public key:
Example
$ export NEW_KEY_NAME=new-rekor.pub $ curl $(oc get rekor -o jsonpath='{.items[0].status.url}')/api/v1/log/publicKey -o $NEW_KEY_NAMEConfigure The Update Framework (TUF) service to use the new Rekor public key.
Set up your shell environment:
Example
$ 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")"Create a temporary TUF directory structure:
Example
$ mkdir -p "${WORK}/root/" "${KEYDIR}" "${INPUT}" "${TUF_REPO}"Download the TUF contents to the temporary TUF directory structure:
Example
$ oc extract --to "${KEYDIR}/" secret/tuf-root-keys $ oc cp "${TUF_SERVER_POD}:/var/www/html" "${TUF_REPO}" $ cp "${TUF_REPO}/root.json" "${ROOT}"Find the active Rekor signer key file name. Open the latest target file, for example,
1.target.json, within the local TUF repository. In this file you will find the active Rekor signer key file name, for example,rekor.pub. Set an environment variable with this active Rekor signer key file name:Example
$ export ACTIVE_KEY_NAME=rekor.pubUpdate the Rekor signer key with the old public key:
Example
$ echo $OLD_PUBLIC_KEY | base64 -d > $ACTIVE_KEY_NAMEExpire the old Rekor signer key:
Example
$ 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}"Add the new Rekor signer key:
Example
$ 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}"Upload these changes to the TUF server:
Example
$ oc rsync "${TUF_REPO}/" "${TUF_SERVER_POD}:/var/www/html"Delete the working directory:
Example
$ rm -r $WORK
Update the
cosignconfiguration with the updated TUF configuration:Example
$ cosign initialize --mirror=$TUF_URL --root=$TUF_URL/root.jsonNow, you are ready to sign and verify your artifacts with the new Rekor signer key.
You can proactively rotate Certificate Transparency (CT) log signer key by using the sharding feature to freeze the log tree, and create a new log tree with a new signer key. This procedure walks you through expiring your old CT log signer key, and replacing it with a new signer key for Red Hat Trusted Artifact Signer (RHTAS) to use. Expiring your old CT log signer key still allows you to verify artifacts signed by the old key.
Prerequisites
- Installation of the RHTAS operator running on Red Hat OpenShift Container Platform.
- A running Securesign instance.
-
A workstation with the
oc,openssl, andcosignbinaries installed.
Procedure
Download the
tuftoolbinary from the OpenShift cluster to your workstation.ImportantThe
tuftoolbinary is only available for Linux operating systems.- From the home page, click the ? icon, click Command line tools, go to the tuftool download section, and click the link for your platform.
Open a terminal on your workstation, decompress the binary
.gzfile, and set the execute bit:Example
$ gunzip tuftool-amd64.gz $ chmod +x tuftool-amd64Move and rename the binary to a location within your
$PATHenvironment:Example
$ sudo mv tuftool-amd64 /usr/local/bin/tuftool
Log in to OpenShift from the command line:
Syntax
oc login --token=TOKEN --server=SERVER_URL_AND_PORTExample
$ oc login --token=sha256~ZvFDBvoIYAbVECixS4-WmkN4RfnNd8Neh3y1WuiFPXC --server=https://example.com:6443NoteYou can find your login token and URL for use on the command line from the OpenShift web console. Log in to the OpenShift web console. Click your user name, and click Copy login command. Offer your user name and password again, if asked, and click Display Token to view the command.
Switch to the RHTAS project:
Example
$ oc project trusted-artifact-signerMake a backup of the current CT log configuration, and keys:
Example
$ export SERVER_CONFIG_NAME=$(oc get ctlog -o jsonpath='{.items[0].status.serverConfigRef.name}') $ oc get secret $SERVER_CONFIG_NAME -o jsonpath="{.data.config}" | base64 --decode > config.txtpb $ oc get secret $SERVER_CONFIG_NAME -o jsonpath="{.data.fulcio-0}" | base64 --decode > fulcio-0.pem $ oc get secret $SERVER_CONFIG_NAME -o jsonpath="{.data.private}" | base64 --decode > private.pem $ oc get secret $SERVER_CONFIG_NAME -o jsonpath="{.data.public}" | base64 --decode > public.pemCapture the current tree identifier:
Example
$ export OLD_TREE_ID=$(oc get ctlog -o jsonpath='{.items[0].status.treeID}')Set the log tree to the
DRAININGstate:Example
$ 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=DRAININGWhile draining, the tree log will not accept any new entries. Watch and wait for the queue to empty.
ImportantYou must wait for the queues to be empty before proceeding to the next step. If leaves are still integrating while draining, then freezing the log tree during this process can cause the log path to exceed the maximum merge delay (MMD).
Once the queue has been fully drained, freeze the log:
Example
$ 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=FROZENCreate a new Merkle tree, and capture the new tree identifier:
Example
$ export NEW_TREE_ID=$(kubectl 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=ctlog-tree)Generate a new certificate, along with new public and private keys:
Example
$ openssl ecparam -genkey -name prime256v1 -noout -out new-ctlog.pem $ openssl ec -in new-ctlog.pem -pubout -out new-ctlog-public.pem $ openssl ec -in new-ctlog.pem -out new-ctlog.pass.pem -des3 -passout pass:"CHANGE_ME"Replace CHANGE_ME with a new password.
ImportantThe certificate and new keys must have unique file names.
Update the CT log configuration.
-
Open the
config.txtpbfile for editing. For the frozen log, add the
not_after_limitfield to the frozen log entry, rename the prefix value to a unique name, and replace the old path to the private key withctfe-keys/private-0:Example
... log_configs:{ # frozen log config:{ log_id:2066075212146181968 prefix:"trusted-artifact-signer-0" roots_pem_file:"/ctfe-keys/fulcio-0" private_key:{[type.googleapis.com/keyspb.PEMKeyFile]:{path:"/ctfe-keys/private-0" password:"Example123"}} public_key:{der:"0Y0\x13\x06\x07*\x86H\xce=\x02\x01\x06\x08*\x86H\xce=\x03\x01\x07\x03B\x00\x04)'.\xffUJ\xe2s)\xefR\x8a\xfcO\xdcewȶy\xa7\x9d<\x13\xb0\x1c\x99\x96\xe4'\xe3v\x07:\xc8I+\x08J\x9d\x8a\xed\x06\xe4\xaeI:q\x98\xf4\xbc<o4VD\x0cr\xf9\x9c\xecxT\x84"} not_after_limit:{seconds:1728056285 nanos:012111000} ext_key_usages:"CodeSigning" log_backend_name:"trillian" }NoteYou can get the current time value for seconds and nanoseconds, by running the following commands:
date +%s, anddate +%N.ImportantThe
not_after_limitfield defines the end of the timestamp range for the frozen log only. Certificates beyond this point in time are no longer accepted for inclusion in this log.-
Copy and paste the frozen log
configblock, appending it to the configuration file to create a new entry. Change the following lines in the new
configblock. Set thelog_idto the new tree identifier, change theprefixtotrusted-artifact-signer, change theprivate_keypath toctfe-keys/private, remove thepublic_keyline, and changenot_after_limittonot_after_startand set the timestamp range:Example
... log_configs:{ # frozen log ... # new active log config:{ log_id: NEW_TREE_ID prefix:"trusted-artifact-signer" roots_pem_file:"/ctfe-keys/fulcio-0" private_key:{[type.googleapis.com/keyspb.PEMKeyFile]:{path:"ctfe-keys/private" password:"CHANGE_ME"}} ext_key_usages:"CodeSigning" not_after_start:{seconds:1713201754 nanos:155663000} log_backend_name:"trillian" }Add the NEW_TREE_ID, and replace CHANGE_ME with the new private key password. The password here must match the password used for generating the new private and public keys.
ImportantThe
not_after_startfield defines the beginning of the timestamp range inclusively. This means the log will start accepting certificates at this point in time.
-
Open the
Create a new secret resource:
Example
$ oc create secret generic ctlog-config \ --from-file=config=config.txtpb \ --from-file=private=new-ctlog.pass.pem \ --from-file=public=new-ctlog-public.pem \ --from-file=fulcio-0=fulcio-0.pem \ --from-file=private-0=private.pem \ --from-file=public-0=public.pem \ --from-literal=password=CHANGE_MEReplace CHANGE_ME with the new private key password.
Configure The Update Framework (TUF) service to use the new CT log public key.
Set up your shell environment:
Example
$ 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")"Create a temporary TUF directory structure:
Example
$ mkdir -p "${WORK}/root/" "${KEYDIR}" "${INPUT}" "${TUF_REPO}"Download the TUF contents to the temporary TUF directory structure:
Example
$ oc extract --to "${KEYDIR}/" secret/tuf-root-keys $ oc cp "${TUF_SERVER_POD}:/var/www/html" "${TUF_REPO}" $ cp "${TUF_REPO}/root.json" "${ROOT}"Find the active CT log public key file name. Open the latest target file, for example,
1.targets.json, within the local TUF repository. In this target file you will find the active CT log public key file name, for example,ctfe.pub. Set an environment variable with this active CT log public key file name:Example
$ export ACTIVE_CTFE_NAME=ctfe.pubExtract the active CT log public key from OpenShift:
Example
$ oc get secret $(oc get ctlog securesign-sample -o jsonpath='{.status.publicKeyRef.name}') -o jsonpath='{.data.public}' | base64 -d > $ACTIVE_CTFE_NAMEExpire the old CT log signer key:
Example
$ tuftool rhtas \ --root "${ROOT}" \ --key "${KEYDIR}/snapshot.pem" \ --key "${KEYDIR}/targets.pem" \ --key "${KEYDIR}/timestamp.pem" \ --set-ctlog-target "$ACTIVE_CTFE_NAME" \ --ctlog-uri "https://ctlog.rhtas" \ --ctlog-status "Expired" \ --outdir "${TUF_REPO}" \ --metadata-url "file://${TUF_REPO}"Add the new CT log signer key:
Example
$ tuftool rhtas \ --root "${ROOT}" \ --key "${KEYDIR}/snapshot.pem" \ --key "${KEYDIR}/targets.pem" \ --key "${KEYDIR}/timestamp.pem" \ --set-ctlog-target "new-ctlog-public.pem" \ --ctlog-uri "https://ctlog.rhtas" \ --outdir "${TUF_REPO}" \ --metadata-url "file://${TUF_REPO}"Upload these changes to the TUF server:
Example
$ oc rsync "${TUF_REPO}/" "${TUF_SERVER_POD}:/var/www/html"Delete the working directory:
Example
$ rm -r $WORK
Update the Securesign CT log configuration with the new tree identifier:
Example
$ read -r -d '' SECURESIGN_PATCH <<EOF [ { "op": "replace", "path": "/spec/ctlog/serverConfigRef", "value": {"name": "ctlog-config"} }, { "op": "replace", "path": "/spec/ctlog/treeID", "value": $NEW_TREE_ID }, { "op": "replace", "path": "/spec/ctlog/privateKeyRef", "value": {"name": "ctlog-config", "key": "private"} }, { "op": "replace", "path": "/spec/ctlog/privateKeyPasswordRef", "value": {"name": "ctlog-config", "key": "password"} }, { "op": "replace", "path": "/spec/ctlog/publicKeyRef", "value": {"name": "ctlog-config", "key": "public"} } ] EOFPatch the Securesign instance:
Example
$ oc patch Securesign securesign-sample --type='json' -p="$SECURESIGN_PATCH"Wait for the CT log server to redeploy:
Example
$ oc wait pod -l app.kubernetes.io/name=ctlog --for=condition=ReadyUpdate the
cosignconfiguration with the updated TUF configuration:Example
$ cosign initialize --mirror=$TUF_URL --root=$TUF_URL/root.jsonNow, you are ready to sign and verify your artifacts with the new CT log signer key.
4.3. Rotating the Fulcio certificate 复制链接链接已复制到粘贴板!
You can proactively rotate the certificate used by the Fulcio service. This procedure walks you through expiring your old Fulcio certificate, and replacing it with a new certificate for Red Hat Trusted Artifact Signer (RHTAS) to use. Expiring your old Fulcio certificate still allows you to verify artifacts signed by the old certificate.
Prerequisites
- Installation of the RHTAS operator running on Red Hat OpenShift Container Platform.
- A running Securesign instance.
-
A workstation with the
oc,openssl, andcosignbinaries installed.
Procedure
Download the
tuftoolbinary from the OpenShift cluster to your workstation.ImportantThe
tuftoolbinary is only available for Linux operating systems.- From the home page, click the ? icon, click Command line tools, go to the tuftool download section, and click the link for your platform.
Open a terminal on your workstation, decompress the binary
.gzfile, and set the execute bit:Example
$ gunzip tuftool-amd64.gz $ chmod +x tuftool-amd64Move and rename the binary to a location within your
$PATHenvironment:Example
$ sudo mv tuftool-amd64 /usr/local/bin/tuftool
Log in to OpenShift from the command line:
Syntax
oc login --token=TOKEN --server=SERVER_URL_AND_PORTExample
$ oc login --token=sha256~ZvFDBvoIYAbVECixS4-WmkN4RfnNd8Neh3y1WuiFPXC --server=https://example.com:6443NoteYou can find your login token and URL for use on the command line from the OpenShift web console. Log in to the OpenShift web console. Click your user name, and click Copy login command. Offer your user name and password again, if asked, and click Display Token to view the command.
Switch to the RHTAS project:
Example
$ oc project trusted-artifact-signerGenerate a new certificate, along with new public and private keys:
Example
$ openssl ecparam -genkey -name prime256v1 -noout -out new-fulcio.pem $ openssl ec -in new-fulcio.pem -pubout -out new-fulcio-public.pem $ openssl ec -in new-fulcio.pem -out new-fulcio.pass.pem -des3 -passout pass:"CHANGE_ME" $ openssl req -new -x509 -key new-fulcio.pass.pem -out new-fulcio.cert.pemReplace CHANGE_ME with a new password.
ImportantThe certificate and new keys must have unique file names.
Create a new secret:
Example
$ oc create secret generic fulcio-config \ --from-file=private=new-fulcio.pass.pem \ --from-file=cert=new-fulcio.cert.pem \ --from-literal=password=CHANGE_MEReplace CHANGE_ME with a new password.
NoteThe password here must match the password used for generating the new private and public keys.
Configure The Update Framework (TUF) service to use the new Fulcio certificate.
Set up your shell environment:
Example
$ 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")"Create a temporary TUF directory structure:
Example
$ mkdir -p "${WORK}/root/" "${KEYDIR}" "${INPUT}" "${TUF_REPO}"Download the TUF contents to the temporary TUF directory structure:
Example
$ oc extract --to "${KEYDIR}/" secret/tuf-root-keys $ oc cp "${TUF_SERVER_POD}:/var/www/html" "${TUF_REPO}" $ cp "${TUF_REPO}/root.json" "${ROOT}"Find the active Fulcio certificate file name. Open the latest target file, for example,
1.targets.json, within the local TUF repository. In this file you will find the active Fulcio certificate file name, for example,fulcio_v1.crt.pem. Set an environment variable with this active Fulcio certificate file name:Example
$ export ACTIVE_CERT_NAME=fulcio_v1.crt.pemExtract the active Fulico certificate from OpenShift:
Example
$ oc get secret $(oc get fulcio securesign-sample -o jsonpath='{.status.certificate.caRef.name}') -o jsonpath='{.data.cert}' | base64 -d > $ACTIVE_CERT_NAMEExpire the old certificate:
Example
$ tuftool rhtas \ --root "${ROOT}" \ --key "${KEYDIR}/snapshot.pem" \ --key "${KEYDIR}/targets.pem" \ --key "${KEYDIR}/timestamp.pem" \ --set-fulcio-target "$ACTIVE_CERT_NAME" \ --fulcio-uri "https://fulcio.rhtas" \ --fulcio-status "Expired" \ --outdir "${TUF_REPO}" \ --metadata-url "file://${TUF_REPO}"Add the new Fulcio certificate:
Example
$ tuftool rhtas \ --root "${ROOT}" \ --key "${KEYDIR}/snapshot.pem" \ --key "${KEYDIR}/targets.pem" \ --key "${KEYDIR}/timestamp.pem" \ --set-fulcio-target "new-fulcio.cert.pem" \ --fulcio-uri "https://fulcio.rhtas" \ --outdir "${TUF_REPO}" \ --metadata-url "file://${TUF_REPO}"Upload these changes to the TUF server:
Example
$ oc rsync "${TUF_REPO}/" "${TUF_SERVER_POD}:/var/www/html"Delete the working directory:
Example
$ rm -r $WORK
Update the Securesign Fulcio configuration:
Example
$ read -r -d '' SECURESIGN_PATCH <<EOF [ { "op": "replace", "path": "/spec/fulcio/certificate/privateKeyRef", "value": {"name": "fulcio-config", "key": "private"} }, { "op": "replace", "path": "/spec/fulcio/certificate/privateKeyPasswordRef", "value": {"name": "fulcio-config", "key": "password"} }, { "op": "replace", "path": "/spec/fulcio/certificate/caRef", "value": {"name": "fulcio-config", "key": "cert"} }, { "op": "replace", "path": "/spec/ctlog/rootCertificates", "value": [{"name": "fulcio-config", "key": "cert"}] } ] EOFPatch the Securesign instance:
Example
$ oc patch Securesign securesign-sample --type='json' -p="$SECURESIGN_PATCH"Wait for the Fulcio server to redeploy:
Example
$ oc wait pod -l app.kubernetes.io/name=fulcio-server --for=condition=Ready $ oc wait pod -l app.kubernetes.io/name=ctlog --for=condition=ReadyUpdate the
cosignconfiguration with the updated TUF configuration:Example
$ cosign initialize --mirror=$TUF_URL --root=$TUF_URL/root.jsonNow, you are ready to sign and verify your artifacts with the new Fulcio certificate.
You can proactively rotate the Timestamp Authority (TSA) signer key and certificate chain. This procedure walks you through expiring your old TSA signer key and certificate chain, and replacing them with a new ones for Red Hat Trusted Artifact Signer (RHTAS) to use. Expiring your old TSA signer key and certificate chain still allows you to verify artifacts signed by the old key and certificate chain.
Prerequisites
- Installation of the RHTAS operator running on Red Hat OpenShift Container Platform.
- A running Securesign instance.
-
A workstation with the
ocandopensslbinaries installed.
Procedure
Download the
tuftoolbinary from the OpenShift cluster to your workstation.ImportantThe
tuftoolbinary is only available for Linux operating systems.- From the home page, click the ? icon, click Command line tools, go to the tuftool download section, and click the link for your platform.
Open a terminal on your workstation, decompress the binary
.gzfile, and set the execute bit:Example
$ gunzip tuftool-amd64.gz $ chmod +x tuftool-amd64Move and rename the binary to a location within your
$PATHenvironment:Example
$ sudo mv tuftool-amd64 /usr/local/bin/tuftool
Log in to OpenShift from the command line:
Syntax
oc login --token=TOKEN --server=SERVER_URL_AND_PORTExample
$ oc login --token=sha256~ZvFDBvoIYAbVECixS4-WmkN4RfnNd8Neh3y1WuiFPXC --server=https://example.com:6443NoteYou can find your login token and URL for use on the command line from the OpenShift web console. Log in to the OpenShift web console. Click your user name, and click Copy login command. Offer your user name and password again, if asked, and click Display Token to view the command.
Switch to the RHTAS project:
Example
$ oc project trusted-artifact-signerGenerate a new certificate chain, and a new signer key.
ImportantThe new certificate and keys must have unique file names.
Create a temporary working directory:
Example
$ mkdir certs && cd certsCreate the root certificate authority (CA) private key, and set a password:
Example
$ openssl req -x509 -newkey rsa:2048 -days 365 -sha256 -nodes \ -keyout rootCA.key.pem -out rootCA.crt.pem \ -passout pass:"CHANGE_ME" \ -subj "/C=CC/ST=state/L=Locality/O=RH/OU=RootCA/CN=RootCA" \ -addext "basicConstraints=CA:true" -addext "keyUsage=cRLSign, keyCertSign"Replace CHANGE_ME with a new password.
Create the intermediate CA private key and certificate signing request (CSR), and set a password:
Example
$ openssl req -newkey rsa:2048 -sha256 \ -keyout intermediateCA.key.pem -out intermediateCA.csr.pem \ -passout pass:"CHANGE_ME" \ -subj "/C=CC/ST=state/L=Locality/O=RH/OU=IntermediateCA/CN=IntermediateCA"Replace CHANGE_ME with a new password.
Sign the intermediate CA certificate with the root CA:
Example
$ openssl x509 -req -in intermediateCA.csr.pem -CA rootCA.crt.pem -CAkey rootCA.key.pem \ -CAcreateserial -out intermediateCA.crt.pem -days 365 -sha256 \ -extfile <(echo -e "basicConstraints=CA:true\nkeyUsage=cRLSign, keyCertSign\nextendedKeyUsage=critical,timeStamping") \ -passin pass:"CHANGE_ME"Replace CHANGE_ME with the root CA private key password to sign the intermediate CA certificate.
Create the leaf CA private key and CSR, and set a password:
Example
$ openssl req -newkey rsa:2048 -sha256 \ -keyout leafCA.key.pem -out leafCA.csr.pem \ -passout pass:"CHANGE_ME" \ -subj "/C=CC/ST=state/L=Locality/O=RH/OU=LeafCA/CN=LeafCA"Sign the leaf CA certificate with the intermediate CA:
Example
$ openssl x509 -req -in leafCA.csr.pem -CA intermediateCA.crt.pem -CAkey intermediateCA.key.pem \ -CAcreateserial -out leafCA.crt.pem -days 365 -sha256 \ -extfile <(echo -e "basicConstraints=CA:false\nkeyUsage=cRLSign, keyCertSign\nextendedKeyUsage=critical,timeStamping") \ -passin pass:"CHANGE_ME"Replace CHANGE_ME with the intermediate CA private key password to sign the leaf CA certificate.
Create the certificate chain by combining the newly created certificates:
Example
$ cat leafCA.crt.pem intermediateCA.crt.pem rootCA.crt.pem > new-cert-chain.pem
Create a new secret resource with the signer key:
Example
$ oc create secret generic rotated-signer-key --from-file=rotated-signer-key=certs/leafCA.key.pemCreate a new secret resource with the new certificate chain:
Example
$ oc create secret generic rotated-cert-chain --from-file=rotated-cert-chain=certs/new-cert-chain.pemCreate a new secret resource with for the password:
Example
$ oc create secret generic rotated-password --from-literal=rotated-password=CHANGE_MEReplace CHANGE_ME with the intermediate CA private key password.
Find your active TSA certificate file name, the TSA URL string, and configure your shell environment with these values:
Example
$ export ACTIVE_CERT_CHAIN_NAME=tsa.certchain.pem $ export TSA_URL=$(oc get timestampauthority securesign-sample -o jsonpath='{.status.url}')/api/v1/timestamp $ curl $TSA_URL/certchain -o $ACTIVE_CERT_CHAIN_NAMEUpdate the Securesign TSA configuration:
Example
$ read -r -d '' SECURESIGN_PATCH <<EOF [ { "op": "replace", "path": "/spec/tsa/signer/certificateChain", "value": { "certificateChainRef" : {"name": "rotated-cert-chain", "key": "rotated-cert-chain"} } }, { "op": "replace", "path": "/spec/tsa/signer/file", "value": { "privateKeyRef": {"name": "rotated-signer-key", "key": "rotated-signer-key"}, "passwordRef": {"name": "rotated-password", "key": "rotated-password"} } } ] EOFPatch the Securesign instance:
Example
$ oc patch Securesign securesign-sample --type='json' -p="$SECURESIGN_PATCH"Wait for the TSA server to redeploy with the new signer key and certificate chain:
Example
$ oc get pods -w -l app.kubernetes.io/name=tsa-serverGet the new certificate chain:
Example
$ export NEW_CERT_CHAIN_NAME=new_tsa.certchain.pem $ curl $TSA_URL/certchain -o $NEW_CERT_CHAIN_NAMEConfigure The Update Framework (TUF) service to use the new TSA certificate chain.
Set up your shell environment:
Example
$ 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")"Create a temporary TUF directory structure:
Example
$ mkdir -p "${WORK}/root/" "${KEYDIR}" "${INPUT}" "${TUF_REPO}"Download the TUF contents to the temporary TUF directory structure:
Example
$ oc extract --to "${KEYDIR}/" secret/tuf-root-keys $ oc cp "${TUF_SERVER_POD}:/var/www/html" "${TUF_REPO}" $ cp "${TUF_REPO}/root.json" "${ROOT}"Expire the old TSA certificate:
Example
$ tuftool rhtas \ --root "${ROOT}" \ --key "${KEYDIR}/snapshot.pem" \ --key "${KEYDIR}/targets.pem" \ --key "${KEYDIR}/timestamp.pem" \ --set-tsa-target "$ACTIVE_CERT_CHAIN_NAME" \ --tsa-uri "$TSA_URL" \ --tsa-status "Expired" \ --outdir "${TUF_REPO}" \ --metadata-url "file://${TUF_REPO}"Add the new TSA certificate:
Example
$ tuftool rhtas \ --root "${ROOT}" \ --key "${KEYDIR}/snapshot.pem" \ --key "${KEYDIR}/targets.pem" \ --key "${KEYDIR}/timestamp.pem" \ --set-tsa-target "$NEW_CERT_CHAIN_NAME" \ --tsa-uri "$TSA_URL" \ --outdir "${TUF_REPO}" \ --metadata-url "file://${TUF_REPO}"Upload these changes to the TUF server:
Example
$ oc rsync "${TUF_REPO}/" "${TUF_SERVER_POD}:/var/www/html"Delete the working directory:
Example
$ rm -r $WORK
Update the
cosignconfiguration with the updated TUF configuration:Example
$ cosign initialize --mirror=$TUF_URL --root=$TUF_URL/root.jsonNow, you are ready to sign and verify your artifacts that uses the new TSA signer key, and certificate.