All Products
Search
Document Center

Object Storage Service:Retention policies

Last Updated:Nov 15, 2024

The Write Once Read Many (WORM) feature of retention policies in Object Storage Service (OSS) allows you to prevent users from modifying or deleting data. If you do not want anyone, including resource owners, to modify or delete objects in a bucket within a specific period of time, you can configure a retention policy for the bucket. Before the specified retention period ends, you can only upload objects to or read objects from the bucket. You can modify or delete objects only after the retention period ends.

Prerequisites

  • The bucket for which you want to configure retention policies is located in one of the following regions: China (Hangzhou), China (Shanghai), China (Fuzhou-Local Region), China (Qingdao), China (Beijing), China (Zhangjiakou), China (Hohhot), China (Ulanqab), China (Shenzhen), China (Heyuan), China (Guangzhou), China (Chengdu), China (Hong Kong), US (Silicon Valley), Japan (Tokyo), South Korea (Seoul), Singapore, Malaysia (Kuala Lumpur), Indonesia (Jakarta), Philippines (Manila), Thailand (Bangkok), Germany (Frankfurt), UK (London), and UAE (Dubai).

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

Scenarios

The WORM feature provided by the retention policies in OSS helps enterprises meet regulatory and compliance requirements of the U.S. Securities and Exchange Commission (SEC) and Financial Industry Regulatory Authority (FINRA). The feature is suitable for sectors such as finance, insurance, healthcare, and securities, and scenarios such as Multi-Layer Protection Scheme (MLPS) audit of log data.

Note

OSS is accredited and audited by Cohasset Associates and meets the stringent requirements for the retention of electronic records. OSS buckets for which retention policies are configured comply with regulatory 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.

Usage notes

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

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

    For example, OSS-HDFS is enabled for a bucket for which a retention policy is configured. When you use methods supported by OSS-HDFS to delete an object from the .dlsdata/ directory, you receive a message that indicates the object is deleted. However, OSS actually retains the object if the deletion occurs within the retention period and cannot recognize and delete the object after the retention period ends.

  • During the retention period, you can configure lifecycle rules to change 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.

Retention policy description

  • Implementation

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

    • In the 24-hour window 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. However, the retention period can be extended.

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

    • 24 hours after the retention policy is created

      If the retention policy is not locked 24 hours after the retention policy is created, the policy becomes invalid. You can delete the policy.

  • Deletion

    • A time-based retention policy is a metadata attribute of a bucket. If a bucket is deleted, the retention policy of the bucket is also 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.

  • Example

    For example, you created a retention policy that has a retention period of 30 days for a bucket on June 1, 2022, and immediately locked the policy. You uploaded the file1.txt, file2.txt, and file3.txt objects to the bucket at different points in time. The following table describes the upload dates and expiration dates of the objects.

    Object

    Upload date

    Expiration date

    file1.txt

    April 1, 2022

    April 30, 2022

    file2.txt

    June 1, 2022

    June 30, 2022

    file3.txt

    September 1, 2022

    September 30, 2022

Methods

Use the OSS console

  1. Create a retention policy.

    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 for which you want to create a retention policy.

    3. In the left-side navigation tree, choose Content Security > Retention Policy.

    4. On the Retention Policy page, click Create Policy.

    5. In the Create Policy dialog box, specify a retention period in the Retention Period field.

      Note

      The retention period is measured in days. Valid values: 1 to 25550.

    6. Click OK.

      Note

      The retention policy is in the IN_PROGRESS state. The retention policy remains in the IN_PROGRESS state for 24 hours. The retention policy protects the resources in the bucket within 24 hours after the policy is created. If you do not need the retention policy, you can delete the policy within 24 hours after it is created.

  2. Lock the retention policy.

    1. On the Retention Policy page, click Lock.

    2. In the message that appears, click OK.

      Important

      After a time-based retention policy is locked, you cannot shorten the retention period or delete the retention policy. You cannot modify or delete data in the bucket during the retention period.

  3. (Optional) Modify the retention period of the retention policy.

    1. On the Retention Policy page, click Edit.

    2. In the Edit dialog box, modify the retention period.

      Important

      You can extend the retention period, but you cannot shorten the retention period.

Use OSS SDKs

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

Java

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.common.auth.*;
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";
        // Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured. 
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // Specify the name of the bucket. Example: examplebucket. 
        String bucketName = "examplebucket";
        // 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 cn-hangzhou. 
        String region = "cn-hangzhou";

        // Create an OSSClient instance. 
        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);        
        OSS ossClient = OSSClientBuilder.create()
        .endpoint(endpoint)
        .credentialsProvider(credentialsProvider)
        .clientConfiguration(clientBuilderConfiguration)
        .region(region)               
        .build();

        try {
            // Create an InitiateBucketWormRequest object. 
            InitiateBucketWormRequest initiateBucketWormRequest = new InitiateBucketWormRequest(bucketName);
            // Set the retention period to 1 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

<?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\Credentials\EnvironmentVariableCredentialsProvider;
use OSS\OssClient;
use OSS\CoreOssException;

// Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured.  
$provider = new EnvironmentVariableCredentialsProvider();
// In this example, the endpoint of the China (Hangzhou) region is used. Specify your actual endpoint. 
$endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
$bucket= "<yourBucketName>";

$config = array(
        "provider" => $provider,
        "endpoint" => $endpoint,
        "signatureVersion" => OssClient::OSS_SIGNATURE_VERSION_V4,
        "region"=> "cn-hangzhou"
    );
    $ossClient = new OssClient($config);

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

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

print(__FUNCTION__ . ": OK" . "\n"); 

Node.js

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',
  // Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured. 
  accessKeyId: process.env.OSS_ACCESS_KEY_ID,
  accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,  
  authorizationV4: true,
  // Specify the name of your bucket.
  bucket: 'yourBucketName',
});
// Create a retention policy. 
async function initiateBucketWorm() {
 // Specify the name of the bucket. 
  const bucket = 'yourbucketname'
  // Specify the retention period of the retention policy. 
  const days = '<Retention Days>'
    const res = await client.initiateBucketWorm(bucket, days)
  console.log(res.wormId)
}

initiateBucketWorm()

Python

# -*- coding: utf-8 -*-
import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider
# Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured. 
auth = oss2.ProviderAuthV4(EnvironmentVariableCredentialsProvider())

# 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. 
endpoint = "https://oss-cn-hangzhou.aliyuncs.com"
# Specify the ID of the region that maps to the endpoint. Example: cn-hangzhou. This parameter is required if you use the signature algorithm V4.
region = "cn-hangzhou"

# Specify the name of your bucket.
bucket = oss2.Bucket(auth, endpoint, "yourBucketName", region=region)

# Create a retention policy and set the retention period to 1 day. 
result = bucket.init_bucket_worm(1)
# Query the ID of the retention policy. 
print(result.worm_id)

Go

package main

import (
	"log"

	"github.com/aliyun/aliyun-oss-go-sdk/oss"
)

func main() {
	// Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured. 
	provider, err := oss.NewEnvironmentVariableCredentialsProvider()
	if err != nil {
		log.Fatalf("Error creating credentials provider: %v", err)
	}

	// 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. 
	// 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 cn-hangzhou. Specify the actual region.
	clientOptions := []oss.ClientOption{oss.SetCredentialsProvider(&provider)}
	clientOptions = append(clientOptions, oss.Region("yourRegion"))
	// Specify the version of the signature algorithm.
	clientOptions = append(clientOptions, oss.AuthVersion(oss.AuthV4))
	client, err := oss.New("yourEndpoint", "", "", clientOptions...)
	if err != nil {
		log.Fatalf("Error creating OSS client: %v", err)
	}

	// Specify the name of the bucket for which you want to configure a retention policy. 
	bucketName := "<yourBucketName>"

	// Set the retention period of the retention policy to 60 days.
	result, err := client.InitiateBucketWorm(bucketName, 60)
	if err != nil {
		log.Fatalf("Error initiating bucket WORM: %v", err)
	}

	log.Println("WORM policy initiated successfully:", result)
}

C++

#include <alibabacloud/oss/OssClient.h>
using namespace AlibabaCloud::OSS;

int main(void)
{
    /* Initialize information about the account that is used to access OSS. */
            
    /* 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 = "yourEndpoint";
    /* Specify the name of the bucket. Example: examplebucket. */
    std::string BucketName = "examplebucket";

      /* Initialize resources, such as network resources. */
      InitializeSdk();

      ClientConfiguration conf;
      /* Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured. */
    auto credentialsProvider = std::make_shared<EnvironmentVariableCredentialsProvider>();
    OssClient client(Endpoint, credentialsProvider, 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;
            std::cout << "WormId:" << outcome.result().WormId() << std::endl;
      }
      else {
        /* Handle exceptions. */
        std::cout << "InitiateBucketWorm fail" <<
        ",code:" << outcome.error().Code() <<
        ",message:" << outcome.error().Message() <<
        ",requestId:" << outcome.error().RequestId() << std::endl;
        return -1;
      }

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

Use ossutil

You can configure retention policies by using ossutil. For more information, see worm (manage retention policies).

Use the OSS API

If your business requires a high level of customization, you can directly call RESTful APIs. To directly call an API, you must include the signature calculation in your code. For more information, see InitiateBucketWorm.

FAQ

What are the benefits of a retention policy?

A retention policy provides secure and compliant data storage. Within the retention period of a retention policy, data cannot be modified or deleted. If you use Resource Access Management (RAM) policies and bucket policies to protect data, data can still be modified or deleted.

In what scenarios do I need a retention policy?

If you want to store important data such as medical records, technical documents, and contracts for a long period of time in a bucket and prohibits modifications to or deletion of the data, you can configure a retention policy for the bucket.

Can I delete a retention policy?

It depends on the status of the retention policy.

  • If the retention policy is not locked, you can delete the policy as the bucket owner or an authorized user.

  • If the retention policy is locked, the policy cannot be deleted.

Can I configure a retention policy for specific objects in a bucket?

No, you cannot configure a retention policy for specific objects in a bucket. You can configure retention policies only at the bucket level. OSS does not support retention policies at the directory or object level.

How do I calculate the expiration date of an object protected by a retention policy?

To calculate the expiration date of an object protected by a retention policy, add the retention period specified in the retention policy to the date when the object was last modified. For example, if the retention period for a bucket is 10 days and an object in the bucket was last modified on February 15, 2022, the object expired on February 25, 2022.

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

  • If the bucket contains no objects, you can directly delete the bucket.

  • If the bucket contains objects and the retention period elapses, you can delete the bucket after you delete all objects in the bucket. If you delete the bucket without first deleting the objects in it, a deletion failure is prompted.

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

If my Alibaba Cloud account has overdue OSS payments, are objects that are protected within the retention period of the retention policy retained?

If your Alibaba Cloud account has overdue payments, Alibaba Cloud applies your retention policy based on the terms and conditions of your contract.

Can an authorized RAM user configure a retention policy?

Yes, an authorized RAM user can configure a retention policy. API operations related to retention policies are available. These API operations support RAM policies. RAM users to which relevant RAM policies are attached can create or delete a retention policy in the OSS console or by using OSS API operations or OSS SDKs.