-
Notifications
You must be signed in to change notification settings - Fork 174
Expand file tree
/
Copy pathkeys.go
More file actions
97 lines (86 loc) · 2.16 KB
/
keys.go
File metadata and controls
97 lines (86 loc) · 2.16 KB
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
package jwt
import (
"encoding/json"
"net/http"
"time"
"github.com/go-jose/go-jose/v4"
"github.com/stackrox/rox/pkg/sync"
"github.com/stackrox/rox/pkg/utils"
)
const (
httpTimeout = 10 * time.Second
)
// KeyGetter is the interface that all providers of JSON Web Keys should implement.
type KeyGetter interface {
// The key should be a type that go-jose understands. Valid types include:
// ed25519.PublicKey
// *rsa.PublicKey
// *ecdsa.PublicKey
// []byte
// jose.JSONWebKey
// *jose.JSONWebKey
Key(id string) interface{}
}
// A JWKSGetter gets trusted keys from a JSON Web Key Set (JWKS) URL.
type JWKSGetter struct {
url string
fetchOnce sync.Once
known map[string]*jose.JSONWebKey
}
// NewJWKSGetter creates a new KeyGetter that gets trusted keys from a JSON Web Key Set (JWKS) URL.
func NewJWKSGetter(url string) *JWKSGetter {
return &JWKSGetter{
url: url,
known: make(map[string]*jose.JSONWebKey),
}
}
// Key returns the key with the given ID, if it is in the set.
func (j *JWKSGetter) Key(id string) interface{} {
j.fetchOnce.Do(j.fetch)
key := j.known[id]
if key == nil {
return nil // note this is NOT equivalent to returning `key`, which is (*JSONWebKey)(nil), not the nil interface{}.
}
return key
}
func (j *JWKSGetter) fetch() {
cli := http.Client{
Timeout: httpTimeout,
}
resp, err := cli.Get(j.url)
if err != nil {
// TODO(cg)
log.Warnf("Couldn't get JWKS URL '%s': %s", j.url, err)
return
}
defer utils.IgnoreError(resp.Body.Close)
dec := json.NewDecoder(resp.Body)
var jwks jose.JSONWebKeySet
if err := dec.Decode(&jwks); err != nil {
// TODO(cg)
log.Warnf("Couldn't decode JWKS response: %s", err)
return
}
for _, jwk := range jwks.Keys {
jwkCopy := jwk
j.known[jwkCopy.KeyID] = &jwkCopy
}
}
type singleKeyStore struct {
keyID string
key interface{}
}
func (s *singleKeyStore) Key(id string) interface{} {
if id == s.keyID {
return s.key
}
log.Error("not found")
return nil
}
// NewSingleKeyStore returns a KeyGetter that allows obtaining a single key with a defined id.
func NewSingleKeyStore(key interface{}, keyID string) KeyGetter {
return &singleKeyStore{
keyID: keyID,
key: key,
}
}