Files
TSYSDevStack/ToolboxStack/output/toolbox-QADocker/build.sh
ReachableCEO ab57e3a3a1 feat: Update toolbox-base and template with latest Docker configurations and documentation
\n- Updated Dockerfiles in both toolbox-base and toolbox-template
- Modified build scripts and docker-compose configurations
- Added new audit tools and documentation files
- Created new toolbox-DocStack and toolbox-QADocker implementations
- Updated README and maintenance documentation
2025-10-31 12:46:36 -05:00

198 lines
6.5 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
# Security: Validate input parameters to prevent command injection
sanitized_input() {
local input="$1"
# Check for potentially dangerous characters/commands
case "$input" in
*[\;\|\&\`\$]*)
echo "Error: Invalid input detected: $input" >&2
exit 1
;;
esac
}
# Validate dependencies
if ! command -v docker &> /dev/null; then
echo "Error: docker is required but not installed." >&2
exit 1
fi
if ! docker buildx version &> /dev/null; then
echo "Error: docker buildx is required but not available." >&2
exit 1
fi
IMAGE_NAME="tsysdevstack-toolboxstack-toolbox-qadocker"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Sanitize user input
USER_ID="${USER_ID_OVERRIDE:-$(id -u)}"
sanitized_input "$USER_ID"
GROUP_ID="${GROUP_ID_OVERRIDE:-$(id -g)}"
sanitized_input "$GROUP_ID"
USERNAME="${USERNAME_OVERRIDE:-toolbox}"
sanitized_input "$USERNAME"
TEA_VERSION="${TEA_VERSION_OVERRIDE:-0.11.1}"
sanitized_input "$TEA_VERSION"
BUILDER_NAME="${BUILDER_NAME:-tsysdevstack-builder}"
sanitized_input "$BUILDER_NAME"
CACHE_DIR="${SCRIPT_DIR}/.build-cache"
TAG="${TAG_OVERRIDE:-dev}"
sanitized_input "$TAG"
RELEASE_TAG="${RELEASE_TAG_OVERRIDE:-release-current}"
sanitized_input "$RELEASE_TAG"
VERSION_TAG="${VERSION_TAG_OVERRIDE:-}"
if [[ -n "$VERSION_TAG" ]]; then
sanitized_input "$VERSION_TAG"
fi
PUSH="${PUSH_OVERRIDE:-false}"
echo "Building ${IMAGE_NAME} with UID=${USER_ID} GID=${GROUP_ID} USERNAME=${USERNAME}"
echo "Primary tag: ${TAG}"
# Ensure builder exists
if ! docker buildx inspect "${BUILDER_NAME}" >/dev/null 2>&1; then
echo "Creating builder: ${BUILDER_NAME}"
if ! docker buildx create --driver docker-container --name "${BUILDER_NAME}" --use >/dev/null; then
echo "Error: Failed to create Docker buildx builder." >&2
exit 1
fi
else
echo "Using existing builder: ${BUILDER_NAME}"
if ! docker buildx use "${BUILDER_NAME}" >/dev/null; then
echo "Error: Failed to use Docker buildx builder." >&2
exit 1
fi
fi
# Ensure cache directory exists
if ! mkdir -p "${CACHE_DIR}"; then
echo "Error: Failed to create cache directory: ${CACHE_DIR}" >&2
exit 1
fi
echo "Starting build..."
BUILD_OUTPUT=$(mktemp)
trap 'rm -f "$BUILD_OUTPUT"' EXIT
# Build the image
if ! docker buildx build \
--builder "${BUILDER_NAME}" \
--load \
--progress=plain \
--build-arg USER_ID="${USER_ID}" \
--build-arg GROUP_ID="${GROUP_ID}" \
--build-arg USERNAME="${USERNAME}" \
--build-arg TEA_VERSION="${TEA_VERSION}" \
--cache-from "type=local,src=${CACHE_DIR}" \
--cache-to "type=local,dest=${CACHE_DIR},mode=max" \
--tag "${IMAGE_NAME}:${TAG}" \
"${SCRIPT_DIR}" 2>&1 | tee "${BUILD_OUTPUT}"; then
echo "Error: Docker build failed. Check output above for details." >&2
exit 1
fi
echo "Build completed successfully."
# Run comprehensive verification tests
echo "Running comprehensive verification tests..."
if ! docker run --rm "${IMAGE_NAME}:${TAG}" zsh -c 'echo "Container starts successfully as $(whoami) user"'; then
echo "Error: Failed to start container with basic test." >&2
exit 1
fi
# Verify core tools are available to toolbox user
echo "Verifying core tools for toolbox user..."
CORE_TOOLS=("zsh" "git" "curl" "jq" "docker" "trivy" "hadolint")
for tool in "${CORE_TOOLS[@]}"; do
if ! docker run --rm "${IMAGE_NAME}:${TAG}" su - toolbox -c "which $tool" >/dev/null 2>&1; then
echo "Error: Core tool '$tool' not found in PATH for toolbox user." >&2
exit 1
fi
done
# Verify Docker QA tools are available to toolbox user
echo "Verifying Docker QA tools for toolbox user..."
QA_TOOLS=("dockerfilelint" "yq")
for tool in "${QA_TOOLS[@]}"; do
if ! docker run --rm "${IMAGE_NAME}:${TAG}" su - toolbox -c "which $tool" >/dev/null 2>&1; then
echo "Error: QA tool '$tool' not found in PATH for toolbox user." >&2
exit 1
fi
done
# Verify Node.js and npm are working properly
echo "Verifying Node.js runtime..."
if ! docker run --rm "${IMAGE_NAME}:${TAG}" su - toolbox -c "node --version && npm --version" >/dev/null 2>&1; then
echo "Error: Node.js or npm not working properly for toolbox user." >&2
exit 1
fi
# Verify mise is managing tools properly
echo "Verifying mise runtime management..."
if ! docker run --rm "${IMAGE_NAME}:${TAG}" su - toolbox -c "mise --version" >/dev/null 2>&1; then
echo "Error: Mise not available for toolbox user." >&2
exit 1
fi
# Verify aqua is managing tools properly
echo "Verifying aqua package management..."
if ! docker run --rm "${IMAGE_NAME}:${TAG}" su - toolbox -c "aqua --version" >/dev/null 2>&1; then
echo "Error: Aqua not available for toolbox user." >&2
exit 1
fi
# Final security check: verify container runs as toolbox user
echo "Verifying runtime security model..."
RUNTIME_USER=$(docker run --rm "${IMAGE_NAME}:${TAG}" whoami)
if [ "$RUNTIME_USER" != "toolbox" ]; then
echo "Error: Container is not running as toolbox user. Current user: $RUNTIME_USER" >&2
exit 1
fi
echo "All verifications passed. Security model is correct."
if [[ "${PUSH}" == "true" ]]; then
echo "Pushing ${IMAGE_NAME}:${TAG}"
if ! docker push "${IMAGE_NAME}:${TAG}"; then
echo "Error: Failed to push ${IMAGE_NAME}:${TAG}" >&2
exit 1
fi
if [[ "${TAG}" == "dev" && -n "${VERSION_TAG}" ]]; then
if ! docker tag "${IMAGE_NAME}:${TAG}" "${IMAGE_NAME}:${VERSION_TAG}"; then
echo "Error: Failed to tag ${IMAGE_NAME}:${VERSION_TAG}" >&2
exit 1
fi
echo "Pushing ${IMAGE_NAME}:${VERSION_TAG}"
if ! docker push "${IMAGE_NAME}:${VERSION_TAG}"; then
echo "Error: Failed to push ${IMAGE_NAME}:${VERSION_TAG}" >&2
exit 1
fi
fi
if [[ "${TAG}" == "dev" ]]; then
if ! docker tag "${IMAGE_NAME}:${TAG}" "${IMAGE_NAME}:${RELEASE_TAG}"; then
echo "Error: Failed to tag ${IMAGE_NAME}:${RELEASE_TAG}" >&2
exit 1
fi
echo "Pushing ${IMAGE_NAME}:${RELEASE_TAG}"
if ! docker push "${IMAGE_NAME}:${RELEASE_TAG}"; then
echo "Error: Failed to push ${IMAGE_NAME}:${RELEASE_TAG}" >&2
exit 1
fi
fi
fi
# Run security scan if TRIVY is available
if command -v trivy &> /dev/null; then
echo "Running security scan with Trivy..."
trivy image --exit-code 0 --severity HIGH,CRITICAL "${IMAGE_NAME}:${TAG}"
else
echo "Trivy not found. Install Trivy to perform security scanning."
fi
echo "Build process completed successfully with all verifications and security checks."