Skip to content

Commit

Permalink
🐛 fix aws s3 bucket public() (#5218)
Browse files Browse the repository at this point in the history
We now check Public Access Block settings first, then Bucket
PolicyStatus which is the native way that AWS computes if a bucket is
public or not, but if that doesn't work, we still parse the bucket
policy to see if it public.

Closes mondoo-community/workspace-jd#8

Signed-off-by: Salim Afiune Maya <afiune@mondoo.com>
  • Loading branch information
afiune authored Feb 15, 2025
1 parent 6e6ac1c commit 0162b01
Showing 1 changed file with 73 additions and 0 deletions.
73 changes: 73 additions & 0 deletions providers/aws/resources/aws_s3.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"context"
"encoding/json"
"fmt"
"slices"
"strings"

"github.com/aws/aws-sdk-go-v2/aws"
Expand Down Expand Up @@ -397,6 +398,78 @@ const (
)

func (a *mqlAwsS3Bucket) public() (bool, error) {
var (
bucketname = a.Name.Data
location = a.Location.Data
conn = a.MqlRuntime.Connection.(*connection.AwsConnection)
svc = conn.S3(location)
ctx = context.Background()
)

// Check Public Access Block settings first
publicAccess, err := svc.GetPublicAccessBlock(ctx, &s3.GetPublicAccessBlockInput{
Bucket: &bucketname,
})
if err != nil && !isNotFoundForS3(err) {
return false, err
}

notPublic := false
if publicAccess != nil && publicAccess.PublicAccessBlockConfiguration != nil {
accessBlock := publicAccess.PublicAccessBlockConfiguration
if accessBlock.BlockPublicAcls != nil && *accessBlock.BlockPublicAcls {
notPublic = true
}
if accessBlock.BlockPublicPolicy != nil && *accessBlock.BlockPublicPolicy {
notPublic = true
}
if accessBlock.IgnorePublicAcls != nil && *accessBlock.IgnorePublicAcls {
notPublic = true
}
if accessBlock.RestrictPublicBuckets != nil && *accessBlock.RestrictPublicBuckets {
notPublic = true
}
}
if notPublic {
return false, nil // Public access is restricted
}

// Then, use GetBucketPolicyStatus to determine public access
statusOutput, err := svc.GetBucketPolicyStatus(ctx, &s3.GetBucketPolicyStatusInput{
Bucket: &bucketname,
})
if err != nil {
return false, err
}
if statusOutput != nil &&
statusOutput.PolicyStatus != nil &&
statusOutput.PolicyStatus.IsPublic != nil {
return *statusOutput.PolicyStatus.IsPublic, nil
}

// If that didn't work, fetch the bucket policy manually and parse it
bucketPolicyResource, err := a.policy()
if err != nil {
return false, err
}

bucketPolicy, err := bucketPolicyResource.parsePolicyDocument()
if err != nil {
return false, err
}

for _, statement := range bucketPolicy.Statements {
if statement.Effect != "Allow" {
continue
}
if awsPrincipal, ok := statement.Principal["AWS"]; ok {
if slices.Contains(awsPrincipal, "*") {
return true, nil
}
}
}

// Finally check for bucket ACLs
acl, err := a.gatherAcl()
if err != nil {
return false, err
Expand Down

0 comments on commit 0162b01

Please sign in to comment.