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 .bandit
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[bandit]
exclude_dirs = tests,.venv,venv,build,dist
skips = B101
skips = B101,B110
24 changes: 24 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ on:
branches: [main]
pull_request:
branches: [main]
schedule:
# Nightly at 03:00 UTC
- cron: "0 3 * * *"
workflow_dispatch:

permissions:
contents: read
Expand Down Expand Up @@ -44,6 +48,26 @@ jobs:
name: coverage-report
path: coverage.xml

integration:
name: Mock Integration Tests
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

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

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e ".[dev,cli,mcp,route53]"

- name: Run mock integration tests
run: pytest tests/integration/ -m "not live" -v --tb=short

lint:
name: Lint
runs-on: ubuntu-latest
Expand Down
62 changes: 62 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
name: Release

on:
push:
tags:
- "v*"

permissions:
contents: write
id-token: write # Required for Sigstore keyless OIDC signing

jobs:
build:
name: Build & Release
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

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

- name: Install build tools
run: |
python -m pip install --upgrade pip
pip install build cyclonedx-bom

- name: Build wheel and sdist
run: python -m build

- name: Install package for SBOM
run: pip install dist/*.whl

- name: Generate SBOM
run: cyclonedx-py environment -o sbom.json --output-format json

- name: Install Cosign
uses: sigstore/cosign-installer@v3

- name: Sign release artifacts
run: |
for f in dist/*.whl dist/*.tar.gz; do
cosign sign-blob --yes "$f" --output-signature "${f}.sig" --output-certificate "${f}.pem"
done
cosign sign-blob --yes sbom.json --output-signature sbom.json.sig --output-certificate sbom.json.pem

- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
generate_release_notes: true
files: |
dist/*.whl
dist/*.whl.sig
dist/*.whl.pem
dist/*.tar.gz
dist/*.tar.gz.sig
dist/*.tar.gz.pem
sbom.json
sbom.json.sig
sbom.json.pem
31 changes: 29 additions & 2 deletions .github/workflows/security.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ jobs:
run: pip install bandit[toml]

- name: Run Bandit
run: bandit -r src/dns_aid -c .bandit -f json -o bandit-report.json || true
run: bandit -r src/dns_aid -c pyproject.toml -f json -o bandit-report.json

- name: Display results
if: always()
run: bandit -r src/dns_aid -c .bandit || true
run: bandit -r src/dns_aid -c pyproject.toml

- name: Upload Bandit report
if: always()
Expand All @@ -42,6 +42,33 @@ jobs:
name: bandit-report
path: bandit-report.json

sbom:
name: SBOM Generation
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

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

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install ".[dev,cli,mcp,route53]"
pip install cyclonedx-bom

- name: Generate SBOM
run: cyclonedx-py environment -o sbom.json --output-format json

- name: Upload SBOM
uses: actions/upload-artifact@v4
with:
name: sbom
path: sbom.json

dependency-audit:
name: Dependency Audit
runs-on: ubuntu-latest
Expand Down
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,28 @@ All notable changes to DNS-AID will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.6.0] - 2026-02-12

### Added
- **DNSSEC Enforcement** — `discover(require_dnssec=True)` checks the AD flag and raises `DNSSECError` if the response is unsigned
- **DANE Full Certificate Matching** — `verify(verify_dane_cert=True)` connects via TLS and compares the peer certificate against TLSA record data (SHA-256/SHA-512, full cert or SPKI selector)
- **Sigstore Release Signing** — Wheels, tarballs, and SBOMs are signed with Sigstore cosign (keyless OIDC) in the release workflow; `.sig` and `.pem` attestation files attached to GitHub Releases
- **Environment Variables Reference** — Documented all env vars (core, SDK, backend-specific) in `docs/getting-started.md`
- **Experimental Models Documentation** — Marked `agent_metadata` and `capability_model` modules as experimental with status docstrings

### Fixed
- **Route53 SVCB custom params** — Route53 rejects private-use SvcParamKeys (`key65001`–`key65006`). The Route53 backend now demotes custom BANDAID params to TXT records with `bandaid_` prefix, keeping the publish working without data loss
- **Cloudflare SVCB custom params** — Same demotion applied to the Cloudflare backend
- **CLI `--backend` help text** — Now lists all five backends (route53, cloudflare, infoblox, ddns, mock) instead of just "route53, mock"
- **SECURITY.md contact** — Updated from placeholder LF mailing list to interim maintainer email
- **Bandit config** — Migrated from `.bandit` INI to `pyproject.toml` `[tool.bandit]` for newer bandit compatibility
- **CLI ANSI escape codes** — Stripped Rich/Typer ANSI codes in test assertions for Python 3.13 compatibility

### Notes
- BIND/DDNS backends natively support custom SVCB params (`key65001`–`key65006`) — no demotion needed
- DNSSEC enforcement defaults to `False` (backwards compatible)
- DANE cert matching defaults to `False` (advisory TLSA existence check remains the default)

## [0.5.1] - 2026-02-05

### Fixed
Expand Down
23 changes: 11 additions & 12 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
# dns-aid-mcp

# Use multi-stage build for smaller final image
FROM python:3.11-slim AS builder
# Pin base image with digest for reproducible builds
FROM python:3.11-slim@sha256:6ed5bff4d7396e3244b0f3c2fe578c87862efedd3e5e8cebd14a4428ec39ee5a AS builder

WORKDIR /app

Expand All @@ -22,34 +23,32 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
gcc \
&& rm -rf /var/lib/apt/lists/*

# Install Python dependencies
# Build wheels instead of editable install
COPY pyproject.toml README.md ./
COPY src/ src/

RUN pip install --no-cache-dir --upgrade pip \
&& pip install --no-cache-dir -e ".[mcp,route53]"
&& pip wheel --no-cache-dir --wheel-dir /wheels ".[mcp,route53]" \
&& pip wheel --no-cache-dir --wheel-dir /wheels .

# Production image
FROM python:3.11-slim AS production
FROM python:3.11-slim@sha256:6ed5bff4d7396e3244b0f3c2fe578c87862efedd3e5e8cebd14a4428ec39ee5a AS production

LABEL org.opencontainers.image.title="DNS-AID MCP Server"
LABEL org.opencontainers.image.description="DNS-based Agent Identification and Discovery"
LABEL org.opencontainers.image.source="https://github.com/iracic82/dns-aid"
LABEL org.opencontainers.image.source="https://github.com/iracic82/dns-aid-core"
LABEL org.opencontainers.image.licenses="Apache-2.0"
LABEL org.opencontainers.image.sbom="cyclonedx"

# Create non-root user for security
RUN groupadd --gid 1000 dnsaid \
&& useradd --uid 1000 --gid dnsaid --shell /bin/bash --create-home dnsaid

WORKDIR /app

# Copy installed packages from builder
COPY --from=builder /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages
COPY --from=builder /usr/local/bin/dns-aid* /usr/local/bin/

# Copy application
COPY --chown=dnsaid:dnsaid src/ src/
COPY --chown=dnsaid:dnsaid pyproject.toml README.md ./
# Install from pre-built wheels (no source code needed)
COPY --from=builder /wheels /wheels
RUN pip install --no-cache-dir /wheels/*.whl && rm -rf /wheels

# Switch to non-root user
USER dnsaid
Expand Down
4 changes: 4 additions & 0 deletions GOVERNANCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ Any Contributor can be nominated for Committer status by an existing Committer.
- Understanding of the DNS-AID architecture and IETF draft
- Adherence to the Code of Conduct

## Maintainers

See [MAINTAINERS.md](MAINTAINERS.md) for the current list of maintainers and open roles. The project is actively seeking additional maintainers to ensure long-term sustainability and diverse representation across DNS providers, security expertise, and standards bodies.

## Modifying Governance

Changes to this governance document require a two-thirds majority vote of all Committers.
Expand Down
34 changes: 34 additions & 0 deletions MAINTAINERS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Maintainers

This file lists the current maintainers of the DNS-AID project. The project is actively seeking additional maintainers to ensure long-term sustainability under the Linux Foundation.

## Current Maintainers

| Name | GitHub | Affiliation | Role | Since |
|------|--------|-------------|------|-------|
| Ivan Racic | [@iracic82](https://github.com/iracic82) | Independent | Project Lead | 2024-12 |

## Desired Roles

The project is looking for maintainers in the following areas:

| Role | Responsibilities | Status |
|------|-----------------|--------|
| DNS Standards Lead | IETF draft alignment, RFC compliance review | **Open** |
| Security Lead | DNSSEC/DANE validation, vulnerability triage | **Open** |
| Backend Maintainer | DNS provider backends (Route53, Cloudflare, Infoblox, DDNS) | **Open** |
| CI/Release Engineer | GitHub Actions, release automation, SBOM generation | **Open** |
| Documentation Lead | User guides, API docs, architecture documentation | **Open** |

## How to Become a Maintainer

See [GOVERNANCE.md](GOVERNANCE.md) for the process. In brief:

1. Contribute sustained, high-quality PRs over at least 3 months
2. Be nominated by an existing maintainer
3. Receive approval via Committer vote

## Contact

- GitHub Issues: [dns-aid-core/issues](https://github.com/iracic82/dns-aid-core/issues)
- Discussions: [dns-aid-core/discussions](https://github.com/iracic82/dns-aid-core/discussions)
26 changes: 17 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,11 @@ _booking._mcp._agents.example.com. SVCB 1 mcp.example.com. alpn="mcp" port=443 \
| `policy` | URI to agent policy document |
| `realm` | Multi-tenant scope identifier |

> **Note:** Route 53 and Cloudflare do not support private-use SVCB SvcParamKeys (`key65001`–`key65006`).
> DNS-AID automatically demotes these parameters to TXT records with a `bandaid_` prefix (e.g.,
> `bandaid_realm=production`), preserving all metadata without data loss. BIND/DDNS (RFC 2136)
> backends natively support custom SVCB params — no demotion needed.

This allows any DNS client to discover agents without proprietary protocols or central registries.

### Discovery Flow (BANDAID Draft Aligned)
Expand Down Expand Up @@ -558,14 +563,17 @@ Infoblox UDDI (Universal DDI) is Infoblox's cloud-native DDI platform. DNS-AID s
> The draft requires ServiceMode SVCB records (priority > 0) with mandatory `alpn` and `port`
> parameters. Infoblox UDDI's limitation is a platform constraint, not a DNS-AID limitation.

| BANDAID Requirement | Route 53 | Infoblox UDDI |
|---------------------|----------|---------------|
| ServiceMode (priority > 0) | ✅ | ❌ |
| `alpn` parameter | ✅ | ❌ |
| `port` parameter | ✅ | ❌ |
| `mandatory` key | ✅ | ❌ |
| BANDAID Requirement | Route 53 | Cloudflare | DDNS (BIND) | Infoblox UDDI |
|---------------------|----------|------------|-------------|---------------|
| ServiceMode (priority > 0) | ✅ | ✅ | ✅ | ❌ |
| `alpn` parameter | ✅ | ✅ | ✅ | ❌ |
| `port` parameter | ✅ | ✅ | ✅ | ❌ |
| `mandatory` key | ✅ | ✅ | ✅ | ❌ |
| Custom SVCB params (`cap`, `realm`, etc.) | ⚠️ TXT | ⚠️ TXT | ✅ Native | ❌ |

**⚠️ TXT** = Custom BANDAID params auto-demoted to TXT records with `bandaid_` prefix (no data loss).

**For full BANDAID compliance, use Route 53 or another RFC 9460-compliant DNS provider.**
**For full BANDAID compliance with native custom SVCB params, use DDNS (BIND/RFC 2136). Route 53 and Cloudflare support all standard SVCB params with automatic TXT demotion for custom params.**

DNS-AID stores `alpn` and `port` in TXT records as a fallback for Infoblox UDDI, but this is
a workaround and not standard-compliant for agent discovery.
Expand Down Expand Up @@ -645,7 +653,7 @@ DDNS (Dynamic DNS) is a universal backend that works with any DNS server support
- **Universal**: Works with BIND, Windows DNS, PowerDNS, Knot, and any RFC 2136 server
- **No vendor lock-in**: Standard protocol, no proprietary APIs
- **On-premise friendly**: Perfect for enterprise internal DNS
- **Full BANDAID compliance**: Supports ServiceMode SVCB with all parameters
- **Full BANDAID compliance**: Supports ServiceMode SVCB with all standard parameters (custom BANDAID params auto-demoted to TXT)

### Cloudflare Setup

Expand Down Expand Up @@ -713,7 +721,7 @@ Cloudflare DNS is ideal for demos, workshops, and quick prototyping thanks to it
- **SVCB support**: Full RFC 9460 compliance with SVCB Type 64 records
- **Global anycast**: Fast DNS resolution worldwide
- **Simple API**: Well-documented REST API v4
- **Full BANDAID compliance**: Supports ServiceMode SVCB with all parameters
- **Full BANDAID compliance**: Supports ServiceMode SVCB with all standard parameters (custom BANDAID params auto-demoted to TXT)

## Why DNS-AID?

Expand Down
Loading