MTCE: reading BMC passwords from Barbican secret storage.

Use Openstack Barbican API to retrieve BMC passwords stored by SysInv.
See SysInv commit for details on how to write password to Barbican.
MTCE is going to find corresponding secret by host uuid and retrieve
secret payload associated with it. mtcSecretApi_get is used to find
secret reference, based on a hostname. mtcSecretApi_read is used to
read a password using the reference found on a prevoius step.
Also, did a little cleanup and removed old unused token handling code.

Depends-On: I7102a9662f3757c062ab310737f4ba08379d0100
Change-Id: I66011dc95bb69ff536bd5888c08e3987bd666082
Story: 2003108
Task: 27700
Signed-off-by: Alex Kozyrev <alex.kozyrev@windriver.com>
changes/49/632149/8
Alex Kozyrev 4 years ago
parent b01f8ea964
commit 506ef3fd7f
  1. 2
      devstack/lib/stx-metal
  2. 1
      mtce-common/centos/mtce-common.spec
  3. 2
      mtce-common/src/common/Makefile
  4. 8
      mtce-common/src/common/hostUtil.cpp
  5. 1
      mtce-common/src/common/hostUtil.h
  6. 124
      mtce-common/src/common/httpUtil.cpp
  7. 52
      mtce-common/src/common/httpUtil.h
  8. 74
      mtce-common/src/common/jsonUtil.cpp
  9. 67
      mtce-common/src/common/jsonUtil.h
  10. 5
      mtce-common/src/common/logMacros.h
  11. 2
      mtce-common/src/common/nodeBase.h
  12. 67
      mtce-common/src/common/nodeUtil.cpp
  13. 11
      mtce-common/src/common/nodeUtil.h
  14. 348
      mtce-common/src/common/secretUtil.cpp
  15. 63
      mtce-common/src/common/secretUtil.h
  16. 93
      mtce-common/src/common/tokenUtil.cpp
  17. 4
      mtce-common/src/common/tokenUtil.h
  18. 6
      mtce-common/src/daemon/daemon_common.h
  19. 26
      mtce-common/src/daemon/daemon_config.cpp
  20. 38
      mtce/src/common/nodeClass.cpp
  21. 13
      mtce/src/common/nodeClass.h
  22. 2
      mtce/src/heartbeat/Makefile
  23. 1
      mtce/src/heartbeat/hbsStubs.cpp
  24. 78
      mtce/src/hwmon/hwmonClass.cpp
  25. 27
      mtce/src/hwmon/hwmonClass.h
  26. 18
      mtce/src/hwmon/hwmonFsm.cpp
  27. 6
      mtce/src/hwmon/hwmonHdlr.cpp
  28. 6
      mtce/src/hwmon/hwmonInit.cpp
  29. 2
      mtce/src/maintenance/Makefile
  30. 2
      mtce/src/maintenance/mtcHttpUtil.cpp
  31. 6
      mtce/src/maintenance/mtcInvApi.cpp
  32. 183
      mtce/src/maintenance/mtcKeyApi.cpp
  33. 25
      mtce/src/maintenance/mtcKeyApi.h
  34. 13
      mtce/src/maintenance/mtcNodeCtrl.cpp
  35. 15
      mtce/src/maintenance/mtcNodeHdlrs.cpp
  36. 1
      mtce/src/scripts/mtc.conf

@ -169,6 +169,7 @@ function install_mtce_common {
"common/regexUtil.h" \
"common/threadUtil.h" \
"common/tokenUtil.h" \
"common/secretUtil.h" \
)
sudo install -m 755 -d ${inc_dir_common}
sudo install -m 644 -t ${inc_dir_common} ${commonhdr_file[*]}
@ -957,6 +958,7 @@ function cleanup_metal {
"regexUtil.h" \
"threadUtil.h" \
"tokenUtil.h" \
"secretUtil.h" \
"daemon_ini.h" \
"daemon_common.h" \
"daemon_option.h" \

@ -140,6 +140,7 @@ install -m 644 -p -D %{_buildsubdir}/common/pingUtil.h %{buildroot}%{_includedir
install -m 644 -p -D %{_buildsubdir}/common/regexUtil.h %{buildroot}%{_includedir}/mtce-common
install -m 644 -p -D %{_buildsubdir}/common/threadUtil.h %{buildroot}%{_includedir}/mtce-common
install -m 644 -p -D %{_buildsubdir}/common/tokenUtil.h %{buildroot}%{_includedir}/mtce-common
install -m 644 -p -D %{_buildsubdir}/common/secretUtil.h %{buildroot}%{_includedir}/mtce-common
%clean
rm -v -rf $RPM_BUILD_ROOT

@ -22,6 +22,7 @@ SRCS = regexUtil.cpp \
jsonUtil.cpp \
httpUtil.cpp \
tokenUtil.cpp \
secretUtil.cpp \
msgClass.cpp
COMMON_OBJS = regexUtil.o \
@ -39,6 +40,7 @@ COMMON_OBJS = regexUtil.o \
jsonUtil.o \
httpUtil.o \
tokenUtil.o \
secretUtil.o \
msgClass.o
OBJS = $(SRCS:.cpp=.o)

@ -56,6 +56,11 @@ string hostUtil_getServiceIp ( mtc_service_enum service )
ip = "localhost" ;
break ;
}
case SERVICE_SECRET:
{
ip = cfg_ptr->barbican_api_host;
break ;
}
default:
{
slog ("Unsupported service (%d)\n", service );
@ -97,6 +102,9 @@ int hostUtil_getServicePort ( mtc_service_enum service )
case SERVICE_TOKEN:
return(cfg_ptr->keystone_port);
case SERVICE_SECRET:
return(cfg_ptr->barbican_api_port);
default:
{
slog ("Unsupported service (%d)\n", service );

@ -70,6 +70,7 @@ typedef enum
SERVICE_TOKEN = 1,
SERVICE_SMGR = 2,
SERVICE_VIM = 3,
SERVICE_SECRET = 4,
} mtc_service_enum ;
string hostUtil_getServiceIp ( mtc_service_enum service );

@ -20,7 +20,7 @@ using namespace std;
#include "tokenUtil.h" /* for ... tokenUtil_handler */
#include "nodeUtil.h" /* for ... string_contains */
#include "timeUtil.h" /* for ... time_debug_type */
#include "keyClass.h" /* for ... add_key, del_key */
#include "keyClass.h" /* for ... add_key, del_key */
static keyClass keyValObject ;
static char rest_api_filename[MAX_FILENAME_LEN];
@ -66,10 +66,10 @@ const char * getHttpCmdType_str ( evhttp_cmd_type type )
*
* ************************************************************************/
int httpUtil_event_init ( libEvent * ptr ,
int httpUtil_event_init ( libEvent * ptr ,
string hostname,
string service,
string ip,
string service,
string ip,
int port )
{
/* Default Starting States */
@ -127,12 +127,12 @@ int httpUtil_event_init ( libEvent * ptr ,
/** Default the user agent to mtce ; other users and commands can override */
ptr->user_agent = "mtce/1.0" ;
ptr->admin_url.clear();
ptr->admin_url.clear();
ptr->internal_url.clear();
ptr->public_url.clear();
/* HTTP Specific Info */
ptr->type = EVHTTP_REQ_GET ; /* request type GET/PUT/PATCH etc */
ptr->type = EVHTTP_REQ_GET ; /* request type GET/PUT/PATCH etc */
/* Result Info */
ptr->status = FAIL;
@ -154,8 +154,8 @@ void httpUtil_init ( void )
{
httpUtil_event_init ( &nullEvent, "null", "null" , "0.0.0.0", 0);
nullEvent.request = SERVICE_NONE ;
snprintf (&rest_api_filename[0], MAX_FILENAME_LEN, "/var/log/%s_api.log",
snprintf (&rest_api_filename[0], MAX_FILENAME_LEN, "/var/log/%s_api.log",
program_invocation_short_name );
}
@ -200,7 +200,7 @@ void httpUtil_free_base ( libEvent & event )
event.base = NULL ;
if ( event.conn )
{
hlog ("%s Free Connection (%p) --------- along with base\n",
hlog ("%s Free Connection (%p) --------- along with base\n",
event.log_prefix.c_str(), event.conn );
evhttp_connection_free ( event.conn );
@ -209,7 +209,7 @@ void httpUtil_free_base ( libEvent & event )
}
else
{
hlog1 ("%s Already Freed Event Base\n", event.log_prefix.c_str());
hlog1 ("%s Already Freed Event Base\n", event.log_prefix.c_str());
}
}
@ -230,7 +230,7 @@ int httpUtil_connect ( libEvent & event )
/* Open an http connection to specified IP and port */
event.conn = evhttp_connection_base_new ( event.base, NULL,
event.ip.c_str(),
event.ip.c_str(),
event.port );
/* bind to the correctly-versioned local address */
if ( event.conn )
@ -262,7 +262,7 @@ int httpUtil_request ( libEvent & event,
void(*hdlr)(struct evhttp_request *, void *))
{
int rc = PASS ;
/* make a new request and bind the event handler to it */
event.req = evhttp_request_new( hdlr , event.base );
if ( ! event.req )
@ -286,14 +286,14 @@ int httpUtil_request ( libEvent & event,
int httpUtil_payload_add ( libEvent & event )
{
int rc = PASS ;
/* Returns the output buffer. */
event.buf = evhttp_request_get_output_buffer ( event.req );
/* Check for no buffer */
if ( ! event.buf )
{
elog ("%s evhttp_request_get_output_buffer returned null (%p)\n",
elog ("%s evhttp_request_get_output_buffer returned null (%p)\n",
event.log_prefix.c_str(), event.req );
rc = FAIL ;
@ -311,7 +311,7 @@ int httpUtil_payload_add ( libEvent & event )
}
else if ( rc == 0 )
{
elog ("%s no data added to output buffer (len=0)\n",
elog ("%s no data added to output buffer (len=0)\n",
event.log_prefix.c_str());
rc = FAIL ;
@ -367,15 +367,15 @@ int httpUtil_header_add ( libEvent * ptr, http_headers_type * hdrs_ptr )
if ( hdrs_ptr->entries > MAX_HEADERS )
{
elog ("%s Too many headers (%d:%d)\n",
elog ("%s Too many headers (%d:%d)\n",
ptr->log_prefix.c_str(), MAX_HEADERS, hdrs_ptr->entries );
return FAIL ;
}
for ( int i = 0 ; i < hdrs_ptr->entries ; i++ )
{
/* Add the header */
rc = evhttp_add_header( ptr->req->output_headers,
hdrs_ptr->entry[i].key.c_str() ,
rc = evhttp_add_header( ptr->req->output_headers,
hdrs_ptr->entry[i].key.c_str(),
hdrs_ptr->entry[i].value.c_str());
if ( rc )
{
@ -385,7 +385,7 @@ int httpUtil_header_add ( libEvent * ptr, http_headers_type * hdrs_ptr )
hdrs_ptr->entry[i].value.c_str());
rc = FAIL ;
break ;
}
}
}
return (rc);
}
@ -432,14 +432,14 @@ int httpUtil_get_response ( libEvent & event )
/* Get a stack buffer, zero it, copy to it and terminate it */
char * stack_buf_ptr = (char*)malloc (event.response_len+1);
memset ( stack_buf_ptr, 0, event.response_len+1 );
real_len = evbuffer_remove( event.req->input_buffer, stack_buf_ptr,
real_len = evbuffer_remove( event.req->input_buffer, stack_buf_ptr,
event.response_len);
if ( real_len != event.response_len )
{
wlog ("%s Length differs from removed length (%ld:%ld)\n",
event.log_prefix.c_str(),
event.response_len,
event.response_len,
real_len );
}
@ -447,7 +447,7 @@ int httpUtil_get_response ( libEvent & event )
{
hlog1 ("%s has no response data\n", event.log_prefix.c_str() );
}
/* Terminate the buffer , this is where the +1 above is required.
/* Terminate the buffer , this is where the +1 above is required.
* Without it there is memory corruption reported by Linux */
*(stack_buf_ptr+event.response_len) = '\0';
@ -538,7 +538,7 @@ void httpUtil_handler ( struct evhttp_request *req, void *arg )
return ;
}
event_ptr = (libEvent*)temp;
event_ptr = (libEvent*)temp;
if (( event_ptr->request >= SERVICE_LAST ) || ( event_ptr->request == SERVICE_NONE ))
{
slog ("HTTP Event Lookup Failed for http base (%p) <------\n", arg);
@ -549,18 +549,17 @@ void httpUtil_handler ( struct evhttp_request *req, void *arg )
event_ptr->status = httpUtil_status ( (*event_ptr) ) ;
if ( event_ptr->status == HTTP_NOTFOUND )
{
elog ("%s returned (Not-Found) (%d)\n",
event_ptr->log_prefix.c_str(),
elog ("%s returned (Not-Found) (%d)\n",
event_ptr->log_prefix.c_str(),
event_ptr->status);
if ( event_ptr->type != EVHTTP_REQ_POST )
event_ptr->status = PASS ;
goto httpUtil_handler_done ;
}
else if (( event_ptr->status != PASS ) && ( ! req ))
{
elog ("%s Request Timeout (%d)\n",
elog ("%s Request Timeout (%d)\n",
event_ptr->log_prefix.c_str(),
event_ptr->timeout);
@ -788,6 +787,11 @@ int httpUtil_api_request ( libEvent & event )
{
;
}
else if (( event.request == BARBICAN_GET_SECRET ) ||
( event.request == BARBICAN_READ_SECRET ))
{
;
}
else
{
slog ("%s Unsupported Request (%d)\n", event.hostname.c_str(), event.request);
@ -799,7 +803,7 @@ int httpUtil_api_request ( libEvent & event )
if ( httpUtil_connect ( event ))
{
event.status = FAIL_CONNECT ;
goto httpUtil_api_request_done ;
goto httpUtil_api_request_done ;
}
if ( httpUtil_request ( event, &httpUtil_handler ))
@ -813,7 +817,7 @@ int httpUtil_api_request ( libEvent & event )
jlog ("%s Address : %s\n", event.hostname.c_str(), event.address.c_str());
}
if (( event.type != EVHTTP_REQ_GET ) &&
if (( event.type != EVHTTP_REQ_GET ) &&
( event.type != EVHTTP_REQ_DELETE ))
{
/* Add payload to the output buffer but only for PUT, POST and PATCH requests */
@ -824,15 +828,15 @@ int httpUtil_api_request ( libEvent & event )
}
if ( daemon_get_cfg_ptr()->debug_json )
{
if ((!string_contains(event.payload,"token")) &&
if ((!string_contains(event.payload,"token")) &&
(!string_contains(event.payload,"assword")))
{
jlog ("%s Payload : %s\n", event.hostname.c_str(),
jlog ("%s Payload : %s\n", event.hostname.c_str(),
event.payload.c_str() );
}
else
{
jlog ("%s Payload : ... contains private content ...\n",
jlog ("%s Payload : ... contains private content ...\n",
event.hostname.c_str());
}
@ -848,7 +852,7 @@ int httpUtil_api_request ( libEvent & event )
hdrs.entry[hdr_entry].value = "admin";
hdr_entry++;
if (( event.type != EVHTTP_REQ_GET ) &&
if (( event.type != EVHTTP_REQ_GET ) &&
( event.type != EVHTTP_REQ_DELETE ))
{
hdrs.entry[hdr_entry].key = "Content-Length" ;
@ -859,14 +863,23 @@ int httpUtil_api_request ( libEvent & event )
hdrs.entry[hdr_entry].key = "User-Agent" ;
hdrs.entry[hdr_entry].value = event.user_agent ;
hdr_entry++;
hdrs.entry[hdr_entry].key = "Content-Type" ;
hdrs.entry[hdr_entry].value = "application/json" ;
hdr_entry++;
hdrs.entry[hdr_entry].key = "Accept" ;
hdrs.entry[hdr_entry].value = "application/json" ;
hdr_entry++;
if ( event.request == BARBICAN_READ_SECRET )
{
hdrs.entry[hdr_entry].key = "Accept" ;
hdrs.entry[hdr_entry].value = "application/octet-stream" ;
hdr_entry++;
}
else
{
hdrs.entry[hdr_entry].key = "Accept" ;
hdrs.entry[hdr_entry].value = "application/json" ;
hdr_entry++;
}
if ( event.request != KEYSTONE_GET_TOKEN )
{
@ -912,8 +925,10 @@ int httpUtil_api_request ( libEvent & event )
}
else
{
hlog ("%s API Internal Address : %s\n", event.hostname.c_str(), event.address.c_str());
event.status = evhttp_make_request ( event.conn, event.req, event.type, event.address.data());
}
daemon_signal_hdlr ();
if ( event.status == PASS )
{
@ -939,14 +954,15 @@ int httpUtil_api_request ( libEvent & event )
httpUtil_latency_log ( event, label.c_str(), __LINE__, MAX_DELAY_B4_LATENCY_LOG );
goto httpUtil_api_request_done ;
}
else if ( event.request == KEYSTONE_GET_TOKEN )
else if ( event.request == KEYSTONE_GET_TOKEN ||
event.request == BARBICAN_GET_SECRET ||
event.request == BARBICAN_READ_SECRET )
{
hlog ("%s Requested (non-blocking) (timeout:%d secs)\n", event.log_prefix.c_str(), event.timeout);
event.active = true ;
event.status = event_base_loop(event.base, EVLOOP_NONBLOCK);
httpUtil_latency_log ( event, label.c_str(), __LINE__, MAX_DELAY_B4_LATENCY_LOG ); /* Should be immediate ; non blocking */
return (event.status);
// goto httpUtil_api_request_done ;
}
else
{
@ -979,9 +995,9 @@ httpUtil_api_request_done:
void httpUtil_event_info ( libEvent & event )
{
ilog ("%s request to %s.%d Status:%d \n",
event.log_prefix.c_str(),
event.ip.c_str(),
ilog ("%s request to %s.%d Status:%d \n",
event.log_prefix.c_str(),
event.ip.c_str(),
event.port,
event.status);
if ( event.request == KEYSTONE_GET_TOKEN )
@ -1001,7 +1017,7 @@ void httpUtil_log_event ( libEvent * event_ptr )
{
string event_sig = daemon_get_cfg_ptr()->debug_event ;
msgSock_type * mtclogd_ptr = get_mtclogd_sockPtr ();
send_log_message ( get_mtclogd_sockPtr(), event_ptr->hostname.data(), &rest_api_filename[0], &event_ptr->req_str[0] );
if ( event_ptr->request == KEYSTONE_GET_TOKEN )
@ -1031,16 +1047,16 @@ void httpUtil_log_event ( libEvent * event_ptr )
if (!event_ptr->payload.empty())
{
if ((!string_contains(event_ptr->payload,"token")) &&
if ((!string_contains(event_ptr->payload,"token")) &&
(!string_contains(event_ptr->payload,"assword")))
{
snprintf (&rest_api_log_str[0], MAX_API_LOG_LEN-1,
snprintf (&rest_api_log_str[0], MAX_API_LOG_LEN-1,
"%s [%5d] %s seq:%d -> Payload : %s",
pt(), getpid(), event_ptr->log_prefix.c_str(), event_ptr->sequence, event_ptr->payload.c_str() );
}
else
{
snprintf (&rest_api_log_str[0], MAX_API_LOG_LEN-1,
snprintf (&rest_api_log_str[0], MAX_API_LOG_LEN-1,
"%s [%5d] %s seq:%d -> Payload : ... contains private content ...",
pt(), getpid(), event_ptr->log_prefix.c_str(), event_ptr->sequence );
}
@ -1049,10 +1065,10 @@ void httpUtil_log_event ( libEvent * event_ptr )
if ( !event_ptr->response.empty() )
{
if ((!string_contains(event_ptr->response,"token")) &&
if ((!string_contains(event_ptr->response,"token")) &&
(!string_contains(event_ptr->response,"assword")))
{
snprintf (&rest_api_log_str[0], MAX_API_LOG_LEN-1,
snprintf (&rest_api_log_str[0], MAX_API_LOG_LEN-1,
"%s [%5d] %s seq:%d -> Response: %s",
pt(), getpid(), event_ptr->log_prefix.c_str(), event_ptr->sequence, event_ptr->response.c_str() );
}
@ -1064,18 +1080,18 @@ void httpUtil_log_event ( libEvent * event_ptr )
}
send_log_message ( mtclogd_ptr, event_ptr->hostname.data(), rest_api_filename, &rest_api_log_str[0] );
}
snprintf (&rest_api_log_str[0], MAX_API_LOG_LEN-1,
snprintf (&rest_api_log_str[0], MAX_API_LOG_LEN-1,
"%s [%5d] %s %s '%s' seq:%d -> Status : %d {execution time %ld.%06ld secs}\n",
pt(), getpid(),
event_ptr->hostname.c_str(),
event_ptr->service.c_str(),
event_ptr->service.c_str(),
event_ptr->operation.c_str(),
event_ptr->sequence,
event_ptr->http_status,
event_ptr->diff_time.secs,
event_ptr->diff_time.secs,
event_ptr->diff_time.msecs );
if (( event_ptr->diff_time.secs > 2 ) || (event_ptr->http_status != HTTP_OK ) )
{
int len = strlen (rest_api_log_str) ;

@ -52,6 +52,7 @@ using namespace std;
#define HTTP_KEYSTONE_GET_TIMEOUT (10)
#define HTTP_SMGR_TIMEOUT (20)
#define HTTP_VIM_TIMEOUT (20)
#define HTTP_SECRET_TIMEOUT (5)
#define SMGR_MAX_RETRIES (3)
@ -61,12 +62,14 @@ using namespace std;
#define SMGR_EVENT_SIG "smgrEvent"
#define SYSINV_EVENT_SIG "sysinvEvent"
#define SECRET_EVENT_SIG "secretEvent"
#define KEYSTONE_SIG "token"
#define SENSOR_SIG "sensor"
#define SYSINV_SIG "sysinv"
#define SMGR_SIG "smgr"
#define VIM_SIG "vim"
#define SECRET_SIG "secret"
#define SYSINV_OPER__LOAD_HOST "load host"
#define SYSINV_OPER__UPDATE_TASK "update task"
@ -108,6 +111,26 @@ typedef struct
error renewal - flood avoidance */
} keyToken_type ;
typedef enum
{
MTC_SECRET__START = 0,
MTC_SECRET__GET_REF,
MTC_SECRET__GET_REF_FAIL,
MTC_SECRET__GET_REF_RECV,
MTC_SECRET__GET_PWD,
MTC_SECRET__GET_PWD_FAIL,
MTC_SECRET__GET_PWD_RECV,
MTC_SECRET__STAGES,
} mtc_secretStages_enum ;
typedef struct
{
string reference;
string payload ;
mtc_secretStages_enum stage ;
} barbicanSecret_type;
/** All supported Request Type Enums */
typedef enum {
SERVICE_NONE,
@ -154,19 +177,22 @@ typedef enum {
SMGR_HOST_LOCKED,
SMGR_HOST_ENABLED,
SMGR_HOST_DISABLED,
KEYSTONE_TOKEN,
KEYSTONE_GET_TOKEN,
KEYSTONE_GET_SERVICE_LIST,
KEYSTONE_GET_ENDPOINT_LIST,
BARBICAN_GET_SECRET,
BARBICAN_READ_SECRET,
SERVICE_LAST
} libEvent_enum ;
/** Local event control structure for REST API services
*
* Nova, Neutron, Keystone and Inventory
*
* Nova, Neutron, Keystone, Barbican and Inventory
*
*/
struct libEvent
@ -177,7 +203,7 @@ struct libEvent
bool mutex ; /**< single operation at a time */
bool active ; /**< true if waiting on response */
int stuck ; /**< Count mutex active stuck state */
bool blocking ; /**< true if command is blocking */
bool blocking ; /**< true if command is blocking */
bool found ; /**< true if query was found */
int timeout ; /**< Request timeout */
int count ; /**< retry recover counter */
@ -204,7 +230,7 @@ struct libEvent
/** Service Specific Request Info */
libEvent_enum request ; /**< Specify the request command */
keyToken_type token ; /**< Copy of the active token */
keyToken_type token ; /**< Copy of the active token */
string service ; /**< Service being executed */
string hostname ; /**< Target hostname */
string uuid ; /**< The UUID for this request */
@ -222,12 +248,12 @@ struct libEvent
string address ; /**< http url address */
string payload ; /**< the request's payload */
string user_agent ; /**< set the User-Agent header */
/** Result Info */
int status ; /**< Execution Status */
int http_status ; /**< raw http returned status */
int exec_time_msec ; /**< execution time in msec */
node_inv_type inv_info ;
node_inv_type inv_info ;
size_t response_len ; /**< the json response length */
string response ; /**< the json response string */
string result ; /**< Command specific result str */
@ -288,10 +314,10 @@ typedef struct
void httpUtil_init ( void );
int httpUtil_event_init ( libEvent * ptr ,
int httpUtil_event_init ( libEvent * ptr ,
string hostname,
string service,
string ip,
string service,
string ip,
int port );
/** Add payload to the HTTP message body. */
@ -310,14 +336,14 @@ int httpUtil_connect ( libEvent & event );
int httpUtil_request ( libEvent & event,
void(*hdlr)(struct evhttp_request *, void *));
/** Common REST API Request Utility */
/** Common REST API Request Utility */
int httpUtil_api_request ( libEvent & event );
/** Common REST API Request Utility */
/** Common REST API Request Utility */
int httpUtil_request ( libEvent & event , bool block,
void(*hdlr)(struct evhttp_request *, void *));
/** Common REST API Receive Utility for non-blocking requests */
/** Common REST API Receive Utility for non-blocking requests */
int httpUtil_receive ( libEvent & event );
/** HTTP response status checker */

@ -619,6 +619,80 @@ load_host_cleanup:
return (rc);
}
int jsonUtil_secret_load ( string & name,
char * json_str_ptr,
jsonUtil_secret_type & info )
{
int rc = PASS ;
json_bool status ;
/* init to null to avoid trap on early cleanup call with
* bad non-null default pointer value */
struct array_list * array_list_obj = (struct array_list *)(NULL);
struct json_object *raw_obj = (struct json_object *)(NULL);
struct json_object *secret_obj = (struct json_object *)(NULL);
struct json_object *ref_obj = (struct json_object *)(NULL);
if (( json_str_ptr == NULL ) || ( *json_str_ptr == '\0' ) ||
( ! strncmp ( json_str_ptr, "(null)" , 6 )))
{
elog ("Cannot tokenize a null json string\n");
return (FAIL);
}
raw_obj = json_tokener_parse( json_str_ptr );
if ( !raw_obj )
{
elog ("No or invalid json string (%s)\n", json_str_ptr );
rc = FAIL ;
goto secret_load_cleanup ;
}
status = json_object_object_get_ex(raw_obj, MTC_JSON_SECRET_LIST, &secret_obj );
if ( ( status == TRUE ) && ( secret_obj ))
{
array_list_obj = json_object_get_array(secret_obj );
if ( array_list_obj )
{
int len = array_list_length (array_list_obj );
if ( len == 0 )
{
wlog ( "No %s elements in array\n", MTC_JSON_SECRET_LIST );
goto secret_load_cleanup;
}
for ( int i = 0 ; i < len ; i++ )
{
ref_obj = _json_object_array_get_idx (secret_obj, i );
if ( ref_obj )
{
string secret_name = _json_get_key_value_string ( ref_obj, MTC_JSON_SECRET_NAME );
if ( ( secret_name.length() > 0) && !secret_name.compare(name) )
{
info.secret_ref = _json_get_key_value_string ( ref_obj, MTC_JSON_SECRET_REFERENCE );
jlog ( "Found secret_ref %s\n", info.secret_ref.c_str() );
break ;
}
}
}
}
else
{
elog ("%s Failed to find %s object array\n", name.c_str(), MTC_JSON_SECRET_LIST );
}
}
else
{
elog ("%s Failed to find %s object\n", name.c_str(), MTC_JSON_SECRET_LIST );
}
secret_load_cleanup:
if (raw_obj) json_object_put(raw_obj );
if (secret_obj) json_object_put(secret_obj );
if (ref_obj) json_object_put(ref_obj );
return (rc);
}
void jsonUtil_print ( jsonUtil_info_type & info, int index )
{
if ( info.elements == 0 )

@ -10,7 +10,7 @@
/**
* @file
* Wind River CGTS Platform Controller Maintenance
*
*
* JSON Utility Header
*/
@ -56,17 +56,57 @@ typedef struct
string adminURL; /**< path to the nova server. */
} jsonUtil_auth_type ;
/** Module initialization interface.
#define MAX_JSON_SECRET_CONTENTS_NUM 7
#define MTC_JSON_SECRET_LIST "secrets"
#define MTC_JSON_SECRET_TOTAL "total"
#define MTC_JSON_SECRET_PREVIOUS "previous"
#define MTC_JSON_SECRET_NEXT "next"
#define MTC_JSON_SECRET_ALGORITHM "algorithm"
#define MTC_JSON_SECRET_LENGTH "bit_length"
#define MTC_JSON_SECRET_CONTENT "content_types"
#define MTC_JSON_SECRET_CREATED "created"
#define MTC_JSON_SECRET_CREATOR "creator_id"
#define MTC_JSON_SECRET_EXPIRATION "expiration"
#define MTC_JSON_SECRET_MODE "mode"
#define MTC_JSON_SECRET_NAME "name"
#define MTC_JSON_SECRET_REFERENCE "secret_ref"
#define MTC_JSON_SECRET_TYPE "secret_type"
#define MTC_JSON_SECRET_STATUS "status"
#define MTC_JSON_SECRET_UPDATED "updated"
typedef struct
{
string type ;
string encoding ;
} content_type ;
typedef struct
{
string algorithm ;
int bit_length ;
content_type contents[MAX_JSON_SECRET_CONTENTS_NUM];
string created ;
string creator_id ;
string expiration ;
string mode ;
string name ;
string secret_ref ;
string secret_type ;
string status ;
string updated ;
} jsonUtil_secret_type ;
/** Module initialization interface.
*/
void jsonUtil_init ( jsonUtil_info_type & info );
/** Print the authroization struct to stdio.
/** Print the authroization struct to stdio.
*/
void jsonUtil_print ( jsonUtil_info_type & info , int index );
void jsonUtil_print_inv ( node_inv_type & info );
int jsonUtil_get_key_val ( char * json_str_ptr,
string key,
string key,
string & value );
int jsonUtil_get_key_val_int ( char * json_str_ptr,
@ -76,10 +116,11 @@ int jsonUtil_get_key_val_int ( char * json_str_ptr,
/** Submit a request to get an authorization token and nova URL */
int jsonApi_auth_request ( string & hostname, string & payload );
/** Parse through the authorization request's response json string
/** Parse through the authorization request's response json string
* and load the relavent information into the passed in structure */
int jsonUtil_inv_load ( char * json_str_ptr,
jsonUtil_info_type & info );
int jsonUtil_inv_load ( char * json_str_ptr, jsonUtil_info_type & info );
int jsonUtil_secret_load ( string & name, char * json_str_ptr, jsonUtil_secret_type & info );
int jsonUtil_load_host ( char * json_str_ptr, node_inv_type & info );
int jsonUtil_load_host_state ( char * json_str_ptr, node_inv_type & info );
@ -102,7 +143,7 @@ int jsonUtil_patch_load ( char * json_str_ptr, node_inv_type & info );
*- FAIL indicates bad or error reply in json string.
*
*/
int jsonApi_auth_load ( string & hostname, char * json_str_ptr,
int jsonApi_auth_load ( string & hostname, char * json_str_ptr,
jsonUtil_auth_type & info );
@ -110,9 +151,9 @@ int jsonApi_auth_load ( string & hostname, char * json_str_ptr,
* This utility searches for an 'array_label' and then loops over the array
* looking at each element for the specified 'search_key' and 'search_value'
* Once found it searches that same element for the specified 'element_key'
* and loads its value content into 'element_value' - what we're looking for
* and loads its value content into 'element_value' - what we're looking for
***************************************************************************/
int jsonApi_array_value ( char * json_str_ptr,
int jsonApi_array_value ( char * json_str_ptr,
string array_label,
string search_key,
string search_value,
@ -123,18 +164,18 @@ int jsonApi_array_value ( char * json_str_ptr,
* This utility updates the reference key_list with all the
* values for the specified label.
***********************************************************************/
int jsonUtil_get_list ( char * json_str_ptr,
int jsonUtil_get_list ( char * json_str_ptr,
string label, list<string> & key_list );
/***********************************************************************
* This utility updates the reference element with the number of array
* elements for the specified label in the provided string
* elements for the specified label in the provided string
***********************************************************************/
int jsonUtil_array_elements ( char * json_str_ptr, string label, int & elements );
/***********************************************************************
* This utility updates the reference string 'element' with the
* contents of the specified labeled array element index.
* contents of the specified labeled array element index.
***********************************************************************/
int jsonUtil_get_array_idx ( char * json_str_ptr, string label, int idx, string & element );

@ -67,7 +67,7 @@ typedef struct
char* keystone_auth_project ; /**< =services */
char* keystone_user_domain; /**< = Default */
char* keystone_project_domain; /**< = Default */
char* keyring_directory ; /**< =/opt/platform/.keyring/<release> */
char* sysinv_mtc_inv_label ; /**< =/v1/hosts/ */
int sysinv_api_port ; /**< =6385 */
char* sysinv_api_bind_ip ; /**< =<local floating IP> */
@ -75,6 +75,9 @@ typedef struct
char* ceilometer_url ; /**< ceilometer sensor sample database url */
int ceilometer_port ; /**< ceilometer REST API port number */
char* barbican_api_host ; /**< Barbican REST API host IP address */
int barbican_api_port ; /**< Barbican REST API port number */
int mtc_rx_mgmnt_port ; /**< mtcClient listens mgmnt nwk cmd reqs */
int mtc_rx_infra_port ; /**< mtcClient listens infra nwk cmd reqs */
int mtc_tx_mgmnt_port ; /**< mtcClient sends mgmnt nwk cmds/resp's */

@ -114,7 +114,7 @@ void daemon_exit ( void );
#define NFVI_PLUGIN_CFG_FILE ((const char *)"/etc/nfv/nfv_plugins/nfvi_plugins/config.ini")
#define SYSINV_CFG_FILE ((const char *)"/etc/sysinv/sysinv.conf")
#define HWMON_CONF_FILE ((const char *)"/etc/mtc/hwmond.conf")
#define SECRET_CFG_FILE ((const char *)"/etc/barbican/barbican.conf")
#define GOENABLED_DIR ((const char *)"/etc/goenabled.d") /* generic */
#define GOENABLED_WORKER_DIR ((const char *)"/etc/goenabled.d/worker")

@ -1188,73 +1188,6 @@ bool string_contains ( string buffer, string sequence )
}
extern char *program_invocation_short_name;
string get_bm_password ( const char * uuid )
{
#define STR_LEN 128
int rc = RETRY ;
string value = "" ;
daemon_signal_hdlr ();
if ( uuid == NULL )
{
slog ("failed ; Null uuid\n" );
return (value);
}
string temp_file = "/tmp/." ;
temp_file.append(program_invocation_short_name);
temp_file.append("_bmc.tmp");
/* If the keyring dir is not present then set the password to unknown */
DIR *d = opendir(daemon_get_cfg_ptr()->keyring_directory);
if (d)
{
char str [STR_LEN] ;
memset (&str[0],0,STR_LEN);
sprintf(&str[0], "/usr/bin/keyring get BM %s > %s", uuid, temp_file.data() );
/* This system call can take 1 sec */
rc = system(str) ;
{
int parms ;
usleep(10);
FILE *fp = fopen(temp_file.c_str(), "r");
if (fp)
{
memset (&str[0],0,STR_LEN);
if ( (parms = fscanf(fp, "%128s", &str[0])) == 1 )
{
value = str ; /* get the value we are looking for */
rc = PASS ;
}
fclose(fp);
}
else
{
wlog ("Failed to open %s\n", temp_file.c_str() );
}
}
closedir(d);
}
else
{
wlog ("Failed to open credentials directory '%s'\n", daemon_get_cfg_ptr()->keyring_directory );
}
if ( rc != PASS )
{
wlog ("password for uuid '%s' not found\n", uuid);
}
/* Don't leave the temp file containing the password around */
daemon_remove_file ( temp_file.data() );
return (value);
}
static int health = NODE_HEALTH_UNKNOWN ;
int get_node_health ( string hostname )
{

@ -41,10 +41,10 @@ typedef struct
} msgSock_type ;
int send_log_message ( msgSock_type * sock_ptr,
const char * hostname,
const char * hostname,
const char * filename,
const char * log_str );
msgSock_type * get_mtclogd_sockPtr ( void ) ;
void mem_log_list_init ( void );
@ -70,14 +70,13 @@ const char * get_iface_name_str ( int iface );
unsigned int get_host_function_mask ( string & nodeType_str );
bool is_combo_system (unsigned int nodetype_mask );
int set_host_functions ( string nodetype_str,
unsigned int * nodetype_bits_ptr,
unsigned int * nodetype_function_ptr,
int set_host_functions ( string nodetype_str,
unsigned int * nodetype_bits_ptr,
unsigned int * nodetype_function_ptr,
unsigned int * nodetype_subfunction_ptr );
bool is_goenabled ( int nodeType, bool pass );
string get_bm_password ( const char * username );
string get_strings_in_string_list ( std::list<string> & l );
bool is_string_in_string_list ( std::list<string> & l , string & str );
bool is_int_in_int_list ( std::list<int> & l , int & val );

@ -0,0 +1,348 @@
/*
* Copyright (c) 2019 Wind River Systems, Inc.
*
* SPDX-License-Identifier: Apache-2.0
*
*/
/**
* @file
* Wind River CGTS Platform Controller Maintenance
* Access to Openstack Barbican via REST API Interface.
*
* This file implements the a set of secret utilities that maintenance
* calls upon to get/read Barbican secrets from the Barbican Secret storage.
*
* The APIs exposed from this file are
*
* secretUtil_get_secret - gets the Barbican secret, filtered by name
* secretUtil_read_secret - reads the payload for a specified secret uuid
*
* Each utility is paired with a private handler.
*
* secretUtil_handler - handles response for Barbican requests
*
* Warning: These calls cannot be nested.
*
**/
#ifdef __AREA__
#undef __AREA__
#endif
#define __AREA__ "pwd"
#include <map>
#include "nodeBase.h" /* for ... Base Service Header */
#include "nodeUtil.h" /* for ... Utility Service Header */
#include "hostUtil.h" /* for ... Host Service Header */
#include "jsonUtil.h" /* for ... Json utilities */
#include "secretUtil.h" /* this .. module header */
std::map<string, barbicanSecret_type> secretList;
barbicanSecret_type * secretUtil_find_secret ( string & host_uuid )
{
std::map<string, barbicanSecret_type>::iterator it;
it = secretList.find( host_uuid );
if ( it != secretList.end() )
{
return &it->second;
}
return NULL;
}
barbicanSecret_type * secretUtil_manage_secret ( libEvent & event,
string & host_uuid,
struct mtc_timer & secret_timer,
void (*handler)(int, siginfo_t*, void*))
{
int rc = PASS;
std::map<string, barbicanSecret_type>::iterator it;
it = secretList.find( host_uuid );
if ( it == secretList.end() )
{
barbicanSecret_type secret;
secret.stage = MTC_SECRET__START;
it = secretList.insert( std::pair<string, barbicanSecret_type>( host_uuid, secret ) ).first;
}
if ( it->second.stage == MTC_SECRET__START )
{
it->second.reference.clear();
it->second.payload.clear();
}
if ( it->second.stage == MTC_SECRET__START ||
it->second.stage == MTC_SECRET__GET_REF_FAIL )
{
if ( secret_timer.ring == true )
{
rc = secretUtil_get_secret ( event, host_uuid );
if (rc)
{
wlog ( "%s getting secret reference failed \n", host_uuid.c_str() );
it->second.stage = MTC_SECRET__GET_REF_FAIL;
mtcTimer_start( secret_timer, handler, SECRET_RETRY_DELAY );
}
else
{
mtcTimer_start( secret_timer, handler, SECRET_REPLY_DELAY );
}
}
else if ( event.base )
{
httpUtil_free_conn ( event );
httpUtil_free_base ( event );
}
}
else if ( it->second.stage == MTC_SECRET__GET_REF_RECV ||
it->second.stage == MTC_SECRET__GET_PWD_FAIL )
{
if ( secret_timer.ring == true )
{
rc = secretUtil_read_secret ( event, host_uuid );
if (rc)
{
wlog ( "%s getting secret payload failed \n", host_uuid.c_str() );
it->second.stage = MTC_SECRET__GET_PWD_FAIL;
mtcTimer_start( secret_timer, handler, SECRET_RETRY_DELAY );
}
else
{
mtcTimer_start( secret_timer, handler, SECRET_REPLY_DELAY );
}
}
else if ( event.base )
{
httpUtil_free_conn ( event );
httpUtil_free_base ( event );
}
}
else if ( it->second.stage == MTC_SECRET__GET_REF ||
it->second.stage == MTC_SECRET__GET_PWD )
{
if ( event.active == true )
{
/* Look for the response */
if ( event.base )
{
event_base_loop( event.base, EVLOOP_NONBLOCK );
}
else
{
/* should not get here. event active while base is null
* try and recover from this error case. */
event.active = false ;
}
}
else if ( event.base )
{
if ( it->second.stage == MTC_SECRET__GET_REF )
{
wlog ( "%s getting secret reference timeout \n", host_uuid.c_str() );
it->second.stage = MTC_SECRET__GET_REF_FAIL ;
mtcTimer_start( secret_timer, handler, SECRET_RETRY_DELAY );
}
if ( it->second.stage == MTC_SECRET__GET_PWD )
{
wlog ( "%s getting secret payload timeout \n", host_uuid.c_str() );
it->second.stage = MTC_SECRET__GET_PWD_FAIL ;
mtcTimer_start( secret_timer, handler, SECRET_RETRY_DELAY );
}
httpUtil_free_conn ( event );
httpUtil_free_base ( event );
}
}
return & it->second ;
}
/***********************************************************************
*
* Name : secretUtil_get_secret
*
* Purpose : Issue an Barbican GET request for a specified secret name
* to manage secret's reference.
*
*/
int secretUtil_get_secret ( libEvent & event, string & host_uuid )
{
httpUtil_event_init ( &event,
host_uuid,
"secretUtil_get_secret",
hostUtil_getServiceIp (SERVICE_SECRET),
hostUtil_getServicePort(SERVICE_SECRET));
std::map<string, barbicanSecret_type>::iterator it;
it = secretList.find( host_uuid );
if ( it != secretList.end() )
{
it->second.stage = MTC_SECRET__GET_REF;
}
else
{
elog ("%s failed to find secret record\n", host_uuid.c_str());
return FAIL;
}
event.hostname = _hn();
event.uuid = host_uuid;
event.token.url = MTC_SECRET_LABEL;
event.token.url.append(MTC_SECRET_NAME);
event.token.url.append(host_uuid);
event.token.url.append(MTC_SECRET_BATCH);
event.token.url.append(MTC_SECRET_BATCH_MAX);
event.address = event.token.url;
event.blocking = false;
event.request = BARBICAN_GET_SECRET;
event.operation = "get secret reference";
event.type = EVHTTP_REQ_GET ;
event.timeout = HTTP_SECRET_TIMEOUT ;
event.handler = &secretUtil_handler ;
dlog ("Path:%s\n", event.token.url.c_str() );
return ( httpUtil_api_request ( event ) ) ;
}
/* ******************************************************************
*
* Name: secretUtil_read_secret
*
* Purpose: Issue an Barbican GET request for a specified secret uuid
* to read secret's payload, ie password itself.
*
*********************************************************************/
int secretUtil_read_secret ( libEvent & event, string & host_uuid )
{
httpUtil_event_init ( &event,
host_uuid,
"secretUtil_get_secret",
hostUtil_getServiceIp (SERVICE_SECRET),
hostUtil_getServicePort(SERVICE_SECRET));
string bm_pw_reference;
std::map<string, barbicanSecret_type>::iterator it;
it = secretList.find( host_uuid );
if ( it != secretList.end() )
{
bm_pw_reference = it->second.reference;
it->second.stage = MTC_SECRET__GET_PWD;
}
else
{
elog ("%s failed to find secret record\n", host_uuid.c_str());
return FAIL;
}
event.hostname = _hn();
event.uuid = host_uuid;
event.token.url = MTC_SECRET_LABEL;
event.token.url.append("/");
event.token.url.append(bm_pw_reference);
event.token.url.append("/");
event.token.url.append(MTC_SECRET_PAYLOAD);
event.address = event.token.url;
event.blocking = false;
event.request = BARBICAN_READ_SECRET ;
event.operation = "get secret payload";
event.type = EVHTTP_REQ_GET ;
event.timeout = HTTP_SECRET_TIMEOUT ;
event.handler = &secretUtil_handler ;
dlog ("Path:%s\n", event.token.url.c_str() );
return ( httpUtil_api_request ( event ) ) ;
}
/*******************************************************************
*
* Name : secretUtil_handler
*
* Description: The handles the barbican get request
* responses for the following messages
*
* BARBICAN_GET_SECRET,
* BARBICAN_READ_SECRET
*</