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.
  • PAR accesses to a bucket are logged in Audit logs. PAR accesses to an object are logged in Service 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 recommend the following:
    • Use object versioning to automatically create an object version each time a new object is uploaded, an existing object is overwritten, or when an object is deleted.
    • Give BUCKET_DELETE and OBJECT_DELETE permissions to a minimum set of IAM users and groups. Grant delete permissions only to tenancy and compartment administrators.
  • Write once read many (WORM) compliance requires that objects cannot be deleted or modified. Use retention rules to achieve WORM compliance. Retention rules are configured at the bucket level and are applied to all individual objects in the bucket. You cannot update, overwrite, or delete objects or object metadata until the retention rule is deleted (indefinite rule) or for the duration specified (time-bound rules).

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 APIfor 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, an MD5 checksum is provided for all objects uploaded to Object Storage. We recommend that you verify that the offline MD5 checksum of an object matches the checksum value returned by the Console or API after upload. Oracle Cloud Infrastructure provides the object checksum value in base64 encoding. To covert the base64 encoded checksum 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 checksum 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 checksum values are computed for each part, and an MD5 checksum computed over all the individual checksum values to get the output MD5 value. To verify the MD5 value returned for a multipart upload, follow the same process for offline MD5 checksum calculation. A sample script for the offline calculation of an MD5 checksum value for a multipart upload to Object Storage is available here: 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.

Restrict Resource Access to a Particular User

You can restrict access to Object Storage resources to a specific user by adding a condition to the policy that specifies the user's OCID in a variable.

The following policy restricts access to the resources in ObjectStorage compartment to the user OCID specified:

Allow any-user to read object-family in compartment ObjectStorage where request.user.id ='ocid1.user.oc1..<user_OCID>'

Restrict Access to Requests That Originate From an Allowed IP Address

You can restrict access only to requests that originate from an allowed IP address. First, you create a network source  to specify the allowed IP addresses, then you add a condition to your policy to restrict access to the IP addresses in the network source.

The following policy restricts access to only IP addresses in a network source corpnet that defines the allowed IP addresses:

Allow group CorporateUsers to manage object-family in tenancy where request.networkSource.name='corpnet'

For information on creating network sources and using them in a policy, see Managing Network Sources.

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

Use retention rules to achieve WORM compliance. Retention rules are configured at the bucket level and are applied to all individual objects in the bucket. You cannot update, overwrite, or delete objects or object metadata until the retention rule is deleted (indefinite rule) or for the duration specified (time-bound rules).

The following policies let BucketUsers manage the buckets and objects in the tenancy and allow BucketUsers to create, manage, and delete retention rules. These policies also let BucketUsers lock retentions rules for a specified time.

Allow group BucketUsers to manage buckets in tenancy
Allow group BucketUsers to manage objects in tenancy

The following more restrictive policies let BucketUsers perform all actions on buckets and objects except locking retention rules.

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

Prevent Public Buckets Configuration

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>