Back to home

Sandbox

Get an agent identity, end to end

Five calls: register an agent, exchange its key for a short-lived certificate, confirm the certificate is still good, then revoke it and watch it disappear from the list. No account, no signup — the sandbox is open, and every call below is one you can paste into a terminal right now.

Nothing here is a real identity. The sandbox signs with a throwaway CA generated in memory at startup, so certificates stop verifying when it restarts and every key and report is forgotten at the same moment. Production issuance is a different key entirely, on register.trustatria.com, and needs an account.

  1. 1

    Pin the sandbox CA

    Everything the sandbox signs chains to this certificate. A proxy pins it once and then trusts nothing else — which is why a certificate from any other issuer is refused at the handshake rather than at the policy check.

    request
    curl -s https://sandbox.trustatria.com/ca -o sandbox-ca.pem
    sandbox-ca.pem
    -----BEGIN CERTIFICATE-----
    MIIBkTCCATegAwIBAgIUJ8k...
    -----END CERTIFICATE-----

    Regenerated whenever the sandbox restarts. Pin it again after one, or certificates minted since will not verify against your copy.

    Try GET /ca in the console
  2. 2

    Register the agent

    Open — no credential, because this is the call an agent makes before it has one. The API key comes back exactly once; the sandbox keeps only a hash of it.

    request
    curl -s -X POST https://sandbox.trustatria.com/register \
      -H 'content-type: application/json' \
      -d '{"agent_id": "demo-bot"}'
    response
    {
      "agent_id": "demo-bot",
      "key_id": "cb2142b586c8854f",
      "api_key": "atria_cb2142b586c8854f_fe6fafa42987...45f452"
    }
    Try POST /register in the console
  3. 3

    Exchange the key for a certificate

    The one call in this walkthrough that takes a credential. Send a PEM certificate signing request to keep the private key yours — that is what a real agent does. Omit it and the sandbox generates the key pair for you, a demo convenience and nothing to copy into production.

    request
    curl -s -X POST https://sandbox.trustatria.com/session \
      -H "authorization: Bearer $API_KEY" \
      -H 'content-type: application/json' \
      -d '{"ttl_seconds": 900}'
    response
    {
      "agent_id": "demo-bot",
      "serial": "67037dbca6524bed12ce984b80343588",
      "certificate_pem": "-----BEGIN CERTIFICATE-----\n...",
      "private_key_pem": "-----BEGIN PRIVATE KEY-----\n...",
      "not_after": "2026-08-24T01:19:14.494811942Z"
    }

    Unknown key, deactivated key and malformed key all answer the same 401 INVALID_API_KEY — the endpoint must not sort guessed key ids into real and not-real.

    Try POST /session in the console
  4. 4

    Check the certificate is still good

    Holding a certificate is only half of an identity. The other half is that it has not been revoked since it was issued, which is what the signed revocation list answers. A proxy pulls this on a schedule and re-checks it on every request — not once at the handshake, because a long-lived connection must not keep working on a certificate that has since been withdrawn.

    request
    curl -s https://sandbox.trustatria.com/crl -o sandbox.crl
    openssl crl -inform DER -in sandbox.crl -noout -text | head -20
    response
    Certificate Revocation List (CRL):
            Version 2 (0x1)
            Signature Algorithm: ecdsa-with-SHA256
            Issuer: CN = Atria CA, O = Trust Atria
            Last Update: Aug 24 01:04:02 2026 GMT
            Next Update: Aug 24 02:04:02 2026 GMT
            CRL extensions:
                X509v3 CRL Number:
                    1
    No Revoked Certificates.
    Try GET /crl in the console
  5. 5

    Revoke it, and watch the list change

    The sandbox exposes the operator side too, so you can see the other end of the loop. This deactivates the agent’s API keys, revokes its outstanding certificates and republishes the list under the next number in one call.

    request
    curl -s -X POST https://sandbox.trustatria.com/admin/revoke \
      -H 'content-type: application/json' \
      -d '{"agent_id": "demo-bot", "reason": "key_compromise"}'
    
    curl -s https://sandbox.trustatria.com/crl -o sandbox.crl   # now lists serial 67037dbc...
    response
    {
      "agent_id": "demo-bot",
      "certificates_revoked": 1,
      "api_keys_deactivated": 1,
      "crl_number": 2
    }

    The certificate from step 3 is now refused everywhere that pulls this list, before its own expiry — and its API key can no longer mint a replacement.

    Try POST /admin/revoke in the console

The other half

Enforcement, and where it runs

The five steps above get an agent an identity. Enforcement is the other half, and it is not something a sandbox can show you from a browser: the agent has to present its certificate over mTLS, so the proxy has to run somewhere that can terminate TLS with a client certificate.

If you are deploying it in front of a real backend, that is apt install atria-proxy — five steps on a Debian or Ubuntu host, nothing to compile.

To watch the whole flow on your own machine instead — allowed call, denied call, audit log, all of it — run the stack from source: four processes and a demo agent.

shell
cargo build --workspace
atria-ca server-cert --out-dir ./tls    # a development server identity
mock-cloud &                            # the cloud, same code as the sandbox
mock-target &                           # the customer's backend
curl -s http://127.0.0.1:8443/ca -o ca.pem

ATRIA_CA_CERT=./ca.pem \
ATRIA_TLS_CERT=./tls/server-cert.pem ATRIA_TLS_KEY=./tls/server-key.pem \
ATRIA_POLICY_FILE=./policies.yaml \
ATRIA_CRL_URL=http://127.0.0.1:8443/crl \
ATRIA_ADMIN_ADDR=127.0.0.1:8081 \
  atria-proxy &

ATRIA_ADMIN_URL=http://127.0.0.1:8081 \
  demo-client --server-ca ./tls/server-ca.pem

The demo agent then makes the two calls worth seeing: one the policy allows, which reaches the backend, and one it does not, which comes back 403 with a reason code and nothing else — which rule matched goes to the audit log, never to the caller.