Skip to content

Bind gateway-minted actor JWTs to the actor's UID through the ateom-for-actor certificate #2208

Open

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.actorUID claim 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's actor_uid against the store. It would also write the UID into the path.
  • In internal/resources, AteomForActorSPIFFEID takes the UID and the parser returns it.
  • In the egress gateway, verifyActorCertificate and actorFromFilterState return the UID. The request legs already receive the whole URI SAN through the dev.ate.actor.identity filter state (%DOWNSTREAM_PEER_URI_SAN%), so the Envoy config doesn't change.
  • Add actor_uid and the ABORTED check back to MintActorJWTRequest. The actor JWT minter sends the UID and caches tokens by UID instead of by name, and applyEffects maps 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.

Related: #1660, #1809, #2135, #2141, #2207.

Metadata

Metadata

Labels

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions