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
15 changes: 14 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ DIRECT_AGENT_CORE_PKGS = ./pkg/atls/... ./pkg/clients/... ./pkg/agtp/... ./pkg/p
PRODUCTION_CONSUMER_PKGS = ./examples/protected-change-consumer
CGO_ENABLED ?= 0
GOARCH ?= amd64
A2A_GOOS ?= $(shell go env GOOS)
A2A_GOARCH ?= $(shell go env GOARCH)
VERSION ?= $(shell git describe --abbrev=0 --tags --always)
A2A_VERSION ?= $(shell git describe --tags --always --dirty)
COMMIT ?= $(shell git rev-parse HEAD)
TIME ?= $(shell date +%F_%T)
EMBED_ENABLED ?= 0
Expand All @@ -23,14 +26,20 @@ define compile_service
-o ${BUILD_DIR}/agents-secure-binding-$(1) ./cmd/$(1)
endef

.PHONY: all $(SERVICES) install clean product-security-gate fuzz-smoke
.PHONY: all $(SERVICES) a2a-test install install-a2a-test clean product-security-gate fuzz-smoke

all: $(SERVICES)

$(SERVICES):
$(call compile_service,$@)
@if [ "$@" = "cli" ] || [ "$@" = "manager" ]; then $(MAKE) build-igvm; fi

a2a-test:
@mkdir -p $(BUILD_DIR)
CGO_ENABLED=$(CGO_ENABLED) GOOS=$(A2A_GOOS) GOARCH=$(A2A_GOARCH) \
go build -ldflags "-s -w -X main.version=$(A2A_VERSION) -X main.commit=$(COMMIT)" \
-o $(BUILD_DIR)/asb-a2a-test ./examples/a2a-multiprocess

protoc:
protoc -I. --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative agent/agent.proto
protoc -I. --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative manager/manager.proto
Expand All @@ -51,6 +60,10 @@ install: $(SERVICES)
install -d $(CONFIG_DIR)
install agents-secure-binding-manager.env $(CONFIG_DIR)/agents-secure-binding-manager.env

install-a2a-test: a2a-test
install -d $(INSTALL_DIR)
install $(BUILD_DIR)/asb-a2a-test $(INSTALL_DIR)/asb-a2a-test

clean:
rm -rf $(BUILD_DIR)

Expand Down
116 changes: 97 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
# Agents Secure Binding

Agents Secure Binding is a verifier-side acceptance profile and implementation
repository for binding an Agent identity to the session, context, attestation
facts, and local policy under which it is accepted.
**Verified interaction for independently operated AI Agents.**

A verifier accepts an Agent only when a verified authority grant,
holder-of-key proof, accepted TLS or exported-authenticator session, freshness
and replay state, any required attestation result, and verifier-local policy
all describe the same intended interaction.
Agents Secure Binding (ASB) lets Agent runtimes exchange LLM-generated messages
through a verified boundary. The receiver authenticates the sending Agent,
binds the exact request to the accepted session, checks its authority and
replay state, and only then releases the request to a local model or tool.

The LLM is not the security principal. It generates content; ASB decides which
Agent sent it, what that Agent may do, and whether the interaction is fresh and
intended. Model choice remains separate from identity and authority.

ASB is also the verifier-side acceptance profile and Go implementation behind
that boundary. A verifier accepts an Agent only when its grant, proof, session,
attestation facts, and local policy describe the same interaction.

The primary failure class is context diversion: accepting cryptographically
valid material for a different service, tenant, Agent, task, delegation, or
Expand All @@ -21,6 +27,45 @@ non-Split-Knowledge protected-change consumer. See
[`docs/API_COMPATIBILITY.md`](docs/API_COMPATIBILITY.md) and
[`docs/production-deployment-profile.md`](docs/production-deployment-profile.md).

## Secure LLM-to-LLM Conversation

The product-candidate `llm-conversation` workflow connects two separately
configured OpenAI-compatible models:

```text
Agent A + LLM A
|
| exact, bound A2A request
v
ASB boundary: mTLS + grant + session + attestation + policy + replay
|
v
Agent B + LLM B
```

Agent A's model writes the request. Agent B calls its model only after the
request passes ASB verification. The two model endpoints and API keys are
configured independently, so they may use different servers or providers.

```sh
make a2a-test
./build/asb-a2a-test \
--workflow llm-conversation \
--prompt-file ./prompt.txt \
--agent-a-llm-url https://provider-a.example \
--agent-a-llm-model model-a \
--agent-b-llm-url https://provider-b.example \
--agent-b-llm-model model-b
```

Set provider keys with `ASB_AGENT_A_LLM_API_KEY` and
`ASB_AGENT_B_LLM_API_KEY`, preferably through a secret manager. The default
demo launches separate processes on one host. An experimental multi-host mode
generates per-role credential bundles and linked run evidence, but no physical
multi-host or independent-vendor run is claimed. Reverse-direction ASB binding
is also outside the verified product surface. See the
[multiprocess guide](examples/a2a-multiprocess/README.md) for the exact scope.

## Acceptance Contract

The verifier evaluates one ordered contract:
Expand All @@ -30,7 +75,9 @@ The verifier evaluates one ordered contract:
3. Check freshness, nonce, and replay state.
4. Bind any required attestation result to the same session.
5. Compare authenticated observed values with verifier-local expected policy.
6. Commit one-shot replay state before returning the accepted identity.
6. Commit one-shot replay state before returning the accepted identity. A
non-idempotent application can reserve its stable operation in the same
transaction.

The core implementation is centered on `pkg/clients`, `pkg/atls`, and
`pkg/atls/identitypolicy`. `pkg/agtp` contains reference adapters for JWT/JWS,
Expand All @@ -47,6 +94,8 @@ slice.
v2 profile for the multiprocess A2A demonstration.
- `docs/live-red-team-report.md`: current live-style red-team evidence and
evaluation boundaries.
- `docs/a2a-security-testkit-v1.md`: candidate self-contained A2A security
binding test surface and result contract.
- `docs/API_COMPATIBILITY.md`: supported v1 API and compatibility policy.
- `docs/production-deployment-profile.md`: fixed production choices for trust,
revocation, attestation, distributed replay, and exact action binding.
Expand All @@ -59,9 +108,16 @@ slice.
- `pkg/clients`, `pkg/atls`, and `pkg/atls/identitypolicy`: Direct-Agent
acceptance implementation.
- `pkg/production`: supported attested and software-only fail-closed
compositions and Redis/Valkey replay adapter.
compositions, plus TLS Redis/Valkey replay and shared operation/result
adapters.
- `pkg/authorityquorum`: generic k-of-n authority approval binding with an
atomic consume contract and a reduced, secret-free projection.
- `pkg/operationjournal`: durable application-operation reservation and state,
including atomic replay acceptance and optional opaque result persistence.
- `interop/draft06-v2`: standard-library Python verifiers for the v2 context
vector and full HTTP/JWS fixture. OpenSSL checks the fixture's three ES256
signatures. This is same-repository, second-language evidence, not a complete
interoperability claim.
- `docs/authority-quorum-binding-v1.md`: authority-slot, policy rotation,
revocation, session interruption, and external release boundary.
- `examples/protected-change-consumer`: independent HTTPS application consumer
Expand Down Expand Up @@ -160,21 +216,43 @@ not change generated protobuf sources.

See `docs/live-red-team-report.md` for the evidence matrix.

## Agent-to-Agent Demonstration
## A2A Interaction Lab

The packaged binary is both a runnable two-Agent lab and a self-contained
Direct-Agent v1 security test kit candidate:

```sh
make a2a-test
./build/asb-a2a-test
```

It starts Manager, Attester, Verifier, durable Replay Store, Agent A, and Agent
B as separate processes. The default suite runs eight ASB binding scenarios
over the A2A 1.0 HTTP+JSON Send Message surface.

Run the multiprocess A2A 1.0 demonstration:
Print JSON or write a report file:

```sh
go run ./examples/a2a-multiprocess
./build/asb-a2a-test --format json
./build/asb-a2a-test --report ./asb-a2a-report.json
```

It separates Manager, Attester, Verifier, durable Replay Store, Agent A, and
Agent B into operating-system processes. The same binary has a Docker Compose
topology and an optional fail-closed SNP/TDX hardware mode. See the
[multiprocess demonstration guide](examples/a2a-multiprocess/README.md) for the
protocol subset, trust boundaries, Docker command, hardware prerequisites, and
negative scenarios. The guide also shows how to select the separate
draft-06-inspired v2 profile; the no-flag behavior remains v1.
Reports follow the versioned
[`a2a-security-test-report-v1` JSON Schema](schemas/a2a-security-test-report-v1.schema.json).
This is an ASB binding tester, not a general A2A conformance suite. External
target mode is not implemented. Text and JSON reports, including the optional
two-model conversation, also work with the separate experimental `draft06-v2`
profile.

The v2 test data also includes a fixed
[HTTP/JWS wire fixture](examples/a2a-multiprocess/testdata/README.md) and an
[independently implemented Python verifier](interop/draft06-v2/README.md) for
the fixed contexts and full fixture. Their claim boundaries are stated with the
fixtures.

See the [test-kit candidate](docs/a2a-security-testkit-v1.md) and
[multiprocess guide](examples/a2a-multiprocess/README.md) for the scenario list,
conversation limits, Docker topology, and hardware prerequisites.

The smaller software-only binding demonstration remains available:

Expand Down
16 changes: 16 additions & 0 deletions docs/API_COMPATIBILITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,22 @@ The following remain experimental or outside the supported product API:

An exported Go identifier outside the supported list is not implicitly stable.

## A2A Security Test Kit candidate

The main branch contains an unreleased, self-contained ASB binding tester. Its
default Direct-Agent v1 profile runs eight fixed scenarios and can emit a
machine-readable report described by
`schemas/a2a-security-test-report-v1.schema.json`. The candidate also includes
strict report decoding and validation in `pkg/a2asecuritytest`.

This surface is not part of the v1.1 compatibility promise. Until it is
released as a supported product surface, its command flags, Go package, and
report schema may change. The experimental multi-host runner can exercise a
configured alternate Agent B that implements the fixed repository profile. It
is not a general target scanner or A2A conformance suite, and `draft06-v2`
remains experimental. The candidate `pkg/llmruntime` adapter and
`llm-conversation` workflow are also outside the v1.1 compatibility promise.

## Compatibility rules

Tags follow semantic versioning.
Expand Down
82 changes: 82 additions & 0 deletions docs/a2a-security-testkit-v1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# ASB A2A Security Test Kit v1

Status: product candidate. This document defines the intended first supported
test surface. It does not make the current repository release a general A2A
conformance product.

## Purpose

The test kit checks one narrow question: does an ASB-protected A2A HTTP+JSON
`Send Message` interaction accept the intended Agent, TLS session, request, and
authority, while rejecting known substitutions and replay?

The [official A2A Technology Compatibility Kit](https://github.com/a2aproject/a2a-tck)
tests A2A protocol conformance. This kit tests the separate ASB security
binding.

## First product surface

The first mode is a self-contained local and CI test lab. It starts Manager,
Attester, Verifier, Replay Store, Agent A, and Agent B as separate processes.
Agent A and Agent B communicate over mutually authenticated TLS 1.3.

The Direct-Agent v1 suite contains these scenarios:

| ID | Expected result |
| --- | --- |
| `ASB-A2A-001` | A correctly bound new message is accepted. |
| `ASB-A2A-002` | A tampered attestation result is rejected by Agent B. |
| `ASB-A2A-003` | A client-supplied unknown A2A Task ID is rejected. |
| `ASB-A2A-004` | An expired, correctly signed session proof is rejected. |
| `ASB-A2A-005` | A consumed proof cannot be replayed. |
| `ASB-A2A-006` | Credentials cannot be moved to another TLS session. |
| `ASB-A2A-007` | Replacing a bound resource breaks the session binding. |
| `ASB-A2A-008` | An A2A version downgrade is rejected. |

A new A2A Task ID is generated by Agent B. The ASB authorization `task_id` is
an authorization scope and is not taken from a client-supplied A2A Task ID.
This follows the Task identifier rules in the
[A2A 1.0.1 specification](https://github.com/a2aproject/A2A/blob/v1.0.1/docs/specification.md).

## Selected LLM conversation

The optional `llm-conversation` workflow connects one configured model to each
Agent runtime. Agent A generates the request text before ASB binds the complete
A2A request. Agent B calls its model only after the normal verification and
replay checks succeed. This is one round trip and does not add model provenance
or a reverse-direction ASB signature. It supports Direct-Agent v1 and the
experimental repository-local `draft06-v2` profile.

## Result contract

The command exits with zero only when every expected decision is observed. It
can also write a JSON report conforming to
`schemas/a2a-security-test-report-v1.schema.json`.

The experimental v2 security suite uses the same report schema. Its profile
field is `draft06-v2`; the report is test evidence for this repository profile,
not an IETF conformance statement.

The report records the tool version and commit, binding profile, requested
attestation mode and platform, run times, scenario results, decision codes,
and totals. It does not contain grants, proofs,
signatures, nonces, keys, attestation evidence, TLS exporter bytes, replay
keys, endpoints, or process IDs. A report file is written with mode `0600` and
replaced as one complete file.

## Scope

This mode tests real local processes and live TLS connections. It remains a
reference security lab: the keys are short-lived, attestation is simulated by
default, and the receiver uses the repository's fixed demonstration policy.
Passing it does not establish full A2A conformance or production readiness for
another Agent.

The next product boundary is an external-target mode. It will keep private
keys and tokens outside scenario files, require HTTPS, reject redirects, and
distinguish a security failure from an unavailable or interrupted target.
Until that adapter exists, a result is not an assessment of a third-party
Agent.

Long-running Task states, streaming, push notifications, Human interaction,
and hosted multi-tenant execution are outside this first surface.
Loading
Loading