Back to Infisical

Proxied Services

docs/documentation/platform/agent-proxy/proxied-services.mdx

0.162.1310.1 KB
Original Source

A proxied service tells the agent proxy how to apply credentials to traffic bound for an external service. It lives in a folder alongside your secrets and defines which hosts it covers.

To create one, open a folder in the secrets dashboard, click the dropdown arrow next to Add Secret, and select Add Proxied Service.

A service applies each secret through a header rewrite, a secret substitution, or both; each is covered in its own section below.

Configuration

Every service has these core fields, plus one or more credential rules described below.

<ParamField path="Service Name" type="string" required> A slug (lowercase letters, numbers, hyphens) that identifies the service, such as `github`. Names are unique within a folder. </ParamField> <ParamField path="Host Pattern" type="string" required> One or more comma-separated patterns describing which hosts this service applies to. See [Host patterns](#host-patterns) below. </ParamField> <ParamField path="Enabled" type="boolean" optional default="true"> Toggle a service off without deleting it. A disabled service is skipped entirely: its placeholder environment variables are not set, no credentials are applied, and traffic to its hosts falls back to the [unmatched host policy](/documentation/platform/agent-proxy/deployment#unmatched-hosts). </ParamField>

Host patterns

A host pattern routes requests to the right service. Each pattern is a host[:port][/path], and multiple patterns can be combined with commas:

bash
api.github.com                            # exact host
*.github.com                              # wildcard: matches api.github.com, not a.b.github.com
api.github.com:443                        # specific port
api.github.com/repos/*                    # path prefix
internal.corp.com:3000/api/*              # port and path
api.github.com, uploads.github.com        # multiple patterns, matches either

A few rules to keep in mind:

  • A *. wildcard matches exactly one label: *.github.com matches api.github.com but not a.b.github.com or bare github.com.
  • Host matching is case-insensitive. A pattern without a port matches any port.
  • Do not include a scheme (https://); patterns are hosts, not URLs.

When a request could match more than one service, the agent proxy picks the best match:

  1. Exact host beats wildcard host.
  2. A pattern with a specific port beats one that matches any port.
  3. The longest matching path prefix wins.
  4. If still tied, the service whose name sorts first alphabetically wins.
<Note> Host patterns are for routing only. Proxied services are also scoped to their folder: an agent connected with `--env=dev --path=/coding-agent` only ever matches services defined in that folder, so the same hostname can be configured differently in different folders, environments, or projects. </Note>

Header rewrites

A header rewrite adds or replaces an HTTP header on the outbound request. The agent does not need to send any credential; if it sends a made-up one, the header is overwritten with the real value. This covers most APIs:

Auth styleConfigurationResulting header
Bearer tokenHeader name Authorization, prefix Bearer, one secretAuthorization: Bearer <secret>
API key headerHeader name x-api-key, no prefix, one secretx-api-key: <secret>
Basic authOne secret as Username, and optionally a second as PasswordAuthorization: Basic base64(username:password)
CustomAny header name and optional prefix<name>: <prefix> <secret>

The password is optional for basic auth. Many APIs pass an API key as the username with an empty password; omitting the password produces Authorization: Basic base64(username:).

A service can rewrite multiple distinct headers (for example, an API key header plus a tenant header), but each header name can only be set by one secret. To build one header value out of several secrets, or use a secret kept elsewhere, see using secrets from other folders and environments.

Secret substitution

With secret substitution, the agent is handed a dummy placeholder value. The agent proxy swaps it for the real credential wherever it appears in the request. It is useful in two situations:

  • The API carries the credential somewhere other than a header. Telegram, for example, puts the bot token in the URL path: api.telegram.org/bot<token>/sendMessage.
  • The agent has to see a value before it will make the call at all, headers included. Some HTTP clients validate that a credential is set, and agents often refuse to attempt a request without a real-looking key. The placeholder satisfies them, and the proxy swaps in the real value on the way out.

The placeholder is also delivered for you: infisical secrets agent-proxy connect sets it as an environment variable in the agent's environment, so there is nothing to hand out.

<ParamField path="Environment Variable" type="string" required> The environment variable name the agent receives, such as `TELEGRAM_BOT_TOKEN`. When an agent connects, `infisical secrets agent-proxy connect` sets this variable to the placeholder, so the agent uses it like a normal credential. </ParamField> <ParamField path="Placeholder Value" type="string" required> The dummy value the agent sends in its requests. A distinctive random string is generated for you, but you can override it, for example when the agent's HTTP client validates the credential's format. </ParamField> <ParamField path="Replace In" type="string[]" required> The request surfaces the agent proxy scans for the placeholder: `path`, `query`, `header`, and/or `body`. Scoping is the security boundary: the proxy only substitutes in the surfaces you list. </ParamField> <ParamField path="Secret" type="string" required> The secret (from the same folder) whose real value replaces the placeholder. </ParamField>

Using secrets from other folders and environments

You cannot point a proxied service at another folder directly, but you can bring an outside value into its folder so the service can use it. There are two ways, both using features that already exist in Infisical:

ApproachWhat you doExample
Imported secretImport another folder into the service's folder, then use the imported key by nameImport /shared-creds, then use its SHARED_API_KEY from the service's folder
Composed with referencesCreate a secret whose value is one or more secret references, then use that secret. Lets you combine several secrets, including ones from other folders or environmentsA secret set to ${AUTH_USERNAME}:${prod.shared.AUTH_PASSWORD} resolves to the two values joined as username:password

Using dynamic secrets

A credential can reference a dynamic secret instead of a static secret. Rather than injecting a fixed value, the agent proxy mints a short-lived lease and injects one of its output fields (for example a GCP access token, a GitHub App token, or a Kubernetes service-account token).

How the agent proxy handles the lease:

  • Minted lazily, per agent session. The first request that needs the credential mints a lease; each agent session gets its own, and later requests reuse it.
  • Refreshed before expiry. A fresh lease is swapped in shortly before the current one expires, with no failed requests in between.
<Warning> Use a TTL of at least a few minutes on dynamic secrets you broker. Each agent session on each proxy instance holds its own lease and re-mints it as it nears expiry, so a very short TTL (for example one minute) causes constant re-minting. </Warning> <Note> Give **Manage Leases** on the dynamic secret to the proxy identity only. If the agent identity also has it, it could mint the credential itself and skip the proxy, so `connect` refuses to start by default. </Note>

Example: API request

Proxied services can also be managed via the API. For example, creating the Telegram service described above:

bash
curl -X POST https://app.infisical.com/api/v1/proxied-services \
  -H "Authorization: Bearer $INFISICAL_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "projectId": "<project-id>",
    "environment": "dev",
    "secretPath": "/coding-agent",
    "name": "telegram-bot-api",
    "hostPattern": "api.telegram.org",
    "credentials": [
      {
        "secretKey": "TELEGRAM_BOT_TOKEN",
        "role": "credential-substitution",
        "placeholderKey": "TELEGRAM_BOT_TOKEN",
        "placeholderValue": "placeholder_tg_bot",
        "substitutionSurfaces": ["path"]
      }
    ]
  }'

Header-rewrite credentials use "role": "header-rewrite" with headerName and an optional headerPrefix, or headerPurpose (username/password) for basic auth.

To reference a dynamic secret, replace secretKey on a credential with dynamicSecretName and dynamicSecretField:

json
{
  "dynamicSecretName": "github-app-token",
  "dynamicSecretField": "TOKEN",
  "role": "header-rewrite",
  "headerName": "Authorization",
  "headerPrefix": "Bearer"
}

Next steps

<CardGroup cols={2}> <Card title="Connecting Agents" icon="plug" href="/documentation/platform/agent-proxy/connecting-agents"> Launch an agent and have it use the services you defined. </Card> <Card title="Security" icon="shield-halved" href="/documentation/platform/agent-proxy/security"> The Proxy permission and the isolation model behind these services. </Card> </CardGroup>