From d927ad77abd5bd0f75e2947807c855fe44f2d567 Mon Sep 17 00:00:00 2001
From: Olgun Cengiz <olgun.cengiz@vereign.com>
Date: Mon, 26 Oct 2020 10:04:03 +0300
Subject: [PATCH] config changes

---
 Gopkg.toml                  |   2 +-
 Makefile                    |   3 +
 config.yaml.sample          |  87 ++++------
 config/configs.go           | 333 +++++++++++++++++-------------------
 config/pem_reader.go        | 211 -----------------------
 handler/generate_keypair.go |  10 +-
 handler/handler.go          |  25 ++-
 main.go                     |  31 ++--
 run.sh                      |   2 +-
 server/server.go            |  26 +--
 utils/utils.go              |  11 +-
 11 files changed, 253 insertions(+), 488 deletions(-)
 delete mode 100644 config/pem_reader.go

diff --git a/Gopkg.toml b/Gopkg.toml
index f915437..05a32c9 100644
--- a/Gopkg.toml
+++ b/Gopkg.toml
@@ -1,5 +1,5 @@
 [[constraint]]
-  branch = "master"
+  branch = "392-fixing-configuration-issues-with-vault-and-default-values"
   name = "code.vereign.com/code/viam-apis"
 
 [[override]]
diff --git a/Makefile b/Makefile
index d3f20a2..88bc162 100644
--- a/Makefile
+++ b/Makefile
@@ -3,6 +3,9 @@ PKG := "code.vereign.com/code/key-storage-agent"
 SERVER_PKG_BUILD := "${PKG}"
 PKG_LIST := $(shell go list ${PKG}/... | grep -v /vendor/)
 VER := $(CI_COMMIT_REF_NAME).$(CI_COMMIT_SHA)
+ifeq ($(VER),.)
+VER := $(shell git rev-parse --abbrev-ref HEAD)
+endif
 
 .PHONY: all api server
 
diff --git a/config.yaml.sample b/config.yaml.sample
index 7e574fe..0dda853 100644
--- a/config.yaml.sample
+++ b/config.yaml.sample
@@ -2,62 +2,41 @@
 
 # You can use this sample YAML file to configure your installation
 
-# Connection Information
-dataStorageUrl: localhost:7777
-grpcListenAddress: localhost:7877
-restListenAddress: localhost:7878
+# Connection information for this agent
+listenAddress: :7878
+grpcListenAddress: :7877
 
 # VIAM Variables
-viamUUID: viam-system
-viamSession: viam-session
+systemAuthentication:
+  viamUUID: viam-system
+  viamSession: viam-user
+
+# Connection information for other Vereign services
+dataStorageAgentURL: data-storage-agent:7777
+entitiesManagementAgentURL: entities-management-agent:7779
 
 # Maximum Message Size (in megabytes)
-maxMessageSize: 64
-
-# Certification Access Method
-# 1 = Certificate Folder and Files
-# 2 = Vault Integration
-#certificationMethod: 1
-certificationMethod: 2
-
-# Certification URL
-# For Method 1: Can be anything (will be ignored)
-# For Method 2: IP address and port number of Vault server
-#certificationURL: localhost
-certificationURL: http://10.6.10.119:8200
-
-# Certification Token
-# For Method 1: Can be anything (will be ignored)
-# For Method 2: Vault authentication token
-#certificationToken: .
-certificationToken: YOUR_VAULT_TOKEN
-
-# Certification Path
-# For Method 1: The full path of the folder where the certificate and private key files are stored
-# For Method 2: Base mount path for certificate secrets
-#certificationPath: /home/ocengiz/Documents/Vereign/03-Codebase/cert
-certificationPath: /developers/data/devteam/cert
-
-# Certification Files
-# For Method 1: The name of the files for certification
-# For Method 2: The name of the secret keys on Vault
-#certificationCertFile: localhost.crt
-certificationCertFile: certificateKey
-#certificationKeyFile: localhost.key
-certificationKeyFile: privateKey
-#certificationCaCertFile: ca.crt
-certificationCaCertFile: caCertificateKey
-#certificationVereignCertFile: vereign_ca.cer
-certificationVereignCertFile: vereignCaCertificateKey
-#certificationVereignKeyFile: Not used anymore, its functionality is moved to vaultEncryptionKeyFile
+maxMessageSize: 32
+
+# Certification related configuration
+certification:
+  # The full path of the folder where the certificate and private key files are stored
+  path: "/home/ocengiz/Documents/Vereign/03-Codebase/cert"
+  # The name of the files for certification
+  certificateFile: "localhost.crt"
+  privateKeyFile: "localhost.key"
+  caCertificateFile: "ca.crt"
+  encryptionCertificateFile: localhost.crt
+  encryptionPrivateKeyFile: localhost.key
+  vereignCertificateFile: ca.crt
+
+# Prometheus settings
+prometeusListenAddress: :2112
+
+replaceKey: false
+
+# prefixes for env
+metricEnvPrefix: gospodinbodurov
+
 #possible levels: trace, info, debug, warn, error, fatal, panic
-globalLogLevel: debug
-
-# Until vereign root cert expires, these values will copy the values of certificationVereign(Cert|Key)File.
-# When the root cert is changed, the new root will be set in certificationVereign(Cert|Key)File,
-# while here will continue to be the old root
-vaultEncryptionURL: http://10.6.16.32:8200
-vaultEncryptionToken: YOUR_VAULT_TOKEN
-vaultEncryptionPath: /developers/data/devteam/cert
-vaultEncryptionCertFile: encryptionCert
-vaultEncryptionKeyFile: encryptionKey
+globalLogLevel: info
\ No newline at end of file
diff --git a/config/configs.go b/config/configs.go
index 6c09c44..39302db 100644
--- a/config/configs.go
+++ b/config/configs.go
@@ -1,15 +1,17 @@
 package config
 
 import (
-	"bytes"
-	"code.vereign.com/code/viam-apis/clientutils"
-	"code.vereign.com/code/viam-apis/errors"
 	"crypto"
 	"crypto/x509"
+	"io/ioutil"
 	"os"
 	"path/filepath"
+	"reflect"
 	"strings"
 
+	"code.vereign.com/code/viam-apis/clientutils"
+	"code.vereign.com/code/viam-apis/errors"
+
 	"code.vereign.com/code/viam-apis/log"
 
 	"code.vereign.com/code/viam-apis/authentication"
@@ -23,76 +25,58 @@ var SystemAuth = &authentication.Authentication{
 	Session: "undefined",
 }
 
-var CertificationMethod string
-var P PEMReader
-var CertificatePEM []byte
-var PrivateKeyPEM []byte
-var CaCertificatePEM []byte
-var VereignCaCertificatePEM []byte
-
-var EncryptionCert *x509.Certificate
-var EncryptionKey crypto.Signer
-
-var ReplaceKey bool
-
-var MaxMessageSize int
-
-var GrpcListenAddress string
-var RestListenAddress string
-var DataStorageUrl string
-var EntitiesManagerUrl string
-var CertDir string
-var GlobalLogLevel string
-
-var PrometeusListenAddress string
-var MetricEnvPrefix string
-
-func SetConfigValues(configFile, etcdURL string) error {
-	// Set Default Values For Config Variables
-
-	// Vereign API Related
-	viper.SetDefault("grpcListenAddress", ":7877")
-	viper.SetDefault("restListenAddress", ":7878")
-	viper.SetDefault("dataStorageUrl", "data-storage-agent:7777")
-	viper.SetDefault("entitiesManagerUrl", "entities-management-agent:7779")
-
-	viper.SetDefault("replaceKey", false)
-
-	viper.SetDefault("viamUUID", "viam-system")
-	viper.SetDefault("viamSession", "viam-session")
-
-	viper.SetDefault("maxMessageSize", 64)
-
-	// Certification Related
-	// File System Defaults
-	viper.SetDefault("certificationMethod", "1")
-	viper.SetDefault("certificationURL", ".")
-	viper.SetDefault("certificationToken", ".")
-	viper.SetDefault("certificationPath", "cert")
-	viper.SetDefault("certificationCertFile", "server.crt")
-	viper.SetDefault("certificationKeyFile", "server.key")
-	viper.SetDefault("certificationCaCertFile", "ca.crt")
-	viper.SetDefault("certificationVereignCertFile", "vereign_ca.cer")
-	viper.SetDefault("globalLogLevel", "info")
-
-	/*
-			// Vault Defaults
-			viper.SetDefault("certificationMethod", "2")
-			viper.SetDefault("certificationURL", "http://10.6.10.119:8200")
-			viper.SetDefault("certificationToken", "")
-			viper.SetDefault("certificationPath", "/developers/data/devteam/cert")
-		    viper.SetDefault("certificationCertFile", "certificateKey")
-			viper.SetDefault("certificationKeyFile", "privateKey")
-			viper.SetDefault("certificationCaCertFile", "caCertificateKey")
-			viper.SetDefault("certificationVereignCertFile", "vereignCaCertificateKey")
-	*/
-
-	// Encryption/Decryption Related
-	viper.SetDefault("vaultEncryptionURL", "")
-	viper.SetDefault("vaultEncryptionToken", "")
-	viper.SetDefault("vaultEncryptionPath", "")
-	viper.SetDefault("vaultEncryptionCertFile", "encryptionCert")
-	viper.SetDefault("vaultEncryptionKeyFile", "encryptionKey")
+const tagValidation = "validation"
+
+type Configuration struct {
+	ListenAddress        string `validation:"optional" yaml:"listenAddress"`
+	GrpcListenAddress    string `validation:"optional" yaml:"grpcListenAddress"`
+	SystemAuthentication struct {
+		UUID    string `validation:"optional" yaml:"viamUUID"`
+		Session string `validation:"optional" yaml:"viamSession"`
+	} `validation:"optional" yaml:"systemAuthentication"`
+	DataStorageAgentURL        string `validation:"optional" yaml:"dataStorageAgentURL"`
+	EntitiesManagementAgentURL string `validation:"optional" yaml:"entitiesManagementAgentURL"`
+	MaxMessageSize             int    `validation:"optional" yaml:"maxMessageSize"`
+	Certification              struct {
+		Path                      string              `validation:"required" yaml:"path"`
+		CertificateFile           string              `validation:"required" yaml:"certificateFile"`
+		CertificatePEM            []byte              `validation:"calculated" yaml:"certificatePEM"`
+		PrivateKeyFile            string              `validation:"required" yaml:"privateKeyFile"`
+		PrivateKeyPEM             []byte              `validation:"calculated" yaml:"privateKeyPEM"`
+		CaCertificateFile         string              `validation:"required" yaml:"caCertificateFile"`
+		CaCertificatePEM          []byte              `validation:"calculated" yaml:"caCertificatePEM"`
+		EncryptionCertificateFile string              `validation:"required" yaml:"encryptionCertificateFile"`
+		EncryptionCertificatePEM  []byte              `validation:"calculated" yaml:"encryptionCertificatePEM"`
+		EncryptionCertificate     []*x509.Certificate `validation:"calculated" yaml:"encryptionCertificate"`
+		EncryptionPrivateKeyFile  string              `validation:"required" yaml:"encryptionPrivateKeyFile"`
+		EncryptionPrivateKeyPEM   []byte              `validation:"calculated" yaml:"encryptionPrivateKeyPEM"`
+		EncryptionPrivateKey      crypto.Signer       `validation:"calculated" yaml:"encryptionPrivateKey"`
+		VereignCertificateFile    string              `validation:"required" yaml:"vereignCertificateFile"`
+		VereignCertificatePEM     []byte              `validation:"calculated" yaml:"vereignCertificatePEM"`
+	} `validation:"required" yaml:"certification"`
+	PrometeusListenAddress  string `validation:"optional" yaml:"prometeusListenAddress"`
+	MetricEnvironmentPrefix string `validation:"optional" yaml:"metricEnvironmentPrefix"`
+	ReplaceKey              bool   `validation:"optional" yaml:"replaceKey"`
+	GlobalLogLevel          string `validation:"optional" yaml:"globalLogLevel"`
+}
+
+var Config Configuration
+
+// SetConfigValues Sets Values For Config Variable
+func SetConfigValues(configFile, etcdURL string) {
+	// Set default values for configuration variable
+	// NOTE: Only for 'validation:"optional"' fields
+	Config.ListenAddress = ":7878"
+	Config.GrpcListenAddress = ":7877"
+	Config.SystemAuthentication.UUID = "viam-system"
+	Config.SystemAuthentication.Session = "viam-session"
+	Config.DataStorageAgentURL = "data-storage-agent:7777"
+	Config.EntitiesManagementAgentURL = "entities-management-agent:7779"
+	Config.MaxMessageSize = 64
+	Config.PrometeusListenAddress = ":2112"
+	Config.MetricEnvironmentPrefix = "staging_data_storage_agent"
+	Config.ReplaceKey = false
+	Config.GlobalLogLevel = "info"
 
 	// Read Config File
 	if configFile != "" {
@@ -113,123 +97,128 @@ func SetConfigValues(configFile, etcdURL string) error {
 		}
 	}
 
-	// Print all config values to log file
-	log.Printf("All Settings From Config:")
-	as := viper.AllSettings()
-	for key, _ := range as {
-		log.Printf("%s => %s", key, viper.GetString(key))
-	}
+	// Read Config File
+	if configFile != "" {
+		configName := strings.Split(filepath.Base(configFile), ".")[0]
+		configDir := filepath.Dir(configFile)
+		viper.SetConfigName(configName)
+		viper.AddConfigPath(configDir)
+		if err := viper.ReadInConfig(); err != nil {
+			errors.LogFormat(err, "can't read config, will use default values")
+		}
+	} else {
+		log.Printf("requesting config at "+etcdURL, "/"+os.Getenv("ENV_NAME")+"/"+os.Getenv("CI_PROJECT_NAME")+".json")
+		viper.AddRemoteProvider("etcd", etcdURL, "/"+os.Getenv("ENV_NAME")+"/"+os.Getenv("CI_PROJECT_NAME")+".json")
+		viper.SetConfigType("json")
 
-	CertificationMethod = viper.GetString("certificationMethod")
-	if CertificationMethod == "1" {
-		// Read From File System
-		P = FilePEMReader{certificationURL: viper.GetString("certificationURL"),
-			certificationToken:           viper.GetString("certificationToken"),
-			certificationPath:            viper.GetString("certificationPath"),
-			certificationCertFile:        viper.GetString("certificationCertFile"),
-			certificationKeyFile:         viper.GetString("certificationKeyFile"),
-			certificationCaCertFile:      viper.GetString("certificationCaCertFile"),
-			certificationVereignCertFile: viper.GetString("certificationVereignCertFile")}
-	} else if CertificationMethod == "2" {
-		// Read From Vault
-		P = VaultPEMReader{certificationURL: viper.GetString("certificationURL"),
-			certificationToken:           viper.GetString("certificationToken"),
-			certificationPath:            viper.GetString("certificationPath"),
-			certificationCertFile:        viper.GetString("certificationCertFile"),
-			certificationKeyFile:         viper.GetString("certificationKeyFile"),
-			certificationCaCertFile:      viper.GetString("certificationCaCertFile"),
-			certificationVereignCertFile: viper.GetString("certificationVereignCertFile")}
+		if err := viper.ReadRemoteConfig(); err != nil {
+			errors.LogFormat(err, "can't read config, will use default values")
+		}
 	}
 
-	// Encryption/Decryption Related
-	if viper.GetString("vaultEncryptionURL") == "" ||
-		viper.GetString("vaultEncryptionToken") == "" ||
-		viper.GetString("vaultEncryptionPath") == "" ||
-		viper.GetString("vaultEncryptionCertFile") == "" ||
-		viper.GetString("vaultEncryptionKeyFile") == "" {
-		log.Error("Some config values for encryption/decryption are missing!")
-		return errors.NewFormat("Some config values for encryption/decryption are missing!")
-	}
-	encryptionCertPEM, err := ReadEncryptionPEMFromVault(
-		viper.GetString("vaultEncryptionURL"),
-		viper.GetString("vaultEncryptionToken"),
-		viper.GetString("vaultEncryptionPath"),
-		viper.GetString("vaultEncryptionCertFile"))
-	if err != nil {
-		errors.LogFormat(err, "Vault Err")
-		return err
-	}
-	encryptionKeyPEM, err := ReadEncryptionPEMFromVault(
-		viper.GetString("vaultEncryptionURL"),
-		viper.GetString("vaultEncryptionToken"),
-		viper.GetString("vaultEncryptionPath"),
-		viper.GetString("vaultEncryptionKeyFile"))
-	if err != nil {
-		errors.LogFormat(err, "Vault Err")
-		return err
-	}
-	var encryptionCerts []*x509.Certificate
-	encryptionCerts, EncryptionKey, err = clientutils.LoadCertAndKey(encryptionCertPEM, encryptionKeyPEM)
-	if err != nil {
-		errors.LogFormat(err, "Load Err")
-		return err
-	}
-	if len(encryptionCerts) != 1 {
-		log.Errorf("%d certs found in vaultEncryptionCertFile, 1 expected", len(encryptionCerts))
-		return err
-	}
-	EncryptionCert = encryptionCerts[0]
-	keyPub, err := x509.MarshalPKIXPublicKey(EncryptionKey.Public())
-	if err != nil {
-		return err
-	}
-	certPub, err := x509.MarshalPKIXPublicKey(EncryptionCert.PublicKey)
+	err := viper.Unmarshal(&Config)
 	if err != nil {
-		return err
-	}
-	if !bytes.Equal(keyPub, certPub) {
-		return errors.New("Encryption certificate public key does not correspond to encryption private key")
+		log.Printf("unable to decode into config struct, %v", err)
 	}
+}
 
-	GrpcListenAddress = viper.GetString("grpcListenAddress")
-	RestListenAddress = viper.GetString("restListenAddress")
-
-	DataStorageUrl = viper.GetString("dataStorageUrl")
-	EntitiesManagerUrl = viper.GetString("entitiesManagerUrl")
-
-	ReplaceKey = viper.GetBool("replaceKey")
-
-	SystemAuth.Uuid = viper.GetString("viamUUID")
-	SystemAuth.Session = viper.GetString("viamSession")
+// CheckConfigValues checks if there is any missing required fields in configuration
+func CheckConfigValues(configs interface{}) error {
+	structIterator := reflect.ValueOf(configs)
+	for i := 0; i < structIterator.NumField(); i++ {
+		field := structIterator.Type().Field(i).Name
+		val := structIterator.Field(i).Interface()
+		tR := structIterator.Type().Field(i).Tag.Get(tagValidation)
+		log.Printf("%v: %v", field, val)
+
+		if tR == "required" {
+			if structIterator.Field(i).Kind() == reflect.Struct {
+				if err := CheckConfigValues(structIterator.Field(i).Interface()); err != nil {
+					return err
+				}
+			}
+
+			if reflect.DeepEqual(val, reflect.Zero(structIterator.Field(i).Type()).Interface()) {
+				// Check if the field is zero-valued, meaning it won't be updated
+				return errors.NewFormat("Empty value for required field: %v", field)
+			}
+		} else if tR != "optional" && tR != "calculated" {
+			return errors.NewFormat("Wrong validation type for field: %v (Must be 'optional', 'required' or 'calculated')", field)
+		}
+	}
 
-	MaxMessageSize = viper.GetInt("maxMessageSize")
+	return nil
+}
 
-	PrometeusListenAddress = viper.GetString("prometeusListenAddress")
+// CalculateConfigValues calculates config values using provided configuraion
+func CalculateConfigValues() {
+	SystemAuth.Uuid = Config.SystemAuthentication.UUID
+	SystemAuth.Session = Config.SystemAuthentication.Session
 
-	MetricEnvPrefix = viper.GetString("metricEnvPrefix")
+	Config.Certification.CertificatePEM = getCertificatePEM()
+	Config.Certification.PrivateKeyPEM = getPrivateKeyPEM()
+	Config.Certification.CaCertificatePEM = getCaCertificatePEM()
+	Config.Certification.VereignCertificatePEM = getVereignCertificatePEM()
+	Config.Certification.EncryptionCertificatePEM = getEncryptionCertificatePEM()
+	Config.Certification.EncryptionPrivateKeyPEM = getEncryptionPrivateKeyPEM()
 
-	GlobalLogLevel = viper.GetString("globalLogLevel")
+	var err error
+	Config.Certification.EncryptionCertificate, Config.Certification.EncryptionPrivateKey, err = clientutils.LoadCertAndKey(Config.Certification.EncryptionCertificatePEM, Config.Certification.EncryptionPrivateKeyPEM)
+	if err != nil {
+		log.Printf("Load Err: %v", err)
+	}
+}
 
-	CertificatePEM = GetCertificatePEM()
-	PrivateKeyPEM = GetPrivateKeyPEM()
-	CaCertificatePEM = GetCaCertificatePEM()
-	VereignCaCertificatePEM = GetVereignCaCertificatePEM()
+func getCertificatePEM() []byte {
+	pem, err := ioutil.ReadFile(Config.Certification.Path + "/" + Config.Certification.CertificateFile)
+	if err != nil {
+		errors.Log(err)
+		return []byte("")
+	}
+	return pem
+}
 
-	return nil
+func getCaCertificatePEM() []byte {
+	pem, err := ioutil.ReadFile(Config.Certification.Path + "/" + Config.Certification.CaCertificateFile)
+	if err != nil {
+		errors.Log(err)
+		return []byte("")
+	}
+	return pem
 }
 
-func GetCertificatePEM() []byte {
-	return P.readCertificatePEM()
+func getPrivateKeyPEM() []byte {
+	pem, err := ioutil.ReadFile(Config.Certification.Path + "/" + Config.Certification.PrivateKeyFile)
+	if err != nil {
+		errors.Log(err)
+		return []byte("")
+	}
+	return pem
 }
 
-func GetPrivateKeyPEM() []byte {
-	return P.readPrivateKeyPEM()
+func getVereignCertificatePEM() []byte {
+	pem, err := ioutil.ReadFile(Config.Certification.Path + "/" + Config.Certification.CaCertificateFile)
+	if err != nil {
+		errors.Log(err)
+		return []byte("")
+	}
+	return pem
 }
 
-func GetCaCertificatePEM() []byte {
-	return P.readCaCertificatePEM()
+func getEncryptionCertificatePEM() []byte {
+	pem, err := ioutil.ReadFile(Config.Certification.Path + "/" + Config.Certification.EncryptionCertificateFile)
+	if err != nil {
+		errors.Log(err)
+		return []byte("")
+	}
+	return pem
 }
 
-func GetVereignCaCertificatePEM() []byte {
-	return P.readVereignCaCertificatePEM()
+func getEncryptionPrivateKeyPEM() []byte {
+	pem, err := ioutil.ReadFile(Config.Certification.Path + "/" + Config.Certification.EncryptionPrivateKeyFile)
+	if err != nil {
+		errors.Log(err)
+		return []byte("")
+	}
+	return pem
 }
diff --git a/config/pem_reader.go b/config/pem_reader.go
deleted file mode 100644
index 88794e6..0000000
--- a/config/pem_reader.go
+++ /dev/null
@@ -1,211 +0,0 @@
-package config
-
-import (
-	"code.vereign.com/code/viam-apis/errors"
-	"io/ioutil"
-
-	"code.vereign.com/code/viam-apis/log"
-
-	vc "github.com/hashicorp/vault/api"
-)
-
-type PEMReader interface {
-	readCertificatePEM() []byte
-	readPrivateKeyPEM() []byte
-	readCaCertificatePEM() []byte
-	readVereignCaCertificatePEM() []byte
-}
-
-type FilePEMReader struct {
-	certificationURL             string
-	certificationToken           string
-	certificationPath            string
-	certificationCertFile        string
-	certificationKeyFile         string
-	certificationCaCertFile      string
-	certificationVereignCertFile string
-}
-
-func (f FilePEMReader) readCertificatePEM() []byte {
-	pem, err := ioutil.ReadFile(f.certificationPath + "/" + f.certificationCertFile)
-	if err != nil {
-		log.Printf("Error: %v", err)
-		return []byte("")
-	}
-	return pem
-}
-
-func (f FilePEMReader) readPrivateKeyPEM() []byte {
-	pem, err := ioutil.ReadFile(f.certificationPath + "/" + f.certificationKeyFile)
-	if err != nil {
-		log.Printf("Error: %v", err)
-		return []byte("")
-	}
-	return pem
-}
-
-func (f FilePEMReader) readCaCertificatePEM() []byte {
-	pem, err := ioutil.ReadFile(f.certificationPath + "/" + f.certificationCaCertFile)
-	if err != nil {
-		log.Printf("Error: %v", err)
-		return []byte("")
-	}
-	return pem
-}
-
-func (f FilePEMReader) readVereignCaCertificatePEM() []byte {
-	pem, err := ioutil.ReadFile(f.certificationPath + "/" + f.certificationVereignCertFile)
-	if err != nil {
-		log.Printf("Error: %v", err)
-		return []byte("")
-	}
-	return pem
-}
-
-type VaultPEMReader struct {
-	certificationURL             string
-	certificationToken           string
-	certificationPath            string
-	certificationCertFile        string
-	certificationKeyFile         string
-	certificationCaCertFile      string
-	certificationVereignCertFile string
-}
-
-func (v VaultPEMReader) readCertificatePEM() []byte {
-	client, err := vc.NewClient(&vc.Config{
-		Address: v.certificationURL,
-	})
-
-	if err != nil {
-		log.Printf("Error: VAULT Can't create client, %s", err)
-	}
-
-	client.SetToken(v.certificationToken)
-
-	keyname := v.certificationPath
-	secretValues, err := client.Logical().Read(keyname)
-	if err != nil {
-		log.Printf("Error: VAULT Can't read value, %s", err)
-	}
-
-	pemMap := secretValues.Data["data"].(map[string]interface{})
-
-	for propName, propValue := range pemMap {
-		if propName == v.certificationCertFile {
-			return []byte(propValue.(string))
-		}
-	}
-	return []byte("")
-}
-
-func (v VaultPEMReader) readPrivateKeyPEM() []byte {
-	client, err := vc.NewClient(&vc.Config{
-		Address: v.certificationURL,
-	})
-
-	if err != nil {
-		log.Printf("Error: VAULT Can't create client, %s", err)
-	}
-
-	client.SetToken(v.certificationToken)
-
-	keyname := v.certificationPath
-	secretValues, err := client.Logical().Read(keyname)
-	if err != nil {
-		log.Printf("Error: VAULT Can't read value, %s", err)
-	}
-
-	pemMap := secretValues.Data["data"].(map[string]interface{})
-
-	for propName, propValue := range pemMap {
-		if propName == v.certificationKeyFile {
-			return []byte(propValue.(string))
-		}
-	}
-	return []byte("")
-}
-
-func (v VaultPEMReader) readCaCertificatePEM() []byte {
-	client, err := vc.NewClient(&vc.Config{
-		Address: v.certificationURL,
-	})
-
-	if err != nil {
-		log.Printf("Error: VAULT Can't create client, %s", err)
-	}
-
-	client.SetToken(v.certificationToken)
-
-	keyname := v.certificationPath
-	secretValues, err := client.Logical().Read(keyname)
-	if err != nil {
-		log.Printf("Error: VAULT Can't read value, %s", err)
-	}
-
-	pemMap := secretValues.Data["data"].(map[string]interface{})
-
-	for propName, propValue := range pemMap {
-		if propName == v.certificationCaCertFile {
-			return []byte(propValue.(string))
-		}
-	}
-	return []byte("")
-}
-
-func (v VaultPEMReader) readVereignCaCertificatePEM() []byte {
-	client, err := vc.NewClient(&vc.Config{
-		Address: v.certificationURL,
-	})
-
-	if err != nil {
-		log.Printf("Error: VAULT Can't create client, %s", err)
-	}
-
-	client.SetToken(v.certificationToken)
-
-	keyname := v.certificationPath
-	secretValues, err := client.Logical().Read(keyname)
-	if err != nil {
-		log.Printf("Error: VAULT Can't read value, %s", err)
-	}
-
-	pemMap := secretValues.Data["data"].(map[string]interface{})
-
-	for propName, propValue := range pemMap {
-		if propName == v.certificationVereignCertFile {
-			return []byte(propValue.(string))
-		}
-	}
-	return []byte("")
-}
-
-//copied from object storage agent
-func ReadEncryptionPEMFromVault(url, token, path, pemFile string) ([]byte, error) {
-	client, err := vc.NewClient(&vc.Config{
-		Address: url,
-	})
-
-	if err != nil {
-		errors.LogFormat(err, "VAULT Can't create client")
-		return nil, err
-	}
-
-	client.SetToken(token)
-
-	keyname := path
-	secretValues, err := client.Logical().Read(keyname)
-	if err != nil {
-		errors.LogFormat(err, "VAULT Can't read value")
-		return nil, err
-	}
-
-	pemMap := secretValues.Data["data"].(map[string]interface{})
-
-	for propName, propValue := range pemMap {
-		if propName == pemFile {
-			return []byte(propValue.(string)), nil
-		}
-	}
-	return []byte(""), nil
-}
diff --git a/handler/generate_keypair.go b/handler/generate_keypair.go
index a2e538c..3ef93cc 100644
--- a/handler/generate_keypair.go
+++ b/handler/generate_keypair.go
@@ -18,8 +18,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
 package handler
 
 import (
-	"code.vereign.com/code/key-storage-agent/config"
-	"code.vereign.com/code/viam-apis/errors"
 	"crypto/aes"
 	"crypto/cipher"
 	"crypto/rand"
@@ -28,6 +26,9 @@ import (
 	"crypto/x509"
 	"encoding/pem"
 
+	"code.vereign.com/code/key-storage-agent/config"
+	"code.vereign.com/code/viam-apis/errors"
+
 	"code.vereign.com/code/viam-apis/log"
 
 	keyutils "code.vereign.com/code/key-storage-agent/utils"
@@ -72,7 +73,6 @@ func (s *KeyStorageServerImpl) GenerateKeyPair(ctx context.Context,
 		return nil, errors.WrapInternalFormat(err, "Could not store key %s", uuid+"/"+api.KeyType.String(api.KeyType_PRIVATE))
 	}
 
-
 	publicKey := &api.Key{Content: publicKeyBytes}
 	_, _, err = client.PutData("keys", uuid+"/"+api.KeyType.String(api.KeyType_PUBLIC), publicKey)
 	if err != nil {
@@ -111,7 +111,7 @@ func (s *KeyStorageServerImpl) GenerateKeyPair(ctx context.Context,
 		return nil, errors.WrapInternalFormat(err, "Could not store key %s", uuid+"/"+api.KeyType.String(api.KeyType_NONCE))
 	}
 
-	generateKeyPairResponse := &api.GenerateKeyPairResponse{Uuid:uuid}
+	generateKeyPairResponse := &api.GenerateKeyPairResponse{Uuid: uuid}
 	return generateKeyPairResponse, nil
 }
 
@@ -160,7 +160,7 @@ func generateKeyPair(keySize int) ([]byte, []byte, error) {
 }
 
 func rsaEncryptWithServerKey(message []byte, label []byte) ([]byte, error) {
-	serverPublicKey := config.EncryptionCert.PublicKey.(*rsa.PublicKey)
+	serverPublicKey := config.Config.Certification.EncryptionCertificate[0].PublicKey.(*rsa.PublicKey)
 
 	encryptedMessageBytes, err := rsa.EncryptOAEP(sha256.New(), rand.Reader, serverPublicKey, message, label)
 	if err != nil {
diff --git a/handler/handler.go b/handler/handler.go
index 6e502d0..0820010 100644
--- a/handler/handler.go
+++ b/handler/handler.go
@@ -18,10 +18,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
 package handler
 
 import (
-	"code.vereign.com/code/viam-apis/errors"
 	"encoding/base64"
 	"strings"
 
+	"code.vereign.com/code/viam-apis/errors"
+
 	"code.vereign.com/code/viam-apis/log"
 
 	"code.vereign.com/code/viam-apis/clientutils"
@@ -40,12 +41,12 @@ const (
 
 // Server represents the gRPC server
 type KeyStorageServerImpl struct {
-	DataStorageUrl       string
-	CertPEM              []byte
-	KeyPEM               []byte
-	CaCertPEM            []byte
-	VereignCertPEM       []byte
-	MaxMessageSize       int
+	DataStorageUrl string
+	CertPEM        []byte
+	KeyPEM         []byte
+	CaCertPEM      []byte
+	VereignCertPEM []byte
+	MaxMessageSize int
 }
 
 var version = "undefined"
@@ -72,8 +73,6 @@ func (s *KeyStorageServerImpl) GetKey(ctx context.Context, in *api.GetKeyRequest
 	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)
@@ -88,7 +87,7 @@ func (s *KeyStorageServerImpl) GetKey(ctx context.Context, in *api.GetKeyRequest
 		key.Content = s.VereignCertPEM
 		key.Revoked = false
 
-		getKeyResponse := &api.GetKeyResponse{Key:key}
+		getKeyResponse := &api.GetKeyResponse{Key: key}
 		return getKeyResponse, nil
 	}
 
@@ -109,7 +108,7 @@ func (s *KeyStorageServerImpl) GetKey(ctx context.Context, in *api.GetKeyRequest
 		return nil, errors.NewUser("No such key " + in.Uuid)
 	}
 
-	getKeyResponse := &api.GetKeyResponse{Key:key}
+	getKeyResponse := &api.GetKeyResponse{Key: key}
 	return getKeyResponse, nil
 }
 
@@ -129,7 +128,7 @@ func (s *KeyStorageServerImpl) SetKey(ctx context.Context, in *api.SetKeyRequest
 
 	key := &api.Key{}
 
-	if config.ReplaceKey == false {
+	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)
@@ -191,7 +190,7 @@ func (s *KeyStorageServerImpl) ReserveKeyUUID(ctx context.Context, in *api.Reser
 		return nil, errors.WrapInternalFormat(err, "Could not store key %s", uuid+"/"+api.KeyType.String(api.KeyType_CERTIFICATE))
 	}
 
-	reserveKeyUUIDResponse := &api.ReserveKeyUUIDResponse{Uuid:uuid}
+	reserveKeyUUIDResponse := &api.ReserveKeyUUIDResponse{Uuid: uuid}
 	return reserveKeyUUIDResponse, nil
 }
 
diff --git a/main.go b/main.go
index ec9523e..783a2f2 100644
--- a/main.go
+++ b/main.go
@@ -18,7 +18,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
 package main
 
 import (
-	"code.vereign.com/code/viam-apis/errors"
 	"flag"
 
 	"code.vereign.com/code/viam-apis/log"
@@ -40,22 +39,28 @@ func main() {
 		return
 	}
 
-	err := config.SetConfigValues(*configFile, *etcdURL)
+	log.Printf("Setting configuration values...")
+	config.SetConfigValues(*configFile, *etcdURL)
+
+	log.Printf("Checking configuration values...")
+	err := config.CheckConfigValues(config.Config)
 	if err != nil {
-		errors.LogFormat(err, "Can not set config values")
-		return
+		log.Fatalf("Exiting due to wrong configuration: %s", err)
 	}
 
-	grpcAddress := config.GrpcListenAddress
-	restAddress := config.RestListenAddress
-	dataStorageAddress := config.DataStorageUrl
-	certPem := config.CertificatePEM
-	keyPem := config.PrivateKeyPEM
-	caCertPem := config.CaCertificatePEM
-	vereignCaCertificatePem := config.VereignCaCertificatePEM
+	log.Printf("Calculating configuration values...")
+	config.CalculateConfigValues()
+
+	grpcAddress := config.Config.GrpcListenAddress
+	restAddress := config.Config.ListenAddress
+	dataStorageAddress := config.Config.DataStorageAgentURL
+	certPem := config.Config.Certification.CertificatePEM
+	keyPem := config.Config.Certification.PrivateKeyPEM
+	caCertPem := config.Config.Certification.CaCertificatePEM
+	vereignCaCertificatePem := config.Config.Certification.VereignCertificatePEM
 
-	maxMessageSize := config.MaxMessageSize
-	log.SetConfiguration(config.GlobalLogLevel)
+	maxMessageSize := config.Config.MaxMessageSize
+	log.SetConfiguration(config.Config.GlobalLogLevel)
 
 	// fire the gRPC server in a goroutine
 	go func() {
diff --git a/run.sh b/run.sh
index 6cdffbd..068f19d 100755
--- a/run.sh
+++ b/run.sh
@@ -17,7 +17,7 @@ fi
 
 PATH=$PATH:/usr/local/bin
 
-nohup $GOPATH/src/code.vereign.com/code/key-storage-agent/bin/server --cert-dir $GOPATH/src/code.vereign.com/code/key-storage-agent/cert > $HOME/key-storage-agent.log 2>&1 &
+nohup $GOPATH/src/code.vereign.com/code/key-storage-agent/bin/server -config-file config.yaml > $HOME/key-storage-agent.log 2>&1 &
 
 echo $! > "${PIDFILE}"
 chmod 644 "${PIDFILE}"
diff --git a/server/server.go b/server/server.go
index 46868ae..0895503 100644
--- a/server/server.go
+++ b/server/server.go
@@ -121,14 +121,14 @@ func unaryInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServ
 }
 
 func createQueryTime(funcName string) prometheus.Summary {
-	if config.PrometeusListenAddress != "" {
+	if config.Config.PrometeusListenAddress != "" {
 		endPointName := strings.Replace(funcName, "/", "_", -1)
 		endPointName = strings.Replace(endPointName, ".", "_", -1)
 
 		metricName := endPointName + "_grpc_request_duration_seconds"
 
-		if config.MetricEnvPrefix != "" {
-			metricName = config.MetricEnvPrefix + "_" + metricName
+		if config.Config.MetricEnvironmentPrefix != "" {
+			metricName = config.Config.MetricEnvironmentPrefix + "_" + metricName
 		}
 
 		mutex.Lock()
@@ -139,7 +139,7 @@ func createQueryTime(funcName string) prometheus.Summary {
 		if ok == false {
 			queryTime = prometheus.NewSummary(prometheus.SummaryOpts{
 				Name: metricName,
-				Help: "grpc request duration seconds of /" + funcName + " for " + config.MetricEnvPrefix + " env",
+				Help: "grpc request duration seconds of /" + funcName + " for " + config.Config.MetricEnvironmentPrefix + " env",
 			})
 
 			// init metrics
@@ -168,12 +168,12 @@ func StartGRPCServer(address string, certPEM, privateKeyPEM, caCertPEM, vereignC
 
 	// create a server instance
 	s := handler.KeyStorageServerImpl{
-		DataStorageUrl:       dataStorageAddress,
-		CertPEM:              certPEM,
-		KeyPEM:               privateKeyPEM,
-		CaCertPEM:            caCertPEM,
-		VereignCertPEM:       vereignCertPEM,
-		MaxMessageSize:       maxMessageSize,
+		DataStorageUrl: dataStorageAddress,
+		CertPEM:        certPEM,
+		KeyPEM:         privateKeyPEM,
+		CaCertPEM:      caCertPEM,
+		VereignCertPEM: vereignCertPEM,
+		MaxMessageSize: maxMessageSize,
 	}
 
 	// Load the certificates from PEM Strings
@@ -206,7 +206,7 @@ func StartGRPCServer(address string, certPEM, privateKeyPEM, caCertPEM, vereignC
 	opts := []grpc.ServerOption{
 		grpc.Creds(creds),
 		grpc.UnaryInterceptor(unaryInterceptor),
-		grpc.MaxRecvMsgSize(config.MaxMessageSize * 1024 * 1024),
+		grpc.MaxRecvMsgSize(config.Config.MaxMessageSize * 1024 * 1024),
 	}
 
 	// create a gRPC server object
@@ -260,12 +260,12 @@ func StartRESTServer(address, grpcAddress string, certPEM []byte) error {
 }
 
 func StartPrometheusServer() error {
-	if config.PrometeusListenAddress != "" {
+	if config.Config.PrometeusListenAddress != "" {
 		// start prometheus
 		promHandler := http.NewServeMux()
 		promHandler.Handle("/metrics", promhttp.Handler())
 		log.Println("Starting prometheus...")
-		err := http.ListenAndServe(config.PrometeusListenAddress, promHandler)
+		err := http.ListenAndServe(config.Config.PrometeusListenAddress, promHandler)
 
 		if err != nil {
 			return err
diff --git a/utils/utils.go b/utils/utils.go
index 315171f..63c0ff2 100644
--- a/utils/utils.go
+++ b/utils/utils.go
@@ -18,12 +18,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
 package utils
 
 import (
-	"code.vereign.com/code/viam-apis/errors"
 	"crypto/rand"
 	"crypto/x509"
 	"fmt"
 	"io"
 
+	"code.vereign.com/code/viam-apis/errors"
+
 	"code.vereign.com/code/viam-apis/log"
 
 	"encoding/pem"
@@ -155,11 +156,11 @@ func GetKey(client *client.DataStorageClientImpl, uuid string, keyType api.KeyTy
 }
 
 func CreateDataStorageClient(auth *authentication.Authentication) *dsclient.DataStorageClientImpl {
-	return clientutils.CreateDataStorageClient(auth, config.DataStorageUrl, config.CertificatePEM,
-		config.PrivateKeyPEM, config.CaCertificatePEM, config.MaxMessageSize)
+	return clientutils.CreateDataStorageClient(auth, config.Config.DataStorageAgentURL, config.Config.Certification.CertificatePEM,
+		config.Config.Certification.PrivateKeyPEM, config.Config.Certification.CaCertificatePEM, config.Config.MaxMessageSize)
 }
 
 func CreateEntitiesManagementClient(auth *authentication.Authentication) *emclient.EntitiesManagerClientImpl {
-	return clientutils.CreateEntitiesManagementClient(auth, config.EntitiesManagerUrl, config.CertificatePEM,
-		config.PrivateKeyPEM, config.CaCertificatePEM, config.MaxMessageSize)
+	return clientutils.CreateEntitiesManagementClient(auth, config.Config.EntitiesManagementAgentURL, config.Config.Certification.CertificatePEM,
+		config.Config.Certification.PrivateKeyPEM, config.Config.Certification.CaCertificatePEM, config.Config.MaxMessageSize)
 }
-- 
GitLab