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
244 changes: 244 additions & 0 deletions aigw/api-reference/admin-api/authentication.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
---
title: "Authentication"
description: "Authorise Admin API requests with a Strata Cloud Manager access token issued to a service account"
---

Admin API requests are authorised with a short-lived access token issued by Strata Cloud Manager, not with an AI Gateway API key.

<Warning>
A gateway API key, the key you send as `Authorization: Bearer $API_KEY` on inference requests, is **not** accepted on any Admin API endpoint. See [Inference API authentication](/aigw/api-reference/inference-api/authentication) for the inference path.
</Warning>

You obtain an Admin API token by authenticating a **service account** against the Palo Alto Networks authentication service. The token carries the ID of the tenant service group (TSG) it was scoped to, and every request made with it is routed to that tenant.

```mermaid
sequenceDiagram
participant SCM as Strata Cloud Manager
participant App as Your job
participant Auth as Auth service
participant API as Admin API

SCM-->>App: Client ID, Secret, TSG ID
App->>Auth: POST /oauth2/access_token
Auth-->>App: access_token, expires_in 900

loop Within 15 minutes
App->>API: Authorization: Bearer
API-->>App: One tenant's resources
end
```

## What you need

Before you can request a token, three values must exist. All three come from Strata Cloud Manager.

| Value | What it identifies | Where it comes from |
|:--|:--|:--|
| TSG ID | The tenant the token will act on. One TSG corresponds to one AI Gateway organisation. | Shown against the tenant in Strata Cloud Manager |
| Client ID | The service account | Issued when the service account is created |
| Client Secret | The service account's credential | Shown **once**, at creation |

<Note>
A TSG must have a service account before you can make any API call against it. If a tenant has no service account of its own, a service account belonging to one of its ancestor TSGs can be used instead. See [Token scope within a TSG hierarchy](#token-scope-within-a-tsg-hierarchy).

One TSG may have many service accounts, and one service account may have many tokens.
</Note>

<Info>
*Tenant service group* and *tenant* are used interchangeably; there is no functional difference between them.
</Info>

## Create a service account

Service accounts are created in Strata Cloud Manager, through Common Services Identity & Access. A service account is not tied to a specific user.

<Steps>
<Step title="Open Identity & Access">
Sign in to [Strata Cloud Manager](https://stratacloudmanager.paloaltonetworks.com/) and go to **System Settings > Identity & Access**.

{/* TODO(screenshot): SCM System Settings > Identity & Access */}
</Step>
<Step title="Select the tenant">
Choose the tenant the service account belongs to.

A service account added to a parent tenant is automatically added to all of that tenant's children, which is how a parent manages its children. Add it to a child tenant instead if you do not want that inheritance.

Creating service accounts in different tenant service groups lets you assign different roles for different access permissions, and keeps the audit trail readable.

{/* TODO(screenshot): tenant selector */}
</Step>
<Step title="Add the identity">
Select **Add** (or **Add Identity**), then set **Identity Type** to **Service Account**.

Give it a unique and meaningful **Service Account Name**. Optionally add a **Service Account Contact** email and a **Description**. The contact person is not added as a user.

{/* TODO(screenshot): Add Identity dialog with Identity Type set to Service Account */}
</Step>
<Step title="Save the client credentials">
Select **Next**. The Client Credentials screen shows the **Client ID** and **Client Secret**.

<Warning>
The Client Secret is presented once. Copy both values, or select **Download CSV File**, before leaving the screen. If you lose the secret you must issue a new credential.
</Warning>

{/* TODO(screenshot): Client Credentials screen with Download CSV File */}
</Step>
<Step title="Note the TSG ID">
Select **Next**. The display name of the service account is formatted as `<ServiceAccountName>@<tsg_id>.iam.panserviceaccount.com`.

Every service account of a parent tenant carries the parent TSG ID, and every service account of a child tenant carries the child TSG ID. Take note of the `tsg_id`, because you pass it on every token request.

{/* TODO(screenshot): display name showing the tsg_id */}
</Step>
<Step title="Assign a role">
On the Assign Roles screen, select the scope (for example **All Apps & Services**) and assign the role the service account needs. A service account with no role assignment cannot obtain a token.

Grant the narrowest role that covers the Admin API operations you intend to automate. A custom role needs `iam.service_account` and `iam.custom_role` permissions if the account will manage identities itself.

{/* TODO(screenshot): Assign Roles screen */}
</Step>
<Step title="Submit">
Save to create the service account. You now have the Client ID, Client Secret and TSG ID needed to request a token.
</Step>
</Steps>

## Request an access token

Exchange the service account credentials for an access token with `POST /oauth2/access_token`.

<Warning>
The authentication service runs on a different FQDN from the rest of Strata Cloud Manager:
`https://auth.apps.paloaltonetworks.com`
</Warning>

The endpoint uses basic auth, with the Client ID as the username and the Client Secret as the password, and takes the TSG ID in the `scope` field:

```sh Request an access token
curl -d "grant_type=client_credentials&scope=tsg_id:<tsg_id>" \
-u <client_id>:<client_secret> \
-H "Content-Type: application/x-www-form-urlencoded" \
-X POST https://auth.apps.paloaltonetworks.com/oauth2/access_token
```

The service account you authenticate with must belong to the TSG named on `scope`, or to one of its ancestors.

A successful response carries the token and its lifetime in seconds:

```json
{
"access_token": "eyJhbGciOi...",
"token_type": "Bearer",
"expires_in": 900
}
```

<Note>
**Access tokens have a lifespan of 15 minutes.** Read `expires_in` rather than hard-coding the number, cache the token in memory for the life of that window, and refresh it about a minute before it lapses. Requesting a fresh token per API call is unnecessary; carrying one across a long-running job is what fails.
</Note>

## Call an Admin API endpoint

Send the token as a bearer token. Every Admin API endpoint takes the same header; the base URL and path for each one are shown on its own reference page.

```sh
curl https://api.apps.paloaltonetworks.com/ai_gw/v2/configs \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json"
```

You do not pass the TSG ID on the request. The token already contains it, and the request is routed to that tenant on the strength of it.

## Token scope within a TSG hierarchy

A token issued for one TSG cannot be used against another. If you have a tenant, Tenant 1A, with a service account named `1a_svc`, then a token obtained through `1a_svc` reaches Tenant 1A and nothing else.

When you run multiple tenants you organise them as a hierarchy of TSGs. Creating a dedicated service account for every TSG and tenant in that hierarchy is the simplest arrangement, but it is not necessary. **A service account belonging to a TSG can name any descendant of that TSG when it requests a token.**

Consider a root TSG A with two tenants, and a child TSG B with two more:

```mermaid
graph TD
TSGA["TSG A<br/>a_svc"] --> T1A[Tenant 1A]
TSGA --> T2A[Tenant 2A]
TSGA --> TSGB["TSG B<br/>b_svc"]
TSGB --> T1B[Tenant 1B]
TSGB --> T2B[Tenant 2B]
```

Assume `a_svc` and `b_svc` were created with the `superuser` role on TSG A and TSG B respectively. Then:

- **`a_svc` can request a token for any TSG ID in the hierarchy**, because every TSG and tenant shown is a descendant of TSG A.
- **`b_svc` can request tokens for TSG B, Tenant 1B and Tenant 2B**, its own descendants.
- **`b_svc` cannot request a token for TSG A, Tenant 1A or Tenant 2A.** Those are its ancestor and its peers.
- Tenants 1A, 2A, 1B and 2B hold no service accounts of their own, so only the service accounts of their parent TSGs can obtain tokens for them.

<Note>
The TSG IDs used in the examples on this page are deliberately fake. Real TSG IDs are 10-digit integers, such as `1000000001`.
</Note>

### Grant cross-hierarchy access with an access policy

`b_svc` cannot obtain a token for Tenant 1A, because Tenant 1A sits outside its subtree. Where you need exactly that, create an **access policy** on Tenant 1A naming the Client ID of `b_svc` as the principal. The policy overrides the hierarchy restriction for that one pairing.

You can do this from the multitenant UI, or with the Identity and Access Management *create an access policy* API. The following grants `b_svc` superuser permissions on Tenant 1A, represented here by TSG ID `18`:

```sh Grant b_svc access to Tenant 1A
curl -d '{"role":"superuser","resource":"prn:18::::","principal":"b_svc@15.iam.panserviceaccount.com"}' \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-X POST https://api.strata.paloaltonetworks.com/iam/v1/access_policies
```

The token you authenticate this call with must itself be scoped to the TSG that owns the resource, `15` in the example above.

The same endpoint grants a person a role on a tenant, with their email address as the principal. Three fields make up a policy:

| Field | Format |
|:--|:--|
| `principal` | A user's email address, or a service account as `<name>@<tsg_id>.iam.panserviceaccount.com` |
| `resource` | `prn:<tsg_id>::::<workspace>`. Leave the last segment empty for the TSG root, which Strata Cloud Manager labels **All Apps & Services** |
| `role` | A built-in role is a bare slug, such as `superuser` or `view_only_admin`. A role defined by a tenant carries that tenant's ID, as `my_custom_role:1000000001` |

`GET /iam/v1/access_policies` lists the policies on the tenant your token is scoped to, and `DELETE /iam/v1/access_policies/{id}` removes one. A duplicate `POST` returns `409`, so the call is safe to retry.

<Warning>
The access policy endpoint does not check that the principal exists. A `POST` naming an address that belongs to nobody returns `201` and a policy ID, and the policy sits in the listing doing nothing until somebody with that address appears. Validate addresses against your directory before creating policies in bulk, and review the IDs you get back.
</Warning>

<Note>
Older Palo Alto Networks documentation shows this endpoint as `https://api.sase.paloaltonetworks.com/access_policies`. `https://api.strata.paloaltonetworks.com/iam/v1/access_policies` is the current host and path.
</Note>

## Check your token

If the credentials baked into a token are not the ones you expect, the Admin API rejects the request and the error reports an invalid authorisation code.

Paste the token into [jwt.io](https://jwt.io/) to decode it and read the claims back. The decoded payload shows the `tsg_id` the token was issued for, which is the fastest way to confirm you are hitting the tenant you think you are, and an `access` claim listing the roles the service account holds on it.

{/* TODO(screenshot): jwt.io showing an encoded token beside its decoded payload, tsg_id highlighted */}

### Common failures

| Symptom | Cause |
|:--|:--|
| Token request rejected at `/oauth2/access_token` | The Client ID or Client Secret is wrong, or the service account has no role assignment |
| Token request rejected for the TSG on `scope` | The service account is not in that TSG or an ancestor of it. Create an [access policy](#grant-cross-hierarchy-access-with-an-access-policy) |
| Admin API returns an authorisation error with a valid-looking token | The token has expired, since they last 15 minutes, or it is scoped to a different tenant. Decode it and check `tsg_id` |
| Admin API rejects a key that works for inference | A gateway API key was sent instead of an access token. Only tokens from the authentication service are accepted |

## Related

<CardGroup cols={2}>
<Card title="Admin API introduction" icon="book" href="/aigw/api-reference/admin-api/introduction">
What the Admin API manages, and the permissions model behind it
</Card>
<Card title="Inference API authentication" icon="key" href="/aigw/api-reference/inference-api/authentication">
Gateway API keys and JWT authentication for inference requests
</Card>
<Card title="Errors" icon="triangle-exclamation" href="/aigw/api-reference/admin-api/error">
Admin API error codes and what they mean
</Card>
<Card title="Audit logs" icon="shield-check" href="/aigw/product/enterprise-offering/audit-logs">
Every administrative action, attributed to the principal that made it
</Card>
</CardGroup>
77 changes: 48 additions & 29 deletions aigw/api-reference/admin-api/error.mdx
Original file line number Diff line number Diff line change
@@ -1,45 +1,64 @@
---
title: Errors
description: Error codes returned by the Admin API and how to resolve them.
description: Every error code the Admin API returns, and what to do about it.
---

# Admin API Error Codes
Admin API failures carry a code in the `AB` series alongside the HTTP status. The code is the precise reason; the status is the class.

Below is a list of error codes returned by Prisma AIRS AI Gateway Admin API. These help with debugging failed requests and ensuring proper authentication, permissions, and request formatting.
## Error reference

## Error Reference
| Code | Status | Message | Type |
|:--|:--|:--|:--|
| `AB01` | 400 | Request Validation Error | Client Error |
| `AB02` | 404 | Request Validation Error | Client Error |
| `AB03` | 403 | User not allowed to access the resource | Client Error |
| `AB04` | 500 | Internal Server Error | Server Error |
| `AB05` | 401 | Unauthorized access | Client Error |
| `AB06` | 429 | Rate limit exceeded | Client Error |
| `AB07` | 409 | Resource already exists | Client Error |
| `AB08` | 404 | Resource not found | Client Error |
| `AB09` | 402 | Subscription exhausted | Client Error |

| Error Code | HTTP Status | Message | Type |
|------------|-------------|----------------------------------------|--------------|
| AB01 | 400 | Request Validation Error | Client Error |
| AB02 | 404 | Request Validation Error | Client Error |
| AB03 | 403 | User not allowed to access the resource | Client Error |
| AB04 | 500 | Internal Server Error | Server Error |
| AB05 | 401 | Unauthorized access | Client Error |
| AB06 | 429 | Rate limit exceeded | Client Error |
| AB07 | 409 | Resource already exists | Client Error |
| AB08 | 404 | Resource not found | Client Error |
| AB09 | 402 | Subscription exhausted | Client Error |
## The four you will actually hit

---
<AccordionGroup>
<Accordion title="AB05: Unauthorized access (401)" icon="lock">
The request never got as far as being authorised. In order of likelihood:

## Notes on Common Errors
<Note>
**AB01 – Request Validation Error (400)**
1. **A gateway API key was sent instead of an access token.** The Admin API does not accept the key your applications use for inference. Obtain a [Strata Cloud Manager access token](/aigw/api-reference/admin-api/authentication) instead.
2. **The token expired.** Access tokens last 15 minutes. Request a fresh one.
3. **The token is malformed**, truncated in an environment variable or carrying a stray newline.

This error usually happens when:
- You're either missing required parameters
- using incorrect data types (e.g., sending a number instead of a string)
- passing values that are not within the allowed set (enum violations).
Paste the token into [jwt.io](https://jwt.io/) to confirm what it actually contains.
</Accordion>
<Accordion title="AB03: User not allowed to access the resource (403)" icon="ban">
The token is valid, but it does not reach this resource.

</Note>
- **Wrong tenant.** The token's `tsg_id` names a different tenant from the one that owns the resource. A token cannot cross a TSG boundary unless an [access policy](/aigw/api-reference/admin-api/authentication#grant-cross-hierarchy-access-with-an-access-policy) grants it.
- **Insufficient role.** The service account that obtained the token holds a role that does not cover this operation.
- **Wrong workspace.** The resource belongs to a workspace, and the `workspace_id` you passed points somewhere else.
</Accordion>
<Accordion title="AB01: Request Validation Error (400)" icon="triangle-exclamation">
The body did not match what the endpoint expects. Usually one of:

<Note>
**AB05 – Unauthorized Access (401)**
- a required parameter is missing
- a value has the wrong type, a number where a string belongs
- a value sits outside the allowed set for an enum

This indicates that the user is not authorized to access the resource, often due to incorrect API key permissions.
The endpoint's reference page lists every field and its type.
</Accordion>
<Accordion title="AB08: Resource not found (404)" icon="magnifying-glass">
The path is right and the resource is not there. Two causes dominate:

**Common Cause**: Your API key does **not have the right permissions** for this request.
- **A slug was passed where an ID was expected**, or the reverse. Configs, integrations and providers take slugs; guardrails, MCP servers, policies and API keys take IDs.
- **The resource belongs to a workspace you did not name.** Pass `workspace_id` as a query parameter on `GET`, and in the body on `POST` and `PUT`.
</Accordion>
</AccordionGroup>

**Fix**: Go to [stratacloudmanager.paloaltonetworks.com](https://stratacloudmanager.paloaltonetworks.com/) → **API Keys**, and check the permissioning for your key. Ensure it includes the required scopes for the endpoint you're calling.
<Note>
`AB07` on a create means the resource already exists. Most creates are not idempotent, so retrying a request that timed out can produce a `409` rather than a duplicate. Check before retrying blindly.
</Note>

<Card title="Authentication" icon="key" href="/aigw/api-reference/admin-api/authentication">
Most Admin API errors are authentication errors. Start here.
</Card>
Loading
Loading