-
Notifications
You must be signed in to change notification settings - Fork 402
/
endpoint.go
105 lines (91 loc) · 3.17 KB
/
endpoint.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
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
package certificate
import (
"context"
"go.uber.org/zap"
"storj.io/common/identity"
"storj.io/common/rpc/rpcpeer"
"storj.io/common/rpc/rpcstatus"
"storj.io/storj/certificate/authorization"
"storj.io/storj/certificate/certificatepb"
"storj.io/storj/certificate/rpcerrs"
)
// Endpoint implements pb.CertificatesServer.
type Endpoint struct {
certificatepb.DRPCCertificatesUnimplementedServer
rpclog *rpcerrs.Log
log *zap.Logger
ca *identity.FullCertificateAuthority
authorizationDB *authorization.DB
minDifficulty uint16
}
// NewEndpoint creates a new certificate signing server.
func NewEndpoint(log *zap.Logger, ca *identity.FullCertificateAuthority, authorizationDB *authorization.DB, minDifficulty uint16) *Endpoint {
rpclog := rpcerrs.NewLog(&Error, log, rpcerrs.StatusMap{
&authorization.ErrNotFound: rpcstatus.Unauthenticated,
&authorization.ErrInvalidClaim: rpcstatus.InvalidArgument,
&authorization.ErrInvalidToken: rpcstatus.InvalidArgument,
&authorization.ErrAlreadyClaimed: rpcstatus.AlreadyExists,
})
return &Endpoint{
rpclog: rpclog,
log: log,
ca: ca,
authorizationDB: authorizationDB,
minDifficulty: minDifficulty,
}
}
// Sign signs the CA certificate of the remote peer's identity with the `certs.ca` certificate.
// Returns a certificate chain consisting of the remote peer's CA followed by the CA chain.
func (endpoint Endpoint) Sign(ctx context.Context, req *certificatepb.SigningRequest) (_ *certificatepb.SigningResponse, err error) {
defer mon.Task()(&ctx)(&err)
peer, err := rpcpeer.FromContext(ctx)
if err != nil {
msg := "error getting peer from context"
return nil, endpoint.rpclog.Error(msg, err)
}
peerIdent, err := identity.PeerIdentityFromPeer(peer)
if err != nil {
msg := "error getting peer identity"
return nil, endpoint.rpclog.Error(msg, err)
}
signedPeerCA, err := endpoint.ca.Sign(peerIdent.CA)
if err != nil {
msg := "error signing peer CA"
return nil, endpoint.rpclog.Error(msg, err)
}
signedChainBytes := [][]byte{signedPeerCA.Raw, endpoint.ca.Cert.Raw}
signedChainBytes = append(signedChainBytes, endpoint.ca.RawRestChain()...)
err = endpoint.authorizationDB.Claim(ctx, &authorization.ClaimOpts{
Req: req,
Peer: peer,
ChainBytes: signedChainBytes,
MinDifficulty: endpoint.minDifficulty,
})
if err != nil {
msg := "error claiming authorization"
return nil, endpoint.rpclog.Error(msg, err)
}
difficulty, err := peerIdent.ID.Difficulty()
if err != nil {
msg := "error checking difficulty"
return nil, endpoint.rpclog.Error(msg, err)
}
token, err := authorization.ParseToken(req.AuthToken)
if err != nil {
msg := "error parsing auth token"
return nil, endpoint.rpclog.Error(msg, err)
}
tokenFormatter := authorization.Authorization{
Token: *token,
}
endpoint.log.Info("certificate successfully signed",
zap.Stringer("Node ID", peerIdent.ID),
zap.Uint16("difficulty", difficulty),
zap.Stringer("truncated token", tokenFormatter),
)
return &certificatepb.SigningResponse{
Chain: signedChainBytes,
}, nil
}