Skip to main content

Let only your customers call it

Alice, the platform engineer, puts the model qwen-chat on eks-prod behind a JWT policy from your identity provider; for a quick test, API keys that AstroPulse keeps for you. Bob, a developer at your customer, then gets an answer with his token, and a request without one is refused.

Before you start​

  • eks-prod (your cluster's name) has gateway, cert-manager and model-serving; apps.example.com (a domain you own) is verified. external-dns is optional: without it, create the DNS record by hand.
  • JWT (production): your issuer and JWKS address, reachable from the cluster.

1. Alice creates the policy: API keys or JWT​

Path: Integrations > Access Policies

  • Identity provider (OIDC): name, Issuer (exactly the iss in your tokens), JWKS URI (optional: found from the issuer), Audiences (the aud your tokens carry for this model) and Required claims (for example sub). A token passes when its signature verifies with a key from the JWKS, its iss equals the issuer exactly, its aud contains one of the audiences, it is unexpired and every required claim holds. Select Test a token on the policy row, or run astroctl access-policy test <policy> --token-file t.jwt, which returns accepted, reason and message as the endpoint would judge it. A workload on a Kubernetes cluster can use its own service-account token: the EKS example.
  • Or, for a quick test, API keys: Policy name inference-callers (a name for your access policy), Create. AstroPulse holds the keys, so there is no Secret to create.
  • API keys only: on the policy row select Keys, then Create key. Enter a Label naming who the key is for, such as first-caller, and an optional expiry. Copy the value. The endpoint reads Not working until the first key exists.
  • Or from a terminal: astroctl access-policy key create inference-callers --label first-caller. It prints the key once; astroctl access-policy key list inference-callers shows ID, label, created and expiry, never a value.
Open zoom view

Identity provider (OIDC) policy form: Policy name, Issuer, JWKS URI, Audiences, Required claims, Create, Cancel

Identity provider (OIDC) policy form: Policy name, Issuer, JWKS URI, Audiences, Required claims, Create, CancelIdentity provider (OIDC) policy form: Policy name, Issuer, JWKS URI, Audiences, Required claims, Create, Cancel
Open zoom view

API-key policy form: Policy name, Create, Cancel

API-key policy form: Policy name, Create, CancelAPI-key policy form: Policy name, Create, Cancel
Open zoom view

The Keys dialog for the inference-callers policy listing two keys with their label, created date and expiry, and the Create key button

The Keys dialog for the inference-callers policy listing two keys with their label, created date and expiry, and the Create key buttonThe Keys dialog for the inference-callers policy listing two keys with their label, created date and expiry, and the Create key button
Open zoom view

The Keys dialog for inference-callers listing the key eks-run-caller, with the Create key form below it filled with the label revoke-test and the expiry Never, before it is submitted

The Keys dialog for inference-callers listing the key eks-run-caller, with the Create key form below it filled with the label revoke-test and the expiry Never, before it is submittedThe Keys dialog for inference-callers listing the key eks-run-caller, with the Create key form below it filled with the label revoke-test and the expiry Never, before it is submitted
A key is shown once

Hand it to the caller when you create it. AstroPulse never lists a key's value again.

2. Alice attaches it to the model​

Path: Workloads > Models > qwen-chat > Update > Access (qwen-chat is your model deployment's name)

  1. Serve on apps.example.com (your domain).
  2. Who may call it: your policy. Exposure is refused without one.
  3. Review, then apply.

On a model already served, as in the picture, the hostname is fixed and only Who may call it changes. The line under it reads Callers present JWT, or Callers present API keys for a test policy.

Open zoom view

Update, Access step on a model already served: External access qwen-chat.apps.example.com marked Immutable, Who may call it set to qwen-keys, with the line Callers present API keys

Update, Access step on a model already served: External access qwen-chat.apps.example.com marked Immutable, Who may call it set to qwen-keys, with the line Callers present API keysUpdate, Access step on a model already served: External access qwen-chat.apps.example.com marked Immutable, Who may call it set to qwen-keys, with the line Callers present API keys

3. Alice gives Bob a credential​

Path: Workloads > Models > qwen-chat > Overview

  • JWT: your identity provider issues Bob's token. API keys: Alice made Bob's key in step 1.
  • Wait for the endpoint to change from Not ready yet to Ready for callers. The pill can also read Open to anyone, Not working or Closed to callers. The line under Try it then starts Callers must send an API key from access policy <name>. or, for an identity provider, Callers must send a token that access policy <name> accepts.
Open zoom view

Endpoint section: address, Who may call it, the Ready for callers pill and the line saying what callers must send

Endpoint section: address, Who may call it, the Ready for callers pill and the line saying what callers must sendEndpoint section: address, Who may call it, the Ready for callers pill and the line saying what callers must send

4. Alice calls it the way Bob will​

Path: Workloads > Models > qwen-chat > Call it from code

  • Set ASTROPULSE_API_KEY to a service-account key from Settings, Service Accounts, then run the code with Bob's credential.
Python
from astropulse import Client

ap = Client() # reads ASTROPULSE_API_KEY
application = ap.applications.get_application("qwen-chat")
print(application.data.model.external_endpoint)
Python
from openai import OpenAI

client = OpenAI(base_url=application.data.model.external_endpoint,
api_key="<key or JWT the policy accepts>")

client.chat.completions.create(
model="<model-name>", # the name shown in Call it from code
messages=[{"role": "user", "content": "Hello"}],
)

The same call with curl; both send the credential as Authorization: Bearer <credential>; a policy with apiKeys.header: x-api-key takes x-api-key: <your-key> instead.

Terminal
ENDPOINT=$(astroctl app endpoint get qwen-chat -o json | jq -r .url) # https://<hostname>/v1
curl -s "$ENDPOINT/chat/completions" \
-H "Authorization: Bearer <your-key-or-token>" \
-H "Content-Type: application/json" \
-d '{"model": "<model-name>", "messages": [{"role": "user", "content": "Hello"}]}'

A call without a credential, or with a wrong, revoked or expired one, is refused with 401. A token for another audience, or a valid token that lacks a required claim, is refused with 403. For what each refusal means and what to do next, see When a call is refused.

Open zoom view

Call it from code: SDK and OpenAI snippets

Call it from code: SDK and OpenAI snippetsCall it from code: SDK and OpenAI snippets

To check without code, select Try it in the Models list or on the model's Overview and paste a key or token the policy accepts; the page keeps it until you reload or leave. Try it is off until the endpoint is serving, and off for an embeddings model, because a chat gets 404 from one.

Open zoom view

Models list: qwen-chat Running on eks-prod, GPU 1× L4, its public endpoint with Copy, and Try it

Models list: qwen-chat Running on eks-prod, GPU 1× L4, its public endpoint with Copy, and Try itModels list: qwen-chat Running on eks-prod, GPU 1× L4, its public endpoint with Copy, and Try it

5. Alice rotates a credential​

Path: Integrations > Access Policies

  • JWT: rotate the signing key in your identity provider; AstroPulse reads its JWKS.
  • API keys: on the policy row select Keys, then Revoke beside the caller's key and type its label to confirm. It stops on every model that uses the policy within a minute, not instantly, with no restart.
Open zoom view

The revoke confirmation for one key, asking to type its label, with the Revoke key button and Cancel

The revoke confirmation for one key, asking to type its label, with the Revoke key button and CancelThe revoke confirmation for one key, asking to type its label, with the Revoke key button and Cancel
Revoking the last key takes models offline

The confirmation names them (qwen-chat will refuse every caller until a new key is created.) and asks you to type the policy name instead of the label; expired keys do not count. astroctl access-policy key revoke prints the same warning and asks for the policy name. A revoke is never blocked, so a leaked key can always be cut off at once.

6. Alice closes the endpoint​

Path: Workloads > Models > qwen-chat > Overview > Endpoint

  • Select Close endpoint and confirm in Close this endpoint?. To open it again, select Reopen endpoint.
Open zoom view

Close this endpoint dialog: Keep it open, Close endpoint

Close this endpoint dialog: Keep it open, Close endpointClose this endpoint dialog: Keep it open, Close endpoint
NovaNova
Is qwen-chat's endpoint ready for callers, and which access policy guards it?

Nova reads the model's endpoint and answers. Create policies and keys in the console or with astroctl.

Never Anyone for a paid API

The Anyone option (no authentication) lets anyone who finds the URL run inference on your GPUs. It needs an org Owner and is audited. In production, use JWT with audiences and required claims set.

Clean up​

Delete the model first, because a policy that an application references cannot be deleted. Then under Integrations > Access Policies select Delete on the policy, type its name, and confirm with Delete policy. For the full order, see Clean up.