This is an automated email from the ASF dual-hosted git repository. hsluoyz pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/casbin-gateway.git
commit 192105781dbdeb66b3bc67b9cb7e7a0f25e15b7a Author: Yang Luo <[email protected]> AuthorDate: Sun Sep 6 15:08:11 2026 +0800 fix(connector): write a connection into the home of the account the agent runs as --- agent/config_owner.go | 41 +++++++++++++++++++++++++++++++++++++++++ controllers/connector.go | 8 ++++++-- controllers/permission.go | 2 +- object/connection.go | 7 +++++-- object/connection_install.go | 13 +++++++++---- 5 files changed, 62 insertions(+), 9 deletions(-) diff --git a/agent/config_owner.go b/agent/config_owner.go new file mode 100644 index 0000000..ac35e61 --- /dev/null +++ b/agent/config_owner.go @@ -0,0 +1,41 @@ +// Copyright 2026 The casbin Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package agent + +import "github.com/apache/casbin-gateway/agenthome" + +// ConfigOwnerOf is the account whose home an agent's configuration files live +// in. It is not the account a Gateway row is stored under: that one names who +// signed in here, and writing a file needs the account the agent runs as. +// +// Installations of one agent under several accounts share an id, so the first +// one whose home this Gateway can actually reach wins. An agent no scan found +// falls back to the account Gateway runs as, which is where its files would be. +func ConfigOwnerOf(agentId string) string { + installations, err := Scan(false) + if err != nil { + return "" + } + + for _, installation := range installations { + if installation.AgentId != agentId { + continue + } + if _, err := agenthome.Resolve(installation.Owner); err == nil { + return installation.Owner + } + } + return "" +} diff --git a/controllers/connector.go b/controllers/connector.go index 5a3759d..f243b62 100644 --- a/controllers/connector.go +++ b/controllers/connector.go @@ -151,11 +151,15 @@ func connectorTargets() ([]*ConnectorTarget, error) { continue } seen[installation.AgentId] = true + // The account whose configuration is written rather than the one this + // row was found under, so the file named here is the file a connection + // actually lands in. + account := agent.ConfigOwnerOf(installation.AgentId) targets = append(targets, &ConnectorTarget{ AgentId: installation.AgentId, Name: installation.Name, - Owner: installation.Owner, - McpFile: agentconfig.McpConfigFile(installation.AgentId, installation.Owner), + Owner: account, + McpFile: agentconfig.McpConfigFile(installation.AgentId, account), }) } diff --git a/controllers/permission.go b/controllers/permission.go index 2784dfd..9f32633 100644 --- a/controllers/permission.go +++ b/controllers/permission.go @@ -59,7 +59,7 @@ func mcpItemsOf(agentId string, owner string) []object.ToolItem { } // A connection that has been tested knows what it offers, so its tools get a // switch each, under the server switch they already had. - items = append(items, object.ConnectionToolItems(agentId, owner)...) + items = append(items, object.ConnectionToolItems(agentId)...) return items } diff --git a/object/connection.go b/object/connection.go index 11fad51..a35ff82 100644 --- a/object/connection.go +++ b/object/connection.go @@ -263,8 +263,11 @@ func DeleteConnection(owner string, name string) error { // this agent, built from what the last test found. A connection nobody has // tested contributes none and is governed by its server switch alone, which is // what makes testing worth doing beyond seeing that it works. -func ConnectionToolItems(agentId string, owner string) []ToolItem { - connections, err := GetConnections(owner) +// Every connection on the machine is looked at, whoever signed in to make it: +// the switches are per agent, and an agent does not know which account added +// the server it was given. +func ConnectionToolItems(agentId string) []ToolItem { + connections, err := getAllConnections() if err != nil { return nil } diff --git a/object/connection_install.go b/object/connection_install.go index b02e899..2ecec4c 100644 --- a/object/connection_install.go +++ b/object/connection_install.go @@ -18,6 +18,7 @@ import ( "fmt" "sort" + "github.com/apache/casbin-gateway/agent" "github.com/apache/casbin-gateway/agentconfig" "github.com/apache/casbin-gateway/agentpatch" "github.com/apache/casbin-gateway/connector" @@ -100,13 +101,17 @@ func proxyRequest(connection *Connection, found connector.Connector, agentId str if err != nil { return agentconfig.McpRequest{}, err } - token, err := agentpatch.IssueIngestToken(agentpatch.Target{AgentId: agentId, Owner: connection.Owner}) + // Two different accounts meet here: connection.Owner is who signed in to + // Gateway, and the entry has to be written into the home of the account the + // agent runs as. Only the proxy's own --owner names the first. + account := agent.ConfigOwnerOf(agentId) + token, err := agentpatch.IssueIngestToken(agentpatch.Target{AgentId: agentId, Owner: account}) if err != nil { return agentconfig.McpRequest{}, err } return agentconfig.McpRequest{ - Owner: connection.Owner, + Owner: account, To: []string{agentId}, Name: found.Server.Name, Transport: agentconfig.TransportStdio, @@ -169,7 +174,7 @@ func revokeUnusedTokens(owner string, agentIds []string) { if remaining[agentId] { continue } - _ = agentpatch.RevokeIngestToken(agentpatch.Target{AgentId: agentId, Owner: owner}) + _ = agentpatch.RevokeIngestToken(agentpatch.Target{AgentId: agentId, Owner: agent.ConfigOwnerOf(agentId)}) } } @@ -211,7 +216,7 @@ func removeFrom(connection *Connection, serverName string, agentIds []string) [] planned := []*agentconfig.PlanItem{} for _, agentId := range agentIds { item := &agentconfig.PlanItem{AgentId: agentId, Name: serverName, Action: agentconfig.ActionRemove} - if err := agentconfig.Delete(agentId, connection.Owner, agentconfig.KindMcp, serverName); err != nil { + if err := agentconfig.Delete(agentId, agent.ConfigOwnerOf(agentId), agentconfig.KindMcp, serverName); err != nil { item.Action, item.Reason = agentconfig.ActionSkip, err.Error() } planned = append(planned, item) --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
