Skip to content
Registry StackDocsv0.46.0

Control who can request evidence

For the assertion provider

View as Markdown

In about fifteen minutes you will register two applications under access profiles of their own, send the same region request as each, and see one answered and the other refused. You continue in the project from Return a governed value, with the source and Registry Evidence still running.

Outcome
Two clients with distinct access profiles, one region request answered and one refused.
Time
About 15 minutes
Level
Local development with synthetic data
Prerequisites
The project, source, and Registry Evidence left running by Return a governed value

In first-evidence-assertion/adult-status, list the clients the project knows:

Terminal window
rstack evidence access client list --format json | jq -c '.entries[]'
{"accessProfiles":["standalone-service"],"id":"example-caller","status":"active"}
{"accessProfiles":["standalone-service"],"id":"tutorial-client","status":"active"}

A client is one application’s identity. Both hold standalone-service, so both may ask every question that access profile grants. example-caller comes with the project; you added tutorial-client in Your first assertion.

Give each new application a profile with one grant. Add these profiles to the end of dev-authority.yaml, at the same indentation as standalone-service:

dev-authority.yaml
age-checker-service:
authority: organizational
actorKind: service
requesterTags:
- age-checker-service
grants:
- definition: adult-status
purpose: age-check
audienceFrom: authenticated-requester
representations:
- signed-jws
subjectBinding: audience-scoped
subjects:
- role: subject
selectorProfile: record-by-id
valueOrigin: request
region-router-service:
authority: organizational
actorKind: service
requesterTags:
- region-router-service
grants:
- definition: residence-region
purpose: residence-check
audienceFrom: authenticated-requester
representations:
- signed-jws
subjectBinding: audience-scoped
subjects:
- role: subject
selectorProfile: record-by-id
valueOrigin: request

requesterTags lists the tags a caller’s token must carry to act under the profile. Check that each grant stays inside its definition’s grant ceiling:

Terminal window
rstack evidence check . --target local-target.yaml
0 errors, 0 warnings in 1 file

Registry Evidence reads profiles and clients only as it starts, and rstack evidence refuses a client change while it runs, so stop it first:

Terminal window
rstack evidence dev stop .
Local Evidence stopped

Register one client per profile; the local issuer puts each profile’s tags in its client’s tokens:

Terminal window
rstack evidence access client add age-checker \
--access-profile age-checker-service \
--generate-local-key
rstack evidence access client add region-router \
--access-profile region-router-service \
--generate-local-key
Added client age-checker with access profile age-checker-service.
Added client region-router with access profile region-router-service.

Start Registry Evidence again with the same ports, so it loads the profiles and clients:

Terminal window
rstack evidence dev start . \
--target local-target.yaml \
--evidence-port 18080 \
--issuer-port 8082
Evidence ready at http://127.0.0.1:18080

The source kept running throughout.

Ask for a purpose the definition does not declare

Section titled “Ask for a purpose the definition does not declare”

adult-status declares only the purpose age-check. Ask under another:

Terminal window
rstack evidence request prepare adult-status \
--client age-checker \
--purpose residence-check \
--subject subject:record-id=adult \
--name adult-wrong-purpose
evidencectl: purpose does not match the active local tutorial definition

Preparation refuses it, so nothing reaches Registry Evidence.

Preparation checks the request against the project, not the grants, so both succeed:

Terminal window
rstack evidence request prepare residence-region \
--client region-router \
--purpose residence-check \
--subject subject:record-id=adult \
--name region-by-router
rstack evidence request prepare residence-region \
--client age-checker \
--purpose residence-check \
--subject subject:record-id=adult \
--name region-by-checker

Send the request as region-router; Registry Evidence applies that client’s grants:

Terminal window
rstack evidence api /v1/evidence \
--client region-router \
--input .evidence/requests/region-by-router/request.json \
--accept application/jose+json \
--output region-by-router.response

Send the other prepared request as age-checker. The API writes the refusal body and exits 1 for the HTTP 403 response:

Terminal window
rstack evidence api /v1/evidence \
--client age-checker \
--input .evidence/requests/region-by-checker/request.json \
--accept application/jose+json \
--output region-by-checker.response

Read the refusal age-checker received:

Terminal window
jq . region-by-checker.response
{
"type": "https://id.registrystack.org/problems/registry-evidence/evidence/denied",
"title": "Evidence request is not permitted",
"status": 403,
"detail": "the Evidence request is not permitted",
"code": "evidence.denied",
"traceId": "<trace-id>"
}

evidence.denied does not name the missing grant. Evidence problems lists every code.

Leave the source and Registry Evidence running; the next tutorial continues with them.

Assert a role-bound relationship