-
Notifications
You must be signed in to change notification settings - Fork 277
/
repository_oidc_key_version.go
173 lines (164 loc) · 6.18 KB
/
repository_oidc_key_version.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
package kms
import (
"context"
"fmt"
"strings"
"github.com/hashicorp/boundary/internal/db"
"github.com/hashicorp/boundary/internal/errors"
wrapping "github.com/hashicorp/go-kms-wrapping"
)
// CreateOidcKeyVersion inserts into the repository and returns the new key
// version with its PrivateId. There are no valid options at this time.
func (r *Repository) CreateOidcKeyVersion(ctx context.Context, rkvWrapper wrapping.Wrapper, oidcKeyId string, key []byte, _ ...Option) (*OidcKeyVersion, error) {
const op = "kms.(Repository).CreateOidcKeyVersion"
if rkvWrapper == nil {
return nil, errors.New(errors.InvalidParameter, op, "missing root key version wrapper")
}
rootKeyVersionId := rkvWrapper.KeyID()
switch {
case !strings.HasPrefix(rootKeyVersionId, RootKeyVersionPrefix):
return nil, errors.New(errors.InvalidParameter, op, fmt.Sprintf("root key version id %s doesn't start with prefix %s", rootKeyVersionId, RootKeyVersionPrefix))
case rootKeyVersionId == "":
return nil, errors.New(errors.InvalidParameter, op, "missing root key version id")
}
if oidcKeyId == "" {
return nil, errors.New(errors.InvalidParameter, op, "missing oidc key id")
}
if len(key) == 0 {
return nil, errors.New(errors.InvalidParameter, op, "missing key")
}
kv := AllocOidcKeyVersion()
id, err := newOidcKeyVersionId()
if err != nil {
return nil, errors.Wrap(err, op)
}
kv.PrivateId = id
kv.RootKeyVersionId = rootKeyVersionId
kv.Key = key
kv.OidcKeyId = oidcKeyId
if err := kv.Encrypt(ctx, rkvWrapper); err != nil {
return nil, errors.Wrap(err, op)
}
var returnedKey interface{}
_, err = r.writer.DoTx(
ctx,
db.StdRetryCnt,
db.ExpBackoff{},
func(_ db.Reader, w db.Writer) error {
returnedKey = kv.Clone()
// no oplog entries for root key version
if err := w.Create(ctx, returnedKey); err != nil {
return errors.Wrap(err, op)
}
return nil
},
)
if err != nil {
return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s oidc key id", kv.OidcKeyId)))
}
return returnedKey.(*OidcKeyVersion), nil
}
// LookupOidcKeyVersion will look up a key version in the repository. If
// the key version is not found, it will return nil, nil.
func (r *Repository) LookupOidcKeyVersion(ctx context.Context, keyWrapper wrapping.Wrapper, privateId string, _ ...Option) (*OidcKeyVersion, error) {
const op = "kms.(Repository).LookupOidcKeyVersion"
if privateId == "" {
return nil, errors.New(errors.InvalidParameter, op, "missing private id")
}
if keyWrapper == nil {
return nil, errors.New(errors.InvalidParameter, op, "missing key wrapper")
}
k := AllocOidcKeyVersion()
k.PrivateId = privateId
if err := r.reader.LookupById(ctx, &k); err != nil {
return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId)))
}
if err := k.Decrypt(ctx, keyWrapper); err != nil {
return nil, errors.Wrap(err, op)
}
return &k, nil
}
// DeleteOidcKeyVersion deletes the key version for the provided id from the
// repository returning a count of the number of records deleted. All options
// are ignored.
func (r *Repository) DeleteOidcKeyVersion(ctx context.Context, privateId string, _ ...Option) (int, error) {
const op = "kms.(Repository).DeleteOidcKeyVersion"
if privateId == "" {
return db.NoRowsAffected, errors.New(errors.InvalidParameter, op, "missing private id")
}
k := AllocOidcKeyVersion()
k.PrivateId = privateId
if err := r.reader.LookupById(ctx, &k); err != nil {
return db.NoRowsAffected, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId)))
}
var rowsDeleted int
_, err := r.writer.DoTx(
ctx,
db.StdRetryCnt,
db.ExpBackoff{},
func(_ db.Reader, w db.Writer) (err error) {
dk := k.Clone()
// no oplog entries for the key version
rowsDeleted, err = w.Delete(ctx, dk)
if err != nil {
return errors.Wrap(err, op)
}
if rowsDeleted > 1 {
return errors.New(errors.MultipleRecords, op, "more than 1 resource would have been deleted")
}
return nil
},
)
if err != nil {
return db.NoRowsAffected, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId)))
}
return rowsDeleted, nil
}
// LatestOidcKeyVersion searches for the key version with the highest
// version number. When no results are found, it returns nil with an
// errors.RecordNotFound error.
func (r *Repository) LatestOidcKeyVersion(ctx context.Context, rkvWrapper wrapping.Wrapper, OidcKeyId string, _ ...Option) (*OidcKeyVersion, error) {
const op = "kms.(Repository).LatestOidcKeyVersion"
if OidcKeyId == "" {
return nil, errors.New(errors.InvalidParameter, op, "missing oidc key id")
}
if rkvWrapper == nil {
return nil, errors.New(errors.InvalidParameter, op, "missing root key version wrapper")
}
var foundKeys []*OidcKeyVersion
if err := r.reader.SearchWhere(ctx, &foundKeys, "oidc_key_id = ?", []interface{}{OidcKeyId}, db.WithLimit(1), db.WithOrder("version desc")); err != nil {
return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s", OidcKeyId)))
}
if len(foundKeys) == 0 {
return nil, errors.E(errors.WithCode(errors.RecordNotFound), errors.WithOp(op))
}
if err := foundKeys[0].Decrypt(ctx, rkvWrapper); err != nil {
return nil, errors.Wrap(err, op)
}
return foundKeys[0], nil
}
// ListOidcKeyVersions will lists versions of a key. Supports the WithLimit option.
func (r *Repository) ListOidcKeyVersions(ctx context.Context, rkvWrapper wrapping.Wrapper, OidcKeyId string, opt ...Option) ([]DekVersion, error) {
const op = "kms.(Repository).ListOidcKeyVersions"
if OidcKeyId == "" {
return nil, errors.New(errors.InvalidParameter, op, "missing oidc key id")
}
if rkvWrapper == nil {
return nil, errors.New(errors.InvalidParameter, op, "missing root key version wrapper")
}
var versions []*OidcKeyVersion
err := r.list(ctx, &versions, "oidc_key_id = ?", []interface{}{OidcKeyId}, opt...)
if err != nil {
return nil, errors.Wrap(err, op)
}
for i, k := range versions {
if err := k.Decrypt(ctx, rkvWrapper); err != nil {
return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("error decrypting key num %d", i)))
}
}
dekVersions := make([]DekVersion, 0, len(versions))
for _, version := range versions {
dekVersions = append(dekVersions, version)
}
return dekVersions, nil
}