1 Star 0 Fork 0

litian/machine

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
awsauth.go 6.04 KB
一键复制 编辑 原始数据 按行查看 历史
// Package awsauth implements AWS request signing using Signed Signature Version 2,
// Signed Signature Version 3, and Signed Signature Version 4. Supports S3 and STS.
package awsauth
import (
"net/http"
"net/url"
"sync"
"time"
)
// Credentials stores the information necessary to authorize with AWS and it
// is from this information that requests are signed.
type Credentials struct {
AccessKeyID string
SecretAccessKey string
SecurityToken string `json:"Token"`
Expiration time.Time
}
// Sign signs a request bound for AWS. It automatically chooses the best
// authentication scheme based on the service the request is going to.
func Sign(req *http.Request, cred ...Credentials) *http.Request {
service, _ := serviceAndRegion(req.URL.Host)
sigVersion := awsSignVersion[service]
switch sigVersion {
case 2:
return Sign2(req, cred...)
case 3:
return Sign3(req, cred...)
case 4:
return Sign4(req, cred...)
case -1:
return SignS3(req, cred...)
}
return nil
}
// Sign4 signs a request with Signed Signature Version 4.
func Sign4(req *http.Request, cred ...Credentials) *http.Request {
signMutex.Lock()
defer signMutex.Unlock()
keys := chooseKeys(cred)
// Add the X-Amz-Security-Token header when using STS
if keys.SecurityToken != "" {
req.Header.Set("X-Amz-Security-Token", keys.SecurityToken)
}
prepareRequestV4(req)
meta := new(metadata)
// Task 1
hashedCanonReq := hashedCanonicalRequestV4(req, meta)
// Task 2
stringToSign := stringToSignV4(req, hashedCanonReq, meta)
// Task 3
signingKey := signingKeyV4(keys.SecretAccessKey, meta.date, meta.region, meta.service)
signature := signatureV4(signingKey, stringToSign)
req.Header.Set("Authorization", buildAuthHeaderV4(signature, meta, keys))
return req
}
// Sign3 signs a request with Signed Signature Version 3.
// If the service you're accessing supports Version 4, use that instead.
func Sign3(req *http.Request, cred ...Credentials) *http.Request {
signMutex.Lock()
defer signMutex.Unlock()
keys := chooseKeys(cred)
// Add the X-Amz-Security-Token header when using STS
if keys.SecurityToken != "" {
req.Header.Set("X-Amz-Security-Token", keys.SecurityToken)
}
prepareRequestV3(req)
// Task 1
stringToSign := stringToSignV3(req)
// Task 2
signature := signatureV3(stringToSign, keys)
// Task 3
req.Header.Set("X-Amzn-Authorization", buildAuthHeaderV3(signature, keys))
return req
}
// Sign2 signs a request with Signed Signature Version 2.
// If the service you're accessing supports Version 4, use that instead.
func Sign2(req *http.Request, cred ...Credentials) *http.Request {
signMutex.Lock()
defer signMutex.Unlock()
keys := chooseKeys(cred)
// Add the SecurityToken parameter when using STS
// This must be added before the signature is calculated
if keys.SecurityToken != "" {
v := url.Values{}
v.Set("SecurityToken", keys.SecurityToken)
augmentRequestQuery(req, v)
}
prepareRequestV2(req, keys)
stringToSign := stringToSignV2(req)
signature := signatureV2(stringToSign, keys)
values := url.Values{}
values.Set("Signature", signature)
augmentRequestQuery(req, values)
return req
}
// SignS3 signs a request bound for Amazon S3 using their custom
// HTTP authentication scheme.
func SignS3(req *http.Request, cred ...Credentials) *http.Request {
signMutex.Lock()
defer signMutex.Unlock()
keys := chooseKeys(cred)
// Add the X-Amz-Security-Token header when using STS
if keys.SecurityToken != "" {
req.Header.Set("X-Amz-Security-Token", keys.SecurityToken)
}
prepareRequestS3(req)
stringToSign := stringToSignS3(req)
signature := signatureS3(stringToSign, keys)
authHeader := "AWS " + keys.AccessKeyID + ":" + signature
req.Header.Set("Authorization", authHeader)
return req
}
// SignS3Url signs a GET request for a resource on Amazon S3 by appending
// query string parameters containing credentials and signature. You must
// specify an expiration date for these signed requests. After that date,
// a request signed with this method will be rejected by S3.
func SignS3Url(req *http.Request, expire time.Time, cred ...Credentials) *http.Request {
signMutex.Lock()
defer signMutex.Unlock()
keys := chooseKeys(cred)
stringToSign := stringToSignS3Url("GET", expire, req.URL.Path)
signature := signatureS3(stringToSign, keys)
qs := req.URL.Query()
qs.Set("AWSAccessKeyId", keys.AccessKeyID)
qs.Set("Signature", signature)
qs.Set("Expires", timeToUnixEpochString(expire))
req.URL.RawQuery = qs.Encode()
return req
}
// expired checks to see if the temporary credentials from an IAM role are
// within 4 minutes of expiration (The IAM documentation says that new keys
// will be provisioned 5 minutes before the old keys expire). Credentials
// that do not have an Expiration cannot expire.
func (k *Credentials) expired() bool {
if k.Expiration.IsZero() {
// Credentials with no expiration can't expire
return false
}
expireTime := k.Expiration.Add(-4 * time.Minute)
// if t - 4 mins is before now, true
if expireTime.Before(time.Now()) {
return true
} else {
return false
}
}
type metadata struct {
algorithm string
credentialScope string
signedHeaders string
date string
region string
service string
}
const (
envAccessKeyID = "AWS_ACCESS_KEY_ID"
envSecretAccessKey = "AWS_SECRET_ACCESS_KEY"
envSecurityToken = "AWS_SECURITY_TOKEN"
)
var (
awsSignVersion = map[string]int{
"autoscaling": 4,
"cloudfront": 4,
"cloudformation": 4,
"cloudsearch": 4,
"monitoring": 4,
"dynamodb": 4,
"ec2": 2,
"elasticmapreduce": 4,
"elastictranscoder": 4,
"elasticache": 2,
"glacier": 4,
"kinesis": 4,
"redshift": 4,
"rds": 4,
"sdb": 2,
"sns": 4,
"sqs": 4,
"s3": 4,
"elasticbeanstalk": 4,
"importexport": 2,
"iam": 4,
"route53": 3,
"elasticloadbalancing": 4,
"email": 3,
}
signMutex sync.Mutex
)
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/litian33/machine.git
git@gitee.com:litian33/machine.git
litian33
machine
machine
v0.2.0-rc1

搜索帮助