mirror of https://github.com/docker/docs.git
160 lines
4.9 KiB
Go
160 lines
4.9 KiB
Go
package api
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"fmt"
|
|
|
|
ctxu "github.com/docker/distribution/context"
|
|
"github.com/docker/notary/signer"
|
|
"github.com/docker/notary/signer/keys"
|
|
"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, algorithm *pb.Algorithm) (*pb.PublicKey, error) {
|
|
keyAlgo := algorithm.Algorithm
|
|
|
|
service := s.CryptoServices[keyAlgo]
|
|
|
|
logger := ctxu.GetLogger(ctx)
|
|
|
|
if service == nil {
|
|
logger.Error("CreateKey: unsupported algorithm: ", algorithm.Algorithm)
|
|
return nil, fmt.Errorf("algorithm %s not supported for create key", algorithm.Algorithm)
|
|
}
|
|
|
|
tufKey, err := service.Create("", "", keyAlgo)
|
|
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) {
|
|
_, service, err := FindKeyByID(s.CryptoServices, keyID)
|
|
|
|
logger := ctxu.GetLogger(ctx)
|
|
|
|
if err != nil {
|
|
logger.Errorf("DeleteKey: key %s not found", keyID.ID)
|
|
return nil, grpc.Errorf(codes.NotFound, "key %s not found", keyID.ID)
|
|
}
|
|
|
|
err = service.RemoveKey(keyID.ID)
|
|
logger.Info("DeleteKey: Deleted KeyID ", keyID.ID)
|
|
if err != nil {
|
|
switch err {
|
|
case keys.ErrInvalidKeyID:
|
|
logger.Errorf("DeleteKey: key %s not found", keyID.ID)
|
|
return nil, grpc.Errorf(codes.NotFound, "key %s not found", keyID.ID)
|
|
default:
|
|
logger.Error("DeleteKey: deleted key ", 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.PublicKey, error) {
|
|
_, service, 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)
|
|
}
|
|
|
|
tufKey := service.GetKey(keyID.ID)
|
|
if tufKey == 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.PublicKey{
|
|
KeyInfo: &pb.KeyInfo{
|
|
KeyID: &pb.KeyID{ID: tufKey.ID()},
|
|
Algorithm: &pb.Algorithm{Algorithm: tufKey.Algorithm()},
|
|
},
|
|
PublicKey: tufKey.Public(),
|
|
}, 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) {
|
|
tufKey, service, err := FindKeyByID(s.CryptoServices, sr.KeyID)
|
|
|
|
logger := ctxu.GetLogger(ctx)
|
|
|
|
if err != nil {
|
|
logger.Errorf("Sign: key %s not found", sr.KeyID.ID)
|
|
return nil, grpc.Errorf(codes.NotFound, "key %s not found", sr.KeyID.ID)
|
|
}
|
|
|
|
privKey, _, err := service.GetPrivateKey(tufKey.ID())
|
|
if err != nil {
|
|
logger.Errorf("Sign: key %s not found", sr.KeyID.ID)
|
|
return nil, grpc.Errorf(codes.NotFound, "key %s not found", sr.KeyID.ID)
|
|
}
|
|
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: tufKey.ID()},
|
|
Algorithm: &pb.Algorithm{Algorithm: tufKey.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
|
|
}
|