如何为OSS Python SDK配置访问凭证

重要

本文中含有需要您注意的重要提示信息,忽略该信息可能对您的业务造成影响,请务必仔细阅读。

使用Python SDK发起OSS请求,您需要配置访问凭证。阿里云服务会通过访问凭证验证您的身份信息和访问权限。您可以根据使用场景对认证和授权的要求,选择不同类型的访问凭证。

前提条件

  • 在配置访问凭证前,您需要安装OSS Python SDK。详情请参见安装

  • 需要注意使用的alibabacloud-credentials版本需大于或等于0.3.5,如果小于此版本会出现报错。

初始化凭证提供者

凭证提供者选型

OSS支持多种方式初始化凭证提供者,您可以根据使用场景对认证和授权的要求,选择对应的方式初始化凭证提供者。

凭证提供者初始化方式

适用场景

是否需要提供前置的AK或STS Token

底层实现基于的凭证

凭证有效期

凭证轮转或刷新方式

方式一:使用AK

部署运行在安全、稳定且不易受外部攻击的环境的应用程序,无需频繁轮转凭证就可以长期访问云服务

AK

长期

手动轮转

方式二:使用自动轮转的AK

部署运行在面临AK泄露风险的环境的应用程序,需要频繁轮转凭证才长期能访问云服务

AK

长期

自动轮转

方式三:使用STS Token

部署运行在不可信的环境的应用程序,希望能控制访问的有效期、权限

STS Token

临时

手动刷新

方式四:使用RAMRoleARN

需要授权访问云服务,例如跨阿里云账号访问云服务的应用程序

STS Token

临时

自动刷新

方式五:使用ECSRAMRole

部署运行在阿里云的ECS实例、ECI实例、容器服务Kubernetes版的Worker节点中的应用程序

STS Token

临时

自动刷新

方式六:使用OIDCRoleARN

部署运行在阿里云的容器服务Kubernetes版的Worker节点中的不可信应用程序

STS Token

临时

自动刷新

方式七:使用函数计算上下文中的Credentials

部署运行在阿里云函数计算中的应用程序的函数

STS Token

临时

无需刷新

方式八:使用CredentialsURI

需要通过外部系统获取访问凭证的应用程序

STS Token

临时

自动刷新

方式九:使用自定义访问凭证

如果以上凭证配置方式都不满足要求时,您可以自定义获取凭证的方式

自定义

自定义

自定义

自定义

方式一:使用AK

如果您的应用程序部署运行在安全、稳定且不易受外部攻击的环境中,需要长期访问您的OSS,且不能频繁轮转凭证时,您可以使用阿里云主账号或RAM用户的AK(Access Key ID、Access Key Secret)初始化凭证提供者。需要注意的是,该方式需要您手动维护一个AK,存在安全性风险和维护复杂度增加的风险。如何获取AK,请参见CreateAccessKey - 创建主账号或RAM用户访问密钥

环境变量

警告

阿里云账号拥有资源的全部权限,AK一旦泄露,会给系统带来巨大风险,不建议使用。推荐使用最小化授权的RAM用户的AK。

  1. 使用AK设置环境变量。

    Mac OS X/Linux/Unix

    export OSS_ACCESS_KEY_ID=<ALIBABA_CLOUD_ACCESS_KEY_ID>
    export OSS_ACCESS_KEY_SECRET=<ALIBABA_CLOUD_ACCESS_KEY_SECRET>

    Windows

    set OSS_ACCESS_KEY_ID=<ALIBABA_CLOUD_ACCESS_KEY_ID>
    set OSS_ACCESS_KEY_SECRET=<ALIBABA_CLOUD_ACCESS_KEY_SECRET>
  2. 使用环境变量来传递凭证信息。

    # -*- coding: utf-8 -*-
    import oss2
    from oss2.credentials import EnvironmentVariableCredentialsProvider
    
    # 使用环境变量中获取的RAM用户访问密钥配置访问凭证
    auth = oss2.ProviderAuthV4(EnvironmentVariableCredentialsProvider())
    
    # 使用auth进行后续操作...
    

静态凭证

您可以在代码中使用变量来引用凭证,这些变量在运行时会被环境变量、配置文件或其他外部数据源中的实际凭证值填充。

以下操作步骤以配置文件为例。

  1. 创建配置文件config.ini

    [configName]
    alibaba_cloud_access_key_id = <ALIBABA_CLOUD_ACCESS_KEY_ID>
    alibaba_cloud_access_key_secret = <ALIBABA_CLOUD_ACCESS_KEY_SECRET>
  2. 使用配置文件来传递凭证信息。

    # -*- coding: utf-8 -*-
    import oss2
    import configparser
    
    # 读取配置文件
    config = configparser.ConfigParser()
    # 假设config.ini位于脚本同级目录下
    config.read('config.ini')
    
    # 从配置文件中获取Access Key ID和Access Key Secret
    access_key_id = config.get('configName', 'alibaba_cloud_access_key_id')
    access_key_secret = config.get('configName', 'alibaba_cloud_access_key_secret')
    
    # 使用获取的RAM用户的访问密钥配置访问凭证
    auth = oss2.AuthV4(access_key_id, access_key_secret)
    
    # 使用auth进行后续操作...
    

方式二:使用自动轮转的AK

如果您的应用程序需要长期访问您的OSS,但部署运行的环境面临AK泄露的风险,需要频繁手动轮转(轮换)AK,您可以使用ClientKey初始化凭证提供者。该方式底层实现是AK。使用ClientKey后,密钥管理服务(KMS)可以对托管的RAM用户AK进行全自动的定期轮转,将静态的RAM用户AK动态化,从而降低AK泄漏的风险。除定期轮转外,KMS还支持立即轮转,在AK泄漏情况下快速更换AK。该方式无需您手动维护一个AK,从而降低安全性风险和维护复杂度增加的风险。如何获取ClientKey,请参见创建应用接入点

  1. 添加凭据客户端依赖。

    pip install aliyun-secret-manager-client
  2. 创建配置文件secretsmanager.properties

    # 访问凭据类型,固定为client_key
    credentials_type=client_key
    
    # 读取Client Key的解密密码:支持从环境变量或者文件读取,只需设置一种
    client_key_password_from_env_variable=<your client key private key password environment variable name>
    client_key_password_from_file_path=<your client key private key password file path>
    
    # Client Key的私钥文件路径
    client_key_private_key_path=<your client key private key file path>
    
    # 关联的KMS服务地域
    cache_client_region_id=[{"regionId":"<regionId>"}]
  3. 使用配置文件来传递凭证信息。

    # -*- coding: utf-8 -*-
    import json
    import oss2
    from oss2 import CredentialsProvider
    from oss2.credentials import Credentials
    from alibaba_cloud_secretsmanager_client.secret_manager_cache_client_builder import SecretManagerCacheClientBuilder
    
    
    class CredentialProviderWrapper(CredentialsProvider):
        def get_credentials(self):
            secret_cache_client = SecretManagerCacheClientBuilder.new_client()
            secret_info = secret_cache_client.get_secret_info("<secretName>")
            secret_value_json = json.loads(secret_info.secret_value)
            return Credentials(secret_value_json["AccessKeyId"], secret_value_json["AccessKeySecret"])
    
    
    credentials_provider = CredentialProviderWrapper()
    
    auth = oss2.ProviderAuthV4(credentials_provider)
    
    # 使用auth进行后续操作...
    

方式三:使用STS Token

如果您的应用程序需要临时访问OSS,细化访问控制,实时调整权限,以提高安全性和灵活性,您可以使用通过STS服务获取的临时身份凭证(Access Key ID、Access Key Secret和Security Token)初始化凭证提供者。需要注意的是,该方式需要您手动维护一个STS Token,存在安全性风险和维护复杂度增加的风险。如何获取STS Token,请参见AssumeRole - 获取扮演角色的临时身份凭证

  1. 使用临时身份凭证设置环境变量。

    Mac OS X/Linux/Unix

    export OSS_ACCESS_KEY_ID=<ALIBABA_CLOUD_ACCESS_KEY_ID>
    export OSS_ACCESS_KEY_SECRET=<ALIBABA_CLOUD_ACCESS_KEY_SECRET>
    export OSS_SESSION_TOKEN=<ALIBABA_CLOUD_SECURITY_TOKEN>

    Windows

    set OSS_ACCESS_KEY_ID=<ALIBABA_CLOUD_ACCESS_KEY_ID>
    set OSS_ACCESS_KEY_SECRET=<ALIBABA_CLOUD_ACCESS_KEY_SECRET>
    set OSS_SESSION_TOKEN=<ALIBABA_CLOUD_SECURITY_TOKEN>
  2. 通过环境变量来传递凭证信息。

    # -*- coding: utf-8 -*-
    import oss2
    from oss2.credentials import EnvironmentVariableCredentialsProvider
    
    # 使用环境变量中获取的STS Token配置访问凭证
    auth = oss2.ProviderAuthV4(EnvironmentVariableCredentialsProvider())
    
    # 使用auth进行后续操作...
    

方式四:使用RAMRoleARN

如果您的应用程序需要跨阿里云账号访问OSS,通过扮演RAM角色的方式进行权限管理,以确保安全性和灵活性,您可以使用RAMRoleARN初始化凭证提供者。该方式底层实现是STS Token。通过指定RAM角色的ARN(Alibabacloud Resource Name),Credentials工具会前往STS服务获取STS Token,并在会话到期前自动刷新STS Token。此外,您还可以通过为policy赋值来限制RAM角色到一个更小的权限集合。需要注意的是,该方式需要您提供一个AK,存在安全性风险和维护复杂度增加的风险。如何获取AK,请参见CreateAccessKey - 为RAM用户创建访问密钥。如何获取RAMRoleARN,请参见CreateRole - 创建角色

  1. 添加alibabacloud_credentials依赖。

    pip install alibabacloud_credentials
  2. 配置AK和RAMRoleARN作为访问凭证。

    # -*- coding: utf-8 -*-
    import oss2
    from alibabacloud_credentials.client import Client
    from alibabacloud_credentials.models import Config
    from oss2 import CredentialsProvider
    from oss2.credentials import Credentials
    import os
    
    
    class CredentialProviderWrapper(CredentialsProvider):
        def __init__(self, client):
            self.client = client
    
        def get_credentials(self):
            credential = self.client.get_credential()
            access_key_id = credential.access_key_id
            access_key_secret = credential.access_key_secret
            security_token = credential.security_token
            return Credentials(access_key_id, access_key_secret, security_token)
    
    
    config = Config(
        # 从环境变量中获取RAM用户的访问密钥(AccessKey ID和AccessKey Secret)
        access_key_id=os.getenv('ALIBABA_CLOUD_ACCESS_KEY_ID'),
        access_key_secret=os.getenv('ALIBABA_CLOUD_ACCESS_KEY_SECRET'),
        type='ram_role_arn',
        # 要扮演的RAM角色ARN,示例值:acs:ram::123456789012****:role/adminrole,可以通过环境变量ALIBABA_CLOUD_ROLE_ARN设置RoleArn
        role_arn='<RoleArn>',
        # 角色会话名称,可以通过环境变量ALIBABA_CLOUD_ROLE_SESSION_NAME设置RoleSessionName
        role_session_name='<RoleSessionName>',
        # 设置更小的权限策略,非必填。示例值:{"Statement": [{"Action": ["*"],"Effect": "Allow","Resource": ["*"]}],"Version":"1"}
        policy='<Policy>',
        # 设置角色会话有效期,非必填
        role_session_expiration=3600
    )
    
    
    cred = Client(config)
    
    credentials_provider = CredentialProviderWrapper(cred)
    
    auth = oss2.ProviderAuthV4(credentials_provider)
    
    # 使用auth进行后续操作...
    

方式五:使用ECSRAMRole

如果您的应用程序运行在ECS实例、ECI实例、容器服务Kubernetes版的Worker节点中,建议您使用ECSRAMRole初始化凭证提供者。该方式底层实现是STS Token。ECSRAMRole允许您将一个角色关联到ECS实例、ECI实例或容器服务 Kubernetes 版的Worker节点,实现在实例内部自动刷新STS Token。该方式无需您提供一个AK或STS Token,消除了手动维护AK或STS Token的风险。如何获取ECSRAMRole,请参见CreateRole - 创建角色

  1. 添加alibabacloud_credentials依赖。

    pip install alibabacloud_credentials
  2. 配置ECSRAMRole作为访问凭证。

    # -*- coding: utf-8 -*-
    import oss2
    from alibabacloud_credentials.client import Client
    from alibabacloud_credentials.models import Config
    from oss2 import CredentialsProvider
    from oss2.credentials import Credentials
    
    
    class CredentialProviderWrapper(CredentialsProvider):
        def __init__(self, client):
            self.client = client
    
        def get_credentials(self):
            credential = self.client.get_credential()
            access_key_id = credential.access_key_id
            access_key_secret = credential.access_key_secret
            security_token = credential.security_token
            return Credentials(access_key_id, access_key_secret, security_token)
    
    
    config = Config(
        type='ecs_ram_role',      # 访问凭证类型。固定为ecs_ram_role。
        role_name='<RoleName>'    # 为ECS授予的RAM角色的名称。可选参数。如果不设置,将自动检索。强烈建议设置,以减少请求。
    )
    
    
    cred = Client(config)
    
    credentials_provider = CredentialProviderWrapper(cred)
    
    auth = oss2.ProviderAuthV4(credentials_provider)
    
    # 使用auth进行后续操作...
    

方式六:使用OIDCRoleARN

容器服务Kubernetes版中设置了Worker节点RAM角色后,对应节点内的Pod中的应用也就可以像ECS上部署的应用一样,通过元数据服务(Meta Data Server)获取关联角色的STS Token。但如果容器集群上部署的是不可信的应用(比如部署您的客户提交的应用,代码也没有对您开放),您可能并不希望它们能通过元数据服务获取Worker节点关联实例RAM角色的STS Token。为了避免影响云上资源的安全,同时又能让这些不可信的应用安全地获取所需的STS Token,实现应用级别的权限最小化,您可以使用RRSA(RAM Roles for Service Account)功能。该方式底层实现是STS Token。阿里云容器集群会为不同的应用Pod创建和挂载相应的服务账户OIDC Token文件,并将相关配置信息注入到环境变量中,Credentials工具通过获取环境变量的配置信息,调用STS服务的AssumeRoleWithOIDC接口换取绑定角色的STS Token。该方式无需您提供一个AK或STS Token,消除了手动维护AK或STS Token的风险。详情请参见通过RRSA配置ServiceAccount的RAM权限实现Pod权限隔离

  1. 添加alibabacloud_credentials依赖。

    pip install alibabacloud_credentials
  1. 配置OIDCRoleArn作为访问凭证。

    # -*- coding: utf-8 -*-
    import oss2
    from alibabacloud_credentials.client import Client
    from alibabacloud_credentials.models import Config
    from oss2 import CredentialsProvider
    from oss2.credentials import Credentials
    import os
    
    
    class CredentialProviderWrapper(CredentialsProvider):
        def __init__(self, client):
            self.client = client
    
        def get_credentials(self):
            credential = self.client.get_credential()
            access_key_id = credential.access_key_id
            access_key_secret = credential.access_key_secret
            security_token = credential.security_token
            return Credentials(access_key_id, access_key_secret, security_token)
    
    
    config = Config(
        # 指定Credential类型,固定值为oidc_role_arn。
        type='oidc_role_arn',
        # RAM角色名称ARN,可以通过环境变量ALIBABA_CLOUD_ROLE_ARN设置RoleArn
        role_arn=os.environ.get('<RoleArn>'),
        # OIDC提供商ARN,可以通过环境变量ALIBABA_CLOUD_OIDC_PROVIDER_ARN设置OidcProviderArn
        oidc_provider_arn=os.environ.get('<OidcProviderArn>'),
        # OIDC Token文件路径,可以通过环境变量ALIBABA_CLOUD_OIDC_TOKEN_FILE设置OidcTokenFilePath
        oidc_token_file_path=os.environ.get('<OidcTokenFilePath>'),
        # 角色会话名称,可以通过环境变量ALIBABA_CLOUD_ROLE_SESSION_NAME设置RoleSessionName
        role_session_name='<RoleSessionName>',
        # 设置更小的权限策略,非必填。示例值:{"Statement": [{"Action": ["*"],"Effect": "Allow","Resource": ["*"]}],"Version":"1"}
        policy='<Policy>',
        # 设置session过期时间
        role_session_expiration=3600
    )
    
    
    cred = Client(config)
    
    credentials_provider = CredentialProviderWrapper(cred)
    
    auth = oss2.ProviderAuthV4(credentials_provider)
    
    # 使用auth进行后续操作...
    

方式七:使用函数计算上下文中的Credentials

如果您的应用程序的函数部署运行在函数计算中,您可以使用函数计算上下文中的Credentials初始化凭证提供者。该方式底层实现是STS Token。函数计算根据函数配置的角色,通过扮演服务角色,而获取一个STS Token,然后通过上下文中的参数Credentials将STS Token传递给您的应用程序。该STS Token的有效期为36小时,且不支持修改。函数的最大执行时间为24小时,因此,执行函数过程中,STS Token不会过期,您无需考虑刷新问题。该方式无需您提供一个AK或STS Token,消除了手动维护AK或STS Token的风险。如何授予函数计算访问OSS的权限,请参见授予函数计算访问其他云服务的权限

  1. 使用函数计算上下文中的Credentials初始化凭证提供者。

    # -*- coding: utf-8 -*-
    import oss2
    from oss2 import CredentialsProvider
    from oss2.credentials import Credentials
    
    
    def handler(event, context):
    
        class CredentialProviderWrapper(CredentialsProvider):
            def get_credentials(self):
                creds = context.credentials
                return Credentials(creds.access_key_id, creds.access_key_secret, creds.security_token)
    
        credentials_provider = CredentialProviderWrapper()
        auth = oss2.ProviderAuthV4(credentials_provider)
        # 使用auth进行后续操作...
    
        return 'success'
    

方式八:使用CredentialsURI

如果您的应用程序需要通过外部系统获取阿里云凭证,从而实现灵活的凭证管理和无密钥访问,您可以使用CredentialsURI初始化凭证提供者。该方式底层实现是STS Token。Credentials工具通过您提供的URI获取STS Token,完成凭证客户端初始化。该方式无需您提供一个AK或STS Token,消除了手动维护AK或STS Token的风险。需要注意的是,提供CredentialsURI响应的后端服务需要实现STS Token的自动刷新逻辑,确保您的应用程序始终能获取到有效凭证。

  1. 为了使Credentials工具正确解析和使用STS Token,URI必须遵循以下响应协议:

    • 响应状态码:200

    • 响应体结构:

      {
          "Code": "Success",
          "AccessKeySecret": "AccessKeySecret",
          "AccessKeyId": "AccessKeyId",
          "Expiration": "2021-09-26T03:46:38Z",
          "SecurityToken": "SecurityToken"
      }
  2. 添加alibabacloud_credentials依赖。

    pip install alibabacloud_credentials
  3. 配置URI凭证作为访问凭证。

    # -*- coding: utf-8 -*-
    import oss2
    from alibabacloud_credentials.client import Client
    from alibabacloud_credentials.models import Config
    from oss2 import CredentialsProvider
    from oss2.credentials import Credentials
    
    
    class CredentialProviderWrapper(CredentialsProvider):
        def __init__(self, client):
            self.client = client
    
        def get_credentials(self):
            credential = self.client.get_credential()
            access_key_id = credential.access_key_id
            access_key_secret = credential.access_key_secret
            security_token = credential.security_token
            return Credentials(access_key_id, access_key_secret, security_token)
    
    
    config = Config(
    	type='credentials_uri',
    	# 凭证的 URI,格式为http://local_or_remote_uri/,可以通过环境变量ALIBABA_CLOUD_CREDENTIALS_URI设置CredentialsUri
    	credentials_uri='<CredentialsUri>',
    )
    
    
    cred = Client(config)
    
    credentials_provider = CredentialProviderWrapper(cred)
    
    auth = oss2.ProviderAuthV4(credentials_provider)
    
    # 使用auth进行后续操作...
    

方式九:使用自定义访问凭证

如果以上凭证配置方式都不满足要求时,您还可以通过实现Credential Providers接口的方式,来自定义凭证提供方式。需要注意,如果底层实现是STS Token,需要提供凭证的更新支持。

# -*- coding: utf-8 -*-
import oss2
from oss2 import CredentialsProvider
from oss2.credentials import Credentials


class CredentialProviderWrapper(CredentialsProvider):
    def get_credentials(self):
        # TODO
        # 自定义访问凭证的获取方法

        # 返回长期凭证access_key_id, access_key_secrect
        return Credentials('<access_key_id>', '<access_key_secrect>')

        # 返回 临时凭证access_key_id, access_key_secrect, token
        # 对于临时凭证,需要根据过期时间,刷新凭证。
        # return Credentials('<access_key_id>', '<access_key_secrect>', '<token>');


credentials_provider = CredentialProviderWrapper()


auth = oss2.ProviderAuthV4(credentials_provider)

# 使用auth进行后续操作...

后续步骤

配置访问凭证后,您需要初始化OSSClient。详情请参见初始化