Skip to main content

awwall

Egress allowlist that fails closed: declare what a workload may reach, watch everything else fail with the rule that denied it.

What It Does

awwall is a Python package that provides an egress allowlist policy engine. It works by:

  1. Failing closed by default — an empty policy denies all outbound connections
  2. Allowing only what you declare — add rules for hosts you trust
  3. Explaining denials — when a connection is blocked, you see exactly which rule (or lack thereof) caused it
  4. Multiple output formats — emit policy as JSON, /etc/hosts, or shell commands for iptables

Rules come in three types:

  • exact — example.com matches only example.com
  • domain — example.com matches example.com, api.example.com, v1.api.example.com, etc.
  • glob — *.example.com matches any subdomain

Installation

pip install awwall

The Adoption Guarantee

Block one outbound host for one workload and watch the call fail closed with the rule that denied it.

# 1. Create an empty policy (denies everything)
$ awwall list
No rules defined (default: deny everything)

# 2. Check if google.com is allowed
$ awwall check google.com
$ echo $?
1  # Denied!

# 3. Explain why
$ awwall explain google.com
DENIED: google.com
  Reason: Policy is empty (default deny)

# 4. Allow one host
$ awwall allow github.com --type domain --description "GitHub repositories"
Added: github.com (domain)

# 5. Check again
$ awwall check github.com
$ echo $?
0  # Allowed!

$ awwall check api.github.com
$ echo $?
0  # Subdomains allowed too (domain rule)

# 6. But google.com is still blocked
$ awwall check google.com
$ echo $?
1  # Still denied

$ awwall explain google.com
DENIED: google.com
  Reason: No rule matched (checked 1 rule(s))

CLI Commands

awwall allow <host>

Add a host to the allowlist.

awwall allow api.example.com                    # Inferred as exact match
awwall allow example.com --type domain          # Explicit domain rule (allows subdomains)
awwall allow *.cdn.com --type glob              # Glob pattern
awwall allow example.com --description "Prod API" --type exact

awwall check <host>

Check if a host is allowed (exit 0 = allowed, exit 1 = denied).

awwall check example.com        # Silent
awwall check example.com -v     # Verbose output

awwall explain <host>

Explain why a host is allowed or denied.

$ awwall explain api.example.com
ALLOWED: api.example.com
  Matched rule: example.com (type: domain)
  Description: Production API

awwall emit --format <format>

Emit policy in different formats.

awwall emit --format json                # Print as JSON
awwall emit --format hosts               # /etc/hosts format
awwall emit --format iptables            # Shell script with iptables rules
awwall emit --format json --output policy.json  # Save to file

awwall list

List all rules in the policy.

$ awwall list
Policy rules (2 total):

  1. api.example.com [exact] - Production API
  2. example.com [domain] - All subdomains

awwall --self-test

Run self-tests to verify the policy engine.

$ awwall --self-test
Running awwall self-tests...
  [PASS] Empty policy denies all
  [PASS] Exact match works
  [PASS] Exact match rejects subdomains
  [PASS] Domain match includes subdomains
  [PASS] Domain match rejects different domain
  [PASS] Glob pattern works
  [PASS] Glob rejects non-matching
  [PASS] Case insensitive matching
  [PASS] Whitespace trimming works
  [PASS] Rejects malformed policy
  [PASS] Missing policy file defaults to deny-all

All self-tests passed!

Policy File Format

By default, policies are stored in ~/.awwall/policy.json:

{
  "rules": [
    {
      "pattern": "api.example.com",
      "rule_type": "exact",
      "description": "Production API"
    },
    {
      "pattern": "example.com",
      "rule_type": "domain",
      "description": "All example.com subdomains"
    },
    {
      "pattern": "*.cdn.com",
      "rule_type": "glob",
      "description": "CDN patterns"
    }
  ]
}

Specify a different file with --policy-file:

awwall --policy-file /etc/awwall/prod.json check example.com

Exit Codes

  • 0 — Success (check: host allowed, command worked)
  • 1 — Denied (check: host blocked) or command failed
  • 2 — Cannot judge (malformed policy, missing file in strict mode)

A policy file that cannot be parsed exits with code 2 (cannot judge), never 0. This prevents silent failures.

Python API

from awwall import Policy, AllowRule

# Create a policy
policy = Policy([
    AllowRule("example.com", "exact"),
    AllowRule("api.other.com", "domain"),
])

# Check a host
allowed, matching_rule = policy.check("api.other.com")
if allowed:
    print(f"Allowed by rule: {matching_rule.pattern}")
else:
    print("Denied: no rule matched")

# Load from file
policy = Policy.from_file("/path/to/policy.json")

# Load from dict
policy = Policy.from_dict({"rules": [...]})

# Export
print(policy.to_hosts_format())
print(policy.to_iptables_format())

Testing

pytest tests/test_awwall.py -v

The test suite includes:

  • Default deny verification — empty policy blocks everything
  • Rule type tests — exact, domain, and glob matching
  • Negative tests — verify rules DON'T match when they shouldn't
  • Fail-closed proofs — malformed policy is treated as empty (deny all)
  • Roundtrip tests — export and reimport preserves semantics

Design Principles

  1. Fail closed by default — empty policy denies all, malformed policy denies all
  2. Transparent denials — every denied connection names the rule that caused it
  3. Simple rules — exact, domain suffix, and glob patterns cover 99% of real use cases
  4. No magic — no attempt to detect "safe" IPs or make assumptions
  5. Exportable — policy can be rendered for other tools (hosts file, iptables, etc.)

License

MIT

Metadata

Release files for awwall 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for awwall 0.1.0
File Size Uploaded Provenance
awwall-0.1.0.tar.gz 18.5 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for awwall 0.1.0
File Interpreter ABI Platform
awwall-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 36.3 kB

Release files / awwall-0.1.0.tar.gz

Download URL awwall-0.1.0.tar.gz
Size 18.5 kB
Tags Source
SHA-256 checksum
How to use checksums
8b875a7bf69a549310b580b92201a677a8cfd9c37a9580bad8c2ddb99f5461ce
BLAKE2b-256 checksum
How to use checksums
43b5bd709d36008ed9517f5ea4df98e31efe3e6509e23a0868de58c93ee206ad
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.10

Release files / awwall-0.1.0-py3-none-any.whl

Download URL awwall-0.1.0-py3-none-any.whl
Size 17.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2022ae6726ce6b36dd456137796da3e65b836cd5119495741e47bd4465226cb5
BLAKE2b-256 checksum
How to use checksums
f41250ba110929feb6ab31205826a321b990102a9b2c07c22b7ad0da240eb0c9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.10

Security for awwall 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page