fix tests. new product advisories enhancements
This commit is contained in:
197
devops/scripts/rotate-rekor-key.sh
Normal file
197
devops/scripts/rotate-rekor-key.sh
Normal file
@@ -0,0 +1,197 @@
|
||||
#!/bin/bash
|
||||
# -----------------------------------------------------------------------------
|
||||
# rotate-rekor-key.sh
|
||||
# Sprint: SPRINT_20260125_003_Attestor_trust_workflows_conformance
|
||||
# Task: WORKFLOW-002 - Create key rotation workflow script
|
||||
# Description: Rotate Rekor public key with grace period
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
|
||||
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
||||
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
||||
log_step() { echo -e "${BLUE}[STEP]${NC} $1"; }
|
||||
|
||||
usage() {
|
||||
echo "Usage: $0 <phase> [options]"
|
||||
echo ""
|
||||
echo "Rotate Rekor public key through a dual-key grace period."
|
||||
echo ""
|
||||
echo "Phases:"
|
||||
echo " add-key Add new key to TUF (starts grace period)"
|
||||
echo " verify Verify both keys are active"
|
||||
echo " remove-old Remove old key (after grace period)"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " --repo DIR TUF repository directory"
|
||||
echo " --new-key FILE Path to new Rekor public key"
|
||||
echo " --new-key-name NAME Target name for new key (default: rekor-key-v{N+1})"
|
||||
echo " --old-key-name NAME Target name for old key to remove"
|
||||
echo " --grace-days N Grace period in days (default: 7)"
|
||||
echo " -h, --help Show this help message"
|
||||
echo ""
|
||||
echo "Example (3-phase rotation):"
|
||||
echo " # Phase 1: Add new key"
|
||||
echo " $0 add-key --repo /path/to/tuf --new-key rekor-key-v2.pub"
|
||||
echo ""
|
||||
echo " # Wait for grace period (clients sync)"
|
||||
echo " sleep 7d"
|
||||
echo ""
|
||||
echo " # Phase 2: Verify"
|
||||
echo " $0 verify"
|
||||
echo ""
|
||||
echo " # Phase 3: Remove old key"
|
||||
echo " $0 remove-old --repo /path/to/tuf --old-key-name rekor-key-v1"
|
||||
exit 1
|
||||
}
|
||||
|
||||
PHASE=""
|
||||
REPO_DIR=""
|
||||
NEW_KEY=""
|
||||
NEW_KEY_NAME=""
|
||||
OLD_KEY_NAME=""
|
||||
GRACE_DAYS=7
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
add-key|verify|remove-old)
|
||||
PHASE="$1"
|
||||
shift
|
||||
;;
|
||||
--repo) REPO_DIR="$2"; shift 2 ;;
|
||||
--new-key) NEW_KEY="$2"; shift 2 ;;
|
||||
--new-key-name) NEW_KEY_NAME="$2"; shift 2 ;;
|
||||
--old-key-name) OLD_KEY_NAME="$2"; shift 2 ;;
|
||||
--grace-days) GRACE_DAYS="$2"; shift 2 ;;
|
||||
-h|--help) usage ;;
|
||||
*) log_error "Unknown argument: $1"; usage ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ -z "$PHASE" ]]; then
|
||||
log_error "Phase is required"
|
||||
usage
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "================================================"
|
||||
echo " Rekor Key Rotation - Phase: $PHASE"
|
||||
echo "================================================"
|
||||
echo ""
|
||||
|
||||
case "$PHASE" in
|
||||
add-key)
|
||||
if [[ -z "$REPO_DIR" ]] || [[ -z "$NEW_KEY" ]]; then
|
||||
log_error "add-key requires --repo and --new-key"
|
||||
usage
|
||||
fi
|
||||
|
||||
if [[ ! -f "$NEW_KEY" ]]; then
|
||||
log_error "New key file not found: $NEW_KEY"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -d "$REPO_DIR" ]]; then
|
||||
log_error "TUF repository not found: $REPO_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Determine new key name if not specified
|
||||
if [[ -z "$NEW_KEY_NAME" ]]; then
|
||||
# Find highest version and increment
|
||||
HIGHEST=$(ls "$REPO_DIR/targets/" 2>/dev/null | grep -E '^rekor-key-v[0-9]+' | \
|
||||
sed 's/rekor-key-v//' | sed 's/\.pub$//' | sort -n | tail -1 || echo "0")
|
||||
NEW_VERSION=$((HIGHEST + 1))
|
||||
NEW_KEY_NAME="rekor-key-v${NEW_VERSION}"
|
||||
fi
|
||||
|
||||
log_step "Adding new Rekor key: $NEW_KEY_NAME"
|
||||
log_info "Source: $NEW_KEY"
|
||||
|
||||
# Copy key to targets
|
||||
cp "$NEW_KEY" "$REPO_DIR/targets/${NEW_KEY_NAME}.pub"
|
||||
|
||||
# Add to targets.json
|
||||
if [[ -x "$REPO_DIR/scripts/add-target.sh" ]]; then
|
||||
"$REPO_DIR/scripts/add-target.sh" "$REPO_DIR/targets/${NEW_KEY_NAME}.pub" "${NEW_KEY_NAME}.pub" --repo "$REPO_DIR"
|
||||
else
|
||||
log_warn "add-target.sh not found, updating targets.json manually required"
|
||||
fi
|
||||
|
||||
log_info ""
|
||||
log_info "Key added: $NEW_KEY_NAME"
|
||||
log_info ""
|
||||
log_warn "IMPORTANT: Dual-key period has started."
|
||||
log_warn "Wait at least $GRACE_DAYS days before running 'remove-old' phase."
|
||||
log_warn "During this time, clients will sync and receive both keys."
|
||||
log_info ""
|
||||
log_info "Next steps:"
|
||||
echo " 1. Sign and publish updated TUF metadata"
|
||||
echo " 2. Monitor client sync status"
|
||||
echo " 3. After $GRACE_DAYS days, run: $0 remove-old --repo $REPO_DIR --old-key-name <old-key>"
|
||||
;;
|
||||
|
||||
verify)
|
||||
log_step "Verifying key rotation status..."
|
||||
|
||||
# Check local trust state
|
||||
stella trust status --show-keys
|
||||
|
||||
log_info ""
|
||||
log_info "Verify that:"
|
||||
echo " 1. Both old and new Rekor keys are listed"
|
||||
echo " 2. Service endpoints are resolving correctly"
|
||||
echo " 3. Attestations signed with old key still verify"
|
||||
;;
|
||||
|
||||
remove-old)
|
||||
if [[ -z "$REPO_DIR" ]] || [[ -z "$OLD_KEY_NAME" ]]; then
|
||||
log_error "remove-old requires --repo and --old-key-name"
|
||||
usage
|
||||
fi
|
||||
|
||||
if [[ ! -d "$REPO_DIR" ]]; then
|
||||
log_error "TUF repository not found: $REPO_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
OLD_KEY_FILE="$REPO_DIR/targets/${OLD_KEY_NAME}.pub"
|
||||
if [[ ! -f "$OLD_KEY_FILE" ]]; then
|
||||
OLD_KEY_FILE="$REPO_DIR/targets/${OLD_KEY_NAME}"
|
||||
fi
|
||||
|
||||
if [[ ! -f "$OLD_KEY_FILE" ]]; then
|
||||
log_error "Old key not found: $OLD_KEY_NAME"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_step "Removing old Rekor key: $OLD_KEY_NAME"
|
||||
log_warn "This is IRREVERSIBLE. Ensure all clients have synced the new key."
|
||||
|
||||
read -p "Type 'CONFIRM' to proceed: " CONFIRM
|
||||
if [[ "$CONFIRM" != "CONFIRM" ]]; then
|
||||
log_error "Aborted"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Remove key file
|
||||
rm -f "$OLD_KEY_FILE"
|
||||
|
||||
# Remove from targets.json (simplified - production should use proper JSON manipulation)
|
||||
log_warn "Remember to update targets.json to remove the old key entry"
|
||||
log_warn "Then sign and publish the updated metadata"
|
||||
|
||||
log_info ""
|
||||
log_info "Old key removed: $OLD_KEY_NAME"
|
||||
log_info "Key rotation complete!"
|
||||
;;
|
||||
esac
|
||||
|
||||
echo ""
|
||||
Reference in New Issue
Block a user