Implement TLS over HTTP 69/26569/1
authorGokul Singaraju <goksing@gmail.com>
Tue, 19 Dec 2017 17:31:40 +0000 (12:31 -0500)
committerGokul Singaraju <goksing@gmail.com>
Tue, 19 Dec 2017 17:32:04 +0000 (12:32 -0500)
Issue-ID: CERT-10
Change-Id: I25421331f249ea0a33fe9280534df8e66d08463f
Signed-off-by: Gokul Singaraju <goksing@gmail.com>
vnfs/VES5.0/evel/evel-library/code/evel_library/evel.c
vnfs/VES5.0/evel/evel-library/code/evel_library/evel.h
vnfs/VES5.0/evel/evel-library/code/evel_library/evel_event_mgr.c
vnfs/VES5.0/evel/evel-library/code/evel_library/evel_internal.h
vnfs/VES5.0/evel/evel-test-collector/code/collector/collector.py
vnfs/VES5.0/evel/evel-test-collector/config/collector.conf
vnfs/VES5.0/evel/evel-test-collector/docs/ssl_certsample [new file with mode: 0644]
vnfs/VESreporting_vFW5.0/vpp_measurement_reporter.c
vnfs/VESreporting_vLB5.0/vpp_measurement_reporter.c

index 246ed5d..c6ead7a 100644 (file)
@@ -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);
index 6b7a872..1c0bea7 100644 (file)
@@ -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
index 187a709..5c6ca4b 100644 (file)
@@ -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.                                               */
index 46f71af..dd4b4b7 100644 (file)
@@ -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);
index b9473ae..58bebc7 100644 (file)
@@ -38,6 +38,7 @@ import string
 import json
 import jsonschema
 from functools import partial
+import ssl
 
 _hello_resp = '''\
 <html>
@@ -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()
 
index 3e23c59..6654428 100644 (file)
@@ -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 (file)
index 0000000..f828177
--- /dev/null
@@ -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
index dbad74e..c9c9bdc 100644 (file)
@@ -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             */
index 3eb984d..728b761 100644 (file)
@@ -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             */