-
Notifications
You must be signed in to change notification settings - Fork 6
/
list.go
76 lines (70 loc) · 2.02 KB
/
list.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
package piv
//go:generate mockgen -source=list.go -destination=../../mock/mock_pivservice.go -package=mock
import (
"crypto"
"crypto/x509"
"fmt"
"github.com/go-piv/piv-go/piv"
"github.com/smlx/piv-agent/internal/securitykey"
"go.uber.org/zap"
)
// SecurityKey is a simple interface for security keys allowing abstraction
// over the securitykey implementation, and allowing generation of mocks for
// testing.
type SecurityKey interface {
AttestationCertificate() (*x509.Certificate, error)
Card() string
Close() error
PrivateKey(s *securitykey.SigningKey) (crypto.PrivateKey, error)
Serial() uint32
SigningKeys() []securitykey.SigningKey
StringsGPG(string, string) ([]string, error)
StringsSSH() []string
}
func (p *KeyService) reloadSecurityKeys() error {
// try to clean up and reset state
for _, k := range p.securityKeys {
_ = k.Close()
}
p.securityKeys = nil
// open cards and load keys from scratch
cards, err := piv.Cards()
if err != nil {
return fmt.Errorf("couldn't get cards: %v", err)
}
for _, card := range cards {
sk, err := securitykey.New(card)
if err != nil {
p.log.Warn("couldn't get SecurityKey", zap.String("card", card),
zap.Error(err))
continue
}
p.securityKeys = append(p.securityKeys, sk)
}
if len(p.securityKeys) == 0 {
p.log.Warn("no valid security keys found")
}
return nil
}
// SecurityKeys returns a slice containing all available security keys.
func (p *KeyService) SecurityKeys() ([]SecurityKey, error) {
p.mu.Lock()
defer p.mu.Unlock()
var err error
// check if any securityKeys are cached, and if not then cache them
if len(p.securityKeys) == 0 {
if err = p.reloadSecurityKeys(); err != nil {
return nil, fmt.Errorf("couldn't reload security keys: %v", err)
}
}
// check they are healthy, and reload if not
for _, k := range p.securityKeys {
if _, err = k.AttestationCertificate(); err != nil {
if err = p.reloadSecurityKeys(); err != nil {
return nil, fmt.Errorf("couldn't reload security keys: %v", err)
}
break
}
}
return p.securityKeys, nil
}