Skip to content
Snippets Groups Projects

config changes

11 files
+ 253
488
Compare changes
  • Side-by-side
  • Inline
Files
11
+ 161
172
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
}
Loading