diff --git a/policy/memory-action.go b/policy/memory-action.go index 5d20282..6e52845 100644 --- a/policy/memory-action.go +++ b/policy/memory-action.go @@ -50,9 +50,15 @@ const ( // MemoryListSecretsAction - list the secrets in a cortex. MemoryListSecretsAction MemoryAction = "memory:ListSecrets" - // MemoryPutAgentAction - write an agent record in a cortex. + // MemoryPutAgentAction - create an agent record, or write a memory beneath + // it. Create-only, so it is safe to grant alongside a memory write. MemoryPutAgentAction MemoryAction = "memory:PutAgent" + // MemoryUpdateAgentAction - modify an existing agent record in a cortex. Separate + // from MemoryPutAgentAction, which only creates: an update re-derives the agent's + // IAM policy from its mounts, so it must be grantable without granting creation. + MemoryUpdateAgentAction MemoryAction = "memory:UpdateAgent" + // MemoryGetAgentAction - read an agent record from a cortex. MemoryGetAgentAction MemoryAction = "memory:GetAgent" @@ -84,6 +90,7 @@ var SupportedMemoryActions = map[MemoryAction]struct{}{ MemoryDeleteSecretAction: {}, MemoryListSecretsAction: {}, MemoryPutAgentAction: {}, + MemoryUpdateAgentAction: {}, MemoryGetAgentAction: {}, MemoryDeleteAgentAction: {}, MemoryListAgentsAction: {}, diff --git a/policy/memory-action_test.go b/policy/memory-action_test.go index a41c641..a261d4a 100644 --- a/policy/memory-action_test.go +++ b/policy/memory-action_test.go @@ -35,6 +35,7 @@ func TestMemoryActionIsValid(t *testing.T) { {MemoryDeleteSecretAction, true}, {MemoryListSecretsAction, true}, {MemoryPutAgentAction, true}, + {MemoryUpdateAgentAction, true}, {MemoryGetAgentAction, true}, {MemoryDeleteAgentAction, true}, {MemoryListAgentsAction, true}, diff --git a/policy/memory-resource_test.go b/policy/memory-resource_test.go index 6514bbd..96bf7f4 100644 --- a/policy/memory-resource_test.go +++ b/policy/memory-resource_test.go @@ -791,7 +791,10 @@ func TestStarPrefixedResourceParses(t *testing.T) { // both actions against one resource would leak names without any cue. func TestMemoryEnumerationConditionKeys(t *testing.T) { listActions := []string{"memory:ListAgents", "memory:ListSecrets", "memory:ListCortexes"} - pointActions := []string{"memory:GetAgent", "memory:PutAgent", "memory:DeleteAgent", "memory:GetSecret"} + pointActions := []string{ + "memory:GetAgent", "memory:PutAgent", "memory:DeleteAgent", "memory:GetSecret", + "memory:UpdateAgent", + } for _, action := range listActions { keys, ok := MemoryActionConditionKeyMap[Action(action)] @@ -809,8 +812,10 @@ func TestMemoryEnumerationConditionKeys(t *testing.T) { // let a policy look scoped while constraining nothing. for _, action := range pointActions { keys := MemoryActionConditionKeyMap[Action(action)] - if keys.Match(condition.MemoryPrefix.ToKey()) { - t.Errorf("%s must not accept %s", action, condition.MemoryPrefix) + for _, key := range []condition.KeyName{condition.MemoryPrefix, condition.MemoryMaxKeys} { + if keys.Match(key.ToKey()) { + t.Errorf("%s must not accept %s", action, key) + } } }