Skip to content

ActorIdentity: protos, cert issuance, actorIdentity x509 extension - #670

Open
Lior Lieberman (LiorLieberman) wants to merge 4 commits into
agent-substrate:mainfrom
LiorLieberman:actoridentity-mintcert-authz
Open

ActorIdentity: protos, cert issuance, actorIdentity x509 extension#670
Lior Lieberman (LiorLieberman) wants to merge 4 commits into
agent-substrate:mainfrom
LiorLieberman:actoridentity-mintcert-authz

Conversation

@LiorLieberman

Copy link
Copy Markdown
Collaborator

Also Fixes #575

(1) mintCert + MintJWT proto changes
(2) validate that atelet is the one that calls actorIdentity Service.
(3) verify that this atelet is only requesting a cert for an actor on its node.
(4) verify that the actor is still running
(5) create another substatex509 extension for actor identities

JWTs needs more love, lots as TODO there

It's a good idea to open an issue first for discussion.

  • Tests pass
  • Appropriate changes to documentation are included in the PR

string actor_uid = 4;
}

//TODO (lior) check why k8s do ":" and not "/" as a seprator for the Subject format

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we clean up this TODO?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

have any opinion on this?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not familiar with the history of k8s JWT and why we decided to use ":", I think either is fine here.

Comment thread docs/api-guide.md Outdated
Comment thread cmd/ateapi/internal/actoridjwt/actoridjwt.go
Comment thread cmd/ateapi/internal/actoridentity/actoridentity.go
app_id, user_id and actor_id had no producer anywhere in the tree and no
mapping to the actor database, which is keyed by (atespace, name). Nothing
could look up the actor a request named. Replace them with the fields the
data model actually uses.

  MintCertRequest: atespace = 1, actor_name = 2, csr = 4
  MintJWTRequest:  audience = 1, atespace = 2, actor_name = 3

Field 3 (MintCert) and field 4 (MintJWT) are deliberately left free as the
slot for a future actor_uid or actor_version, per the TODOs.

The credential identities move with the fields:

  JWT sub  apps/${app}/users/${user}/actors/${actor}
        -> atespaces/${atespace}/actors/${name}
  ate.dev  {appID, userID, actorID} -> {atespace, actorName}
  SPIFFE   spiffe://substrate-actor.local/app/../user/../actor/..
        -> spiffe://substrate-actor.local/atespace/../actor/..

BREAKING: the request wire format changes. MintCert has no caller in the
tree, so nothing in-repo breaks; external callers must be updated.

No behavior change beyond the rename — the authorization gate this enables
lands separately. Stubs regenerated with the pinned toolchain (protoc-gen-go
v1.36.11-devel, protoc-gen-go-grpc v1.6.1, grpcio-tools 1.81.1), verified to
reproduce the committed baseline byte-for-byte before the proto was edited.
MintCert previously signed any CSR it was handed. The only gate was that a
client certificate had been presented; it never checked who presented it or
whether they had any relationship to the requested actor, contrary to the
contract stated in ateapi.proto. Any workload holding a pod-identity
certificate could mint a credential for an arbitrary actor.

Require instead that the caller is the atelet on the node hosting the actor,
and that the actor is still running:

  - the client certificate must carry the atelet SPIFFE identity and a
    PodIdentity extension, which pins the caller to a node;
  - the actor must be STATUS_RUNNING in the actor database;
  - the worker Pod hosting it must be on the caller's node and still assigned
    to that actor.

Denials are deliberately indistinguishable so the RPC cannot be used to
discover whether an actor exists or where it is running.
Subject: fmt.Sprintf("apps/%s/users/%s/actors/%s", req.GetAppId(), req.GetUserId(), req.GetActorId()),
// TODO: This is currently API but it has to be a globally unique, oidc-compliant and accsible DNS name
Issuer: "https://api.ate-system.svc",
Subject: fmt.Sprintf("atespaces/%s/actors/%s", req.GetAtespace(), req.GetActorName()),

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/atesapces OR at atespace/%s

actors/ OR actor/

@zoez7

Copy link
Copy Markdown
Collaborator

LGTM. I approve this spelling as a Canadian but we need to make the tests happy:
image

@maxsmythe Max Smythe (maxsmythe) left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Rename SessionIdentity to ActorIdentity and reconsider JWT claims

3 participants