AOSharedServiceLibrary
tiered_app_profile.h
1 /*
2 MIT License Block
3 
4 Copyright (c) 2016 Alex Barry
5 
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
12 
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15 
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 THE SOFTWARE.
23 */
24 
25 #include <sys/stat.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <algorithm>
29 #include <cstdlib>
30 #include <iostream>
31 #include <string>
32 #include <unordered_map>
33 #include <exception>
34 #include <vector>
35 #include <utility>
36 #include <iterator>
37 #include <sstream>
38 #include <fstream>
39 
40 #include "rapidjson/document.h"
41 #include "rapidjson/error/en.h"
42 
43 #include "aossl/core/include/kv_store.h"
44 #include "aossl/core/include/kv_store_interface.h"
45 #include "aossl/profile/include/app_profile.h"
46 #include "aossl/profile/include/safe_app_profile.h"
47 #include "aossl/vault/include/vault_interface.h"
48 #include "aossl/vault/include/factory_vault.h"
49 
50 #ifndef AOSSL_PROFILE_INCLUDE_TIERED_APP_PROFILE_H_
51 #define AOSSL_PROFILE_INCLUDE_TIERED_APP_PROFILE_H_
52 
53 namespace AOSSL {
54 
56 
64  std::string props_file_name;
65  std::string cluster_name;
66  std::string configuration_key_start;
67  std::vector<std::string> secure_opt_keys;
68  std::vector<std::string> config_record;
69  inline bool exists_test(const std::string& name) {
70  struct stat buffer;
71  return (stat (name.c_str(), &buffer) == 0);
72  }
73 
74  // Load a value from a KV Store
75  inline void load_config_value(KeyValueStoreInterface *kv, std::string& key) {
76  if (kv) {
77  if (kv->opt_exist(key)) {
79  kv->get_opt(key, buf);
80  KeyValueStore::set_opt(key, buf.val);
81  }
82  }
83  }
84 
85  // Retrieve a secret from Vault
86  inline void get_vault_secret(KeyValueStoreInterface *kv, std::string& key, StringBuffer& return_buf) {
87  StringBuffer buf;
88  kv->get_opt(key, buf);
89  if (buf.success && !(buf.val.empty())) {
90  // Parse out the data and compare it
91  rapidjson::Document d;
92  d.Parse<rapidjson::kParseStopWhenDoneFlag>(buf.val.c_str());
93  if (d.HasParseError()) {
94  return_buf.success = false;
95  return_buf.err_msg.assign(GetParseError_En(d.GetParseError()));
96  } else {
97  if (d.IsObject()) {
98  const rapidjson::Value& token_val = d["data"]["data"][key.c_str()];
99  return_buf.val.assign(token_val.GetString());
100  }
101  }
102  } else {
103  return_buf.success = false;
104  return_buf.err_msg.assign(buf.err_msg);
105  }
106  }
107 
108  // Load a value from Vault into configuration
109  inline void load_vault_secret(KeyValueStoreInterface *kv, std::string& key) {
110  if (kv) {
111  StringBuffer buf;
112  std::string vault_key = key;
113  // Convert to all caps
114  std::transform(vault_key.begin(), vault_key.end(), vault_key.begin(), toupper);
115  // Convert '.' to '_'
116  std::replace(vault_key.begin(), vault_key.end(), '.', '_');
117  get_vault_secret(kv, vault_key, buf);
118  if (buf.success) {
119  KeyValueStore::set_opt(key, buf.val);
120  } else {
121  config_record.push_back(std::string("Failed to retrieve Vault Secret: ") \
122  + buf.err_msg);
123  }
124  }
125  }
126 
127  // Load a value from Consul
128  inline void load_consul_value(ConsulInterface *kv, std::string& key) {
129  if (kv) {
130  if (key.empty()) return;
131  // Copy the key before modifying in-place
132  std::string env_key = key;
133  // Convert to all caps
134  std::transform(env_key.begin(), env_key.end(), env_key.begin(), toupper);
135  // Convert '.' to '_'
136  std::replace(env_key.begin(), env_key.end(), '.', '_');
137  std::string query_key;
138  // Prefix the key with the application & profile name
139  // to ensure we get unique values for different apps
140  if (!(ApplicationProfile::get_app_name().empty() && \
142  query_key = ApplicationProfile::get_app_name() + std::string("/") + \
143  ApplicationProfile::get_profile_name() + std::string("/");
144  }
145  query_key = query_key + env_key;
146  if (kv->opt_exist(query_key)) {
148  kv->get_opt(query_key, buf);
149  if (!(buf.val.empty()) && buf.success) {
150  // Parse the response
151  rapidjson::Document d;
152  d.Parse<rapidjson::kParseStopWhenDoneFlag>(buf.val.c_str());
153  if (d.HasParseError()) {
154  throw std::invalid_argument(GetParseError_En(d.GetParseError()));
155  }
156  // Pull the value field
157  StringBuffer parsed_buffer;
158  std::string value_string;
159  if (d.IsArray()) {
160  for (auto& itr : d.GetArray()) {
161  rapidjson::Value::ConstMemberIterator val_iter = \
162  itr.FindMember("Value");
163  if (val_iter != itr.MemberEnd()) {
164  if (!(val_iter->value.IsNull())) {
165  parsed_buffer.val.assign(val_iter->value.GetString());
166  }
167  }
168  }
169  }
170  // decode the base64 value
171  StringBuffer decoded_buffer;
173  parsed_buffer.val, decoded_buffer);
174  if (KeyValueStore::opt_exist(key)) {
175  KeyValueStore::set_opt(key, decoded_buffer.val);
176  }
177  }
178  }
179  }
180  }
181 
182  // Load a value from an environment variable
183  inline void load_environment_variable(std::string& key) {
184  // Copy the key before modifying in-place
185  std::string env_key = key;
186  // Convert to all caps
187  std::transform(env_key.begin(), env_key.end(), env_key.begin(), toupper);
188  // Convert '.' to '_'
189  std::replace(env_key.begin(), env_key.end(), '.', '_');
190  // Get the environment variable
191  const char *env_value = std::getenv(env_key.c_str());
192  if (env_value && KeyValueStore::opt_exist(key)) {
193  std::string env_str(env_value);
194  KeyValueStore::set_opt(key, env_str);
195  }
196  }
197 
198  inline void load_vault_info(KeyValueStoreInterface *kv, \
199  bool auth_details_included, std::string& un, std::string& pw) {
200  if (kv) {
201  // Check the commandline arguments for Vault Information
202  std::string vault_addr_key = configuration_key_start + "vault";
203  std::string vault_cert_key = configuration_key_start + "vault.cert";
204  std::string vault_atype_key = configuration_key_start + "vault.authtype";
205  std::string vault_un_key = configuration_key_start + "vault.un";
206  std::string vault_pw_key = configuration_key_start + "vault.pw";
207  std::string secrets_path("/v1/secret/data/");
208  int auth_type = BASIC_AUTH_TYPE;
209  StringBuffer vault_addr_buf;
210  StringBuffer vault_cert_buf;
211  StringBuffer vault_authtype_buf;
212  StringBuffer vault_un_buf;
213  StringBuffer vault_pw_buf;
214  // Check for authentication info
215  if (auth_details_included || (kv->opt_exist(vault_un_key) && kv->opt_exist(vault_pw_key))) {
216  if (auth_details_included) {
217  vault_un_buf.val.assign(un);
218  vault_pw_buf.val.assign(pw);
219  } else {
220  kv->get_opt(vault_un_key, vault_un_buf);
221  kv->get_opt(vault_pw_key, vault_pw_buf);
222  }
223  // Check for the rest of the config info for Vault
224  if (kv->opt_exist(vault_addr_key) && kv->opt_exist(vault_cert_key) \
225  && kv->opt_exist(vault_atype_key)) {
226  kv->get_opt(vault_addr_key, vault_addr_buf);
227  kv->get_opt(vault_cert_key, vault_cert_buf);
228  kv->get_opt(vault_atype_key, vault_authtype_buf);
229  if (vault_authtype_buf.val == "APPROLE") {
230  auth_type = APPROLE_AUTH_TYPE;
231  }
232  config_record.push_back(std::string("Setting Vault Information: ") \
233  + vault_addr_buf.val);
234  ApplicationProfile::set_vault_address(vault_addr_buf.val, secrets_path, \
235  5, vault_cert_buf.val, auth_type, vault_un_buf.val, vault_pw_buf.val);
236  } else if (kv->opt_exist(vault_addr_key) && kv->opt_exist(vault_atype_key)) {
237  kv->get_opt(vault_addr_key, vault_addr_buf);
238  kv->get_opt(vault_atype_key, vault_authtype_buf);
239  kv->get_opt(vault_un_key, vault_un_buf);
240  kv->get_opt(vault_pw_key, vault_pw_buf);
241  if (vault_authtype_buf.val == "APPROLE") {
242  auth_type = APPROLE_AUTH_TYPE;
243  }
244  config_record.push_back(std::string("Setting Vault Information: ") \
245  + vault_addr_buf.val);
246  ApplicationProfile::set_vault_address(vault_addr_buf.val, secrets_path, \
247  5, auth_type, vault_un_buf.val, vault_pw_buf.val);
248  }
249  }
250  }
251  }
252 
253  inline void load_consul_info(KeyValueStoreInterface *kv, \
254  StringBuffer& vconsul_cert_buf, StringBuffer& vconsul_token_buf) {
255  if (kv) {
256  // Check the commandline arguments for Consul Information
257  std::string consul_add_key = configuration_key_start + "consul";
258  std::string consul_cert_key = configuration_key_start + "consul.cert";
259  std::string consul_token_key = configuration_key_start + "consul.token";
260  StringBuffer consul_addr_buf;
261  StringBuffer consul_cert_buf;
262  StringBuffer consul_token_buf;
263  // We have a pre-existing cert and token, and have been given an address
264  if (kv->opt_exist(consul_add_key) && vconsul_cert_buf.success && \
265  vconsul_token_buf.success) {
266  kv->get_opt(consul_add_key, consul_addr_buf);
267  config_record.push_back(std::string("Setting Consul Information: ") \
268  + consul_addr_buf.val);
269  ApplicationProfile::set_consul_address(consul_addr_buf.val, 5, \
270  vconsul_cert_buf.val, vconsul_token_buf.val);
271  // We have been given an address, cert, and a pre-existing token
272  } else if (kv->opt_exist(consul_add_key) && kv->opt_exist(consul_cert_key) && \
273  vconsul_token_buf.success) {
274  kv->get_opt(consul_add_key, consul_addr_buf);
275  kv->get_opt(consul_cert_key, consul_cert_buf);
276  config_record.push_back(std::string("Setting Consul Information: ") \
277  + consul_addr_buf.val);
278  ApplicationProfile::set_consul_address(consul_addr_buf.val, 5, \
279  consul_cert_buf.val, vconsul_token_buf.val);
280  // We have been given an address, cert, and a token
281  } else if (kv->opt_exist(consul_add_key) && \
282  kv->opt_exist(consul_cert_key) && \
283  kv->opt_exist(consul_token_key)) {
284  config_record.push_back(std::string("Setting Consul Information: ") \
285  + consul_addr_buf.val);
286  kv->get_opt(consul_add_key, consul_addr_buf);
287  kv->get_opt(consul_cert_key, consul_cert_buf);
288  kv->get_opt(consul_token_key, consul_token_buf);
289  ApplicationProfile::set_consul_address(consul_addr_buf.val, 5, \
290  consul_cert_buf.val, consul_token_buf.val);
291  // We have been given an address and a cert
292  } else if (kv->opt_exist(consul_add_key) && \
293  (kv->opt_exist(consul_cert_key) || vconsul_cert_buf.success)) {
294  kv->get_opt(consul_add_key, consul_addr_buf);
295  if (vconsul_cert_buf.success) {
296  consul_cert_buf.val = vconsul_cert_buf.val;
297  consul_cert_buf.success = true;
298  } else {
299  kv->get_opt(consul_cert_key, consul_cert_buf);
300  }
301  config_record.push_back(std::string("Secure Consul Connection: ") \
302  + consul_addr_buf.val);
303  ApplicationProfile::set_consul_address(consul_addr_buf.val, 5, \
304  consul_cert_buf.val);
305  // We have been given an address and a token
306  } else if (kv->opt_exist(consul_add_key) && \
307  (kv->opt_exist(consul_token_key) || vconsul_token_buf.success)) {
308  kv->get_opt(consul_add_key, consul_addr_buf);
309  if (vconsul_token_buf.success) {
310  consul_token_buf.val = vconsul_token_buf.val;
311  consul_token_buf.success = true;
312  } else {
313  kv->get_opt(consul_token_key, consul_token_buf);
314  }
315  config_record.push_back(std::string("Authenticated Consul Connection: ") \
316  + consul_addr_buf.val);
318  config_record.push_back(std::string("Adding ACL Token: ") \
319  + consul_addr_buf.val);
320  ApplicationProfile::get_consul()->add_acl_token(consul_token_buf.val);
321  // We've been given an address
322  } else if (kv->opt_exist(consul_add_key)) {
323  kv->get_opt(consul_add_key, consul_addr_buf);
324  config_record.push_back(std::string("Setting Consul Information: ") \
325  + consul_addr_buf.val);
327  }
328  }
329  }
330 
331  // Initialize the Profile
332  inline void init() {
333  // See if we have a profile name provided
335  if (ApplicationProfile::get_cli()->opt_exist(std::string("profile"))) {
336  StringBuffer profile_name_buf;
337  ApplicationProfile::get_cli()->get_opt(std::string("profile"), profile_name_buf);
338  ApplicationProfile::set_profile_name(profile_name_buf.val);
339  }
340  }
341 
342  // What should the start of our config strings be?
343  std::string config_key_start;
344  if (!(ApplicationProfile::get_app_name().empty())) {
345  config_key_start += ApplicationProfile::get_app_name();
346  config_key_start += std::string(".");
347  }
348  if (!(ApplicationProfile::get_profile_name().empty())) {
349  config_key_start += ApplicationProfile::get_profile_name();
350  config_key_start += std::string(".");
351  }
352  config_record.push_back(config_key_start);
353  configuration_key_start.assign(config_key_start);
354  std::string env_config_key_start(config_key_start);
355  std::transform(env_config_key_start.begin(), env_config_key_start.end(), \
356  env_config_key_start.begin(), toupper);
357  std::replace(env_config_key_start.begin(), env_config_key_start.end(), '.', '_');
358  // Start by looking for properties files, as values for other configs can
359  // be stored in the props files.
360 
361  // Check Env Variables for a Properties File
362  std::string props_env_key = env_config_key_start + std::string("PROPS_FILE");
363  const char *env_props_value = std::getenv(props_env_key.c_str());
364  if (env_props_value) {
365  std::string props_file_str(env_props_value);
367  config_record.push_back(std::string("Setting Properties File: ") \
368  + props_file_str);
369  }
370 
371  // Check the commandline arguments for a properties file
372  std::string props_key = config_key_start + std::string("props");
374  if (ApplicationProfile::get_cli()->opt_exist(props_key)) {
375  StringBuffer props_buf;
376  ApplicationProfile::get_cli()->get_opt(props_key, props_buf);
378  config_record.push_back(std::string("Setting Properties File: ") \
379  + props_buf.val);
380  }
381  }
382 
383  // Check for default property files
384  props_file_name = "/etc/";
385  props_file_name += ApplicationProfile::get_app_name();
386  props_file_name += "/app.properties";
387  if ((!(ApplicationProfile::get_props())) && exists_test(props_file_name)) {
388  ApplicationProfile::set_property_file(props_file_name);
389  config_record.push_back(std::string("Setting Properties File: ") \
390  + props_file_name);
391  }
392  props_file_name = "app.properties";
393  if ((!(ApplicationProfile::get_props())) && exists_test(props_file_name)) {
394  ApplicationProfile::set_property_file(props_file_name);
395  config_record.push_back(std::string("Setting Properties File: ") \
396  + props_file_name);
397  }
398 
399  // Next, we want to check for Vault information, as further
400  // security information needed for configuration may be held there.
401 
402  std::string vault_un_file = "vault_un.txt";
403  std::string vault_pw_file = "vault_pw.txt";
404  std::string vault_un_value;
405  std::string vault_pw_value;
406  bool vault_auth_from_file = false;
407 
408  // See if we have vault username/password files
409  if (exists_test(vault_un_file) && exists_test(vault_pw_file)) {
410  std::ifstream unfs(vault_un_file);
411  vault_un_value.assign((std::istreambuf_iterator<char>(unfs)), \
412  (std::istreambuf_iterator<char>()));
413  std::ifstream pwfs(vault_pw_file);
414  vault_pw_value.assign((std::istreambuf_iterator<char>(pwfs)), \
415  (std::istreambuf_iterator<char>()));
416  vault_auth_from_file = true;
417  config_record.push_back(std::string("Using Vault authentication info from files"));
418  }
419 
420  // Check environment variables for vault information
421  std::string env_vault_addr_key = env_config_key_start + std::string("VAULT_ADDRESS");
422  std::string env_vault_cert_key = env_config_key_start + std::string("VAULT_SSL_CERT");
423  std::string env_vault_authtype_key = env_config_key_start + std::string("VAULT_AUTH_TYPE");
424  std::string env_vault_authun_key = env_config_key_start + std::string("VAULT_AUTH_UN");
425  std::string env_vault_authpw_key = env_config_key_start + std::string("VAULT_AUTH_PW");
426  const char *env_vault_addr = std::getenv(env_vault_addr_key.c_str());
427  const char *env_vault_cert = std::getenv(env_vault_cert_key.c_str());
428  const char *env_vault_authtype = std::getenv(env_vault_authtype_key.c_str());
429  const char *env_vault_authun = std::getenv(env_vault_authun_key.c_str());
430  const char *env_vault_authpw = std::getenv(env_vault_authpw_key.c_str());
431  std::string un;
432  std::string pw;
433  if (env_vault_addr && env_vault_cert && env_vault_authtype) {
434  if (vault_auth_from_file || (env_vault_authun && env_vault_authpw)) {
435  if (vault_auth_from_file) {
436  un.assign(vault_un_value);
437  pw.assign(vault_pw_value);
438  } else {
439  un.assign(env_vault_authun);
440  pw.assign(env_vault_authpw);
441  }
442  std::string vaddr(env_vault_addr);
443  std::string cert(env_vault_cert);
444  std::string secrets_path("/v1/secret/data/");
445  std::string authtype_string(env_vault_authtype);
446  int auth_type = BASIC_AUTH_TYPE;
447  if (authtype_string == "APPROLE") {
448  auth_type = APPROLE_AUTH_TYPE;
449  }
450  config_record.push_back(std::string("Setting Vault Information from Environment Variables: ") \
451  + vaddr);
452  ApplicationProfile::set_vault_address(vaddr, secrets_path, 5, cert, auth_type, un, pw);
453  }
454  } else if (env_vault_addr && env_vault_authtype && env_vault_authun && env_vault_authpw) {
455  if (vault_auth_from_file) {
456  un.assign(vault_un_value);
457  pw.assign(vault_pw_value);
458  } else {
459  un.assign(env_vault_authun);
460  pw.assign(env_vault_authpw);
461  }
462  std::string vaddr(env_vault_addr);
463  std::string secrets_path("/v1/secret/data/");
464  std::string authtype_string(env_vault_authtype);
465  int auth_type = BASIC_AUTH_TYPE;
466  if (authtype_string == "APPROLE") {
467  auth_type = APPROLE_AUTH_TYPE;
468  }
469  config_record.push_back(std::string("Setting Vault Information from Environment Variables: ") \
470  + vaddr);
471  ApplicationProfile::set_vault_address(vaddr, secrets_path, 5, auth_type, un, pw);
472  }
473  // Try to load vault information from the CLI arguments
474  load_vault_info(ApplicationProfile::get_cli(), vault_auth_from_file, vault_un_value, vault_pw_value);
475  // Try to load vault information from the Properties File
476  load_vault_info(ApplicationProfile::get_props(), vault_auth_from_file, vault_un_value, vault_pw_value);
477 
478  // Next, we'll check for any Consul information
479 
480  // Start by checking Vault for any SSL Certs or ACL Tokens.
481  std::string consul_cert_vault_key = env_config_key_start \
482  + std::string("CONSUL_SSL_CERT");
483  std::string consul_token_vault_key = env_config_key_start \
484  + std::string("CONSUL_ACL_TOKEN");
485  StringBuffer consul_cert_buf;
486  consul_cert_buf.success = false;
487  StringBuffer consul_token_buf;
488  consul_token_buf.success = false;
490  config_record.push_back(std::string("Checking Vault for Consul Security info"));
491  get_vault_secret(ApplicationProfile::get_vault(), consul_cert_vault_key, consul_cert_buf);
492  get_vault_secret(ApplicationProfile::get_vault(), consul_token_vault_key, consul_token_buf);
493  }
494 
495  // See if we've been instructed to generate the Consul ACL token
496  // from the Vault Consul Secrets Engine, rather than the KV Store
497  bool generate_consul_token = false;
498  StringBuffer gen_consul_token_buf;
500  std::string gen_consul_token_key = config_key_start + "consul.token.role";
501  if (ApplicationProfile::get_cli()->opt_exist(gen_consul_token_key)) {
502  generate_consul_token = true;
503  ApplicationProfile::get_cli()->get_opt(gen_consul_token_key, gen_consul_token_buf);
504  }
505  }
506 
507  std::string env_get_consul_token_key = env_config_key_start \
508  + std::string("CONSUL_TOKEN_ROLE");
509  const char *env_gen_consul_token = std::getenv(env_get_consul_token_key.c_str());
510  if (env_gen_consul_token) {
511  gen_consul_token_buf.val.assign(env_gen_consul_token);
512  gen_consul_token_buf.success = true;
513  generate_consul_token = true;
514  }
515 
516  if (generate_consul_token && gen_consul_token_buf.success) {
517  config_record.push_back("Generating Consul ACL Token with role: " + gen_consul_token_buf.val);
518  ApplicationProfile::get_vault()->gen_consul_token(gen_consul_token_buf.val, \
519  consul_token_buf);
520  if (!(consul_token_buf.success)) {
521  config_record.push_back(std::string("Failed to generate Consul ACL Token: ") \
522  + consul_token_buf.err_msg);
523  }
524  }
525 
526  // Check the Properties file for the Consul args
527  load_consul_info(ApplicationProfile::get_props(), consul_cert_buf, consul_token_buf);
528 
529  // Check Env Variables for Consul Information
530  std::string env_consul_value_key = env_config_key_start \
531  + std::string("CONSUL_ADDRESS");
532  std::string env_consul_cert_key = env_config_key_start \
533  + std::string("CONSUL_SSL_CERT");
534  std::string env_consul_token_key = env_config_key_start \
535  + std::string("CONSUL_ACL_TOKEN");
536  const char *env_consul_value = std::getenv(env_consul_value_key.c_str());
537  const char *env_consul_cert_value = std::getenv(env_consul_cert_key.c_str());
538  const char *env_consul_token_value = std::getenv(env_consul_token_key.c_str());
539  if (env_consul_value && env_consul_cert_value && env_consul_token_value) {
540  std::string consul_addr_str(env_consul_value);
541  std::string consul_cert_str(env_consul_cert_value);
542  std::string consul_token_str(env_consul_token_value);
543  config_record.push_back(std::string("Setting Consul Address: ") + consul_addr_str);
544  ApplicationProfile::set_consul_address(consul_addr_str, 5, consul_cert_str, env_consul_value);
545  } else if (env_consul_value && env_consul_cert_value) {
546  std::string consul_addr_str(env_consul_value);
547  std::string consul_cert_str(env_consul_cert_value);
548  config_record.push_back(std::string("Setting Consul Address: ") + consul_addr_str);
549  ApplicationProfile::set_consul_address(consul_addr_str, 5, consul_cert_str);
550  } else if (env_consul_value) {
551  // Mix environment variables with token/certs retrieved from Vault
552  std::string consul_addr_str(env_consul_value);
553  if (consul_cert_buf.success && consul_token_buf.success) {
554  config_record.push_back(std::string("Setting Consul Address: ") + consul_addr_str);
555  ApplicationProfile::set_consul_address(consul_addr_str, 5, consul_cert_buf.val, consul_token_buf.val);
556  } else if (consul_cert_buf.success && env_consul_token_value) {
557  std::string consul_token_str(env_consul_token_value);
558  config_record.push_back(std::string("Setting Consul Address: ") + consul_addr_str);
559  ApplicationProfile::set_consul_address(consul_addr_str, 5, consul_cert_buf.val, consul_token_str);
560  } else if (env_consul_cert_value && consul_token_buf.success) {
561  std::string consul_cert_str(env_consul_cert_value);
562  config_record.push_back(std::string("Setting Consul Address: ") + consul_addr_str);
563  ApplicationProfile::set_consul_address(consul_addr_str, 5, consul_cert_str, consul_token_buf.val);
564  } else {
565  config_record.push_back(std::string("Setting Consul Address: ") + consul_addr_str);
567  }
568  }
569 
570  // Check the commandline arguments for the Consul args
571  load_consul_info(ApplicationProfile::get_cli(), consul_cert_buf, consul_token_buf);
572 
573  // Check for a provided Cluster Name
574  std::string cluster_key = config_key_start + std::string("cluster");
575  std::string env_cluster_key = env_config_key_start + std::string("CLUSTER");
577  if (ApplicationProfile::get_props()->opt_exist(cluster_key)) {
578  StringBuffer cluster_name_buf;
579  ApplicationProfile::get_props()->get_opt(cluster_key, cluster_name_buf);
580  cluster_name.assign(cluster_name_buf.val);
581  config_record.push_back(std::string("Setting Cluster Name: ") + cluster_name);
582  }
583  }
585  if (ApplicationProfile::get_cli()->opt_exist(cluster_key)) {
586  StringBuffer cluster_name_buf;
587  ApplicationProfile::get_cli()->get_opt(cluster_key, cluster_name_buf);
588  cluster_name.assign(cluster_name_buf.val);
589  config_record.push_back(std::string("Setting Cluster Name: ") + cluster_name);
590  }
591  }
592  const char *env_cluster_name = std::getenv(env_cluster_key.c_str());
593  if (env_cluster_name) {
594  cluster_name.assign(env_cluster_name);
595  config_record.push_back(std::string("Setting Cluster Name: ") + cluster_name);
596  }
597  }
598 
599  public:
600  TieredApplicationProfile(int argc, char* argv[]) : \
601  SafeApplicationProfile(argc, argv) {init();}
602  TieredApplicationProfile(int argc, char* argv[], std::string app_name, \
603  std::string prof_name) : \
604  SafeApplicationProfile(argc, argv, app_name, prof_name) {init();}
605  explicit TieredApplicationProfile(const std::vector<std::string>& args) : \
606  SafeApplicationProfile(args) {init();}
607  TieredApplicationProfile(const std::vector<std::string>& args, \
608  std::string app_name, std::string prof_name) : \
609  SafeApplicationProfile(args, app_name, prof_name) {init();}
610  TieredApplicationProfile(std::string app_name, std::string prof_name) : \
611  SafeApplicationProfile(app_name, prof_name) {init();}
612 
613  virtual ~TieredApplicationProfile() {}
614 
616  inline void load_config() {
617  config_record.clear();
618  config_record.push_back(std::string("Loading Configuration"));
619  config_record.push_back(configuration_key_start);
620  // Update the configuration for the properties file reader
623  }
624  // Iterate over the default values and pull
625  // values from available sources with the same key
626  for (std::pair<std::string, std::string> element : \
627  KeyValueStore::get_opts()) {
628  config_record.push_back(std::string("Loading Records for Key: ") \
629  + element.first);
630  // Load Properties File values, if present
631  load_config_value(ApplicationProfile::get_props(), element.first);
632  // Load Consul Values, if present
634  load_consul_value(consul, element.first);
635  // Load Environment variables
636  load_environment_variable(element.first);
637  // Load Commandline Values, if present
638  load_config_value(ApplicationProfile::get_cli(), element.first);
639  }
640  // Get secure opts
641  for (auto& secure_opt : secure_opt_keys) {
642  // Load Vault Secret, if present
643  load_vault_secret(ApplicationProfile::get_vault(), secure_opt);
644  }
645  }
646 
652  inline void add_secure_opt(std::string& key) {
653  std::string final_key = configuration_key_start + key;
654  std::string blank_val;
655  secure_opt_keys.push_back(final_key);
656  KeyValueStore::add_opt(final_key, blank_val);
657  }
658 
660  std::string get_cluster_name() {return cluster_name;}
661 
663  void set_cluster_name(std::string& new_name) {cluster_name.assign(new_name);}
664 
666  std::vector<std::string> get_config_record() {return config_record;}
667 
669  inline void get_opt(std::string key, StringBuffer& val) {
670  std::string final_key = configuration_key_start + key;
671  KeyValueStore::get_opt(final_key, val);
672  }
673 
675  inline void add_opt(const std::string& key, const std::string& val) {
676  std::string final_key = configuration_key_start + key;
677  KeyValueStore::add_opt(final_key, val);
678  }
679 
681  inline void set_opt(std::string& key, std::string& val) {
682  std::string final_key = configuration_key_start + key;
683  KeyValueStore::set_opt(final_key, val);
684  }
685 
687  inline bool opt_exist(std::string& key) {
688  std::string final_key = configuration_key_start + key;
689  return KeyValueStore::opt_exist(final_key);
690  }
691 };
692 
693 } // namespace AOSSL
694 
695 #endif // AOSSL_PROFILE_INCLUDE_TIERED_APP_PROFILE_H_
std::string get_profile_name()
Get the Profile Name.
Definition: app_profile.h:186
Application Session which accepts default configuration values.
Definition: safe_app_profile.h:42
void load_config()
Load the configuration from the various sources.
Definition: tiered_app_profile.h:616
A Structure for holding a single value.
Definition: buffers.h:42
void add_opt(const std::string &key, std::string value)
Add an option.
Definition: kv_store.h:79
std::string val
Value stored.
Definition: buffers.h:44
void set_opt(std::string &key, std::string &val)
Set an option.
Definition: tiered_app_profile.h:681
void get_opt(std::string key, StringBuffer &val)
Get an option by key.
Definition: tiered_app_profile.h:669
bool opt_exist(std::string &key)
Does an option exist?
Definition: tiered_app_profile.h:687
VaultInterface * get_vault()
Get the Vault Interface.
Definition: app_profile.h:177
Biased Application Session which implements tiered configuration.
Definition: tiered_app_profile.h:63
std::vector< std::string > get_config_record()
Get the latest Configuration Record.
Definition: tiered_app_profile.h:666
KeyValueStoreInterface * get_cli()
Get the Command Line Interface.
Definition: app_profile.h:168
void set_opt(std::string &key, std::string &value)
Set an option.
Definition: kv_store.h:83
std::string get_app_name()
Get the Application Name.
Definition: app_profile.h:183
virtual void load_config()=0
Re-load configuration.
void set_profile_name(std::string prof)
Get the Profile Name.
Definition: app_profile.h:192
StringBuffer * get_opt(std::string key)
Get an option by key.
Definition: kv_store.h:60
void add_opt(const std::string &key, const std::string &val)
Add an option.
Definition: tiered_app_profile.h:675
The Consul Administrator, who handles configuration & service discovery.
Definition: consul_interface.h:115
void set_consul_address(std::string caddr)
Set the address of the consul agent.
Definition: app_profile.h:121
virtual StringBuffer * get_opt(std::string key)=0
Get an option by key.
virtual void add_acl_token(std::string &token)=0
Add an ACL Token to the Consul Admin.
void set_vault_address(std::string &vaddr, std::string &secrets_path, int tout, std::string &cert, int auth_type, std::string &un, std::string &pw)
Update the Vault connectivity information.
Definition: app_profile.h:148
Key Value Store.
Definition: kv_store_interface.h:38
bool success
Success flag.
Definition: buffers.h:35
virtual void base64_decode_by_reference(std::string const &encoded_string, StringBuffer &ret_buffer)=0
Convinience Method for base64 decoding.
std::string get_cluster_name()
Get the Cluster Name.
Definition: tiered_app_profile.h:660
ConsulInterface * get_consul()
Get the Consul Interface.
Definition: app_profile.h:174
KeyValueStoreInterface * get_props()
Get the Properties File Reader.
Definition: app_profile.h:171
std::string err_msg
Error Message.
Definition: buffers.h:38
void add_secure_opt(std::string &key)
Definition: tiered_app_profile.h:652
void set_property_file(std::string &filename)
Set the location of the properties file.
Definition: app_profile.h:112
virtual bool opt_exist(std::string key)=0
Does a key exist?
void set_cluster_name(std::string &new_name)
Set the Cluster Name.
Definition: tiered_app_profile.h:663
Definition: cli.h:35
bool opt_exist(std::string key)
Does a key exist?
Definition: kv_store.h:49