-
Notifications
You must be signed in to change notification settings - Fork 33
PER-14853: Add HTTP Egress Proxy customer documentation #640
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
7b37680
PER-14853: Add HTTP Egress Proxy customer documentation
EliMoshkovich 4991814
PER-14853: Sharpen HTTPS passthrough/intercept accuracy in proxy docs
EliMoshkovich 12f7eb5
PER-14853: correct HTTP Egress Proxy docs to the shipped API workflow…
EliMoshkovich ee087d6
PER-14853: address review — token-file in CLI example + clearer verif…
EliMoshkovich 3d5c159
PER-14853: address Zeev's review — HTTPS/CONNECT model, vault precond…
EliMoshkovich File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
87 changes: 87 additions & 0 deletions
87
docs/permit-mcp-gateway/http-egress-proxy/authorization.mdx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 | ||
|
|
||
| # 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). | | ||
|
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
98
docs/permit-mcp-gateway/http-egress-proxy/connecting-agents.mdx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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. |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.