-
Notifications
You must be signed in to change notification settings - Fork 0
/
backend.go
164 lines (149 loc) · 4.11 KB
/
backend.go
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
package gmsm
import (
"context"
"io"
"strings"
"sync"
"github.com/hashicorp/errwrap"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/logical"
)
const backendHelp = `
The gmsm backend handles Chinese Shangmi(SM) operations on data in-transit.
Data sent to the backend are not stored.
`
// Minimum cache size for transit backend
const minCacheSize = 10
func Factory(ctx context.Context, conf *logical.BackendConfig) (logical.Backend, error) {
b, err := Backend(ctx, conf)
if err != nil {
return nil, err
}
if err := b.Setup(ctx, conf); err != nil {
return nil, err
}
return b, nil
}
func Backend(ctx context.Context, conf *logical.BackendConfig) (*backend, error) {
var b backend
b.Backend = &framework.Backend{
Help: backendHelp,
PathsSpecial: &logical.Paths{
SealWrapStorage: []string{
"archive/",
"policy/",
},
},
Paths: []*framework.Path{
// Rotate/Config needs to come before Keys
// as the handler is greedy
b.pathConfig(),
b.pathRotate(),
b.pathRewrap(),
b.pathKeys(),
b.pathListKeys(),
b.pathExportKeys(),
b.pathEncrypt(),
b.pathDecrypt(),
b.pathDatakey(),
b.pathRandom(),
b.pathHash(),
//b.pathHMAC(),
b.pathSign(),
b.pathVerify(),
b.pathBackup(),
b.pathRestore(),
b.pathTrim(),
b.pathCacheConfig(),
},
Secrets: []*framework.Secret{},
Invalidate: b.invalidate,
BackendType: logical.TypeLogical,
}
// determine cacheSize to use. Defaults to 0 which means unlimited
cacheSize := 0
useCache := !conf.System.CachingDisabled()
if useCache {
var err error
cacheSize, err = GetCacheSizeFromStorage(ctx, conf.StorageView)
if err != nil {
return nil, errwrap.Wrapf("Error retrieving cache size from storage: {{err}}", err)
}
if cacheSize != 0 && cacheSize < minCacheSize {
b.Logger().Warn("size %d is less than minimum %d. Cache size is set to %d", cacheSize, minCacheSize, minCacheSize)
cacheSize = minCacheSize
}
}
var err error
b.lm, err = NewLockManager(useCache, cacheSize)
if err != nil {
return nil, err
}
return &b, nil
}
type backend struct {
*framework.Backend
lm *LockManager
// Lock to make changes to any of the backend's cache configuration.
configMutex sync.RWMutex
cacheSizeChanged bool
}
func GetCacheSizeFromStorage(ctx context.Context, s logical.Storage) (int, error) {
size := 0
entry, err := s.Get(ctx, "config/cache")
if err != nil {
return 0, err
}
if entry != nil {
var storedCache configCache
if err := entry.DecodeJSON(&storedCache); err != nil {
return 0, err
}
size = storedCache.Size
}
return size, nil
}
// Update cache size and get policy
func (b *backend) GetPolicy(ctx context.Context, polReq PolicyRequest, rand io.Reader) (retP *Policy, retUpserted bool, retErr error) {
// Acquire read lock to read cacheSizeChanged
b.configMutex.RLock()
if b.lm.GetUseCache() && b.cacheSizeChanged {
var err error
currentCacheSize := b.lm.GetCacheSize()
storedCacheSize, err := GetCacheSizeFromStorage(ctx, polReq.Storage)
if err != nil {
return nil, false, err
}
if currentCacheSize != storedCacheSize {
err = b.lm.InitCache(storedCacheSize)
if err != nil {
return nil, false, err
}
}
// Release the read lock and acquire the write lock
b.configMutex.RUnlock()
b.configMutex.Lock()
defer b.configMutex.Unlock()
b.cacheSizeChanged = false
}
p, _, err := b.lm.GetPolicy(ctx, polReq, rand)
if err != nil {
return p, false, err
}
return p, true, nil
}
func (b *backend) invalidate(_ context.Context, key string) {
if b.Logger().IsDebug() {
b.Logger().Debug("invalidating key", "key", key)
}
switch {
case strings.HasPrefix(key, "policy/"):
name := strings.TrimPrefix(key, "policy/")
b.lm.InvalidatePolicy(name)
case strings.HasPrefix(key, "cache-config/"):
// Acquire the lock to set the flag to indicate that cache size needs to be refreshed from storage
b.configMutex.Lock()
defer b.configMutex.Unlock()
b.cacheSizeChanged = true
}
}