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
87 changes: 87 additions & 0 deletions docs/permit-mcp-gateway/http-egress-proxy/authorization.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
---
title: Authorization & Trust
sidebar_label: Authorization & Trust
description: How a workflow's rules, Permit.io policy, and human consent compose — including per-human, per-workflow trust ceilings that cap how much access a person can delegate to an agent.
sidebar_position: 5
---

# Authorization & Trust

An allowed outbound request passes through **two independent gates**. Both must say yes. This mirrors how the gateway authorizes MCP tool calls, so the same mental model — and the same Permit policy environment — governs both planes.

## The two gates

```mermaid
flowchart TB
Req["Outbound request"]
Rule{"1. Workflow match<br/>domain / path / method"}
Permit{"2. Permit policy<br/>agent's role for the rule"}
Ceiling["Trust ceiling<br/>(delegated agents)"]
Allow["Forwarded"]
Deny["Denied"]

Req --> Rule
Rule -->|"no matching rule"| Deny
Rule -->|"matched"| Permit
Permit -->|"deny"| Deny
Permit -->|"allow"| Ceiling
Ceiling -->|"over ceiling"| Deny
Ceiling -->|"within ceiling"| Allow
```

### Gate 1 — Workflow match

Every token is bound to one [workflow](./egress-rules). The gateway resolves that workflow, checks the request's target host against the workflow's domains, and finds the rule that governs its path and method. A request with no matching rule is denied before any policy evaluation. This is the coarse, operator-controlled "is this domain/path/method even on the menu" check.

### Gate 2 — Permit.io policy

For requests a rule matches, the gateway then asks your **Permit.io** policy whether *this agent* holds a role that authorizes *this rule's action* — each rule is a Permit action on the workflow resource. The trust level a request must meet is declared **by the rule itself** (its required trust); the method class only determines which rules a request can match, and seeds the **Auto** default when you don't set a level explicitly. Because every gateway host maps to a Permit environment, you manage these policies in the same place as your MCP policies — see [Permit.io Integration](/permit-mcp-gateway/permit-integration).

This split means an operator can define a workflow's domains and rules while your central policy still decides, per agent, which of those rules that agent may actually use.

## Human consent and trust ceilings

Agents usually act **on behalf of a human**. The proxy supports the same delegation-with-consent model the gateway uses for MCP: a person explicitly authorizes an agent to make egress calls for them, for a specific workflow, and the access an agent gets through that person is capped by a **trust ceiling**.

### Trust ceilings

An admin sets, per human and per workflow, the **maximum** trust level that person is allowed to delegate — `low`, `medium`, or `high`. This is the same **Max Trust Level** control described in [Host Setup](/permit-mcp-gateway/host-setup). When a human consents to an agent, the access that agent receives is the **lesser** of what the human grants and the admin-defined ceiling. A person can never delegate more than their ceiling allows.

This has an important security property: an agent that acts for **several** humans does **not** get to combine their ceilings. Each human caps their own delegation independently, so one person's grant can't be used to escalate another's.

### Human consent

To have a human delegate egress access to an agent, run the consent flow:

```bash
asg proxy authorize <agent-client-id> --workflow charge_customers
```

This opens a browser where the human signs in and chooses what to allow:

1. **Sign in** — the human authenticates.
2. **Review the workflow** — the screen shows the workflow's domains and rules the agent is requesting.
3. **Choose an access level** — defaulting to least privilege, and capped at the admin's ceiling for that human and workflow.
4. **Approve** — a short-lived, human-bound token is issued for the agent, bound to that workflow.

Omit `--workflow` in the browser flow to let the consent screen present a picker over the workflows that human may delegate. The optional `--trust low|medium|high` flag lets the human (or the operator preparing the request) propose a lower cap than the ceiling; omit it to default to least privilege.

The result is a token whose access is bound to that specific human's consent — and which the human can revoke.

### Revocation

A human can revoke an agent's delegated access at any time from their account. Revoking removes the agent's policy assignment, so **new** authorization decisions fail immediately. A proxy token already issued under that grant stays valid until it expires (up to its TTL) **unless** the human also chooses **deny in-flight tokens** — the panic-button option for a lost device or compromised agent, which hard-denies every token minted before the revoke for the rest of its life.

Even then, revocation is only re-evaluated on requests the gateway **inspects**. Traffic already flowing inside an open `passthrough` HTTPS tunnel is opaque and isn't re-checked — it continues until the client closes it or the idle timeout fires. Use `intercept` if you need revocation to cut off an in-progress HTTPS connection. This is the egress equivalent of revoking an MCP consent.

## How automated agents differ

Not every agent acts for a human. A CI job or backend service can be issued a token directly with [`asg proxy token create --workflow <slug>`](./quickstart#4-mint-a-workflow-bound-agent-token). Such a token isn't bound to a human, so the per-human trust ceiling doesn't apply — its access is governed purely by the workflow's rules and the agent's own Permit policy. Use direct tokens for machine-to-machine automation, and the consent flow whenever a real person is accountable for what the agent does.

---

## What's next

- [**Workflows & Rules**](./egress-rules) — the operator allow-list that forms the first gate.
- [**Permit.io Integration**](/permit-mcp-gateway/permit-integration) — the policy model behind the second gate.
- [**Security**](./security) — the protections that wrap both gates.
130 changes: 130 additions & 0 deletions docs/permit-mcp-gateway/http-egress-proxy/cli.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
---
title: The asg CLI
sidebar_label: asg CLI
description: Install and use the asg command-line tool — the operator's front door for enabling the HTTP Egress Proxy, managing credentials, minting agent tokens, and wiring agents into the proxy.
sidebar_position: 2
---

# The `asg` CLI

`asg` is the command-line tool for managing the Permit MCP Gateway, including the HTTP Egress Proxy control plane. Most of what you can do in the **CLIs / APIs** section of the [dashboard](https://app.agent.security) — enable the proxy, manage credentials, mint tokens, run diagnostics — you can also do with `asg`, scripted and CI-friendly.

The CLI is the operator and automation surface. End users who simply delegate access to an agent normally do that through the browser consent flow, not the CLI.

:::note Workflows are authored in the dashboard
Egress policy lives in **API workflows** (a set of allowed domains and rules). Today you create and edit workflows in the [dashboard](https://app.agent.security) under **CLIs / APIs → Workflows** — there is no CLI command for authoring them yet. The CLI handles everything around them: enabling the proxy, storing credentials, minting workflow-bound tokens, and connecting agents.
:::

## Install

The published package is `@permitio/agent-security-cli`. The quickest way to use it is without installing — run it on demand with your package runner:

```bash
# With Bun (recommended)
bunx @permitio/agent-security-cli --help

# Or with npm
npx -y @permitio/agent-security-cli --help
```

To install it globally and get the `asg` command on your `PATH`:

```bash
# With Bun
bun install -g @permitio/agent-security-cli

# Or with npm
npm install -g @permitio/agent-security-cli
```

Verify the install:

```bash
asg --help
asg proxy --help
```

## Configure

`asg` resolves settings in priority order: environment variables, then a config file at `~/.agent-security/`, then built-in defaults.

The admin token is issued by your **gateway operator** (it's the gateway deployment's admin secret); the CLI never mints one. If you're a tenant developer, ask your platform administrator for it. Save it to a file, then:

```bash
# Point at your gateway and store an admin token (saved with restrictive permissions).
asg config set gateway-url https://gateway.example.com
asg login --token-file ./admin-token # reads the token from a file, not a process-visible flag
Comment thread
EliMoshkovich marked this conversation as resolved.

# Verify the token against the gateway.
asg whoami
```

You can also supply settings through environment variables, which is the preferred approach in CI:

| Variable | Purpose |
| --- | --- |
| `AGENT_SECURITY_API_KEY` | Admin token used to authenticate control-plane commands. |
| `AGENT_SECURITY_GATEWAY_URL` | Your gateway's admin URL. |
| `AGENT_SECURITY_SUBDOMAIN` | Default host subdomain, so you can omit it from each command. |
| `AGENT_SECURITY_CONSENT_URL` | Consent origin used by `asg proxy authorize` (usually auto-derived). |
| `AGENT_SECURITY_PROXY_TOKEN_FILE` | Path to the agent's proxy token file (set by `asg proxy env`). |

:::warning Treat the admin token as a high-value secret
Prefer the interactive prompt, `AGENT_SECURITY_API_KEY`, or the `--token-file` form over passing the token as a `--token` flag — command-line flags are visible to other users on the machine via the process list. The secret-bearing flags on the proxy and login commands (`--token`, `--secret`, `--client-secret`) each have a companion `--<flag>-file` that reads the value from a file instead. The CLI scrubs secret-shaped strings from its own output, but the process list is outside its control.
:::

## Output and exit codes

Every command supports machine-readable output so agents and CI can drive it deterministically:

```bash
asg proxy doctor acme --json --quiet
```

- `--json` emits structured JSON to stdout.
- `--quiet` drops decorative output (spinners, hints).
- `--yes` accepts confirmation prompts non-interactively.

Exit codes are stable:

| Code | Meaning |
| --- | --- |
| `0` | Success |
| `1` | User error — bad input, missing token, cancelled prompt, or a human-denied approval |
| `2` | Server error — gateway unreachable, 5xx, or network failure |

## The `asg proxy` command tree

| Command | What it does |
| --- | --- |
| `asg proxy config <host> --enable\|--disable` | Turn proxy mode on or off for a host. |
| `asg proxy credentials list\|create\|update\|delete` | Manage stored upstream secrets (write-only). See [Credentials](./credentials). |
Comment thread
EliMoshkovich marked this conversation as resolved.
| `asg proxy connect <provider> <host> --key <credential-key> --client-id <id>` | Connect an OAuth provider (`github_app`, `notion`, `google`, `atlassian`) and store the resulting credential. |
| `asg proxy token create <host> --client-id <id> --workflow <slug>` | Mint a short-lived, workflow-bound proxy access token (`--out <file>` writes it securely). |
| `asg proxy authorize <agent-client-id> --workflow <slug>` | Run the browser consent flow so a human can delegate access to an agent for a workflow, within a trust ceiling. |
| `asg proxy env <host>` | Print the `HTTP_PROXY` / `HTTPS_PROXY` / `NO_PROXY` environment for the current shell. |
| `asg proxy container-config <host>` | Emit Docker, Docker Compose, Kubernetes ConfigMap, or shell bootstrap config. |
| `asg proxy ca status\|download\|rotate\|trust-shell` | Manage the per-host TLS-interception certificate authority. See [Connecting Agents](./connecting-agents#https-interception). |
| `asg proxy doctor <host>` | Diagnose proxy setup end to end. |

Run `asg proxy <command> --help` for the full flag list of any command. `asg proxy --help` also lists preset packs (`asg proxy preset list` browses the built-in catalog) and two opt-in capabilities: **agent identity registration** (see [Agent Verification](/permit-mcp-gateway/advanced-features)) and the **intent guardian**, which judges each request against an operator-declared task description. [Contact us](mailto:support@permit.io) to enable the opt-in capabilities for your account.

## Passing the host subdomain

Most commands take the host subdomain as a positional argument (e.g. `asg proxy config acme`). If you've set a default with `asg config set subdomain acme` (or `AGENT_SECURITY_SUBDOMAIN`), you can omit it. Commands that already take another positional keep the host as the **second positional** (e.g. `asg proxy credentials create stripe acme`). `asg proxy authorize` is the exception: it takes the agent's client id positionally and the host as `--subdomain`.

## Shell completions

Enable tab-completion for your shell:

```bash
asg completion --shell zsh >> ~/.zshrc # or: --shell bash >> ~/.bashrc
```

---

## What's next

- [**Workflows & Rules**](./egress-rules) — the egress policy model in depth.
- [**Credentials & Connections**](./credentials) — static secrets, OAuth connections, and request signing.
- [**Connecting Agents**](./connecting-agents) — `asg proxy env`, `container-config`, and `doctor` in context.
98 changes: 98 additions & 0 deletions docs/permit-mcp-gateway/http-egress-proxy/connecting-agents.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
---
title: Connecting Agents
sidebar_label: Connecting Agents
description: Route an agent's outbound traffic through the HTTP Egress Proxy — shell, Docker, and Kubernetes setup, the proxy access token, HTTPS interception, and the doctor diagnostic.
sidebar_position: 6
---

# Connecting Agents

The proxy uses the standard `HTTP_PROXY` / `HTTPS_PROXY` convention, so most HTTP client libraries route through it automatically once the environment is set. Connecting an agent has two parts: **the environment variables** that point traffic at the gateway, and **a proxy access token** the agent presents to authenticate.

## The pieces

| Piece | What it is |
| --- | --- |
| `HTTP_PROXY` / `HTTPS_PROXY` | Point your agent's outbound HTTP and HTTPS at the gateway. |
| `NO_PROXY` | Hosts that should bypass the proxy (e.g. localhost). |
| Proxy access token | A short-lived, workflow-bound token the agent presents to the proxy. Minted with [`asg proxy token create`](./quickstart#4-mint-a-workflow-bound-agent-token) or the [consent flow](./authorization#human-consent), and referenced via a token file. |

You rarely set these by hand — `asg proxy env` and `asg proxy container-config` generate them for you.

## Shell / local process

```bash
eval "$(asg proxy env acme)"
```

This exports `HTTP_PROXY`, `HTTPS_PROXY`, `NO_PROXY`, and `AGENT_SECURITY_PROXY_TOKEN_FILE` (the path to the token file) into the current shell. Mint the token first (step 4 of the [Quick Start](./quickstart)) at the path `asg proxy env` expects — `$HOME/.agent-security/tokens/<subdomain>.token` — or point `AGENT_SECURITY_PROXY_TOKEN_FILE` at wherever you wrote it.

Routing traffic through the proxy is only half of it: every request must also carry `Proxy-Authorization: Bearer <token>`. Exporting the env does **not** authenticate your requests — your HTTP client has to read the token from `$AGENT_SECURITY_PROXY_TOKEN_FILE` and send that header (or launch the agent with [`asg run`](./cli), which injects the token into the proxy URL for you). Without it the proxy answers `407`.

## Docker and Kubernetes

Generate ready-to-use container configuration:

```bash
# Docker env file or Compose snippet.
asg proxy container-config acme --format docker-env
asg proxy container-config acme --format docker-compose

# Kubernetes ConfigMap.
asg proxy container-config acme --format k8s-configmap
```

Mount or reference the emitted configuration in your agent's container so the proxy variables are present in its environment. Supply the proxy token through your platform's normal secret mechanism (a mounted file or secret), and point `AGENT_SECURITY_PROXY_TOKEN_FILE` at it.

## HTTPS interception

By default the proxy handles HTTPS in **passthrough** mode: it authenticates and authorizes the connection against the domain's **tunnel rule** (the `all`-method, path-less rule — see [Workflows & Rules](./egress-rules#https-needs-a-tunnel-rule)), but the encrypted tunnel is forwarded opaquely — the proxy does not see the request path or body, and it can't inject a credential or scrub the response inside the tunnel.

To apply **full** governance to HTTPS — path-level rules, credential injection, and response scrubbing inside the encrypted connection — switch the domain's **tunnel rule** to **intercept** mode. You set TLS mode in the [dashboard](https://app.agent.security) workflow editor (**CLIs / APIs → Workflows**, open the workflow, edit the tunnel rule, set **TLS mode** to **Intercept (decrypt + inject credential)**). TLS mode is read from the tunnel rule, so setting it on a path- or method-scoped rule has no effect.

In intercept mode the proxy terminates the agent's TLS using a **certificate authority issued for your host** and re-applies every check to the decrypted request. For your agent to trust those connections, it must trust that CA certificate — manage it with the CLI:

```bash
# Inspect your host's interception CA.
asg proxy ca status acme

# Download the CA certificate to install in your agent's trust store.
asg proxy ca download acme --output ./agent-security-ca.pem

# Print a shell snippet that points common tools at the CA.
asg proxy ca trust-shell acme

# Rotate the CA, keeping the previous one valid during a grace window.
asg proxy ca rotate acme --grace-days 7
```

:::note Choosing a mode
Use **passthrough** when domain-level control is enough, or for very large uploads, downloads, and long-lived streaming connections. Use **intercept** when you need path-level rules, credential injection, or response scrubbing on HTTPS traffic. Mode is decided by the rule that authorizes the tunnel, so in practice it's **per domain** for HTTPS — you can mix passthrough and intercept across domains.
:::

## Diagnose with `doctor`

When something isn't connecting, run the built-in diagnostic:

```bash
asg proxy doctor acme
```

`doctor` checks, end to end:

- Gateway reachability
- Whether the proxy is enabled for the host
- How many credentials are configured
- Your local proxy environment variables
- The interception CA's status and expiry, and whether your environment trusts it
- The token file's permissions and the token's expiry

Each check reports **pass**, **warn**, or **fail**; anything that isn't a pass carries a suggested fix. `doctor` exits `0` (clean), `1` (operator-fixable failure), or `2` (gateway fault), so it's safe to gate CI on — and it's the first thing to run whenever an agent's traffic isn't behaving.

---

## What's next

- [**Quick Start**](./quickstart) — the end-to-end setup these commands fit into.
- [**Security**](./security) — what the proxy enforces on the traffic you route through it.
- [**The `asg` CLI**](./cli) — full command reference.
Loading