S3 Bucket Policy: match at least 1 (OR)

Viewed 54

I currently have a S3 bucket policy that ONLY allows GET access if the user agent matches "ALLOW_USER_AGENT"

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "allow-username-and-password-access",
            "Effect": "Deny",
            "Principal": {
                "AWS": "*"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::MY_BUCKET/*",
            "Condition": {
                "ForAllValues:StringNotEquals": {
                    "aws:UserAgent": [
                        "ALLOW_USER_AGENT"
                    ]
                }
            }
        }
}

I want to modify this policy so that it allows GET access if the user agent matches "ALLOW_USER_AGENT" OR if the origin IP is 11.11.11.11

Here is my first crack at this policy. Is this the right policy? I want to allow GET access if 1 of these 2 statements are true (not both)

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "allow-username-and-password-access",
            "Effect": "Deny",
            "Principal": {
                "AWS": "*"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::MY_BUCKET/*",
            "Condition": {
                "ForAllValues:StringNotEquals": {
                    "aws:UserAgent": [
                        "ALLOW_USER_AGENT"
                    ]
                }
            }
        },
        {
          "Sid": "SourceIP",
          "Action": "s3:GetObject",
          "Effect": "Deny",
          "Resource": "arn:aws:s3:::MY_BUCKET/*",

          "Condition": {
            "NotIpAddress": {
              "aws:SourceIp": [
                "11.11.11.11/32",
              ]
            },    
            "Principal": {
                "AWS": "*"
            }
        }
    ]
}
1 Answers

According to your requeriments the Allow/Deny rules should be:

  • C1 (condition 1): aws:UserAgent = ALLOW_USER_AGENT
  • C2 (condition 2): aws:SourceIp = 11.11.11.11/32

enter image description here

The corresponding bucket policy would be:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "deny-if-both-conditions-are-true",
            "Effect": "Deny",
            "Principal": {
                "AWS": "*"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::MY_BUCKET/*",
            "Condition": {
                "ForAnyValue:StringEquals": {
                    "aws:UserAgent": "ALLOW_USER_AGENT"
                },
                "IpAddress": {
                    "aws:SourceIp": "11.11.11.11/32"
                }
            }
        },
        {
            "Sid": "deny-if-neither-conditions-are-met",
            "Effect": "Deny",
            "Principal": {
                "AWS": "*"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::MY_BUCKET/*",
            "Condition": {
                "NotIpAddress": {
                    "aws:SourceIp": "11.11.11.11/32"
                },
                "ForAnyValue:StringNotEquals": {
                    "aws:UserAgent": "ALLOW_USER_AGENT"
                }
            }
        }
    ]
}

I have tested this policy and works as expected. Additionally, I have updated the operator "ForAllValues" by "ForAnyValue". Use the curl command with "-A" option to set any User Agent.


Reference:

Creating a condition with multiple keys or values

Related