forked from hashicorp/vault
-
Notifications
You must be signed in to change notification settings - Fork 1
/
path_config.go
189 lines (158 loc) · 5.55 KB
/
path_config.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
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
package transit
import (
"context"
"fmt"
"github.com/hashicorp/vault/helper/keysutil"
"github.com/hashicorp/vault/logical"
"github.com/hashicorp/vault/logical/framework"
)
func (b *backend) pathConfig() *framework.Path {
return &framework.Path{
Pattern: "keys/" + framework.GenericNameRegex("name") + "/config",
Fields: map[string]*framework.FieldSchema{
"name": &framework.FieldSchema{
Type: framework.TypeString,
Description: "Name of the key",
},
"min_decryption_version": &framework.FieldSchema{
Type: framework.TypeInt,
Description: `If set, the minimum version of the key allowed
to be decrypted. For signing keys, the minimum
version allowed to be used for verification.`,
},
"min_encryption_version": &framework.FieldSchema{
Type: framework.TypeInt,
Description: `If set, the minimum version of the key allowed
to be used for encryption; or for signing keys,
to be used for signing. If set to zero, only
the latest version of the key is allowed.`,
},
"deletion_allowed": &framework.FieldSchema{
Type: framework.TypeBool,
Description: "Whether to allow deletion of the key",
},
"exportable": &framework.FieldSchema{
Type: framework.TypeBool,
Description: `Enables export of the key. Once set, this cannot be disabled.`,
},
"allow_plaintext_backup": &framework.FieldSchema{
Type: framework.TypeBool,
Description: `Enables taking a backup of the named key in plaintext format. Once set, this cannot be disabled.`,
},
},
Callbacks: map[logical.Operation]framework.OperationFunc{
logical.UpdateOperation: b.pathConfigWrite,
},
HelpSynopsis: pathConfigHelpSyn,
HelpDescription: pathConfigHelpDesc,
}
}
func (b *backend) pathConfigWrite(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
name := d.Get("name").(string)
// Check if the policy already exists before we lock everything
p, _, err := b.lm.GetPolicy(ctx, keysutil.PolicyRequest{
Storage: req.Storage,
Name: name,
})
if err != nil {
return nil, err
}
if p == nil {
return logical.ErrorResponse(
fmt.Sprintf("no existing key named %s could be found", name)),
logical.ErrInvalidRequest
}
if !b.System().CachingDisabled() {
p.Lock(true)
}
defer p.Unlock()
resp := &logical.Response{}
persistNeeded := false
minDecryptionVersionRaw, ok := d.GetOk("min_decryption_version")
if ok {
minDecryptionVersion := minDecryptionVersionRaw.(int)
if minDecryptionVersion < 0 {
return logical.ErrorResponse("min decryption version cannot be negative"), nil
}
if minDecryptionVersion == 0 {
minDecryptionVersion = 1
resp.AddWarning("since Vault 0.3, transit key numbering starts at 1; forcing minimum to 1")
}
if minDecryptionVersion != p.MinDecryptionVersion {
if minDecryptionVersion > p.LatestVersion {
return logical.ErrorResponse(
fmt.Sprintf("cannot set min decryption version of %d, latest key version is %d", minDecryptionVersion, p.LatestVersion)), nil
}
p.MinDecryptionVersion = minDecryptionVersion
persistNeeded = true
}
}
minEncryptionVersionRaw, ok := d.GetOk("min_encryption_version")
if ok {
minEncryptionVersion := minEncryptionVersionRaw.(int)
if minEncryptionVersion < 0 {
return logical.ErrorResponse("min encryption version cannot be negative"), nil
}
if minEncryptionVersion != p.MinEncryptionVersion {
if minEncryptionVersion > p.LatestVersion {
return logical.ErrorResponse(
fmt.Sprintf("cannot set min encryption version of %d, latest key version is %d", minEncryptionVersion, p.LatestVersion)), nil
}
p.MinEncryptionVersion = minEncryptionVersion
persistNeeded = true
}
}
// Check here to get the final picture after the logic on each
// individually. MinDecryptionVersion will always be 1 or above.
if p.MinEncryptionVersion > 0 &&
p.MinEncryptionVersion < p.MinDecryptionVersion {
return logical.ErrorResponse(
fmt.Sprintf("cannot set min encryption/decryption values; min encryption version of %d must be greater than or equal to min decryption version of %d", p.MinEncryptionVersion, p.MinDecryptionVersion)), nil
}
allowDeletionInt, ok := d.GetOk("deletion_allowed")
if ok {
allowDeletion := allowDeletionInt.(bool)
if allowDeletion != p.DeletionAllowed {
p.DeletionAllowed = allowDeletion
persistNeeded = true
}
}
// Add this as a guard here before persisting since we now require the min
// decryption version to start at 1; even if it's not explicitly set here,
// force the upgrade
if p.MinDecryptionVersion == 0 {
p.MinDecryptionVersion = 1
persistNeeded = true
}
exportableRaw, ok := d.GetOk("exportable")
if ok {
exportable := exportableRaw.(bool)
// Don't unset the already set value
if exportable && !p.Exportable {
p.Exportable = exportable
persistNeeded = true
}
}
allowPlaintextBackupRaw, ok := d.GetOk("allow_plaintext_backup")
if ok {
allowPlaintextBackup := allowPlaintextBackupRaw.(bool)
// Don't unset the already set value
if allowPlaintextBackup && !p.AllowPlaintextBackup {
p.AllowPlaintextBackup = allowPlaintextBackup
persistNeeded = true
}
}
if !persistNeeded {
return nil, nil
}
if len(resp.Warnings) == 0 {
return nil, p.Persist(ctx, req.Storage)
}
return resp, p.Persist(ctx, req.Storage)
}
const pathConfigHelpSyn = `Configure a named encryption key`
const pathConfigHelpDesc = `
This path is used to configure the named key. Currently, this
supports adjusting the minimum version of the key allowed to
be used for decryption via the min_decryption_version parameter.
`