/* Copyright (c) 2018 Vereign AG [https://www.vereign.com] This is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package handler import ( "encoding/base64" "strings" "code.vereign.com/code/viam-apis/errors" "code.vereign.com/code/viam-apis/log" "code.vereign.com/code/viam-apis/clientutils" "code.vereign.com/code/key-storage-agent/config" keyutils "code.vereign.com/code/key-storage-agent/utils" "code.vereign.com/code/viam-apis/authentication" "code.vereign.com/code/viam-apis/key-storage-agent/api" "golang.org/x/net/context" "google.golang.org/grpc/metadata" ) const ( keyToKeyIdTable = "authenticationKeyToKeyId" ) // Server represents the gRPC server type KeyStorageServerImpl struct { DataStorageUrl string CertPEM []byte KeyPEM []byte CaCertPEM []byte VereignCertPEM []byte MaxMessageSize int } var version = "undefined" func (s *KeyStorageServerImpl) CreateAuthentication(ctx context.Context) *authentication.Authentication { if md, ok := metadata.FromIncomingContext(ctx); ok { uuid := strings.Join(md["uuid"], "") session := strings.Join(md["session"], "") auth := &authentication.Authentication{ Uuid: uuid, Session: session, } return auth } return nil } func (s *KeyStorageServerImpl) GetKey(ctx context.Context, in *api.GetKeyRequest) (*api.GetKeyResponse, error) { auth := s.CreateAuthentication(ctx) client := keyutils.CreateDataStorageClient(auth) defer client.CloseClient() if in.KeyType == api.KeyType_CERTIFICATE && in.Uuid == "root" { key := &api.Key{} /*data, err := ioutil.ReadFile(s.VereignCertFilePath) if err != nil { log.Printf("Error: %v", err) getKeyResponse.StatusList = utils.AddStatus(getKeyResponse.StatusList, "400", api.StatusType_ERROR, "Can not get root certificate") return getKeyResponse, nil }*/ key.Content = s.VereignCertPEM key.Revoked = false getKeyResponse := &api.GetKeyResponse{Key: key} return getKeyResponse, nil } if in.KeyType == api.KeyType_KT_EMPTY { return nil, errors.NewUser("KeyType cannot be empty") } key := &api.Key{} hasData, _, err := client.GetData("keys", in.Uuid+"/"+api.KeyType.String(in.KeyType), key) if err != nil { log.Printf("grpc call GetData to DataStorage failed: %s", err) return nil, err } if !hasData { log.Println("No such key " + in.Uuid) return nil, errors.NewUser("No such key " + in.Uuid) } getKeyResponse := &api.GetKeyResponse{Key: key} return getKeyResponse, nil } func (s *KeyStorageServerImpl) SetKey(ctx context.Context, in *api.SetKeyRequest) (*api.SetKeyResponse, error) { auth := s.CreateAuthentication(ctx) client := keyutils.CreateDataStorageClient(auth) defer client.CloseClient() if in.Uuid == "root" { return nil, errors.NewUser("Can not set root CA keys") } if in.KeyType == api.KeyType_KT_EMPTY { return nil, errors.NewUser("KeyType cannot be empty") } key := &api.Key{} if config.Config.ReplaceKey == false { _, _, err := client.GetData("keys", in.Uuid+"/"+api.KeyType.String(in.KeyType), key) if err != nil { log.Printf("grpc call GetData to DataStorage failed: %s", err) return nil, errors.WrapInternalFormat(err, "grpc call GetData to DataStorage failed: %s", err) } if len(key.Content) > 0 { return nil, errors.NewUser("Key is already set") } } _, _, err := client.PutData("keys", in.Uuid+"/"+api.KeyType.String(in.KeyType), in.Key) if err != nil { return nil, err } if in.KeyType == api.KeyType_PUBLIC { keyContent := base64.StdEncoding.EncodeToString(in.Key.Content) _, _, err = client.PutString(keyToKeyIdTable, keyContent, in.Uuid) if err != nil { log.Printf("can't PutString: %s", err) return nil, errors.WrapInternal(err, "can't PutString") } } setKeyResponse := &api.SetKeyResponse{} return setKeyResponse, nil } func (s *KeyStorageServerImpl) ReserveKeyUUID(ctx context.Context, in *api.ReserveKeyUUIDRequest) (*api.ReserveKeyUUIDResponse, error) { auth := s.CreateAuthentication(ctx) client := keyutils.CreateDataStorageClient(auth) defer client.CloseClient() uuid, err := keyutils.GenerateUnusedUUID(client) if err != nil { log.Printf("Error: %v", err) return nil, err } emptyKey := &api.Key{ Content: []byte{}, } _, _, err = client.PutData("keys", uuid+"/"+api.KeyType.String(api.KeyType_PRIVATE), emptyKey) if err != nil { return nil, errors.WrapInternalFormat(err, "Could not store key %s", uuid+"/"+api.KeyType.String(api.KeyType_PRIVATE)) } _, _, err = client.PutData("keys", uuid+"/"+api.KeyType.String(api.KeyType_PUBLIC), emptyKey) if err != nil { return nil, errors.WrapInternalFormat(err, "Could not store key %s", uuid+"/"+api.KeyType.String(api.KeyType_PUBLIC)) } _, _, err = client.PutData("keys", uuid+"/"+api.KeyType.String(api.KeyType_CERTIFICATE), emptyKey) if err != nil { return nil, errors.WrapInternalFormat(err, "Could not store key %s", uuid+"/"+api.KeyType.String(api.KeyType_CERTIFICATE)) } reserveKeyUUIDResponse := &api.ReserveKeyUUIDResponse{Uuid: uuid} return reserveKeyUUIDResponse, nil } func (s *KeyStorageServerImpl) GetKeyId(ctx context.Context, in *api.GetKeyIdByKeyRequest) (*api.GetKeyIdByKeyResponse, error) { auth := s.CreateAuthentication(ctx) //in.PublicKey entitiesMagamentClient := keyutils.CreateEntitiesManagementClient(auth) defer entitiesMagamentClient.CloseClient() dataStorageClient := keyutils.CreateDataStorageClient(auth) defer dataStorageClient.CloseClient() keyIdResponse := &api.GetKeyIdByKeyResponse{} keyId, errorsString, err := dataStorageClient.GetString(keyToKeyIdTable, in.PublicKey) if err == nil && errorsString == "" && keyId != "" { keyIdResponse.KeyId = keyId return keyIdResponse, nil } else { if err != nil { return nil, err } else { return nil, errors.New("Can not get public key") } } entity, err := clientutils.GetLastEntity(entitiesMagamentClient, in.EntityUUID) if err != nil { return nil, err } for _, checkID := range entity.AuthenticationKeys { key := &api.Key{} hasData, errorsString, err := dataStorageClient.GetData("keys", checkID+"/"+api.KeyType_PUBLIC.String(), key) if err != nil { log.Printf("grpc call GetData to DataStorage failed: %s", err) return nil, err } if errorsString != "" { log.Printf("Error: %s", errorsString) return nil, errors.New(errorsString) } if !hasData { log.Println("No such checkID " + checkID) return nil, errors.New("No such checkID " + checkID) } keyFromStorage := base64.StdEncoding.EncodeToString(key.Content) if in.PublicKey != keyFromStorage { continue } _, _, err = dataStorageClient.PutString(keyToKeyIdTable, in.PublicKey, checkID) if err != nil { log.Printf("can't PutString: %s", err) return nil, err } keyIdResponse.KeyId = checkID return keyIdResponse, nil } //getKeyFromContent return keyIdResponse, nil } func (s *KeyStorageServerImpl) GetVersionKSA(ctx context.Context, in *api.GetVersionKSAMessage) (*api.GetVersionKSAResponseMessage, error) { log.Println("Version: " + version) return &api.GetVersionKSAResponseMessage{Version: version}, nil }