/* * 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 #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 secretList; barbicanSecret_type * secretUtil_find_secret ( string & host_uuid ) { std::map::iterator it; it = secretList.find( host_uuid ); if ( it != secretList.end() ) { return &it->second; } return NULL; } barbicanSecret_type * secretUtil_manage_secret ( libEvent & event, string & hostname, string & host_uuid, struct mtc_timer & secret_timer, void (*handler)(int, siginfo_t*, void*)) { int rc = PASS; std::map::iterator it; it = secretList.find( host_uuid ); if ( it == secretList.end() ) { barbicanSecret_type secret; secret.stage = MTC_SECRET__START; it = secretList.insert( std::pair( 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 ( mtcTimer_expired ( secret_timer ) ) { rc = secretUtil_get_secret ( event, hostname, 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 ( mtcTimer_expired ( secret_timer ) ) { rc = secretUtil_read_secret ( event, hostname, 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_reset( secret_timer ); 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_reset( secret_timer ); 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 & hostname, string & host_uuid ) { httpUtil_event_init ( &event, host_uuid, "secretUtil_get_secret", hostUtil_getServiceIp (SERVICE_SECRET), hostUtil_getServicePort(SERVICE_SECRET)); std::map::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 (%s)\n", hostname.c_str(), host_uuid.c_str()); return FAIL; } event.hostname = hostname ; 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 ; hlog ("%s secretUtil_get_secret %s\n", hostname.c_str(), 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 & hostname, string & host_uuid ) { httpUtil_event_init ( &event, host_uuid, "secretUtil_read_secret", hostUtil_getServiceIp (SERVICE_SECRET), hostUtil_getServicePort(SERVICE_SECRET)); string bm_pw_reference; std::map::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 = hostname ; 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 ; hlog ("%s secretUtil_read_secret %s", hostname.c_str(), 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 * *******************************************************************/ int secretUtil_handler ( libEvent & event ) { /* Declare and clean the json info object string containers */ jsonUtil_secret_type json_info ; string hn = event.hostname ; int rc = event.status ; std::map::iterator it; it = secretList.find( event.uuid ); if ( it == secretList.end() ) { elog ("%s failed to find secret record\n", hn.c_str()); return ( rc ) ; } if ( event.request == BARBICAN_GET_SECRET ) { if ( event.status ) { elog ("%s failed to get secret - error code (%d) \n", hn.c_str(), event.status ); it->second.stage = MTC_SECRET__GET_REF_FAIL; return ( rc ) ; } rc = jsonUtil_secret_load ( event.uuid, (char*)event.response.data(), json_info ); if ( rc != PASS ) { elog ( "%s failed to parse secret response (%s)\n", event.hostname.c_str(), event.response.c_str() ); event.status = FAIL_JSON_PARSE ; it->second.stage = MTC_SECRET__GET_REF_FAIL; } else { size_t pos = json_info.secret_ref.find_last_of( '/' ); it->second.reference = json_info.secret_ref.substr( pos+1 ); if ( it->second.reference.empty() ) { wlog ("%s no barbican secret reference found \n", hn.c_str() ); it->second.stage = MTC_SECRET__GET_PWD_RECV; } else { dlog ("%s barbican secret reference found \n", hn.c_str() ); it->second.stage = MTC_SECRET__GET_REF_RECV; } } } else if ( event.request == BARBICAN_READ_SECRET ) { if ( event.status == HTTP_NOTFOUND ) { wlog ("%s no barbican secret payload found \n", hn.c_str() ); } else if ( event.status != PASS ) { elog ("%s failed to read secret - error code (%d) \n", hn.c_str(), event.status ); it->second.stage = MTC_SECRET__GET_REF_FAIL; return ( rc ) ; } dlog ("%s barbican secret payload found \n", hn.c_str() ); it->second.payload = event.response; it->second.stage = MTC_SECRET__GET_PWD_RECV; } else { elog ("%s unsupported secret request (%d)\n", hn.c_str(), event.request ); } return ( rc ) ; }