chore(filesystem): reflect major filesystem restructuring changes
- Renamed DocStack to dockstack - Transformed toolbox-template into toolbox-qadocker with new functionality - Removed NewToolbox.sh script - Updated PROMPT and configuration files across all toolboxes - Consolidated audit and testing scripts - Updated QWEN.md to reflect new filesystem structure as authoritative source - Merged PROMPT content into QWEN.md as requested Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> The filesystem structure has been intentionally restructured and is now the authoritative source of truth for the project organization.
This commit is contained in:
@@ -1,52 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
if [[ $# -ne 1 ]]; then
|
||||
echo "Usage: $0 <toolbox-name>" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
RAW_NAME="$1"
|
||||
if [[ "${RAW_NAME}" == toolbox-* ]]; then
|
||||
TOOLBOX_NAME="${RAW_NAME}"
|
||||
else
|
||||
TOOLBOX_NAME="toolbox-${RAW_NAME}"
|
||||
fi
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
TEMPLATE_DIR="${SCRIPT_DIR}/toolbox-template"
|
||||
TARGET_DIR="${SCRIPT_DIR}/${TOOLBOX_NAME}"
|
||||
|
||||
if [[ ! -d "${TEMPLATE_DIR}" ]]; then
|
||||
echo "Error: template directory not found at ${TEMPLATE_DIR}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -e "${TARGET_DIR}" ]]; then
|
||||
echo "Error: ${TARGET_DIR} already exists" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cp -R "${TEMPLATE_DIR}" "${TARGET_DIR}"
|
||||
|
||||
python3 - "$TARGET_DIR" "$TOOLBOX_NAME" <<'PY'
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
base = Path(sys.argv[1])
|
||||
toolbox_name = sys.argv[2]
|
||||
|
||||
for path in base.rglob("*"):
|
||||
if not path.is_file():
|
||||
continue
|
||||
text = path.read_text()
|
||||
updated = text.replace("{{toolbox_name}}", toolbox_name)
|
||||
if updated != text:
|
||||
path.write_text(updated)
|
||||
PY
|
||||
|
||||
echo "Created ${TARGET_DIR} from template."
|
||||
echo "Next steps:"
|
||||
echo " 1) Edit ${TARGET_DIR}/SEED once to describe the toolbox goals."
|
||||
echo " 2) Load ${TARGET_DIR}/PROMPT in Codex; it will instruct you to read SEED and proceed."
|
||||
@@ -1,19 +0,0 @@
|
||||
You are Codex helping with TSYSDevStack ToolboxStack deliverables.
|
||||
|
||||
Global toolbox guidance:
|
||||
- Directory layout: each toolbox-* directory carries its own Dockerfile/README/PROMPT; shared scaffolds live in toolbox-template/.devcontainer and docker-compose.yml.
|
||||
- Use ./NewToolbox.sh <name> to scaffold a new toolbox-* directory from toolbox-template.
|
||||
- Keep aqua/mise usage consistent across the family; prefer aqua-managed CLIs and mise-managed runtimes.
|
||||
- Reference toolbox-template when bootstrapping a new toolbox. Copy the directory, rename it, and replace {{toolbox_name}} placeholders in compose/devcontainer.
|
||||
- Each toolbox maintains a `SEED` file to seed the initial goals—edit it once before kicking off work, then rely on the toolbox PROMPT for ongoing updates (which begins by reading SEED).
|
||||
- Default build workflow: `./build.sh` produces a `:dev` tag; `./release.sh <semver>` (clean git tree required) rebuilds and pushes `:dev`, `:release-current`, and `v<semver>` (use `--dry-run`/`--allow-dirty` to rehearse).
|
||||
- Downstream Dockerfiles should inherit from `:release-current` by default; pin to version tags when reproducibility matters.
|
||||
|
||||
Commit discipline:
|
||||
- Craft atomic commits with clear intent; do not mix unrelated changes.
|
||||
- Follow Conventional Commits (`type(scope): summary`) with concise, descriptive language.
|
||||
- Commit frequently as features evolve, keeping diffs reviewable.
|
||||
- After documentation/tooling changes, run ./build.sh to ensure the image builds, then push once the build succeeds.
|
||||
- Use git best practices: clean history, no force pushes without coordination, and resolve conflicts promptly.
|
||||
|
||||
Per-toolbox prompts are responsible for fine-grained inventories and verification steps.
|
||||
@@ -1,25 +1,14 @@
|
||||
{
|
||||
"name": "TSYSDevStack Docker QA Toolbox",
|
||||
"name": "TSYSDevStack {{toolbox_name}}",
|
||||
"dockerComposeFile": [
|
||||
"../docker-compose.yml"
|
||||
],
|
||||
"service": "toolbox-qadocker",
|
||||
"service": "{{toolbox_name}}",
|
||||
"workspaceFolder": "/workspace",
|
||||
"remoteUser": "toolbox",
|
||||
"runServices": [
|
||||
"toolbox-qadocker"
|
||||
"{{toolbox_name}}"
|
||||
],
|
||||
"overrideCommand": false,
|
||||
"postCreateCommand": "zsh -lc 'echo \"Docker QA environment ready. Available tools: trivy, hadolint, docker, dockerfilelint\"'",
|
||||
"mounts": [
|
||||
"source=/var/run/docker.sock,target=/var/run/docker.sock,type=bind"
|
||||
],
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": [
|
||||
"ms-azuretools.vscode-docker",
|
||||
"hadolint.hadolint"
|
||||
]
|
||||
}
|
||||
}
|
||||
"postCreateCommand": "zsh -lc 'starship --version >/dev/null'"
|
||||
}
|
||||
@@ -1,101 +1,120 @@
|
||||
# 🛡️ Docker QA Toolbox Audit Checklist
|
||||
# 🧰 Toolbox Template Audit Checklist
|
||||
|
||||
This checklist ensures the Docker QA toolbox meets all security, functionality, and maintainability requirements for Docker image auditing.
|
||||
This checklist ensures the toolbox-template provides a solid foundation for creating new toolboxes that extend from toolbox-base.
|
||||
|
||||
## 🔒 Security Audit
|
||||
## 🏗️ Structure Audit
|
||||
|
||||
- [ ] All packages installed with specific versions (no `latest` tags)
|
||||
- [ ] All external downloads verified with checksums/signatures
|
||||
- [ ] No root access possible at runtime (sudo removed)
|
||||
- [ ] Non-root user properly configured with UID/GID mapping
|
||||
- [ ] No hardcoded secrets or credentials in image
|
||||
- [ ] Minimal attack surface (unnecessary packages removed)
|
||||
- [ ] Regular security scanning implemented (Trivy integration)
|
||||
- [ ] Base image (Ubuntu) regularly updated
|
||||
- [ ] All aqua packages verified through registry
|
||||
- [ ] Docker socket access properly secured
|
||||
- [ ] Template Dockerfile properly extends from toolbox-base:release-current
|
||||
- [ ] Template Dockerfile follows best practices for extension
|
||||
- [ ] Template docker-compose.yml properly inherits from base configuration
|
||||
- [ ] Template build.sh script properly wraps docker build with UID/GID mapping
|
||||
- [ ] Template run.sh script properly manages container lifecycle
|
||||
- [ ] Template devcontainer.json properly references base configuration
|
||||
- [ ] Template SEED file properly defines extension objectives
|
||||
- [ ] Template PROMPT file properly guides contributors
|
||||
- [ ] Template README.md properly documents usage and customization
|
||||
- [ ] Template aqua.yaml properly extends from base tooling
|
||||
|
||||
## 🛠️ Functionality Audit
|
||||
## 🔧 Consistency Audit
|
||||
|
||||
- [ ] All Docker QA tools properly installed and accessible
|
||||
- [ ] All tools respond to `--version` flag correctly
|
||||
- [ ] Aqua proxy mechanism properly configured
|
||||
- [ ] Docker access to host daemon working correctly
|
||||
- [ ] Security scanning tools (Trivy, Hadolint) functional
|
||||
- [ ] Dockerfile linting tools working properly
|
||||
- [ ] Shell configurations properly set up (zsh, bash)
|
||||
- [ ] Environment variables properly configured
|
||||
- [ ] PATH correctly set for all tools
|
||||
- [ ] User home directory properly configured
|
||||
- [ ] Workspace directory properly set up with correct permissions
|
||||
- [ ] Template inherits all base security practices
|
||||
- [ ] Template follows same build process patterns as base
|
||||
- [ ] Template uses same user model as base (non-root with UID/GID mapping)
|
||||
- [ ] Template workspace mounting consistent with base
|
||||
- [ ] Template runtime behavior consistent with base
|
||||
- [ ] Template error handling consistent with base
|
||||
- [ ] Template documentation style consistent with base
|
||||
- [ ] Template testing approach consistent with base
|
||||
- [ ] Template customization points clearly defined
|
||||
- [ ] Template extension patterns well-documented
|
||||
|
||||
## 🏗️ Build Process Audit
|
||||
## 🛡️ Security Audit
|
||||
|
||||
- [ ] Dockerfile follows best practices
|
||||
- [ ] Multi-stage build optimizations implemented
|
||||
- [ ] Build cache properly utilized
|
||||
- [ ] Build arguments properly validated
|
||||
- [ ] Error handling in build scripts comprehensive
|
||||
- [ ] Build verification tests implemented
|
||||
- [ ] Image tagging strategy consistent
|
||||
- [ ] Release process properly documented
|
||||
- [ ] Template maintains all base security guarantees
|
||||
- [ ] Template doesn't introduce security vulnerabilities
|
||||
- [ ] Template doesn't weaken base security model
|
||||
- [ ] Template properly validates user inputs
|
||||
- [ ] Template properly handles file permissions
|
||||
- [ ] Template doesn't expose additional attack surfaces
|
||||
- [ ] Template properly manages secrets/configuration
|
||||
- [ ] Template follows principle of least privilege
|
||||
- [ ] Template properly isolates user processes
|
||||
- [ ] Template maintains non-root execution model
|
||||
|
||||
## 🧪 Testing Audit
|
||||
|
||||
- [ ] Automated testing of all installed tools
|
||||
- [ ] Integration tests for Docker daemon access
|
||||
- [ ] Regression tests for known issues
|
||||
- [ ] Security scanning of built images
|
||||
- [ ] Performance benchmarks
|
||||
- [ ] Security scanning during build
|
||||
- [ ] Template includes testing framework
|
||||
- [ ] Template tests verify proper extension from base
|
||||
- [ ] Template tests validate added functionality
|
||||
- [ ] Template tests check for regression issues
|
||||
- [ ] Template tests cover error conditions
|
||||
- [ ] Template tests verify security properties
|
||||
- [ ] Template tests run automatically during build
|
||||
- [ ] Template tests provide clear failure diagnostics
|
||||
- [ ] Template tests cover all customization points
|
||||
- [ ] Template tests align with base testing philosophy
|
||||
|
||||
## 📚 Documentation Audit
|
||||
|
||||
- [ ] README.md accurately reflects current state
|
||||
- [ ] All tools properly documented
|
||||
- [ ] Usage examples for Docker QA workflows provided
|
||||
- [ ] Troubleshooting guide included
|
||||
- [ ] Contribution guidelines clear
|
||||
- [ ] License information up to date
|
||||
- [ ] Template README.md clearly explains purpose and usage
|
||||
- [ ] Template README.md properly documents customization options
|
||||
- [ ] Template README.md links to base documentation
|
||||
- [ ] Template README.md includes quick start guide
|
||||
- [ ] Template README.md covers troubleshooting
|
||||
- [ ] Template README.md explains extension patterns
|
||||
- [ ] Template README.md documents versioning strategy
|
||||
- [ ] Template README.md covers maintenance procedures
|
||||
- [ ] Template README.md explains collaboration guidelines
|
||||
- [ ] Template README.md maintains consistent style with base
|
||||
|
||||
## 🔄 Maintenance Audit
|
||||
|
||||
- [ ] Dependency update strategy defined
|
||||
- [ ] Version pinning strategy consistent
|
||||
- [ ] Backward compatibility maintained
|
||||
- [ ] Deprecation policy established
|
||||
- [ ] Release notes properly maintained
|
||||
- [ ] Issue tracking process defined
|
||||
- [ ] Template properly tracks base image updates
|
||||
- [ ] Template provides clear upgrade paths
|
||||
- [ ] Template maintains backward compatibility
|
||||
- [ ] Template follows same release cadence as base
|
||||
- [ ] Template properly handles dependency updates
|
||||
- [ ] Template includes update automation where appropriate
|
||||
- [ ] Template documents breaking changes
|
||||
- [ ] Template provides migration guides when needed
|
||||
- [ ] Template follows same versioning scheme as base
|
||||
- [ ] Template maintains consistent issue tracking
|
||||
|
||||
## 🎯 Specialized QA Features Audit
|
||||
## 🎯 Usability Audit
|
||||
|
||||
- [ ] Trivy vulnerability scanning functional
|
||||
- [ ] Hadolint Dockerfile linting operational
|
||||
- [ ] Dockerfilelint working correctly
|
||||
- [ ] Docker history/inspect tools accessible
|
||||
- [ ] Image layer analysis capabilities present
|
||||
- [ ] Best practices validation tools available
|
||||
|
||||
## 📈 Performance Audit
|
||||
|
||||
- [ ] Image size optimized
|
||||
- [ ] Startup time acceptable
|
||||
- [ ] Memory footprint reasonable
|
||||
- [ ] CPU usage within expected bounds
|
||||
- [ ] Docker scanning performance adequate
|
||||
- [ ] Template is easy to copy and customize
|
||||
- [ ] Template provides clear extension points
|
||||
- [ ] Template includes helpful examples
|
||||
- [ ] Template reduces boilerplate code
|
||||
- [ ] Template provides sensible defaults
|
||||
- [ ] Template includes proper error messages
|
||||
- [ ] Template supports common customization patterns
|
||||
- [ ] Template includes helpful documentation
|
||||
- [ ] Template follows intuitive naming conventions
|
||||
- [ ] Template minimizes configuration complexity
|
||||
|
||||
## 🌐 Compatibility Audit
|
||||
|
||||
- [ ] Works on all supported platforms
|
||||
- [ ] Docker daemon access functional across platforms
|
||||
- [ ] Backward compatibility with Docker versions maintained
|
||||
- [ ] Integration with common CI/CD tools verified
|
||||
- [ ] Template works with all supported platforms
|
||||
- [ ] Template maintains cross-platform consistency
|
||||
- [ ] Template integrates well with base tooling
|
||||
- [ ] Template supports common development workflows
|
||||
- [ ] Template handles various project structures
|
||||
- [ ] Template works with popular IDEs/editors
|
||||
- [ ] Template supports CI/CD integration
|
||||
- [ ] Template compatible with common deployment methods
|
||||
- [ ] Template supports popular version control systems
|
||||
- [ ] Template integrates with common development tools
|
||||
|
||||
## 🧹 Cleanup Audit
|
||||
## 🧹 Cleanliness Audit
|
||||
|
||||
- [ ] Temporary files properly removed
|
||||
- [ ] Build artifacts cleaned up
|
||||
- [ ] Cache directories properly managed
|
||||
- [ ] Log files rotated or removed
|
||||
- [ ] Orphaned processes prevented
|
||||
- [ ] Resource leaks eliminated
|
||||
- [ ] Template includes no unnecessary files
|
||||
- [ ] Template follows consistent file organization
|
||||
- [ ] Template includes proper .gitignore
|
||||
- [ ] Template avoids duplicating base functionality
|
||||
- [ ] Template includes proper licensing information
|
||||
- [ ] Template maintains clean directory structure
|
||||
- [ ] Template includes appropriate comments/documentation
|
||||
- [ ] Template avoids hardcoded values where possible
|
||||
- [ ] Template follows consistent naming conventions
|
||||
- [ ] Template includes proper attribution where needed
|
||||
@@ -1,195 +1,77 @@
|
||||
# Multi-stage approach to minimize final image size and attack surface
|
||||
FROM ubuntu:24.04 AS installer
|
||||
|
||||
ARG USER_ID=1000
|
||||
ARG GROUP_ID=1000
|
||||
ARG USERNAME=toolbox
|
||||
ARG TEA_VERSION=0.11.1
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
# ROOT STAGE 1: System package installation for Docker QA tools only
|
||||
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
|
||||
--mount=type=cache,target=/var/lib/apt/lists,sharing=locked \
|
||||
apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
ca-certificates \
|
||||
curl \
|
||||
git \
|
||||
jq \
|
||||
bc \
|
||||
locales \
|
||||
openssh-client \
|
||||
zsh \
|
||||
unzip \
|
||||
zip \
|
||||
python3 \
|
||||
python3-pip \
|
||||
wget \
|
||||
# Docker and container tools \
|
||||
docker.io \
|
||||
# Security scanning tools \
|
||||
clamav \
|
||||
# Static analysis tools \
|
||||
shellcheck \
|
||||
# JSON/YAML tools \
|
||||
yq \
|
||||
# Development tools for custom scripts \
|
||||
make \
|
||||
gcc \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# ROOT: Configure locale
|
||||
RUN locale-gen en_US.UTF-8
|
||||
ENV LANG=en_US.UTF-8 \
|
||||
LANGUAGE=en_US:en \
|
||||
LC_ALL=en_US.UTF-8
|
||||
|
||||
# ROOT: Create non-root user with matching UID/GID for host mapping
|
||||
RUN if getent passwd "${USER_ID}" >/dev/null; then \
|
||||
existing_user="$(getent passwd "${USER_ID}" | cut -d: -f1)"; \
|
||||
userdel --remove "${existing_user}"; \
|
||||
fi \
|
||||
&& if ! getent group "${GROUP_ID}" >/dev/null; then \
|
||||
groupadd --gid "${GROUP_ID}" "${USERNAME}"; \
|
||||
fi \
|
||||
&& useradd --uid "${USER_ID}" --gid "${GROUP_ID}" --shell /usr/bin/zsh --create-home "${USERNAME}"
|
||||
|
||||
# ROOT: Set up toolbox user home directory with proper permissions
|
||||
RUN chown -R "${USER_ID}:${GROUP_ID}" "/home/${USERNAME}"
|
||||
|
||||
# SWITCH TO NON-ROOT USER: All further operations as toolbox user
|
||||
USER ${USERNAME}
|
||||
WORKDIR /home/${USERNAME}
|
||||
|
||||
# NON-ROOT: Install mise runtime manager for toolbox user
|
||||
RUN curl -sSfL https://mise.jdx.dev/install.sh | sh
|
||||
|
||||
# NON-ROOT: Update PATH for mise tools
|
||||
ENV PATH=/home/${USERNAME}/.local/bin:/home/${USERNAME}/.local/share/mise/shims:$PATH
|
||||
|
||||
# NON-ROOT: Install Node.js via mise as toolbox user
|
||||
RUN mise install node@22.13.0 && mise use -g node@22.13.0
|
||||
|
||||
# NON-ROOT: Install aqua package manager for toolbox user
|
||||
RUN curl -sSfL https://raw.githubusercontent.com/aquaproj/aqua-installer/v2.3.1/aqua-installer > /tmp/aqua-installer.sh && \
|
||||
chmod +x /tmp/aqua-installer.sh && \
|
||||
AQUA_ROOT_DIR=/home/${USERNAME}/.local/share/aquaproj-aqua /tmp/aqua-installer.sh && \
|
||||
rm /tmp/aqua-installer.sh
|
||||
|
||||
# NON-ROOT: Update PATH for aqua tools
|
||||
ENV PATH=/home/${USERNAME}/.local/share/aquaproj-aqua/bin:$PATH
|
||||
|
||||
# NON-ROOT: Install Oh My Zsh
|
||||
RUN git clone --depth=1 https://github.com/ohmyzsh/ohmyzsh.git ~/.oh-my-zsh
|
||||
|
||||
# NON-ROOT: Configure shells (zsh, bash) with all customizations
|
||||
RUN cp ~/.oh-my-zsh/templates/zshrc.zsh-template ~/.zshrc \
|
||||
&& sed -i "s/^plugins=(git)$/plugins=(git docker docker-compose)/" ~/.zshrc \
|
||||
&& printf "\nexport PATH=\"\$HOME/.local/share/aquaproj-aqua/bin:\$HOME/.local/share/mise/shims:\$HOME/.local/bin:\$PATH\"\n" >> ~/.zshrc \
|
||||
&& printf "\n# Starship prompt\neval \"\$(starship init zsh)\"\n" >> ~/.zshrc \
|
||||
&& printf "\n# mise runtime manager\neval \"\$(mise activate zsh)\"\n" >> ~/.zshrc \
|
||||
&& printf "\n# direnv\nexport DIRENV_LOG_FORMAT=\"\"\neval \"\$(direnv hook zsh)\"\n" >> ~/.zshrc \
|
||||
&& printf "\nexport AQUA_GLOBAL_CONFIG=\"\$HOME/.config/aquaproj-aqua/aqua.yaml\"\n" >> ~/.bashrc \
|
||||
&& printf "\n# mise runtime manager (bash)\neval \"\$(mise activate bash)\"\n" >> ~/.bashrc \
|
||||
&& printf "\n# direnv\nexport DIRENV_LOG_FORMAT=\"\"\neval \"\$(direnv hook bash)\"\n" >> ~/.bashrc
|
||||
|
||||
# NON-ROOT: Install aqua packages for Docker QA tools
|
||||
RUN mkdir -p ~/.config/aquaproj-aqua \
|
||||
&& echo "version: 1.0.0\nregistries:\n - type: standard\n ref: v4.431.0\npackages:\n - name: aquasecurity/trivy@v0.54.1\n - name: hadolint/hadolint@v2.14.0\n - name: github/gh@v2.69.0\n - name: dandavison/delta@0.18.2\n - name: ajeetdsouza/zoxide@v0.9.8\n - name: mikefarah/yq@v4.48.1\n - name: direnv/direnv@v2.37.1" > ~/.config/aquaproj-aqua/aqua.yaml \
|
||||
&& aqua install \
|
||||
&& aqua install --all
|
||||
|
||||
# NON-ROOT: Install additional Docker QA tools via npm
|
||||
RUN mise exec -- npm install -g dockerfilelint@latest && mise reshim
|
||||
|
||||
# NON-ROOT: Install additional Python-based tools using --break-system-packages
|
||||
RUN pip3 install --break-system-packages docker-image-py
|
||||
|
||||
# ROOT: Set up workspace directory
|
||||
USER root
|
||||
RUN mkdir -p /workspace && chown "${USER_ID}:${GROUP_ID}" /workspace
|
||||
USER ${USERNAME}
|
||||
|
||||
# NON-ROOT: Verify all tools are accessible during build
|
||||
RUN bash -c 'command -v docker && command -v dockerfilelint' \
|
||||
&& bash -c 'docker --version && node --version && npm --version'
|
||||
|
||||
# NON-ROOT: Final mise reshim to ensure all tools are properly linked
|
||||
RUN mise reshim
|
||||
|
||||
# FINAL STAGE: Copy completed setup to minimize image and enhance security
|
||||
# Use Ubuntu 24.04 as base for the QA Docker toolbox
|
||||
FROM ubuntu:24.04
|
||||
|
||||
# Set build arguments (these can be overridden at build time)
|
||||
ARG USER_ID=1000
|
||||
ARG GROUP_ID=1000
|
||||
ARG USERNAME=toolbox
|
||||
ARG TEA_VERSION=0.11.1
|
||||
|
||||
# Set up environment and install essential packages
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
# ROOT: Install minimal runtime dependencies only
|
||||
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
|
||||
--mount=type=cache,target=/var/lib/apt/lists,sharing=locked \
|
||||
apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
ca-certificates \
|
||||
curl \
|
||||
git \
|
||||
jq \
|
||||
bc \
|
||||
locales \
|
||||
openssh-client \
|
||||
zsh \
|
||||
unzip \
|
||||
zip \
|
||||
python3 \
|
||||
docker.io \
|
||||
&& apt-get clean \
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
ca-certificates \
|
||||
curl \
|
||||
gnupg \
|
||||
lsb-release \
|
||||
git \
|
||||
unzip \
|
||||
wget \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# ROOT: Restore system-wide configurations
|
||||
RUN locale-gen en_US.UTF-8
|
||||
ENV LANG=en_US.UTF-8 \
|
||||
LANGUAGE=en_US:en \
|
||||
LC_ALL=en_US.UTF-8
|
||||
# Install Docker CLI
|
||||
RUN install -m 0755 -d /etc/apt/keyrings \
|
||||
&& curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg \
|
||||
&& chmod a+r /etc/apt/keyrings/docker.gpg \
|
||||
&& echo \
|
||||
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
|
||||
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
|
||||
tee /etc/apt/sources.list.d/docker.list > /dev/null \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y --no-install-recommends docker-ce-cli \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# ROOT: Create non-root user with matching UID/GID for host mapping
|
||||
RUN if getent passwd "${USER_ID}" >/dev/null; then \
|
||||
existing_user="$(getent passwd "${USER_ID}" | cut -d: -f1)"; \
|
||||
userdel --remove "${existing_user}"; \
|
||||
fi \
|
||||
&& if ! getent group "${GROUP_ID}" >/dev/null; then \
|
||||
# Install hadolint for Dockerfile linting
|
||||
RUN wget -O /usr/bin/hadolint https://github.com/hadolint/hadolint/releases/download/v2.12.0/hadolint-Linux-x86_64 \
|
||||
&& chmod +x /usr/bin/hadolint
|
||||
|
||||
# Install dive for exploring Docker image layers
|
||||
RUN wget -O /tmp/dive_0.10.0_linux_amd64.deb https://github.com/wagoodman/dive/releases/download/v0.10.0/dive_0.10.0_linux_amd64.deb \
|
||||
&& dpkg -i /tmp/dive_0.10.0_linux_amd64.deb \
|
||||
&& rm /tmp/dive_0.10.0_linux_amd64.deb
|
||||
|
||||
# Create non-root user
|
||||
RUN if ! getent group "${USERNAME}" >/dev/null; then \
|
||||
groupadd --gid "${GROUP_ID}" "${USERNAME}"; \
|
||||
fi \
|
||||
&& useradd --uid "${USER_ID}" --gid "${GROUP_ID}" --shell /usr/bin/zsh --create-home "${USERNAME}"
|
||||
fi && \
|
||||
if ! id "${USERNAME}" >/dev/null 2>&1; then \
|
||||
useradd --uid "${USER_ID}" --gid "${GROUP_ID}" --shell /bin/bash --create-home "${USERNAME}"; \
|
||||
fi
|
||||
|
||||
# ROOT: Copy the complete user environment from the installer stage
|
||||
COPY --from=installer --chown=${USER_ID}:${GROUP_ID} /home/${USERNAME} /home/${USERNAME}
|
||||
# Install aqua for package management
|
||||
RUN curl -sSfL https://raw.githubusercontent.com/aquaproj/aqua-installer/v3.0.0/aqua-installer | bash -s -- -v v3.0.0 \
|
||||
&& mv /usr/local/bin/aqua /usr/local/bin/aqua-tmp \
|
||||
&& mkdir -p /root/.local/share/aquaproj-aqua/bin \
|
||||
&& mv /usr/local/bin/aqua-tmp /root/.local/share/aquaproj-aqua/bin/aqua \
|
||||
&& ln -s /root/.local/share/aquaproj-aqua/bin/aqua /usr/local/bin/aqua
|
||||
|
||||
# ROOT: Create workspace directory
|
||||
RUN mkdir -p /workspace && chown "${USER_ID}:${GROUP_ID}" /workspace
|
||||
# Copy the aqua.yaml configuration for the non-root user and install packages
|
||||
COPY aqua.yaml /tmp/aqua.yaml
|
||||
RUN chown "${USER_ID}:${GROUP_ID}" /tmp/aqua.yaml \
|
||||
&& mkdir -p /home/${USERNAME}/.config/aquaproj-aqua \
|
||||
&& chown "${USER_ID}:${GROUP_ID}" /home/${USERNAME}/.config/aquaproj-aqua \
|
||||
&& su - "${USERNAME}" -c 'cp /tmp/aqua.yaml /home/${USERNAME}/.config/aquaproj-aqua/aqua.yaml' \
|
||||
&& su - "${USERNAME}" -c 'AQUA_GLOBAL_CONFIG=/home/${USERNAME}/.config/aquaproj-aqua/aqua.yaml aqua install'
|
||||
|
||||
# ROOT: Install system-wide tools (tea and starship) which were in the source image
|
||||
RUN curl -fsSL "https://dl.gitea.io/tea/${TEA_VERSION}/tea-${TEA_VERSION}-linux-amd64" -o /tmp/tea \
|
||||
&& curl -fsSL "https://dl.gitea.io/tea/${TEA_VERSION}/tea-${TEA_VERSION}-linux-amd64.sha256" -o /tmp/tea.sha256 \
|
||||
&& sed -n 's/ .*//p' /tmp/tea.sha256 | awk '{print $1 " /tmp/tea"}' | sha256sum -c - \
|
||||
&& install -m 0755 /tmp/tea /usr/local/bin/tea \
|
||||
&& rm -f /tmp/tea /tmp/tea.sha256
|
||||
# Prepare workspace directory with appropriate ownership
|
||||
RUN mkdir -p /workspace \
|
||||
&& chown "${USER_ID}:${GROUP_ID}" /workspace
|
||||
|
||||
RUN curl -fsSL https://starship.rs/install.sh | sh -s -- -y -b /usr/local/bin
|
||||
|
||||
# ROOT: Security hardening - remove sudo if present
|
||||
# Remove sudo to ensure no root escalation is possible at runtime
|
||||
RUN apt-get remove -y sudo 2>/dev/null || true && apt-get autoremove -y 2>/dev/null || true && rm -rf /var/lib/apt/lists/* 2>/dev/null || true
|
||||
|
||||
# ROOT: Final environment variables
|
||||
ENV PATH=/home/${USERNAME}/.local/share/aquaproj-aqua/bin:/home/${USERNAME}/.local/share/mise/shims:/home/${USERNAME}/.local/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin
|
||||
ENV SHELL=/usr/bin/zsh \
|
||||
AQUA_GLOBAL_CONFIG=/home/${USERNAME}/.config/aquaproj-aqua/aqua.yaml
|
||||
ENV PATH=/root/.local/share/aquaproj-aqua/bin:/home/${USERNAME}/.local/share/aquaproj-aqua/bin:/usr/local/bin:${PATH}
|
||||
|
||||
# FINAL USER: Switch to toolbox user for runtime
|
||||
USER ${USERNAME}
|
||||
WORKDIR /workspace
|
||||
USER ${USERNAME}
|
||||
|
||||
CMD ["/usr/bin/zsh"]
|
||||
CMD ["/bin/bash"]
|
||||
@@ -1,34 +1,27 @@
|
||||
# Docker QA Toolbox Prompt
|
||||
You are Codex, collaborating with a human on the TSYSDevStack ToolboxStack project.
|
||||
|
||||
You are an AI assistant working inside the Docker QA Toolbox container. Your purpose is to assist with Docker image auditing, security scanning, and quality assurance.
|
||||
- Seed context:
|
||||
- `SEED` captures the initial scope. Edit it once to define goals, then treat it as read-only unless the high-level objectives change.
|
||||
- Start each session by reading it (`cat SEED`) and summarize progress or adjustments here in PROMPT.
|
||||
|
||||
## Your Environment
|
||||
- You're running as the 'toolbox' user with the same UID/GID as the host user
|
||||
- You have access to the Docker daemon via the mounted socket
|
||||
- You're in a bash shell with access to various Docker auditing tools
|
||||
Context snapshot ({{toolbox_name}}):
|
||||
- Working directory: artifacts/ToolboxStack/{{toolbox_name}}
|
||||
- Image: tsysdevstack-toolboxstack-{{toolbox_name}} (extends from tsysdevstack-toolboxstack-toolbox-base:release-current)
|
||||
- Container user: toolbox (non-root, UID/GID mapped to host)
|
||||
- Mounted workspace: current repo at /workspace (rw)
|
||||
|
||||
## Your Capabilities
|
||||
1. Scan Docker images for vulnerabilities using Trivy
|
||||
2. Lint Dockerfiles using Hadolint and dockerfilelint
|
||||
3. Analyze Docker image layers and composition
|
||||
4. Validate Docker best practices
|
||||
5. Perform security audits of container images
|
||||
6. Generate reports on Docker image quality
|
||||
Current state:
|
||||
- Extends from the standard toolbox-base image, inheriting all base tooling (shells, CLIs, package managers).
|
||||
- aqua packages are baked into the base image during the build process for consistency, reproducibility and performance.
|
||||
- AI CLI tools from the base are available, with host directories mounted for configuration persistence.
|
||||
- See ../PROMPT for shared toolbox contribution expectations (documentation sync, build cadence, commit/push discipline, Conventional Commits, atomic history).
|
||||
|
||||
## Common Commands
|
||||
- `trivy image <image-name>` - Scan an image for vulnerabilities
|
||||
- `hadolint <Dockerfile>` - Lint a Dockerfile against best practices
|
||||
- `dockerfilelint <Dockerfile>` - Additional Dockerfile linting
|
||||
- `docker history <image-name>` - Show image layer history
|
||||
- `docker inspect <image-name>` - Show image metadata
|
||||
- `docker run --rm -it <image-name> /bin/sh` - Inspect image contents interactively
|
||||
Collaboration checklist:
|
||||
1. Translate SEED goals into concrete tooling decisions; mirror outcomes in README.md and this PROMPT (do not rewrite SEED unless the scope resets).
|
||||
2. Prefer aqua-managed CLIs and mise-managed runtimes for reproducibility.
|
||||
3. After each tooling change, update README/PROMPT, run ./build.sh, commit (Conventional Commit message, focused diff), and push only once the build succeeds per ../PROMPT.
|
||||
4. Record verification steps (build/test commands) as they are performed.
|
||||
5. Maintain UID/GID mapping and non-root execution.
|
||||
|
||||
## Best Practices to Follow
|
||||
1. Always scan images before deploying to production
|
||||
2. Use multi-stage builds to minimize attack surface
|
||||
3. Run containers as non-root users
|
||||
4. Pin base image versions rather than using 'latest'
|
||||
5. Regularly update base images and packages
|
||||
6. Verify checksums when downloading external binaries
|
||||
|
||||
Remember: The workspace directory is mounted from your host system, so you can analyze Dockerfiles and images from the host.
|
||||
Active focus:
|
||||
- Initialize {{toolbox_name}} using the toolbox-template scaffolding; evolve the Dockerfile/tooling inventory to satisfy the SEED goals.
|
||||
@@ -1,85 +1,107 @@
|
||||
# 🛡️ Docker QA Toolbox
|
||||
# 🧰 TSYSDevStack Toolbox Template
|
||||
|
||||
A specialized development environment for Docker image auditing, security scanning, and quality assurance.
|
||||
Template for creating new toolboxes that extend from the `toolbox-base` image.
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Quick Start
|
||||
|
||||
```bash
|
||||
cd output/toolbox-QADocker
|
||||
./build.sh # build the image with UID/GID matching your host
|
||||
./run.sh up # launch the toolbox-qadocker service in the background
|
||||
docker exec -it tsysdevstack-toolboxstack-toolbox-qadocker zsh
|
||||
1. **Create a new toolbox**
|
||||
```bash
|
||||
cp -r /path/to/toolbox-template /path/to/new-toolbox
|
||||
cd /path/to/new-toolbox
|
||||
```
|
||||
|
||||
2. **Customize the toolbox**
|
||||
- Edit `Dockerfile` to add toolbox-specific tooling
|
||||
- Modify `docker-compose.yml` to adjust service configuration
|
||||
- Update `SEED` to define the toolbox's purpose and goals
|
||||
|
||||
3. **Build the toolbox**
|
||||
```bash
|
||||
./build.sh
|
||||
```
|
||||
|
||||
4. **Start the toolbox**
|
||||
```bash
|
||||
./run.sh up
|
||||
```
|
||||
|
||||
5. **Access the toolbox**
|
||||
```bash
|
||||
docker exec -it tsysdevstack-toolboxstack-{{toolbox_name}} zsh
|
||||
```
|
||||
|
||||
6. **Stop the toolbox**
|
||||
```bash
|
||||
./run.sh down
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🧱 Architecture
|
||||
|
||||
- **Base Image**: Extends from `tsysdevstack-toolboxstack-toolbox-base:release-current`
|
||||
- **User**: Runs as non-root `toolbox` user (UID/GID mapped to host)
|
||||
- **Workspace**: Mounts current directory to `/workspace` (read/write)
|
||||
- **Runtime**: Inherits all tooling from base plus toolbox-specific additions
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ Customization
|
||||
|
||||
### Dockerfile
|
||||
Extend the base image with toolbox-specific tooling:
|
||||
```dockerfile
|
||||
# Extend from the toolbox-base image
|
||||
FROM tsysdevstack-toolboxstack-toolbox-base:release-current
|
||||
|
||||
# Add toolbox-specific packages or configurations
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
specific-package \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
```
|
||||
|
||||
Use `./run.sh down` to stop the container when you are finished.
|
||||
|
||||
## 🧰 Included Tools
|
||||
|
||||
### Security Scanning
|
||||
- **Trivy** - Comprehensive vulnerability scanner for containers and code
|
||||
- **ClamAV** - Antivirus scanner for file system analysis
|
||||
- **Hadolint** - Dockerfile linter for best practices
|
||||
|
||||
### Docker Analysis
|
||||
- **Dockerfilelint** - Node.js-based Dockerfile linter
|
||||
- **Docker** - Docker CLI with access to host Docker daemon via socket
|
||||
- **Docker Buildx** - Docker CLI plugin for extended build capabilities
|
||||
|
||||
### Development Tools
|
||||
- **Git** - Version control system
|
||||
- **Zsh** - Interactive shell with Oh My Zsh framework
|
||||
- **Mise** - Runtime manager for language versions
|
||||
- **Aqua** - CLI tool manager
|
||||
- **YQ** - YAML/JSON processor
|
||||
- **JQ** - JSON processor
|
||||
|
||||
## 📋 QA Workflows
|
||||
|
||||
### Security Scanning
|
||||
```bash
|
||||
# Scan a Docker image with Trivy
|
||||
trivy image <your-image-name>
|
||||
|
||||
# Scan a Dockerfile with Hadolint
|
||||
hadolint Dockerfile
|
||||
|
||||
# Scan a Dockerfile with dockerfilelint
|
||||
dockerfilelint Dockerfile
|
||||
### docker-compose.yml
|
||||
Adjust service configuration for toolbox-specific needs:
|
||||
```yaml
|
||||
services:
|
||||
my-toolbox:
|
||||
# Inherits all base configuration
|
||||
# Add toolbox-specific volumes, ports, etc.
|
||||
volumes:
|
||||
- ./custom-config:/home/toolbox/.config/custom-tool
|
||||
```
|
||||
|
||||
### Image Analysis
|
||||
```bash
|
||||
# Analyze image layers and size
|
||||
docker history <your-image-name>
|
||||
|
||||
# Extract image contents for analysis
|
||||
docker save <your-image-name> -o image.tar
|
||||
tar -xf image.tar
|
||||
### SEED
|
||||
Define the toolbox's purpose and goals:
|
||||
```markdown
|
||||
- Describe what this toolbox should provide (languages, CLIs, workflows)
|
||||
- List required base image modifications or additional mounts
|
||||
- Note verification or testing expectations specific to this toolbox
|
||||
```
|
||||
|
||||
### Best Practices Validation
|
||||
The toolbox includes tools to validate Docker best practices:
|
||||
- Hadolint for Dockerfile best practices
|
||||
- Trivy for security vulnerabilities
|
||||
- Docker's own best practices recommendations
|
||||
---
|
||||
|
||||
## ⚙️ Configuration
|
||||
## 📂 Project Layout
|
||||
|
||||
The toolbox is configured to:
|
||||
- Run as a non-root user with host UID/GID mapping
|
||||
- Access the host Docker daemon via socket mounting
|
||||
- Include both Docker build and runtime analysis tools
|
||||
- Follow security best practices (no sudo, minimal attack surface)
|
||||
| Path | Purpose |
|
||||
|------|---------|
|
||||
| `Dockerfile` | Extends base image with toolbox-specific tooling |
|
||||
| `docker-compose.yml` | Service configuration for the toolbox |
|
||||
| `build.sh` | Wrapper around `docker build` with host UID/GID mapping |
|
||||
| `run.sh` | Helper to bring the service up/down |
|
||||
| `.devcontainer/devcontainer.json` | VS Code remote container definition |
|
||||
| `SEED` | Defines the toolbox's purpose and goals |
|
||||
| `PROMPT` | LLM onboarding prompt for future contributors |
|
||||
|
||||
## 🔐 Security Features
|
||||
---
|
||||
|
||||
- Non-root user execution with UID/GID mapping
|
||||
- Sudo is removed from the final image
|
||||
- Multi-stage build minimizing attack surface
|
||||
- Regular security scanning capabilities
|
||||
## 🤝 Collaboration Notes
|
||||
|
||||
## 🤖 AI Agent
|
||||
This toolbox is maintained by **ToolboxBot**, an AI agent focused on Docker QA tooling.
|
||||
|
||||
## 📄 License
|
||||
See [LICENSE](../LICENSE) for full terms.
|
||||
- Inherits all collaboration policies from `toolbox-base`
|
||||
- Document toolbox-specific additions in `README.md` and `PROMPT`
|
||||
- Update `SEED` only when the high-level objectives change
|
||||
- Prefer aqua/mise for new tooling to keep installations reproducible
|
||||
- Keep documentation synchronized for future contributors
|
||||
@@ -1,26 +1,38 @@
|
||||
# Docker QA Toolbox SEED
|
||||
# Toolbox Template SEED
|
||||
|
||||
## Purpose
|
||||
This toolbox is specifically designed for Docker image auditing, security scanning, and quality assurance. It provides a comprehensive set of tools to analyze, validate, and secure Docker images and Dockerfiles.
|
||||
This SEED file defines the high-level objectives for all toolboxes created from this template.
|
||||
|
||||
## Core Functionality
|
||||
- Security scanning of Docker images using Trivy
|
||||
- Linting of Dockerfiles using Hadolint and dockerfilelint
|
||||
- Analysis of Docker image composition and layers
|
||||
- Validation of Docker best practices
|
||||
- Compliance checking against security standards
|
||||
## 🎯 Goals
|
||||
|
||||
## Target Use Cases
|
||||
- Pre-deployment security scanning of Docker images
|
||||
- Dockerfile quality validation in CI/CD pipelines
|
||||
- Docker image composition analysis
|
||||
- Security audit of existing container images
|
||||
- Verification of container best practices
|
||||
- **Extensibility**: Each toolbox should extend from `toolbox-base` to inherit core tooling
|
||||
- **Consistency**: All toolboxes should follow the same patterns and conventions
|
||||
- **Reproducibility**: Toolbox builds should be deterministic and cache-efficient
|
||||
- **Security**: Toolboxes should run as non-root users with minimal privileges
|
||||
- **Portability**: Toolboxes should work identically across different host environments
|
||||
|
||||
## Key Tools
|
||||
- Trivy: Comprehensive vulnerability scanner
|
||||
- Hadolint: Dockerfile linter for best practices
|
||||
- Dockerfilelint: Additional Dockerfile validation
|
||||
- Docker CLI: Direct access to Docker daemon
|
||||
- Mise: Runtime version management
|
||||
- Aqua: CLI tool management
|
||||
## 🧰 Requirements
|
||||
|
||||
- **Base Image**: Extend from `tsysdevstack-toolboxstack-toolbox-base:release-current`
|
||||
- **User Model**: Run as non-root `toolbox` user (UID/GID mapped to host)
|
||||
- **Workspace**: Mount current directory to `/workspace` (read/write)
|
||||
- **Runtime**: Inherit all base tooling plus toolbox-specific additions
|
||||
- **Configuration**: Preserve user configs/mise toolchains via volume mounts
|
||||
|
||||
## 🛠️ Implementation
|
||||
|
||||
- **Dockerfile**: Extend from base with toolbox-specific tooling
|
||||
- **docker-compose.yml**: Configure service with inherited + custom settings
|
||||
- **build.sh**: Wrapper around `docker build` with UID/GID mapping
|
||||
- **run.sh**: Helper to bring service up/down
|
||||
- **devcontainer.json**: VS Code remote container definition
|
||||
- **SEED**: Define toolbox-specific objectives (this file)
|
||||
- **PROMPT**: LLM onboarding prompt for future contributors
|
||||
|
||||
## ✅ Verification
|
||||
|
||||
- Toolboxes should build without errors
|
||||
- Toolboxes should start and run indefinitely
|
||||
- Toolboxes should be accessible via `docker exec`
|
||||
- Toolboxes should inherit all base tooling
|
||||
- Toolboxes should support toolbox-specific additions
|
||||
- Toolboxes should preserve user configurations across restarts
|
||||
@@ -3,20 +3,22 @@ registries:
|
||||
- type: standard
|
||||
ref: v4.431.0
|
||||
packages:
|
||||
# Docker and container analysis tools
|
||||
- name: aquasecurity/trivy@v0.54.1
|
||||
- name: hadolint/hadolint@v2.14.0
|
||||
|
||||
# GitHub and collaboration tools
|
||||
- name: cli/cli@v2.82.1
|
||||
|
||||
# Environment and runtime management
|
||||
- name: direnv/direnv@v2.37.1
|
||||
# Docker auditing and security tools
|
||||
- name: hadolint/hadolint@v2.12.0
|
||||
- name: aquasecurity/trivy@v0.56.2
|
||||
- name: anchore/grype@v0.84.1
|
||||
- name: docker/docker-bench-security@v1.8.0
|
||||
- name: snyk/snyk@v1.1308.0
|
||||
# General utility tools
|
||||
- name: jesseduffield/lazygit@v0.44.0
|
||||
- name: direnv/direnv@v2.35.0
|
||||
- name: dandavison/delta@0.18.2
|
||||
- name: ajeetdsouza/zoxide@v0.9.8
|
||||
|
||||
# Development and build tools
|
||||
- name: mikefarah/yq@v4.48.0
|
||||
|
||||
# Configuration management
|
||||
- name: twpayne/chezmoi@v2.66.1
|
||||
- name: ajeetdsouza/zoxide@v0.9.6
|
||||
- name: mikefarah/yq@v4.44.3
|
||||
- name: ducaale/xh@v0.22.3
|
||||
- name: rs/curlie@v1.8.6
|
||||
- name: koalaman/shellcheck@v0.10.0
|
||||
- name: mvdan/sh@v3.7.0
|
||||
- name: golangci/golangci-lint@v1.60.3
|
||||
- name: golang/go@go1.23.0
|
||||
- name: cli/cli@v2.57.0
|
||||
@@ -25,7 +25,12 @@ if ! docker buildx version &> /dev/null; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
IMAGE_NAME="tsysdevstack-toolboxstack-toolbox-qadocker"
|
||||
# Get the toolbox name from the directory name (or you can pass it as an argument)
|
||||
TOOLBOX_NAME="${TOOLBOX_NAME_OVERRIDE:-$(basename "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")}"
|
||||
sanitized_input "$TOOLBOX_NAME"
|
||||
# Convert to lowercase and replace any uppercase letters to ensure valid Docker image name
|
||||
IMAGE_NAME_RAW="tsysdevstack-toolboxstack-${TOOLBOX_NAME#toolbox-}"
|
||||
IMAGE_NAME=$(echo "$IMAGE_NAME_RAW" | tr '[:upper:]' '[:lower:]')
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
# Sanitize user input
|
||||
@@ -37,7 +42,7 @@ 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}"
|
||||
BUILDER_NAME="${BUILDER_NAME:-tsysdevstack-toolboxstack-builder}"
|
||||
sanitized_input "$BUILDER_NAME"
|
||||
CACHE_DIR="${SCRIPT_DIR}/.build-cache"
|
||||
TAG="${TAG_OVERRIDE:-dev}"
|
||||
@@ -97,64 +102,36 @@ 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
|
||||
# Run post-build verification
|
||||
echo "Running post-build verification..."
|
||||
if ! docker run --rm "${IMAGE_NAME}:${TAG}" bash -c 'echo "Container starts successfully"'; 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
|
||||
# Verify critical tools for Docker auditing are available
|
||||
echo "Verifying Docker auditing tools..."
|
||||
CRITICAL_TOOLS=("git" "curl" "wget" "docker" "hadolint" "dive" "bash")
|
||||
for tool in "${CRITICAL_TOOLS[@]}"; do
|
||||
if ! docker run --rm "${IMAGE_NAME}:${TAG}" which "$tool" >/dev/null 2>&1; then
|
||||
echo "Error: Critical Docker auditing tool '$tool' not found in PATH." >&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
|
||||
# Verify additional aqua tools for QA are available
|
||||
echo "Verifying QA aqua tools..."
|
||||
AQUA_TOOLS=("lazygit" "direnv" "delta" "zoxide" "yq" "xh" "curlie" "shellcheck" "trivy" "grype" "docker-bench-security")
|
||||
for tool in "${AQUA_TOOLS[@]}"; do
|
||||
if ! docker run --rm "${IMAGE_NAME}:${TAG}" which "$tool" >/dev/null 2>&1; then
|
||||
echo "Error: QA aqua tool '$tool' not found in PATH." >&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."
|
||||
echo "All verifications passed."
|
||||
|
||||
# Push if requested
|
||||
if [[ "${PUSH}" == "true" ]]; then
|
||||
echo "Pushing ${IMAGE_NAME}:${TAG}"
|
||||
if ! docker push "${IMAGE_NAME}:${TAG}"; then
|
||||
@@ -195,4 +172,4 @@ else
|
||||
echo "Trivy not found. Install Trivy to perform security scanning."
|
||||
fi
|
||||
|
||||
echo "Build process completed successfully with all verifications and security checks."
|
||||
echo "Build process completed successfully with all verifications."
|
||||
@@ -1,9 +1,10 @@
|
||||
services:
|
||||
toolbox-qadocker:
|
||||
container_name: tsysdevstack-toolboxstack-toolbox-qadocker
|
||||
image: ${TOOLBOX_IMAGE:-tsysdevstack-toolboxstack-toolbox-qadocker:release-current}
|
||||
{{toolbox_name}}:
|
||||
container_name: tsysdevstack-toolboxstack-{{toolbox_name}}
|
||||
image: tsysdevstack-toolboxstack-{{toolbox_name}}
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
args:
|
||||
USER_ID: ${LOCAL_UID:-1000}
|
||||
GROUP_ID: ${LOCAL_GID:-1000}
|
||||
@@ -16,8 +17,19 @@ services:
|
||||
stdin_open: true
|
||||
volumes:
|
||||
- .:/workspace:rw
|
||||
- /var/run/docker.sock:/var/run/docker.sock:rw
|
||||
- ${HOME}/.local/share/mise:/home/toolbox/.local/share/mise:rw
|
||||
- ${HOME}/.cache/mise:/home/toolbox/.cache/mise:rw
|
||||
# Aqua configuration
|
||||
- ${HOME}/.config/aquaproj-aqua:/home/toolbox/.config/aquaproj-aqua:rw
|
||||
# AI CLI tool configuration and cache directories
|
||||
- ${HOME}/.config/openai:/home/toolbox/.config/openai:rw
|
||||
- ${HOME}/.config/gemini:/home/toolbox/.config/gemini:rw
|
||||
- ${HOME}/.config/qwen:/home/toolbox/.config/qwen:rw
|
||||
- ${HOME}/.config/code:/home/toolbox/.config/code:rw
|
||||
- ${HOME}/.config/opencode:/home/toolbox/.config/opencode:rw
|
||||
- ${HOME}/.cache/openai:/home/toolbox/.cache/openai:rw
|
||||
- ${HOME}/.cache/gemini:/home/toolbox/.cache/gemini:rw
|
||||
- ${HOME}/.cache/qwen:/home/toolbox/.cache/qwen:rw
|
||||
- ${HOME}/.cache/code:/home/toolbox/.cache/code:rw
|
||||
- ${HOME}/.cache/opencode:/home/toolbox/.cache/opencode:rw
|
||||
# Additional AI tool directories
|
||||
- ${HOME}/.config/codex:/home/toolbox/.config/codex:rw
|
||||
- ${HOME}/.cache/codex:/home/toolbox/.cache/codex:rw
|
||||
@@ -2,34 +2,110 @@
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Validate input parameters
|
||||
if [ "$#" -ne 1 ]; then
|
||||
echo "Usage: $0 <version-tag>"
|
||||
usage() {
|
||||
cat <<'EOU'
|
||||
Usage: ./release.sh [--dry-run] [--allow-dirty] <semver>
|
||||
|
||||
Examples:
|
||||
./release.sh 0.2.0
|
||||
./release.sh --dry-run 0.2.0
|
||||
|
||||
This script rebuilds the toolbox image, tags it as:
|
||||
- tsysdevstack-toolboxstack-<name>:dev
|
||||
- tsysdevstack-toolboxstack-<name>:release-current
|
||||
- tsysdevstack-toolboxstack-<name>:v<semver>
|
||||
|
||||
When run without --dry-run it pushes all three tags.
|
||||
EOU
|
||||
}
|
||||
|
||||
DRY_RUN=false
|
||||
ALLOW_DIRTY=false
|
||||
VERSION=""
|
||||
|
||||
while (( $# > 0 )); do
|
||||
case "$1" in
|
||||
--dry-run)
|
||||
DRY_RUN=true
|
||||
shift
|
||||
;;
|
||||
--allow-dirty)
|
||||
ALLOW_DIRTY=true
|
||||
shift
|
||||
;;
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
-*)
|
||||
echo "Unknown option: $1" >&2
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
*)
|
||||
VERSION="$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ -z "${VERSION}" ]]; then
|
||||
echo "Error: semantic version is required." >&2
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
VERSION="$1"
|
||||
IMAGE_NAME="tsysdevstack-toolboxstack-toolbox-qadocker"
|
||||
|
||||
# Build the image with the version tag
|
||||
echo "Building ${IMAGE_NAME}:${VERSION}"
|
||||
if ! docker build --tag "${IMAGE_NAME}:${VERSION}" .; then
|
||||
echo "Error: Failed to build ${IMAGE_NAME}:${VERSION}" >&2
|
||||
if [[ "${VERSION}" =~ ^v?([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then
|
||||
SEMVER="v${BASH_REMATCH[1]}.${BASH_REMATCH[2]}.${BASH_REMATCH[3]}"
|
||||
else
|
||||
echo "Error: version must be semantic (e.g., 0.2.0 or v0.2.0)." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Run tests
|
||||
echo "Running tests..."
|
||||
if ! ./test.sh; then
|
||||
echo "Error: Tests failed for ${IMAGE_NAME}:${VERSION}" >&2
|
||||
exit 1
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "${SCRIPT_DIR}" && git rev-parse --show-toplevel 2>/dev/null || true)"
|
||||
|
||||
if [[ -n "${REPO_ROOT}" && "${ALLOW_DIRTY}" != "true" ]]; then
|
||||
if ! git -C "${REPO_ROOT}" diff --quiet --ignore-submodules --exit-code; then
|
||||
echo "Error: git working tree has uncommitted changes. Please commit or stash before releasing." >&2
|
||||
exit 1
|
||||
fi
|
||||
elif [[ -z "${REPO_ROOT}" ]]; then
|
||||
echo "Warning: unable to resolve git repository root; skipping clean tree check." >&2
|
||||
fi
|
||||
|
||||
# Create release tag
|
||||
echo "Creating release tag..."
|
||||
if ! docker tag "${IMAGE_NAME}:${VERSION}" "${IMAGE_NAME}:release-current"; then
|
||||
echo "Error: Failed to create release tag for ${IMAGE_NAME}" >&2
|
||||
exit 1
|
||||
fi
|
||||
# Get the toolbox name from the directory name (or you can pass it as an argument)
|
||||
TOOLBOX_NAME="${TOOLBOX_NAME_OVERRIDE:-$(basename "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")}"
|
||||
IMAGE_NAME="tsysdevstack-toolboxstack-${TOOLBOX_NAME#toolbox-}"
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
echo "Release ${IMAGE_NAME}:${VERSION} completed successfully!"
|
||||
USER_ID="${USER_ID_OVERRIDE:-$(id -u)}"
|
||||
GROUP_ID="${GROUP_ID_OVERRIDE:-$(id -g)}"
|
||||
USERNAME="${USERNAME_OVERRIDE:-toolbox}"
|
||||
TEA_VERSION="${TEA_VERSION_OVERRIDE:-0.11.1}"
|
||||
BUILDER_NAME="${BUILDER_NAME:-tsysdevstack-toolboxstack-builder}"
|
||||
CACHE_DIR="${SCRIPT_DIR}/.build-cache"
|
||||
TAG="${TAG_OVERRIDE:-dev}"
|
||||
RELEASE_TAG="${RELEASE_TAG_OVERRIDE:-release-current}"
|
||||
VERSION_TAG="${VERSION_TAG_OVERRIDE:-}"
|
||||
if [[ -n "$VERSION_TAG" ]]; then
|
||||
VERSION_TAG="$SEMVER"
|
||||
fi
|
||||
PUSH="${PUSH_OVERRIDE:-false}"
|
||||
|
||||
echo "Preparing release for ${SEMVER}"
|
||||
echo " dry-run: ${DRY_RUN}"
|
||||
echo " allow-dirty: ${ALLOW_DIRTY}"
|
||||
|
||||
if [[ "${DRY_RUN}" == "true" ]]; then
|
||||
echo "[dry-run] Would build ${IMAGE_NAME}:${TAG}"
|
||||
TAG_OVERRIDE="${TAG}" PUSH_OVERRIDE=false "${SCRIPT_DIR}/build.sh"
|
||||
echo "[dry-run] Skipped pushing tags."
|
||||
else
|
||||
echo "Building ${IMAGE_NAME}:${TAG}"
|
||||
TAG_OVERRIDE="${TAG}" PUSH_OVERRIDE=true RELEASE_TAG_OVERRIDE="${RELEASE_TAG}" VERSION_TAG_OVERRIDE="${SEMVER}" "${SCRIPT_DIR}/build.sh"
|
||||
echo "Release ${SEMVER} pushed as:"
|
||||
echo " - ${IMAGE_NAME}:dev"
|
||||
echo " - ${IMAGE_NAME}:release-current"
|
||||
echo " - ${IMAGE_NAME}:${SEMVER}"
|
||||
fi
|
||||
@@ -28,14 +28,13 @@ fi
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
COMPOSE_FILE="${SCRIPT_DIR}/docker-compose.yml"
|
||||
|
||||
# Sanitize user input
|
||||
export LOCAL_UID="${USER_ID_OVERRIDE:-$(id -u)}"
|
||||
sanitized_input "$LOCAL_UID"
|
||||
export LOCAL_GID="${GROUP_ID_OVERRIDE:-$(id -g)}"
|
||||
sanitized_input "$LOCAL_GID"
|
||||
export LOCAL_USERNAME="${USERNAME_OVERRIDE:-toolbox}"
|
||||
sanitized_input "$LOCAL_USERNAME"
|
||||
export TOOLBOX_IMAGE="${TOOLBOX_IMAGE_OVERRIDE:-tsysdevstack-toolboxstack-toolbox-qadocker:release-current}"
|
||||
export TOOLBOX_IMAGE="${TOOLBOX_IMAGE_OVERRIDE:-tsysdevstack-toolboxstack-{{toolbox_name}}}"
|
||||
sanitized_input "$TOOLBOX_IMAGE"
|
||||
|
||||
if [[ ! -f "${COMPOSE_FILE}" ]]; then
|
||||
@@ -50,13 +49,19 @@ shift || true
|
||||
if [[ "${ACTION}" == "up" ]]; then
|
||||
# Create necessary directories for the toolbox tools with proper permissions
|
||||
mkdir -p "${HOME}/.local/share/mise" "${HOME}/.cache/mise"
|
||||
mkdir -p "${HOME}/.config/aquaproj-aqua"
|
||||
mkdir -p "${HOME}/.config" "${HOME}/.local/share"
|
||||
mkdir -p "${HOME}/.cache/openai" "${HOME}/.cache/gemini" "${HOME}/.cache/qwen" "${HOME}/.cache/code" "${HOME}/.cache/opencode"
|
||||
mkdir -p "${HOME}/.config/openai" "${HOME}/.config/gemini" "${HOME}/.config/qwen" "${HOME}/.config/code" "${HOME}/.config/opencode"
|
||||
mkdir -p "${HOME}/.config/codex" "${HOME}/.cache/codex"
|
||||
|
||||
# Set proper permissions for created directories
|
||||
chmod 700 "${HOME}/.config" "${HOME}/.local/share" "${HOME}/.cache" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
case "${ACTION}" in
|
||||
up)
|
||||
docker compose -f "${COMPOSE_FILE}" up --build --detach "$@"
|
||||
echo "Container started. Use 'docker exec -it tsysdevstack-toolboxstack-toolbox-qadocker zsh' to access the shell."
|
||||
echo "Container started. Use 'docker exec -it tsysdevstack-toolboxstack-{{toolbox_name}} zsh' to access the shell."
|
||||
;;
|
||||
down)
|
||||
docker compose -f "${COMPOSE_FILE}" down "$@"
|
||||
|
||||
@@ -2,41 +2,154 @@
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
echo "Running security audit on the current environment..."
|
||||
# Security audit script for the toolbox-template
|
||||
|
||||
# Check for any security issues with the current setup
|
||||
echo "Checking for common security issues..."
|
||||
IMAGE_NAME="${IMAGE_NAME_OVERRIDE:-tsysdevstack-toolboxstack-{{toolbox_name}}}"
|
||||
|
||||
# Check if running as root (should not be)
|
||||
if [ "$EUID" -eq 0 ]; then
|
||||
echo "WARNING: Running as root user" >&2
|
||||
exit 1
|
||||
else
|
||||
echo "✓ Running as non-root user"
|
||||
fi
|
||||
echo "🔒 Running security audit on ${IMAGE_NAME}"
|
||||
|
||||
# Check for sudo access (should not have)
|
||||
if command -v sudo &> /dev/null; then
|
||||
echo "WARNING: Sudo is available in the container" >&2
|
||||
exit 1
|
||||
else
|
||||
echo "✓ Sudo correctly removed from container"
|
||||
fi
|
||||
|
||||
# Verify important security tools are available
|
||||
echo "Checking for security tools..."
|
||||
# Check if Trivy is available for security scanning
|
||||
if command -v trivy &> /dev/null; then
|
||||
echo "✓ Trivy security scanner available"
|
||||
echo "🔍 Running Trivy security scan..."
|
||||
trivy image --exit-code 0 --severity HIGH,CRITICAL "${IMAGE_NAME}"
|
||||
echo "✅ Trivy scan completed"
|
||||
else
|
||||
echo "✗ Trivy security scanner not available" >&2
|
||||
exit 1
|
||||
echo "⚠️ Trivy not found. Install Trivy to perform security scanning."
|
||||
echo " Visit https://aquasecurity.github.io/trivy/ for installation instructions."
|
||||
fi
|
||||
|
||||
if command -v hadolint &> /dev/null; then
|
||||
echo "✓ Hadolint Dockerfile linter available"
|
||||
# Check for outdated packages
|
||||
echo "📦 Checking for outdated packages..."
|
||||
OUTDATED_PACKAGES=$(docker run --rm "${IMAGE_NAME}" apt list --upgradable 2>/dev/null | grep -v "Listing..." | wc -l)
|
||||
if [[ "${OUTDATED_PACKAGES}" -gt 0 ]]; then
|
||||
echo "⚠️ ${OUTDATED_PACKAGES} packages can be upgraded"
|
||||
echo " Run 'apt update && apt upgrade' to update packages"
|
||||
else
|
||||
echo "✗ Hadolint Dockerfile linter not available" >&2
|
||||
exit 1
|
||||
echo "✅ All system packages are up to date"
|
||||
fi
|
||||
|
||||
echo "Security audit completed successfully!"
|
||||
# Check for unnecessary packages that increase attack surface
|
||||
echo "🛡️ Checking for unnecessary packages..."
|
||||
UNNECESSARY_PACKAGES=$(docker run --rm "${IMAGE_NAME}" dpkg -l | grep -E "(telnet|ftp|rsh-client|nfs-common|rpcbind)" | wc -l)
|
||||
if [[ "${UNNECESSARY_PACKAGES}" -gt 0 ]]; then
|
||||
echo "⚠️ Found ${UNNECESSARY_PACKAGES} potentially unnecessary packages that increase attack surface"
|
||||
echo " Consider removing packages like telnet, ftp, rsh-client, nfs-common, rpcbind"
|
||||
else
|
||||
echo "✅ No unnecessary packages found that increase attack surface"
|
||||
fi
|
||||
|
||||
# Check for world-writable files/directories
|
||||
echo "📁 Checking for world-writable files/directories..."
|
||||
WORLD_WRITABLE=$(docker run --rm "${IMAGE_NAME}" find / -xdev -type f -perm -0002 -not -path "/proc/*" -not -path "/sys/*" 2>/dev/null | wc -l)
|
||||
if [[ "${WORLD_WRITABLE}" -gt 0 ]]; then
|
||||
echo "⚠️ Found ${WORLD_WRITABLE} world-writable files/directories"
|
||||
echo " These should be reviewed and permissions adjusted if necessary"
|
||||
else
|
||||
echo "✅ No world-writable files/directories found"
|
||||
fi
|
||||
|
||||
# Check for setuid/setgid binaries
|
||||
echo "🔑 Checking for setuid/setgid binaries..."
|
||||
SETUID_BINARIES=$(docker run --rm "${IMAGE_NAME}" find / -xdev \( -perm -4000 -o -perm -2000 \) -type f -not -path "/proc/*" -not -path "/sys/*" 2>/dev/null | wc -l)
|
||||
if [[ "${SETUID_BINARIES}" -gt 0 ]]; then
|
||||
echo "⚠️ Found ${SETUID_BINARIES} setuid/setgid binaries"
|
||||
echo " These should be reviewed for security implications"
|
||||
else
|
||||
echo "✅ No setuid/setgid binaries found"
|
||||
fi
|
||||
|
||||
# Check for running services
|
||||
echo "サービ Checking for running services..."
|
||||
RUNNING_SERVICES=$(docker run --rm "${IMAGE_NAME}" ps aux 2>/dev/null | grep -v "PID" | wc -l)
|
||||
if [[ "${RUNNING_SERVICES}" -gt 1 ]]; then
|
||||
echo "⚠️ Found ${RUNNING_SERVICES} running processes"
|
||||
echo " These should be reviewed for necessity"
|
||||
else
|
||||
echo "✅ No unnecessary running services found"
|
||||
fi
|
||||
|
||||
# Check for listening ports
|
||||
echo "📡 Checking for listening ports..."
|
||||
LISTENING_PORTS=$(docker run --rm "${IMAGE_NAME}" netstat -tuln 2>/dev/null | grep LISTEN | wc -l)
|
||||
if [[ "${LISTENING_PORTS}" -gt 0 ]]; then
|
||||
echo "⚠️ Found ${LISTENING_PORTS} listening ports"
|
||||
echo " These should be reviewed for security implications"
|
||||
else
|
||||
echo "✅ No unnecessary listening ports found"
|
||||
fi
|
||||
|
||||
# Check for sudo availability
|
||||
echo "🛑 Checking for sudo availability..."
|
||||
if docker run --rm "${IMAGE_NAME}" which sudo >/dev/null 2>&1; then
|
||||
echo "❌ Sudo is available in the image - this is a security risk"
|
||||
echo " Sudo should be removed to prevent privilege escalation"
|
||||
else
|
||||
echo "✅ Sudo is not available in the image"
|
||||
fi
|
||||
|
||||
# Check for root login capability
|
||||
echo "🔐 Checking for root login capability..."
|
||||
ROOT_LOGIN_ENABLED=$(docker run --rm "${IMAGE_NAME}" cat /etc/passwd | grep root | grep -v "nologin" | wc -l)
|
||||
if [[ "${ROOT_LOGIN_ENABLED}" -gt 0 ]]; then
|
||||
echo "⚠️ Root login might be enabled"
|
||||
echo " Ensure root login is disabled for security"
|
||||
else
|
||||
echo "✅ Root login is properly disabled"
|
||||
fi
|
||||
|
||||
# Check user configuration
|
||||
echo "👤 Checking user configuration..."
|
||||
USER_ID=$(docker run --rm "${IMAGE_NAME}" id -u toolbox 2>/dev/null || echo "not_found")
|
||||
if [[ "${USER_ID}" == "1000" ]]; then
|
||||
echo "✅ Non-root user 'toolbox' with UID 1000 is properly configured"
|
||||
else
|
||||
echo "⚠️ Non-root user configuration might be incorrect"
|
||||
fi
|
||||
|
||||
# Check for hardcoded passwords
|
||||
echo "🔑 Checking for hardcoded passwords..."
|
||||
HARDCODED_PASSWORDS=$(docker run --rm "${IMAGE_NAME}" grep -r "password\|passwd" /etc/ 2>/dev/null | grep -v "shadow" | wc -l)
|
||||
if [[ "${HARDCODED_PASSWORDS}" -gt 0 ]]; then
|
||||
echo "⚠️ Found ${HARDCODED_PASSWORDS} potential hardcoded password references"
|
||||
echo " These should be reviewed for security implications"
|
||||
else
|
||||
echo "✅ No hardcoded password references found"
|
||||
fi
|
||||
|
||||
# Check for exposed secrets
|
||||
echo " секр Checking for exposed secrets..."
|
||||
EXPOSED_SECRETS=$(docker run --rm "${IMAGE_NAME}" find / -xdev -type f -name "*.key" -o -name "*.pem" -o -name "*.cert" 2>/dev/null | wc -l)
|
||||
if [[ "${EXPOSED_SECRETS}" -gt 0 ]]; then
|
||||
echo "⚠️ Found ${EXPOSED_SECRETS} potential secret files"
|
||||
echo " These should be reviewed for security implications"
|
||||
else
|
||||
echo "✅ No exposed secret files found"
|
||||
fi
|
||||
|
||||
# Check that this template properly extends from the base image
|
||||
echo "🔗 Checking inheritance from base image..."
|
||||
BASE_INHERITANCE=$(docker history "${IMAGE_NAME}" 2>/dev/null | grep "FROM tsysdevstack-toolboxstack-toolbox-base:release-current" | wc -l)
|
||||
if [[ "${BASE_INHERITANCE}" -gt 0 ]]; then
|
||||
echo "✅ Template properly extends from toolbox-base:release-current"
|
||||
else
|
||||
echo "⚠️ Template might not properly extend from toolbox-base:release-current"
|
||||
fi
|
||||
|
||||
# Summary
|
||||
echo ""
|
||||
echo "🔒 Security Audit Summary:"
|
||||
echo " - Image: ${IMAGE_NAME}"
|
||||
echo " - Scan completed with recommendations above"
|
||||
echo ""
|
||||
echo "💡 Recommendations:"
|
||||
echo " 1. Install Trivy for comprehensive security scanning"
|
||||
echo " 2. Regularly update packages to address vulnerabilities"
|
||||
echo " 3. Remove unnecessary packages to reduce attack surface"
|
||||
echo " 4. Review world-writable files/directories"
|
||||
echo " 5. Review setuid/setgid binaries"
|
||||
echo " 6. Remove sudo to prevent privilege escalation"
|
||||
echo " 7. Ensure root login is disabled"
|
||||
echo " 8. Verify non-root user configuration"
|
||||
echo " 9. Review hardcoded password references"
|
||||
echo " 10. Check for exposed secrets"
|
||||
echo " 11. Ensure proper inheritance from base image"
|
||||
@@ -2,40 +2,111 @@
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
echo "Testing toolbox-QADocker functionality..."
|
||||
# Test script to verify all tools are working properly in the toolbox-template
|
||||
|
||||
# Test core tools availability
|
||||
echo "Testing core tools..."
|
||||
if ! command -v zsh &> /dev/null; then
|
||||
echo "Error: zsh is not available" >&2
|
||||
IMAGE_NAME="${IMAGE_NAME_OVERRIDE:-tsysdevstack-toolboxstack-{{toolbox_name}}}"
|
||||
|
||||
echo "🧪 Testing all tools in ${IMAGE_NAME}"
|
||||
|
||||
# Function to test a command
|
||||
test_cmd() {
|
||||
local cmd="$1"
|
||||
local description="$2"
|
||||
|
||||
echo -n "Testing ${cmd} (${description})... "
|
||||
|
||||
if docker run --rm "${IMAGE_NAME}" "${cmd}" --version >/dev/null 2>&1; then
|
||||
echo "✅ PASS"
|
||||
return 0
|
||||
else
|
||||
echo "❌ FAIL"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to test a command with specific args
|
||||
test_cmd_args() {
|
||||
local cmd="$1"
|
||||
local args="$2"
|
||||
local description="$3"
|
||||
|
||||
echo -n "Testing ${cmd} ${args} (${description})... "
|
||||
|
||||
if docker run --rm "${IMAGE_NAME}" "${cmd}" ${args} >/dev/null 2>&1; then
|
||||
echo "✅ PASS"
|
||||
return 0
|
||||
else
|
||||
echo "❌ FAIL"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Counter for tracking results
|
||||
PASSED=0
|
||||
FAILED=0
|
||||
|
||||
# Test core tools inherited from base
|
||||
echo "🔍 Testing core tools inherited from base..."
|
||||
|
||||
test_cmd "zsh" "Z shell" && ((PASSED++)) || ((FAILED++))
|
||||
test_cmd "git" "Git version control" && ((PASSED++)) || ((FAILED++))
|
||||
test_cmd "curl" "cURL utility" && ((PASSED++)) || ((FAILED++))
|
||||
test_cmd "jq" "JSON processor" && ((PASSED++)) || ((FAILED++))
|
||||
test_cmd "fish" "Fish shell" && ((PASSED++)) || ((FAILED++))
|
||||
test_cmd "fzf" "Fuzzy finder" && ((PASSED++)) || ((FAILED++))
|
||||
test_cmd "bat" "Cat clone with wings" && ((PASSED++)) || ((FAILED++))
|
||||
test_cmd "fd" "Simple, fast alternative to find" && ((PASSED++)) || ((FAILED++))
|
||||
test_cmd "rg" "Ripgrep - line-oriented search tool" && ((PASSED++)) || ((FAILED++))
|
||||
test_cmd "htop" "Interactive process viewer" && ((PASSED++)) || ((FAILED++))
|
||||
test_cmd "btop" "Modern and colorful terminal monitor" && ((PASSED++)) || ((FAILED++))
|
||||
|
||||
# Test aqua installed tools inherited from base
|
||||
echo "🔧 Testing aqua installed tools inherited from base..."
|
||||
|
||||
test_cmd "gh" "GitHub CLI" && ((PASSED++)) || ((FAILED++))
|
||||
test_cmd "lazygit" "Simple terminal UI for git commands" && ((PASSED++)) || ((FAILED++))
|
||||
test_cmd "direnv" "Unclutter your .profile" && ((PASSED++)) || ((FAILED++))
|
||||
test_cmd "delta" "Syntax-highlighting pager for git, diff, and grep output" && ((PASSED++)) || ((FAILED++))
|
||||
test_cmd "zoxide" "Smarter cd command" && ((PASSED++)) || ((FAILED++))
|
||||
test_cmd "just" "Just a command runner" && ((PASSED++)) || ((FAILED++))
|
||||
test_cmd "yq" "Portable command-line YAML processor" && ((PASSED++)) || ((FAILED++))
|
||||
test_cmd "xh" "Friendly and fast tool for sending HTTP requests" && ((PASSED++)) || ((FAILED++))
|
||||
test_cmd "curlie" "The power of curl, the ease of use of httpie" && ((PASSED++)) || ((FAILED++))
|
||||
test_cmd "chezmoi" "Manage your dotfiles across multiple machines" && ((PASSED++)) || ((FAILED++))
|
||||
test_cmd "shfmt" "Shell formatter" && ((PASSED++)) || ((FAILED++))
|
||||
test_cmd "shellcheck" "Shell script analysis tool" && ((PASSED++)) || ((FAILED++))
|
||||
test_cmd "hadolint" "Dockerfile linter" && ((PASSED++)) || ((FAILED++))
|
||||
test_cmd "uv" "Python package installer and resolver" && ((PASSED++)) || ((FAILED++))
|
||||
test_cmd "watchexec" "Execute commands in response to file modifications" && ((PASSED++)) || ((FAILED++))
|
||||
test_cmd "tea" "Gitea CLI" && ((PASSED++)) || ((FAILED++))
|
||||
|
||||
# Test AI CLI tools inherited from base
|
||||
echo "🤖 Testing AI CLI tools inherited from base..."
|
||||
|
||||
test_cmd_args "code" "--version" "just-every/code AI CLI" && ((PASSED++)) || ((FAILED++))
|
||||
test_cmd_args "qwen" "--version" "QwenLM/qwen-code AI CLI" && ((PASSED++)) || ((FAILED++))
|
||||
test_cmd_args "gemini" "--version" "google-gemini/gemini-cli AI CLI" && ((PASSED++)) || ((FAILED++))
|
||||
test_cmd_args "codex" "--version" "openai/codex AI CLI" && ((PASSED++)) || ((FAILED++))
|
||||
test_cmd_args "opencode" "--version" "sst/opencode AI CLI" && ((PASSED++)) || ((FAILED++))
|
||||
|
||||
# Test additional tools inherited from base
|
||||
echo "🧰 Testing additional tools inherited from base..."
|
||||
|
||||
test_cmd "starship" "Cross-shell prompt" && ((PASSED++)) || ((FAILED++))
|
||||
test_cmd "mise" "Polyglot runtime manager" && ((PASSED++)) || ((FAILED++))
|
||||
test_cmd_args "aqua" "--version" "Declarative CLI Version Manager" && ((PASSED++)) || ((FAILED++))
|
||||
|
||||
# Summary
|
||||
echo ""
|
||||
echo "📊 Test Results:"
|
||||
echo " Passed: ${PASSED}"
|
||||
echo " Failed: ${FAILED}"
|
||||
echo " Total: $((PASSED + FAILED))"
|
||||
|
||||
if [[ "${FAILED}" -eq 0 ]]; then
|
||||
echo "🎉 All tests passed!"
|
||||
exit 0
|
||||
else
|
||||
echo "💥 ${FAILED} tests failed!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v git &> /dev/null; then
|
||||
echo "Error: git is not available" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v docker &> /dev/null; then
|
||||
echo "Error: docker is not available" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test QA tools availability
|
||||
echo "Testing QA tools..."
|
||||
if ! command -v trivy &> /dev/null; then
|
||||
echo "Error: trivy is not available" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v hadolint &> /dev/null; then
|
||||
echo "Error: hadolint is not available" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v dockerfilelint &> /dev/null; then
|
||||
echo "Error: dockerfilelint is not available" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "All tests passed! toolbox-QADocker is functional."
|
||||
fi
|
||||
81
ToolboxStack/output/toolbox-qadocker/Dockerfile
Normal file
81
ToolboxStack/output/toolbox-qadocker/Dockerfile
Normal file
@@ -0,0 +1,81 @@
|
||||
# Use Ubuntu 24.04 as base for the QA Docker toolbox
|
||||
FROM ubuntu:24.04
|
||||
|
||||
# Set build arguments (these can be overridden at build time)
|
||||
ARG USER_ID=1000
|
||||
ARG GROUP_ID=1000
|
||||
ARG USERNAME=toolbox
|
||||
|
||||
# Set up environment and install essential packages
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
ca-certificates \
|
||||
curl \
|
||||
gnupg \
|
||||
lsb-release \
|
||||
git \
|
||||
unzip \
|
||||
wget \
|
||||
zsh \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install Docker CLI
|
||||
RUN install -m 0755 -d /etc/apt/keyrings \
|
||||
&& curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg \
|
||||
&& chmod a+r /etc/apt/keyrings/docker.gpg \
|
||||
&& echo \
|
||||
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
|
||||
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
|
||||
tee /etc/apt/sources.list.d/docker.list > /dev/null \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y --no-install-recommends docker-ce-cli \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install hadolint for Dockerfile linting
|
||||
RUN wget -O /usr/local/bin/hadolint https://github.com/hadolint/hadolint/releases/download/v2.12.0/hadolint-Linux-x86_64 \
|
||||
&& chmod +x /usr/local/bin/hadolint
|
||||
|
||||
# Install dive for exploring Docker image layers
|
||||
RUN wget -O /tmp/dive_0.10.0_linux_amd64.deb https://github.com/wagoodman/dive/releases/download/v0.10.0/dive_0.10.0_linux_amd64.deb \
|
||||
&& dpkg -i /tmp/dive_0.10.0_linux_amd64.deb \
|
||||
&& rm /tmp/dive_0.10.0_linux_amd64.deb
|
||||
|
||||
# Install git for cloning security repositories
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends git \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Create non-root user
|
||||
RUN groupadd --gid "${GROUP_ID}" "${USERNAME}" \
|
||||
&& useradd --uid "${USER_ID}" --gid "${GROUP_ID}" --shell /bin/bash --create-home "${USERNAME}"
|
||||
|
||||
# Set up basic shell configuration
|
||||
RUN echo 'export PATH="$PATH:/usr/local/bin"' >> /home/${USERNAME}/.bashrc
|
||||
|
||||
# Prepare workspace directory with appropriate ownership
|
||||
RUN mkdir -p /workspace \
|
||||
&& chown "${USER_ID}:${GROUP_ID}" /workspace
|
||||
|
||||
# Remove sudo to ensure no root escalation is possible at runtime
|
||||
RUN apt-get remove -y sudo 2>/dev/null || true && apt-get autoremove -y 2>/dev/null || true && rm -rf /var/lib/apt/lists/* 2>/dev/null || true
|
||||
|
||||
# Install aqua for package management
|
||||
RUN curl -sSfL https://raw.githubusercontent.com/aquaproj/aqua-installer/v3.0.0/aqua-installer | bash -s -- -v v3.0.0 \
|
||||
&& mv /usr/local/bin/aqua /usr/local/bin/aqua-tmp \
|
||||
&& mkdir -p /root/.local/share/aquaproj-aqua/bin \
|
||||
&& mv /usr/local/bin/aqua-tmp /root/.local/share/aquaproj-aqua/bin/aqua \
|
||||
&& ln -s /root/.local/share/aquaproj-aqua/bin/aqua /usr/local/bin/aqua
|
||||
|
||||
# Copy the aqua.yaml configuration for the non-root user and install packages
|
||||
COPY aqua.yaml /tmp/aqua.yaml
|
||||
RUN chown "${USER_ID}:${GROUP_ID}" /tmp/aqua.yaml \
|
||||
&& mkdir -p /home/${USERNAME}/.config/aquaproj-aqua \
|
||||
&& chown "${USER_ID}:${GROUP_ID}" /home/${USERNAME}/.config/aquaproj-aqua \
|
||||
&& su - "${USERNAME}" -c 'cp /tmp/aqua.yaml /home/${USERNAME}/.config/aquaproj-aqua/aqua.yaml' \
|
||||
&& su - "${USERNAME}" -c 'AQUA_GLOBAL_CONFIG=/home/${USERNAME}/.config/aquaproj-aqua/aqua.yaml aqua install'
|
||||
|
||||
ENV PATH=/root/.local/share/aquaproj-aqua/bin:/home/${USERNAME}/.local/share/aquaproj-aqua/bin:/usr/local/bin:${PATH}
|
||||
|
||||
WORKDIR /workspace
|
||||
USER ${USERNAME}
|
||||
|
||||
CMD ["/bin/bash"]
|
||||
79
ToolboxStack/output/toolbox-qadocker/README.md
Normal file
79
ToolboxStack/output/toolbox-qadocker/README.md
Normal file
@@ -0,0 +1,79 @@
|
||||
# 🧰 TSYSDevStack QA Docker Toolbox
|
||||
|
||||
A minimal Docker image designed for auditing, verifying, and testing Docker images and container configurations.
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Quick Start
|
||||
|
||||
1. **Build the toolbox**
|
||||
```bash
|
||||
./build.sh
|
||||
```
|
||||
|
||||
2. **Start the toolbox**
|
||||
```bash
|
||||
./run.sh up
|
||||
```
|
||||
|
||||
3. **Access the toolbox**
|
||||
```bash
|
||||
docker exec -it tsysdevstack-toolboxstack-qadocker bash
|
||||
```
|
||||
|
||||
4. **Stop the toolbox**
|
||||
```bash
|
||||
./run.sh down
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🧱 Architecture
|
||||
|
||||
- **Base Image**: Ubuntu 24.04 (minimal base without extending from toolbox-base)
|
||||
- **User**: Runs as non-root `toolbox` user (UID/GID mapped to host)
|
||||
- **Workspace**: Mounts current directory to `/workspace` (read/write)
|
||||
- **Tools**: Contains essential Docker auditing and security tools
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ Included Tools
|
||||
|
||||
### Docker Auditing & Security
|
||||
- **Docker CLI**: For Docker operations and container management
|
||||
- **Hadolint**: Dockerfile linter for best practices and common errors
|
||||
- **Dive**: Tool to explore Docker image layers and discover inefficiencies
|
||||
- **Trivy**: Comprehensive security scanner for vulnerabilities
|
||||
- **Grype**: Vulnerability scanner for container images
|
||||
- **Docker Bench Security**: Tool for running CIS Docker benchmark tests
|
||||
|
||||
### Version Control & General Tools
|
||||
- **Git**: For version control operations
|
||||
- **Lazygit**: Terminal UI for Git
|
||||
- **Curl/Wget**: For downloading resources
|
||||
- **Yq**: Command-line YAML processor
|
||||
- **Xh**: Friendly and fast tool for HTTP requests
|
||||
|
||||
---
|
||||
|
||||
## 📂 Project Layout
|
||||
|
||||
| Path | Purpose |
|
||||
|------|---------|
|
||||
| `Dockerfile` | Defines the minimal QA Docker image with auditing tools |
|
||||
| `docker-compose.yml` | Service configuration for the QA toolbox |
|
||||
| `build.sh` | Wrapper around `docker build` with host UID/GID mapping |
|
||||
| `run.sh` | Helper to bring the service up/down |
|
||||
| `aqua.yaml` | Configuration for aqua-managed CLI tools |
|
||||
| `SEED` | Defines the toolbox's purpose and goals |
|
||||
| `PROMPT` | LLM onboarding prompt for future contributors |
|
||||
|
||||
---
|
||||
|
||||
## 🤝 Collaboration Notes
|
||||
|
||||
- This is the ONLY image that does NOT extend from `toolbox-base` (used for bootstrap purposes)
|
||||
- Designed for use by AI CLI agents when creating and verifying container images
|
||||
- Contains tools for auditing Docker images (hadolint, dive, etc.)
|
||||
- Meant to be rebuilt quickly and be easy to extend
|
||||
- Follows best security practices for minimal attack surface
|
||||
24
ToolboxStack/output/toolbox-qadocker/aqua.yaml
Normal file
24
ToolboxStack/output/toolbox-qadocker/aqua.yaml
Normal file
@@ -0,0 +1,24 @@
|
||||
version: 1.0.0
|
||||
registries:
|
||||
- type: standard
|
||||
ref: v4.431.0
|
||||
packages:
|
||||
# Docker auditing and security tools
|
||||
- name: hadolint/hadolint@v2.12.0
|
||||
- name: aquasecurity/trivy@v0.56.2
|
||||
- name: anchore/grype@v0.84.1
|
||||
- name: docker/docker-bench-security@v1.8.0
|
||||
- name: snyk/snyk@v1.1308.0
|
||||
# General utility tools
|
||||
- name: jesseduffield/lazygit@v0.44.0
|
||||
- name: direnv/direnv@v2.35.0
|
||||
- name: dandavison/delta@0.18.2
|
||||
- name: ajeetdsouza/zoxide@v0.9.6
|
||||
- name: mikefarah/yq@v4.44.3
|
||||
- name: ducaale/xh@v0.22.3
|
||||
- name: rs/curlie@v1.8.6
|
||||
- name: koalaman/shellcheck@v0.10.0
|
||||
- name: mvdan/sh@v3.7.0
|
||||
- name: golangci/golangci-lint@v1.60.3
|
||||
- name: golang/go@go1.23.0
|
||||
- name: cli/cli@v2.57.0
|
||||
@@ -28,7 +28,9 @@ fi
|
||||
# Get the toolbox name from the directory name (or you can pass it as an argument)
|
||||
TOOLBOX_NAME="${TOOLBOX_NAME_OVERRIDE:-$(basename "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")}"
|
||||
sanitized_input "$TOOLBOX_NAME"
|
||||
IMAGE_NAME="tsysdevstack-toolboxstack-${TOOLBOX_NAME#toolbox-}"
|
||||
# Convert to lowercase and replace any uppercase letters to ensure valid Docker image name
|
||||
IMAGE_NAME_RAW="tsysdevstack-toolboxstack-${TOOLBOX_NAME#toolbox-}"
|
||||
IMAGE_NAME=$(echo "$IMAGE_NAME_RAW" | tr '[:upper:]' '[:lower:]')
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
# Sanitize user input
|
||||
@@ -107,42 +109,22 @@ if ! docker run --rm "${IMAGE_NAME}:${TAG}" zsh -c 'echo "Container starts succe
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify critical tools are available
|
||||
echo "Verifying critical tools..."
|
||||
CRITICAL_TOOLS=("zsh" "git" "curl" "jq" "fish" "fzf" "bat" "fd" "rg" "htop" "btop")
|
||||
# Verify critical tools for Docker auditing are available
|
||||
echo "Verifying Docker auditing tools..."
|
||||
CRITICAL_TOOLS=("git" "curl" "wget" "docker" "hadolint" "dive")
|
||||
for tool in "${CRITICAL_TOOLS[@]}"; do
|
||||
if ! docker run --rm "${IMAGE_NAME}:${TAG}" which "$tool" >/dev/null 2>&1; then
|
||||
echo "Error: Critical tool '$tool' not found in PATH." >&2
|
||||
echo "Error: Critical Docker auditing tool '$tool' not found in PATH." >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
# Verify aqua tools are available
|
||||
echo "Verifying aqua tools..."
|
||||
AQUA_TOOLS=("gh" "lazygit" "direnv" "delta" "zoxide" "just" "yq" "xh" "curlie" "chezmoi" "shfmt" "shellcheck" "hadolint" "uv" "uvx" "watchexec" "kroki")
|
||||
# Verify additional aqua tools for QA are available
|
||||
echo "Verifying QA aqua tools..."
|
||||
AQUA_TOOLS=("lazygit" "direnv" "delta" "zoxide" "yq" "xh" "curlie" "shellcheck" "trivy" "grype" "docker-bench-security")
|
||||
for tool in "${AQUA_TOOLS[@]}"; do
|
||||
if ! docker run --rm "${IMAGE_NAME}:${TAG}" which "$tool" >/dev/null 2>&1; then
|
||||
echo "Error: Aqua tool '$tool' not found in PATH." >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
# Verify AI CLI tools are available
|
||||
echo "Verifying AI CLI tools..."
|
||||
AI_TOOLS=("code" "qwen" "gemini" "codex" "opencode")
|
||||
for tool in "${AI_TOOLS[@]}"; do
|
||||
if ! docker run --rm "${IMAGE_NAME}:${TAG}" which "$tool" >/dev/null 2>&1; then
|
||||
echo "Error: AI CLI tool '$tool' not found in PATH." >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
# Verify testing tools are available
|
||||
echo "Verifying testing tools..."
|
||||
TESTING_TOOLS=("bats" "shellcheck" "shfmt" "hadolint")
|
||||
for tool in "${TESTING_TOOLS[@]}"; do
|
||||
if ! docker run --rm "${IMAGE_NAME}:${TAG}" which "$tool" >/dev/null 2>&1; then
|
||||
echo "Error: Testing tool '$tool' not found in PATH." >&2
|
||||
echo "Error: QA aqua tool '$tool' not found in PATH." >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"name": "TSYSDevStack {{toolbox_name}}",
|
||||
"dockerComposeFile": [
|
||||
"../docker-compose.yml"
|
||||
],
|
||||
"service": "{{toolbox_name}}",
|
||||
"workspaceFolder": "/workspace",
|
||||
"remoteUser": "toolbox",
|
||||
"runServices": [
|
||||
"{{toolbox_name}}"
|
||||
],
|
||||
"overrideCommand": false,
|
||||
"postCreateCommand": "zsh -lc 'starship --version >/dev/null'"
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
# Extend from the toolbox-base image
|
||||
# NOTE: Always use the full image name to ensure compatibility in standalone builds
|
||||
FROM tsysdevstack-toolboxstack-toolbox-base:release-current
|
||||
|
||||
# Set build arguments (these can be overridden at build time)
|
||||
ARG USER_ID=1000
|
||||
ARG GROUP_ID=1000
|
||||
ARG USERNAME=toolbox
|
||||
|
||||
# Ensure the non-root user exists with the correct UID/GID
|
||||
# Check if user/group already exists and handle appropriately
|
||||
RUN if getent passwd "${USER_ID}" >/dev/null; then \
|
||||
existing_user="$(getent passwd "${USER_ID}" | cut -d: -f1)"; \
|
||||
echo "User with UID ${USER_ID} already exists: ${existing_user}" >&2; \
|
||||
else \
|
||||
if ! getent group "${GROUP_ID}" >/dev/null; then \
|
||||
groupadd --gid "${GROUP_ID}" "${USERNAME}"; \
|
||||
fi \
|
||||
useradd --uid "${USER_ID}" --gid "${GROUP_ID}" --shell /usr/bin/zsh --create-home "${USERNAME}"; \
|
||||
fi
|
||||
|
||||
# Install toolbox-specific packages here
|
||||
# Example:
|
||||
# RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
# specific-package \
|
||||
# && apt-get clean \
|
||||
# && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install toolbox-specific aqua packages here
|
||||
# Example:
|
||||
# COPY aqua.yaml /tmp/aqua.yaml
|
||||
# RUN chown "${USER_ID}:${GROUP_ID}" /tmp/aqua.yaml \
|
||||
# && su - "${USERNAME}" -c 'mkdir -p ~/.config/aquaproj-aqua' \
|
||||
# && su - "${USERNAME}" -c 'cp /tmp/aqua.yaml ~/.config/aquaproj-aqua/aqua.yaml' \
|
||||
# && AQUA_GLOBAL_CONFIG=/tmp/aqua.yaml aqua install \
|
||||
# && su - "${USERNAME}" -c 'AQUA_GLOBAL_CONFIG=~/.config/aquaproj-aqua/aqua.yaml aqua install'
|
||||
|
||||
# Install toolbox-specific npm packages here
|
||||
# Example:
|
||||
# RUN su - "${USERNAME}" -c 'mise exec -- npm install -g @scope/package@version'
|
||||
|
||||
# Prepare workspace directory with appropriate ownership
|
||||
RUN mkdir -p /workspace \
|
||||
&& chown "${USER_ID}:${GROUP_ID}" /workspace
|
||||
|
||||
# Remove sudo to ensure no root escalation is possible at runtime
|
||||
RUN apt-get remove -y sudo 2>/dev/null || true && apt-get autoremove -y 2>/dev/null || true && rm -rf /var/lib/apt/lists/* 2>/dev/null || true
|
||||
|
||||
ENV SHELL=/usr/bin/zsh \
|
||||
AQUA_GLOBAL_CONFIG=/home/${USERNAME}/.config/aquaproj-aqua/aqua.yaml \
|
||||
PATH=/home/${USERNAME}/.local/share/aquaproj-aqua/bin:/home/${USERNAME}/.local/share/mise/shims:/home/${USERNAME}/.local/bin:${PATH}
|
||||
|
||||
WORKDIR /workspace
|
||||
USER ${USERNAME}
|
||||
|
||||
CMD ["/usr/bin/zsh"]
|
||||
@@ -1,107 +0,0 @@
|
||||
# 🧰 TSYSDevStack Toolbox Template
|
||||
|
||||
Template for creating new toolboxes that extend from the `toolbox-base` image.
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Quick Start
|
||||
|
||||
1. **Create a new toolbox**
|
||||
```bash
|
||||
cp -r /path/to/toolbox-template /path/to/new-toolbox
|
||||
cd /path/to/new-toolbox
|
||||
```
|
||||
|
||||
2. **Customize the toolbox**
|
||||
- Edit `Dockerfile` to add toolbox-specific tooling
|
||||
- Modify `docker-compose.yml` to adjust service configuration
|
||||
- Update `SEED` to define the toolbox's purpose and goals
|
||||
|
||||
3. **Build the toolbox**
|
||||
```bash
|
||||
./build.sh
|
||||
```
|
||||
|
||||
4. **Start the toolbox**
|
||||
```bash
|
||||
./run.sh up
|
||||
```
|
||||
|
||||
5. **Access the toolbox**
|
||||
```bash
|
||||
docker exec -it tsysdevstack-toolboxstack-{{toolbox_name}} zsh
|
||||
```
|
||||
|
||||
6. **Stop the toolbox**
|
||||
```bash
|
||||
./run.sh down
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🧱 Architecture
|
||||
|
||||
- **Base Image**: Extends from `tsysdevstack-toolboxstack-toolbox-base:release-current`
|
||||
- **User**: Runs as non-root `toolbox` user (UID/GID mapped to host)
|
||||
- **Workspace**: Mounts current directory to `/workspace` (read/write)
|
||||
- **Runtime**: Inherits all tooling from base plus toolbox-specific additions
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ Customization
|
||||
|
||||
### Dockerfile
|
||||
Extend the base image with toolbox-specific tooling:
|
||||
```dockerfile
|
||||
# Extend from the toolbox-base image
|
||||
FROM tsysdevstack-toolboxstack-toolbox-base:release-current
|
||||
|
||||
# Add toolbox-specific packages or configurations
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
specific-package \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
```
|
||||
|
||||
### docker-compose.yml
|
||||
Adjust service configuration for toolbox-specific needs:
|
||||
```yaml
|
||||
services:
|
||||
my-toolbox:
|
||||
# Inherits all base configuration
|
||||
# Add toolbox-specific volumes, ports, etc.
|
||||
volumes:
|
||||
- ./custom-config:/home/toolbox/.config/custom-tool
|
||||
```
|
||||
|
||||
### SEED
|
||||
Define the toolbox's purpose and goals:
|
||||
```markdown
|
||||
- Describe what this toolbox should provide (languages, CLIs, workflows)
|
||||
- List required base image modifications or additional mounts
|
||||
- Note verification or testing expectations specific to this toolbox
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📂 Project Layout
|
||||
|
||||
| Path | Purpose |
|
||||
|------|---------|
|
||||
| `Dockerfile` | Extends base image with toolbox-specific tooling |
|
||||
| `docker-compose.yml` | Service configuration for the toolbox |
|
||||
| `build.sh` | Wrapper around `docker build` with host UID/GID mapping |
|
||||
| `run.sh` | Helper to bring the service up/down |
|
||||
| `.devcontainer/devcontainer.json` | VS Code remote container definition |
|
||||
| `SEED` | Defines the toolbox's purpose and goals |
|
||||
| `PROMPT` | LLM onboarding prompt for future contributors |
|
||||
|
||||
---
|
||||
|
||||
## 🤝 Collaboration Notes
|
||||
|
||||
- Inherits all collaboration policies from `toolbox-base`
|
||||
- Document toolbox-specific additions in `README.md` and `PROMPT`
|
||||
- Update `SEED` only when the high-level objectives change
|
||||
- Prefer aqua/mise for new tooling to keep installations reproducible
|
||||
- Keep documentation synchronized for future contributors
|
||||
@@ -1,22 +0,0 @@
|
||||
version: 1.0.0
|
||||
registries:
|
||||
- type: standard
|
||||
ref: v4.431.0
|
||||
packages:
|
||||
# Add additional packages specific to your toolbox here
|
||||
# Example:
|
||||
# - name: cli/cli@v2.82.1
|
||||
# - name: jesseduffield/lazygit@v0.55.1
|
||||
# - name: direnv/direnv@v2.37.1
|
||||
# - name: dandavison/delta@0.18.2
|
||||
# - name: ajeetdsouza/zoxide@v0.9.8
|
||||
# - name: casey/just@1.43.0
|
||||
# - name: mikefarah/yq@v4.48.1
|
||||
# - name: ducaale/xh@v0.25.0
|
||||
# - name: rs/curlie@v1.8.2
|
||||
# - name: twpayne/chezmoi@v2.66.1
|
||||
# - name: mvdan/sh@v3.12.0
|
||||
# - name: koalaman/shellcheck@v0.11.0
|
||||
# - name: hadolint/hadolint@v2.14.0
|
||||
# - name: astral-sh/uv@0.9.6
|
||||
# - name: watchexec/watchexec@v2.3.2
|
||||
Reference in New Issue
Block a user