dodo  0.0.1
A C++ library to create containerized Linux services
config.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the dodo library (https://github.com/jmspit/dodo).
3  * Copyright (c) 2019 Jan-Marten Spit.
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, version 3.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 /**
19  * @file config.cpp
20  * Implements the dodo::common::Config class.
21  */
22 
23 #include <fstream>
24 #include <iostream>
25 #include <sstream>
26 
27 #include <common/config.hpp>
28 #include <common/datacrypt.hpp>
29 #include <common/exception.hpp>
30 #include <common/util.hpp>
31 
32 namespace dodo::common {
33 
34  const Config::KeyPath Config::config_dodo = {"dodo"};
35  const Config::KeyPath Config::config_dodo_common = {"dodo","common"};
36  const Config::KeyPath Config::config_dodo_common_application = {"dodo","common","application"};
37  const Config::KeyPath Config::config_dodo_common_application_name = {"dodo","common","application","name"};
38  const Config::KeyPath Config::config_dodo_common_application_secret = {"dodo","common","application","secret"};
39  const Config::KeyPath Config::config_dodo_common_application_secret_file = {"dodo","common","application","secret","file"};
40  const Config::KeyPath Config::config_dodo_common_application_secret_env = {"dodo","common","application","secret","env"};
41  const Config::KeyPath Config::config_dodo_common_logger = {"dodo","common","logger"};
42  const Config::KeyPath Config::config_dodo_common_logger_console = {"dodo","common","logger","console"};
43  const Config::KeyPath Config::config_dodo_common_logger_console_level = {"dodo","common","logger","console","level"};
44  const Config::KeyPath Config::config_dodo_common_logger_file = {"dodo","common","logger","file"};
45  const Config::KeyPath Config::config_dodo_common_logger_file_level = {"dodo","common","logger","file","level"};
46  const Config::KeyPath Config::config_dodo_common_logger_file_directory = {"dodo","common","logger","file","directory"};
47  const Config::KeyPath Config::config_dodo_common_logger_file_max_size_mib = {"dodo","common","logger","file","max-size-mib"};
48  const Config::KeyPath Config::config_dodo_common_logger_file_max_file_trail = {"dodo","common","logger","file","max-file-trail"};
49  const Config::KeyPath Config::config_dodo_common_logger_syslog = {"dodo","common","logger","syslog"};
50  const Config::KeyPath Config::config_dodo_common_logger_syslog_level = {"dodo","common","logger","syslog","level"};
51  const Config::KeyPath Config::config_dodo_common_logger_syslog_facility = {"dodo","common","logger","syslog","facility"};
52 
53  Config* Config::config_ = nullptr;
54 
55  std::string Config::path_ = "";
56 
57  Config::Config( const std::string path ) {
58  path_ = path;
59  readConfig();
60  }
61 
62  Config* Config::initialize( const std::string path ) {
63  if ( config_ ) throw_Exception( "calling initialize on an existing Config singleton" );
64  config_ = new Config( path );
65  return config_;
66  }
67 
69  if ( config_ == nullptr ) throw_Exception( "null singleton - call initialize before getConfig" );
70  return config_;
71  }
72 
74  try {
75  if ( exists(config_dodo) ) {
76  if ( exists(config_dodo_common) ) {
79  << " node missing" );
84  char* c = secure_getenv( getValue<std::string>(config_dodo_common_application_secret_env).c_str() );
85  if ( c ) secret_ = c;
86  else throw_Exception( "ENV var " << getValue<std::string>( config_dodo_common_application_secret_env ) << " does not exist" );
87  } else throw_Exception( flattenKeyPath( config_dodo_common_application_secret ) << " must have one of 'file' or 'env'" );
88  }
89  } else throw_Exception( flattenKeyPath( config_dodo_common_application ) << " node missing" );
91 
96 
102  }
103 
107  }
108  } else throw_Exception( flattenKeyPath(config_dodo_common_logger) << " node missing" );
109  } else throw_Exception( flattenKeyPath(config_dodo_common) << " node missing" );
110  } else throw_Exception( flattenKeyPath(config_dodo) << " node missing" );
111  }
112  catch ( const std::exception &e ) {
113  throw_Exception( "Config file '" << path_ << "' content error: " << e.what() );
114  }
115  }
116 
118  try {
119  yaml_ = YAML::LoadFile(path_);
120  }
121  catch ( const std::exception &e ) {
122  throw_Exception( "Config file '" << path_ << "' parse error: " << e.what() );
123  }
124  checkConfig();
125  }
126 
127  std::string Config::flattenKeyPath( const KeyPath& keypath ) {
128  std::stringstream ss;
129  for ( const auto &k : keypath ) {
130  if ( ss.str().size() ) ss << "::";
131  ss << k;
132  }
133  return ss.str();
134  }
135 
136  void Config::getDecryptedValue( const KeyPath &keypath, Bytes &decrypted ) {
137  YAML::Node ref = Clone( yaml_ );
138  for( const auto &k : keypath ) {
139  if ( ! ref[k] ) throw_Exception( "key " << flattenKeyPath(keypath) << " not found in " << path_ );
140  ref = ref[k];
141  }
142  DataCrypt::decrypt( getSecret(), ref.as<std::string>(), decrypted );
143  }
144 
145 
146 }
dodo::common::Config::config_dodo_common_logger
static const Config::KeyPath config_dodo_common_logger
The dodo.common.logger node.
Definition: config.hpp:92
dodo::common::Config::exists
bool exists(const KeyPath &keypath) const
Return true if the KeyPath exists.
Definition: config.hpp:201
dodo::common::Config::getConfig
static Config * getConfig()
return the singleton.
Definition: config.cpp:68
dodo::common::Config::secret_
std::string secret_
The encryption secret / key.
Definition: config.hpp:253
dodo::common::fileReadString
std::string fileReadString(const std::string &filename)
Read the file as a single string.
Definition: util.cpp:161
config.hpp
dodo::common::Config::config_
static Config * config_
The singleton pointer.
Definition: config.hpp:238
dodo::common::DataCrypt::decrypt
static int decrypt(const std::string &key, const std::string src, Bytes &dest)
Decrypt data with a key.
Definition: datacrypt.cpp:129
dodo::common::Config::config_dodo_common_application_secret_file
static const Config::KeyPath config_dodo_common_application_secret_file
The dodo.common.application.secret.file node.
Definition: config.hpp:86
dodo::common::Bytes
An array of Octets with size elements.
Definition: bytes.hpp:44
dodo::common::Config::config_dodo_common_logger_syslog_level
static const Config::KeyPath config_dodo_common_logger_syslog_level
The dodo.common.logger.syslog.level node.
Definition: config.hpp:119
dodo::common::Config::getSecret
std::string getSecret() const
Get the application secret.
Definition: config.hpp:180
dodo::common::Config::config_dodo
static const Config::KeyPath config_dodo
The dodo root node.
Definition: config.hpp:71
dodo::common::Config::config_dodo_common_application
static const Config::KeyPath config_dodo_common_application
The dodo.common.application node.
Definition: config.hpp:77
dodo::common::Config::config_dodo_common_logger_file_directory
static const Config::KeyPath config_dodo_common_logger_file_directory
The dodo.common.logger.file.directory node.
Definition: config.hpp:107
dodo::common::Config::yaml_
YAML::Node yaml_
The root YAML node.
Definition: config.hpp:248
dodo::common::Config::Config
Config(const Config &)=delete
Disallow the copy constructor as this is a singleton.
dodo::common::Config::config_dodo_common_logger_syslog
static const Config::KeyPath config_dodo_common_logger_syslog
The dodo.common.logger.syslog node.
Definition: config.hpp:116
dodo::common::Config::readConfig
void readConfig()
Read the configuration file.
Definition: config.cpp:117
dodo::common::Config::config_dodo_common_logger_console_level
static const Config::KeyPath config_dodo_common_logger_console_level
The dodo.common.logger.console.level node.
Definition: config.hpp:98
dodo::common::Config::config_dodo_common
static const Config::KeyPath config_dodo_common
The dodo.common node.
Definition: config.hpp:74
dodo::common::Config
Singleton interface to a (read-only) deployment configuration, combining data from the deployment con...
Definition: config.hpp:52
dodo::common::Config::config_dodo_common_logger_file_max_file_trail
static const Config::KeyPath config_dodo_common_logger_file_max_file_trail
The dodo.common.logger.file.max-file-trail node.
Definition: config.hpp:113
throw_Exception
#define throw_Exception(what)
Throws an Exception, passes FILE and LINE to constructor.
Definition: exception.hpp:174
dodo::common::Config::path_
static std::string path_
The path to the configuration file.
Definition: config.hpp:243
datacrypt.hpp
dodo::common::Config::checkConfig
void checkConfig()
Check for required elements in the config file.
Definition: config.cpp:73
dodo::common
Common and utility interfaces.
Definition: application.hpp:29
dodo::common::Config::config_dodo_common_logger_file_level
static const Config::KeyPath config_dodo_common_logger_file_level
The dodo.common.logger.file.level node.
Definition: config.hpp:104
dodo::common::Config::config_dodo_common_logger_syslog_facility
static const Config::KeyPath config_dodo_common_logger_syslog_facility
The dodo.common.logger.syslog.facility node.
Definition: config.hpp:122
exception.hpp
dodo::common::Config::KeyPath
std::list< std::string > KeyPath
Used by getValue, enable use of list initializers as path specification, eg.
Definition: config.hpp:68
dodo::common::Config::config_dodo_common_application_secret
static const Config::KeyPath config_dodo_common_application_secret
The dodo.common.application.secret node.
Definition: config.hpp:83
dodo::common::Config::config_dodo_common_application_name
static const Config::KeyPath config_dodo_common_application_name
The dodo.common.application.name node.
Definition: config.hpp:80
dodo::common::Config::initialize
static Config * initialize(const std::string path)
Initialize the singleton.
Definition: config.cpp:62
dodo::common::Config::config_dodo_common_logger_console
static const Config::KeyPath config_dodo_common_logger_console
The dodo.common.logger.console node.
Definition: config.hpp:95
dodo::common::Config::config_dodo_common_application_secret_env
static const Config::KeyPath config_dodo_common_application_secret_env
The dodo.common.application.secret.env node.
Definition: config.hpp:89
dodo::common::Config::config_dodo_common_logger_file
static const Config::KeyPath config_dodo_common_logger_file
The dodo.common.logger.file node.
Definition: config.hpp:101
util.hpp
dodo::common::Config::flattenKeyPath
static std::string flattenKeyPath(const KeyPath &keypath)
Transform a keypath to a string with ":" as seperator between levels.
Definition: config.cpp:127
dodo::common::Config::config_dodo_common_logger_file_max_size_mib
static const Config::KeyPath config_dodo_common_logger_file_max_size_mib
The dodo.common.logger.file.max-size-mib node.
Definition: config.hpp:110
dodo::common::Config::getDecryptedValue
void getDecryptedValue(const KeyPath &keypath, Bytes &decrypted)
Get the decrypted value from KeyPath - decrypted using the secret from getSecret().
Definition: config.cpp:136