storj/certificate/endpoint.go
Egon Elbre e2d589f3cc certificate/rpcerrs: move logging sanitizer into certificate
Currently that is the only place using it and it's tied to zap
implementation. We don't want to have zap in common to reduce common
dependencies.

Change-Id: I72c064008f83ad3a8a3aa21944753208d4844c85
2020-10-14 14:11:36 +03:00

104 lines
3.1 KiB
Go

// 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/pb"
"storj.io/common/rpc/rpcpeer"
"storj.io/common/rpc/rpcstatus"
"storj.io/storj/certificate/authorization"
"storj.io/storj/certificate/rpcerrs"
)
// Endpoint implements pb.CertificatesServer.
type Endpoint struct {
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 *pb.SigningRequest) (_ *pb.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 &pb.SigningResponse{
Chain: signedChainBytes,
}, nil
}