package config import ( "crypto" "crypto/x509" "io/ioutil" "os" "path/filepath" "strings" "code.vereign.com/code/viam-apis/clientutils" "code.vereign.com/code/viam-apis/config" "code.vereign.com/code/viam-apis/errors" "code.vereign.com/code/viam-apis/log" "code.vereign.com/code/viam-apis/authentication" "github.com/spf13/viper" _ "github.com/spf13/viper/remote" ) var SystemAuth = &authentication.Authentication{ Uuid: "undefined", Session: "undefined", } type Configuration struct { ListenAddress string `required:"false" yaml:"listenAddress"` GrpcListenAddress string `required:"false" yaml:"grpcListenAddress"` SystemAuthentication struct { UUID string `required:"false" yaml:"viamUUID"` Session string `required:"false" yaml:"viamSession"` } `required:"false" yaml:"systemAuthentication"` DataStorageAgentURL string `required:"false" yaml:"dataStorageAgentURL"` EntitiesManagementAgentURL string `required:"false" yaml:"entitiesManagementAgentURL"` MaxMessageSize int `required:"false" yaml:"maxMessageSize"` Certification struct { Path string `required:"true" yaml:"path"` CertificateFile string `required:"true" yaml:"certificateFile"` CertificatePEM []byte `required:"true"` PrivateKeyFile string `required:"true" yaml:"privateKeyFile"` PrivateKeyPEM []byte `required:"true"` CaCertificateFile string `required:"true" yaml:"caCertificateFile"` CaCertificatePEM []byte `required:"true"` EncryptionCertificateFile string `required:"true" yaml:"encryptionCertificateFile"` EncryptionCertificatePEM []byte `required:"true"` EncryptionCertificate []*x509.Certificate `required:"true"` EncryptionPrivateKeyFile string `required:"true" yaml:"encryptionPrivateKeyFile"` EncryptionPrivateKeyPEM []byte `required:"true"` EncryptionPrivateKey crypto.Signer `required:"true"` VereignCertificateFile string `required:"true" yaml:"vereignCertificateFile"` VereignCertificatePEM []byte `required:"true"` } `required:"true" yaml:"certification"` PrometeusListenAddress string `required:"false" yaml:"prometeusListenAddress"` MetricEnvironmentPrefix string `required:"false" yaml:"metricEnvironmentPrefix"` ReplaceKey bool `required:"false" yaml:"replaceKey"` GlobalLogLevel string `required:"false" yaml:"globalLogLevel"` } var Config Configuration // LoadConfigValues loads config values from config file func LoadConfigValues(configFile, etcdURL string) error { setConfigValues(configFile, etcdURL) calculateConfigValues() err := config.CheckConfigValues(Config) if err != nil { log.Fatalf("Exiting due to wrong configuration: %s", err) return err } return nil } // SetConfigValues Sets Values For Config Variable func setConfigValues(configFile, etcdURL string) { // Set default values for configuration variable // NOTE: Only for 'required:"false"' 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 != "" { configName := strings.Split(filepath.Base(configFile), ".")[0] configDir := filepath.Dir(configFile) viper.SetConfigName(configName) viper.AddConfigPath(configDir) if err := viper.ReadInConfig(); err != nil { log.Printf("can't read config: %v, will use default values", err) } } 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") if err := viper.ReadRemoteConfig(); err != nil { log.Printf("can't read config: %v, will use default values", err) } } // 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") if err := viper.ReadRemoteConfig(); err != nil { errors.LogFormat(err, "can't read config, will use default values") } } err := viper.Unmarshal(&Config) if err != nil { log.Printf("unable to decode into config struct, %v", err) } } // CalculateConfigValues calculates config values using provided configuraion func calculateConfigValues() { SystemAuth.Uuid = Config.SystemAuthentication.UUID SystemAuth.Session = Config.SystemAuthentication.Session Config.Certification.CertificatePEM = getCertificatePEM() Config.Certification.PrivateKeyPEM = getPrivateKeyPEM() Config.Certification.CaCertificatePEM = getCaCertificatePEM() Config.Certification.VereignCertificatePEM = getVereignCertificatePEM() Config.Certification.EncryptionCertificatePEM = getEncryptionCertificatePEM() Config.Certification.EncryptionPrivateKeyPEM = getEncryptionPrivateKeyPEM() 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) } } func getCertificatePEM() []byte { pem, err := ioutil.ReadFile(Config.Certification.Path + "/" + Config.Certification.CertificateFile) if err != nil { errors.Log(err) return []byte("") } return pem } func getCaCertificatePEM() []byte { pem, err := ioutil.ReadFile(Config.Certification.Path + "/" + Config.Certification.CaCertificateFile) if err != nil { errors.Log(err) return []byte("") } return pem } func getPrivateKeyPEM() []byte { pem, err := ioutil.ReadFile(Config.Certification.Path + "/" + Config.Certification.PrivateKeyFile) if err != nil { errors.Log(err) return []byte("") } return pem } func getVereignCertificatePEM() []byte { pem, err := ioutil.ReadFile(Config.Certification.Path + "/" + Config.Certification.CaCertificateFile) if err != nil { errors.Log(err) return []byte("") } return pem } func getEncryptionCertificatePEM() []byte { pem, err := ioutil.ReadFile(Config.Certification.Path + "/" + Config.Certification.EncryptionCertificateFile) if err != nil { errors.Log(err) return []byte("") } return pem } func getEncryptionPrivateKeyPEM() []byte { pem, err := ioutil.ReadFile(Config.Certification.Path + "/" + Config.Certification.EncryptionPrivateKeyFile) if err != nil { errors.Log(err) return []byte("") } return pem }