#!/usr/bin/env bash # Script to audit all toolboxes in the ToolboxStack # This script is designed to be run as part of the QA audit process set -euo pipefail # Determine the base directory SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" TOOLBOX_STACK_ROOT="$(dirname "${SCRIPT_DIR}")" OUTPUT_DIR="${1:-${SCRIPT_DIR}/audits/$(date +%Y)/$(date +%m)/$(date +%d)/$(date +%H)$(date +%M)}" # Create output directory mkdir -p "${OUTPUT_DIR}" echo "Starting comprehensive toolbox audit..." echo "Audit directory: ${OUTPUT_DIR}" # Function to audit a single toolbox audit_toolbox() { local toolbox_path="$1" local toolbox_name="$2" echo "Auditing ${toolbox_name}..." # Create a report for this toolbox local report_file="${OUTPUT_DIR}/${toolbox_name}-audit-report.txt" echo "=== ${toolbox_name} Audit Report ===" > "${report_file}" echo "Audit Date: $(date)" >> "${report_file}" echo "" >> "${report_file}" # Check if Dockerfile exists if [[ -f "${toolbox_path}/Dockerfile" ]]; then echo "✓ Dockerfile exists" >> "${report_file}" # Check for security best practices in Dockerfile if grep -q "FROM ubuntu:24.04" "${toolbox_path}/Dockerfile"; then echo "✓ Uses Ubuntu 24.04 base image" >> "${report_file}" else echo "⚠ Does not use Ubuntu 24.04 base image" >> "${report_file}" fi if grep -q "USER.*toolbox" "${toolbox_path}/Dockerfile"; then echo "✓ Runs as non-root user (toolbox)" >> "${report_file}" else echo "⚠ Does not run as non-root user" >> "${report_file}" fi if grep -q "sudo.*remove\|sudo.*purge" "${toolbox_path}/Dockerfile"; then echo "✓ Sudo removed from final image" >> "${report_file}" else echo "⚠ Sudo may not be removed from final image" >> "${report_file}" fi # Check for multi-stage build if grep -i "as.*installer\|as.*build\|as.*final" "${toolbox_path}/Dockerfile" | grep -v "^#" > /dev/null; then echo "✓ Uses multi-stage build" >> "${report_file}" else echo "⚠ Does not appear to use multi-stage build" >> "${report_file}" fi # Count number of tools installed via aqua if [[ -f "${toolbox_path}/aqua.yaml" ]]; then local aqua_tools_count=$(grep -c "name:" "${toolbox_path}/aqua.yaml" 2>/dev/null || echo 0) echo "✓ Aqua package manager configuration found (${aqua_tools_count} tools)" >> "${report_file}" else echo "⚠ No aqua.yaml configuration found" >> "${report_file}" fi else echo "✗ No Dockerfile found" >> "${report_file}" fi # Check for required scripts for script in build.sh run.sh test.sh; do if [[ -f "${toolbox_path}/${script}" ]]; then echo "✓ ${script} exists" >> "${report_file}" else echo "⚠ ${script} missing" >> "${report_file}" fi done # Check for documentation if [[ -f "${toolbox_path}/README.md" ]]; then echo "✓ README.md exists" >> "${report_file}" else echo "⚠ README.md missing" >> "${report_file}" fi if [[ -f "${toolbox_path}/PROMPT" ]]; then echo "✓ PROMPT exists" >> "${report_file}" else echo "⚠ PROMPT missing" >> "${report_file}" fi if [[ -f "${toolbox_path}/SEED" ]]; then echo "✓ SEED exists" >> "${report_file}" else echo "⚠ SEED missing" >> "${report_file}" fi if [[ -f "${toolbox_path}/.devcontainer/devcontainer.json" ]]; then echo "✓ Devcontainer configuration exists" >> "${report_file}" else echo "⚠ Devcontainer configuration missing" >> "${report_file}" fi echo "" >> "${report_file}" echo "Dockerfile excerpt:" >> "${report_file}" echo "================== " >> "${report_file}" head -20 "${toolbox_path}/Dockerfile" 2>/dev/null || echo "Could not read Dockerfile" >> "${report_file}" echo "" >> "${report_file}" } # Find all toolboxes echo "Discovering toolboxes..." TOOLBOXES_DIR="${TOOLBOX_STACK_ROOT}/output" if [[ -d "${TOOLBOXES_DIR}" ]]; then for toolbox_dir in "${TOOLBOXES_DIR}"/toolbox-*; do if [[ -d "${toolbox_dir}" ]]; then toolbox_name=$(basename "${toolbox_dir}") audit_toolbox "${toolbox_dir}" "${toolbox_name}" fi done else echo "ERROR: Toolboxes directory not found: ${TOOLBOXES_DIR}" exit 1 fi echo "Toolbox audits completed. Results in: ${OUTPUT_DIR}" # Create a summary report SUMMARY_FILE="${OUTPUT_DIR}/toolbox-audit-summary.txt" echo "=== Toolbox Audit Summary ===" > "${SUMMARY_FILE}" echo "Total audit date: $(date)" >> "${SUMMARY_FILE}" echo "" >> "${SUMMARY_FILE}" for report in "${OUTPUT_DIR}"/*-audit-report.txt; do if [[ -f "${report}" ]]; then toolbox_name=$(basename "${report}" | sed 's/-audit-report.txt//') echo "Toolbox: ${toolbox_name}" >> "${SUMMARY_FILE}" # Count checks total_checks=$(grep -c "^✓\|^⚠\|^✗" "${report}" || echo 0) pass_checks=$(grep -c "^✓" "${report}" || echo 0) warn_checks=$(grep -c "^⚠" "${report}" || echo 0) fail_checks=$(grep -c "^✗" "${report}" || echo 0) echo " Total checks: ${total_checks}" >> "${SUMMARY_FILE}" echo " Passed: ${pass_checks}" >> "${SUMMARY_FILE}" echo " Warnings: ${warn_checks}" >> "${SUMMARY_FILE}" echo " Failures: ${fail_checks}" >> "${SUMMARY_FILE}" echo "" >> "${SUMMARY_FILE}" fi done # Create a comprehensive report that combines all individual reports COMPREHENSIVE_REPORT="${OUTPUT_DIR}/comprehensive-toolbox-audit.txt" echo "# Comprehensive Toolbox Audit Report" > "${COMPREHENSIVE_REPORT}" echo "Generated: $(date)" >> "${COMPREHENSIVE_REPORT}" echo "" >> "${COMPREHENSIVE_REPORT}" cat "${SUMMARY_FILE}" >> "${COMPREHENSIVE_REPORT}" echo "" >> "${COMPREHENSIVE_REPORT}" for report in "${OUTPUT_DIR}"/*-audit-report.txt; do if [[ -f "${report}" ]]; then cat "${report}" >> "${COMPREHENSIVE_REPORT}" echo "" >> "${COMPREHENSIVE_REPORT}" fi done echo "Comprehensive report created: ${COMPREHENSIVE_REPORT}" # Copy the comprehensive report to the main audit directory for easy access during QA cp "${COMPREHENSIVE_REPORT}" "${OUTPUT_DIR}/../latest-toolbox-audit.txt" 2>/dev/null || true echo "All audits completed successfully!"