Files
explorer-monorepo/scripts/analyze-besu-logs.sh
Devin ad69385beb fix(security): fail-fast on missing JWT_SECRET, harden CSP, strip hardcoded passwords
backend/api/rest/server.go:
- NewServer() now delegates to loadJWTSecret(), which:
    - Rejects JWT_SECRET < 32 bytes (log.Fatal).
    - Requires JWT_SECRET when APP_ENV=production or GO_ENV=production.
    - Generates a 32-byte crypto/rand ephemeral secret in dev only.
    - Treats rand.Read failure as fatal (removes the prior time-based
      fallback that was deterministic and forgeable).
- Default Content-Security-Policy rewritten:
    - Drops 'unsafe-inline' and 'unsafe-eval'.
    - Drops private CIDRs (192.168.11.221:854[5|6]).
    - Adds frame-ancestors 'none', base-uri 'self', form-action 'self'.
    - CSP_HEADER is required in production; fatal if unset there.

backend/api/rest/server_security_test.go (new):
- Covers the three loadJWTSecret() paths (valid, whitespace-trimmed,
  ephemeral in dev).
- Covers isProductionEnv() across APP_ENV / GO_ENV combinations.
- Asserts defaultDevCSP contains no unsafe directives or private CIDRs
  and includes the frame-ancestors / base-uri / form-action directives.

scripts/*.sh:
- Removed '***REDACTED-LEGACY-PW***' default value from SSH_PASSWORD / NEW_PASSWORD in
  7 helper scripts. Each script now fails with exit 2 and points to
  docs/SECURITY.md if the password isn't supplied via env or argv.

EXECUTE_DEPLOYMENT.sh, EXECUTE_NOW.sh:
- Replaced hardcoded DB_PASSWORD='***REDACTED-LEGACY-PW***' with a ':?' guard that
  aborts with a clear error if DB_PASSWORD (and, for EXECUTE_DEPLOYMENT,
  RPC_URL) is not exported. Other env vars keep sensible non-secret
  defaults via ${VAR:-default}.

README.md:
- Removed the hardcoded Database Password / RPC URL lines. Replaced with
  an env-variable reference table pointing at docs/SECURITY.md and
  docs/DATABASE_CONNECTION_GUIDE.md.

docs/DEPLOYMENT.md:
- Replaced 'PASSWORD: SSH password (default: ***REDACTED-LEGACY-PW***)' with a
  required-no-default contract and a link to docs/SECURITY.md.

docs/SECURITY.md (new):
- Full secret inventory keyed to the env variable name and the file that
  consumes it.
- Five-step rotation checklist covering the Postgres role, the Proxmox
  VM SSH password, JWT_SECRET, vendor API keys, and a gitleaks-based
  history audit.
- Explicit note that merging secret-scrub PRs does NOT invalidate
  already-leaked credentials; rotation is the operator's responsibility.

Verification:
- go build ./... + go vet ./... pass clean.
- Targeted tests (LoadJWTSecret*, IsProduction*, DefaultDevCSP*) pass.

Advances completion criterion 2 (Secrets & config hardened). Residual
leakage from START_HERE.md / LETSENCRYPT_CONFIGURATION_GUIDE.md is
handled by PR #2 (doc consolidation), which deletes those files.
2026-04-18 19:02:27 +00:00

187 lines
8.2 KiB
Bash
Executable File
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# Analyze Besu Logs for Deployment Errors
# Searches for transaction-related errors and deployment issues
set -euo pipefail
RPC_IP="${1:-192.168.11.250}"
SSH_PASSWORD="${SSH_PASSWORD:-${2:-}}"
if [ -z "${SSH_PASSWORD}" ]; then
echo "ERROR: SSH_PASSWORD is required. Pass it as an argument or export SSH_PASSWORD in the environment." >&2
echo " Hardcoded default removed for security; see docs/SECURITY.md." >&2
exit 2
fi
LOG_LINES="${3:-1000}"
echo "╔══════════════════════════════════════════════════════════════╗"
echo "║ ANALYZING BESU LOGS FOR DEPLOYMENT ERRORS ║"
echo "╚══════════════════════════════════════════════════════════════╝"
echo ""
echo "RPC IP: $RPC_IP"
echo "Analyzing last $LOG_LINES lines of logs"
echo ""
# Check if sshpass is available
if ! command -v sshpass >/dev/null 2>&1; then
echo "⚠️ sshpass not installed. Installing..."
sudo apt-get update -qq && sudo apt-get install -y sshpass 2>/dev/null || {
echo "❌ Cannot install sshpass automatically"
echo "Please install manually: sudo apt-get install sshpass"
exit 1
}
fi
# Get full logs
echo "Retrieving Besu logs..."
FULL_LOGS=$(sshpass -p "$SSH_PASSWORD" ssh -o StrictHostKeyChecking=no -o ConnectTimeout=10 \
root@"$RPC_IP" \
"journalctl -u besu-rpc -n $LOG_LINES --no-pager 2>/dev/null" 2>&1)
if [ -z "$FULL_LOGS" ] || echo "$FULL_LOGS" | grep -q "Permission denied\|Connection refused"; then
echo "❌ Failed to retrieve logs"
exit 1
fi
echo "✅ Retrieved logs"
echo ""
# Search for transaction-related errors
echo "═══════════════════════════════════════════════════════════════"
echo "1. TRANSACTION-RELATED ERRORS"
echo "═══════════════════════════════════════════════════════════════"
echo ""
TX_ERRORS=$(echo "$FULL_LOGS" | grep -iE "transaction|tx|reject|invalid|revert|error|fail" | grep -v "PersistBlock" || echo "")
if [ -n "$TX_ERRORS" ]; then
echo "$TX_ERRORS" | tail -50
else
echo " No transaction errors found in recent logs"
fi
echo ""
# Search for deployment/contract creation errors
echo "═══════════════════════════════════════════════════════════════"
echo "2. CONTRACT CREATION / DEPLOYMENT ERRORS"
echo "═══════════════════════════════════════════════════════════════"
echo ""
DEPLOY_ERRORS=$(echo "$FULL_LOGS" | grep -iE "deploy|create|contract|bytecode|code|init" | grep -iE "error|fail|reject|invalid" || echo "")
if [ -n "$DEPLOY_ERRORS" ]; then
echo "$DEPLOY_ERRORS" | tail -50
else
echo " No deployment errors found in recent logs"
fi
echo ""
# Search for gas-related errors
echo "═══════════════════════════════════════════════════════════════"
echo "3. GAS-RELATED ERRORS"
echo "═══════════════════════════════════════════════════════════════"
echo ""
GAS_ERRORS=$(echo "$FULL_LOGS" | grep -iE "gas|limit|exceed|out of gas" | grep -iE "error|fail|reject" || echo "")
if [ -n "$GAS_ERRORS" ]; then
echo "$GAS_ERRORS" | tail -50
else
echo " No gas-related errors found in recent logs"
fi
echo ""
# Search for permission-related errors
echo "═══════════════════════════════════════════════════════════════"
echo "4. PERMISSION-RELATED ERRORS"
echo "═══════════════════════════════════════════════════════════════"
echo ""
PERM_ERRORS=$(echo "$FULL_LOGS" | grep -iE "permission|allowlist|whitelist|denied|forbidden" || echo "")
if [ -n "$PERM_ERRORS" ]; then
echo "$PERM_ERRORS" | tail -50
else
echo " No permission errors found in recent logs"
fi
echo ""
# Search for specific transaction hashes from failed deployments
echo "═══════════════════════════════════════════════════════════════"
echo "5. FAILED DEPLOYMENT TRANSACTIONS"
echo "═══════════════════════════════════════════════════════════════"
echo ""
FAILED_TXS=(
"0x4dc9f5eedf580c2b37457916b04048481aba19cf3c1a106ea1ee9eefa0dc03c8"
"0xc6502cdc4cb2f583fc6b3ddeb8b67b81877cff7a3c824634874a844651609a51"
"0x808eab4238297ea68930cd5bf33b887937be0d8e533b638c33d8d1bd0de48018"
"0xf43b359ea1f99c3c38651796647903bc5f9c2b5ffb7948062b9be924da97b828"
)
for tx in "${FAILED_TXS[@]}"; do
TX_SHORT="${tx:0:20}..."
TX_LOG=$(echo "$FULL_LOGS" | grep -i "$tx" || echo "")
if [ -n "$TX_LOG" ]; then
echo " Found transaction: $TX_SHORT"
echo "$TX_LOG" | head -5
echo ""
fi
done
if [ -z "$TX_LOG" ]; then
echo " No logs found for known failed transactions"
echo " (Transactions may have been processed but not logged)"
fi
echo ""
# Search for WARN and ERROR level messages
echo "═══════════════════════════════════════════════════════════════"
echo "6. WARN AND ERROR LEVEL MESSAGES"
echo "═══════════════════════════════════════════════════════════════"
echo ""
WARN_ERROR=$(echo "$FULL_LOGS" | grep -iE "WARN|ERROR" | grep -v "PersistBlock" || echo "")
if [ -n "$WARN_ERROR" ]; then
echo "$WARN_ERROR" | tail -50
else
echo " No WARN or ERROR messages found in recent logs"
fi
echo ""
# Summary
echo "═══════════════════════════════════════════════════════════════"
echo "SUMMARY"
echo "═══════════════════════════════════════════════════════════════"
echo ""
TX_ERROR_COUNT=$(echo "$TX_ERRORS" | wc -l)
DEPLOY_ERROR_COUNT=$(echo "$DEPLOY_ERRORS" | wc -l)
GAS_ERROR_COUNT=$(echo "$GAS_ERRORS" | wc -l)
PERM_ERROR_COUNT=$(echo "$PERM_ERRORS" | wc -l)
WARN_ERROR_COUNT=$(echo "$WARN_ERROR" | wc -l)
echo "Transaction errors: $TX_ERROR_COUNT"
echo "Deployment errors: $DEPLOY_ERROR_COUNT"
echo "Gas errors: $GAS_ERROR_COUNT"
echo "Permission errors: $PERM_ERROR_COUNT"
echo "WARN/ERROR messages: $WARN_ERROR_COUNT"
echo ""
if [ "$TX_ERROR_COUNT" -eq 0 ] && [ "$DEPLOY_ERROR_COUNT" -eq 0 ] && [ "$GAS_ERROR_COUNT" -eq 0 ] && [ "$PERM_ERROR_COUNT" -eq 0 ]; then
echo "⚠️ No errors found in logs, but deployments are still failing."
echo " This suggests the issue may be:"
echo " 1. Network-level restriction (not logged)"
echo " 2. Validator-level restriction"
echo " 3. Transaction pool rejection (before processing)"
echo " 4. RPC node configuration issue"
echo ""
echo " Next steps:"
echo " - Check transaction pool status"
echo " - Verify network configuration"
echo " - Check validator logs"
fi
echo ""