s3: allow single Statement object in policy document (#8212)

* s3: allow single Statement object in policy document

Fixes #8201

* s3: add unit test for single Statement object in policy

* s3: improve error message for malformed PolicyDocument.Statement

* s3: simplify error message for malformed PolicyDocument.Statement
This commit is contained in:
Chris Lu
2026-02-04 16:23:20 -08:00
committed by GitHub
parent c9c46db77e
commit 7831257ed5
2 changed files with 43 additions and 0 deletions

View File

@@ -286,6 +286,18 @@ func TestPolicyValidation(t *testing.T) {
}`,
expectError: false,
},
{
name: "Valid policy with single statement object",
policyJSON: `{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::test-bucket/*"
}
}`,
expectError: false,
},
{
name: "Invalid version",
policyJSON: `{

View File

@@ -88,6 +88,37 @@ type PolicyDocument struct {
Statement []PolicyStatement `json:"Statement"`
}
// UnmarshalJSON implements json.Unmarshaler for PolicyDocument
func (p *PolicyDocument) UnmarshalJSON(data []byte) error {
type Alias PolicyDocument
aux := &struct {
Statement json.RawMessage `json:"Statement"`
*Alias
}{
Alias: (*Alias)(p),
}
if err := json.Unmarshal(data, &aux); err != nil {
return err
}
// Try unmarshaling as []PolicyStatement first
var statements []PolicyStatement
if err := json.Unmarshal(aux.Statement, &statements); err == nil {
p.Statement = statements
return nil
}
// Try unmarshaling as single PolicyStatement
var statement PolicyStatement
if err := json.Unmarshal(aux.Statement, &statement); err == nil {
p.Statement = []PolicyStatement{statement}
return nil
}
return fmt.Errorf("Statement must be an array or a single object")
}
// PolicyStatement represents a single policy statement
type PolicyStatement struct {
Sid string `json:"Sid,omitempty"`