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
86 changes: 86 additions & 0 deletions .github/workflows/test-examples.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
name: Examples Test

on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch:

permissions:
contents: read

jobs:
test-examples:
name: Test Examples
runs-on: ubuntu-latest
timeout-minutes: 15

steps:
- name: Checkout repository
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4

- name: Setup Node.js
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: '20'
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Build project
run: npm run build

- name: Install awf globally
run: sudo npm link

- name: Pre-test cleanup
run: sudo ./scripts/ci/cleanup.sh

- name: Make examples executable
run: chmod +x examples/*.sh

- name: Test basic-curl.sh
run: |
echo "=== Testing basic-curl.sh ==="
sudo ./examples/basic-curl.sh

- name: Test using-domains-file.sh
run: |
echo "=== Testing using-domains-file.sh ==="
sudo ./examples/using-domains-file.sh

- name: Test debugging.sh
run: |
echo "=== Testing debugging.sh ==="
sudo ./examples/debugging.sh

- name: Test blocked-domains.sh
run: |
echo "=== Testing blocked-domains.sh ==="
sudo ./examples/blocked-domains.sh

- name: Test docker-in-docker.sh
run: |
echo "=== Testing docker-in-docker.sh ==="
sudo ./examples/docker-in-docker.sh

# Note: github-copilot.sh is skipped as it requires GITHUB_TOKEN for Copilot CLI
# To test it, you would need to set up a secret with a valid Copilot token

- name: Post-test cleanup
if: always()
run: sudo ./scripts/ci/cleanup.sh

- name: Upload logs on failure
if: failure()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: examples-test-logs
path: |
/tmp/*-test.log
/tmp/awf-*/
/tmp/awf-agent-logs-*/
/tmp/squid-logs-*/
retention-days: 7
42 changes: 42 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# AWF Examples

This directory contains example scripts demonstrating common ways to use the Agentic Workflow Firewall (`awf`).

## Prerequisites

- Docker running on your machine
- `awf` installed (see [installation instructions](../README.md#get-started-fast))
- `sudo` access (required for iptables manipulation)

## Examples

| File | Description |
|------|-------------|
| [basic-curl.sh](basic-curl.sh) | Simple HTTP request through the firewall |
| [github-copilot.sh](github-copilot.sh) | Using GitHub Copilot CLI with the firewall |
| [docker-in-docker.sh](docker-in-docker.sh) | Running Docker containers inside the firewall |
| [using-domains-file.sh](using-domains-file.sh) | Using a file to specify allowed domains |
| [blocked-domains.sh](blocked-domains.sh) | Blocking specific domains with allowlist/blocklist |
| [debugging.sh](debugging.sh) | Debug mode with log inspection |
| [domains.txt](domains.txt) | Example domain allowlist file |

## Running Examples

Each example is a standalone shell script. Run with:

```bash
# Make executable (if needed)
chmod +x examples/*.sh

# Run an example
./examples/basic-curl.sh
```

> **Note:** Most examples require `sudo` for iptables manipulation. The scripts will prompt for sudo access if needed.

## Domain Matching

AWF automatically matches subdomains. For example:
- `github.com` matches `github.com`, `api.github.com`, `raw.githubusercontent.com`, etc.

See [domains.txt](domains.txt) for domain file format examples.
24 changes: 24 additions & 0 deletions examples/basic-curl.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/bin/bash
# Example: Basic curl request through the firewall
#
# This example demonstrates the simplest use case: making an HTTP request
# through the firewall with a specific domain allowlist.
#
# Usage: sudo ./examples/basic-curl.sh

set -e

echo "=== AWF Basic Curl Example ==="
echo ""
echo "Making a request to api.github.com (allowed)"
echo ""

# Simple curl request to GitHub API
# The --allow-domains flag specifies which domains are accessible
# Subdomains are automatically included (github.com includes api.github.com)
sudo awf \
--allow-domains github.com \
-- curl -s https://api.github.com | head -20

echo ""
echo "=== Example Complete ==="
50 changes: 50 additions & 0 deletions examples/blocked-domains.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#!/bin/bash
# Example: Domain blocking with allowlist and blocklist
#
# This example demonstrates how to use both allow and block lists.
# Blocked domains take precedence over allowed domains, enabling
# fine-grained control over network access.
#
# Usage: sudo ./examples/blocked-domains.sh

set -e

echo "=== AWF Domain Blocking Example ==="
echo ""

echo "1. Allow github.com but block a specific subdomain..."
echo ""
echo " Allowing: github.com (includes all subdomains)"
echo " Blocking: gist.github.com"
echo ""

# Block gist.github.com specifically while allowing other github.com subdomains
# api.github.com should work, gist.github.com should be blocked
echo "Attempting to access api.github.com (should succeed):"
sudo awf \
--allow-domains github.com \
--block-domains gist.github.com \
-- curl -s -o /dev/null -w "%{http_code}" https://api.github.com && echo " - OK"

echo ""
echo "Attempting to access gist.github.com (should be blocked):"
sudo awf \
--allow-domains github.com \
--block-domains gist.github.com \
-- curl -f --max-time 10 https://gist.github.com 2>&1 || echo " - Blocked (expected)"

echo ""
echo "2. Using wildcard patterns in blocklist..."
echo ""

# Block all subdomains matching a pattern
# Note: awf supports wildcards (*) in domain patterns
# Patterns are converted to regex internally (e.g., * becomes .*)
echo "Blocking all internal-* subdomains while allowing example.com:"
sudo awf \
--allow-domains example.com \
--block-domains 'internal-*.example.com' \
-- 'echo "Firewall configured with wildcard blocklist"'

echo ""
echo "=== Example Complete ==="
52 changes: 52 additions & 0 deletions examples/debugging.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#!/bin/bash
# Example: Debug mode with log inspection
#
# This example shows how to use debug logging and keep containers
# running after command execution for inspection.
#
# Usage: sudo ./examples/debugging.sh

set -e

echo "=== AWF Debugging Example ==="
echo ""

echo "Running with debug logging enabled..."
echo "Use --log-level debug to see detailed output"
echo "Use --keep-containers to preserve containers after execution"
echo ""

# Run with debug logging
# --log-level debug: Shows configuration details, iptables rules, etc.
# --keep-containers: Keeps containers running for inspection after command exits
sudo awf \
--allow-domains github.com \
--log-level debug \
-- curl -s https://api.github.com/zen

echo ""
echo "=== Inspecting Logs ==="
echo ""

# After a run, logs are automatically preserved
# Note: These paths are based on awf's default behavior and may change in future versions
echo "Agent logs are saved to: /tmp/awf-agent-logs-<timestamp>"
echo "Squid logs are saved to: /tmp/squid-logs-<timestamp>"
echo ""

# List preserved log directories
echo "Available log directories:"
ls -d /tmp/awf-agent-logs-* /tmp/squid-logs-* 2>/dev/null || echo " (no logs found - run a command first)"

echo ""
echo "To view live logs from a running container (with --keep-containers):"
echo " docker logs awf-squid # View proxy logs"
echo " docker logs awf-agent # View agent logs"
echo ""
echo "To view preserved Squid access logs:"
echo " sudo cat /tmp/squid-logs-*/access.log"
echo ""
echo "To find blocked requests:"
echo " sudo grep 'TCP_DENIED' /tmp/squid-logs-*/access.log"
echo ""
echo "=== Example Complete ==="
39 changes: 39 additions & 0 deletions examples/docker-in-docker.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/bin/bash
# Example: Running Docker containers inside the firewall (Docker-in-Docker)
#
# This example demonstrates how spawned Docker containers inherit
# the firewall restrictions. All network traffic from nested containers
# is also filtered through the domain allowlist.
#
# Usage: sudo ./examples/docker-in-docker.sh

set -e

echo "=== AWF Docker-in-Docker Example ==="
echo ""

# Docker-in-Docker requires access to Docker Hub for pulling images
DOCKER_DOMAINS="registry-1.docker.io,auth.docker.io,production.cloudflare.docker.com"

echo "1. Running curl container with api.github.com allowed..."
echo ""

# This should succeed - api.github.com is in the allowlist
sudo awf \
--allow-domains "api.github.com,$DOCKER_DOMAINS" \
-- 'docker run --rm curlimages/curl -s https://api.github.com/zen'

echo ""
echo "2. Attempting to access example.com (should be blocked)..."
echo ""

# This should fail - example.com is NOT in the allowlist
# Capture exit code to show what a blocked request looks like
sudo awf \
--allow-domains "$DOCKER_DOMAINS" \
-- 'docker run --rm curlimages/curl -f --max-time 10 https://example.com' || echo "Exit code: $? (blocked as expected)"

echo ""
echo "(The above error is expected - example.com was blocked by the firewall)"
echo ""
echo "=== Example Complete ==="
40 changes: 40 additions & 0 deletions examples/github-copilot.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/bin/bash
# Example: Using GitHub Copilot CLI with the firewall
#
# This example shows how to run GitHub Copilot CLI through the firewall.
# Copilot requires access to several GitHub domains.
#
# Prerequisites:
# - GitHub Copilot CLI installed: npm install -g @github/copilot
# - GITHUB_TOKEN environment variable set
#
# Usage: sudo -E ./examples/github-copilot.sh

set -e

echo "=== AWF GitHub Copilot CLI Example ==="
echo ""

# Check for GITHUB_TOKEN
if [ -z "$GITHUB_TOKEN" ]; then
echo "Error: GITHUB_TOKEN environment variable is not set"
echo "Set it with: export GITHUB_TOKEN='your_token'"
exit 1
fi

echo "Running GitHub Copilot CLI through the firewall..."
echo ""

# Run Copilot CLI with required domains
# Use sudo -E to preserve environment variables (especially GITHUB_TOKEN)
# Required domains:
# - github.com: GitHub API access
# - api.github.com: GitHub REST API
# - api.enterprise.githubcopilot.com: Copilot API endpoint
# - registry.npmjs.org: NPM package registry (for npx)
sudo -E awf \
--allow-domains github.com,api.github.com,api.enterprise.githubcopilot.com,registry.npmjs.org \
-- 'npx @github/copilot --prompt "What is 2+2?" --no-mcp'

echo ""
echo "=== Example Complete ==="
34 changes: 34 additions & 0 deletions examples/using-domains-file.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#!/bin/bash
# Example: Using a domains file for allowed domains
#
# Instead of specifying domains on the command line, you can use a file
# containing the list of allowed domains. This is useful for:
# - Managing large domain lists
# - Sharing domain configurations across teams
# - Version controlling domain allowlists
#
# Usage: sudo ./examples/using-domains-file.sh

set -e

echo "=== AWF Using Domains File Example ==="
echo ""

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
DOMAINS_FILE="$SCRIPT_DIR/domains.txt"

echo "Using domains file: $DOMAINS_FILE"
echo ""
echo "Contents of domains file:"
echo "---"
cat "$DOMAINS_FILE"
echo "---"
echo ""

# Use --allow-domains-file to specify domains from a file
sudo awf \
--allow-domains-file "$DOMAINS_FILE" \
-- curl -s https://api.github.com | head -10

echo ""
echo "=== Example Complete ==="
Loading