@ -143,42 +143,106 @@ func TestBucketResourceValidation(t *testing.T) {
bucket string
valid bool
} {
// SeaweedFS ARN format
{
name : "Exact bucket ARN" ,
name : "Exact bucket ARN (SeaweedFS) " ,
resource : "arn:seaweed:s3:::test-bucket" ,
bucket : "test-bucket" ,
valid : true ,
} ,
{
name : "Bucket wildcard ARN" ,
name : "Bucket wildcard ARN (SeaweedFS) " ,
resource : "arn:seaweed:s3:::test-bucket/*" ,
bucket : "test-bucket" ,
valid : true ,
} ,
{
name : "Specific object ARN" ,
name : "Specific object ARN (SeaweedFS) " ,
resource : "arn:seaweed:s3:::test-bucket/path/to/object.txt" ,
bucket : "test-bucket" ,
valid : true ,
} ,
// AWS ARN format (compatibility)
{
name : "Different bucket ARN" ,
name : "Exact bucket ARN (AWS)" ,
resource : "arn:aws:s3:::test-bucket" ,
bucket : "test-bucket" ,
valid : true ,
} ,
{
name : "Bucket wildcard ARN (AWS)" ,
resource : "arn:aws:s3:::test-bucket/*" ,
bucket : "test-bucket" ,
valid : true ,
} ,
{
name : "Specific object ARN (AWS)" ,
resource : "arn:aws:s3:::test-bucket/path/to/object.txt" ,
bucket : "test-bucket" ,
valid : true ,
} ,
// Simplified format (without ARN prefix)
{
name : "Simplified bucket name" ,
resource : "test-bucket" ,
bucket : "test-bucket" ,
valid : true ,
} ,
{
name : "Simplified bucket wildcard" ,
resource : "test-bucket/*" ,
bucket : "test-bucket" ,
valid : true ,
} ,
{
name : "Simplified specific object" ,
resource : "test-bucket/path/to/object.txt" ,
bucket : "test-bucket" ,
valid : true ,
} ,
// Invalid cases
{
name : "Different bucket ARN (SeaweedFS)" ,
resource : "arn:seaweed:s3:::other-bucket/*" ,
bucket : "test-bucket" ,
valid : false ,
} ,
{
name : "Global S3 wildcard" ,
name : "Different bucket ARN (AWS)" ,
resource : "arn:aws:s3:::other-bucket/*" ,
bucket : "test-bucket" ,
valid : false ,
} ,
{
name : "Different bucket simplified" ,
resource : "other-bucket/*" ,
bucket : "test-bucket" ,
valid : false ,
} ,
{
name : "Global S3 wildcard (SeaweedFS)" ,
resource : "arn:seaweed:s3:::*" ,
bucket : "test-bucket" ,
valid : false ,
} ,
{
name : "Global S3 wildcard (AWS)" ,
resource : "arn:aws:s3:::*" ,
bucket : "test-bucket" ,
valid : false ,
} ,
{
name : "Invalid ARN format" ,
resource : "invalid-arn" ,
bucket : "test-bucket" ,
valid : false ,
} ,
{
name : "Bucket name prefix match but different bucket" ,
resource : "test-bucket-different/*" ,
bucket : "test-bucket" ,
valid : false ,
} ,
}
for _ , tt := range tests {
@ -226,3 +290,106 @@ func marshalPolicy(t *testing.T, policyDoc *policy.PolicyDocument) []byte {
require . NoError ( t , err )
return data
}
// TestIssue7252Examples tests the specific examples from GitHub issue #7252
func TestIssue7252Examples ( t * testing . T ) {
s3Server := & S3ApiServer { }
tests := [ ] struct {
name string
policy * policy . PolicyDocument
bucket string
expectedValid bool
description string
} {
{
name : "Issue #7252 - Standard ARN with wildcard" ,
policy : & policy . PolicyDocument {
Version : "2012-10-17" ,
Statement : [ ] policy . Statement {
{
Effect : "Allow" ,
Principal : map [ string ] interface { } {
"AWS" : "*" ,
} ,
Action : [ ] string { "s3:GetObject" } ,
Resource : [ ] string { "arn:aws:s3:::main-bucket/*" } ,
} ,
} ,
} ,
bucket : "main-bucket" ,
expectedValid : true ,
description : "AWS ARN format should be accepted" ,
} ,
{
name : "Issue #7252 - Simplified resource with wildcard" ,
policy : & policy . PolicyDocument {
Version : "2012-10-17" ,
Statement : [ ] policy . Statement {
{
Effect : "Allow" ,
Principal : map [ string ] interface { } {
"AWS" : "*" ,
} ,
Action : [ ] string { "s3:GetObject" } ,
Resource : [ ] string { "main-bucket/*" } ,
} ,
} ,
} ,
bucket : "main-bucket" ,
expectedValid : true ,
description : "Simplified format with wildcard should be accepted" ,
} ,
{
name : "Issue #7252 - Resource as exact bucket name" ,
policy : & policy . PolicyDocument {
Version : "2012-10-17" ,
Statement : [ ] policy . Statement {
{
Effect : "Allow" ,
Principal : map [ string ] interface { } {
"AWS" : "*" ,
} ,
Action : [ ] string { "s3:GetObject" } ,
Resource : [ ] string { "main-bucket" } ,
} ,
} ,
} ,
bucket : "main-bucket" ,
expectedValid : true ,
description : "Exact bucket name should be accepted" ,
} ,
{
name : "Public read policy with AWS ARN" ,
policy : & policy . PolicyDocument {
Version : "2012-10-17" ,
Statement : [ ] policy . Statement {
{
Sid : "PublicReadGetObject" ,
Effect : "Allow" ,
Principal : map [ string ] interface { } {
"AWS" : "*" ,
} ,
Action : [ ] string { "s3:GetObject" } ,
Resource : [ ] string { "arn:aws:s3:::my-public-bucket/*" } ,
} ,
} ,
} ,
bucket : "my-public-bucket" ,
expectedValid : true ,
description : "Standard public read policy with AWS ARN should work" ,
} ,
}
for _ , tt := range tests {
t . Run ( tt . name , func ( t * testing . T ) {
err := s3Server . validateBucketPolicy ( tt . policy , tt . bucket )
if tt . expectedValid {
assert . NoError ( t , err , "Policy should be valid: %s" , tt . description )
} else {
assert . Error ( t , err , "Policy should be invalid: %s" , tt . description )
}
} )
}
}