/
rpc_api.go
147 lines (119 loc) · 4.47 KB
/
rpc_api.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
package api
import (
"crypto/rand"
"fmt"
ctxu "github.com/docker/distribution/context"
"github.com/docker/notary/signer"
"github.com/docker/notary/trustmanager"
"github.com/docker/notary/tuf/data"
"golang.org/x/net/context"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
pb "github.com/docker/notary/proto"
)
//KeyManagementServer implements the KeyManagementServer grpc interface
type KeyManagementServer struct {
CryptoServices signer.CryptoServiceIndex
HealthChecker func() map[string]string
}
//SignerServer implements the SignerServer grpc interface
type SignerServer struct {
CryptoServices signer.CryptoServiceIndex
HealthChecker func() map[string]string
}
//CreateKey returns a PublicKey created using KeyManagementServer's SigningService
func (s *KeyManagementServer) CreateKey(ctx context.Context, req *pb.CreateKeyRequest) (*pb.PublicKey, error) {
service := s.CryptoServices[req.Algorithm]
logger := ctxu.GetLogger(ctx)
if service == nil {
logger.Error("CreateKey: unsupported algorithm: ", req.Algorithm)
return nil, fmt.Errorf("algorithm %s not supported for create key", req.Algorithm)
}
var tufKey data.PublicKey
var err error
tufKey, err = service.Create(req.Role, req.Gun, req.Algorithm)
if err != nil {
logger.Error("CreateKey: failed to create key: ", err)
return nil, grpc.Errorf(codes.Internal, "Key creation failed")
}
logger.Info("CreateKey: Created KeyID ", tufKey.ID())
return &pb.PublicKey{
KeyInfo: &pb.KeyInfo{
KeyID: &pb.KeyID{ID: tufKey.ID()},
Algorithm: &pb.Algorithm{Algorithm: tufKey.Algorithm()},
},
PublicKey: tufKey.Public(),
}, nil
}
//DeleteKey deletes they key associated with a KeyID
func (s *KeyManagementServer) DeleteKey(ctx context.Context, keyID *pb.KeyID) (*pb.Void, error) {
logger := ctxu.GetLogger(ctx)
// delete key ID from all services
for _, service := range s.CryptoServices {
if err := service.RemoveKey(keyID.ID); err != nil {
logger.Errorf("Failed to delete key %s", keyID.ID)
return nil, grpc.Errorf(codes.Internal, "Key deletion for KeyID %s failed", keyID.ID)
}
}
return &pb.Void{}, nil
}
//GetKeyInfo returns they PublicKey associated with a KeyID
func (s *KeyManagementServer) GetKeyInfo(ctx context.Context, keyID *pb.KeyID) (*pb.GetKeyInfoResponse, error) {
privKey, role, err := findKeyByID(s.CryptoServices, keyID)
logger := ctxu.GetLogger(ctx)
if err != nil {
logger.Errorf("GetKeyInfo: key %s not found", keyID.ID)
return nil, grpc.Errorf(codes.NotFound, "key %s not found", keyID.ID)
}
logger.Debug("GetKeyInfo: Returning PublicKey for KeyID ", keyID.ID)
return &pb.GetKeyInfoResponse{
KeyInfo: &pb.KeyInfo{
KeyID: &pb.KeyID{ID: privKey.ID()},
Algorithm: &pb.Algorithm{Algorithm: privKey.Algorithm()},
},
PublicKey: privKey.Public(),
Role: role,
}, nil
}
//CheckHealth returns the HealthStatus with the service
func (s *KeyManagementServer) CheckHealth(ctx context.Context, v *pb.Void) (*pb.HealthStatus, error) {
return &pb.HealthStatus{
Status: s.HealthChecker(),
}, nil
}
//Sign signs a message and returns the signature using a private key associate with the KeyID from the SignatureRequest
func (s *SignerServer) Sign(ctx context.Context, sr *pb.SignatureRequest) (*pb.Signature, error) {
privKey, _, err := findKeyByID(s.CryptoServices, sr.KeyID)
logger := ctxu.GetLogger(ctx)
switch err.(type) {
case trustmanager.ErrKeyNotFound:
logger.Errorf("Sign: key %s not found", sr.KeyID.ID)
return nil, grpc.Errorf(codes.NotFound, err.Error())
case nil:
break
default:
logger.Errorf("Getting key %s failed: %s", sr.KeyID.ID, err.Error())
return nil, grpc.Errorf(codes.Internal, err.Error())
}
sig, err := privKey.Sign(rand.Reader, sr.Content, nil)
if err != nil {
logger.Errorf("Sign: signing failed for KeyID %s on hash %s", sr.KeyID.ID, sr.Content)
return nil, grpc.Errorf(codes.Internal, "Signing failed for KeyID %s on hash %s", sr.KeyID.ID, sr.Content)
}
logger.Info("Sign: Signed ", string(sr.Content), " with KeyID ", sr.KeyID.ID)
signature := &pb.Signature{
KeyInfo: &pb.KeyInfo{
KeyID: &pb.KeyID{ID: privKey.ID()},
Algorithm: &pb.Algorithm{Algorithm: privKey.Algorithm()},
},
Algorithm: &pb.Algorithm{Algorithm: privKey.SignatureAlgorithm().String()},
Content: sig,
}
return signature, nil
}
//CheckHealth returns the HealthStatus with the service
func (s *SignerServer) CheckHealth(ctx context.Context, v *pb.Void) (*pb.HealthStatus, error) {
return &pb.HealthStatus{
Status: s.HealthChecker(),
}, nil
}