mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-11-12 23:09:33 +01:00
* s3api: record the caller on AssumeRole sessions The session name is the caller's choice; the session now carries the caller itself as the user it was issued to, as the web identity, LDAP and credential paths already do. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * s3api: take a role session's aws:username from its user, not its name An assumed-role ARN ends in the session name the caller picked, so naming a session after another user resolved ${aws:username} and ${aws:userid} to that user in bucket and attached policies. Resolve them from the user the session was issued to instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * iam: take a role session's aws:username from its user, not its name IsActionAllowed set aws:username to the last segment of an assumed-role ARN, the caller-chosen session name, for role and bucket policies. Use the user the session was issued to, and drop a forwarded value when the session names none. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * s3api: pass a role session caller's user on to the session it assumes A role session that calls AssumeRole is named by its session ID, so the new session recorded that ID as its user. An STS session caller now passes on its own recorded user, or none. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * s3api: size the session claims map from the request context Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
67 lines
2.3 KiB
Go
67 lines
2.3 KiB
Go
package integration
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/seaweedfs/seaweedfs/weed/iam/policy"
|
|
"github.com/seaweedfs/seaweedfs/weed/iam/sts"
|
|
)
|
|
|
|
// ${aws:username} of a role session is the user the session was issued to,
|
|
// not the session name its caller chose or a value forwarded in the request
|
|
// context.
|
|
func TestAssumedRoleUsernameIsTheSessionUser(t *testing.T) {
|
|
ctx := context.Background()
|
|
manager := setupIntegratedIAMSystem(t)
|
|
require.NoError(t, manager.CreatePolicy(ctx, "", "OwnFolderPolicy", &policy.PolicyDocument{
|
|
Version: "2012-10-17",
|
|
Statement: []policy.Statement{{
|
|
Effect: "Allow",
|
|
Action: []string{"s3:GetObject"},
|
|
Resource: []string{"arn:aws:s3:::home/${aws:username}/*"},
|
|
}},
|
|
}))
|
|
require.NoError(t, manager.CreateRole(ctx, "", "SharedRole", &RoleDefinition{
|
|
RoleName: "SharedRole",
|
|
TrustPolicy: &policy.PolicyDocument{
|
|
Version: "2012-10-17",
|
|
Statement: []policy.Statement{{
|
|
Effect: "Allow",
|
|
Principal: map[string]interface{}{"Federated": "test-oidc"},
|
|
Action: []string{"sts:AssumeRoleWithWebIdentity"},
|
|
}},
|
|
},
|
|
AttachedPolicies: []string{"OwnFolderPolicy"},
|
|
}))
|
|
|
|
response, err := manager.AssumeRoleWithWebIdentity(ctx, &sts.AssumeRoleWithWebIdentityRequest{
|
|
RoleArn: "arn:aws:iam::role/SharedRole",
|
|
WebIdentityToken: createTestJWT(t, "https://test-issuer.com", "test-user-123", "test-signing-key"),
|
|
RoleSessionName: "alice",
|
|
})
|
|
require.NoError(t, err)
|
|
session, err := manager.GetSTSService().ValidateSessionToken(ctx, response.Credentials.SessionToken)
|
|
require.NoError(t, err)
|
|
require.NotEmpty(t, session.ExternalUserId)
|
|
require.NotEqual(t, "alice", session.ExternalUserId)
|
|
|
|
allowed := func(resource string) bool {
|
|
t.Helper()
|
|
ok, err := manager.IsActionAllowed(ctx, &ActionRequest{
|
|
Principal: response.AssumedRoleUser.Arn,
|
|
Action: "s3:GetObject",
|
|
Resource: resource,
|
|
SessionToken: response.Credentials.SessionToken,
|
|
RequestContext: map[string]interface{}{"aws:username": "alice"},
|
|
})
|
|
require.NoError(t, err)
|
|
return ok
|
|
}
|
|
assert.False(t, allowed("arn:aws:s3:::home/alice/notes.txt"), "the session name must not select another user's folder")
|
|
assert.True(t, allowed("arn:aws:s3:::home/"+session.ExternalUserId+"/notes.txt"), "the session's user keeps its folder")
|
|
}
|