All Products
Search
Document Center

Retention policies

Last Updated: Jul 11, 2022

Object Storage Service (OSS) supports the Write Once Read Many (WORM) feature. The feature helps prevent objects from being deleted or overwritten within a specified period of time. This complies with the regulations of the U.S. Securities and Exchange Commission (SEC) and Financial Industry Regulatory Authority. (FINRA).

Prerequisites

  • Retention policies are not supported in the China (Guangzhou), China (Nanjing - Local Region), and US (Virginia) regions.

  • Versioning is not enabled for the bucket for which you want to configure retention policies. For more information about versioning, see Overview.

Scenarios

OSS provides strong compliance policies. You can configure time-based retention policies for OSS buckets. After you configure and lock a retention policy for a bucket, you can upload objects to or read objects from the bucket. However, you cannot delete objects from the bucket or the retention policy within the retention period. You can delete the objects only after the retention period expires. The WORM feature is suitable for fields that involve privacy, such as finance, insurance, health care, securities, and logs data classified protection censorship. OSS enables you to build compliant buckets on the cloud.

Note

OSS is accredited by Cohasset Associates in audit and meets specific requirements for electronic data storage. OSS buckets that are configured with retention policies can be used for business that is subject to regulations such as SEC Rule 17a-4(f), CFTC Rule 1.31(c)-(d), and FINRA Rule 4511(c). For more information, see OSS Cohasset Assessment Report.

Limits

  • You can configure retention policies only for buckets in OSS.

  • We recommend that you do not enable the OSS-HDFS service and configure retention policies for a bucket.

    If you enable the OSS-HDFS service, configure a retention policy for a bucket, and then delete data from the .dlsdata/ directory by using the methods that are supported by the OSS-HDFS service, a message that indicates that the data is successfully deleted is displayed. However, OSS still retains the deleted data during the retention period that is specified for the retention policy and OSS cannot recognize and delete the data after the retention period expires.

  • During the retention period, you can configure lifecycle rules to convert the storage classes of objects in the bucket. This way, you can reduce costs and ensure compliance. For more information, see Lifecycle rules based on the last modified time.

Rules

You can configure only a single time-based retention policy for each bucket. The policy specifies a retention period that ranges from one day to 70 years.

For example, assume that you created a bucket named examplebucket on June 1, 2013, and uploaded the file1.txt, file2.txt, and file3.txt objects to the bucket at different points in time. On July 1, 2014, you created a retention policy for the bucket and specified a five-year retention period. The following table describes the upload and expiration dates of the objects.

Object

Upload date

Expiration date

file1.txt

June 1, 2013

May 31, 2018

file2.txt

July 1, 2014

June 30, 2019

file3.txt

September 30, 2018

September 29, 2023

  • Implementation rules

    By default, a time-based retention policy is in the InProgress state after the policy is created for a bucket. The InProgress state lasts for 24 hours. The retention policy protects the resources in the bucket within 24 hours after the policy is created.

    • Within 24 hours after the retention policy is created: If the retention policy is not locked, the bucket owner and authorized users can delete the policy. If the retention policy is locked, the retention period of the policy cannot be shortened and the policy cannot be deleted. You can only extend the retention period.

    • 24 hours after the retention policy is created: If the retention policy is not locked, the policy becomes invalid.

    • If you attempt to delete or modify data in the protected bucket, a 409 FileImmutable error is returned.

  • Deletion rules

    • A time-based retention policy is a metadata attribute of a bucket. If a bucket is deleted, the retention policy and the access control list (ACL) of the bucket are also deleted. If a bucket is empty, the bucket owner can delete the bucket. This way, the retention policy of the bucket is deleted.

    • If the retention policy is not locked within 24 hours after the policy is created, the bucket owner and authorized users can delete the policy.

    • If a bucket contains objects that are protected within the retention period, you cannot delete the bucket or the retention policy.

Use the OSS console

  1. Log on to the OSS console.

  2. In the left-side navigation pane, click Buckets. On the Buckets page, click the name of the bucket in which you want to create a directory.

  3. In the left-side navigation pane, choose Basic Settings > Retention Policy. In the Retention Policy section, click Configure.

  4. Click Create Policy.

  5. In the Create Policy dialog box, set Retention Period.

    The retention period ranges from one day to 70 years.
  6. Click OK.

    After you create the policy, the policy is in the InProgress state. You can click Lock or Delete to lock or delete a policy in the InProgress state.
  7. Click Lock.

  8. In the message that appears, click OK.

    Notice
    • The policy enters the Locked state. You cannot delete the policy or shorten the retention period. However, you can click Edit to extend the retention period.
    • During the retention period, data in the bucket is protected. If you attempt to delete or modify the data, the following error message is displayed: The file is locked and cannot be operated.

Use OSS SDKs

The following sample code provides an example on how to configure retention policies by using OSS SDKs for common programming languages. For more information about the sample code that is used to configure retention policies by using OSS SDKs for other programming languages, see Overview.

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.InitiateBucketWormRequest;
import com.aliyun.oss.model.InitiateBucketWormResult;

public class Demo {

    public static void main(String[] args) throws Exception {
        // In this example, the endpoint of the China (Hangzhou) region is used. Specify your actual endpoint. 
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // The AccessKey pair of an Alibaba Cloud account has permissions on all API operations. Using these credentials to perform operations in OSS is a high-risk operation. We recommend that you use a Resource Access Management (RAM) user to call API operations or perform routine O&M. To create a RAM user, log on to the RAM console. 
        String accessKeyId = "yourAccessKeyId";
        String accessKeySecret = "yourAccessKeySecret";
        // Specify the name of the bucket. Example: examplebucket. 
        String bucketName = "examplebucket";

        // Create an OSSClient instance. 
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        try {
            // Create an InitiateBucketWormRequest request. 
            InitiateBucketWormRequest initiateBucketWormRequest = new InitiateBucketWormRequest(bucketName);
            // Set the retention period to one day. 
            initiateBucketWormRequest.setRetentionPeriodInDays(1);

            // Create a retention policy. 
            InitiateBucketWormResult initiateBucketWormResult = ossClient.initiateBucketWorm(initiateBucketWormRequest);

            // Display the ID of the retention policy. 
            String wormId = initiateBucketWormResult.getWormId();
            System.out.println(wormId);
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
}
<?php
if (is_file(__DIR__ . '/../autoload.php')) {
    require_once __DIR__ . '/../autoload.php';
}
if (is_file(__DIR__ . '/../vendor/autoload.php')) {
    require_once __DIR__ . '/../vendor/autoload.php';
}

use OSS\OssClient;
use OSS\Core\OssException;

// The AccessKey pair of an Alibaba Cloud account has permissions on all API operations. Using these credentials to perform operations in OSS is a high-risk operation. We recommend that you use a RAM user to call API operations or perform routine O&M. To create a RAM user, log on to the RAM console. 
$accessKeyId = "yourAccessKeyId";
$accessKeySecret = "yourAccessKeySecret";
// In this example, the endpoint of the China (Hangzhou) region is used. Specify your actual endpoint. 
$endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// Specify the name of the bucket. Example: examplebucket. 
$bucket= "examplebucket";

$ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, false);

try {
    // Create a retention policy and set the retention period to 30 days. 
    $wormId = $ossClient->initiateBucketWorm($bucket, 30);

    // Display the ID of the retention policy. 
    print($wormId);
} catch (OssException $e) {
    printf(__FUNCTION__ . ": FAILED\n");
    printf($e->getMessage() . "\n");
    return;
}

print(__FUNCTION__ . ": OK" . "\n");
const OSS = require('ali-oss');

const client = new OSS({
  // Specify the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the region to oss-cn-hangzhou. 
  region: 'yourregion',
  // The AccessKey pair of an Alibaba Cloud account has permissions on all API operations. Using these credentials to perform operations in OSS is a high-risk operation. We recommend that you use a RAM user to call API operations or perform routine O&M. To create a RAM user, log on to the RAM console. 
  accessKeyId: 'yourAccessKeyId',
  accessKeySecret: 'yourAccessKeySecret'
});
// Create a retention policy. 
async function initiateBucketWorm() {
 // Specify the name of the bucket. Example: examplebucket. 
  const bucket = 'examplebucket'
  // Specify the retention period of objects in the bucket. 
  const days = '30'
        const res = await client.initiateBucketWorm(bucket, days)
  console.log(res.wormId)
}

initiateBucketWorm()
# -*- coding: utf-8 -*-
import oss2

# The AccessKey pair of an Alibaba Cloud account has permissions on all API operations. Using these credentials to perform operations in OSS is a high-risk operation. We recommend that you log on as a RAM user to call API operations or perform routine O&M. To create a RAM user, log on to the RAM console. 
auth = oss2.Auth('yourAccessKeyId', 'yourAccessKeySecret')
# Specify the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com. 
# Specify the name of the bucket. Example: examplebucket. 
bucket = oss2.Bucket(auth, 'https://oss-cn-hangzhou.aliyuncs.com', 'examplebucket')

# Create the retention policy and set the retention period to one day. 
result = bucket.init_bucket_worm(1)
# Display the ID of the retention policy. 
print(result.worm_id)
package main

import (
    "fmt"
    "github.com/aliyun/aliyun-oss-go-sdk/oss"
    "os"
)

func HandleError(err error) {
    fmt.Println("Error:", err)
    os.Exit(-1)
}

func main() {
    // Create an OSSClient instance. 
    // Specify the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com. Specify your actual endpoint. 
    // The AccessKey pair of an Alibaba Cloud account has permissions on all API operations. Using these credentials to perform operations in OSS is a high-risk operation. We recommend that you use a RAM user to call API operations or perform routine operations and maintenance. To create a RAM user, log on to the RAM console. 
    client, err := oss.New("yourEndpoint", "yourAccessKeyId", "yourAccessKeySecret")
    if err != nil {
        HandleError(err)
    }

    // Specify the name of the bucket. Example: examplebucket. 
    bucketname := "examplebucket"
    // Set the retention period to 60 days. 
    result,err := client.InitiateBucketWorm(bucketname,60)
    if err != nil {
        HandleError(err)
    }

    fmt.Println(result)
}
#include <alibabacloud/oss/OssClient.h>
using namespace AlibabaCloud::OSS;

int main(void)
{
      /* Initialize information about the account that is used to access OSS. */
      /* The AccessKey pair of an Alibaba Cloud account has permissions on all API operations. Using these credentials to perform operations in OSS is a high-risk operation. We recommend that you use a RAM user to call API operations or perform routine O&M. To create a RAM user, log on to the RAM console. */
      std::string AccessKeyId = "yourAccessKeyId";
      std::string AccessKeySecret = "yourAccessKeySecret";
      /* Specify the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com. */
      std::string Endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
      /* Specify the name of the bucket. Example: examplebucket. */
      std::string BucketName = "examplebucket";

      /* Initialize resources such as networks. */
      InitializeSdk();

      ClientConfiguration conf;
      OssClient client(Endpoint, AccessKeyId, AccessKeySecret, conf);
  
        /* Create a retention policy and set the retention period to 10 days. */
      auto outcome = client.InitiateBucketWorm(InitiateBucketWormRequest(BucketName, 10));

      if (outcome.isSuccess()) {      
            std::cout << " InitiateBucketWorm success " << std::endl;
      }
      else {
        /* Handle exceptions. */
        std::cout << "InitiateBucketWorm fail" <<
        ",code:" << outcome.error().Code() <<
        ",message:" << outcome.error().Message() <<
        ",requestId:" << outcome.error().RequestId() << std::endl;
        ShutdownSdk();
        return -1;
      }

      /* Release resources such as networks. */
      ShutdownSdk();
      return 0;
}

Use ossutil

For more information about how to configure retention policies by using ossutil, see worm (manage retention policies).

Use the RESTful API

If your program requires more custom options to configure retention policies, you can call RESTful API operations. To directly call an API, you must include the signature calculation in your code. For more information, see InitiateBucketWorm.

FAQ

  • Q: What are the benefits of a retention policy?

    A: A retention policy can be used to meet data security standards. Within the retention period of a retention policy, data cannot be modified or deleted. The data that is protected by using RAM policies and bucket policies can be modified and deleted.

  • Q: What are the scenarios in which a retention policy can be used?

    A: You can use a retention policy if you want to store important data that is infrequently accessed and not allowed to be modified or deleted. This type of data includes medical records, technical documents, and contracts. You can store these objects in a specific bucket and configure a retention policy for the bucket.

  • Q: Can I configure a retention policy at the object level?

    A: No, retention policies can be configured only at the bucket level.

  • Q: How do I calculate the expiration time of an object within a retention period?

    A: The expiration time of an object within a retention period can be calculated based on the retention period and the time when the object is last modified. For example, the retention period of Bucket A is 10 days. An object in the bucket is last modified at 12:00 on February 15, 2022. In this case, the object expires at 12:01 on February 25, 2022.

  • Q: How do I delete a bucket that is protected by a retention policy?

    • A: If the bucket contains no objects, you can delete the bucket. This way, the retention policy is deleted.

    • If the bucket contains objects, the bucket cannot be deleted even if the retention period ends. In this case, you can delete all objects from the bucket and then delete the bucket.

    • If the bucket contains objects that are protected within the retention period, the bucket cannot be deleted.

  • Q: Are objects that are protected within the retention period of a retention policy retained if my account has overdue OSS payments?

    A: If your account has overdue payments, Alibaba Cloud retains data based on the corresponding terms and conditions of your contract.

  • Q: Can an authorized RAM user configure a retention policy?

    A: All API operations related to the retention policy are available and they support RAM policies. RAM users that are granted permissions by using RAM policies can create or delete a retention policy by using the OSS console, API operations, or OSS SDKs.