Browse Source

Refactor tests to use VerifyActionPermission directly

Introduced IAMIntegration interface to facilitate mocking of internal IAM integration logic.
Updated IdentityAccessManagement to use the interface.
Updated tests to directy call VerifyActionPermission using a mocked IAM integration, eliminating duplicated logic in tests.
pull/7988/head
Chris Lu 4 days ago
parent
commit
0acd5205ce
  1. 2
      weed/s3api/auth_credentials.go
  2. 8
      weed/s3api/auth_signature_v4.go
  3. 23
      weed/s3api/auth_signature_v4_sts_test.go
  4. 17
      weed/s3api/s3_iam_middleware.go

2
weed/s3api/auth_credentials.go

@ -55,7 +55,7 @@ type IdentityAccessManagement struct {
grpcDialOption grpc.DialOption
// IAM Integration for advanced features
iamIntegration *S3IAMIntegration
iamIntegration IAMIntegration
// Bucket policy engine for evaluating bucket policies
policyEngine *BucketPolicyEngine

8
weed/s3api/auth_signature_v4.go

@ -303,15 +303,15 @@ func (iam *IdentityAccessManagement) verifyV4Signature(r *http.Request, shouldCh
// validateSTSSessionToken validates an STS session token and extracts temporary credentials
func (iam *IdentityAccessManagement) validateSTSSessionToken(r *http.Request, sessionToken string, accessKey string) (*Identity, *Credential, s3err.ErrorCode) {
// Check if IAM integration with STS is available
if iam.iamIntegration == nil || iam.iamIntegration.stsService == nil {
glog.V(2).Infof("STS service not available, cannot validate session token")
// Check if IAM integration is available
if iam.iamIntegration == nil {
glog.V(2).Infof("IAM integration not available, cannot validate session token")
return nil, nil, s3err.ErrInvalidAccessKeyID
}
// Validate the session token with the STS service
ctx := r.Context()
sessionInfo, err := iam.iamIntegration.stsService.ValidateSessionToken(ctx, sessionToken)
sessionInfo, err := iam.iamIntegration.ValidateSessionToken(ctx, sessionToken)
if err != nil {
glog.V(2).Infof("Failed to validate STS session token: %v", err)
return nil, nil, s3err.ErrInvalidAccessKeyID

23
weed/s3api/auth_signature_v4_sts_test.go

@ -8,6 +8,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/seaweedfs/seaweedfs/weed/iam/sts"
"github.com/seaweedfs/seaweedfs/weed/s3api/s3_constants"
"github.com/seaweedfs/seaweedfs/weed/s3api/s3err"
)
@ -28,6 +29,10 @@ func (m *MockIAMIntegration) AuthenticateJWT(ctx context.Context, r *http.Reques
return nil, s3err.ErrNotImplemented
}
func (m *MockIAMIntegration) ValidateSessionToken(ctx context.Context, token string) (*sts.SessionInfo, error) {
return nil, nil // Not needed for these tests
}
// TestVerifyV4SignatureWithSTSIdentity tests that verifyV4Signature properly handles STS identities
// by falling back to IAM authorization when shouldCheckPermissions is true
func TestVerifyV4SignatureWithSTSIdentity(t *testing.T) {
@ -224,20 +229,14 @@ func TestVerifyV4SignatureSTSStreamingUpload(t *testing.T) {
action := s3_constants.ACTION_WRITE
var errCode s3err.ErrorCode
if len(stsIdentity.Actions) > 0 {
if !stsIdentity.canDo(Action(action), bucket, object) {
errCode = s3err.ErrAccessDenied
}
} else if iamMock != nil {
// Use the mock IAM integration
errCode = iamMock.AuthorizeAction(req.Context(), &IAMIdentity{
Name: stsIdentity.Name,
Account: stsIdentity.Account,
}, Action(action), bucket, object, req)
} else {
errCode = s3err.ErrAccessDenied
// Create minimal IAM instance logic
iam := &IdentityAccessManagement{
iamIntegration: iamMock,
}
errCode = iam.VerifyActionPermission(req, stsIdentity, Action(action), bucket, object)
// Verify that the STS identity is authorized via IAM
assert.Equal(t, s3err.ErrNone, errCode, "STS identity should be authorized via IAM for streaming upload")
assert.True(t, iamAuthCalled, "IAM authorization should have been called for STS identity")

17
weed/s3api/s3_iam_middleware.go

@ -18,6 +18,13 @@ import (
"github.com/seaweedfs/seaweedfs/weed/s3api/s3err"
)
// IAMIntegration defines the interface for IAM integration
type IAMIntegration interface {
AuthenticateJWT(ctx context.Context, r *http.Request) (*IAMIdentity, s3err.ErrorCode)
AuthorizeAction(ctx context.Context, identity *IAMIdentity, action Action, bucket string, objectKey string, r *http.Request) s3err.ErrorCode
ValidateSessionToken(ctx context.Context, token string) (*sts.SessionInfo, error)
}
// S3IAMIntegration provides IAM integration for S3 API
type S3IAMIntegration struct {
iamManager *integration.IAMManager
@ -167,6 +174,14 @@ func (s3iam *S3IAMIntegration) AuthenticateJWT(ctx context.Context, r *http.Requ
return identity, s3err.ErrNone
}
// ValidateSessionToken checks the validity of an STS session token
func (s3iam *S3IAMIntegration) ValidateSessionToken(ctx context.Context, token string) (*sts.SessionInfo, error) {
if s3iam.stsService == nil {
return nil, fmt.Errorf("STS service not available")
}
return s3iam.stsService.ValidateSessionToken(ctx, token)
}
// AuthorizeAction authorizes actions using our policy engine
func (s3iam *S3IAMIntegration) AuthorizeAction(ctx context.Context, identity *IAMIdentity, action Action, bucket string, objectKey string, r *http.Request) s3err.ErrorCode {
if !s3iam.enabled {
@ -463,7 +478,7 @@ func (s3a *S3ApiServer) SetIAMIntegration(iamManager *integration.IAMManager) {
// EnhancedS3ApiServer extends S3ApiServer with IAM integration
type EnhancedS3ApiServer struct {
*S3ApiServer
iamIntegration *S3IAMIntegration
iamIntegration IAMIntegration
}
// NewEnhancedS3ApiServer creates an S3 API server with IAM integration

Loading…
Cancel
Save