服务端加密(Go SDK)
功能说明
用户可以使用普通方式上传、下载对象,也可以使用服务端加密方式进行上传、下载对象。
OBS支持服务端加密功能,使加密的行为在服务端进行。
用户可以根据自身的需求,使用不同的密钥管理方式来使用服务端加密功能。当前支持两种服务端加密方式: KMS托管密钥的服务端加密(SSE-KMS)和客户提供加密密钥的服务端加密(SSE-C)。上述两种方式都采用行业标准的AES256加密算法。
SSE-KMS方式,OBS使用KMS(Key Management Service)服务提供的密钥进行服务端加密。
SSE-C方式,OBS使用用户提供的密钥和密钥的MD5值进行服务端加密。
使用服务端加密,返回的ETag值不是对象的MD5值。无论是否使用服务端加密上传对象,请求消息头中加入Content-MD5参数时,OBS均会对对象进行MD5校验。
更多关于服务端加密的内容请参考服务端加密。
接口约束
- 您必须是桶拥有者或拥有上传对象的权限,才能上传对象。建议使用IAM或桶策略进行授权,如果使用IAM则需授予obs:object:PutObject权限,如果使用桶策略则需授予PutObject权限。相关授权方式介绍可参见OBS权限控制概述,配置方式详见使用IAM自定义策略、配置对象策略。
- OBS支持的Region与Endpoint的对应关系,详细信息请参见地区与终端节点。
方法定义
func (obsClient ObsClient) PutFile(input *PutFileInput, extensions...extensionOptions) (output *PutObjectOutput, err error)
支持接口
OBS Go SDK支持服务端加密的接口见下表:
OBS Go SDK接口方法 |
描述 |
支持加密类型 |
---|---|---|
ObsClient.PutObject |
上传对象时设置加密算法、密钥,对对象启用服务端加密。 |
SSE-KMS SSE-C |
ObsClient.PutFile |
上传文件时设置加密算法、密钥,对对象启用服务端加密。 |
SSE-KMS SSE-C |
ObsClient.GetObject |
下载对象时设置解密算法、密钥,用于解密对象。 |
SSE-C |
ObsClient.CopyObject |
|
SSE-KMS SSE-C |
ObsClient.GetObjectMetadata |
获取对象元数据时设置解密算法、密钥,用于解密对象。 |
SSE-C |
ObsClient.InitiateMultipartUpload |
初始化分段上传任务时设置加密算法、密钥,对分段上传任务最终生成的对象启用服务端加密。 |
SSE-KMS SSE-C |
ObsClient.UploadPart |
上传段时设置加密算法、密钥,对分段数据启用服务端加密。 |
SSE-C |
ObsClient.CopyPart |
|
SSE-C |
代码示例
本示例用于加密流式上传到examplebucket桶中的example/objectname对象
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 54 55 56 57 58 59 |
package main import ( "crypto/md5" "encoding/base64" "fmt" "os" "strings" obs "github.com/huaweicloud/huaweicloud-sdk-go-obs/obs" ) func main() { //推荐通过环境变量获取AKSK,这里也可以使用其他外部引入方式传入,如果使用硬编码可能会存在泄露风险。 //您可以登录访问管理控制台获取访问密钥AK/SK,获取方式请参见https://support.huaweicloud.com/usermanual-ca/ca_01_0003.html。 ak := os.Getenv("AccessKeyID") sk := os.Getenv("SecretAccessKey") // 【可选】如果使用临时AK/SK和SecurityToken访问OBS,同样建议您尽量避免使用硬编码,以降低信息泄露风险。您可以通过环境变量获取访问密钥AK/SK,也可以使用其他外部引入方式传入。 // securityToken := os.Getenv("SecurityToken") // endpoint填写Bucket对应的Endpoint, 这里以华北-北京四为例,其他地区请按实际情况填写。 endPoint := "https://obs.cn-north-4.myhuaweicloud.com" // 创建obsClient实例 // 如果使用临时AKSK和SecurityToken访问OBS,需要在创建实例时通过obs.WithSecurityToken方法指定securityToken值。 obsClient, err := obs.New(ak, sk, endPoint/*, obs.WithSecurityToken(securityToken)*/) if err != nil { fmt.Printf("Create obsClient error, errMsg: %s", err.Error()) } input := &obs.PutObjectInput{} // 指定存储桶名称 input.Bucket = "examplebucket" // 指定上传对象名,此处以 example/objectname 为例。 input.Key = "example/objectname" // 指定上传的内容 input.Body = strings.NewReader("Hello OBS") // 指定服务端加密头信息,此处以 obs.SseCHeader为例 key := os.Getenv("Key") digest := md5.New() digest.Write([]byte(key)) bodyHash := digest.Sum(nil) input.SseHeader = obs.SseCHeader{ Encryption: "AES256", Key: base64.StdEncoding.EncodeToString([]byte(key)), // 32byteslongsecretkeymustprovided KeyMD5: base64.StdEncoding.EncodeToString(bodyHash), } // 流式上传本地文件 output, err := obsClient.PutObject(input) if err == nil { fmt.Printf("Put object(%s) under the bucket(%s) successful!\n", input.Key, input.Bucket) fmt.Printf("RequestId:%s\n", output.RequestId) fmt.Printf("StorageClass:%s, ETag:%s\n", output.StorageClass, output.ETag) return } fmt.Printf("Put object(%s) under the bucket(%s) fail!\n", input.Key, input.Bucket) if obsError, ok := err.(obs.ObsError); ok { fmt.Println("An ObsError was found, which means your request sent to OBS was rejected with an error response.") fmt.Println(obsError.Error()) } else { fmt.Println("An Exception was found, which means the client encountered an internal problem when attempting to communicate with OBS, for example, the client was unable to access the network.") fmt.Println(err) } } |
本示例用于流式下载examplebucket桶中的example/objectname加密对象
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 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
package main import ( "crypto/md5" "encoding/base64" "fmt" "os" obs "github.com/huaweicloud/huaweicloud-sdk-go-obs/obs" ) func main() { // 您可以通过环境变量获取访问密钥AK/SK,也可以使用其他外部引入方式传入。如果使用硬编码可能会存在泄露风险。 // 您可以登录访问管理控制台获取访问密钥AK/SK,获取方式请参见https://support.huaweicloud.com/usermanual-ca/ca_01_0003.html ak := os.Getenv("AccessKeyID") sk := os.Getenv("SecretAccessKey") // 【可选】如果使用临时AK/SK和SecurityToken访问OBS,同样建议您尽量避免使用硬编码,以降低信息泄露风险。您可以通过环境变量获取访问密钥AK/SK,也可以使用其他外部引入方式传入。 // securityToken := os.Getenv("SecurityToken") // endpoint填写Bucket对应的Endpoint, 这里以华北-北京四为例,其他地区请按实际情况填写。 endPoint := "https://obs.cn-north-4.myhuaweicloud.com" // 创建obsClient实例 // 如果使用临时AKSK和SecurityToken访问OBS,需要在创建实例时通过obs.WithSecurityToken方法指定securityToken值。 obsClient, err := obs.New(ak, sk, endPoint/*, obs.WithSecurityToken(securityToken)*/) if err != nil { fmt.Printf("Create obsClient error, errMsg: %s", err.Error()) } input := &obs.GetObjectInput{} // 指定存储桶名称 input.Bucket = "examplebucket" // 指定下载对象,此处以 example/objectname 为例。 input.Key = "example/objectname" // 指定服务端加密头信息,此处以 obs.SseCHeader为例 key := os.Getenv("Key") digest := md5.New() digest.Write([]byte(key)) bodyHash := digest.Sum(nil) input.SseHeader = obs.SseCHeader{ Encryption: "AES256", Key: base64.StdEncoding.EncodeToString([]byte(key)), // 32byteslongsecretkeymustprovided KeyMD5: base64.StdEncoding.EncodeToString(bodyHash), } // 流式下载对象 output, err := obsClient.GetObject(input) if err == nil { // output.Body 在使用完毕后必须关闭,否则会造成连接泄漏。 defer output.Body.Close() fmt.Printf("Get object(%s) under the bucket(%s) successful!\n", input.Key, input.Bucket) fmt.Printf("StorageClass:%s, ETag:%s, ContentType:%s, ContentLength:%d, LastModified:%s\n", output.StorageClass, output.ETag, output.ContentType, output.ContentLength, output.LastModified) // 读取对象内容 p := make([]byte, 1024) var readErr error var readCount int for { readCount, readErr = output.Body.Read(p) if readCount > 0 { fmt.Printf("%s", p[:readCount]) } if readErr != nil { break } } return } fmt.Printf("List objects under the bucket(%s) fail!\n", input.Bucket) if obsError, ok := err.(obs.ObsError); ok { fmt.Println("An ObsError was found, which means your request sent to OBS was rejected with an error response.") fmt.Println(obsError.Error()) } else { fmt.Println("An Exception was found, which means the client encountered an internal problem when attempting to communicate with OBS, for example, the client was unable to access the network.") fmt.Println(err) } } |