Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit68ec532

Browse files
authored
feat: add jwt pkg (#14928)
- Adds a `jwtutils` package to be shared amongst the variouspackages in the codebase that make use of JWTs. It's intended to help usstandardize on one library instead of some implementations using`go-jose` and others using `golang-jwt`.The main reason we're converging on `go-jose` is due to its support forJWEs, `golang-jwt` also has a repo to handle it but it doesn't lookmaintained:https://github.com/golang-jwt/jwe
1 parent50d9206 commit68ec532

File tree

13 files changed

+1001
-122
lines changed

13 files changed

+1001
-122
lines changed

‎Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,8 @@ gen/mark-fresh:
537537
tailnet/tailnettest/coordinatormock.go\
538538
tailnet/tailnettest/coordinateemock.go\
539539
tailnet/tailnettest/multiagentmock.go\
540-
"
540+
"
541+
541542
for file in $$files; do
542543
echo "$$file"
543544
if [ ! -f "$$file" ]; then

‎coderd/cryptokeys/dbkeycache.go

Lines changed: 110 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,22 @@ package cryptokeys
22

33
import (
44
"context"
5+
"strconv"
56
"sync"
67
"time"
78

89
"golang.org/x/xerrors"
910

1011
"cdr.dev/slog"
1112
"github.com/coder/coder/v2/coderd/database"
12-
"github.com/coder/coder/v2/coderd/database/db2sdk"
13-
"github.com/coder/coder/v2/codersdk"
1413
"github.com/coder/quartz"
1514
)
1615

1716
// never represents the maximum value for a time.Duration.
1817
constnever=1<<63-1
1918

20-
//DBCache implements Keycache for callers with access to the database.
21-
typeDBCachestruct {
19+
//dbCache implements Keycache for callers with access to the database.
20+
typedbCachestruct {
2221
db database.Store
2322
feature database.CryptoKeyFeature
2423
logger slog.Logger
@@ -34,18 +33,34 @@ type DBCache struct {
3433
closedbool
3534
}
3635

37-
typeDBCacheOptionfunc(*DBCache)
36+
typeDBCacheOptionfunc(*dbCache)
3837

3938
funcWithDBCacheClock(clock quartz.Clock)DBCacheOption {
40-
returnfunc(d*DBCache) {
39+
returnfunc(d*dbCache) {
4140
d.clock=clock
4241
}
4342
}
4443

45-
//NewDBCache creates a new DBCache. Close should be called to
44+
//NewSigningCache creates a new DBCache. Close should be called to
4645
// release resources associated with its internal timer.
47-
funcNewDBCache(logger slog.Logger,db database.Store,feature database.CryptoKeyFeature,opts...func(*DBCache))*DBCache {
48-
d:=&DBCache{
46+
funcNewSigningCache(logger slog.Logger,db database.Store,feature database.CryptoKeyFeature,opts...func(*dbCache)) (SigningKeycache,error) {
47+
if!isSigningKeyFeature(feature) {
48+
returnnil,ErrInvalidFeature
49+
}
50+
51+
returnnewDBCache(logger,db,feature,opts...),nil
52+
}
53+
54+
funcNewEncryptionCache(logger slog.Logger,db database.Store,feature database.CryptoKeyFeature,opts...func(*dbCache)) (EncryptionKeycache,error) {
55+
if!isEncryptionKeyFeature(feature) {
56+
returnnil,ErrInvalidFeature
57+
}
58+
59+
returnnewDBCache(logger,db,feature,opts...),nil
60+
}
61+
62+
funcnewDBCache(logger slog.Logger,db database.Store,feature database.CryptoKeyFeature,opts...func(*dbCache))*dbCache {
63+
d:=&dbCache{
4964
db:db,
5065
feature:feature,
5166
clock:quartz.NewReal(),
@@ -56,23 +71,61 @@ func NewDBCache(logger slog.Logger, db database.Store, feature database.CryptoKe
5671
opt(d)
5772
}
5873

74+
// Initialize the timer. This will get properly initialized the first time we fetch.
5975
d.timer=d.clock.AfterFunc(never,d.clear)
6076

6177
returnd
6278
}
6379

64-
// Verifying returns the CryptoKey with the given sequence number, provided that
80+
func (d*dbCache)EncryptingKey(ctx context.Context) (idstring,keyinterface{},errerror) {
81+
if!isEncryptionKeyFeature(d.feature) {
82+
return"",nil,ErrInvalidFeature
83+
}
84+
85+
returnd.latest(ctx)
86+
}
87+
88+
func (d*dbCache)DecryptingKey(ctx context.Context,idstring) (keyinterface{},errerror) {
89+
if!isEncryptionKeyFeature(d.feature) {
90+
returnnil,ErrInvalidFeature
91+
}
92+
93+
returnd.sequence(ctx,id)
94+
}
95+
96+
func (d*dbCache)SigningKey(ctx context.Context) (idstring,keyinterface{},errerror) {
97+
if!isSigningKeyFeature(d.feature) {
98+
return"",nil,ErrInvalidFeature
99+
}
100+
101+
returnd.latest(ctx)
102+
}
103+
104+
func (d*dbCache)VerifyingKey(ctx context.Context,idstring) (keyinterface{},errerror) {
105+
if!isSigningKeyFeature(d.feature) {
106+
returnnil,ErrInvalidFeature
107+
}
108+
109+
returnd.sequence(ctx,id)
110+
}
111+
112+
// sequence returns the CryptoKey with the given sequence number, provided that
65113
// it is neither deleted nor has breached its deletion date. It should only be
66114
// used for verifying or decrypting payloads. To sign/encrypt call Signing.
67-
func (d*DBCache)Verifying(ctx context.Context,sequenceint32) (codersdk.CryptoKey,error) {
115+
func (d*dbCache)sequence(ctx context.Context,idstring) (interface{},error) {
116+
sequence,err:=strconv.ParseInt(id,10,32)
117+
iferr!=nil {
118+
returnnil,xerrors.Errorf("expecting sequence number got %q: %w",id,err)
119+
}
120+
68121
d.keysMu.RLock()
69122
ifd.closed {
70123
d.keysMu.RUnlock()
71-
returncodersdk.CryptoKey{},ErrClosed
124+
returnnil,ErrClosed
72125
}
73126

74127
now:=d.clock.Now()
75-
key,ok:=d.keys[sequence]
128+
key,ok:=d.keys[int32(sequence)]
76129
d.keysMu.RUnlock()
77130
ifok {
78131
returncheckKey(key,now)
@@ -82,67 +135,67 @@ func (d *DBCache) Verifying(ctx context.Context, sequence int32) (codersdk.Crypt
82135
deferd.keysMu.Unlock()
83136

84137
ifd.closed {
85-
returncodersdk.CryptoKey{},ErrClosed
138+
returnnil,ErrClosed
86139
}
87140

88-
key,ok=d.keys[sequence]
141+
key,ok=d.keys[int32(sequence)]
89142
ifok {
90143
returncheckKey(key,now)
91144
}
92145

93-
err:=d.fetch(ctx)
146+
err=d.fetch(ctx)
94147
iferr!=nil {
95-
returncodersdk.CryptoKey{},xerrors.Errorf("fetch: %w",err)
148+
returnnil,xerrors.Errorf("fetch: %w",err)
96149
}
97150

98-
key,ok=d.keys[sequence]
151+
key,ok=d.keys[int32(sequence)]
99152
if!ok {
100-
returncodersdk.CryptoKey{},ErrKeyNotFound
153+
returnnil,ErrKeyNotFound
101154
}
102155

103156
returncheckKey(key,now)
104157
}
105158

106-
//Signing returns the latest valid key for signing. A valid key is one that is
159+
//latest returns the latest valid key for signing. A valid key is one that is
107160
// both past its start time and before its deletion time.
108-
func (d*DBCache)Signing(ctx context.Context) (codersdk.CryptoKey,error) {
161+
func (d*dbCache)latest(ctx context.Context) (string,interface{},error) {
109162
d.keysMu.RLock()
110163

111164
ifd.closed {
112165
d.keysMu.RUnlock()
113-
returncodersdk.CryptoKey{},ErrClosed
166+
return"",nil,ErrClosed
114167
}
115168

116169
latest:=d.latestKey
117170
d.keysMu.RUnlock()
118171

119172
now:=d.clock.Now()
120173
iflatest.CanSign(now) {
121-
returndb2sdk.CryptoKey(latest),nil
174+
returnidSecret(latest)
122175
}
123176

124177
d.keysMu.Lock()
125178
deferd.keysMu.Unlock()
126179

127180
ifd.closed {
128-
returncodersdk.CryptoKey{},ErrClosed
181+
return"",nil,ErrClosed
129182
}
130183

131184
ifd.latestKey.CanSign(now) {
132-
returndb2sdk.CryptoKey(d.latestKey),nil
185+
returnidSecret(d.latestKey)
133186
}
134187

135188
// Refetch all keys for this feature so we can find the latest valid key.
136189
err:=d.fetch(ctx)
137190
iferr!=nil {
138-
returncodersdk.CryptoKey{},xerrors.Errorf("fetch: %w",err)
191+
return"",nil,xerrors.Errorf("fetch: %w",err)
139192
}
140193

141-
returndb2sdk.CryptoKey(d.latestKey),nil
194+
returnidSecret(d.latestKey)
142195
}
143196

144197
// clear invalidates the cache. This forces the subsequent call to fetch fresh keys.
145-
func (d*DBCache)clear() {
198+
func (d*dbCache)clear() {
146199
now:=d.clock.Now("DBCache","clear")
147200
d.keysMu.Lock()
148201
deferd.keysMu.Unlock()
@@ -158,7 +211,7 @@ func (d *DBCache) clear() {
158211

159212
// fetch fetches all keys for the given feature and determines the latest key.
160213
// It must be called while holding the keysMu lock.
161-
func (d*DBCache)fetch(ctx context.Context)error {
214+
func (d*dbCache)fetch(ctx context.Context)error {
162215
keys,err:=d.db.GetCryptoKeysByFeature(ctx,d.feature)
163216
iferr!=nil {
164217
returnxerrors.Errorf("get crypto keys by feature: %w",err)
@@ -189,22 +242,45 @@ func (d *DBCache) fetch(ctx context.Context) error {
189242
returnnil
190243
}
191244

192-
funccheckKey(key database.CryptoKey,now time.Time) (codersdk.CryptoKey,error) {
245+
funccheckKey(key database.CryptoKey,now time.Time) (interface{},error) {
193246
if!key.CanVerify(now) {
194-
returncodersdk.CryptoKey{},ErrKeyInvalid
247+
returnnil,ErrKeyInvalid
195248
}
196249

197-
returndb2sdk.CryptoKey(key),nil
250+
returnkey.DecodeString()
198251
}
199252

200-
func (d*DBCache)Close() {
253+
func (d*dbCache)Close()error {
201254
d.keysMu.Lock()
202255
deferd.keysMu.Unlock()
203256

204257
ifd.closed {
205-
return
258+
returnnil
206259
}
207260

208261
d.timer.Stop()
209262
d.closed=true
263+
returnnil
264+
}
265+
266+
funcisEncryptionKeyFeature(feature database.CryptoKeyFeature)bool {
267+
returnfeature==database.CryptoKeyFeatureWorkspaceApps
268+
}
269+
270+
funcisSigningKeyFeature(feature database.CryptoKeyFeature)bool {
271+
switchfeature {
272+
casedatabase.CryptoKeyFeatureTailnetResume,database.CryptoKeyFeatureOidcConvert:
273+
returntrue
274+
default:
275+
returnfalse
276+
}
277+
}
278+
279+
funcidSecret(k database.CryptoKey) (string,interface{},error) {
280+
key,err:=k.DecodeString()
281+
iferr!=nil {
282+
return"",nil,xerrors.Errorf("decode key: %w",err)
283+
}
284+
285+
returnstrconv.FormatInt(int64(k.Sequence),10),key,nil
210286
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp