Repository navigation
Description
Problem
#2207 removed actor_uid from MintActorJWTRequest, along with the check that refused with ABORTED when the stored actor had a different UID. That check caught a caller still acting for an actor that was deleted and then recreated under the same name.
It went because the egress gateway (#2135, #2141), the only caller, knows the actor only by name: the ateom-for-actor certificate's one URI SAN is spiffe://substrate-actor.local/ateom-for-actor/<atespace>/<name>. Any UID the gateway sent came from ateapi itself, so the check compared ateapi with itself (review on #2135).
As a result, gateway tokens follow the name. If an actor is deleted and a new one is created with the same name:
- an old ateom that still holds a valid certificate can get tokens for the new actor;
- the gateway's token cache can give the new actor its predecessor's token until the refresh point, which is up to 40 minutes at the 3600s maximum lifetime. That token's
ate.dev.actorUIDclaim names the old actor.
Proposal
Put the UID in the ateom-for-actor SPIFFE ID, for example spiffe://substrate-actor.local/ateom-for-actor/<atespace>/<name>/<uid>.
MintAteomActorCertificate(cmd/ateapi/internal/workerservice/certificate.go) already checks the request'sactor_uidagainst the store. It would also write the UID into the path.- In
internal/resources,AteomForActorSPIFFEIDtakes the UID and the parser returns it. - In the egress gateway,
verifyActorCertificateandactorFromFilterStatereturn the UID. The request legs already receive the whole URI SAN through thedev.ate.actor.identityfilter state (%DOWNSTREAM_PEER_URI_SAN%), so the Envoy config doesn't change. - Add
actor_uidand the ABORTED check back toMintActorJWTRequest. The actor JWT minter sends the UID and caches tokens by UID instead of by name, andapplyEffectsmaps ABORTED to 403.
Today only the certificate issuer, internal/resources, and the egress handler use the ateom-for-actor ID format.
Open questions
- Where should the UID go? A SPIFFE path segment reaches the request legs with no Envoy change, because they already receive the URI SAN through filter state, but it makes the ID unique per actor incarnation. A Subject field or a non-critical extension keeps the ID name-only. Envoy can expose the Subject (
%DOWNSTREAM_PEER_SUBJECT%) but not an extension, so either one needs new filter-state plumbing to the request legs, and an extension also needs an OID. A second URI SAN is out, since an X.509-SVID carries exactly one. - Rollout: certificates are valid for an hour. A gateway that requires the new format would refuse old-format certificates until each ateom renews, so upgrade order matters, or we accept that window.
- The egress policy check also identifies the actor by name. With the UID available on every leg, it could check the UID too. That's probably a separate issue.
Activity
MintActorJWT no longer takes the actor's UID (agent-substrate#2207)
Document the actor JWT contract and how relying parties verify it (ag…
Document the actor JWT contract and how relying parties verify it (#2605