mirror of https://github.com/docker/docs.git
Don't hardcode RSA algorithm
When we need to find a key from its ID, search all available signing services. There should only be a few, so this shouldn't have much overhead. This avoids the need to maintain a persistent mapping between key ID and the responsible signing service. Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
This commit is contained in:
parent
321b155596
commit
e7e9ef4a0d
|
|
@ -47,15 +47,7 @@ func KeyInfo(sigServices signer.SigningServiceIndex) http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
|
|
||||||
// TODO(diogo): call resolve method from KeyID -> KeyInfo
|
key, _, err := FindKeyByID(sigServices, &pb.KeyID{ID: vars["ID"]})
|
||||||
sigService := getSigningService(w, RSAAlgorithm, sigServices)
|
|
||||||
if sigService == nil {
|
|
||||||
// Error handled inside getSigningService
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
keyID := &pb.KeyID{ID: vars["ID"]}
|
|
||||||
key, err := sigService.KeyInfo(keyID)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
switch err {
|
switch err {
|
||||||
// If we received an ErrInvalidKeyID, the key doesn't exist, return 404
|
// If we received an ErrInvalidKeyID, the key doesn't exist, return 404
|
||||||
|
|
@ -109,11 +101,21 @@ func DeleteKey(sigServices signer.SigningServiceIndex) http.Handler {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(diogo): call resolve method from KeyID -> KeyInfo
|
_, sigService, err := FindKeyByID(sigServices, keyID)
|
||||||
sigService := getSigningService(w, RSAAlgorithm, sigServices)
|
|
||||||
if sigService == nil {
|
if err != nil {
|
||||||
// Error handled inside getSigningService
|
switch err {
|
||||||
return
|
// If we received an ErrInvalidKeyID, the key doesn't exist, return 404
|
||||||
|
case keys.ErrInvalidKeyID:
|
||||||
|
w.WriteHeader(http.StatusNotFound)
|
||||||
|
w.Write([]byte(err.Error()))
|
||||||
|
return
|
||||||
|
// If we received anything else, it is unexpected, and we return a 500
|
||||||
|
default:
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
w.Write([]byte(err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = sigService.DeleteKey(keyID)
|
_, err = sigService.DeleteKey(keyID)
|
||||||
|
|
@ -151,15 +153,19 @@ func Sign(sigServices signer.SigningServiceIndex) http.Handler {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(diogo): call resolve method from KeyID -> KeyInfo
|
_, sigService, err := FindKeyByID(sigServices, sigRequest.KeyID)
|
||||||
keyInfo := &pb.KeyInfo{KeyID: sigRequest.KeyID, Algorithm: &pb.Algorithm{Algorithm: RSAAlgorithm}}
|
if err == keys.ErrInvalidKeyID {
|
||||||
sigService := getSigningService(w, keyInfo.Algorithm.Algorithm, sigServices)
|
w.WriteHeader(http.StatusNotFound)
|
||||||
if sigService == nil {
|
w.Write([]byte(err.Error()))
|
||||||
// Error handled inside getSigningService
|
return
|
||||||
|
} else if err != nil {
|
||||||
|
// We got an unexpected error
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
w.Write([]byte(err.Error()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
signer, err := sigService.Signer(keyInfo)
|
signer, err := sigService.Signer(sigRequest.KeyID)
|
||||||
if err == keys.ErrInvalidKeyID {
|
if err == keys.ErrInvalidKeyID {
|
||||||
w.WriteHeader(http.StatusNotFound)
|
w.WriteHeader(http.StatusNotFound)
|
||||||
w.Write([]byte(err.Error()))
|
w.Write([]byte(err.Error()))
|
||||||
|
|
|
||||||
|
|
@ -52,9 +52,8 @@ func (s EdDSASigningService) KeyInfo(keyID *pb.KeyID) (*pb.PublicKey, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Signer returns a Signer for a specific KeyID
|
// Signer returns a Signer for a specific KeyID
|
||||||
func (s EdDSASigningService) Signer(keyInfo *pb.KeyInfo) (signer.Signer, error) {
|
func (s EdDSASigningService) Signer(keyID *pb.KeyID) (signer.Signer, error) {
|
||||||
// TODO(diogo): add verification of keyInfo.Algorithm to be ECDSA
|
key, err := s.KeyDB.GetKey(keyID)
|
||||||
key, err := s.KeyDB.GetKey(keyInfo.KeyID)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, keys.ErrInvalidKeyID
|
return nil, keys.ErrInvalidKeyID
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@ func TestSigner(t *testing.T) {
|
||||||
sigService := api.NewEdDSASigningService(&m)
|
sigService := api.NewEdDSASigningService(&m)
|
||||||
|
|
||||||
m.On("GetKey", fakeKeyID).Return(&keys.Key{}, nil).Once()
|
m.On("GetKey", fakeKeyID).Return(&keys.Key{}, nil).Once()
|
||||||
_, err := sigService.Signer(&pb.KeyInfo{KeyID: &pb.KeyID{ID: fakeKeyID}})
|
_, err := sigService.Signer(&pb.KeyID{ID: fakeKeyID})
|
||||||
|
|
||||||
m.Mock.AssertExpectations(t)
|
m.Mock.AssertExpectations(t)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/docker/notary/signer"
|
||||||
|
"github.com/docker/notary/signer/keys"
|
||||||
|
|
||||||
|
pb "github.com/docker/notary/proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
func FindKeyByID(sigServices signer.SigningServiceIndex, keyID *pb.KeyID) (*pb.PublicKey, signer.SigningService, error) {
|
||||||
|
for _, service := range sigServices {
|
||||||
|
key, err := service.KeyInfo(keyID)
|
||||||
|
if err == nil {
|
||||||
|
return key, service, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, nil, keys.ErrInvalidKeyID
|
||||||
|
}
|
||||||
|
|
@ -42,22 +42,20 @@ func (s *KeyManagementServer) CreateKey(ctx context.Context, algorithm *pb.Algor
|
||||||
|
|
||||||
//DeleteKey deletes they key associated with a KeyID
|
//DeleteKey deletes they key associated with a KeyID
|
||||||
func (s *KeyManagementServer) DeleteKey(ctx context.Context, keyID *pb.KeyID) (*pb.Void, error) {
|
func (s *KeyManagementServer) DeleteKey(ctx context.Context, keyID *pb.KeyID) (*pb.Void, error) {
|
||||||
// TODO(diogo): call resolve method from KeyID -> KeyInfo
|
_, service, err := FindKeyByID(s.SigServices, keyID)
|
||||||
keyInfo := &pb.KeyInfo{KeyID: keyID, Algorithm: &pb.Algorithm{Algorithm: RSAAlgorithm}}
|
|
||||||
service := s.SigServices[keyInfo.Algorithm.Algorithm]
|
|
||||||
|
|
||||||
if service == nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("algorithm %s not supported for delete key", keyInfo.Algorithm.Algorithm)
|
return nil, grpc.Errorf(codes.NotFound, "Invalid keyID: key %s not found", keyID.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := service.DeleteKey(keyInfo.KeyID)
|
_, err = service.DeleteKey(keyID)
|
||||||
log.Println("[Notary-signer DeleteKey] : Deleted KeyID ", keyInfo.KeyID.ID)
|
log.Println("[Notary-signer DeleteKey] : Deleted KeyID ", keyID.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
switch err {
|
switch err {
|
||||||
case keys.ErrInvalidKeyID:
|
case keys.ErrInvalidKeyID:
|
||||||
return nil, grpc.Errorf(codes.NotFound, "Invalid keyID: key %s not found", keyInfo.KeyID.ID)
|
return nil, grpc.Errorf(codes.NotFound, "Invalid keyID: key %s not found", keyID.ID)
|
||||||
default:
|
default:
|
||||||
return nil, grpc.Errorf(codes.Internal, "Key deletion for keyID %s failed", keyInfo.KeyID.ID)
|
return nil, grpc.Errorf(codes.Internal, "Key deletion for keyID %s failed", keyID.ID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -66,43 +64,39 @@ func (s *KeyManagementServer) DeleteKey(ctx context.Context, keyID *pb.KeyID) (*
|
||||||
|
|
||||||
//GetKeyInfo returns they PublicKey associated with a KeyID
|
//GetKeyInfo returns they PublicKey associated with a KeyID
|
||||||
func (s *KeyManagementServer) GetKeyInfo(ctx context.Context, keyID *pb.KeyID) (*pb.PublicKey, error) {
|
func (s *KeyManagementServer) GetKeyInfo(ctx context.Context, keyID *pb.KeyID) (*pb.PublicKey, error) {
|
||||||
// TODO(diogo): call resolve method from KeyID -> KeyInfo
|
_, service, err := FindKeyByID(s.SigServices, keyID)
|
||||||
keyInfo := &pb.KeyInfo{KeyID: keyID, Algorithm: &pb.Algorithm{Algorithm: RSAAlgorithm}}
|
|
||||||
service := s.SigServices[keyInfo.Algorithm.Algorithm]
|
|
||||||
|
|
||||||
if service == nil {
|
|
||||||
return nil, fmt.Errorf("algorithm %s not supported for get key info", keyInfo.Algorithm.Algorithm)
|
|
||||||
}
|
|
||||||
|
|
||||||
key, err := service.KeyInfo(keyInfo.KeyID)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, grpc.Errorf(codes.NotFound, "Invalid keyID: key %s not found", keyInfo.KeyID.ID)
|
return nil, grpc.Errorf(codes.NotFound, "Invalid keyID: key %s not found", keyID.ID)
|
||||||
}
|
}
|
||||||
log.Println("[Notary-signer GetKeyInfo] : Returning PublicKey for KeyID ", keyInfo.KeyID.ID)
|
|
||||||
|
key, err := service.KeyInfo(keyID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, grpc.Errorf(codes.NotFound, "Invalid keyID: key %s not found", keyID.ID)
|
||||||
|
}
|
||||||
|
log.Println("[Notary-signer GetKeyInfo] : Returning PublicKey for KeyID ", keyID.ID)
|
||||||
return key, nil
|
return key, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//Sign signs a message and returns the signature using a private key associate with the KeyID from the SignatureRequest
|
//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) {
|
func (s *SignerServer) Sign(ctx context.Context, sr *pb.SignatureRequest) (*pb.Signature, error) {
|
||||||
// TODO(diogo): call resolve method from KeyID -> KeyInfo
|
_, service, err := FindKeyByID(s.SigServices, sr.KeyID)
|
||||||
keyInfo := &pb.KeyInfo{KeyID: sr.KeyID, Algorithm: &pb.Algorithm{Algorithm: RSAAlgorithm}}
|
|
||||||
service := s.SigServices[keyInfo.Algorithm.Algorithm]
|
|
||||||
|
|
||||||
if service == nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("algorithm %s not supported for sign", keyInfo.Algorithm.Algorithm)
|
return nil, grpc.Errorf(codes.NotFound, "Invalid keyID: key %s not found", sr.KeyID.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Println("[Notary-signer Sign] : Signing ", string(sr.Content), " with KeyID ", keyInfo.KeyID.ID)
|
log.Println("[Notary-signer Sign] : Signing ", string(sr.Content), " with KeyID ", sr.KeyID.ID)
|
||||||
signer, err := service.Signer(keyInfo)
|
signer, err := service.Signer(sr.KeyID)
|
||||||
if err == keys.ErrInvalidKeyID {
|
if err == keys.ErrInvalidKeyID {
|
||||||
return nil, grpc.Errorf(codes.NotFound, "Invalid keyID: key not found")
|
return nil, grpc.Errorf(codes.NotFound, "Invalid keyID: key %s not found", sr.KeyID.ID)
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return nil, grpc.Errorf(codes.Internal, "Signing failed for keyID %s on hash %s", keyInfo.KeyID.ID, sr.Content)
|
return nil, grpc.Errorf(codes.Internal, "Signing failed for keyID %s on hash %s", sr.KeyID.ID, sr.Content)
|
||||||
}
|
}
|
||||||
|
|
||||||
signature, err := signer.Sign(sr)
|
signature, err := signer.Sign(sr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, grpc.Errorf(codes.Internal, "Signing failed for keyID %s on hash %s", keyInfo.KeyID.ID, sr.Content)
|
return nil, grpc.Errorf(codes.Internal, "Signing failed for keyID %s on hash %s", sr.KeyID.ID, sr.Content)
|
||||||
}
|
}
|
||||||
|
|
||||||
return signature, nil
|
return signature, nil
|
||||||
|
|
|
||||||
|
|
@ -139,9 +139,8 @@ func (s RSASigningService) KeyInfo(keyID *pb.KeyID) (*pb.PublicKey, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Signer returns a Signer for a specific KeyID
|
// Signer returns a Signer for a specific KeyID
|
||||||
func (s RSASigningService) Signer(keyInfo *pb.KeyInfo) (signer.Signer, error) {
|
func (s RSASigningService) Signer(keyID *pb.KeyID) (signer.Signer, error) {
|
||||||
// TODO(diogo): Add verification of keyInfo.Algorithm to be RSA.
|
key, ok := s.keys[keyID.ID]
|
||||||
key, ok := s.keys[keyInfo.KeyID.ID]
|
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, keys.ErrInvalidKeyID
|
return nil, keys.ErrInvalidKeyID
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ type SigningService interface {
|
||||||
KeyManager
|
KeyManager
|
||||||
|
|
||||||
// Signer returns a Signer for a given keyID
|
// Signer returns a Signer for a given keyID
|
||||||
Signer(keyID *pb.KeyInfo) (Signer, error)
|
Signer(keyID *pb.KeyID) (Signer, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SigningServiceIndex represents a mapping between a service algorithm string
|
// SigningServiceIndex represents a mapping between a service algorithm string
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue