Skip to content

ateom/actor ID split: Ateom uses MintAteomActorCertificate - #1809

Merged
Haven Xia (HavenXia) merged 10 commits into
agent-substrate:mainfrom
ahmedtd:separate-certs-2
Sep 25, 2026
Merged

Haven Xia (HavenXia) merged 10 commits into
agent-substrate:mainfrom
ahmedtd:separate-certs-2

Conversation

@ahmedtd

@ahmedtd Taahir Ahmed (ahmedtd) commented Sep 22, 2026 •

Copy link
Copy Markdown
Collaborator

Update atelet/ateom/atunnel to use the new MintAteomActorCertificate, and correct anything that was coded to expect the old actor SPIFFE URI.

return nil
}
actor, err := resources.ActorRefFromSPIFFEID(actorSpiffeID)
actor, err := resources.ActorRefFromActorSPIFFEID(actorSpiffeID)

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.

Does this need to use ActorRefFromAteomForActorSPIFFEID? My understanding is that the actorSpiffeID here is the one we constructed with AteomForActorSPIFFEID in egress/credentials.go and passed to FetchSecret.

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.

Hmmmm. I think this field logically should be the actor SPIFFE ID, not the ateom-for-actor SPIFFE ID. This might mean we need to rewrite the URI in the egress gateway: once we authenticate the incoming ateom-for-actor certificate, construct the correct actor SPIFFE ID.

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.

I've made the necessary adjustments.

Egress parses the ateom-for-actor SPIFFE ID from the incoming connection into an ActorRef, then flattens it back to a plain actor SPIFFE ID when calling plugins (because they care about the actor identity, not the ateom identity).

Comment on lines +42 to +66
func ActorRefFromActorSPIFFEID(id string) (ActorRef, error) {
u, err := url.Parse(id)
if err != nil {
return ActorRef{}, fmt.Errorf("invalid actor SPIFFE ID %q: %w", id, err)
}
return ActorRefFromActorSPIFFEURL(u)
}

func ActorRefFromActorSPIFFEURL(u *url.URL) (ActorRef, error) {
if u.Scheme != "spiffe" || u.Host != ActorSPIFFETrustDomain || u.User != nil || u.RawQuery != "" || u.Fragment != "" {
return ActorRef{}, fmt.Errorf("%q does not have format spiffe://<trust.domain>/actor/<atespace>/<name>", u.String())
}
segments := strings.Split(strings.TrimPrefix(u.Path, "/"), "/")
if len(segments) != 3 || segments[0] != "actor" {
return ActorRef{}, fmt.Errorf("%q does not have format spiffe://<trust.domain>/actor/<atespace>/<name>", u.String())
}
atespace, name := segments[1], segments[2]
if !IsValidResourceName(atespace) {
return ActorRef{}, fmt.Errorf("%q is not a valid atespace", atespace)
}
if !IsValidResourceName(name) {
return ActorRef{}, fmt.Errorf("%q is not a valid actor name", name)
}
return ActorRef{Atespace: atespace, Name: name}, nil
}

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.

Should we add tests for these?

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.

Done.

Scheme: "spiffe",
Host: "substrate-actor.local",
Path: path.Join("atespace", identity.Atespace, "actor", identity.ActorName),
Path: path.Join("ateom", "actor", atespace, actorName),

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.

IIUC the new ateom for actor cert identifier format is "ateom-for-actor/Atespace/Name", do we need to update that here?

Also not sure how the tests are passing here while the "wrong" format is being used.

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.

Yup, let me investigate why they are passing.

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.

The SPIFFE ID is only used in a context where it is supposed to point at an invalid actor.

Comment on lines +284 to +303
if !strings.Contains(line.text, actorName) {
t.Logf("Log line does not contain %s, discarding", actorName)
continue
}
t.Logf("Considering log line: %s", line.text)
authority, ok := accessLogField(line.text, "authority")
if ok && strings.HasSuffix(authority, ":"+port) && strings.Contains(line.text, "/actor/"+actorName) {
t.Logf("egress gateway tunneled the request: %s", line.text)
return true
if !ok {
t.Logf("Log line does not have an authority field, discarding")
continue
}
if !strings.HasSuffix(authority, ":"+port) {
t.Logf("Authority does not contain %s, discarding", ":"+port)
continue
}
spiffeSlug := "/ateom-for-actor/" + atespace + "/" + actorName
if !strings.Contains(line.text, spiffeSlug) {
t.Logf("Log line does not contain %q, discarding", spiffeSlug)
continue
}
t.Logf("Log line matches")

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.

Looks like some of these logs might be for debugging tests, are they all useful or should we trim them down?

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.

Thanks, trimmed

Merged via the queue into agent-substrate:main with commit 8d6be5f Sep 25, 2026
10 of 11 checks passed
Davanum Srinivas (dims) pushed a commit to dims/substrate that referenced this pull request Sep 26, 2026
…nt-substrate#1810)

The purpose field in MintActorCertificate (and the certs it issues) is
no longer needed. The distinction between actors and ateoms-for-actors
is now built into the SPIFFE URI.

Stacked over agent-substrate#1809
John Howard (howardjohn) pushed a commit to agentgateway/agentgateway that referenced this pull request Sep 26, 2026
Substrate's ateom/actor identity split in
agent-substrate/substrate#1809 removed the
certificate extension that agentgateway used to authorize egress. It
also changed the actor SPIFFE URI expected by credential providers, so
both CONNECT authorization and credential injection broke.

This PR reads the single
`spiffe://substrate-actor.local/ateom-for-actor/<atespace>/<actor>` URI
from the authenticated certificate and keeps the `GetActor` check that
the actor exists and is running. The UID now comes from `GetActor` for
logging. Credential providers receive
`spiffe://substrate-actor.local/actor/<atespace>/<actor>`.

AI assistance: Codex prepared the implementation, tests, code comments,
and this draft description.

- [x] As required by the [Code of
Conduct](https://github.com/agentgateway/agentgateway/blob/main/CODE_OF_CONDUCT.md#generative-ai-policy),
the description, docs, and comments (words meant for humans) are written
by a human, not by an LLM.

Signed-off-by: Eitan Yarmush <eitan.yarmush@solo.io>
@bowei Bowei Du (bowei) added area/api-machinery area/identity area/network area/node area/security Security related issue/pr kind/feature An enhancement / feature request or implementation labels Sep 29, 2026
Quentin Bisson (QuentinBisson) added a commit to giantswarm/substrate that referenced this pull request Oct 5, 2026
…ess gateway

The agentgateway line's 2.3.0 is its re-pin onto upstream v1.6.0 (ea560864): the egress gateway authorizes
from the spiffe://substrate-actor.local/ateom-for-actor/<atespace>/<actor> URI that kagent-dev/substrate
v0.3.0-alpha3's ateom presents (agent-substrate#1809, agentgateway#3677), which 2.2.2 refuses.
Upstream's chart pins the same build as ghcr.io/kagent-dev/substrate/agentgateway:50999825cb55 (agentgateway#3689).
The chart default and the CircleCI agentgateway-image parameter move together.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/api-machinery area/identity area/network area/node area/security Security related issue/pr kind/feature An enhancement / feature request or implementation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants