/* 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 utils import ( "crypto/rand" "crypto/x509" "fmt" "io" "code.vereign.com/code/viam-apis/errors" "code.vereign.com/code/viam-apis/log" "encoding/pem" "io/ioutil" "code.vereign.com/code/key-storage-agent/config" "code.vereign.com/code/viam-apis/authentication" "code.vereign.com/code/viam-apis/clientutils" "code.vereign.com/code/viam-apis/data-storage-agent/client" dsclient "code.vereign.com/code/viam-apis/data-storage-agent/client" emclient "code.vereign.com/code/viam-apis/entities-management-agent/client" "code.vereign.com/code/viam-apis/key-storage-agent/api" ) var ErrNoData = errors.New("No data") func GenerateUnusedUUID(client *client.DataStorageClientImpl) (string, error) { count := 0 for { uuid, err := NewUUID() // check that uuid is not used key := &api.Key{} hasData, _, err := client.GetData("keys", uuid+"/"+api.KeyType.String(api.KeyType_PRIVATE), key) if err != nil { return "", errors.WrapInternal(err, "Could not generate unused UUID") } if !hasData { return uuid, nil } if count >= 10 { return "", errors.New("Could not generate unused UUID in 10 tries") } count++ } } //TODO create one single function to create UUIDs func NewUUID() (string, error) { uuid := make([]byte, 16) n, err := io.ReadFull(rand.Reader, uuid) if n != len(uuid) || err != nil { return "", err } uuid[8] = uuid[8]&^0xc0 | 0x80 uuid[6] = uuid[6]&^0xf0 | 0x40 return fmt.Sprintf("%x-%x-%x-%x-%x", uuid[0:4], uuid[4:6], uuid[6:8], uuid[8:10], uuid[10:]), nil } //func HandlePutDataErrors(statusList []*api.Status, errors string, err error) []*api.Status { // if err != nil { // log.Printf("Error: %v", err) // statusList = utils.AddStatus(statusList, "500", api.StatusType_ERROR, err.Error()) // } else if errors != "" { // statusList = utils.AddStatus(statusList, "400", api.StatusType_ERROR, errors) // } // // return statusList //} func ReadCertificateFromPEM(pemString []byte) (*x509.Certificate, error) { certificatePemBlock, err := ReadPemBlockFromBytes(pemString) if err != nil { log.Printf("Error: %v", err) return nil, err } certificate, err := x509.ParseCertificate(certificatePemBlock.Bytes) if err != nil { log.Printf("Error: %v", err) return nil, err } return certificate, nil } func ReadPemBlockFromBytes(pemString []byte) (*pem.Block, error) { fileBytes := pemString certificatePemBlock, _ := pem.Decode(fileBytes) return certificatePemBlock, nil } func ReadCertificateFromFile(fileName string) (*x509.Certificate, error) { certificatePemBlock, err := ReadPemBlockFromFile(fileName) if err != nil { log.Printf("Error: %v", err) return nil, err } certificate, err := x509.ParseCertificate(certificatePemBlock.Bytes) if err != nil { log.Printf("Error: %v", err) return nil, err } return certificate, nil } func ReadPemBlockFromFile(fileName string) (*pem.Block, error) { fileBytes, err := ioutil.ReadFile(fileName) if err != nil { log.Printf("Error: %v", err) return nil, err } certificatePemBlock, _ := pem.Decode(fileBytes) return certificatePemBlock, nil } func GetKey(client *client.DataStorageClientImpl, uuid string, keyType api.KeyType) (*api.Key, error) { key := &api.Key{} hasData, _, err := client.GetData("keys", uuid+"/"+api.KeyType.String(keyType), key) if err != nil { return nil, errors.WrapInternalFormat(err, "Could not get key %s", uuid+"/"+api.KeyType.String(keyType)) } if !hasData { return nil, errors.WrapUserFormat(ErrNoData, "Could not get key %s", uuid+"/"+api.KeyType.String(keyType)) } return key, nil } func CreateDataStorageClient(auth *authentication.Authentication) *dsclient.DataStorageClientImpl { return clientutils.CreateDataStorageClient(auth, config.DataStorageUrl, config.UseTLS, config.CertificatePEM, config.PrivateKeyPEM, config.CaCertificatePEM, config.MaxMessageSize) } func CreateEntitiesManagementClient(auth *authentication.Authentication) *emclient.EntitiesManagerClientImpl { return clientutils.CreateEntitiesManagementClient(auth, config.EntitiesManagerUrl, config.UseTLS, config.CertificatePEM, config.PrivateKeyPEM, config.CaCertificatePEM, config.MaxMessageSize) }