合规保留策略

对象存储OSS支持WORM特性,允许用户以“不可删除、不可篡改”方式保存和使用数据,符合美国证券交易委员会(SEC)和金融业监管局(FINRA)的合规要求。

前提条件

  • 仅华东5(南京本地地域)以及美国(弗吉尼亚)地域不支持设置合规保留策略。

  • 确保需要设置合规保留策略的Bucket未开启版本控制。关于版本控制的更多信息,请参见版本控制介绍

使用场景

OSS提供强合规策略,您可以针对存储空间(Bucket)设置基于时间的合规保留策略。当策略锁定后,您可以在Bucket中上传和读取文件(Object),但是在Object的保留时间到期之前,任何用户都无法删除Object和策略。Object的保留时间到期后,才可以删除Object。OSS支持的WORM特性,适用于金融、保险、医疗、证券、日志数据等保审查等场景。您可以基于OSS搭建云上数据合规存储空间。 

说明

OSS是目前已通过Cohasset Associates审计认证的云服务,可满足严格的电子记录保留要求,例如SEC Rule 17a-4(f)、FINRA 4511、CFTC 1.31等合规要求。更多信息,请参见OSS Cohasset Assessment Report

注意事项

  • 目前仅支持针对Bucket级别设置合规保留策略。

  • 同一个Bucket中,不建议同时开通OSS-HDFS服务并设置保留策略。

    如果Bucket开通了OSS-HDFS服务并设置了保留策略,会导致通过OSS-HDFS提供的方式删除.dlsdata/目录下的数据时提示删除成功,但在保留策略有效期内OSS仍将保留该目录下被删除的数据,且在保留策略失效后也无法识别并删除.dlsdata/目录下相关的数据。

  • Bucket内的Object在合规保留策略生效期间,可通过设置生命周期规则进行存储类型转化,在保证合规性的前提下,降低存储成本。

规则说明

OSS允许添加一条基于时间的合规保留策略,保护周期为1天到70年。

假设您在2013年06月01日创建一个名为examplebucket的Bucket,并且在不同时间上传了file1.txt、file2.txt、file3.txt三个Object。随后,在2014年07月01日创建了保护周期为5年的合规保留策略。有关这三个Object的具体上传时间以及对应的Object到期时间如下: 

Object名称

上传时间

Object到期时间

file1.txt

2013年06月01日

2018年05月31日

file2.txt

2014年07月01日

2019年06月30日

file3.txt

2018年09月30日

2023年09月29日

  • 生效规则 

    当基于时间的合规保留策略创建后,该策略默认处于“InProgress”状态,且该状态的有效期为 24 小时。在有效期24小时内,此策略对应的Bucket资源处于保护状态。

    • 启动合规保留策略24小时内:如果该策略未提交锁定,则Bucket所有者以及授权用户可以删除该策略;如果该保留策略已提交锁定,则不允许删除该策略,且无法缩短策略保护周期,仅可以延长保护周期。

    • 启动合规保留策略24小时后:如果超过24小时该保留策略未提交锁定,则该策略自动失效。

    • Bucket内的数据处于被保护状态时,如果您尝试删除或修改这些数据,OSS API将返回409 FileImmutable的错误信息。

  • 删除规则 

    • 基于时间的合规保留策略是Bucket的一种Metadata属性。当删除某个Bucket时,该Bucket对应的合规保留策略以及访问策略也会被删除。因此当Bucket为空时,Bucket的所有者可以删除该Bucket,从而间接删除该Bucket的保留策略。

    • 启动保留策略24小时内,如果该保留策略未提交锁定,则Bucket所有者以及授权用户可以删除该策略。

    • 如果Bucket内有Object处于保护周期内,那么您将无法删除保留策略,同时也无法删除Bucket。

使用OSS控制台

  1. 登录OSS管理控制台

  2. 单击左侧导航栏的Bucket列表,然后单击目标Bucket名称。

  3. 在左侧导航栏,选择基础设置 > 保留策略。在保留策略区域单击设置

  4. 单击创建策略

  5. 创建策略对话框,设置合规保留策略的保留周期

    保留周期的取值范围为1天到70年。
  6. 单击确定

    策略创建后,状态显示为InProgress。此状态下,策略可被锁定删除
  7. 单击锁定

  8. 确认合规保留策略无误后,单击确定

    注意
    • 此时策略状态变为Locked,您仅可以单击编辑延长文件的保护周期,无法删除策略或缩短文件的保护周期。
    • 当Bucket内的数据处于被保护状态时,若您在控制台上尝试删除或修改这些数据,控制台上会返回该文件已被锁定,不可执行操作的错误提示。

使用阿里云SDK

以下仅列举常见SDK的设置合规保留策略的代码示例。关于其他SDK的设置合规保留策略代码示例,请参见SDK简介

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 {
        // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
        String accessKeyId = "yourAccessKeyId";
        String accessKeySecret = "yourAccessKeySecret";
        // 填写Bucket名称,例如examplebucket。
        String bucketName = "examplebucket";

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        try {
            // 创建InitiateBucketWormRequest对象。
            InitiateBucketWormRequest initiateBucketWormRequest = new InitiateBucketWormRequest(bucketName);
            // 指定Object保护天数为1天。
            initiateBucketWormRequest.setRetentionPeriodInDays(1);

            // 创建合规保留策略。
            InitiateBucketWormResult initiateBucketWormResult = ossClient.initiateBucketWorm(initiateBucketWormRequest);

            // 查看合规保留策略ID。
            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;

// 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
$accessKeyId = "yourAccessKeyId";
$accessKeySecret = "yourAccessKeySecret";
// Endpoint以杭州为例,其它Region请按实际情况填写。
$endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// 填写Bucket名称,例如examplebucket。
$bucket= "examplebucket";

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

try {
    // 创建合规保留策略,指定Object保护天数为30天。
    $wormId = $ossClient->initiateBucketWorm($bucket, 30);

    // 查看合规保留策略ID。
    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({
  // yourregion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
  region: 'yourregion',
  // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
  accessKeyId: 'yourAccessKeyId',
  accessKeySecret: 'yourAccessKeySecret'
});
// 创建合规保留策略。
async function initiateBucketWorm() {
 // 填写Bucket名称,例如examplebucket。
  const bucket = 'examplebucket'
  // 指定Object保护天数。
  const days = '30'
        const res = await client.initiateBucketWorm(bucket, days)
  console.log(res.wormId)
}

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

# 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
auth = oss2.Auth('yourAccessKeyId', 'yourAccessKeySecret')
# yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
# yourBucketName填写Bucket名称,例如examplebucket。
bucket = oss2.Bucket(auth, 'https://oss-cn-hangzhou.aliyuncs.com', 'examplebucket')

# 新建合规保留策略,并指定Object保护天数为1天。
result = bucket.init_bucket_worm(1)
# 查看合规保留策略ID。
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() {
    // 创建OSSClient实例。
    // yourEndpoint填写Bucket对应的Endpoint,以华东1(杭州)为例,填写为https://oss-cn-hangzhou.aliyuncs.com。其它Region请按实际情况填写。
    // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
    client, err := oss.New("yourEndpoint", "yourAccessKeyId", "yourAccessKeySecret")
    if err != nil {
        HandleError(err)
    }

    // 填写Bucket名称,例如examplebucket。
    bucketname := "examplebucket"
    // 指定Object保护天数为60天。
    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)
{
      /*初始化OSS账号信息。*/
      /*阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。*/
      std::string AccessKeyId = "yourAccessKeyId";
      std::string AccessKeySecret = "yourAccessKeySecret";
      /*yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。*/
      std::string Endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
      /*填写Bucket名称,例如examplebucket。*/
      std::string BucketName = "examplebucket";

      /*初始化网络等资源。*/
      InitializeSdk();

      ClientConfiguration conf;
      OssClient client(Endpoint, AccessKeyId, AccessKeySecret, conf);
  
        /*创建合规保留策略,指定Object保护天数为10天。*/
      auto outcome = client.InitiateBucketWorm(InitiateBucketWormRequest(BucketName, 10));

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

      /*释放网络等资源。*/
      ShutdownSdk();
      return 0;
}

使用命令行工具ossutil

关于使用ossutil设置合规保留策略的具体步骤,请参见worm(合规保留策略)

使用REST API

如果您的程序自定义要求较高,您可以直接发起REST API请求。直接发起REST API请求需要手动编写代码计算签名。更多信息,请参见InitiateBucketWorm

常见问题

  • 合规保留策略有哪些优势? 

    合规保留策略可提供数据合规存储,数据在合规保留策略保护周期内,任何用户都不能删除和修改。而通过RAM policy和Bucket Policy保护的数据,则存在被修改和删除可能。

  • 什么情况下需要配置合规保留策略?

    您需要长期存储且不允许修改或删除的重要数据,如医疗档案、技术文件、合同文书等,可以存放在指定的Bucket内,并通过开启合规保留策略保护您的重要数据。

  • 是否支持针对Object设置合规保留策略?

    目前仅支持针对Bucket设置保留策略,不支持针对目录以及单个对象设置合规保留策略。

  • 如何计算Object的保留时间?

    您可以根据Bucket内Object的最后更新时间加上合规保留策略设置的保留周期计算出Object的保留时间。例如,Bucket A已设置合规保留策略,保留时间是10天,Object的最后更新时间是2022年02月15日12:00,则该Object的保留时间为2022年02月25日12:01。

  • 如何删除已开启合规保留策略的Bucket ?

    • 如果该Bucket内未存储Object,可以直接删除该Bucket。

    • 如果该Bucket内已存储Object,且所有Object均已过了保护期,删除该Bucket会提示失败。此时,您可以先删除该Bucket内所有Object,再删除Bucket。

    • 如果该Bucket内已存储Object,且还有Object处于保护期内,无法删除该Bucket。

  • 如果OSS欠费,但仍有Object处于合规保留策略的保护期内,这些Object会被保留么?

    在未付款的情况下,阿里云会根据您签署的合同条款和条件,应用对应的数据保留策略。

  • 授权的RAM用户是否可以设置合规保留策略?

    合规保留策略相关API接口已全部对外开放,并且相关API操作已支持接入RAM policy。通过RAM Policy授权的RAM用户可以通过控制台、API、SDK等方式创建、删除合规保留策略。

阿里云首页 对象存储 OSS 相关技术圈