文档首页/ 对象存储服务 OBS/ 权限配置指南/ 典型场景配置案例/ 对其他账号授权/ 对象owner给桶owner授予对象的完全控制权限(对象owner和桶owner不属于同一个账号)
更新时间:2025-11-07 GMT+08:00
分享

对象owner给桶owner授予对象的完全控制权限(对象owner和桶owner不属于同一个账号)

本案例介绍当桶中对象来源于其他账号(非桶owner上传)时,桶owner如何获取对象的完全控制权限,即对象owner如何给桶owner授予对象的完全控制权限。例如账号A将对象a上传到账号B的桶b中,如何给账号B授予对象a的完全控制权限。

场景介绍

在使用云服务的过程中,您可能会遇到如下场景:

  • 跨账号上传对象后,基于业务诉求,桶owner需要访问和分析对象桶中的数据需要多个账号进行写入,之后桶owner需要对桶中数据进行访问和分析。例如跨账号的日志存储场景,假设您拥有3个账号,账号A、B用于运行业务生成日志,账号C用于收集和分析日志。账号A、B在使用云服务例如ELB、OBS等的过程中产生的日志文件会统一集中存储到账号C的日志存储桶中,之后账号C需要访问并分析这些日志文件。
  • 跨账号上传对象后,桶owner需管理对象由于业务需要,您的桶可能会涉及到多个账号进行写入,作为桶owner您需要对桶中对象进行统一管理。例如:1)其余账号上传时可能意外将对象设置为公开读,桶owner需要将对象访问权限修正为私有;2)其他账号上传对象后,为了节省成本桶owner需要删除或修改对象的存储类别,或者使用生命周期定期删除、转换对象的存储类别;3)其他账号上传对象后,桶owner需要检查对象是否合规,如不符合要求需要删除。

在以上场景中,桶中的对象虽然并非桶owner上传,但是基于业务和管理的需要,桶owner需要拥有对象的访问和管理权限,OBS支持使用对象ACL完成对象owner对桶owner的授权。

背景介绍

在进行授权操作前,您可能想要了解以下背景知识:

  • 桶owner(桶拥有者):创建存储桶的IAM用户。
  • 对象owner(对象拥有者):上传对象的IAM用户。当用户A向另一个用户B的桶中上传对象时,用户A是该对象的拥有者。这意味着即使桶属于用户B,用户B也默认没有权限访问或管理这个对象。
  • 对象ACL:一种访问控制方式,用于对象owner给其他账号配置对象的访问权限。了解更多请参见ACL
  • bucket-owner-full-control:是对象ACL的一个配置选项。如果您作为对象owner将对象的ACL配置为bucket-owner-full-control,那么就意味着您将该对象的完全控制权授予了桶owner(对象所在桶的桶owner)。授权后,桶owner可以为自己授予对象所有操作的权限,也可以授予其他用户对象的访问权限。了解更多请参见如何设置ACL
  • 桶策略:除了ACL,桶策略是另外一种OBS的权限管理方式,桶owner可以使用桶策略配置的桶及桶内对象的访问权限。了解更多请参见桶策略

方案架构

图1 对象owner授权其他账号对象的访问权限

图1所示,账号A上传对象a到账号B的桶b中,此时账号A是对象a的对象owner,账号B是桶b的桶owner:

  • 授权前:账号B访问对象a会失败,报错403权限不足,原因是对象默认只有对象owner才能访问。
  • 授权后:账号A将对象a的对象ACL配置为bucket-owner-full-control,配置后账号B拥有对象a的完全控制权。账号B自己可以访问和管理对象a,也可以授权其他用户访问对象a。

配置流程

图2 配置流程
表1 配置流程

序号

操作步骤

说明

详细操作

1

准备工作

桶owner通过桶策略为对象owner开通上传对象(obs:object:PutObject)的权限。

步骤一:准备工作

2

对象owner配置对象ACL

对象owner将对象的ACL设置为bucket-owner-full-control,配置后桶owner拥有对象的完全控制权

步骤二:为桶owner授予bucket-owner-full-control权限

3

【可选】桶owner使用桶策略授权

桶owner作为访问者时,若操作不涉及修改对象元数据或增删改对象标签,可直接访问或管理对象;若操作涉及上述内容,则需通过桶策略为自己授予对应的权限

如果访问者既不是桶owner也不是对象owner,那么桶owner需要使用桶策略为访问者授予对象操作对应的权限

【可选】步骤三:桶owner使用桶策略授权

4

访问或修改对象

桶owner或其他用户在授权后可正常访问或修改对象。

步骤四:访问或修改对象

步骤一:准备工作

为了使其他账号能够向您的桶中上传对象,您需要为这些账号授予上传权限,即桶owner需要为对象owner开通上传对象(obs:object:PutObject)的权限。例如账号A需要上传对象a到账号B的桶b中,那么账号B需要给账号A授予向桶b中上传对象的权限,如何授权请参考对其他账号下的IAM用户授予桶和桶内资源的访问权限

步骤二:为桶owner授予bucket-owner-full-control权限

您可以在上传对象时直接授权,此处以对象owner将名为exampleobject-a的对象,上传到名为examplebucket的桶中为例,在上传对象的同时将对象的ACL配置为owner bucket-owner-full-control。

您可以使用管理控制台、API、SDK、OBS Browser+、obsutil设置对象的ACL为bucket-owner-full-control:

【可选】步骤三:桶owner使用桶策略授权

  • 如果访问者是桶owner并且操作不包含修改对象元数据或者增删改对象标签,那么桶owner可以直接访问或管理对象,无需进行桶策略授权,请直接进行步骤四
  • 如果访问者是桶owner,并且操作包含表3 需要进行桶策略授权的操作中的操作,那么桶owner需要使用桶策略为自己授予相关操作的权限。
  • 如果访问者既不是桶owner也不是对象owner,那么桶owner需要使用桶策略为访问者授予相关操作的权限。
    表2 需要进行桶策略授权的操作

    操作人

    操作

    授权项

    桶owner

    修改对象元数据

    obs:object:modifyObjectMetadata

    新建/修改对象标签(未开启多版本)

    obs:object:putObjectTagging

    新建/修改对象标签(开启多版本)

    obs:object:putObjectVersionTagging

    删除对象标签(未开启多版本)

    obs:object:deleteObjectTagging

    删除对象标签(开启多版本)

    obs:object:deleteObjectVersionTagging

    非桶owner且非对象owner

    所有操作都需要桶策略授权

    各个对象操作对应的授权项

OBS支持使用管理控制台APISDKOBS Browser+obsutil设置桶策略,请以“桶owner”的身份执行本步骤。

此处以桶examplebucket的桶owner,使用桶策略授予exampleobject-a对象的对象元数据修改权限为例,提供以下示例代码供参考:

Java示例代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import com.obs.services.ObsClient;
import com.obs.services.exception.ObsException;
public class SetBucketPolicy001 {
    public static void main(String[] args) {
        // 此处的AK/SK是桶owner的AK/SK
        // 您可以通过环境变量获取访问密钥AK/SK,也可以使用其他外部引入方式传入。如果使用硬编码可能会存在泄露风险。
        // 您可以登录访问管理控制台获取访问密钥AK/SK
        String ak = System.getenv("ACCESS_KEY_ID");
        String sk = System.getenv("SECRET_ACCESS_KEY_ID");
        // 【可选】如果使用临时AK/SK和SecurityToken访问OBS,同样建议您尽量避免使用硬编码,以降低信息泄露风险。
        // 您可以通过环境变量获取访问密钥AK/SK/SecurityToken,也可以使用其他外部引入方式传入。
        // String securityToken = System.getenv("SECURITY_TOKEN");
        // endpoint填写桶所在的endpoint, 此处以华北-北京四为例,其他地区请按实际情况填写。
        String endPoint = "https://obs.cn-north-4.myhuaweicloud.com";
        // 您可以通过环境变量获取endPoint,也可以使用其他外部引入方式传入。
        //String endPoint = System.getenv("ENDPOINT");

        // 创建ObsClient实例
        // 使用永久AK/SK初始化客户端
        ObsClient obsClient = new ObsClient(ak, sk,endPoint);
        // 使用临时AK/SK和SecurityToken初始化客户端
        // ObsClient obsClient = new ObsClient(ak, sk, securityToken, endPoint);

        try {
            // 示例桶名
            String exampleBucket = "examplebucket";
            // 示例桶策略,Principal字段填写被授权用户的账号ID(domainId)和IAM用户ID(userId),例如要给桶owner授权,就填写桶owner的账号ID和IAM用户ID,要给其他用户授权就填写对应用户的ID
            String examplePolicy ="{\"Statement\":[{\"Principal\":{\"ID\":[\"domain/YourDomainId:user/YourUserId\"]},\"Effect\":\"Allow\",\"Action\":[\"ModifyObjectMetaData\"],\"Resource\":\""
                    + exampleBucket
                    + "/exampleobject-a\"}]}";
            obsClient.setBucketPolicy(exampleBucket, examplePolicy);
            System.out.println("SetBucketPolicy successfully");
        } catch (ObsException e) {
            System.out.println("SetBucketPolicy failed");
            // 请求失败,打印http状态码
            System.out.println("HTTP Code:" + e.getResponseCode());
            // 请求失败,打印服务端错误码
            System.out.println("Error Code:" + e.getErrorCode());
            // 请求失败,打印详细错误信息
            System.out.println("Error Message:" + e.getErrorMessage());
            // 请求失败,打印请求id
            System.out.println("Request ID:" + e.getErrorRequestId());
            System.out.println("Host ID:" + e.getErrorHostId());
            e.printStackTrace();
        } catch (Exception e) {
            System.out.println("SetBucketPolicy failed");
            // 其他异常信息打印
            e.printStackTrace();
        }
    }
}

Python示例代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
from obs import ObsClient
import os
import traceback
# 此处的AccessKeyID和SecretAccessKey是桶owner的AK/SK
# 推荐通过环境变量获取AKSK,这里也可以使用其他外部引入方式传入,如果使用硬编码可能会存在泄露风险
# 您可以登录访问管理控制台获取访问密钥AK/SK,获取方式请参见https://support.huaweicloud.com/usermanual-ca/ca_01_0003.html
ak = os.getenv("AccessKeyID")
sk = os.getenv("SecretAccessKey")
# 【可选】如果使用临时AKSK和SecurityToken访问OBS,则同样推荐通过环境变量获取
# security_token = os.getenv("SecurityToken")
# server填写Bucket对应的Endpoint, 这里以华北-北京四为例,其他地区请按实际情况填写
server = "https://obs.cn-north-4.myhuaweicloud.com"
# 创建obsClient实例
# 如果使用临时AKSK和SecurityToken访问OBS,需要在创建实例时通过security_token参数指定securityToken值
obsClient = ObsClient(access_key_id=ak, secret_access_key=sk, server=server)
try:
    bucketName = "examplebucket"
    # 示例桶策略,Principal字段填写被授权用户的账号ID(domainId)和IAM用户ID(userId),例如要给桶owner授权,就填写桶owner的账号ID和IAM用户ID,要给其他用户授权就填写对应用户的ID
    policyJSON = '{"Statement":[{"Sid":"ExampleStatementID1","Effect":"Allow","Principal":{"ID":["domain/**********:user/**********"]},"Action":["ModifyObjectMetaData"],"Resource":["examplebucket/exampleobject-a"]}]}'
    # 设置桶策略
    resp = obsClient.setBucketPolicy(bucketName, policyJSON)
    # 返回码为2xx时,接口调用成功,否则接口调用失败
    if resp.status < 300:
        print('Set Bucket Policy Succeeded')
        print('requestId:', resp.requestId)
    else:
        print('Set Bucket Policy Failed')
        print('requestId:', resp.requestId)
        print('errorCode:', resp.errorCode)
        print('errorMessage:', resp.errorMessage)
except:
    print('Set Bucket Policy Failed')
    print(traceback.format_exc())

步骤四:访问或修改对象

桶owner或其他用户在授权后可正常访问或修改对象。OBS支持使用管理控制台APISDKOBS Browser+obsutil访问或修改对象,请以“桶owner或其他被授权用户”的身份执行本步骤。

此处以桶owner修改examplebucket桶中exampleobject-a对象的存储类别(修改存储类别本质上是修改对象元数据)为例。

Java示例代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import com.obs.services.ObsClient;
import com.obs.services.exception.ObsException;
import com.obs.services.model.ObjectMetadata;
import com.obs.services.model.SetObjectMetadataRequest;
import java.util.HashMap;
public class SetObjectMetadata001 {
    public static void main(String[] args) {
        // 此处的AK/SK是被授予对象访问权限的用户的AK/SK,如果是桶owner被授权就是桶owner的AK/SK,如果是其他用户被授权,就是其他用户的AK/SK
        // 您可以通过环境变量获取访问密钥AK/SK,也可以使用其他外部引入方式传入。如果使用硬编码可能会存在泄露风险。
        // 您可以登录访问管理控制台获取访问密钥AK/SK
        String ak = System.getenv("ACCESS_KEY_ID");
        String sk = System.getenv("SECRET_ACCESS_KEY_ID");
        // 【可选】如果使用临时AK/SK和SecurityToken访问OBS,同样建议您尽量避免使用硬编码,以降低信息泄露风险。
        // 您可以通过环境变量获取访问密钥AK/SK/SecurityToken,也可以使用其他外部引入方式传入。
        // String securityToken = System.getenv("SECURITY_TOKEN");
        // endpoint填写桶所在的endpoint, 此处以华北-北京四为例,其他地区请按实际情况填写。
        String endPoint = "https://obs.cn-north-4.myhuaweicloud.com";
        // 您可以通过环境变量获取endPoint,也可以使用其他外部引入方式传入。
        //String endPoint = System.getenv("ENDPOINT");

        // 创建ObsClient实例
        // 使用永久AK/SK初始化客户端
        ObsClient obsClient = new ObsClient(ak, sk,endPoint);
        // 使用临时AK/SK和SecurityToken初始化客户端
        // ObsClient obsClient = new ObsClient(ak, sk, securityToken, endPoint);

        try {
            // 设置对象元数据
            SetObjectMetadataRequest request = new SetObjectMetadataRequest("examplebucket", "exampleobject-a");
            // 设置桶的存储类别为标准存储
            request.setObjectStorageClass(StorageClassEnum.WARM);
            ObjectMetadata metadata = obsClient.setObjectMetadata(request);
            System.out.println("setObjectMetadata successfully");
            System.out.println("UserMetadata:" + metadata.toString());
        } catch (ObsException e) {
            System.out.println("setObjectMetadata failed");
            // 请求失败,打印http状态码
            System.out.println("HTTP Code:" + e.getResponseCode());
            // 请求失败,打印服务端错误码
            System.out.println("Error Code:" + e.getErrorCode());
            // 请求失败,打印详细错误信息
            System.out.println("Error Message:" + e.getErrorMessage());
            // 请求失败,打印请求id
            System.out.println("Request ID:" + e.getErrorRequestId());
            System.out.println("Host ID:" + e.getErrorHostId());
            e.printStackTrace();
        } catch (Exception e) {
            System.out.println("setObjectMetadata failed");
            // 其他异常信息打印
            e.printStackTrace();
        }
    }
}

Python示例代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
from obs import SetObjectMetadataHeader
from obs import ObsClient
import os
import traceback

# 此处的AccessKeyID和SecretAccessKey是被授予对象访问权限的用户的AK/SK,如果是桶owner被授权就是桶owner的AK/SK,如果是其他用户被授权,就是其他用户的AK/SK
# 推荐通过环境变量获取AKSK,这里也可以使用其他外部引入方式传入,如果使用硬编码可能会存在泄露风险
# 您可以登录访问管理控制台获取访问密钥AK/SK,获取方式请参见https://support.huaweicloud.com/usermanual-ca/ca_01_0003.html
ak = os.getenv("AccessKeyID")
sk = os.getenv("SecretAccessKey")
# 【可选】如果使用临时AKSK和SecurityToken访问OBS,则同样推荐通过环境变量获取
# security_token = os.getenv("SecurityToken")
# server填写Bucket对应的Endpoint, 这里以华北-北京四为例,其他地区请按实际情况填写
server = "https://obs.cn-north-4.myhuaweicloud.com"
# 创建obsClient实例
# 如果使用临时AKSK和SecurityToken访问OBS,需要在创建实例时通过security_token参数指定securityToken值
obsClient = ObsClient(access_key_id=ak, secret_access_key=sk, server=server)
try:
    # 设置对象自定义元数据
    metadata = {'property1': 'property-value1', 'property2': 'property-value2'}
    # 设置对象附加头域
    headers = SetObjectMetadataHeader()
    # 【可选】待上传对象的MIME类型
    headers.contentType = "Your Content-Type"
    # 设置目标存储类别
    headers.storageClass = "WARM" 
    bucketName = "examplebucket"
    objectKey = "exampleobject-a"
    # 设置对象元数据
    resp = obsClient.setObjectMetadata(bucketName, objectKey, metadata, headers)

    # 返回码为2xx时,接口调用成功,否则接口调用失败
    if resp.status < 300:
        print('Set Object Metadata Succeeded')
        print('requestId:', resp.requestId)
    else:
        print('Set Object Metadata Failed')
        print('requestId:', resp.requestId)
        print('errorCode:', resp.errorCode)
        print('errorMessage:', resp.errorMessage)
except:
    print('Set Object Metadata Failed')
    print(traceback.format_exc())

相关文档