# Use Bucket Policy

Exoscale's Simple Object Storage (SOS) supports bucket policies, enabling fine-grained access control over your storage resources. This feature aligns with our commitment to offer enhanced security and flexibility for managing access to your data.

## What's New
With the introduction of bucket policies, you can define detailed access permissions directly at the bucket level using JSON-based policy documents. These policies provide control over who can access your buckets and objects, ensuring your data is secure and accessible only to the right users. Unlike the current use of Org Policy and IAM policies with IAM keys they are also enforced for unauthenticated users.

## Bucket Policies
Bucket policies in Exoscale SOS allow you to specify permissions using our existing Exoscale policy format with Common Expression Language [(CEL)]({{< ref "/product/security/iam/how-to/policy-guide#cel-bindings" >}}) expressions. These policies can be managed via the SOS API, compatible with common AWS S3 API tools.

> [!WARNING]
> Please note that in order to allow access to the bucket without authentication, we have to set 
> the bucket/object to 'all users' with read-only.

### Example Policies
_Minimal IP filter policy:_

```json
{
  "default-service-strategy": "deny",
  "services": {
    "sos": {
      "type": "rules",
      "rules": [
        {
          "action": "allow",
          "expression": "source_ip.inIpRange('89.145.160.0/24')"
        },
        {
          "action": "allow",
          "expression": "source_ip.inIpRange('2a04:c46::/32')"
        }
      ]
    }
  }
}
```

The `default-service-strategy` is `deny` which means if no rule matches we deny the operation on the bucket / object in the bucket. Then we specify a rule for the `"sos"` service: if the source IP of the request comes from IPv4 subnet `89.145.160.0/24` or IPv6 subnet `2a04:c46::/32` we allow the operation (tip: if your network interface has an IPv4 and IPv6 address assigned you should specify both).

_IP filter only for unauthenticated requests:_

```json
{
  "default-service-strategy": "deny",
  "services": {
    "sos": {
      "type": "rules",
      "rules": [
        {
          "action": "allow",
          "expression": "identity.key != ''"
        },
        {
          "action": "allow",
          "expression": "source_ip.inIpRange('89.145.160.0/24')"
        },
        {
          "action": "allow",
          "expression": "source_ip.inIpRange('2a04:c46::/32')"
        }
      ]
    }
  }
}
```

_Only accept object creation via conditional if-none-match: '*":_

This policy is useful to eg: prevent accidental overwrites of existing objects.

```json
{
  "default-service-strategy": "deny",
  "services": {
    "sos": {
      "type": "rules",
      "rules": [
        {
          "action": "allow",
          "expression": "!parameters.object_creation"
        },
        {
          "action": "allow",
          "expression": "headers['if-none-match'] == '*'"
        }
      ]
    }
  }
}
```

_Only accept object creation if the client is using SSE-C encryption:_

This can be useful to enforce encryption on sensitive data when using customer-managed keys. Note that for most use cases, [SSE-SOS]({{< ref "/product/storage/object-storage/how-to/encryption#sse-sos" >}}) (enabled by default on all new buckets) is the recommended encryption method.

```json
{
  "default-service-strategy": "deny",
  "services": {
    "sos": {
      "type": "rules",
      "rules": [
        {
          "action": "allow",
          "expression": "!parameters.object_creation"
        },
        {
          "action": "allow",
          "expression": "headers['sse-c-customer-algorithm'] == 'AES256'"
        }
      ]
    }
  }
}
```


For more details on writing policies, refer to the [Exoscale IAM documentation]({{< ref "/product/security/iam/overview/" >}}).


## Testing a bucket policy
Before applying the bucket policy to a bucket you can test it on a specific IAM key. To do this you can create a role with the bucket policy you want to test:

![](iam-role.png "Portal create new Role with bucket policy")

In the next step you create an IAM api key that uses that role.

![](iam-key1.png "Portal new IAM key")

![](iam-key2.png "Portal new IAM key2")

Now you can test the bucket policy with the newly created key.
On requests with a different key the bucket policy doesn't have
an influence.

> [!NOTE]
> When you use the example policy it will apply to all buckets since it does not filter for the bucket name. 

In the next section we will install the policy on a bucket which will have an effect on all requests with or without an IAM api key!


## Policy Management
You can use the following S3 API-compatible commands to manage your bucket policies:

First let's create an alias so we don't have to repeat the same options to use aws cli (I assume we use a bucket in our Zurich zone `ch-dk-2`):

```bash
alias awsexo='aws --profile=exo  --endpoint=https://sos-ch-dk-2.exo.io --region=ch-dk-2'
```

### Get Bucket Policy
```bash
awsexo s3api get-bucket-policy --bucket my-bucket
```

If no bucket policy is configured for the bucket an `NoSuchBucketPolicy` error is returned.

### Put Bucket Policy
```bash
awsexo s3api put-bucket-policy --bucket my-bucket --policy file://policy.json
```

### Delete Bucket Policy
```bash
awsexo s3api delete-bucket-policy --bucket my-bucket
```

> [!NOTE]
> It's possible that you specify a policy that makes it impossible for you to access the bucket or delete 
> the bucket policy (e.g. wrong IP in the filter). In this case contact our support via the portal to unlock your bucket.

