#!/bin/bash # ----------------------------------------------------------------------------- # bootstrap-trust.sh # Sprint: SPRINT_20260125_003_Attestor_trust_workflows_conformance # Task: WORKFLOW-001 - Create bootstrap workflow script # Description: Initialize trust for new StellaOps deployment # ----------------------------------------------------------------------------- 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 [options]" echo "" echo "Initialize trust for a new StellaOps deployment." echo "" echo "Options:" echo " --tuf-url URL TUF repository URL (required)" echo " --service-map NAME Service map target name (default: sigstore-services-v1)" echo " --pin KEY Rekor key to pin (can specify multiple)" echo " --key-dir DIR Directory for signing keys (default: /etc/stellaops/keys)" echo " --skip-keygen Skip signing key generation" echo " --skip-test Skip sign/verify test" echo " --offline Initialize in offline mode" echo " -h, --help Show this help message" echo "" echo "Example:" echo " $0 --tuf-url https://trust.example.com/tuf/ --pin rekor-key-v1" exit 1 } TUF_URL="" SERVICE_MAP="sigstore-services-v1" PIN_KEYS=() KEY_DIR="/etc/stellaops/keys" SKIP_KEYGEN=false SKIP_TEST=false OFFLINE=false while [[ $# -gt 0 ]]; do case $1 in --tuf-url) TUF_URL="$2"; shift 2 ;; --service-map) SERVICE_MAP="$2"; shift 2 ;; --pin) PIN_KEYS+=("$2"); shift 2 ;; --key-dir) KEY_DIR="$2"; shift 2 ;; --skip-keygen) SKIP_KEYGEN=true; shift ;; --skip-test) SKIP_TEST=true; shift ;; --offline) OFFLINE=true; shift ;; -h|--help) usage ;; *) log_error "Unknown option: $1"; usage ;; esac done if [[ -z "$TUF_URL" ]]; then log_error "TUF URL is required" usage fi if [[ ${#PIN_KEYS[@]} -eq 0 ]]; then PIN_KEYS=("rekor-key-v1") fi echo "" echo "================================================" echo " StellaOps Trust Bootstrap" echo "================================================" echo "" log_info "TUF URL: $TUF_URL" log_info "Service Map: $SERVICE_MAP" log_info "Pinned Keys: ${PIN_KEYS[*]}" log_info "Key Directory: $KEY_DIR" echo "" # Step 1: Generate signing keys (if using local keys) if [[ "$SKIP_KEYGEN" != "true" ]]; then log_step "Step 1: Generating signing keys..." mkdir -p "$KEY_DIR" chmod 700 "$KEY_DIR" if [[ ! -f "$KEY_DIR/signing-key.pem" ]]; then stella keys generate --type ecdsa-p256 --out "$KEY_DIR/signing-key.pem" 2>/dev/null || \ openssl ecparam -name prime256v1 -genkey -noout -out "$KEY_DIR/signing-key.pem" chmod 600 "$KEY_DIR/signing-key.pem" log_info "Generated signing key: $KEY_DIR/signing-key.pem" else log_info "Signing key already exists: $KEY_DIR/signing-key.pem" fi else log_step "Step 1: Skipping key generation (--skip-keygen)" fi # Step 2: Initialize TUF client log_step "Step 2: Initializing TUF client..." PIN_ARGS="" for key in "${PIN_KEYS[@]}"; do PIN_ARGS="$PIN_ARGS --pin $key" done OFFLINE_ARG="" if [[ "$OFFLINE" == "true" ]]; then OFFLINE_ARG="--offline" fi stella trust init \ --tuf-url "$TUF_URL" \ --service-map "$SERVICE_MAP" \ $PIN_ARGS \ $OFFLINE_ARG \ --force if [[ $? -ne 0 ]]; then log_error "Failed to initialize TUF client" exit 1 fi log_info "TUF client initialized successfully" # Step 3: Verify TUF metadata loaded log_step "Step 3: Verifying TUF metadata..." stella trust status --show-keys --show-endpoints if [[ $? -ne 0 ]]; then log_error "Failed to verify TUF status" exit 1 fi # Step 4: Test sign/verify cycle if [[ "$SKIP_TEST" != "true" ]] && [[ "$SKIP_KEYGEN" != "true" ]]; then log_step "Step 4: Testing sign/verify cycle..." TEST_FILE=$(mktemp) TEST_SIG=$(mktemp) echo "StellaOps bootstrap test $(date -u +%Y-%m-%dT%H:%M:%SZ)" > "$TEST_FILE" stella sign "$TEST_FILE" --key "$KEY_DIR/signing-key.pem" --out "$TEST_SIG" 2>/dev/null || { # Fallback to openssl if stella sign not available openssl dgst -sha256 -sign "$KEY_DIR/signing-key.pem" -out "$TEST_SIG" "$TEST_FILE" } if [[ -f "$TEST_SIG" ]] && [[ -s "$TEST_SIG" ]]; then log_info "Sign/verify test passed" else log_warn "Sign test could not be verified (this may be expected)" fi rm -f "$TEST_FILE" "$TEST_SIG" else log_step "Step 4: Skipping sign/verify test" fi # Step 5: Test Rekor connectivity (if online) if [[ "$OFFLINE" != "true" ]]; then log_step "Step 5: Testing Rekor connectivity..." REKOR_URL=$(stella trust status --output json 2>/dev/null | grep -o '"rekor_url"[[:space:]]*:[[:space:]]*"[^"]*"' | head -1 | cut -d'"' -f4 || echo "") if [[ -n "$REKOR_URL" ]]; then if curl -sf "${REKOR_URL}/api/v1/log" >/dev/null 2>&1; then log_info "Rekor connectivity: OK" else log_warn "Rekor connectivity check failed (service may be unavailable)" fi else log_warn "Could not determine Rekor URL from trust status" fi else log_step "Step 5: Skipping Rekor test (offline mode)" fi echo "" echo "================================================" echo -e "${GREEN} Bootstrap Complete!${NC}" echo "================================================" echo "" log_info "Trust repository initialized at: ~/.local/share/StellaOps/TufCache" log_info "Signing key (if generated): $KEY_DIR/signing-key.pem" echo "" log_info "Next steps:" echo " 1. Configure your CI/CD to use the signing key" echo " 2. Set up periodic 'stella trust sync' for metadata freshness" echo " 3. For air-gap deployments, run 'stella trust export' to create bundles" echo ""