VOL-264: REST Channel ( External REST Client <==> Chameleon) needs to be Secured

These are voltha itest and documentation updates after enforcing a https based
REST server implementation from the chameleon.

The chameleon related changes are already available as part of another review
https://gerrit.opencord.org/#/c/4478/ .

Change-Id: Icd585bb0403524c2e7a0f46fddcf3046876042b4
diff --git a/tests/itests/ofagent/test_ofagent_multicontroller_failover.py b/tests/itests/ofagent/test_ofagent_multicontroller_failover.py
index 89228a8..27eb41e 100644
--- a/tests/itests/ofagent/test_ofagent_multicontroller_failover.py
+++ b/tests/itests/ofagent/test_ofagent_multicontroller_failover.py
@@ -49,9 +49,9 @@
     onos1_ip="docker inspect --format '{{ .NetworkSettings.Networks.compose_default.IPAddress }}' onos1",
     onos2_ip ="docker inspect --format '{{ .NetworkSettings.Networks.compose_default.IPAddress }}' onos2",
     onos3_ip="docker inspect --format '{{ .NetworkSettings.Networks.compose_default.IPAddress }}' onos3",
-    add_olt='''curl -s -X POST -d '{"type": "simulated_olt", "mac_address": "01:0c:e2:31:40:00"}' \
-               http://localhost:8881/api/v1/local/devices''',
-    enable_olt="curl -s -X POST http://localhost:8881/api/v1/local/devices/",
+    add_olt='''curl -k -s -X POST -d '{"type": "simulated_olt", "mac_address": "01:0c:e2:31:40:00"}' \
+               https://localhost:8881/api/v1/local/devices''',
+    enable_olt="curl -k -s -X POST https://localhost:8881/api/v1/local/devices/",
     onos1_devices="curl -u karaf:karaf  http://localhost:8181/onos/v1/devices",
     onos2_devices="curl -u karaf:karaf  http://localhost:8182/onos/v1/devices",
     onos3_devices="curl -u karaf:karaf  http://localhost:8183/onos/v1/devices")
diff --git a/tests/itests/voltha/rest_base.py b/tests/itests/voltha/rest_base.py
index 3b880d6..b400283 100644
--- a/tests/itests/voltha/rest_base.py
+++ b/tests/itests/voltha/rest_base.py
@@ -1,10 +1,15 @@
 from unittest import TestCase
 from requests import get, post, put, patch, delete
+import urllib3
+
+# This is to suppress the insecure request warning when using
+# self signed ssl certificates
+urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
 
 
 class RestBase(TestCase):
 
-    base_url = 'http://localhost:8881'
+    base_url = 'https://localhost:8881'
 
     def url(self, path):
         while path.startswith('/'):
@@ -26,31 +31,29 @@
                 return response.content
 
     def get(self, path, expected_code=200,
-            expected_content_type='application/json', headers=None):
-        r = get(self.url(path), headers=headers)
+            expected_content_type='application/json', headers=None, verify=False):
+        r = get(self.url(path), headers=headers, verify=verify)
         self.assertEqual(r.status_code, expected_code,
                          msg='Code %d!=%d; msg:%s' % (
                              r.status_code, expected_code, r.content))
         return self.verify_content_type_and_return(r, expected_content_type)
 
-    def post(self, path, json_dict=None, expected_code=201):
-        r = post(self.url(path), json=json_dict)
+    def post(self, path, json_dict=None, expected_code=201, verify=False):
+        r = post(self.url(path), json=json_dict, verify=verify)
         self.assertEqual(r.status_code, expected_code,
                          msg='Code %d!=%d; msg:%s' % (
                              r.status_code, expected_code, r.content))
         return self.verify_content_type_and_return(r, 'application/json')
 
-    def put(self, path, json_dict, expected_code=200):
-        r = put(self.url(path), json=json_dict)
+    def put(self, path, json_dict, expected_code=200, verify=False):
+        r = put(self.url(path), json=json_dict, verify=verify)
         self.assertEqual(r.status_code, expected_code,
                          msg='Code %d!=%d; msg:%s' % (
                              r.status_code, expected_code, r.content))
         return self.verify_content_type_and_return(r, 'application/json')
 
-    def delete(self, path, expected_code=209):
-        r = delete(self.url(path))
+    def delete(self, path, expected_code=209, verify=False):
+        r = delete(self.url(path), verify=verify)
         self.assertEqual(r.status_code, expected_code,
                          msg='Code %d!=%d; msg:%s' % (
                              r.status_code, expected_code, r.content))
-
-
diff --git a/tests/itests/voltha/test_cold_activation_sequence.py b/tests/itests/voltha/test_cold_activation_sequence.py
index 9a780f5..fc93ce8 100644
--- a/tests/itests/voltha/test_cold_activation_sequence.py
+++ b/tests/itests/voltha/test_cold_activation_sequence.py
@@ -17,7 +17,7 @@
     rest_endpoint = get_endpoint_from_consul(LOCAL_CONSUL, 'chameleon-rest')
 
     # Construct the base_url
-    base_url = 'http://' + rest_endpoint
+    base_url = 'https://' + rest_endpoint
 
     def wait_till(self, msg, predicate, interval=0.1, timeout=5.0):
         deadline = time() + timeout
diff --git a/tests/itests/voltha/test_device_state_changes.py b/tests/itests/voltha/test_device_state_changes.py
index 9b3bc76..9cc62b7 100644
--- a/tests/itests/voltha/test_device_state_changes.py
+++ b/tests/itests/voltha/test_device_state_changes.py
@@ -27,7 +27,7 @@
     rest_endpoint = get_endpoint_from_consul(LOCAL_CONSUL, 'chameleon-rest')
 
     # Construct the base_url
-    base_url = 'http://' + rest_endpoint
+    base_url = 'https://' + rest_endpoint
 
     def wait_till(self, msg, predicate, interval=0.1, timeout=5.0):
         deadline = time() + timeout
diff --git a/tests/itests/voltha/test_dispatcher.py b/tests/itests/voltha/test_dispatcher.py
index 0f6ba73..71f6c8a 100644
--- a/tests/itests/voltha/test_dispatcher.py
+++ b/tests/itests/voltha/test_dispatcher.py
@@ -271,7 +271,7 @@
     def set_rest_endpoint(self):
         self.rest_endpoint = get_endpoint_from_consul(LOCAL_CONSUL,
                                                       'chameleon-rest')
-        self.base_url = 'http://' + self.rest_endpoint
+        self.base_url = 'https://' + self.rest_endpoint
 
     def set_kafka_endpoint(self):
         self.kafka_endpoint = get_endpoint_from_consul(LOCAL_CONSUL, 'kafka')
diff --git a/tests/itests/voltha/test_persistence.py b/tests/itests/voltha/test_persistence.py
index 1111c1e..29b084a 100644
--- a/tests/itests/voltha/test_persistence.py
+++ b/tests/itests/voltha/test_persistence.py
@@ -250,7 +250,7 @@
     def set_rest_endpoint(self):
         self.rest_endpoint = get_endpoint_from_consul(LOCAL_CONSUL,
                                                       'chameleon-rest')
-        self.base_url = 'http://' + self.rest_endpoint
+        self.base_url = 'https://' + self.rest_endpoint
 
     def set_kafka_endpoint(self):
         self.kafka_endpoint = get_endpoint_from_consul(LOCAL_CONSUL, 'kafka')
diff --git a/tests/itests/voltha/test_self_signed_cert_auth_failure.py b/tests/itests/voltha/test_self_signed_cert_auth_failure.py
new file mode 100644
index 0000000..5857417
--- /dev/null
+++ b/tests/itests/voltha/test_self_signed_cert_auth_failure.py
@@ -0,0 +1,99 @@
+from time import time, sleep
+from unittest import main, TestCase
+from nose.tools import *
+from requests import get
+from tests.itests.voltha.rest_base import RestBase
+from common.utils.consulhelpers import get_endpoint_from_consul
+from common.utils.consulhelpers import verify_all_services_healthy
+from tests.itests.docutests.test_utils import \
+    run_command_to_completion_with_raw_stdout, \
+    run_command_to_completion_with_stdout_in_list
+
+LOCAL_CONSUL = "localhost:8500"
+DOCKER_COMPOSE_FILE = "compose/docker-compose-system-test.yml"
+
+command_defs = dict(
+    docker_ps="docker ps",
+    docker_compose_start_all="docker-compose -f {} up -d "
+        .format(DOCKER_COMPOSE_FILE),
+    docker_stop_and_remove_all_containers="docker-compose -f {} down"
+        .format(DOCKER_COMPOSE_FILE),
+)
+
+
+class SelfSignedSSLCertAuthFail(RestBase):
+
+    t0 = [time()]
+
+    def pt(self, msg=''):
+        t1 = time()
+        print '%20.8f ms - %s' % (1000 * (t1 - SelfSignedSSLCertAuthFail.t0[0]),
+                                  msg)
+        SelfSignedSSLCertAuthFail.t0[0] = t1
+
+
+    def wait_till(self, msg, predicate, interval=0.1, timeout=5.0):
+        deadline = time() + timeout
+        while time() < deadline:
+            if predicate():
+                return
+            sleep(interval)
+        self.fail('Timed out while waiting for condition: {}'.format(msg))
+
+
+    def test_01_self_signed_ssl_cert_auth_failure(self):
+        # Start the voltha ensemble with a single voltha instance
+        self._stop_and_remove_all_containers()
+        sleep(5)  # A small wait for the system to settle down
+        self.start_all_containers()
+        self.set_rest_endpoint()
+
+        self._get_health()
+
+    def _stop_and_remove_all_containers(self):
+        # check if there are any running containers first
+        cmd = command_defs['docker_ps']
+        out, err, rc = run_command_to_completion_with_stdout_in_list(cmd)
+        self.assertEqual(rc, 0)
+        if len(out) > 1:  # not counting docker ps header
+            cmd = command_defs['docker_stop_and_remove_all_containers']
+            out, err, rc = run_command_to_completion_with_raw_stdout(cmd)
+            self.assertEqual(rc, 0)
+
+    def start_all_containers(self):
+        t0 = time()
+
+        # start all the containers
+        self.pt("Starting all containers ...")
+        cmd = command_defs['docker_compose_start_all']
+        out, err, rc = run_command_to_completion_with_raw_stdout(cmd)
+        self.assertEqual(rc, 0)
+
+        self.pt("Waiting for voltha and chameleon containers to be ready ...")
+        self.wait_till('voltha services HEALTHY',
+                       lambda: verify_all_services_healthy(
+                           LOCAL_CONSUL, service_name='voltha-grpc') == True,
+                       timeout=10)
+        self.wait_till('chameleon services HEALTHY',
+                       lambda: verify_all_services_healthy(
+                           LOCAL_CONSUL,service_name='chameleon-rest') == True,
+                       timeout=10)
+
+        # Chameleon takes some time to compile the protos and make them
+        # available.  So let's wait 10 seconds
+        sleep(10)
+
+    def set_rest_endpoint(self):
+        self.rest_endpoint = get_endpoint_from_consul(LOCAL_CONSUL,
+                                                      'chameleon-rest')
+        self.base_url = 'https://' + self.rest_endpoint
+
+    @raises(Exception)
+    def _get_health(self):
+        # Raises SSLError exception because "verify" set to true and
+        # we use self-signed certificates
+        res = self.get('/health', verify=True)
+
+
+if __name__ == '__main__':
+    main()
diff --git a/tests/itests/voltha/test_voltha_alarm_events.py b/tests/itests/voltha/test_voltha_alarm_events.py
index c5e2858..5e8b8ec 100644
--- a/tests/itests/voltha/test_voltha_alarm_events.py
+++ b/tests/itests/voltha/test_voltha_alarm_events.py
@@ -47,7 +47,7 @@
     rest_endpoint = get_endpoint_from_consul(LOCAL_CONSUL, 'chameleon-rest')
 
     # Construct the base_url
-    base_url = 'http://' + rest_endpoint
+    base_url = 'https://' + rest_endpoint
 
     # Start by querying consul to get the endpoint details
     kafka_endpoint = get_endpoint_from_consul(LOCAL_CONSUL, 'kafka')
diff --git a/tests/itests/voltha/test_voltha_alarm_filters.py b/tests/itests/voltha/test_voltha_alarm_filters.py
index 4b73509..e9d67a2 100644
--- a/tests/itests/voltha/test_voltha_alarm_filters.py
+++ b/tests/itests/voltha/test_voltha_alarm_filters.py
@@ -29,7 +29,7 @@
     rest_endpoint = get_endpoint_from_consul(LOCAL_CONSUL, 'chameleon-rest')
 
     # Construct the base_url
-    base_url = 'http://' + rest_endpoint
+    base_url = 'https://' + rest_endpoint
 
     # Start by querying consul to get the endpoint details
     kafka_endpoint = get_endpoint_from_consul(LOCAL_CONSUL, 'kafka')
diff --git a/tests/itests/voltha/test_voltha_rest_apis.py b/tests/itests/voltha/test_voltha_rest_apis.py
index b1f66d6..0760fca 100644
--- a/tests/itests/voltha/test_voltha_rest_apis.py
+++ b/tests/itests/voltha/test_voltha_rest_apis.py
@@ -25,7 +25,7 @@
     rest_endpoint = get_endpoint_from_consul(LOCAL_CONSUL, 'chameleon-rest')
 
     # Construct the base_url
-    base_url = 'http://' + rest_endpoint
+    base_url = 'https://' + rest_endpoint
     
     def test_01_global_rest_apis(self):
         # ~~~~~~~~~~~~~~~~~~~ GLOBAL TOP-LEVEL SERVICES~ ~~~~~~~~~~~~~~~~~~~~~~
@@ -283,7 +283,7 @@
     rest_endpoint = get_endpoint_from_consul(LOCAL_CONSUL, 'chameleon-rest')
 
     # Construct the base_url
-    base_url = 'http://' + rest_endpoint
+    base_url = 'https://' + rest_endpoint
 
     def test_02_local_rest_apis(self):
         # ~~~~~~~~~~~~~~~~ VOLTHA INSTANCE LEVEL OPERATIONS ~~~~~~~~~~~~~~~~~~~
@@ -447,7 +447,7 @@
     rest_endpoint = get_endpoint_from_consul(LOCAL_CONSUL, 'chameleon-rest')
 
     # Construct the base_url
-    base_url = 'http://' + rest_endpoint
+    base_url = 'https://' + rest_endpoint
 
     # ~~~~~~~~~~~~~~~~~~~~~~~~~~ NEGATIVE TEST CASES ~~~~~~~~~~~~~~~~~~~~~~~~~~
 
diff --git a/tests/itests/voltha/test_voltha_retrieve_software_info.py b/tests/itests/voltha/test_voltha_retrieve_software_info.py
index ddb5909..22d58bf 100644
--- a/tests/itests/voltha/test_voltha_retrieve_software_info.py
+++ b/tests/itests/voltha/test_voltha_retrieve_software_info.py
@@ -1,5 +1,6 @@
 from unittest import main
 from time import time, sleep
+from common.utils.consulhelpers import get_endpoint_from_consul
 from tests.itests.voltha.rest_base import RestBase
 from google.protobuf.json_format import MessageToDict
 from voltha.protos.device_pb2 import Device
@@ -42,6 +43,7 @@
     "type": "object"
 }
 
+LOCAL_CONSUL = "localhost:8500"
 
 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -55,10 +57,10 @@
 
 class VolthaDeviceManagementRetrieveSoftwareInfo(RestBase):
     # Retrieve details on the REST entry point
-    rest_endpoint = "127.0.0.1:8881"
+    rest_endpoint = get_endpoint_from_consul(LOCAL_CONSUL, 'chameleon-rest')
 
     # Construct the base_url
-    base_url = 'http://' + rest_endpoint
+    base_url = 'https://' + rest_endpoint
 
     def wait_till(self, msg, predicate, interval=0.1, timeout=5.0):
         deadline = time() + timeout