/* 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 ( "fmt" "io/ioutil" "strings" "code.vereign.com/code/viam-apis/versions" "github.com/golang/protobuf/proto" "code.vereign.com/code/viam-apis/authentication" "code.vereign.com/code/viam-apis/data-storage-agent/client" "code.vereign.com/code/viam-apis/key-storage-agent/api" "code.vereign.com/code/viam-apis/utils" "golang.org/x/net/context" "google.golang.org/grpc/metadata" ) // Server represents the gRPC server type KeyStorageServerImpl struct { DataStorageUrl string CertFilePath string KeyFilePath string CaCertFilePath string VereignCertFilePath string VereignPrivateKeyFilePath string 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 := &client.DataStorageClientImpl{} client.SetUpClient(auth, s.DataStorageUrl, s.CertFilePath, s.KeyFilePath, s.CaCertFilePath, s.MaxMessageSize) defer client.CloseClient() getKeyResponse := &api.GetKeyResponse{} if in.KeyType == api.KeyType_CERTIFICATE && in.Uuid == "root" { key := &api.Key{} data, err := ioutil.ReadFile(s.VereignCertFilePath) if err != nil { getKeyResponse.StatusList = utils.AddStatus(getKeyResponse.StatusList, "400", api.StatusType_ERROR, "Can not get root certificate") return getKeyResponse, nil } key.Content = data key.Revoked = false getKeyResponse.Key = key return getKeyResponse, nil } if in.KeyType == api.KeyType_KT_EMPTY { getKeyResponse.StatusList = utils.AddStatus(getKeyResponse.StatusList, "400", api.StatusType_ERROR, "KeyType cannot be empty") return getKeyResponse, nil } data, _ := client.DoGetDataCall("keys", in.Uuid+"/"+api.KeyType.String(in.KeyType)) if data.Errors != "" { getKeyResponse.Key = nil getKeyResponse.StatusList = utils.AddStatus(getKeyResponse.StatusList, "500", api.StatusType_ERROR, data.Errors) } else { key := &api.Key{} proto.Unmarshal(data.Data.Data, key) getKeyResponse.Key = key } return getKeyResponse, nil } func (s *KeyStorageServerImpl) SetKey(ctx context.Context, in *api.SetKeyRequest) (*api.SetKeyResponse, error) { auth := s.CreateAuthentication(ctx) client := &client.DataStorageClientImpl{} client.SetUpClient(auth, s.DataStorageUrl, s.CertFilePath, s.KeyFilePath, s.CaCertFilePath, s.MaxMessageSize) defer client.CloseClient() setKeyResponse := &api.SetKeyResponse{} if in.Uuid == "root" { setKeyResponse.StatusList = utils.AddStatus(setKeyResponse.StatusList, "400", api.StatusType_ERROR, "Can not set root CA keys") return setKeyResponse, nil } if in.KeyType == api.KeyType_KT_EMPTY { setKeyResponse.StatusList = utils.AddStatus(setKeyResponse.StatusList, "400", api.StatusType_ERROR, "KeyType cannot be empty") return setKeyResponse, nil } data, _ := client.DoGetDataCall("keys", in.Uuid+"/"+api.KeyType.String(in.KeyType)) if data.Errors != "" { setKeyResponse.StatusList = utils.AddStatus(setKeyResponse.StatusList, "400", api.StatusType_ERROR, data.Errors) return setKeyResponse, nil } key := &api.Key{} proto.Unmarshal(data.Data.Data, key) if key != nil && key.Content != nil && len(key.Content) > 0 { setKeyResponse.StatusList = utils.AddStatus(setKeyResponse.StatusList, "400", api.StatusType_ERROR, "Key is already set") return setKeyResponse, nil } result, errors, err := client.DoPutDataCall("keys", in.Uuid+"/"+api.KeyType.String(in.KeyType), in.Key, versions.EntitiesManagementAgentApiVersion) setKeyResponse.StatusList = handlePutDataErrors(setKeyResponse.StatusList, errors, err) if setKeyResponse.StatusList == nil || len(setKeyResponse.StatusList) == 0 { setKeyResponse.StatusList = utils.AddStatus(setKeyResponse.StatusList, "200", api.StatusType_INFO, result) } return setKeyResponse, nil } func (s *KeyStorageServerImpl) ReserveKeyUUID(ctx context.Context, in *api.ReserveKeyUUIDRequest) (*api.ReserveKeyUUIDResponse, error) { auth := s.CreateAuthentication(ctx) client := &client.DataStorageClientImpl{} client.SetUpClient(auth, s.DataStorageUrl, s.CertFilePath, s.KeyFilePath, s.CaCertFilePath, s.MaxMessageSize) defer client.CloseClient() reserveKeyUUIDResponse := &api.ReserveKeyUUIDResponse{} uuid, err := generateUnusedUUID(client) if err != nil { reserveKeyUUIDResponse.StatusList = utils.AddStatus(reserveKeyUUIDResponse.StatusList, "500", api.StatusType_INFO, err.Error()) } emptyKey := &api.Key{ Content: []byte{}, } result, errors, err := client.DoPutDataCall("keys", uuid+"/"+api.KeyType.String(api.KeyType_PRIVATE), emptyKey, versions.EntitiesManagementAgentApiVersion) reserveKeyUUIDResponse.StatusList = handlePutDataErrors(reserveKeyUUIDResponse.StatusList, errors, err) if reserveKeyUUIDResponse.StatusList == nil || len(reserveKeyUUIDResponse.StatusList) == 0 { result, errors, err = client.DoPutDataCall("keys", uuid+"/"+api.KeyType.String(api.KeyType_PUBLIC), emptyKey, versions.EntitiesManagementAgentApiVersion) reserveKeyUUIDResponse.StatusList = handlePutDataErrors(reserveKeyUUIDResponse.StatusList, errors, err) } if reserveKeyUUIDResponse.StatusList == nil || len(reserveKeyUUIDResponse.StatusList) == 0 { result, errors, err = client.DoPutDataCall("keys", uuid+"/"+api.KeyType.String(api.KeyType_CERTIFICATE), emptyKey, versions.EntitiesManagementAgentApiVersion) reserveKeyUUIDResponse.StatusList = handlePutDataErrors(reserveKeyUUIDResponse.StatusList, errors, err) } if reserveKeyUUIDResponse.StatusList == nil || len(reserveKeyUUIDResponse.StatusList) == 0 { reserveKeyUUIDResponse.Uuid = uuid reserveKeyUUIDResponse.StatusList = utils.AddStatus(reserveKeyUUIDResponse.StatusList, "200", api.StatusType_INFO, result) } return reserveKeyUUIDResponse, nil } func (s *KeyStorageServerImpl) GetVersionKSA(ctx context.Context, in *api.GetVersionKSAMessage) (*api.GetVersionKSAResponseMessage, error) { fmt.Println("Version: " + version) return &api.GetVersionKSAResponseMessage{Version: version, Errors: ""}, nil }