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  config_record.push_back(std::string("Retrieved Record: ") + buf.val \
82  + std::string(" for key: ") + key);
83  }
84  }
85  }
86 
87  // Retrieve a secret from Vault
88  inline void get_vault_secret(KeyValueStoreInterface *kv, std::string& key, StringBuffer& return_buf) {
89  StringBuffer buf;
90  kv->get_opt(key, buf);
91  if (buf.success && !(buf.val.empty())) {
92  // Parse out the data and compare it
93  rapidjson::Document d;
94  d.Parse<rapidjson::kParseStopWhenDoneFlag>(buf.val.c_str());
95  if (d.HasParseError()) {
96  return_buf.success = false;
97  return_buf.err_msg.assign(GetParseError_En(d.GetParseError()));
98  } else {
99  if (d.IsObject()) {
100  const rapidjson::Value& token_val = d["data"]["data"][key.c_str()];
101  return_buf.val.assign(token_val.GetString());
102  config_record.push_back(std::string("Retrieved Record for key: ") \
103  + key + std::string(" from Vault"));
104  }
105  }
106  } else {
107  return_buf.success = false;
108  return_buf.err_msg.assign(buf.err_msg);
109  }
110  }
111 
112  // Load a value from Vault into configuration
113  inline void load_vault_secret(KeyValueStoreInterface *kv, std::string& key) {
114  if (kv) {
115  StringBuffer buf;
116  std::string vault_key = key;
117  // Convert to all caps
118  std::transform(vault_key.begin(), vault_key.end(), vault_key.begin(), toupper);
119  // Convert '.' to '_'
120  std::replace(vault_key.begin(), vault_key.end(), '.', '_');
121  get_vault_secret(kv, vault_key, buf);
122  if (buf.success) {
123  KeyValueStore::set_opt(key, buf.val);
124  } else {
125  config_record.push_back(std::string("Failed to retrieve Vault Secret: ") \
126  + buf.err_msg);
127  }
128  }
129  }
130 
131  // Load a value from Consul
132  inline void load_consul_value(ConsulInterface *kv, std::string& key) {
133  if (kv) {
134  if (key.empty()) return;
135  // Copy the key before modifying in-place
136  std::string env_key = key;
137  // Convert to all caps
138  std::transform(env_key.begin(), env_key.end(), env_key.begin(), toupper);
139  // Convert '.' to '_'
140  std::replace(env_key.begin(), env_key.end(), '.', '_');
141  std::string query_key;
142  // Prefix the key with the application & profile name
143  // to ensure we get unique values for different apps
144  if (!(ApplicationProfile::get_app_name().empty() && \
146  query_key = ApplicationProfile::get_app_name() + std::string("/") + \
147  ApplicationProfile::get_profile_name() + std::string("/");
148  }
149  query_key = query_key + env_key;
150  if (kv->opt_exist(query_key)) {
152  kv->get_opt(query_key, buf);
153  if (!(buf.val.empty()) && buf.success) {
154  // Parse the response
155  rapidjson::Document d;
156  d.Parse<rapidjson::kParseStopWhenDoneFlag>(buf.val.c_str());
157  if (d.HasParseError()) {
158  throw std::invalid_argument(GetParseError_En(d.GetParseError()));
159  }
160  // Pull the value field
161  StringBuffer parsed_buffer;
162  std::string value_string;
163  if (d.IsArray()) {
164  for (auto& itr : d.GetArray()) {
165  rapidjson::Value::ConstMemberIterator val_iter = \
166  itr.FindMember("Value");
167  if (val_iter != itr.MemberEnd()) {
168  if (!(val_iter->value.IsNull())) {
169  parsed_buffer.val.assign(val_iter->value.GetString());
170  }
171  }
172  }
173  }
174  // decode the base64 value
175  StringBuffer decoded_buffer;
177  parsed_buffer.val, decoded_buffer);
178  if (KeyValueStore::opt_exist(key)) {
179  KeyValueStore::set_opt(key, decoded_buffer.val);
180  config_record.push_back(std::string("Retrieved Record: ") + decoded_buffer.val \
181  + std::string(" for key: ") + key + std::string(" from Consul"));
182  }
183  }
184  }
185  }
186  }
187 
188  // Load a value from an environment variable
189  inline void load_environment_variable(std::string& key) {
190  // Copy the key before modifying in-place
191  std::string env_key = key;
192  // Convert to all caps
193  std::transform(env_key.begin(), env_key.end(), env_key.begin(), toupper);
194  // Convert '.' to '_'
195  std::replace(env_key.begin(), env_key.end(), '.', '_');
196  // Get the environment variable
197  const char *env_value = std::getenv(env_key.c_str());
198  if (env_value && KeyValueStore::opt_exist(key)) {
199  std::string env_str(env_value);
200  KeyValueStore::set_opt(key, env_str);
201  config_record.push_back(std::string("Retrieved Record: ") + env_str \
202  + std::string(" for key: ") + key + std::string(" from Environment Variable"));
203  }
204  }
205 
206  inline void load_vault_info(KeyValueStoreInterface *kv, \
207  bool auth_details_included, std::string& un, std::string& pw) {
208  if (kv) {
209  // Check the commandline arguments for Vault Information
210  std::string vault_addr_key = configuration_key_start + "vault";
211  std::string vault_cert_key = configuration_key_start + "vault.cert";
212  std::string vault_atype_key = configuration_key_start + "vault.authtype";
213  std::string vault_un_key = configuration_key_start + "vault.un";
214  std::string vault_pw_key = configuration_key_start + "vault.pw";
215  std::string secrets_path("/v1/secret/data/");
216  int auth_type = BASIC_AUTH_TYPE;
217  StringBuffer vault_addr_buf;
218  StringBuffer vault_cert_buf;
219  StringBuffer vault_authtype_buf;
220  StringBuffer vault_un_buf;
221  StringBuffer vault_pw_buf;
222  // Check for authentication info
223  if (auth_details_included || (kv->opt_exist(vault_un_key) && kv->opt_exist(vault_pw_key))) {
224  if (auth_details_included) {
225  vault_un_buf.val.assign(un);
226  vault_pw_buf.val.assign(pw);
227  } else {
228  kv->get_opt(vault_un_key, vault_un_buf);
229  kv->get_opt(vault_pw_key, vault_pw_buf);
230  }
231  // Check for the rest of the config info for Vault
232  if (kv->opt_exist(vault_addr_key) && kv->opt_exist(vault_cert_key) \
233  && kv->opt_exist(vault_atype_key)) {
234  kv->get_opt(vault_addr_key, vault_addr_buf);
235  kv->get_opt(vault_cert_key, vault_cert_buf);
236  kv->get_opt(vault_atype_key, vault_authtype_buf);
237  if (vault_authtype_buf.val == "APPROLE") {
238  auth_type = APPROLE_AUTH_TYPE;
239  }
240  config_record.push_back(std::string("Setting Vault Information: ") \
241  + vault_addr_buf.val);
242  ApplicationProfile::set_vault_address(vault_addr_buf.val, secrets_path, \
243  5, vault_cert_buf.val, auth_type, vault_un_buf.val, vault_pw_buf.val);
244  } else if (kv->opt_exist(vault_addr_key) && kv->opt_exist(vault_atype_key)) {
245  kv->get_opt(vault_addr_key, vault_addr_buf);
246  kv->get_opt(vault_atype_key, vault_authtype_buf);
247  kv->get_opt(vault_un_key, vault_un_buf);
248  kv->get_opt(vault_pw_key, vault_pw_buf);
249  if (vault_authtype_buf.val == "APPROLE") {
250  auth_type = APPROLE_AUTH_TYPE;
251  }
252  config_record.push_back(std::string("Setting Vault Information: ") \
253  + vault_addr_buf.val);
254  ApplicationProfile::set_vault_address(vault_addr_buf.val, secrets_path, \
255  5, auth_type, vault_un_buf.val, vault_pw_buf.val);
256  }
257  }
258  }
259  }
260 
261  inline void load_consul_info(KeyValueStoreInterface *kv, \
262  StringBuffer& vconsul_cert_buf, StringBuffer& vconsul_token_buf) {
263  if (kv) {
264  // Check the commandline arguments for Consul Information
265  std::string consul_add_key = configuration_key_start + "consul";
266  std::string consul_cert_key = configuration_key_start + "consul.cert";
267  std::string consul_token_key = configuration_key_start + "consul.token";
268  StringBuffer consul_addr_buf;
269  StringBuffer consul_cert_buf;
270  StringBuffer consul_token_buf;
271  // We have a pre-existing cert and token, and have been given an address
272  if (kv->opt_exist(consul_add_key) && vconsul_cert_buf.success && \
273  vconsul_token_buf.success) {
274  kv->get_opt(consul_add_key, consul_addr_buf);
275  config_record.push_back(std::string("Setting Consul Information: ") \
276  + consul_addr_buf.val);
277  ApplicationProfile::set_consul_address(consul_addr_buf.val, 5, \
278  vconsul_cert_buf.val, vconsul_token_buf.val);
279  // We have been given an address, cert, and a pre-existing token
280  } else if (kv->opt_exist(consul_add_key) && kv->opt_exist(consul_cert_key) && \
281  vconsul_token_buf.success) {
282  kv->get_opt(consul_add_key, consul_addr_buf);
283  kv->get_opt(consul_cert_key, consul_cert_buf);
284  config_record.push_back(std::string("Setting Consul Information: ") \
285  + consul_addr_buf.val);
286  ApplicationProfile::set_consul_address(consul_addr_buf.val, 5, \
287  consul_cert_buf.val, vconsul_token_buf.val);
288  // We have been given an address, cert, and a token
289  } else if (kv->opt_exist(consul_add_key) && \
290  kv->opt_exist(consul_cert_key) && \
291  kv->opt_exist(consul_token_key)) {
292  config_record.push_back(std::string("Setting Consul Information: ") \
293  + consul_addr_buf.val);
294  kv->get_opt(consul_add_key, consul_addr_buf);
295  kv->get_opt(consul_cert_key, consul_cert_buf);
296  kv->get_opt(consul_token_key, consul_token_buf);
297  ApplicationProfile::set_consul_address(consul_addr_buf.val, 5, \
298  consul_cert_buf.val, consul_token_buf.val);
299  // We have been given an address and a cert
300  } else if (kv->opt_exist(consul_add_key) && \
301  (kv->opt_exist(consul_cert_key) || vconsul_cert_buf.success)) {
302  kv->get_opt(consul_add_key, consul_addr_buf);
303  if (vconsul_cert_buf.success) {
304  consul_cert_buf.val = vconsul_cert_buf.val;
305  consul_cert_buf.success = true;
306  } else {
307  kv->get_opt(consul_cert_key, consul_cert_buf);
308  }
309  config_record.push_back(std::string("Secure Consul Connection: ") \
310  + consul_addr_buf.val);
311  ApplicationProfile::set_consul_address(consul_addr_buf.val, 5, \
312  consul_cert_buf.val);
313  // We have been given an address and a token
314  } else if (kv->opt_exist(consul_add_key) && \
315  (kv->opt_exist(consul_token_key) || vconsul_token_buf.success)) {
316  kv->get_opt(consul_add_key, consul_addr_buf);
317  if (vconsul_token_buf.success) {
318  consul_token_buf.val = vconsul_token_buf.val;
319  consul_token_buf.success = true;
320  } else {
321  kv->get_opt(consul_token_key, consul_token_buf);
322  }
323  config_record.push_back(std::string("Authenticated Consul Connection: ") \
324  + consul_addr_buf.val);
326  config_record.push_back(std::string("Adding ACL Token: ") \
327  + consul_addr_buf.val);
328  ApplicationProfile::get_consul()->add_acl_token(consul_token_buf.val);
329  // We've been given an address
330  } else if (kv->opt_exist(consul_add_key)) {
331  kv->get_opt(consul_add_key, consul_addr_buf);
332  config_record.push_back(std::string("Setting Consul Information: ") \
333  + consul_addr_buf.val);
335  }
336  }
337  }
338 
339  // Initialize the Profile
340  inline void init() {
341  // See if we have a profile name provided
343  if (ApplicationProfile::get_cli()->opt_exist(std::string("profile"))) {
344  StringBuffer profile_name_buf;
345  ApplicationProfile::get_cli()->get_opt(std::string("profile"), profile_name_buf);
346  ApplicationProfile::set_profile_name(profile_name_buf.val);
347  }
348  }
349 
350  // What should the start of our config strings be?
351  std::string config_key_start;
352  if (!(ApplicationProfile::get_app_name().empty())) {
353  config_key_start += ApplicationProfile::get_app_name();
354  config_key_start += std::string(".");
355  }
356  if (!(ApplicationProfile::get_profile_name().empty())) {
357  config_key_start += ApplicationProfile::get_profile_name();
358  config_key_start += std::string(".");
359  }
360  config_record.push_back(config_key_start);
361  configuration_key_start.assign(config_key_start);
362  std::string env_config_key_start(config_key_start);
363  std::transform(env_config_key_start.begin(), env_config_key_start.end(), \
364  env_config_key_start.begin(), toupper);
365  std::replace(env_config_key_start.begin(), env_config_key_start.end(), '.', '_');
366  // Start by looking for properties files, as values for other configs can
367  // be stored in the props files.
368 
369  // Check Env Variables for a Properties File
370  std::string props_env_key = env_config_key_start + std::string("PROPS_FILE");
371  const char *env_props_value = std::getenv(props_env_key.c_str());
372  if (env_props_value) {
373  std::string props_file_str(env_props_value);
375  config_record.push_back(std::string("Setting Properties File: ") \
376  + props_file_str);
377  }
378 
379  // Check the commandline arguments for a properties file
380  std::string props_key = config_key_start + std::string("props");
382  if (ApplicationProfile::get_cli()->opt_exist(props_key)) {
383  StringBuffer props_buf;
384  ApplicationProfile::get_cli()->get_opt(props_key, props_buf);
386  config_record.push_back(std::string("Setting Properties File: ") \
387  + props_buf.val);
388  }
389  }
390 
391  // Check for default property files
392  props_file_name = "/etc/";
393  props_file_name += ApplicationProfile::get_app_name();
394  props_file_name += "/app.properties";
395  if ((!(ApplicationProfile::get_props())) && exists_test(props_file_name)) {
396  ApplicationProfile::set_property_file(props_file_name);
397  config_record.push_back(std::string("Setting Properties File: ") \
398  + props_file_name);
399  }
400  props_file_name = "app.properties";
401  if ((!(ApplicationProfile::get_props())) && exists_test(props_file_name)) {
402  ApplicationProfile::set_property_file(props_file_name);
403  config_record.push_back(std::string("Setting Properties File: ") \
404  + props_file_name);
405  }
406 
407  // Next, we want to check for Vault information, as further
408  // security information needed for configuration may be held there.
409 
410  std::string vault_un_file = "vault_un.txt";
411  std::string vault_pw_file = "vault_pw.txt";
412  std::string vault_un_value;
413  std::string vault_pw_value;
414  bool vault_auth_from_file = false;
415 
416  // See if we have vault username/password files
417  if (exists_test(vault_un_file) && exists_test(vault_pw_file)) {
418  std::ifstream unfs(vault_un_file);
419  vault_un_value.assign((std::istreambuf_iterator<char>(unfs)), \
420  (std::istreambuf_iterator<char>()));
421  std::ifstream pwfs(vault_pw_file);
422  vault_pw_value.assign((std::istreambuf_iterator<char>(pwfs)), \
423  (std::istreambuf_iterator<char>()));
424  vault_auth_from_file = true;
425  config_record.push_back(std::string("Using Vault authentication info from files"));
426  }
427 
428  // Check environment variables for vault information
429  std::string env_vault_addr_key = env_config_key_start + std::string("VAULT_ADDRESS");
430  std::string env_vault_cert_key = env_config_key_start + std::string("VAULT_SSL_CERT");
431  std::string env_vault_authtype_key = env_config_key_start + std::string("VAULT_AUTH_TYPE");
432  std::string env_vault_authun_key = env_config_key_start + std::string("VAULT_AUTH_UN");
433  std::string env_vault_authpw_key = env_config_key_start + std::string("VAULT_AUTH_PW");
434  const char *env_vault_addr = std::getenv(env_vault_addr_key.c_str());
435  const char *env_vault_cert = std::getenv(env_vault_cert_key.c_str());
436  const char *env_vault_authtype = std::getenv(env_vault_authtype_key.c_str());
437  const char *env_vault_authun = std::getenv(env_vault_authun_key.c_str());
438  const char *env_vault_authpw = std::getenv(env_vault_authpw_key.c_str());
439  std::string un;
440  std::string pw;
441  if (env_vault_addr && env_vault_cert && env_vault_authtype) {
442  if (vault_auth_from_file || (env_vault_authun && env_vault_authpw)) {
443  if (vault_auth_from_file) {
444  un.assign(vault_un_value);
445  pw.assign(vault_pw_value);
446  } else {
447  un.assign(env_vault_authun);
448  pw.assign(env_vault_authpw);
449  }
450  std::string vaddr(env_vault_addr);
451  std::string cert(env_vault_cert);
452  std::string secrets_path("/v1/secret/data/");
453  std::string authtype_string(env_vault_authtype);
454  int auth_type = BASIC_AUTH_TYPE;
455  if (authtype_string == "APPROLE") {
456  auth_type = APPROLE_AUTH_TYPE;
457  }
458  config_record.push_back(std::string("Setting Vault Information from Environment Variables: ") \
459  + vaddr);
460  ApplicationProfile::set_vault_address(vaddr, secrets_path, 5, cert, auth_type, un, pw);
461  }
462  } else if (env_vault_addr && env_vault_authtype && env_vault_authun && env_vault_authpw) {
463  if (vault_auth_from_file) {
464  un.assign(vault_un_value);
465  pw.assign(vault_pw_value);
466  } else {
467  un.assign(env_vault_authun);
468  pw.assign(env_vault_authpw);
469  }
470  std::string vaddr(env_vault_addr);
471  std::string secrets_path("/v1/secret/data/");
472  std::string authtype_string(env_vault_authtype);
473  int auth_type = BASIC_AUTH_TYPE;
474  if (authtype_string == "APPROLE") {
475  auth_type = APPROLE_AUTH_TYPE;
476  }
477  config_record.push_back(std::string("Setting Vault Information from Environment Variables: ") \
478  + vaddr);
479  ApplicationProfile::set_vault_address(vaddr, secrets_path, 5, auth_type, un, pw);
480  }
481  // Try to load vault information from the CLI arguments
482  load_vault_info(ApplicationProfile::get_cli(), vault_auth_from_file, vault_un_value, vault_pw_value);
483  // Try to load vault information from the Properties File
484  load_vault_info(ApplicationProfile::get_props(), vault_auth_from_file, vault_un_value, vault_pw_value);
485 
486  // Next, we'll check for any Consul information
487 
488  // Start by checking Vault for any SSL Certs or ACL Tokens.
489  std::string consul_cert_vault_key = env_config_key_start \
490  + std::string("CONSUL_SSL_CERT");
491  std::string consul_token_vault_key = env_config_key_start \
492  + std::string("CONSUL_ACL_TOKEN");
493  StringBuffer consul_cert_buf;
494  consul_cert_buf.success = false;
495  StringBuffer consul_token_buf;
496  consul_token_buf.success = false;
498  config_record.push_back(std::string("Checking Vault for Consul Security info"));
499  get_vault_secret(ApplicationProfile::get_vault(), consul_cert_vault_key, consul_cert_buf);
500  get_vault_secret(ApplicationProfile::get_vault(), consul_token_vault_key, consul_token_buf);
501  }
502 
503  // See if we've been instructed to generate the Consul ACL token
504  // from the Vault Consul Secrets Engine, rather than the KV Store
505  bool generate_consul_token = false;
506  StringBuffer gen_consul_token_buf;
508  std::string gen_consul_token_key = config_key_start + "consul.token.role";
509  if (ApplicationProfile::get_cli()->opt_exist(gen_consul_token_key)) {
510  generate_consul_token = true;
511  ApplicationProfile::get_cli()->get_opt(gen_consul_token_key, gen_consul_token_buf);
512  }
513  }
514 
515  std::string env_get_consul_token_key = env_config_key_start \
516  + std::string("CONSUL_TOKEN_ROLE");
517  const char *env_gen_consul_token = std::getenv(env_get_consul_token_key.c_str());
518  if (env_gen_consul_token) {
519  gen_consul_token_buf.val.assign(env_gen_consul_token);
520  gen_consul_token_buf.success = true;
521  generate_consul_token = true;
522  }
523 
524  if (generate_consul_token && gen_consul_token_buf.success) {
525  config_record.push_back("Generating Consul ACL Token with role: " + gen_consul_token_buf.val);
526  ApplicationProfile::get_vault()->gen_consul_token(gen_consul_token_buf.val, \
527  consul_token_buf);
528  if (!(consul_token_buf.success)) {
529  config_record.push_back(std::string("Failed to generate Consul ACL Token: ") \
530  + consul_token_buf.err_msg);
531  }
532  }
533 
534  // Check the Properties file for the Consul args
535  load_consul_info(ApplicationProfile::get_props(), consul_cert_buf, consul_token_buf);
536 
537  // Check Env Variables for Consul Information
538  std::string env_consul_value_key = env_config_key_start \
539  + std::string("CONSUL_ADDRESS");
540  std::string env_consul_cert_key = env_config_key_start \
541  + std::string("CONSUL_SSL_CERT");
542  std::string env_consul_token_key = env_config_key_start \
543  + std::string("CONSUL_ACL_TOKEN");
544  const char *env_consul_value = std::getenv(env_consul_value_key.c_str());
545  const char *env_consul_cert_value = std::getenv(env_consul_cert_key.c_str());
546  const char *env_consul_token_value = std::getenv(env_consul_token_key.c_str());
547  if (env_consul_value && env_consul_cert_value && env_consul_token_value) {
548  std::string consul_addr_str(env_consul_value);
549  std::string consul_cert_str(env_consul_cert_value);
550  std::string consul_token_str(env_consul_token_value);
551  config_record.push_back(std::string("Setting Consul Address: ") + consul_addr_str);
552  ApplicationProfile::set_consul_address(consul_addr_str, 5, consul_cert_str, env_consul_value);
553  } else if (env_consul_value && env_consul_cert_value) {
554  std::string consul_addr_str(env_consul_value);
555  std::string consul_cert_str(env_consul_cert_value);
556  config_record.push_back(std::string("Setting Consul Address: ") + consul_addr_str);
557  ApplicationProfile::set_consul_address(consul_addr_str, 5, consul_cert_str);
558  } else if (env_consul_value) {
559  // Mix environment variables with token/certs retrieved from Vault
560  std::string consul_addr_str(env_consul_value);
561  if (consul_cert_buf.success && consul_token_buf.success) {
562  config_record.push_back(std::string("Setting Consul Address: ") + consul_addr_str);
563  ApplicationProfile::set_consul_address(consul_addr_str, 5, consul_cert_buf.val, consul_token_buf.val);
564  } else if (consul_cert_buf.success && env_consul_token_value) {
565  std::string consul_token_str(env_consul_token_value);
566  config_record.push_back(std::string("Setting Consul Address: ") + consul_addr_str);
567  ApplicationProfile::set_consul_address(consul_addr_str, 5, consul_cert_buf.val, consul_token_str);
568  } else if (env_consul_cert_value && consul_token_buf.success) {
569  std::string consul_cert_str(env_consul_cert_value);
570  config_record.push_back(std::string("Setting Consul Address: ") + consul_addr_str);
571  ApplicationProfile::set_consul_address(consul_addr_str, 5, consul_cert_str, consul_token_buf.val);
572  } else {
573  config_record.push_back(std::string("Setting Consul Address: ") + consul_addr_str);
575  }
576  }
577 
578  // Check the commandline arguments for the Consul args
579  load_consul_info(ApplicationProfile::get_cli(), consul_cert_buf, consul_token_buf);
580 
581  // Check for a provided Cluster Name
582  std::string cluster_key = config_key_start + std::string("cluster");
583  std::string env_cluster_key = env_config_key_start + std::string("CLUSTER");
585  if (ApplicationProfile::get_props()->opt_exist(cluster_key)) {
586  StringBuffer cluster_name_buf;
587  ApplicationProfile::get_props()->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  }
593  if (ApplicationProfile::get_cli()->opt_exist(cluster_key)) {
594  StringBuffer cluster_name_buf;
595  ApplicationProfile::get_cli()->get_opt(cluster_key, cluster_name_buf);
596  cluster_name.assign(cluster_name_buf.val);
597  config_record.push_back(std::string("Setting Cluster Name: ") + cluster_name);
598  }
599  }
600  const char *env_cluster_name = std::getenv(env_cluster_key.c_str());
601  if (env_cluster_name) {
602  cluster_name.assign(env_cluster_name);
603  config_record.push_back(std::string("Setting Cluster Name: ") + cluster_name);
604  }
605  }
606 
607  public:
608  TieredApplicationProfile(int argc, char* argv[]) : \
609  SafeApplicationProfile(argc, argv) {init();}
610  TieredApplicationProfile(int argc, char* argv[], std::string app_name, \
611  std::string prof_name) : \
612  SafeApplicationProfile(argc, argv, app_name, prof_name) {init();}
613  explicit TieredApplicationProfile(const std::vector<std::string>& args) : \
614  SafeApplicationProfile(args) {init();}
615  TieredApplicationProfile(const std::vector<std::string>& args, \
616  std::string app_name, std::string prof_name) : \
617  SafeApplicationProfile(args, app_name, prof_name) {init();}
618  TieredApplicationProfile(std::string app_name, std::string prof_name) : \
619  SafeApplicationProfile(app_name, prof_name) {init();}
620 
621  virtual ~TieredApplicationProfile() {}
622 
624  inline void load_config() {
625  config_record.clear();
626  config_record.push_back(std::string("Loading Configuration"));
627  config_record.push_back(configuration_key_start);
628  // Update the configuration for the properties file reader
631  }
632  // Iterate over the default values and pull
633  // values from available sources with the same key
634  for (std::pair<std::string, std::string> element : \
635  KeyValueStore::get_opts()) {
636  config_record.push_back(std::string("Loading Records for Key: ") \
637  + element.first);
638  // Load Properties File values, if present
639  load_config_value(ApplicationProfile::get_props(), element.first);
640  // Load Consul Values, if present
642  load_consul_value(consul, element.first);
643  // Load Environment variables
644  load_environment_variable(element.first);
645  // Load Commandline Values, if present
646  load_config_value(ApplicationProfile::get_cli(), element.first);
647  }
648  // Get secure opts
649  for (auto& secure_opt : secure_opt_keys) {
650  // Load Vault Secret, if present
651  load_vault_secret(ApplicationProfile::get_vault(), secure_opt);
652  }
653  }
654 
660  inline void add_secure_opt(std::string& key) {
661  std::string final_key = configuration_key_start + key;
662  std::string blank_val;
663  secure_opt_keys.push_back(final_key);
664  KeyValueStore::add_opt(final_key, blank_val);
665  }
666 
668  std::string get_cluster_name() {return cluster_name;}
669 
671  void set_cluster_name(std::string& new_name) {cluster_name.assign(new_name);}
672 
674  std::vector<std::string> get_config_record() {return config_record;}
675 
677  inline void get_opt(std::string key, StringBuffer& val) {
678  std::string final_key = configuration_key_start + key;
679  KeyValueStore::get_opt(final_key, val);
680  }
681 
683  inline void add_opt(const std::string& key, const std::string& val) {
684  std::string final_key = configuration_key_start + key;
685  KeyValueStore::add_opt(final_key, val);
686  }
687 
689  inline void set_opt(std::string& key, std::string& val) {
690  std::string final_key = configuration_key_start + key;
691  KeyValueStore::set_opt(final_key, val);
692  }
693 
695  inline bool opt_exist(std::string& key) {
696  std::string final_key = configuration_key_start + key;
697  return KeyValueStore::opt_exist(final_key);
698  }
699 };
700 
701 } // namespace AOSSL
702 
703 #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:624
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:689
void get_opt(std::string key, StringBuffer &val)
Get an option by key.
Definition: tiered_app_profile.h:677
bool opt_exist(std::string &key)
Does an option exist?
Definition: tiered_app_profile.h:695
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:674
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:683
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:668
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:660
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:671
Definition: cli.h:35
bool opt_exist(std::string key)
Does a key exist?
Definition: kv_store.h:49