Skip to content
Snippets Groups Projects
etsi14Quantummodule.go 6.29 KiB
Newer Older
  • Learn to ignore specific revisions
  • package peers
    
    import (
    	"context"
    	"fmt"
    	"net/http"
    	"net/url"
    	"time"
    
    	etsi14ClientGenerated "code.fbi.h-da.de/danet/quant/etsi014/go/rest/etsi/client"
    	pbIC "code.fbi.h-da.de/danet/quant/goKMS/api/gen/proto/go/kmsintercom"
    	"code.fbi.h-da.de/danet/quant/goKMS/config"
    	etsi14ClientImpl "code.fbi.h-da.de/danet/quant/goKMS/kms/etsi/etsi14/client"
    	"code.fbi.h-da.de/danet/quant/goKMS/kms/event"
    	"code.fbi.h-da.de/danet/quant/goKMS/kms/store"
    	kmstls "code.fbi.h-da.de/danet/quant/goKMS/kms/tls"
    	"github.com/google/uuid"
    	log "github.com/sirupsen/logrus"
    )
    
    type ETSI014HTTPQuantumModule struct {
    
    	id               uuid.UUID
    	kmsId            string
    	addr             string
    	keyStore         *store.KmsKeyStore
    	kmsClient        *GRPCClient
    	client           *etsi14ClientImpl.ClientImpl
    	localSAEID       string
    	targetSAEID      string
    	master           bool
    	keyFetchInterval int
    	keyFetchAmount   int64
    	maxKeyFillLevel  uint64
    
    func NewETSI014HTTPQuantumModule(addr, kmsId, localSAEID, targetSAEID string, tlsConfig config.TLSConfig, master bool, keyFetchInterval int, keyFetchAmount int64, maxKeyFillLevel uint64) (*ETSI014HTTPQuantumModule, error) {
    
    	parsedUrl, err := url.Parse(addr)
    	if err != nil {
    		return nil, err
    	}
    
    	restClientConf := &etsi14ClientGenerated.Configuration{
    		Debug: true,
    		Servers: etsi14ClientGenerated.ServerConfigurations{
    			{
    				URL:         parsedUrl.String(),
    				Description: "QKD Module with ETSI14 implemented as API.",
    			},
    		},
    		Scheme: parsedUrl.Scheme,
    	}
    
    
    		tlsConf, err := kmstls.GenerateTlsLibraryConfig(tlsConfig)
    		if err != nil {
    			return nil, fmt.Errorf("unable to generate TLS config: %w", err)
    		}
    
    		restClientConf.HTTPClient = &http.Client{
    			Transport: &http.Transport{
    				TLSClientConfig: tlsConf,
    			},
    		}
    	}
    
    	client, err := etsi14ClientImpl.NewClientImpl(restClientConf)
    	if err != nil {
    		return nil, err
    	}
    
    
    	// set defaults for key fetching if not defined in config
    	if keyFetchInterval == 0 {
    		keyFetchInterval = defaultKeyFetchInterval
    	}
    
    	if keyFetchAmount == 0 {
    		keyFetchAmount = defaultKeyFetchAmount
    	}
    
    	if maxKeyFillLevel == 0 {
    
    		maxKeyFillLevel = DefaultMaxKeyFillLevel
    
    		id:               uuid.New(),
    		kmsId:            kmsId,
    		addr:             addr,
    		keyStore:         store.NewKmsKeyStore(256),
    		kmsClient:        nil,
    		client:           client,
    		localSAEID:       localSAEID,
    		targetSAEID:      targetSAEID,
    		master:           master,
    		keyFetchInterval: keyFetchInterval,
    		keyFetchAmount:   keyFetchAmount,
    		maxKeyFillLevel:  maxKeyFillLevel,
    
    	}, nil
    }
    
    func (qm *ETSI014HTTPQuantumModule) ID() uuid.UUID {
    	return qm.id
    }
    
    func (qm *ETSI014HTTPQuantumModule) Client() *etsi14ClientImpl.ClientImpl {
    	return qm.client
    }
    
    func (qm *ETSI014HTTPQuantumModule) Initialize() error {
    
    			restartWaitingTime := time.Duration(2) * time.Minute
    			ticker := time.NewTicker(restartWaitingTime)
    
    			// immediately start with the ticker instead of waiting the defined amount
    			for ; true; <-ticker.C {
    				if *restartedAfterWaitingTime == 5 {
    					log.Fatalf("Stopped retrying to fetch keys after %d attempts waiting %v each time in between.", restartedAfterWaitingTime, restartWaitingTime)
    
    				qm.doKeyFetching(restartedAfterWaitingTime)
    				*restartedAfterWaitingTime++
    
    			}
    		}()
    	}
    	return nil
    }
    
    func (qm *ETSI014HTTPQuantumModule) SetKmsPeerInformation(kmsClient *GRPCClient, kmsEventBus *event.EventBus, kmsTcpSocketStr string) error {
    	qm.kmsClient = kmsClient
    	return nil
    }
    
    func (qm *ETSI014HTTPQuantumModule) Address() string {
    	return qm.addr
    }
    
    func (qm *ETSI014HTTPQuantumModule) KeyStore() *store.KmsKeyStore {
    	return qm.keyStore
    }
    
    func (qm *ETSI014HTTPQuantumModule) SetKeyStore(newKeyStore *store.KmsKeyStore) {
    	qm.keyStore = newKeyStore
    }
    
    func (qm *ETSI014HTTPQuantumModule) Sync() error {
    	return nil
    }
    
    func (qm *ETSI014HTTPQuantumModule) KmsGrpcClient() *GRPCClient {
    	return nil
    }
    
    func (qm *ETSI014HTTPQuantumModule) SetKmsGrpcClient(peer *GRPCClient) {
    }
    
    
    func (qm *ETSI014HTTPQuantumModule) GetKeys(number int64, size int64, additionalTargetSAEIDs []string, extensionMandatory []map[string]string, extensionOptional []map[string]string) (*etsi14ClientGenerated.KeyContainer, error) {
    	container, _, err := qm.client.GetKeyPost(qm.targetSAEID, number, size, additionalTargetSAEIDs, extensionMandatory, extensionOptional)
    	if err != nil {
    		return nil, err
    	}
    
    	if len(container.GetKeys()) == 0 {
    		return nil, fmt.Errorf("no key received, length of key container was: %d", len(container.GetKeys()))
    	}
    
    	return container, nil
    }
    
    func (qm *ETSI014HTTPQuantumModule) GetKeyWithIds(keyIds []etsi14ClientGenerated.KeyIDsRequestKeyIDsInner) (*etsi14ClientGenerated.KeyContainer, error) {
    	container, _, err := qm.client.GetKeyWithIdPost(qm.targetSAEID, keyIds)
    	if err != nil {
    		return nil, err
    	}
    
    	if len(container.GetKeys()) == 0 {
    		return nil, fmt.Errorf("no key received, length of key container was: %d", len(container.GetKeys()))
    	}
    
    	return container, nil
    }
    
    
    func (qm *ETSI014HTTPQuantumModule) doKeyFetching(restartedAfterWaitingTime *int) {
    	ticker := time.NewTicker(time.Duration(qm.keyFetchInterval) * time.Second)
    	defer ticker.Stop()
    
    	failedAttemps := 0
    
    	// TODO: add context/channel to stop
    	for range ticker.C {
    		if failedAttemps == maxFailedKeyRequestAttempts {
    			log.Errorf("stopped trying to fetch keys from qkd module after %d tries", failedAttemps)
    			break
    		}
    
    		if qm.keyStore.Length() < int(qm.maxKeyFillLevel) {
    			container, err := qm.GetKeys(qm.keyFetchAmount, 256, nil, nil, nil)
    			if err != nil {
    				log.Error(err)
    				failedAttemps++
    				continue
    			}
    
    			keyIds := make([]string, len(container.GetKeys()))
    			for i, keyItem := range container.GetKeys() {
    				keyIds[i] = keyItem.GetKeyID()
    			}
    
    			_, err = qm.kmsClient.KeyIdNotification(context.Background(),
    				&pbIC.KeyIdNotificationRequest{
    					Timestamp: time.Now().Unix(),
    					KmsId:     qm.kmsId,
    					KeyIds:    keyIds,
    				})
    			if err != nil {
    				log.Error(err)
    				failedAttemps++
    				continue
    			}
    
    			err = store.AddETSIKeysToKeystore(qm.keyStore, container.GetKeys())
    			if err != nil {
    				log.Error(err)
    				failedAttemps++
    				continue
    			}
    
    			failedAttemps = 0
    			*restartedAfterWaitingTime = 0
    		}
    	}
    }