Oracle Cloud Infrastructure Documentation

Securing Object Storage

Security Recommendations

Assign least privileged access for IAM users and groups to resource types in object-family (buckets and objects). For example, the inspect verb gives the least privilege. Inspect lets you check to see if a bucket exists (HeadBucket) and list the buckets in a compartment (ListBucket). The manage verb gives all permissions on the resource. You can create IAM security policies to give appropriate bucket and object access to various IAM groups. For more information about IAM verbs and permissions for Object Storage buckets and objects, see Details for Object Storage, Archive Storage, and Data Transfer. For users without IAM credentials, we recommend that you use pre-authenticated requests (PARs) to give time-bound access to objects or buckets.

Public Buckets Security Controls

  • A public bucket allows unauthenticated and anonymous reads to all objects in the bucket. Carefully evaluate the intended use case for public buckets before you enable public buckets. We recommend that you use pre-authenticated requests (PARs) to give bucket or object access(read or write) to users without IAM credentials. By defaults, buckets are created with no public access (access type is set to NoPublicAccess).
  • You can make existing buckets public by updating the bucket access type to ObjectRead or ObjectReadWithoutList. To minimize the possibility of existing buckets being made public inadvertently or maliciously, BUCKET_UPDATE permission should be restricted to a minimal set of IAM groups.

Pre-Authenticated Request (PAR)

  • Pre-authenticated requests (PARs) provide a mechanism to provide access to objects stored in buckets, to users who do not have IAM user credentials. In a PAR, an IAM user who has appropriate privileges for accessing objects, can create URLs which grant time-bound read or write access to these objects. For more information about creating PARs, see Using Pre-Authenticated Requests.
  • The creator of a PAR must have PAR_MANAGE IAM permission. You can create the following PARs:
    • Bucket PAR to allow writes to a bucket
    • Object PAR for reading an object
    • Object PAR for writing an object
    • Object PAR to read or write an object
  • A PAR cannot be used to list objects in a bucket.
  • All PAR accesses to a bucket or object are logged in Audit logs.
  • We recommend that you note down the PAR URL created. By design, it is not possible to retrieve a forgotten PAR URL. If you forget a PAR URL, you must create a new PAR.

Data Durability

  • Minimize data loss because of inadvertent deletes by an authorized user or malicious deletes. We recommended giving BUCKET_DELETE and OBJECT_DELETE permissions to a minimum set of IAM users and groups. Grant DELETE permission only to tenancy and compartment admins.
  • Write once read many (WORM) compliance requires that objects cannot be deleted or modified. WORM is achieved by granting OBJECT_CREATE, OBJECT_READ, and OBJECT_INSPECT permissions to an IAM group. Grant OBJECT_OVERWRITE permission to prevent modification to existing an object.

Data Encryption

  • All data in Object Storage is encrypted at rest by using AES-256. Encryption is on by default and cannot be turned off. Each object is encrypted with its encryption key, and the object encryption keys are encrypted with a master encryption key. In addition, customers can use client-side encryption to encrypt objects with their encryption keys before storing them in Object Storage buckets. An available option for customers is to use the Amazon S3 Compatibility API, along with client-side object encryption support available in AWS SDK for Java. See Amazon S3 Compatibility API for more details about on this SDK.
  • Data in transit between customer clients (for example, SDKs and CLIs) and Object Storage public endpoints is encrypted with TLS 1.2 by default. FastConnect public peering allows on-premises access to Object Storage to go over a private network, rather than the public internet.

Data Integrity

  • To verify object data integrity, a cryptographic hash using MD5 is provided for all objects uploaded to Object Storage. We recommend that you verify that the offline MD5 hash of an object matches the hash value returned by the Console or API after upload. Oracle Cloud Infrastructure provides the object hash value in base64 encoding. To covert the base64 encoded hash value to hexadecimal, use the following command:

    python -c 'print "BASE64-ENCODED-MD5-VALUE".decode("base64").encode("hex")'

    Linux provides an md5sum command line utility to compute MD5 hash value of an object in hexadecimal format.

  • Object Storage service supports multipart uploads for more efficient and resilient uploads, especially for large objects. In a multipart upload, a large object is broken up into smaller parts by specifying a part size in MiB. Each part is uploaded separately. Object Storage then combines all the parts to create the original object. If any of the parts fail to upload, only those parts need to be retried for upload, and not the entire object. In a multipart upload, the MD5 hash values are computed for each part, and an MD5 hash computed over all the individual hash values to get the output MD5 value. To verify the MD5 value returned for a multipart upload, follow the same process for offline MD5 hash calculation. A sample script for offline calculation of MD5 hash value for a multipart upload to Object Storage is available here (link: https://gist.github.com/itemir/f5bc9fded6483cd79c89ebf4ca1cfd30).

Security Policy Examples

In the following examples, the policies are scoped to a tenancy. However, specifying a compartment name reduces the scope to a specific compartment in a tenancy.

Restrict Group Access to Specific Buckets

You can restrict access by a group to a specific bucket by using the specific bucket name (target.bucket.name), regular expression matching (/*name/, /name*/, /*name*/), or defined tags (target.tag.definition.name).

The following is an example of restricting access by groups BucketUsers to a specific bucket.

Allow group BucketUsers to use buckets in tenancy
 where target.bucket.name='BucketFoo'.

You can modify this policy to restrict access by group BucketUsers to all buckets whose names are prefixed with ProjectA_.

Allow group BucketUsers to use buckets in tenancy
 where target.bucket.name=/ProjectA_*/

You can also match for post-fix (/*_ProjectA/) or substring (/*ProjectA*/).

Restrict Group Access to Read or Write to Objects in a Specific Bucket

The following example allows listing and reading objects by group BucketUsers from a specific bucket named BucketFoo.

Allow group BucketUsers to read buckets in tenancy
Allow group BucketUsers to manage objects in tenancy
 where all {target.bucket.name='BucketFoo', 
            any {request.permission='OBJECT_INSPECT', 
                 request.permission='OBJECT_READ'}}

The following policy modifies the previous policy to allow listing and writing objects to BucketFoo.

Allow group BucketUsers to read buckets in tenancy 
Allow group BucketUsers to manage objects in tenancy
 where all {target.bucket.name='BucketFoo', 
            any {request.permission='OBJECT_INSPECT', 
                 request.permission='OBJECT_CREATE'}}

You can restrict this policy to read or write access to a set of buckets by using regular expressions or tags rather than a specific bucket.

Prevent Delete of Buckets or Objects

In the following example, the group BucketUsers can perform all actions on buckets and objects except delete.

Allow group BucketUsers to manage objects in tenancy
 where request.permission!='OBJECT_DELETE' 
Allow group BucketUsers to manage buckets in tenancy
 where request.permission!='BUCKET_DELETE'

The following example further restricts object deletion from the specific bucket (BucketFoo).

Allow group BucketUsers to manage objects in tenancy
  where any {target.bucket.name!='BucketFoo', 
             all {target.bucket.name='BucketFoo',
                  request.permission!='OBJECT_DELETE'}}

Enable WORM Compliance for Objects

The following policy enables WORM compliance by removing permissions for group BucketUsers to delete or update objects.

Allow group BucketUsers to manage objects in tenancy
 where any {request.permission='OBJECT_INSPECT', 
            request.permission='OBJECT_READ', 
            request.permission='OBJECT_CREATE'}

The following policy allows for WORM compliance.

Allow group BucketUsers to manage buckets in tenancy
 where any {request.permission='BUCKET_INSPECT', 
            request.permission='BUCKET_READ', 
            request.permission='BUCKET_CREATE', 
            request.permission='PAR_MANAGE'}

Prevent Public Buckets Configuration

As mentioned in previous section, BUCKET_CREATE and BUCKET_UDPATE permissions are required to create buckets or make existing private buckets public. Removing these permissions prevents users from creating buckets or making existing buckets public.

Allow group BucketUsers to manage buckets in tenancy
 where any {request.permission='BUCKET_INSPECT', 
            request.permission='BUCKET_READ', 
            request.permission='PAR_MANAGE'}

Useful CLI Commands

Here are some useful commands to determine if you have public buckets or PARS in your tenancy.

List of Public Buckets

The following command returns the public-access-type assigned to a bucket.

# "public-access-type" of 'NoPublicAccess' indicates a private bucket, and 
# anything else ('ObjectRead') indicates a public bucket 
oci os bucket get -ns <your_namespace> --bucket-name <bucket_name> | grep "public-access-type"

List of Bucket Pre-Authenticated Requests (PARs)

The following command returns a list of object PARs in a bucket.

# list all PARs for objects in bucket $BUCKET_NAME 
oci os preauth-request list -ns <your_namespace> -bn <bucket_name>