Skip to content
Merged
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
2 changes: 1 addition & 1 deletion .github/workflows/smoke-copilot.lock.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ The `--` separator divides firewall options from the command to run.

- [Quick start](docs/quickstart.md) — install, verify, and run your first command
- [Usage guide](docs/usage.md) — CLI flags, domain allowlists, examples
- [AWF config schema](docs/awf-config.schema.json) — machine-readable JSON Schema for JSON/YAML configs
- [AWF config spec](docs/awf-config-spec.md) — normative processing and precedence rules for tooling/compiler integration
- [Enterprise configuration](docs/enterprise-configuration.md) — GitHub Enterprise Cloud and Server setup
- [Chroot mode](docs/chroot-mode.md) — use host binaries with network isolation
- [API proxy sidecar](docs/api-proxy-sidecar.md) — secure credential management for LLM APIs
Expand Down
50 changes: 40 additions & 10 deletions containers/agent/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,35 @@ ARG BASE_IMAGE=ubuntu:22.04

FROM ${BASE_IMAGE}

# Switch to Azure apt mirror for faster, more reliable package fetches in CI
# GitHub Actions runners are Azure-hosted; azure.archive.ubuntu.com is geographically closer
# Handles both traditional sources.list (jammy) and DEB822 format (noble+)
RUN if [ -f /etc/apt/sources.list ]; then \
sed -i 's|http://archive.ubuntu.com|http://azure.archive.ubuntu.com|g' /etc/apt/sources.list; \
sed -i 's|http://security.ubuntu.com|http://azure.archive.ubuntu.com|g' /etc/apt/sources.list; \
fi && \
if [ -d /etc/apt/sources.list.d ]; then \
find /etc/apt/sources.list.d -name '*.sources' -exec \
sed -i 's|http://archive.ubuntu.com|http://azure.archive.ubuntu.com|g' {} + 2>/dev/null || true; \
find /etc/apt/sources.list.d -name '*.sources' -exec \
sed -i 's|http://security.ubuntu.com|http://azure.archive.ubuntu.com|g' {} + 2>/dev/null || true; \
fi

# Install required packages and Node.js 22
# Note: Some packages may already exist in runner-like base images, apt handles this gracefully
# Retry logic handles transient 404s when Ubuntu archive supersedes package versions mid-build
# apt_update_retry: retries up to 3 times with backoff to survive prolonged mirror syncs
RUN set -eux; \
apt_update_retry() { \
local i; for i in 1 2 3; do \
rm -rf /var/lib/apt/lists/* && apt-get update && return 0; \
echo "apt-get update attempt $i/3 failed, retrying in $((i*10))s..." >&2; sleep $((i*10)); \
done; return 1; \
}; \
PKGS="iptables curl ca-certificates git gh gnupg dnsutils net-tools netcat-openbsd gosu libcap2-bin"; \
apt-get update && \
apt_update_retry && \
( apt-get install -y --no-install-recommends $PKGS || \
(echo "apt-get install failed, retrying with fresh package index..." && \
rm -rf /var/lib/apt/lists/* && \
apt-get update && \
apt_update_retry && \
apt-get install -y --no-install-recommends $PKGS) ) && \
# Prefer system binaries over runner toolcache (e.g., act images) for Node checks.
export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$PATH" && \
Expand All @@ -39,22 +58,33 @@ RUN set -eux; \
# These packages are commonly needed by workflows and avoid agents spending time installing them manually
# See: https://github.com/actions/runner-images/blob/main/images/ubuntu/Ubuntu2204-Readme.md
RUN set -eux; \
apt_update_retry() { \
local i; for i in 1 2 3; do \
rm -rf /var/lib/apt/lists/* && apt-get update && return 0; \
echo "apt-get update attempt $i/3 failed, retrying in $((i*10))s..." >&2; sleep $((i*10)); \
done; return 1; \
}; \
PARITY_PKGS="libgdiplus libev-dev libssl-dev php-intl php-gd"; \
apt-get update && \
apt_update_retry && \
( apt-get install -y --no-install-recommends $PARITY_PKGS || \
(echo "apt-get install failed, retrying with fresh package index..." && \
rm -rf /var/lib/apt/lists/* && \
apt-get update && \
apt_update_retry && \
apt-get install -y --no-install-recommends $PARITY_PKGS) ) && \
rm -rf /var/lib/apt/lists/*

# Upgrade all packages to pick up security patches
# Addresses CVE-2023-44487 (HTTP/2 Rapid Reset) and other known vulnerabilities
# Retry logic handles transient mirror sync failures during apt-get update
RUN apt-get update && apt-get upgrade -y && rm -rf /var/lib/apt/lists/* || \
RUN apt_update_retry() { \
local i; for i in 1 2 3; do \
rm -rf /var/lib/apt/lists/* && apt-get update && return 0; \
echo "apt-get update attempt $i/3 failed, retrying in $((i*10))s..." >&2; sleep $((i*10)); \
done; return 1; \
}; \
apt_update_retry && \
apt-get upgrade -y && rm -rf /var/lib/apt/lists/* || \
(echo "apt-get upgrade failed, retrying with fresh package index..." && \
rm -rf /var/lib/apt/lists/* && \
apt-get update && apt-get upgrade -y && rm -rf /var/lib/apt/lists/*)
apt_update_retry && apt-get upgrade -y && rm -rf /var/lib/apt/lists/*)

# Create non-root user with UID/GID matching host user
# This allows the user command to run with appropriate permissions
Expand Down
26 changes: 23 additions & 3 deletions containers/squid/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,13 +1,33 @@
FROM ubuntu/squid:latest

# Switch to Azure apt mirror for faster, more reliable package fetches in CI
# GitHub Actions runners are Azure-hosted; azure.archive.ubuntu.com is geographically closer
# Handles both traditional sources.list (jammy) and DEB822 format (noble+)
RUN if [ -f /etc/apt/sources.list ]; then \
sed -i 's|http://archive.ubuntu.com|http://azure.archive.ubuntu.com|g' /etc/apt/sources.list; \
sed -i 's|http://security.ubuntu.com|http://azure.archive.ubuntu.com|g' /etc/apt/sources.list; \
fi && \
if [ -d /etc/apt/sources.list.d ]; then \
find /etc/apt/sources.list.d -name '*.sources' -exec \
sed -i 's|http://archive.ubuntu.com|http://azure.archive.ubuntu.com|g' {} + 2>/dev/null || true; \
find /etc/apt/sources.list.d -name '*.sources' -exec \
sed -i 's|http://security.ubuntu.com|http://azure.archive.ubuntu.com|g' {} + 2>/dev/null || true; \
fi

# Install additional tools for debugging, healthcheck, and SSL Bump
# Retry logic handles transient 404s when Ubuntu archive supersedes package versions mid-build
# apt_update_retry: retries up to 3 times with backoff to survive prolonged mirror syncs
RUN set -eux; \
apt_update_retry() { \
local i; for i in 1 2 3; do \
rm -rf /var/lib/apt/lists/* && apt-get update && return 0; \
echo "apt-get update attempt $i/3 failed, retrying in $((i*10))s..." >&2; sleep $((i*10)); \
done; return 1; \
}; \
PKGS="curl dnsutils net-tools netcat-openbsd openssl squid-openssl"; \
apt-get update && \
apt_update_retry && \
apt-get install -y --only-upgrade gpgv && \
( apt-get install -y --no-install-recommends $PKGS || \
(rm -rf /var/lib/apt/lists/* && apt-get update && \
(apt_update_retry && \
apt-get install -y --no-install-recommends $PKGS) ) && \
rm -rf /var/lib/apt/lists/*

Expand Down
116 changes: 116 additions & 0 deletions docs/awf-config-spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# AWF Configuration Specification (W3C-style)

## Status of This Document

This document defines the canonical configuration model for AWF (`awf`) and is intended for:

- `awf` CLI runtime loading (`--config`)
- tooling that compiles workflows to AWF invocations (including `gh-aw`)
- IDE/static validation via JSON Schema

The machine-readable schema is published at:

- `docs/awf-config.schema.json`

## 1. Conformance

The normative keywords in this document are to be interpreted as described in RFC 2119.

An AWF config document is conforming when:

1. It is valid JSON or YAML.
2. Its data model satisfies `docs/awf-config.schema.json`.
3. Unknown properties are not present (closed-world schema).

## 2. Processing Model

1. The user invokes `awf --config <path|-> -- <command>`.
2. If `<path>` is `-`, AWF reads configuration bytes from stdin.
3. If `<path>` ends with `.json`, AWF parses as JSON.
4. If `<path>` ends with `.yaml` or `.yml`, AWF parses as YAML.
5. Otherwise, AWF attempts JSON parse first, then YAML parse.
6. AWF validates the parsed document and fails fast on validation errors.
7. AWF maps config fields to CLI option semantics.
8. **CLI options MUST take precedence over config file values**.

## 3. Precedence Rules

The effective configuration order is:

1. AWF internal defaults
2. Config file (`--config`)
3. Explicit CLI flags

This precedence model allows reusable checked-in configs with environment-specific CLI overrides.

## 4. Data Model

The root object MAY contain:

- `$schema`
- `network`
- `apiProxy`
- `security`
- `container`
- `environment`
- `logging`
- `rateLimiting`

Section semantics and constraints are defined by `docs/awf-config.schema.json`.

## 5. CLI Mapping (Normative)

Tools generating AWF invocations (such as `gh-aw`) SHOULD use this mapping:

- `network.allowDomains[]` → `--allow-domains <csv>`
- `network.blockDomains[]` → `--block-domains <csv>`
- `network.dnsServers[]` → `--dns-servers <csv>`
- `network.upstreamProxy` → `--upstream-proxy`
- `apiProxy.enabled` → `--enable-api-proxy`
- `apiProxy.targets.<provider>.host` → `--<provider>-api-target`
- `apiProxy.targets.openai.basePath` → `--openai-api-base-path`
- `apiProxy.targets.anthropic.basePath` → `--anthropic-api-base-path`
- `apiProxy.targets.gemini.basePath` → `--gemini-api-base-path`
- `security.sslBump` → `--ssl-bump`
- `security.enableDlp` → `--enable-dlp`
- `security.enableHostAccess` → `--enable-host-access`
- `security.allowHostPorts` → `--allow-host-ports`
- `security.allowHostServicePorts` → `--allow-host-service-ports`
- `security.difcProxy.host` → `--difc-proxy-host`
- `security.difcProxy.caCert` → `--difc-proxy-ca-cert`
- `container.memoryLimit` → `--memory-limit`
- `container.agentTimeout` → `--agent-timeout`
- `container.enableDind` → `--enable-dind`
- `container.workDir` → `--work-dir`
- `container.containerWorkDir` → `--container-workdir`
- `container.imageRegistry` → `--image-registry`
- `container.imageTag` → `--image-tag`
- `container.skipPull` → `--skip-pull`
- `container.buildLocal` → `--build-local`
- `container.agentImage` → `--agent-image`
- `container.tty` → `--tty`
- `container.dockerHost` → `--docker-host`
- `environment.envFile` → `--env-file`
- `environment.envAll` → `--env-all`
- `environment.excludeEnv[]` → repeated `--exclude-env`
- `logging.logLevel` → `--log-level`
- `logging.diagnosticLogs` → `--diagnostic-logs`
- `logging.auditDir` → `--audit-dir`
- `logging.proxyLogsDir` → `--proxy-logs-dir`
- `logging.sessionStateDir` → `--session-state-dir`
- `rateLimiting.enabled: false` → `--no-rate-limit`
- `rateLimiting.requestsPerMinute` → `--rate-limit-rpm`
- `rateLimiting.requestsPerHour` → `--rate-limit-rph`
- `rateLimiting.bytesPerMinute` → `--rate-limit-bytes-pm`

## 6. Stdin Mode

AWF MUST support `--config -` for programmatic/pipeline scenarios.

## 7. Error Reporting

On parse or validation failure, AWF MUST:

1. exit non-zero
2. print an error describing location and reason
3. avoid partial execution
Loading
Loading