mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2024-01-19 02:48:24 +00:00
Clean up old signature hash pools
This commit is contained in:
parent
cdd817edf9
commit
98dcec0ee2
|
@ -33,6 +33,7 @@ type IdentityAccessManagement struct {
|
||||||
isAuthEnabled bool
|
isAuthEnabled bool
|
||||||
domain string
|
domain string
|
||||||
hashes map[string]*sync.Pool
|
hashes map[string]*sync.Pool
|
||||||
|
hashCounters map[string]*int32
|
||||||
hashMu sync.RWMutex
|
hashMu sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,8 +80,9 @@ func (action Action) getPermission() Permission {
|
||||||
|
|
||||||
func NewIdentityAccessManagement(option *S3ApiServerOption) *IdentityAccessManagement {
|
func NewIdentityAccessManagement(option *S3ApiServerOption) *IdentityAccessManagement {
|
||||||
iam := &IdentityAccessManagement{
|
iam := &IdentityAccessManagement{
|
||||||
domain: option.DomainName,
|
domain: option.DomainName,
|
||||||
hashes: make(map[string]*sync.Pool),
|
hashes: make(map[string]*sync.Pool),
|
||||||
|
hashCounters: make(map[string]*int32),
|
||||||
}
|
}
|
||||||
if option.Config != "" {
|
if option.Config != "" {
|
||||||
if err := iam.loadS3ApiConfigurationFromFile(option.Config); err != nil {
|
if err := iam.loadS3ApiConfigurationFromFile(option.Config); err != nil {
|
||||||
|
|
|
@ -32,6 +32,7 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
|
@ -463,36 +464,67 @@ func (iam *IdentityAccessManagement) doesPresignedSignatureMatch(hashedPayload s
|
||||||
return identity, s3err.ErrNone
|
return identity, s3err.ErrNone
|
||||||
}
|
}
|
||||||
|
|
||||||
// getSignature
|
|
||||||
func (iam *IdentityAccessManagement) getSignature(secretKey string, t time.Time, region string, service string, stringToSign string) string {
|
func (iam *IdentityAccessManagement) getSignature(secretKey string, t time.Time, region string, service string, stringToSign string) string {
|
||||||
|
pool := iam.getSignatureHashPool(secretKey, t, region, service)
|
||||||
|
h := pool.Get().(hash.Hash)
|
||||||
|
defer pool.Put(h)
|
||||||
|
|
||||||
|
h.Reset()
|
||||||
|
h.Write([]byte(stringToSign))
|
||||||
|
sig := hex.EncodeToString(h.Sum(nil))
|
||||||
|
|
||||||
|
return sig
|
||||||
|
}
|
||||||
|
|
||||||
|
func (iam *IdentityAccessManagement) getSignatureHashPool(secretKey string, t time.Time, region string, service string) *sync.Pool {
|
||||||
|
// Build a caching key for the pool.
|
||||||
date := t.Format(yyyymmdd)
|
date := t.Format(yyyymmdd)
|
||||||
hashID := "AWS4" + secretKey + "/" + date + "/" + region + "/" + service + "/" + "aws4_request"
|
hashID := "AWS4" + secretKey + "/" + date + "/" + region + "/" + service + "/" + "aws4_request"
|
||||||
|
|
||||||
|
// Try to find an existing pool and return it.
|
||||||
iam.hashMu.RLock()
|
iam.hashMu.RLock()
|
||||||
pool, ok := iam.hashes[hashID]
|
pool, ok := iam.hashes[hashID]
|
||||||
iam.hashMu.RUnlock()
|
iam.hashMu.RUnlock()
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
iam.hashMu.Lock()
|
iam.hashMu.Lock()
|
||||||
if pool, ok = iam.hashes[hashID]; !ok {
|
defer iam.hashMu.Unlock()
|
||||||
pool = &sync.Pool{
|
pool, ok = iam.hashes[hashID]
|
||||||
New: func() any {
|
|
||||||
signingKey := getSigningKey(secretKey, date, region, service)
|
|
||||||
return hmac.New(sha256.New, signingKey)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
iam.hashes[hashID] = pool
|
|
||||||
}
|
|
||||||
iam.hashMu.Unlock()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
h := pool.Get().(hash.Hash)
|
if ok {
|
||||||
h.Reset()
|
atomic.StoreInt32(iam.hashCounters[hashID], 1)
|
||||||
h.Write([]byte(stringToSign))
|
return pool
|
||||||
sig := hex.EncodeToString(h.Sum(nil))
|
}
|
||||||
pool.Put(h)
|
|
||||||
|
|
||||||
return sig
|
// Create a pool that returns HMAC hashers for the requested parameters to avoid expensive re-initializing
|
||||||
|
// of new instances on every request.
|
||||||
|
iam.hashes[hashID] = &sync.Pool{
|
||||||
|
New: func() any {
|
||||||
|
signingKey := getSigningKey(secretKey, date, region, service)
|
||||||
|
return hmac.New(sha256.New, signingKey)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
iam.hashCounters[hashID] = new(int32)
|
||||||
|
|
||||||
|
// Clean up unused pools automatically after one hour of inactivity
|
||||||
|
ticker := time.NewTicker(time.Hour)
|
||||||
|
go func() {
|
||||||
|
for range ticker.C {
|
||||||
|
old := atomic.SwapInt32(iam.hashCounters[hashID], 0)
|
||||||
|
if old == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ticker.Stop()
|
||||||
|
iam.hashMu.Lock()
|
||||||
|
delete(iam.hashes, hashID)
|
||||||
|
delete(iam.hashCounters, hashID)
|
||||||
|
iam.hashMu.Unlock()
|
||||||
|
}()
|
||||||
|
|
||||||
|
return iam.hashes[hashID]
|
||||||
}
|
}
|
||||||
|
|
||||||
func contains(list []string, elem string) bool {
|
func contains(list []string, elem string) bool {
|
||||||
|
|
|
@ -127,7 +127,8 @@ func TestCheckAdminRequestAuthType(t *testing.T) {
|
||||||
func BenchmarkGetSignature(b *testing.B) {
|
func BenchmarkGetSignature(b *testing.B) {
|
||||||
t := time.Now()
|
t := time.Now()
|
||||||
iam := IdentityAccessManagement{
|
iam := IdentityAccessManagement{
|
||||||
hashes: make(map[string]*sync.Pool),
|
hashes: make(map[string]*sync.Pool),
|
||||||
|
hashCounters: make(map[string]*int32),
|
||||||
}
|
}
|
||||||
|
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
|
|
Loading…
Reference in a new issue