Tutorials#

How to setup a custom domain for a website#

By default, a bucket running in the website mode is accessible at ‘bucket-name’:, where bucket-name is the name of the bucket. Instead of the above domain name, you can use your own custom domain name.

Setting up your third-level domain for a website#

You can use your own domain to host a website, for example, a third-level domain img.example.com in the example.com zone.

First of all, you need to create a bucket named img.example.com, upload the website content into it, and turn on website mode.

To make the website accessible at http://img.example.com, configure the DNS server of the example.com zone.

In the example.com zone settings, create a record of the type CNAME :

BIND#
img.example.com. IN CNAME img.example.com.website.k2.cloud

After making these changes, the website will be accessible at http://img.example.com, as well as (by default) at http://img.example.com.website.k2.cloud.

Setting up your second-level domain for a website#

You can use your own domain to host a website, for example, a second-level example.com domain.

Create a bucket example.com, upload the website content into it, and turn on website mode.

To make the website accessible at http://example.com, configure the DNS server of the example.com zone.

Important

This example uses a second-level domain, which is also the zone apex of the example.com zone. The DNS specification does not allow a CNAME record for such a domain, but some DNS servers and services do. Make sure your DNS server or service supports this. Such records are often called something other than CNAME, for example ALIAS or ANAME.

In the example.com zone settings, create a record of the type ALIAS or ANAME (depending on what your DNS provider uses):

BIND#
example.com. IN ALIAS example.com.website.k2.cloud

Setting up HTTPS for a website#

By default, you can access a bucket with website mode enabled by http://bucket-name.website.k2.cloud address, where bucket-name is the name of this bucket.

You can enable HTTPS support, as well as configure automatic redirect from HTTP to HTTPS.

At the moment, there is no API to automatically enable HTTPS.

Important

To enable HTTPS for a specific website, submit a request via the support portal or send an email to support@k2.cloud. Request examples are shown below.

Configure access to the website over HTTPS#

To make the website http://bucket1.website.k2.cloud accessible over HTTPS, create a bucket bucket1 and enable website mode.

Once these actions are completed, submit a request via the support portal.

Request example
Subject: HTTPS for |website_bucket1_http|

Description:

- Bucket name: *bucket1*
- Website domain: |website_bucket1|
- Enable forced redirect from HTTP to HTTPS: *yes/no*

where:

- *Bucket name* — Your bucket in object storage (S3) that must be available over HTTPS in website mode.
- *Website domain name* — The website name for which a certificate will be issued for HTTPS.
- *Enable forced redirect from HTTP to HTTPS* — If you want users who open the website over HTTP to be redirected automatically to the HTTPS version, specify *yes*.
  If you want to keep the website available over HTTP, specify *no*.

After the request validation, a certificate will be issued for the specified domain name and HTTPS will be enabled. Let’s Encrypt will be used as a Certification Authority.

Setting up access to the website in a custom domain over HTTPS#

To make the website http://img.example.com accessible over HTTPS, create a bucket img.example.com and enable website mode. Then, configure your DNS so that the website is accessible at http://img.example.com.

Once these actions are completed, submit a request via the support portal.

Request example
Subject: HTTPS for img.example.com

Description:

- Bucket name: *img.example.com*
- Website domain: *img.example.com*
- Enable forced redirect from HTTP to HTTPS: *yes/no*
- Use your own certificate: *yes/no*

where:

- *Bucket name* — your bucket in object storage (S3) that must be available over HTTPS in website mode.
- *Website domain name* — the website name for which a certificate will be issued for HTTPS.
- *Enable forced redirect from HTTP to HTTPS* — if you want users who open the website over HTTP to be redirected automatically to the HTTPS version, specify *yes*. If you want to keep the website available over HTTP, specify *no*.
- *Use your own certificate*. If the website uses your own domain, you can provide your own certificate. In that case, specify *yes* and attach the certificate for the specified domain name to the request. This may be needed for testing, or when the certificate must have particular attributes. If you specify *no*, a certificate from the Let's Encrypt certification authority is issued and used for this domain.

Setting up website redirect rules#

A bucket in website mode can be configured to redirect all or some incoming requests to other buckets or external resources.

The documentation contains the list of commands supported in the K2 Cloud S3 API and setup instructions AWS CLI.

To receive the current configuration of the website in a specific bucket, you can use the aws s3api get-bucket-website command.

aws --endpoint-url https://s3.ru-msk.k2.cloud s3api get-bucket-website --bucket bucket1

{
  "IndexDocument": {
      "Suffix": "index.html"
  }
}

To configure the bucket website, use the s3api put-bucket-website command.

There are several redirect options:

Supported redirect rule parameters#

Condition is a container for describing a condition that must be met for the specified redirect to be applied.

Redirect is a container for information redirection. You can redirect requests to a different host, a different page, or via a different protocol. In case of an error, you can specify another error code for the return.

Block

Parameter

Description

Condition

HttpErrorCodeReturnedEquals

The HTTP error code when to apply a redirect. If an error code is equal to this value, then the specified redirect is applied. Required if the Condition container is specified and KeyPrefixEquals is not specified. If both conditions are specified, then both must be met to apply the redirect.

Condition

KeyPrefixEquals

The object key prefix to which the redirect applies. For example, to redirect requests for ExamplePage.html, the key prefix is ExamplePage.html. To redirect requests for all pages with the docs/ prefix, the key prefix is docs/, which identifies all objects in the docs/ folder. Required when Condition is specified and HttpErrorCodeReturnedEquals is not. If both conditions are specified, both must be met for the redirect to apply.

Redirect

HostName

The hostname in a redirect request.

Redirect

HttpRedirectCode

HTTP code in the response to a redirect request.

Redirect

Protocol

The protocol to be used to redirect requests. By default, the protocol of the original request is used.

Redirect

ReplaceKeyPrefixWith

The object key prefix to use in the redirect request. For example, to redirect requests for all pages with the docs/ prefix (objects in the docs/ folder) to documents/, set KeyPrefixEquals to docs/ and, in the Redirect block, set ReplaceKeyPrefixWith to documents/. It can be present only if ReplaceKeyWith is not used.

Redirect

ReplaceKeyWith

The specific object key prefix is to be used in a redirect request, such as a redirect request to error.html. It can only be used if ReplaceKeyPrefixWith is absent.

Redirect all requests to another resource#

If you want to redirect all requests to another resource, prepare a JSON file with the following bucket parameters bucket1.json.

File bucket1.json
{
  "RedirectAllRequestsTo": {
    "HostName": "new-site.com",
    "Protocol": "http"
  }
}

In this example, the bucket bucket1.website.k2.cloud is configured as a website. The configuration specifies that all GET requests to the bucket1.website.k2.cloud website endpoint are redirected to the new-site.com host. This redirect is useful when you have two websites, an old one, old-site.com (bucket1.website.k2.cloud in this example), and a new one, new-site.com, and you want every request to the old website to be redirected to the new one.

aws --endpoint-url https://s3.ru-msk.k2.cloud s3api put-bucket-website --bucket old-site.com --website-configuration file://bucket1.json

Note

If you specify the RedirectAllRequestsTo parameter in the configuration, you cannot specify another parameter.

Configuring multiple redirect rules to another resource#

If you want to flexibly configure redirect rules to one or more objects, add routing rules.

Suppose your bucket2 contains the following objects:

index.html
docs/site1.html
docs/site2.html

If you want to rename the docs/ folder to documents/, you need to redirect requests to the docs/ prefix to documents/. For example, if a request for docs/site1.html should be redirected to documents/ site1.html, you need to update the website configuration and add a routing rule as shown in the following JSON file bucket2.json:

File bucket2.json
{
  "IndexDocument": {
    "Suffix": "index.html"
  }
  "ErrorDocument": {
    "Key": "Error.html"
  }

  "RoutingRules": [
    {
    "Condition": {
      "KeyPrefixEquals": "docs/"
    }
    "Redirect": {
      "ReplaceKeyPrefixWith": "documents/"
    }
  }
  ]
}
aws --endpoint-url https://s3.ru-msk.k2.cloud s3api put-bucket-website --bucket bucket2 --website-configuration file://bucket2.json

Configuring multiple redirect rules to another resource#

If you want to use multiple redirect rules at the same time, provision an appropriate JSON file. For example, to configure different redirect rules for the Russian and English website versions, you need to provision a JSON file bucket3.json:

File bucket3.json
{
  "IndexDocument": {
      "Suffix": "index.html"
  },
  "ErrorDocument": {
      "Key": "error.html"
  },
  "RoutingRules": [
      {
          "Redirect": {
              "ReplaceKeyWith": "ru/data.html",
              "HostName": "new-site.com",
              "Protocol": "https",
              "HttpRedirectCode": "302"
          },
          "Condition": {
              "KeyPrefixEquals": "ru/manual/data.html"
          }
      },
      {
          "Redirect": {
              "ReplaceKeyWith": "en/data.html",
              "HostName": "new-site.com",
              "Protocol": "https",
              "HttpRedirectCode": "302"
          },
          "Condition": {
              "KeyPrefixEquals": "en/manual/data.html"
          }
      }
  ]
}
aws --endpoint-url https://s3.ru-msk.k2.cloud s3api put-bucket-website --bucket old-site --website-configuration file://bucket3.json

How to configure the lifecycle of objects in a bucket#

To make storing objects in a bucket cost-effective, you can customize their lifecycle. If you use a bucket to store log files or regular reports, then at some point, there may be too many files. In this case, you can reduce the storage time and the time you spent manually deleting objects by configuring object auto-deletion from the bucket using bucket lifecycle rules.

Lifecycle rules can be described in a JSON file (see examples below). To apply these rules, run the command:

aws s3api put-bucket-lifecycle-configuration --bucket <your_bucket> --lifecycle-configuration file://lifecycle.json --endpoint-url https://s3.ru-msk.k2.cloud

Deleting objects from a bucket#

An example of a rule in the lifecycle.json file, pursuant to which log files will be automatically deleted from the bucket in 30 days after upload.

An example of a rule to delete objects
{
    "Rules": [
        {
            "ID": "Expire old logs",
            "Filter": {
                    "Prefix": "logs/"
            },
            "Status": "Enabled",
            "Expiration": {
                    "Days": 30
             }
        }
    ]
}

Deleting object versions from a bucket#

An example of a rule in the lifecycle.json file, pursuant to which older object versions and delete markers will be automatically deleted from the bucket in 30 days after creation.

An example of a rule to delete object versions
{
    "Rules": [
        {
            "Expiration": {
                "ExpiredObjectDeleteMarker": true
            },
            "ID": "delete-old-versions",
            "Prefix": "",
            "Status": "Enabled",
            "NoncurrentVersionExpiration": {
                "NoncurrentDays": 30
            }
        }
    ]
}

Deleting parts of a multipart upload#

An example of a rule in the lifecycle.json file, pursuant to which parts of a multipart upload will be automatically deleted from the bucket in 30 days after creation.

An example of a rule to delete parts of a multipart upload
{
    "Rules": [
        {
            "ID": "abort-multipart",
            "Prefix": "",
            "Status": "Enabled",
            "AbortIncompleteMultipartUpload": {
                  "DaysAfterInitiation": 30
            }
        }
    ]
}

Read more about the object storage.

How to setup Object Lock for an object version#

If you want to prevent objects and their versions from being deleted and overwritten, you can use S3 Object Lock methods. This instruction covers the basic steps to configure Object Lock. For more details on Object Lock principles and methods, see Object Lock API Manual. The AWS command-line utility is used to configure Object Lock (see how to install and configure it).

Creating a bucket#

It is possible to lock objects in a bucket only if Object Lock was enabled when the bucket was created. To enable it, select –object-lock-enabled-for-bucket option when you create a bucket.

aws s3api create-bucket --bucket <bucket-name> --object-lock-enabled-for-bucket --endpoint-url=https://s3.ru-msk.k2.cloud

Setting a default policy#

You can set a retention policy for a bucket. By default, it applies to every uploaded object, unless other retention parameters are specified for a particular object. The policy sets the retention period of the object version and the retention mode (COMPLIANCE or GOVERNANCE). You do not have to define a default policy, but without one you must set retention parameters for every object you want to protect when you upload it.

COMPLIANCE mode ensures strict locking, i.e. the object version cannot be deleted or overwritten until the retention period ends. In GOVERNANCE mode, the retention period can be modified by any user with privileges for the object storage. In the example below, the uploaded object is locked for 360 days in COMPLIANCE mode.

aws s3api --endpoint-url=https://s3.ru-msk.k2.cloud put-object-lock-configuration \
 --bucket <bucket-name> \
 --object-lock-configuration "ObjectLockEnabled=Enabled,Rule={DefaultRetention={Mode=COMPLIANCE,Days=360}}"

The default policy can be retrieved using the get-object-lock-configuration command:

aws s3api --endpoint-url=https://s3.ru-msk.k2.cloud get-object-lock-configuration \
  --bucket <bucket-name>

{
    "ObjectLockConfiguration": {
        "ObjectLockEnabled": "Enabled",
        "Rule": {
            "DefaultRetention": {
                "Mode": "GOVERNANCE",
                "Days": 360
            }
        }
    }
}

Uploading an object#

The locking parameters specified during upload override the default Object Lock policy for a bucket. You can use this method to lock objects immediately after the bucket is created and skip setting a default policy.

In this example, GOVERNANCE mode is set for the object to be uploaded, with a retention period until October 20, 2024.

aws s3api --endpoint-url=https://s3.ru-msk.k2.cloud put-object \
  --bucket <bucket-name> \
  --key <object-name> \
  --body <path-to-file> \
  --object-lock-mode GOVERNANCE \
  --object-lock-retain-until-date "2024-11-20"

{
    "ETag": "\"dff23456a91215d7153f85a7c127aaa9\"",
    "VersionId": "<version-id>"
}

Modifying the lock parameters#

If COMPLIANCE mode is set for the object version, you can only increase the retention period. If GOVERNANCE mode is set, you can both increase and reduce the retention period, as well as change the retention mode. To reduce the retention period and change the locking mode, you should use the option –bypass-governance-retention.

Example of increasing the retention period.

aws s3api --endpoint-url=https://s3.ru-msk.k2.cloud put-object-retention \
  --bucket <bucket-name> \
  --key <object-name> \
  --version-id <version-id> \
  --retention '{ "Mode": "GOVERNANCE", "RetainUntilDate": "2024-12-01T00:00:00" }'

Example of reducing the retention period.

aws s3api --endpoint-url=https://s3.ru-msk.k2.cloud put-object-retention \
  --bucket <bucket-name> \
  --key <object-name> \
  --version-id <version-id> \
  --bypass-governance-retention \
  --retention '{ "Mode": "GOVERNANCE", "RetainUntilDate": "2024-10-01T00:00:00" }'

The current locking parameters for the object version can be found by the command get-object-retention.

aws s3api --endpoint-url=https://s3.ru-msk.k2.cloud get-object-retention \
  --bucket <bucket-name> \
  --key <object-name> \
  --version-id <version-id>

{
    "Retention": {
        "Mode": "GOVERNANCE",
        "RetainUntilDate": "2024-10-01T00:00:00.000000000Z"
    }
}

Enabling Legal Hold#

You can also enable Legal Hold for an object version. This method can be applied independently of locking for a predefined period of time. When enabled, it will protect the object version from deletion even when its retention period expires.

Example of how to enable Legal Hold when uploading an object.

aws s3api --endpoint-url=https://s3.ru-msk.k2.cloud put-object \
  --bucket <bucket-name> \
  --key <object-name> \
  --body <path-to-file> \
  --object-lock-legal-hold-status ON

{
    "ETag": "\"dff23456a91215d7153f85a7c127aaa9\"",
    "VersionId": "1TrVY0XDY44WvOmMqxw04HbSIemIHtG"
}

Example of how to enable Legal Hold for an object version.

aws s3api --endpoint-url=https://s3.ru-msk.k2.cloud put-object-legal-hold \
  --bucket <bucket-name> \
  --key <object-name> \
  --legal-hold Status=ON \
  --version-id <version-id>

Example of how to disable Legal Hold for an object version.

Note

Legal Hold can be disabled by any project user with full privileges to the object storage.

aws s3api --endpoint-url=https://s3.ru-msk.k2.cloud put-object-legal-hold \
  --bucket <bucket-name> \
  --key <object-name> \
  --version-id <version-id> \
  --legal-hold Status=OFF

The current lock status for an object version can be found with the command get-object-legal-hold.

aws s3api --endpoint-url=https://s3.ru-msk.k2.cloud get-object-legal-hold \
  --bucket <bucket-name> \
  --key <object-name> \
  --version-id <version-id>

{
    "LegalHold": {
        "Status": "ON"
    }
}

Deleting an object#

When an object is deleted from a bucket with versioning enabled, the latest version of the object is not deleted — only a delete marker is created. However, if the non-locked version of the object can then be deleted, the locked version of the object is protected from deletion.

In COMPLIANCE mode, the locked object version cannot be deleted until the retention period expires. In GOVERNANCE mode, the version can be deleted using bypass (the option x-amz-bypass-governance-retention).

Example of deleting an object with the creation of a deletion marker.

aws s3api --endpoint-url=https://s3.ru-msk.k2.cloud delete-object \
  --bucket <bucket-name> \
  --key <object-name>

  {
      "DeleteMarker": true,
      "VersionId": "<delete-marker-id>"
  }

Example of how to delete an object version in GOVERNANCE mode by bypassing the lock.

aws s3api --endpoint-url=https://s3.ru-msk.k2.cloud delete-object \
  --bucket <bucket-name> \
  --key <object-name> \
  --version-id <version-id> \
  --bypass-governance-retention

{
    "VersionId": "<version-id>"
}

Managing a multipart upload#

A multipart upload accelerates the upload of large files by uploading several parts simultaneously.

Note

For uploading large files, we recommend using the s3cmd utility. It automatically splits files larger than 15 MB into parts.

Multipart upload#

Multipart upload is recommended for files larger than 100 MB. The file must first be split into several parts, for example, using the split command or 7-Zip in Windows. Each file part (except for the last one) must be at least 5 MB in size.

  1. Initiate multipart upload.

    $ aws s3api create-multipart-upload --bucket <bucket> --key <large_file> --endpoint-url=https://s3.ru-msk.k2.cloud
    
    {
    
        "Bucket": "bucket",
    
        "Key": "large_file",
    
        "UploadId": "2~Lp183FiHlNDzKDO5LIwd4X2AmhbuyLf"
    
    }
    

    The output contains the multipart upload ID, which should be used in subsequent commands to identify the upload.

  2. Upload every part.

    Note

    For each subsequent part being uploaded, increase its number.

    $ aws s3api upload-part --bucket <bucket> --key <large_file> --part-number 1 --upload-id 2~Lp183FiHlNDzKDO5LIwd4X2AmhbuyLf --body <part_1> --endpoint-url=https://s3.ru-msk.k2.cloud
    
    {
    
         "ETag": "\"3977495e279a33abe9c8795beaa52c45\""
    
    }
    
    $ aws s3api upload-part --bucket <bucket> --key <large_file> --part-number 2 --upload-id 2~Lp183FiHlNDzKDO5LIwd4X2AmhbuyLf --body <part_2> --endpoint-url=https://s3.ru-msk.k2.cloud
    
    {
    
         "ETag": "\"f1c7c253aec96cb9af8910c55dd13cb0\""
    
    }
    

    For each part, the output of the upload command contains ETag, which must be saved for further use. This tag is required to assemble the file from the parts.

  3. Create a JSON file describing parts of the multipart upload, from which the object in the bucket must be assembled:

    $ cat parts.json
    
    {
    
        "Parts": [{
    
            "ETag": "3977495e279a33abe9c8795beaa52c45",
    
            "PartNumber":1
    
        },
    
        {
    
            "ETag": "f1c7c253aec96cb9af8910c55dd13cb0",
    
            "PartNumber":2
    
        }]
    
    }
    
  4. Complete the multipart upload.

    $ aws s3api complete-multipart-upload --multipart-upload file://parts.json --bucket <bucket> --key <large_file> --upload-id 2~Lp183FiHlNDzKDO5LIwd4X2AmhbuyLf --endpoint-url=https://s3.ru-msk.k2.cloud
    
    {
    
        "Location": "s3.ru-msk.k2.cloud/bucket/large_file",
    
        "Bucket": "bucket",
    
        "Key": "large_file",
    
        "ETag": "7ab490b300478451de681d1859d8a6a2-2"
    
    }
    

Aborting a multipart upload#

An incomplete multipart upload can be aborted.

  1. Check the bucket for multipart uploads in progress:

    $ aws s3api list-multipart-uploads --bucket <bucket> --endpoint-url=https://s3.ru-msk.k2.cloud
    
    {
    
        "Uploads": [
    
            {
    
                "UploadId": "2~mdty_HtKZOHy6rIHFq9Vv7dUWK7EIBC",
    
                "Key": "large_file",
    
                "Initiated": "2024-08-27T10:00:28.060Z",
    
                "StorageClass": "STANDARD",
    
                "Owner": {
    
                    "DisplayName": "User@company",
    
                    "ID": "S3_user_id"
    
                },
    
                "Initiator": {
    
                    "ID": "S3_user_id",
    
                    "DisplayName": "User@company"
    
                }
    
            }
    
        ]
    
    }
    
  2. Abort the incomplete multipart upload. The parts of the object that have already been uploaded are then deleted from the bucket. You may need to run the command again if some parts were still being uploaded while it ran.

    $ aws s3api abort-multipart-upload --bucket <bucket> --key <large_file> --upload-id 2~mdty_HtKZOHy6rIHFq9Vv7dUWK7EIBC --endpoint-url=https://s3.ru-msk.k2.cloud
    
  3. Check for any non-deleted parts remaining.

    $ aws s3api list-parts --bucket <bucket> --key <large_file> --upload-id 2~mdty_HtKZOHy6rIHFq9Vv7dUWK7EIBC --endpoint-url=https://s3.ru-msk.k2.cloud
    
    {
    
        "Parts": [
    
            {
    
                "PartNumber": 1,
    
                "LastModified": "2024-08-27T10:01:30.270Z",
    
                "ETag": "\"496431d179b88aa424ed7a8a17587a8b\"",
    
                "Size": 5922
    
            },
    
            {
    
                "PartNumber": 2,
    
                "LastModified": "2024-08-27T10:02:46.818Z",
    
                "ETag": "\"fdaba5b0e698fe4a16e591d1753ebccb\"",
    
                "Size": 5923
    
            }
    
        ],
    
        "Initiator": null,
    
        "Owner": {
    
            "DisplayName": "",
    
            "ID": ""
    
        },
    
        "StorageClass": "STANDARD"
    
    }
    

How to install s3cmd to use advanced object storage management features#

The s3cmd utility provides advanced features. Follow the steps below to install and set it up.

  1. Before installation, get API access settings in the cloud management console. Click the user login in the top right corner, select Profile Get API access settings.

  2. By default, S3cmd utility is included in Ubuntu, Debian, Fedora, CentOS, and RHEL Linux repositories, and can be installed, using the following commands.

    # yum install epel-release -y
    # yum install s3cmd -y
    
    # sudo apt-get install s3cmd
    
  3. Then you have to configure s3cmd (access and secret keys can be found in API access settings):

    S3cmd settings
    $ s3cmd --configure
    
    Enter new values or accept defaults in brackets with Enter.
    Refer to user manual for detailed description of all options.
    Access key and Secret key are your identifiers for Amazon S3.
    Leave them empty for using the env variables.
    
    Access Key: <Project ID in K2 Cloud>:<Your login to K2 Cloud>
    Secret Key: XXXXXXXXXXXXXXXXXXXXXX
    Default Region [US]:
    
    Use "s3.amazonaws.com" for S3 Endpoint and not modify it to the target Amazon S3.
    S3 Endpoint [s3.amazonaws.com]: s3.ru-msk.k2.cloud
    
    Use "%(bucket)s.s3.amazonaws.com" to the target Amazon S3.
    "%(bucket)s" and "%(location)s" vars can be used
    if the target S3 system supports dns based buckets.
    DNS-style bucket+hostname:port template for accessing
    a bucket [%(bucket)s.s3.amazonaws.com]: %(bucket)s.s3.ru-msk.k2.cloud
    
    Encryption password is used to protect your files from reading
    by unauthorized persons while in transfer to S3
    Encryption password:
    Path to GPG program [/usr/bin/gpg]:
    
    When using secure HTTPS protocol all communication with Amazon S3
    servers is protected from 3rd party eavesdropping. This method is
    slower than plain HTTP, and can only be proxied with Python 2.7 or newer
    Use HTTPS protocol [No]: yes
    
    On some networks all internet access must go through a HTTP proxy.
    Try setting it here if you can't connect to S3 directly
    HTTP Proxy server name:
    
    New settings:
    Access Key: <Project ID in K2 Cloud>:<Your login to K2 Cloud>
    Secret Key: XXXXXXXXXXXXXXXXXXXXXX
    Default Region: US
    S3 Endpoint: s3.ru-msk.k2.cloud
    DNS-style bucket+hostname:port template for accessing a bucket: %(bucket)s.s3.ru-msk.k2.cloud
    Encryption password:
    Path to GPG program: /usr/bin/gpg
    Use HTTPS protocol: True
    HTTP Proxy server name:
    HTTP Proxy server port: 0
    
    Test access with supplied credentials? [Y/n] y
    
    Save settings? [y/N] y
    

Now you can use S3cmd utility. To learn more about working with the utility, run s3cmd --help.

Granting users different access rights to a bucket#

Fine-grained access control for individual users is under development.

To configure different access, for example read-only for one user and read and write for another, add them to different projects and define bucket policies (Bucket Policy).

Bucket policy specifics:

  • Permissions are granted at the project level. A bucket policy grants permissions to entire projects, not to individual users.

  • One S3 account per project. All users in one project who have access to object storage receive the same permissions under a shared S3 account.

  • Identification by S3 User ID. When you create access rules in a bucket policy, specify the S3 User ID of the corresponding project as the principal.

  • Separate roles. Create a separate project for each distinct set of access rights.

Access scheme#

The example uses the access-demo bucket and three projects.

Project

Who works in the project

Access to access-demo

storage-owner

Storage administrator

Managing bucket settings on behalf of the bucket owner

storage-ro

User reader

Viewing the object list and downloading

storage-rw

User writer

Viewing the object list, downloading, and uploading

The bucket is in the storage-owner project. The storage-ro and storage-rw projects access it according to the bucket policy. If a group of users needs the same access rights, keep those users in one project.

If the bucket whose access you need to configure already exists, leave it in the current project and use that project instead of storage-owner. For one external reader user, one additional project is enough. If the second user must have full owner rights, that user can work in the owner project, so two projects are enough in total. Separate projects for the reader and writer users are needed when both of them must have limited access to the bucket.

Note

From here on, use your bucket name instead of access-demo, including in policy documents.

Creating projects and assigning users#

To configure access rights, the administrator must have privileges to manage IAM. How to work with users and projects is described in Users and projects.

  1. Create projects storage-ro and storage-rw in IAM Projects. If necessary, create the storage-owner project where the bucket will be located.

  2. If the users do not exist yet, create them in IAM Users.

  3. Open the storage-ro project, go to the Users tab, and click Add. Select the reader user and attach the S3FullAccess project policy to that user.

  4. Similarly, add the writer user to the storage-rw project and attach the S3FullAccess project policy to that user.

Note

The S3FullAccess policy lets the user work with object storage in the selected project. Access to a bucket in another project is configured by its owner through a bucket policy. S3FullAccess privileges in the reader user’s project are therefore compatible with read-only access to a bucket in another project.

Obtaining identifiers#

In each of the storage-ro and storage-rw projects, open Profile, find the S3 User ID of the corresponding project, and save it. To open the profile, click the user login in the top right corner and select Profile.

In the policy, use the identifier in this format:

arn:aws:iam:::user/<PROJECT_S3_USER_ID>

Configuring the AWS CLI#

Click the user login in the top right corner and select Profile Get API access settings. In the window that opens, select the required region and project.

Install and configure AWS CLI. Create three named profiles:

aws configure --profile s3-owner
aws configure --profile s3-ro
aws configure --profile s3-rw

In each profile, set the Access Key ID and Secret Access Key for the required combination of project and user. When configuring, specify the US region and the json output format.

Note

When using AWS CLI 1.37.0 or later, or 2.23.0 or later, enable checksum verification only when the operation requires it.

For each profile, run:

aws configure set request_checksum_calculation when_required --profile s3-owner
aws configure set response_checksum_validation when_required --profile s3-owner
aws configure set request_checksum_calculation when_required --profile s3-ro
aws configure set response_checksum_validation when_required --profile s3-ro
aws configure set request_checksum_calculation when_required --profile s3-rw
aws configure set response_checksum_validation when_required --profile s3-rw

Preparing the bucket#

Use an existing bucket in the owner project, or create a new one in Object storage Buckets of that project. For a first introduction to the scheme, it is more convenient to create a separate test bucket.

For an existing bucket, check the current policy. If the bucket has just been created and no policy has been set yet, skip this step:

aws s3api --profile s3-owner get-bucket-policy --bucket access-demo --output text --endpoint-url https://s3.ru-msk.k2.cloud

If the command returned data in JSON format, save the policy to the policy-before.json file in UTF-8 encoding. The NoSuchBucketPolicy error means that no policy has been set before. If you get AccessDenied or another error, find out its cause first.

Important

A bucket uses a single policy document. The command that applies a policy replaces the document entirely. If a policy already exists, add the required statements to the Statement array and keep the current restrictions and the necessary permissions. Do not replace a working policy with the example without checking its contents.

Also check the bucket ACL and, if necessary, the object ACLs:

aws s3api --profile s3-owner get-bucket-acl --bucket access-demo --endpoint-url https://s3.ru-msk.k2.cloud

The allow policy below does not by itself revoke permissions granted in another way. For access to match what you expect, read-only or read and upload, the projects must not have extra write or delete permissions through an ACL or other statements in the same bucket policy. For example, an explicit Deny in the current policy can also block actions that are allowed below.

Preparing a policy with two rules#

Save the following JSON document to the policy.json file. Replace <RO_PROJECT_S3_USER_ID> and <RW_PROJECT_S3_USER_ID> with the S3 User ID of the reader and writer users’ projects.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ReadOnlyProject",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam:::user/<RO_PROJECT_S3_USER_ID>"
      },
      "Action": ["s3:ListBucket", "s3:GetObject"],
      "Resource": ["arn:aws:s3:::access-demo", "arn:aws:s3:::access-demo/*"]
    },
    {
      "Sid": "ReadWriteProject",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam:::user/<RW_PROJECT_S3_USER_ID>"
      },
      "Action": ["s3:ListBucket", "s3:GetObject", "s3:PutObject"],
      "Resource": ["arn:aws:s3:::access-demo", "arn:aws:s3:::access-demo/*"]
    }
  ]
}

The first statement lets the reader user’s project list and download objects. The second lets the writer user’s project do the same and upload objects. This document does not allow deleting objects or changing the bucket policy.

Action

Purpose

Resource

s3:ListBucket

Get the list of objects

arn:aws:s3:::access-demo

s3:GetObject

Download an object and get its headers

arn:aws:s3:::access-demo/*

s3:PutObject

Upload an object or write data to an existing key

arn:aws:s3:::access-demo/*

Each rule lists the bucket and its objects, so these actions can be combined in one Statement. Multiple Resource values are written as an array in square brackets.

ListBucket does not grant permission to download objects, and GetObject does not grant permission to list them. The reader user needs both actions. The /* wildcard covers object keys at any depth, including objects uploaded later, if the access conditions are met for them.

Important

Writing allows overwriting: PutObject allows data to be uploaded to an existing object key. In other words, the absence of the DeleteObject permission does not protect existing data from being changed, because objects can be overwritten.

Applying the policy#

Run the command on behalf of the owner project:

aws s3api --profile s3-owner put-bucket-policy --bucket access-demo --policy file://policy.json --endpoint-url https://s3.ru-msk.k2.cloud

Make sure that the command completed without an error, then read the policy that was set:

aws s3api --profile s3-owner get-bucket-policy --bucket access-demo --endpoint-url https://s3.ru-msk.k2.cloud

Compare the S3 User ID, the bucket name, and the actions with the prepared JSON. A successful read of the policy confirms that it has been saved. The permissions themselves need to be checked with separate requests.

Other policy options#

The following examples are separate policy documents. To combine several options for one bucket, merge the required Statement rules into one document, check the allow and deny effects, and then apply it as a whole.

Separating read and upload access#

Read only#

If you need to grant read-only permissions, one statement for the project with the reader user is enough:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ReadOnlyProject",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam:::user/<RO_PROJECT_S3_USER_ID>"
      },
      "Action": ["s3:ListBucket", "s3:GetObject"],
      "Resource": ["arn:aws:s3:::access-demo", "arn:aws:s3:::access-demo/*"]
    }
  ]
}

If the bucket already has other write permissions, an allow statement for reading does not cancel them.

Upload only, without reading or listing objects#

The policy below denies the writer-only user reading, listing, deletion, and changes to object ACLs. It also rejects uploads without the specified ACL, so the writer-only user cannot make an object public and download it anonymously.

Use a separate write-only project and the s3-write-only profile. Configure the profile as described above, and substitute the S3 User ID of this project for <WRITE_ONLY_PROJECT_S3_USER_ID>.

In this policy, the --acl bucket-owner-full-control parameter is required when uploading an object. It grants the bucket owner full access to the uploaded object. The writer-only user’s project remains the owner of the object itself.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowUpload",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam:::user/<WRITE_ONLY_PROJECT_S3_USER_ID>"
      },
      "Action": [
        "s3:PutObject"
      ],
      "Resource": [
        "arn:aws:s3:::access-demo/*"
      ]
    },
    {
      "Sid": "DenyReadingListingAndDeletion",
      "Effect": "Deny",
      "Principal": {
        "AWS": "arn:aws:iam:::user/<WRITE_ONLY_PROJECT_S3_USER_ID>"
      },
      "Action": [
        "s3:GetObject",
        "s3:GetObjectVersion",
        "s3:ListBucket",
        "s3:ListBucketVersions",
        "s3:DeleteObject",
        "s3:DeleteObjectVersion",
        "s3:PutObjectAcl",
        "s3:PutObjectVersionAcl"
      ],
      "Resource": [
        "arn:aws:s3:::access-demo",
        "arn:aws:s3:::access-demo/*"
      ]
    },
    {
      "Sid": "DenyUploadWithoutBucketOwnerControl",
      "Effect": "Deny",
      "Principal": {
        "AWS": "arn:aws:iam:::user/<WRITE_ONLY_PROJECT_S3_USER_ID>"
      },
      "Action": [
        "s3:PutObject"
      ],
      "Resource": [
        "arn:aws:s3:::access-demo/*"
      ],
      "Condition": {
        "StringNotEqualsIfExists": {
          "s3:x-amz-acl": "bucket-owner-full-control"
        }
      }
    }
  ]
}

The policy allows a regular upload with the bucket-owner-full-control ACL and denies the project reading, listing, deletion, and a later change of object ACLs. The writer-only user therefore cannot make uploaded objects public through an ACL and download them anonymously. The writer-only user’s project remains the object owner, and the bucket owner receives full FULL_CONTROL rights.

If, in addition to the writer-only user, you need to grant access to the reader user, add the allow statement for the reader user from the storage-ro project to these three statements. That makes four Statement items. The --acl bucket-owner-full-control parameter is not required for reading.

Read permissions for two projects and read and upload permissions for a third#

Note

To grant read permissions to two users, you do not need two separate projects. Add both users to the project that has read permissions.

List the S3 User ID of projects with the same permissions in the Principal.AWS array:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ReadOnlyProjects",
      "Effect": "Allow",
      "Principal": {
        "AWS": [
          "arn:aws:iam:::user/<PROJECT_1_S3_USER_ID>",
          "arn:aws:iam:::user/<PROJECT_2_S3_USER_ID>"
        ]
      },
      "Action": ["s3:ListBucket", "s3:GetObject"],
      "Resource": ["arn:aws:s3:::access-demo", "arn:aws:s3:::access-demo/*"]
    },
    {
      "Sid": "ReadWriteProject",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam:::user/<PROJECT_3_S3_USER_ID>"
      },
      "Action": ["s3:ListBucket", "s3:GetObject", "s3:PutObject"],
      "Resource": ["arn:aws:s3:::access-demo", "arn:aws:s3:::access-demo/*"]
    }
  ]
}

When adding the next project with the same permissions, add a line with its S3 User ID to the appropriate array. For a different set of permissions, create a separate rule. Do not specify the same project in groups with different expected restrictions at the same time: its permissions add up, and a matching explicit deny takes precedence.

Uploading large files in parts#

The operations that start a multipart upload, upload its parts, and complete it use the PutObject permission. The client may also need permissions for the following actions:

Action

Purpose

s3:AbortMultipartUpload

Abort an incomplete upload

s3:ListMultipartUploadParts

Get the list of upload parts

s3:ListBucketMultipartUploads

Get the list of the bucket’s incomplete uploads

For such a client, add the required actions from the table to the Action array of the writer user’s statement in the main example. Start with the minimum set and add the operations that the client in use needs.

If deletion is required, add s3:DeleteObject only to the project that needs it. Reading specific versions requires s3:GetObjectVersion, listing versions requires s3:ListBucketVersions, and deleting specific versions requires s3:DeleteObjectVersion. The basic examples do not grant these permissions.

Restricting access by keys and prefixes#

Reading objects with a specific prefix#

The following policy allows every user in the project to read the reports/* keys and list them:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ListReports",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam:::user/<RO_PROJECT_S3_USER_ID>"
      },
      "Action": ["s3:ListBucket"],
      "Resource": ["arn:aws:s3:::access-demo"],
      "Condition": {
        "StringLike": {
          "s3:prefix": ["reports/", "reports/*"]
        }
      }
    },
    {
      "Sid": "ReadReports",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam:::user/<RO_PROJECT_S3_USER_ID>"
      },
      "Action": ["s3:GetObject"],
      "Resource": ["arn:aws:s3:::access-demo/reports/*"]
    }
  ]
}

To request a list of objects with a prefix allowed by the policy, use:

aws s3api --profile s3-ro list-objects-v2 --bucket access-demo --prefix reports/ --endpoint-url https://s3.ru-msk.k2.cloud

This document does not allow a list request without a prefix, or with other prefixes. The resource restriction applies to keys, and the s3:prefix condition in ListBucket applies to the list request. Both statements are needed for isolation.

Anonymous access for downloading objects with the public prefix#

The statement is suitable when one bucket stores both public and private files. New objects with the public/ prefix also become available for download. The statement does not allow listing objects.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "PublicReadPublishedObjects",
      "Effect": "Allow",
      "Principal": "*",
      "Action": ["s3:GetObject"],
      "Resource": ["arn:aws:s3:::access-demo/public/*"]
    }
  ]
}

Without access keys, you can download public/manual.pdf, for example, but you cannot download private/report.pdf if there are no other permissions for it.

Restricting access by IP address#

Anonymous access for downloading from allowed IP addresses#

Replace the addresses in the example with your clients’ addresses:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "PublicReadFromAllowedIPs",
      "Effect": "Allow",
      "Principal": "*",
      "Action": ["s3:GetObject"],
      "Resource": ["arn:aws:s3:::access-demo/*"],
      "Condition": {
        "IpAddress": {
          "aws:SourceIp": ["203.0.113.10/32", "198.51.100.0/24"]
        }
      }
    }
  ]
}

When traffic goes through NAT, a VPN, or a proxy, the address from which the request reaches the object storage endpoint may differ from the client address. In that case, specify the public IP address of the NAT, VPN, or proxy node that the traffic passes through.

This is an allow statement: it does not block access already granted through an ACL or another statement. For example, the bucket owner can keep access from other addresses.

Denying anonymous access from other IP addresses#

The statement denies all operations on the specified bucket and its objects if the request did not come from an allowed address. The deny also applies to the bucket owner if that address is not in the allowed list. Resource must include both the bucket itself and its objects with the /* wildcard, because the entry arn:aws:s3:::access-demo/ does not cover objects.

Attention

Access to the bucket through the web interface is blocked if the IP address of console requests to object storage is not in the allowed list. Before applying the policy, also make sure that your current IP address is in the allowed list. Otherwise, you will also deny yourself the ability to change and delete the policy.

The statement itself does not grant any permissions. Previously granted owner rights, ACLs, and allow statements continue to apply when access comes from an allowed address. To grant access from another project, add the required allow Statement elements from the previous examples to this document.

Important

An IP address restriction does not replace authorization. For only project-key access to work from the allowed network, the bucket and objects must not have public ACLs or allow statements for anonymous clients. A deny with the NotIpAddress condition does not cancel public access from the allowed network.

In the example, replace the addresses with your own.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyOutsideAllowedIPs",
      "Effect": "Deny",
      "Principal": "*",
      "Action": ["s3:*"],
      "Resource": ["arn:aws:s3:::access-demo", "arn:aws:s3:::access-demo/*"],
      "Condition": {
        "NotIpAddress": {
          "aws:SourceIp": ["203.0.113.10/32", "198.51.100.0/24"]
        }
      }
    }
  ]
}
Reading only from the project’s IP address#

Attention

For the specified project, access to the bucket through the web interface is also blocked if the IP address of console requests to object storage is not in the allowed list. This statement does not restrict the owner project.

Unlike an IP address deny for all users, the restrictions here apply only to a specific project:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ReadOnlyProject",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam:::user/<RO_PROJECT_S3_USER_ID>"
      },
      "Action": ["s3:ListBucket", "s3:GetObject"],
      "Resource": ["arn:aws:s3:::access-demo", "arn:aws:s3:::access-demo/*"],
      "Condition": {
        "IpAddress": {
          "aws:SourceIp": ["203.0.113.10/32"]
        }
      }
    },
    {
      "Sid": "DenyProjectOutsideAllowedIPs",
      "Effect": "Deny",
      "Principal": {
        "AWS": "arn:aws:iam:::user/<RO_PROJECT_S3_USER_ID>"
      },
      "Action": ["s3:*"],
      "Resource": ["arn:aws:s3:::access-demo", "arn:aws:s3:::access-demo/*"],
      "Condition": {
        "NotIpAddress": {
          "aws:SourceIp": ["203.0.113.10/32"]
        }
      }
    }
  ]
}

The first statement lets the project list objects and download them from the allowed address. The second denies this project any operations on the bucket from other addresses, including when extra permissions are granted through an ACL. Other projects are not restricted by this deny.

An IP address condition does not distinguish users of the same project. Different restrictions still require different projects.

Anonymous access for downloading all objects#

The policy allows any client, including a client without access keys, to download an object by a known key:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "PublicReadGetObject",
      "Effect": "Allow",
      "Principal": "*",
      "Action": ["s3:GetObject"],
      "Resource": ["arn:aws:s3:::access-demo/*"]
    }
  ]
}

The permission applies to existing objects and to objects uploaded later whose keys match the access-demo/* pattern. It does not grant permission to list, upload, or delete objects. A matching explicit Deny takes precedence.

Changing and revoking access rights#

Note

Before making changes, we recommend saving the policy document.

To revoke the access rights that the policy grants to a project, remove the line with its S3 User ID from the corresponding allow statements, or delete those statements, and then apply the document again.

Deleting the entire policy also removes every restriction it contains. To revoke access rights from one project, it is usually enough to change only that project’s statements. The ACL and the owner’s rights remain when the policy is deleted.

If the access rights differ from the expected ones#

  • The list is returned, but the object is not downloaded. Check that GetObject is allowed, that the resource uses the /* wildcard, and check the object key, its owner, and the ACL. Permission to view the bucket ACL does not grant permission to download the object.

  • The reader user can write or delete objects. Check the selected profile, the S3 User ID, the user’s access to projects, the ACL, and the other policy statements.

  • A new object from another project cannot be read. Check that the owner and ACL of the new object are the same as those of an object uploaded by the bucket owner. Reading a previously uploaded object does not guarantee access to newly uploaded objects in another project’s bucket. The rights belong to the specific object, not to the bucket.

  • The policy JSON file is not accepted. Check the quotes, commas, arrays, UTF-8 encoding, and that there are no unreplaced templates. If there are several resources, they must be inside a single Resource array.

  • The required bucket is missing from the general list. Access the known bucket directly. A bucket in another project is not shown in your project’s general bucket list.

  • A small file uploads, but a large one does not. Check the multipart upload operations and the client’s checksum parameters.

  • AccessDenied despite an allow statement that is in effect. Check the Deny statements, the endpoint, the project key, the resource, and the additional conditions. Do not add "Principal": "*" to bypass closed access: an allow statement without additional restrictions can open the bucket to outsiders.

Additional information: object storage access rights, supported S3 API features, and AWS CLI.