Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Version control
.git
.gitignore

# Python
__pycache__
*.pyc
*.pyo
.pytest_cache
.coverage
.venv
venv
env
*.egg-info

# Build artifacts
dist
build

# Environment
.env
.env.*
*.env

# IDE
.idea
.vscode
*.swp
*.swo

# OS
.DS_Store
Thumbs.db

# Project-specific
tests
.github
*.md
27 changes: 27 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,30 @@ jobs:
run: uv run pytest --cov=src tests/
- name: Lint
run: uv run flake8 src/ tests/

docker-build-and-audit:
runs-on: ubuntu-latest
if: github.event_name == 'pull_request' || github.ref == 'refs/heads/main'

steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build image (no-cache for audit accuracy)
uses: docker/build-push-action@v6
with:
context: .
file: Dockerfile
push: false
load: true
tags: agent-orchestrator:ci-${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: |
BUILD_ENV=ci
PIP_INDEX_URL=https://pypi.org/simple
UV_VERSION=0.6.0
- name: Run image metadata audit
run: |
chmod +x infra/scripts/audit_image_metadata.sh
./infra/scripts/audit_image_metadata.sh agent-orchestrator:ci-${{ github.sha }}
89 changes: 89 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
name: Release

on:
push:
tags:
- 'v*'

permissions:
id-token: write # Required for provenance attestation
contents: write # Required for creating releases
attestations: write # Required for storing attestations

jobs:
build-and-attest:
name: Build & Attest Provenance
runs-on: ubuntu-latest

steps:
- name: Checkout source
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Install uv
uses: astral-sh/setup-uv@v3

- name: Build packages
run: uv build

- name: Generate provenance attestation
uses: actions/attest-build-provenance@v1
with:
subject-path: 'dist/*'

- name: Create GitHub Release
env:
GH_TOKEN: ${{ github.token }}
run: |
gh release create "${{ github.ref_name }}" \
--title "${{ github.ref_name }}" \
--generate-notes \
dist/*

- name: Upload attestation as release asset
env:
GH_TOKEN: ${{ github.token }}
run: |
# The attestation is stored by GitHub; download it and attach to release
gh release upload "${{ github.ref_name }}" \
".github/attestations/"* 2>/dev/null || true

publish-pypi:
name: Publish to PyPI
needs: build-and-attest
runs-on: ubuntu-latest
permissions:
id-token: write
attestations: write
contents: read

steps:
- name: Checkout source
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Install uv
uses: astral-sh/setup-uv@v3

- name: Build packages
run: uv build

- name: Generate provenance attestation
uses: actions/attest-build-provenance@v1
with:
subject-path: 'dist/*'

- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
attestations: true
92 changes: 92 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# =============================================================================
# Multi-stage Dockerfile — Agent Orchestration Platform
# Security: build-time configuration (ARG) is consumed only in intermediate
# stages and never propagated to the runtime image. The final stage
# declares zero build-time-only ARGs, preventing leakage into image history,
# labels, or environment variables.
# =============================================================================

# ── Stage 0: UV image resolver (resolves before COPY --from=) ───────────────
# Docker does not support variable expansion in COPY --from= source refs.
# The workaround is a separate FROM that resolves the ARG into a stage name.
ARG UV_VERSION=0.6.0
FROM ghcr.io/astral-sh/uv:${UV_VERSION} AS uv-image

# ── Stage 1: Builder (install dependencies) ─────────────────────────────────
# All build-time ARGs live here and are consumed before the COPY --from step.
ARG PYTHON_VERSION=3.11-slim

FROM python:${PYTHON_VERSION} AS builder

# ⚠️ BUILD-ONLY ARGUMENTS — these are consumed in this stage only and do NOT
# appear in the final image history, labels, or layers.
ARG BUILD_ENV=production
ARG PIP_INDEX_URL=https://pypi.org/simple
ARG PIP_TRUSTED_HOST=pypi.org

WORKDIR /build

# Install system build deps (will be discarded with this stage)
RUN apt-get update && apt-get install -y --no-install-recommends \
gcc \
libpq-dev \
&& rm -rf /var/lib/apt/lists/*

# Install uv for fast dependency resolution (from pre-resolved stage)
COPY --from=uv-image /uv /usr/local/bin/uv

# Copy dependency manifests
COPY pyproject.toml uv.lock ./

# Install production dependencies (frozen — matches lock file)
RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --frozen --no-dev --no-install-project

# ── Stage 2: Final runtime image ────────────────────────────────────────────
# This stage contains ZERO build-time-only ARG declarations. Every layer is
# immutable and auditable.
# Only ARG still present is the Python base image tag (semantic versioning
# metadata baked at build time — not a secret or configuration leak).
FROM python:${PYTHON_VERSION} AS final

# Only runtime‑relevant metadata LABELs — no build‑time configuration leaks.
LABEL org.opencontainers.image.title="Agent Orchestrator" \
org.opencontainers.image.description="Enterprise Agent Orchestration Platform" \
org.opencontainers.image.vendor="Agent Orchestration" \
org.opencontainers.image.licenses="Enterprise" \
org.opencontainers.image.documentation="https://docs.agent-orchestrator.io"

# Runtime environment variables (overridable at container start)
ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
APP_HOME=/app \
APP_PORT=8000

WORKDIR ${APP_HOME}

# Install only runtime system packages
RUN apt-get update && apt-get install -y --no-install-recommends \
libpq5 \
ca-certificates \
&& rm -rf /var/lib/apt/lists/*

# Copy the pre-built virtualenv (and only the venv) from the builder stage
COPY --from=builder /build/.venv /app/.venv

# Copy application source code
COPY src/ /app/src/
COPY pyproject.toml /app/

# Non-privileged runtime user
RUN useradd --system --no-create-home --shell /usr/sbin/nologin agentorch \
&& chown -R agentorch:agentorch /app
USER agentorch

# Health check
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD python -c "import http.client; conn=http.client.HTTPConnection('localhost',${APP_PORT}); conn.request('GET','/health'); assert conn.getresponse().status==200"

EXPOSE ${APP_PORT}

ENTRYPOINT ["/app/.venv/bin/uvicorn"]
CMD ["src.api.server:create_app", "--host", "0.0.0.0", "--port", "8000"]
10 changes: 10 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,16 @@ docker-up:
docker-down:
docker compose -f infra/docker-compose.yml down

docker-audit:
./infra/scripts/audit_image_metadata.sh agent-orchestrator:latest

docker-build-slim:
docker build --build-arg BUILD_ENV=production -t agent-orchestrator:latest -f Dockerfile .

docker-audit-slim:
docker build --build-arg BUILD_ENV=production -t agent-orchestrator:latest -f Dockerfile . \
&& ./infra/scripts/audit_image_metadata.sh agent-orchestrator:latest

# 2019-01-15T19:25:56 update

# 2019-01-24T16:02:28 update
Expand Down
31 changes: 31 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,37 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for contribution guidelines.

Report vulnerabilities via our [bug bounty program](SECURITY.md).

## Artifact Verification

Every release artifact published from a tagged build includes a **provenance attestation** generated by the GitHub release workflow. These attestations cryptographically link artifacts to the source repository, commit SHA, workflow run, and build environment.

### Verifying Release Artifacts

All releases are built and attested by the trusted release workflow. You can verify provenance using the [GitHub CLI](https://cli.github.com):

```bash
# Verify a release artifact against its attestation
gh attestation verify <path-to-artifact> \
--repo orchestration-agent/AgentOrchestration

# Example: verify the wheel package
gh attestation verify dist/agent_orchestrator-*.whl \
--repo orchestration-agent/AgentOrchestration
```

Verification confirms:
- **Source repository**: The artifact was built from `orchestration-agent/AgentOrchestration`
- **Commit SHA**: The exact revision used to produce the build
- **Workflow**: The artifact was produced by the trusted Release workflow
- **Artifact digest**: The file matches the attested content hash

### Attestation Storage

Provenance attestations are:
1. Uploaded to GitHub's attestation API during the release workflow
2. Attached as release assets for direct download
3. Verifiable offline using `gh attestation` or the [Sigstore](https://www.sigstore.dev) toolchain

## License

Enterprise License — see [LICENSE](LICENSE) for details.
Expand Down
Loading
Loading