Repository navigation
Description
Summary & Root Cause
The 512-byte limit is enforced on the raw member string. OpenFGA's TupleKey.User limit (also 512) applies to the encoded string that formatUser produces. Each :, %, #, space or * in the ID grows by 2 bytes when encoded. A member like "user:" + "a:"*180 is 365 bytes raw (passes) and encodes to 5 + 180*4 = 725 bytes. OpenFGA rejects it inside the policy write transaction with InvalidArgument. That status is not an apierror, so mapAccessPolicyWrite wraps it as a plain error and the client sees codes.Internal with OpenFGA's validation text.
Affected Code Locations
cmd/ateapi/internal/apivalidation/zz_generated.validation.go:1697-1702:Validate_Bindingappliesvalidate.MaxLength(..., 512)to each rawmembersstring.cmd/ateapi/internal/apivalidation/access_policy.go:144-148:validateBindingscallsauthz.FormatMember(member)but only checks the error. It never checks the length of the encoded result.cmd/ateapi/internal/authz/authz_util.go:101-107:tupleReplacerexpands%→%25,:→%3A,#→%23, space→%20,*→%2A(1 byte to 3 bytes each).cmd/ateapi/internal/authz/authz_util.go:157-159:formatUserreturns"user:" + tupleReplacer.Replace(id).cmd/ateapi/internal/authz/authz_util.go:164-176:FormatMembervalidates prefix, empty, wildcard and control characters. It has no length check.cmd/ateapi/internal/authz/policy_manager.go:176: wraps the OpenFGA error asreconciling policy tuples on %q: %w.cmd/ateapi/internal/controlapi/access_policy.go:171-188:mapAccessPolicyWritefalls through tofmt.Errorf("while writing AccessPolicy: %w", err). A plain error reaches the caller ascodes.Internal.
Note: Earlier write-ups cited the generated validator as
api/ateapi/v1/zz_generated.validation.go. At15b58199that path does not exist. The file iscmd/ateapi/internal/apivalidation/zz_generated.validation.go, and lines 1697-1702 there are theMaxLength(512)check.
Detailed Reproduction Guide
- As an atespace owner, fetch the current policy and add one viewer member whose raw length is 512 bytes or less but which contains many
:characters:
kubectl ate --token-file alice.token get access-policy -a ate-demo-counter -o json > pol-current.json
LONG_COLONS="user:$(printf 'a:%.0s' $(seq 1 180))" # 365 bytes raw, 725 bytes encoded
jq --arg m "$LONG_COLONS" '(.bindings[] | select(.role == "viewer")).members += [$m]' pol-current.json > pol-512-overflow.json
kubectl ate --token-file alice.token update access-policy -a ate-demo-counter -f pol-512-overflow.jsonExpected vs. Actual Behavior
- Expected:
400 InvalidArgumentonaccess_policy.bindings[i].members[j], saying the encoded member exceeds 512 bytes. No OpenFGA call is made. - Actual: the request passes validation and fails in
fgaServer.Writewith500 codes.Internal, which leaks the OpenFGA validation chain.
Observed Output & Logs
$ kubectl ate --token-file alice.token update access-policy -a ate-demo-counter -f pol-512-overflow.json
Error: failed to update atespace "ate-demo-counter" access policy: rpc error: code = Internal desc = internal server error: while writing AccessPolicy: reconciling access policy bindings for ate-demo-counter: reconciling policy tuples on "atespace:ate-demo-counter": rpc error: code = InvalidArgument desc = invalid WriteRequest.Writes: embedded message failed validation | caused by: invalid WriteRequestWrites.TupleKeys[0]: embedded message failed validation | caused by: invalid TupleKey.User: value length must be at most 512 bytes
RC=1ate-demo-counter policy uid=11a20139-db83-43e7-bba0-f53981455032 version=1
$ kubectl ate --token-file alice.token update access-policy -a ate-demo-counter -f pol-512-overflow.json
Error: failed to update atespace "ate-demo-counter" access policy: rpc error: code = Internal desc = internal server error: while writing AccessPolicy: reconciling access policy bindings for ate-demo-counter: reconciling policy tuples on "atespace:ate-demo-counter": rpc error: code = InvalidArgument desc = invalid WriteRequest.Writes: embedded message failed validation | caused by: invalid WriteRequestWrites.TupleKeys[0]: embedded message failed validation | caused by: invalid TupleKey.User: value length must be at most 512 bytes
RC=1
policy version after failed update: 1 (unchanged => tx rolled back)
Activity
ateapi: reject policy members whose encoded form exceeds OpenFGA's 51…
ateapi: reject policy members whose encoded form exceeds OpenFGA's 51…