Support BYOK for OSS storage driver
Change-Id: I423ad03e63bd38aded3abfcba49079ff2fbb3b74 Signed-off-by: Li Yi <denverdino@gmail.com>
This commit is contained in:
parent
40b7b5830a
commit
90bed67126
15 changed files with 1216 additions and 110 deletions
88
vendor/github.com/denverdino/aliyungo/oss/authenticate_callback.go
generated
vendored
Normal file
88
vendor/github.com/denverdino/aliyungo/oss/authenticate_callback.go
generated
vendored
Normal file
|
@ -0,0 +1,88 @@
|
|||
package oss
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/md5"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"encoding/base64"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type authenticationType struct {
|
||||
lock *sync.RWMutex
|
||||
certificate map[string]*rsa.PublicKey
|
||||
}
|
||||
|
||||
var (
|
||||
authentication = authenticationType{lock: &sync.RWMutex{}, certificate: map[string]*rsa.PublicKey{}}
|
||||
urlReg = regexp.MustCompile(`^http(|s)://gosspublic.alicdn.com/[0-9a-zA-Z]`)
|
||||
)
|
||||
|
||||
//验证OSS向业务服务器发来的回调函数。
|
||||
//该方法是并发安全的
|
||||
//pubKeyUrl 回调请求头中[x-oss-pub-key-url]一项,以Base64编码
|
||||
//reqUrl oss所发来请求的url,由path+query组成
|
||||
//reqBody oss所发来请求的body
|
||||
//authorization authorization为回调头中的签名
|
||||
func AuthenticateCallBack(pubKeyUrl, reqUrl, reqBody, authorization string) error {
|
||||
//获取证书url
|
||||
keyURL, err := base64.URLEncoding.DecodeString(pubKeyUrl)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
url := string(keyURL)
|
||||
//判断证书是否来自于阿里云
|
||||
if !urlReg.Match(keyURL) {
|
||||
return errors.New("certificate address error")
|
||||
}
|
||||
//获取文件名
|
||||
rs := []rune(url)
|
||||
filename := string(rs[strings.LastIndex(url, "/") : len(rs)-1])
|
||||
authentication.lock.RLock()
|
||||
certificate := authentication.certificate[filename]
|
||||
authentication.lock.RUnlock()
|
||||
//内存中没有证书,下载
|
||||
if certificate == nil {
|
||||
authentication.lock.Lock()
|
||||
res, err := http.Get(url)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
body, err := ioutil.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
block, _ := pem.Decode(body)
|
||||
if block == nil {
|
||||
return errors.New("certificate error")
|
||||
}
|
||||
pubKey, err := x509.ParsePKIXPublicKey(block.Bytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
certificate = pubKey.(*rsa.PublicKey)
|
||||
authentication.certificate[filename] = certificate
|
||||
authentication.lock.Unlock()
|
||||
}
|
||||
//证书准备完毕,开始验证
|
||||
//解析签名
|
||||
signature, err := base64.StdEncoding.DecodeString(authorization)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
hashed := md5.New()
|
||||
hashed.Write([]byte(reqUrl + "\n" + reqBody))
|
||||
if err := rsa.VerifyPKCS1v15(certificate, crypto.MD5, hashed.Sum(nil), signature); err != nil {
|
||||
return err
|
||||
}
|
||||
//验证通过
|
||||
return nil
|
||||
}
|
43
vendor/github.com/denverdino/aliyungo/oss/client.go
generated
vendored
43
vendor/github.com/denverdino/aliyungo/oss/client.go
generated
vendored
|
@ -57,12 +57,14 @@ type Owner struct {
|
|||
// Options struct
|
||||
//
|
||||
type Options struct {
|
||||
ServerSideEncryption bool
|
||||
Meta map[string][]string
|
||||
ContentEncoding string
|
||||
CacheControl string
|
||||
ContentMD5 string
|
||||
ContentDisposition string
|
||||
ServerSideEncryption bool
|
||||
ServerSideEncryptionKeyID string
|
||||
|
||||
Meta map[string][]string
|
||||
ContentEncoding string
|
||||
CacheControl string
|
||||
ContentMD5 string
|
||||
ContentDisposition string
|
||||
//Range string
|
||||
//Expires int
|
||||
}
|
||||
|
@ -72,6 +74,9 @@ type CopyOptions struct {
|
|||
CopySourceOptions string
|
||||
MetadataDirective string
|
||||
//ContentType string
|
||||
|
||||
ServerSideEncryption bool
|
||||
ServerSideEncryptionKeyID string
|
||||
}
|
||||
|
||||
// CopyObjectResult is the output from a Copy request
|
||||
|
@ -366,7 +371,7 @@ func (b *Bucket) Exists(path string) (exists bool, err error) {
|
|||
}
|
||||
|
||||
if err != nil {
|
||||
// We can treat a 403 or 404 as non existance
|
||||
// We can treat a 403 or 404 as non existence
|
||||
if e, ok := err.(*Error); ok && (e.StatusCode == 403 || e.StatusCode == 404) {
|
||||
return false, nil
|
||||
}
|
||||
|
@ -430,7 +435,7 @@ func (b *Bucket) Put(path string, data []byte, contType string, perm ACL, option
|
|||
func (b *Bucket) PutCopy(path string, perm ACL, options CopyOptions, source string) (*CopyObjectResult, error) {
|
||||
headers := make(http.Header)
|
||||
|
||||
headers.Set("x-oss-acl", string(perm))
|
||||
headers.Set("x-oss-object-acl", string(perm))
|
||||
headers.Set("x-oss-copy-source", source)
|
||||
|
||||
options.addHeaders(headers)
|
||||
|
@ -455,7 +460,7 @@ func (b *Bucket) PutReader(path string, r io.Reader, length int64, contType stri
|
|||
headers := make(http.Header)
|
||||
headers.Set("Content-Length", strconv.FormatInt(length, 10))
|
||||
headers.Set("Content-Type", contType)
|
||||
headers.Set("x-oss-acl", string(perm))
|
||||
headers.Set("x-oss-object-acl", string(perm))
|
||||
|
||||
options.addHeaders(headers)
|
||||
req := &request{
|
||||
|
@ -491,7 +496,10 @@ func (b *Bucket) PutFile(path string, file *os.File, perm ACL, options Options)
|
|||
|
||||
// addHeaders adds o's specified fields to headers
|
||||
func (o Options) addHeaders(headers http.Header) {
|
||||
if o.ServerSideEncryption {
|
||||
if len(o.ServerSideEncryptionKeyID) != 0 {
|
||||
headers.Set("x-oss-server-side-encryption", "KMS")
|
||||
headers.Set("x-oss-server-side-encryption-key-id", o.ServerSideEncryptionKeyID)
|
||||
} else if o.ServerSideEncryption {
|
||||
headers.Set("x-oss-server-side-encryption", "AES256")
|
||||
}
|
||||
if len(o.ContentEncoding) != 0 {
|
||||
|
@ -516,6 +524,13 @@ func (o Options) addHeaders(headers http.Header) {
|
|||
|
||||
// addHeaders adds o's specified fields to headers
|
||||
func (o CopyOptions) addHeaders(headers http.Header) {
|
||||
if len(o.ServerSideEncryptionKeyID) != 0 {
|
||||
headers.Set("x-oss-server-side-encryption", "KMS")
|
||||
headers.Set("x-oss-server-side-encryption-key-id", o.ServerSideEncryptionKeyID)
|
||||
} else if o.ServerSideEncryption {
|
||||
headers.Set("x-oss-server-side-encryption", "AES256")
|
||||
}
|
||||
|
||||
if len(o.MetadataDirective) != 0 {
|
||||
headers.Set("x-oss-metadata-directive", o.MetadataDirective)
|
||||
}
|
||||
|
@ -1100,7 +1115,7 @@ func (client *Client) setupHttpRequest(req *request) (*http.Request, error) {
|
|||
// body will be unmarshalled on it.
|
||||
func (client *Client) doHttpRequest(c *http.Client, hreq *http.Request, resp interface{}) (*http.Response, error) {
|
||||
|
||||
if true {
|
||||
if client.debug {
|
||||
log.Printf("%s %s ...\n", hreq.Method, hreq.URL.String())
|
||||
}
|
||||
hresp, err := c.Do(hreq)
|
||||
|
@ -1323,9 +1338,9 @@ func (b *Bucket) CopyLargeFileInParallel(sourcePath string, destPath string, con
|
|||
}
|
||||
|
||||
currentLength, err := b.GetContentLength(sourcePath)
|
||||
|
||||
log.Printf("Parallel Copy large file[size: %d] from %s to %s\n",currentLength, sourcePath, destPath)
|
||||
|
||||
|
||||
log.Printf("Parallel Copy large file[size: %d] from %s to %s\n", currentLength, sourcePath, destPath)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
22
vendor/github.com/denverdino/aliyungo/oss/regions.go
generated
vendored
22
vendor/github.com/denverdino/aliyungo/oss/regions.go
generated
vendored
|
@ -9,15 +9,25 @@ type Region string
|
|||
|
||||
// Constants of region definition
|
||||
const (
|
||||
Hangzhou = Region("oss-cn-hangzhou")
|
||||
Qingdao = Region("oss-cn-qingdao")
|
||||
Beijing = Region("oss-cn-beijing")
|
||||
Hongkong = Region("oss-cn-hongkong")
|
||||
Shenzhen = Region("oss-cn-shenzhen")
|
||||
Hangzhou = Region("oss-cn-hangzhou")
|
||||
Qingdao = Region("oss-cn-qingdao")
|
||||
Beijing = Region("oss-cn-beijing")
|
||||
Hongkong = Region("oss-cn-hongkong")
|
||||
Shenzhen = Region("oss-cn-shenzhen")
|
||||
Shanghai = Region("oss-cn-shanghai")
|
||||
Zhangjiakou = Region("oss-cn-zhangjiakou")
|
||||
Huhehaote = Region("oss-cn-huhehaote")
|
||||
|
||||
USWest1 = Region("oss-us-west-1")
|
||||
USEast1 = Region("oss-us-east-1")
|
||||
APSouthEast1 = Region("oss-ap-southeast-1")
|
||||
Shanghai = Region("oss-cn-shanghai")
|
||||
APNorthEast1 = Region("oss-ap-northeast-1")
|
||||
APSouthEast2 = Region("oss-ap-southeast-2")
|
||||
|
||||
MEEast1 = Region("oss-me-east-1")
|
||||
|
||||
EUCentral1 = Region("oss-eu-central-1")
|
||||
EUWest1 = Region("oss-eu-west-1")
|
||||
|
||||
DefaultRegion = Hangzhou
|
||||
)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue