From: Gokul Singaraju Date: Tue, 19 Dec 2017 17:31:40 +0000 (-0500) Subject: Implement TLS over HTTP X-Git-Tag: v1.2.0~151 X-Git-Url: https://gerrit.onap.org/r/gitweb?p=demo.git;a=commitdiff_plain;h=a19bd423c1e4d2f5552bab090ba2650c38fa7192 Implement TLS over HTTP Issue-ID: CERT-10 Change-Id: I25421331f249ea0a33fe9280534df8e66d08463f Signed-off-by: Gokul Singaraju --- diff --git a/vnfs/VES5.0/evel/evel-library/code/evel_library/evel.c b/vnfs/VES5.0/evel/evel-library/code/evel_library/evel.c index 246ed5de..c6ead7ad 100644 --- a/vnfs/VES5.0/evel/evel-library/code/evel_library/evel.c +++ b/vnfs/VES5.0/evel/evel-library/code/evel_library/evel.c @@ -67,8 +67,15 @@ char *functional_role = NULL; * @param path The optional path (may be NULL). * @param topic The optional topic part of the URL (may be NULL). * @param secure Whether to use HTTPS (0=HTTP, 1=HTTPS) + * @param cert_file_path Path to client certificate file + * @param key_file_path Path to client key file + * @param ca_info Path to CA cert file + * @param ca_file_path Path to CA cert files + * @param verify_peer SSL verification of peer 0 or 1 + * @param verify_host SSL verification of host 0 or 1 * @param username Username for Basic Authentication of requests. * @param password Password for Basic Authentication of requests. + * @param source_ip The ip of node we represent (NULL for default ip). * @param source_type The kind of node we represent. * @param role The role this node undertakes. * @param verbosity 0 for normal operation, positive values for chattier @@ -83,8 +90,15 @@ EVEL_ERR_CODES evel_initialize(const char * const fqdn, const char * const path, const char * const topic, int secure, + const char * const cert_file_path, + const char * const key_file_path, + const char * const ca_info, + const char * const ca_file_path, + long verify_peer, + long verify_host, const char * const username, const char * const password, + const char * const source_ip, EVEL_SOURCE_TYPES source_type, const char * const role, int verbosity @@ -134,6 +148,42 @@ EVEL_ERR_CODES evel_initialize(const char * const fqdn, } EVEL_INFO("API transport is: %s", secure ? "HTTPS" : "HTTP"); + if( secure ) { + assert( verify_peer >= 0 ); + assert( verify_host >= 0 ); + if (cert_file_path != NULL) + { + EVEL_INFO("Client cert is: %s", cert_file_path); + } + else + { + EVEL_INFO("No Client cert"); + } + if (key_file_path != NULL) + { + EVEL_INFO("Key file is: %s", key_file_path); + } + else + { + EVEL_INFO("No Key file"); + } + if (ca_file_path != NULL) + { + EVEL_INFO("Client CA certs path is: %s", ca_file_path); + } + else + { + EVEL_INFO("No CA certs path"); + } + if (ca_info != NULL) + { + EVEL_INFO("Client CA cert file is: %s", ca_info); + } + else + { + EVEL_INFO("No CA cert file"); + } + } EVEL_INFO("Event Source Type is: %d", source_type); EVEL_INFO("Functional Role is: %s", role); EVEL_INFO("Log verbosity is: %d", verbosity); @@ -200,6 +250,14 @@ EVEL_ERR_CODES evel_initialize(const char * const fqdn, /***************************************************************************/ rc = event_handler_initialize(event_api_url, throt_api_url, + source_ip, + secure, + cert_file_path, + key_file_path, + ca_info, + ca_file_path, + verify_peer, + verify_host, username, password, verbosity); diff --git a/vnfs/VES5.0/evel/evel-library/code/evel_library/evel.h b/vnfs/VES5.0/evel/evel-library/code/evel_library/evel.h index 6b7a8720..1c0bea74 100644 --- a/vnfs/VES5.0/evel/evel-library/code/evel_library/evel.h +++ b/vnfs/VES5.0/evel/evel-library/code/evel_library/evel.h @@ -1401,8 +1401,15 @@ typedef struct copyright { * @param path The optional path (may be NULL). * @param topic The optional topic part of the URL (may be NULL). * @param secure Whether to use HTTPS (0=HTTP, 1=HTTPS). + * @param cert_file_path Path to client certificate file + * @param key_file_path Path to client key file + * @param ca_info Path to CA info + * @param ca_file_path Path to CA file + * @param verify_peer SSL verification of peer 0 or 1 + * @param verify_host SSL verification of host 0 or 1 * @param username Username for Basic Authentication of requests. * @param password Password for Basic Authentication of requests. + * @param source_ip The ip of node we represent.(NULL for default ip) * @param source_type The kind of node we represent. * @param role The role this node undertakes. * @param verbosity 0 for normal operation, positive values for chattier @@ -1417,8 +1424,15 @@ EVEL_ERR_CODES evel_initialize(const char * const fqdn, const char * const path, const char * const topic, int secure, + const char * const cert_file_path, + const char * const key_file_path, + const char * const ca_info, + const char * const ca_file_path, + long verify_peer, + long verify_host, const char * const username, const char * const password, + const char * const source_ip, EVEL_SOURCE_TYPES source_type, const char * const role, int verbosity diff --git a/vnfs/VES5.0/evel/evel-library/code/evel_library/evel_event_mgr.c b/vnfs/VES5.0/evel/evel-library/code/evel_library/evel_event_mgr.c index 187a7090..5c6ca4b3 100644 --- a/vnfs/VES5.0/evel/evel-library/code/evel_library/evel_event_mgr.c +++ b/vnfs/VES5.0/evel/evel-library/code/evel_library/evel_event_mgr.c @@ -114,6 +114,14 @@ static char * evel_batch_api_url; * to be. * @param[in] throt_api_url * The URL where the Throttling API is expected to be. + * @param[in] source_ip Source IP of VES Agent + * @param[in] secure Whether Using http or https + * @param[in] cert_file_path Path to Client Certificate file + * @param[in] key_file_path Path to Client key file + * @param[in] ca_info Path to CA info file + * @param[in] ca_file_path Path to CA file + * @param[in] verify_peer Using peer verification or not 0 or 1 + * @param[in] verify_host Using host verification or not 0 or 1 * @param[in] username The username for the Basic Authentication of requests. * @param[in] password The password for the Basic Authentication of requests. * @param verbosity 0 for normal operation, positive values for chattier @@ -121,6 +129,14 @@ static char * evel_batch_api_url; *****************************************************************************/ EVEL_ERR_CODES event_handler_initialize(const char * const event_api_url, const char * const throt_api_url, + const char * const source_ip, + int secure, + const char * const cert_file_path, + const char * const key_file_path, + const char * const ca_info, + const char * const ca_file_path, + long verify_peer, + long verify_host, const char * const username, const char * const password, int verbosity) @@ -128,6 +144,7 @@ EVEL_ERR_CODES event_handler_initialize(const char * const event_api_url, int rc = EVEL_SUCCESS; CURLcode curl_rc = CURLE_OK; char batch_api_url[EVEL_MAX_URL_LEN + 1] = {0}; + char local_address[64]; EVEL_ENTER(); @@ -240,6 +257,114 @@ EVEL_ERR_CODES event_handler_initialize(const char * const event_api_url, goto exit_label; } + /***************************************************************************/ + /* configure local ip address if provided */ + /* Default ip if NULL */ + /***************************************************************************/ + if( source_ip != NULL ) + { + snprintf(local_address,sizeof(local_address),source_ip); + if( local_address[0] != '\0' ) + { + curl_rc = curl_easy_setopt(curl_handle, + CURLOPT_INTERFACE, + local_address); + if (curl_rc != CURLE_OK) + { + rc = EVEL_CURL_LIBRARY_FAIL; + log_error_state("Failed to initialize libCURL with the local address. " + "Error code=%d (%s)", curl_rc, curl_err_string); + goto exit_label; + } + } + } + + /***************************************************************************/ + /* configure SSL options for HTTPS transfers */ + /***************************************************************************/ + if( secure ) + { + if( cert_file_path != NULL ) + { + curl_rc = curl_easy_setopt(curl_handle, + CURLOPT_SSLCERT, + cert_file_path); + if (curl_rc != CURLE_OK) + { + rc = EVEL_CURL_LIBRARY_FAIL; + log_error_state("Failed to initialize libCURL with the client cert. " + "Error code=%d (%s)", curl_rc, curl_err_string); + goto exit_label; + } + } + + if( key_file_path != NULL ) + { + curl_rc = curl_easy_setopt(curl_handle, + CURLOPT_SSLKEY, + key_file_path); + if (curl_rc != CURLE_OK) + { + rc = EVEL_CURL_LIBRARY_FAIL; + log_error_state("Failed to initialize libCURL with the client key. " + "Error code=%d (%s)", curl_rc, curl_err_string); + goto exit_label; + } + } + + if( ca_info != NULL ) + { + curl_rc = curl_easy_setopt(curl_handle, + CURLOPT_CAINFO, + ca_info); + if (curl_rc != CURLE_OK) + { + rc = EVEL_CURL_LIBRARY_FAIL; + log_error_state("Failed to initialize libCURL with the CA cert file. " + "Error code=%d (%s)", curl_rc, curl_err_string); + goto exit_label; + } + } + + if( ca_file_path != NULL ) + { + curl_rc = curl_easy_setopt(curl_handle, + CURLOPT_CAPATH, + ca_file_path); + if (curl_rc != CURLE_OK) + { + rc = EVEL_CURL_LIBRARY_FAIL; + log_error_state("Failed to initialize libCURL with the CA cert path. " + "Error code=%d (%s)", curl_rc, curl_err_string); + goto exit_label; + } + } + + curl_rc = curl_easy_setopt(curl_handle, + CURLOPT_SSL_VERIFYPEER, + verify_peer); + if (curl_rc != CURLE_OK) + { + rc = EVEL_CURL_LIBRARY_FAIL; + log_error_state("Failed to initialize libCURL with SSL Server verification. " + "Error code=%d (%s)", curl_rc, curl_err_string); + goto exit_label; + } + curl_rc = curl_easy_setopt(curl_handle, + CURLOPT_SSL_VERIFYHOST, + verify_host); + if (curl_rc != CURLE_OK) + { + rc = EVEL_CURL_LIBRARY_FAIL; + log_error_state("Failed to initialize libCURL with Client host verification. " + "Error code=%d (%s)", curl_rc, curl_err_string); + goto exit_label; + } + + } + + + /***************************************************************************/ /* some servers don't like requests that are made without a user-agent */ /* field, so we provide one. */ diff --git a/vnfs/VES5.0/evel/evel-library/code/evel_library/evel_internal.h b/vnfs/VES5.0/evel/evel-library/code/evel_library/evel_internal.h index 46f71af1..dd4b4b7c 100644 --- a/vnfs/VES5.0/evel/evel-library/code/evel_library/evel_internal.h +++ b/vnfs/VES5.0/evel/evel-library/code/evel_library/evel_internal.h @@ -174,6 +174,14 @@ typedef struct evel_throttle_spec { * to be. * @param[in] throt_api_url * The URL where the Throttling API is expected to be. + * @param[in] source_ip Source IP of VES Agent + * @param[in] secure Whether Using http or https + * @param[in] cert_file_path Path to Client Certificate file + * @param[in] key_file_path Path to Client key file + * @param[in] ca_info Path to CA info file + * @param[in] ca_file_path Path to CA file + * @param[in] verify_peer Using peer verification or not + * @param[in] verify_host Using host verification or not * @param[in] username The username for the Basic Authentication of requests. * @param[in] password The password for the Basic Authentication of requests. * @param verbosity 0 for normal operation, positive values for chattier @@ -181,6 +189,14 @@ typedef struct evel_throttle_spec { *****************************************************************************/ EVEL_ERR_CODES event_handler_initialize(const char * const event_api_url, const char * const throt_api_url, + const char * const source_ip, + int secure, + const char * const cert_file_path, + const char * const key_file_path, + const char * const ca_info, + const char * const ca_file_path, + long verify_peer, + long verify_host, const char * const username, const char * const password, int verbosity); diff --git a/vnfs/VES5.0/evel/evel-test-collector/code/collector/collector.py b/vnfs/VES5.0/evel/evel-test-collector/code/collector/collector.py index b9473ae5..58bebc74 100644 --- a/vnfs/VES5.0/evel/evel-test-collector/code/collector/collector.py +++ b/vnfs/VES5.0/evel/evel-test-collector/code/collector/collector.py @@ -38,6 +38,7 @@ import string import json import jsonschema from functools import partial +import ssl _hello_resp = '''\ @@ -407,7 +408,8 @@ USAGE defaults = {'log_file': 'collector.log', 'vel_port': '12233', 'vel_path': '', - 'vel_topic_name': '' + 'vel_topic_name': '', + 'transport_prot': 'http' } overrides = {} config = ConfigParser.SafeConfigParser(defaults) @@ -419,9 +421,16 @@ USAGE log_file = config.get(config_section, 'log_file', vars=overrides) vel_port = config.get(config_section, 'vel_port', vars=overrides) vel_path = config.get(config_section, 'vel_path', vars=overrides) + transport_prot = config.get(config_section, 'protocol', vars=overrides) vel_topic_name = config.get(config_section, 'vel_topic_name', vars=overrides) + + if (transport_prot.lower() != 'http' and transport_prot.lower() != 'https' ): + logger.error('Invalid Transport must be http or https ({0}) ' + 'specified'.format(transport_prot)) + raise RuntimeError('Invalid Transport protcol specified ({0}) ' + 'specified'.format(transport_prot)) global vel_username global vel_password vel_username = config.get(config_section, @@ -457,6 +466,28 @@ USAGE handler = logging.handlers.RotatingFileHandler(log_file, maxBytes=1000000, backupCount=10) + + if (transport_prot.lower() == 'https' ): + transport_prot = transport_prot.lower() + ca_file = config.get(config_section, 'ca_file', vars=overrides) + cert_file = config.get(config_section, 'cert_file', vars=overrides) + key_file = config.get(config_section, 'key_file', vars=overrides) + if not os.path.exists(ca_file): + logger.error('Event Listener SSL CA File ({0}) not found. ' + 'No validation will be undertaken.'.format(ca_file)) + raise RuntimeError('Invalid CA file ({0}) ' + 'specified'.format(ca_file)) + if not os.path.exists(cert_file): + logger.error('Event Listener SSL Certificate File ({0}) not found. ' + 'No validation will be undertaken.'.format(cert_file)) + raise RuntimeError('Invalid Certificate file ({0}) ' + 'specified'.format(cert_file)) + if not os.path.exists(key_file): + logger.error('Event Listener SSL Key File ({0}) not found. ' + 'No validation will be undertaken.'.format(key_file)) + raise RuntimeError('Invalid Key file ({0}) ' + 'specified'.format(key_file)) + if (platform.system() == 'Windows'): date_format = '%Y-%m-%d %H:%M:%S' else: @@ -472,6 +503,7 @@ USAGE # Log the details of the configuration. #---------------------------------------------------------------------- logger.debug('Log file = {0}'.format(log_file)) + logger.debug('Event Listener Transport = {0}'.format(transport_prot)) logger.debug('Event Listener Port = {0}'.format(vel_port)) logger.debug('Event Listener Path = {0}'.format(vel_path)) logger.debug('Event Listener Topic = {0}'.format(vel_topic_name)) @@ -587,6 +619,10 @@ USAGE dispatcher.register('GET', test_control_url, test_control_listener) httpd = make_server('', int(vel_port), dispatcher) + if (transport_prot == 'https' ): + #httpd.socket = ssl.wrap_socket(httpd.socket, server_side=True, ca_certs = "../../../sslcerts/test.ca.pem", certfile="../../../sslcerts/www.testsite.com.crt", keyfile="../../../sslcerts/www.testsite.com.key", cert_reqs=ssl.CERT_REQUIRED, ssl_version=ssl.PROTOCOL_TLSv1_2) + logger.debug('Invoking HTTP Secure mode : ca file {0} cert file {1} key file {2} '.format(ca_file,cert_file,key_file)) + httpd.socket = ssl.wrap_socket(httpd.socket, server_side=True, ca_certs=ca_file, certfile=cert_file, keyfile=key_file, cert_reqs=ssl.CERT_REQUIRED, ssl_version=ssl.PROTOCOL_TLSv1_2) print('Serving on port {0}...'.format(vel_port)) httpd.serve_forever() diff --git a/vnfs/VES5.0/evel/evel-test-collector/config/collector.conf b/vnfs/VES5.0/evel/evel-test-collector/config/collector.conf index 3e23c594..66544288 100644 --- a/vnfs/VES5.0/evel/evel-test-collector/config/collector.conf +++ b/vnfs/VES5.0/evel/evel-test-collector/config/collector.conf @@ -60,6 +60,11 @@ vel_path = vendor_event_listener/ vel_username = vel_password = vel_topic_name = example_vnf +protocol = HTTP +#protocol = HTTPS +#ca_file = ../../../sslcerts/test.ca.pem +#cert_file = ../../../sslcerts/www.testsite.com.crt +#key_file = ../../../sslcerts/www.testsite.com.key #------------------------------------------------------------------------------ # Settings to be used when running in a windows test environment rather than @@ -96,4 +101,9 @@ vel_path = vel_username = will vel_password = pill vel_topic_name = +protocol = HTTP +#protocol = HTTPS +#ca_file = ../../../sslcerts/test.ca.pem +#cert_file = ../../../sslcerts/www.testsite.com.crt +#key_file = ../../../sslcerts/www.testsite.com.key diff --git a/vnfs/VES5.0/evel/evel-test-collector/docs/ssl_certsample b/vnfs/VES5.0/evel/evel-test-collector/docs/ssl_certsample new file mode 100644 index 00000000..f8281779 --- /dev/null +++ b/vnfs/VES5.0/evel/evel-test-collector/docs/ssl_certsample @@ -0,0 +1,15 @@ +# Generate CA key and certificate +openssl genrsa -des3 -out test.ca.key 8192 +openssl req -new -key test.ca.key -x509 -days 30 -out test.ca.crt + +# Generate server key and certificate +openssl genrsa -out www.testsite.com.key 1024 +openssl req -new -key www.testsite.com.key -out www.testsite.com.csr +openssl x509 -req -days 30 -in www.testsite.com.csr -CA test.ca.crt -CAkey test.ca.key -CAcreateserial -out www.testsite.com.crt + +# Generate client key and certificate +openssl genrsa -out testclient.key 1024 +openssl req -new -key testclient.key -out testclient.csr +openssl x509 -req -days 30 -in testclient.csr -CA test.ca.crt -CAkey test.ca.key -CAcreateserial -out testclient.crt + +openssl pkcs12 -export -clcerts -in testclient.crt -inkey testclient.key -out testclient.p12 diff --git a/vnfs/VESreporting_vFW5.0/vpp_measurement_reporter.c b/vnfs/VESreporting_vFW5.0/vpp_measurement_reporter.c index dbad74e5..c9c9bdc6 100644 --- a/vnfs/VESreporting_vFW5.0/vpp_measurement_reporter.c +++ b/vnfs/VESreporting_vFW5.0/vpp_measurement_reporter.c @@ -192,8 +192,15 @@ int main(int argc, char** argv) NULL, /* optional path */ NULL, /* optional topic */ 0, /* HTTPS? */ + NULL, /* cert file */ + NULL, /* key file */ + NULL, /* ca info */ + NULL, /* ca file */ + 0, /* verify peer */ + 0, /* verify host */ "", /* Username */ "", /* Password */ + NULL, /* Source ip */ EVEL_SOURCE_VIRTUAL_MACHINE, /* Source type */ "vFirewall", /* Role */ 1)) /* Verbosity */ diff --git a/vnfs/VESreporting_vLB5.0/vpp_measurement_reporter.c b/vnfs/VESreporting_vLB5.0/vpp_measurement_reporter.c index 3eb984d5..728b7611 100644 --- a/vnfs/VESreporting_vLB5.0/vpp_measurement_reporter.c +++ b/vnfs/VESreporting_vLB5.0/vpp_measurement_reporter.c @@ -140,8 +140,15 @@ int main(int argc, char** argv) NULL, /* optional path */ NULL, /* optional topic */ 0, /* HTTPS? */ + NULL, /* cert file */ + NULL, /* key file */ + NULL, /* ca info */ + NULL, /* ca file */ + 0, /* verify peer */ + 0, /* verify host */ "", /* Username */ "", /* Password */ + NULL, /* Source IP */ EVEL_SOURCE_VIRTUAL_MACHINE, /* Source type */ "vLoadBalancer", /* Role */ 1)) /* Verbosity */