Add test cases for call-home (devices connected with TLS transport) 30/91030/18
authorOleksii Mozghovyi <oleksii.mozghovyi@pantheon.tech>
Wed, 8 Jul 2020 20:18:14 +0000 (23:18 +0300)
committerOleksii Mozghovyi <oleksii.mozghovyi@pantheon.tech>
Thu, 11 Feb 2021 19:50:06 +0000 (21:50 +0200)
Verification for the TLS transport based on the following flow:
- Generates certificate for the device
- Installs certificates into the netopeer2 device
- Installs certificates into the OpenDaylight controller
- Checks if the device is recognized by the OpenDaylight CallHome feature and
mounted successfully

JIRA: NETCONF-5
Change-Id: Ibe08c61ab6956d83748ae95be776a1be8c1a1d78
Signed-off-by: Oleksii Mozghovyi <oleksii.mozghovyi@pantheon.tech>
Signed-off-by: Vladyslav Marchenko <vladyslav.marchenko@pantheon.tech>
csit/libraries/NetconfCallHome.robot
csit/suites/netconf/callhome/callhome.robot
csit/variables/netconf/callhome/configuration-files/tls/ietf-keystore.xml [new file with mode: 0644]
csit/variables/netconf/callhome/configuration-files/tls/ietf-netconf-server.xml [new file with mode: 0644]
csit/variables/netconf/callhome/configuration-files/tls/ietf-truststore.xml [new file with mode: 0644]
csit/variables/netconf/callhome/init_configuration.sh
csit/variables/netconf/callhome/json/apiv2/add_keystore_entry.json [new file with mode: 0644]
csit/variables/netconf/callhome/json/apiv2/add_private_key.json [new file with mode: 0644]
csit/variables/netconf/callhome/json/apiv2/add_trusted_certificate.json [new file with mode: 0644]
csit/variables/netconf/callhome/json/apiv2/create_tls_device.json [new file with mode: 0644]
csit/variables/netconf/callhome/x509_v3.cfg [new file with mode: 0644]

index 6afb7bfc2a3302be17040c59382262e54053806e..d18568d70b84f4d292f8dc32a28fcbea064ebd3e 100644 (file)
@@ -9,6 +9,8 @@ ${mount_point_url}    /restconf/operational/network-topology:network-topology/to
 ${device_status}    /restconf/operational/odl-netconf-callhome-server:netconf-callhome-server
 ${whitelist}      /restconf/config/odl-netconf-callhome-server:netconf-callhome-server/allowed-devices
 ${global_config_url}    /restconf/config/odl-netconf-callhome-server:netconf-callhome-server/global/credentials
+${netconf_keystore_url}    /rests/operations/netconf-keystore
+${netconf_keystore_data_url}    /rests/data/netconf-keystore:keystore
 ${substring1}     "netconf-node-topology:connection-status":"connected"
 ${substring2}     "node-id":"netopeer2"
 ${substring3}     "netconf-node-topology:available-capabilities"
@@ -28,6 +30,53 @@ Apply SSH-based Call-Home configuration
     SSHLibrary.Put File    ${CURDIR}/../variables/netconf/callhome/configuration-files/ssh/ietf-keystore.xml
     ...    configuration-files/ietf-keystore.xml
 
+Apply TLS-based Call-Home configuration
+    [Documentation]    Upload netopeer2 configuration files needed for TLS transport
+    Generate certificates for TLS configuration
+    SSHLibrary.Put File    ${CURDIR}/../variables/netconf/callhome/configuration-files/tls/ietf-keystore.xml
+    ...    configuration-files/ietf-keystore.xml
+    SSHLibrary.Put File    ${CURDIR}/../variables/netconf/callhome/configuration-files/tls/ietf-truststore.xml
+    ...    configuration-files/ietf-truststore.xml
+    SSHLibrary.Put File    ${CURDIR}/../variables/netconf/callhome/configuration-files/tls/ietf-netconf-server.xml
+    ...    configuration-files/ietf-netconf-server.xml
+
+Generate certificates for TLS configuration
+    [Documentation]    Generates certificates for 2-way TLS authentication (ca, server, client)
+    ${stdout}    SSHLibrary.Execute Command    rm -rf ./certs && mkdir ./certs
+    SSHLibrary.Put File    ${CURDIR}/../variables/netconf/callhome/x509_v3.cfg    ./x509_v3.cfg
+    ${stdout}    SSHLibrary.Execute Command    openssl genrsa -out ./certs/ca.key 2048
+    ${stdout}    SSHLibrary.Execute Command    openssl req -x509 -new -extensions v3_ca -nodes -key ./certs/ca.key -sha256 -days 365 -subj "/C=US/ST=CA/L=Netopeer/O=netopeerCA/CN=netopeerCA" -out ./certs/ca.pem
+    ${stdout}    SSHLibrary.Execute Command    openssl genrsa -out ./certs/server.key 2048
+    ${stdout}    SSHLibrary.Execute Command    openssl req -new -sha256 -key ./certs/server.key -subj "/C=US/ST=CA/L=Netopeer/O=Netopeer2/CN=netopeer2-server" -out ./certs/server.csr
+    ${stdout}    SSHLibrary.Execute Command    openssl x509 -req -in ./certs/server.csr -CA ./certs/ca.pem -CAkey ./certs/ca.key -CAcreateserial -extfile x509_v3.cfg -out ./certs/server.crt -days 365 -sha256
+    ${stdout}    SSHLibrary.Execute Command    openssl rsa -in ./certs/server.key -pubout > ./certs/server.pub
+    ${stdout}    SSHLibrary.Execute Command    openssl genrsa -out ./certs/client.key 2048
+    ${stdout}    SSHLibrary.Execute Command    openssl req -new -sha256 -key ./certs/client.key -subj "/C=US/ST=CA/L=Netopeer/O=Netopeer2/CN=netopeer2-client" -out ./certs/client.csr
+    ${stdout}    SSHLibrary.Execute Command    openssl x509 -req -in ./certs/client.csr -CA ./certs/ca.pem -CAkey ./certs/ca.key -CAcreateserial -extfile x509_v3.cfg -out ./certs/client.crt -days 1024 -sha256
+    ${stdout}    SSHLibrary.Execute Command    mv ./certs ./configuration-files/certs
+
+Register keys and certificates in ODL controller
+    [Documentation]    Register pre-configured netopeer2 certificates and key in ODL-netconf keystore
+    ${base64-client-key}    ${stderr}    SSHLibrary.Execute_Command    openssl enc -base64 -A -in ./configuration-files/certs/client.key    return_stdout=True    return_stderr=True
+    ${template}    OperatingSystem.Get File    ${ADD_KEYSTORE_ENTRY_REQ}
+    ${body}    Replace String    ${template}    {base64-client-key}    ${base64-client-key}
+    ${resp}    RequestsLibrary.Post Request    session    ${netconf_keystore_url}:add-keystore-entry    data=${body}    headers=${HEADERS}
+    Should Contain    ${ALLOWED_STATUS_CODES}    ${resp.status_code}
+    ${client-key}    ${stderr}    SSHLibrary.Execute_Command    sed -u '1d; $d' ./configuration-files/certs/client.key | sed -z 's!\\n!\\\\n!g'    return_stdout=True    return_stderr=True
+    ${certificate-chain}    ${stderr}    SSHLibrary.Execute_Command    sed -u '1d; $d' ./configuration-files/certs/client.crt | sed -z 's!\\n!\\\\n!g'    return_stdout=True    return_stderr=True
+    ${template}    OperatingSystem.Get File    ${ADD_PRIVATE_KEY_REQ}
+    ${body}    Replace String    ${template}    {client-key}    ${client-key}
+    ${body}    Replace String    ${body}    {certificate-chain}    ${certificate-chain}
+    ${resp}    RequestsLibrary.Post Request    session    ${netconf_keystore_url}:add-private-key    data=${body}    headers=${HEADERS}
+    Should Contain    ${ALLOWED_STATUS_CODES}    ${resp.status_code}
+    ${ca-certificate}    ${stderr}    SSHLibrary.Execute_Command    sed -u '1d; $d' ./configuration-files/certs/ca.pem | sed -z 's!\\n!\\\\n!g'    return_stdout=True    return_stderr=True
+    ${device-certificate}    ${stderr}    SSHLibrary.Execute_Command    sed -u '1d; $d' ./configuration-files/certs/server.crt | sed -z 's!\\n!\\\\n!g'    return_stdout=True    return_stderr=True
+    ${template}    OperatingSystem.Get File    ${ADD_TRUSTED_CERTIFICATE}
+    ${body}    Replace String    ${template}    {ca-certificate}    ${ca-certificate}
+    ${body}    Replace String    ${body}    {device-certificate}    ${device-certificate}
+    ${resp}    RequestsLibrary.Post Request    session    ${netconf_keystore_url}:add-trusted-certificate    data=${body}    headers=${HEADERS}
+    Should Contain    ${ALLOWED_STATUS_CODES}    ${resp.status_code}
+
 Register global credentials for SSH call-home devices (APIv1)
     [Arguments]    ${username}    ${password}
     [Documentation]    Set global credentials for SSH call-home devices
@@ -77,6 +126,16 @@ Get create device request without credentials template (APIv2)
     ${template}    OperatingSystem.Get File    ${CREATE_SSH_DEVICE_REQ_V2_HOST_KEY_ONLY}
     Set Test Variable    ${template}
 
+Register TLS call-home device in ODL controller (APIv2)
+    [Arguments]    ${device_name}    ${key_id}    ${certificate_id}
+    [Documentation]    Registration call-home device with TLS transport
+    ${template}    OperatingSystem.Get File    ${CREATE_TLS_DEVICE_REQ}
+    ${body}    Replace String    ${template}    {device_name}    ${device_name}
+    ${body}    Replace String    ${body}    {key_id}    ${key_id}
+    ${body}    Replace String    ${body}    {certificate_id}    ${certificate_id}
+    ${resp}    RequestsLibrary.Post Request    session    ${whitelist}    data=${body}    headers=${HEADERS}
+    Should Contain    ${ALLOWED_STATUS_CODES}    ${resp.status_code}
+
 Pull Netopeer2 Docker Image
     [Documentation]    Pulls the netopeer image from the docker repository.
     ${stdout}    ${stderr}    ${rc}=    SSHLibrary.Execute Command    docker pull sysrepo/sysrepo-netopeer2:latest    return_stdout=True    return_stderr=True
@@ -117,6 +176,7 @@ Test Teardown
     ...    return_rc=True
     SSHLibrary.Execute_Command    rm -rf ./configuration-files
     ${resp} =    RequestsLibrary.Delete_Request    session    ${whitelist}
+    ${resp} =    RequestsLibrary.Delete_Request    session    ${netconf_keystore_data_url}
 
 Suite Setup
     [Documentation]    Get the suite ready for callhome test cases.
@@ -132,6 +192,10 @@ Suite Setup
     Set Suite Variable    ${CREATE_GLOBAL_CREDENTIALS_REQ}    ${CURDIR}/../variables/netconf/callhome/json/apiv1/create_global_credentials.json
     Set Suite Variable    ${CREATE_SSH_DEVICE_REQ_V2}    ${CURDIR}/../variables/netconf/callhome/json/apiv2/create_ssh_device.json
     Set Suite Variable    ${CREATE_SSH_DEVICE_REQ_V2_HOST_KEY_ONLY}    ${CURDIR}/../variables/netconf/callhome/json/apiv2/create_device_hostkey_only.json
+    Set Suite Variable    ${CREATE_TLS_DEVICE_REQ}    ${CURDIR}/../variables/netconf/callhome/json/apiv2/create_tls_device.json
+    Set Suite Variable    ${ADD_KEYSTORE_ENTRY_REQ}    ${CURDIR}/../variables/netconf/callhome/json/apiv2/add_keystore_entry.json
+    Set Suite Variable    ${ADD_PRIVATE_KEY_REQ}    ${CURDIR}/../variables/netconf/callhome/json/apiv2/add_private_key.json
+    Set Suite Variable    ${ADD_TRUSTED_CERTIFICATE}    ${CURDIR}/../variables/netconf/callhome/json/apiv2/add_trusted_certificate.json
 
 Suite Teardown
     [Documentation]    Tearing down the setup.
index f1651a1456f8ceb99ac532d9395da8618f0ecfa0..4778ca17c293ec3ddf0015a82692b6ecfa13670c 100644 (file)
@@ -119,3 +119,14 @@ CallHome over SSH with incorrect global credentials (APIv2)
     Wait Until Keyword Succeeds    90s    2s    NetconfCallHome.Check Device Status    FAILED_AUTH_FAILURE
     Wait Until Keyword Succeeds    30s    2s    Run Keyword And Expect Error    *    Utils.Check For Elements At URI    ${mount_point_url}
     ...    ${netconf_mount_expected_values}
+
+CallHome over TLS with correct certificate and key (APIv2)
+    [Documentation]    Using correct certificate and key pair should result to successful mount. CONNECTED should be the device status.
+    CompareStream.Run_Keyword_If_Less_Than_Silicon    BuiltIn.Pass_Execution    Test case valid only for versions silicon and above.
+    Apply TLS-based Call-Home configuration
+    Register keys and certificates in ODL controller
+    Register TLS call-home device in ODL controller (APIv2)    netopeer2    tls-device-key    tls-device-certificate
+    ${stdout}    ${stderr}    ${rc}=    SSHLibrary.Execute Command    docker-compose up -d    return_stdout=True    return_stderr=True
+    ...    return_rc=True
+    Wait Until Keyword Succeeds    90s    2s    NetconfCallHome.Check Device Status    CONNECTED
+    Wait Until Keyword Succeeds    30s    2s    Utils.Check For Elements At URI    ${mount_point_url}    ${netconf_mount_expected_values}
diff --git a/csit/variables/netconf/callhome/configuration-files/tls/ietf-keystore.xml b/csit/variables/netconf/callhome/configuration-files/tls/ietf-keystore.xml
new file mode 100644 (file)
index 0000000..b263e64
--- /dev/null
@@ -0,0 +1,22 @@
+<keystore xmlns="urn:ietf:params:xml:ns:yang:ietf-keystore">
+    <asymmetric-keys>
+        <asymmetric-key>
+            <name>genkey</name>
+            <algorithm>rsa2048</algorithm>
+            <public-key>$NP_PUBKEY</public-key>
+            <private-key>$NP_PRIVKEY</private-key>
+        </asymmetric-key>
+        <asymmetric-key>
+            <name>serverkey</name>
+            <algorithm>rsa2048</algorithm>
+            <public-key>$NP_SERVER_PUBLIC_KEY</public-key>
+            <private-key>$NP_SERVER_PRIVATE_KEY</private-key>
+            <certificates>
+                <certificate>
+                    <name>servercert</name>
+                    <cert>$NP_SERVER_CERTIFICATE</cert>
+                </certificate>
+            </certificates>
+        </asymmetric-key>
+    </asymmetric-keys>
+</keystore>
diff --git a/csit/variables/netconf/callhome/configuration-files/tls/ietf-netconf-server.xml b/csit/variables/netconf/callhome/configuration-files/tls/ietf-netconf-server.xml
new file mode 100644 (file)
index 0000000..e103ebc
--- /dev/null
@@ -0,0 +1,80 @@
+<netconf-server xmlns="urn:ietf:params:xml:ns:yang:ietf-netconf-server">
+    <listen>
+        <endpoint>
+            <name>default-ssh</name>
+            <ssh>
+                <tcp-server-parameters>
+                    <local-address>0.0.0.0</local-address>
+                    <keepalives>
+                        <idle-time>1</idle-time>
+                        <max-probes>10</max-probes>
+                        <probe-interval>5</probe-interval>
+                    </keepalives>
+                </tcp-server-parameters>
+                <ssh-server-parameters>
+                    <server-identity>
+                        <host-key>
+                            <name>default-key</name>
+                            <public-key>
+                                <keystore-reference>genkey</keystore-reference>
+                            </public-key>
+                        </host-key>
+                    </server-identity>
+                    <client-authentication>
+                        <supported-authentication-methods>
+                            <publickey/>
+                            <passsword/>
+                            <other>interactive</other>
+                        </supported-authentication-methods>
+                        <users/>
+                    </client-authentication>
+                </ssh-server-parameters>
+            </ssh>
+        </endpoint>
+    </listen>
+    <call-home>
+        <netconf-client>
+            <name>default-client</name>
+            <endpoints>
+                <endpoint>
+                    <name>default-tls</name>
+                    <tls>
+                        <tcp-client-parameters>
+                            <remote-address>$CALL_HOME_SERVER_IP</remote-address>
+                            <remote-port>$CALL_HOME_TLS_PORT</remote-port>
+                            <keepalives>
+                                <idle-time>1</idle-time>
+                                <max-probes>10</max-probes>
+                                <probe-interval>5</probe-interval>
+                            </keepalives>
+                        </tcp-client-parameters>
+                        <tls-server-parameters>
+                            <server-identity>
+                                <keystore-reference>
+                                    <asymmetric-key>serverkey</asymmetric-key>
+                                    <certificate>servercert</certificate>
+                                </keystore-reference>
+                            </server-identity>
+                            <client-authentication>
+                                <required/>
+                                <ca-certs>cacerts</ca-certs>
+                                <client-certs>clientcerts</client-certs>
+                                <cert-maps>
+                                    <cert-to-name>
+                                        <id>1</id>
+                                        <fingerprint>02:$NP_CLIENT_CERT_FINGERPRINT</fingerprint>
+                                        <map-type xmlns:x509c2n="urn:ietf:params:xml:ns:yang:ietf-x509-cert-to-name">x509c2n:specified</map-type>
+                                        <name>tls-test</name>
+                                    </cert-to-name>
+                                </cert-maps>
+                            </client-authentication>
+                        </tls-server-parameters>
+                    </tls>
+                </endpoint>
+            </endpoints>
+            <connection-type>
+                <persistent/>
+            </connection-type>
+        </netconf-client>
+    </call-home>
+</netconf-server>
diff --git a/csit/variables/netconf/callhome/configuration-files/tls/ietf-truststore.xml b/csit/variables/netconf/callhome/configuration-files/tls/ietf-truststore.xml
new file mode 100644 (file)
index 0000000..5097284
--- /dev/null
@@ -0,0 +1,16 @@
+<truststore xmlns="urn:ietf:params:xml:ns:yang:ietf-truststore">
+  <certificates>
+    <name>clientcerts</name>
+    <certificate>
+      <name>clientcert</name>
+      <cert>$NP_CLIENT_CERT</cert>
+    </certificate>
+  </certificates>
+  <certificates>
+    <name>cacerts</name>
+    <certificate>
+      <name>cacert</name>
+      <cert>$NP_CA_CERT</cert>
+    </certificate>
+  </certificates>
+</truststore>
index 6ea5c21fa4055759f4572dbdb561fcdcab0e455b..e8925e63627645847d340c268b8da936c86e314c 100644 (file)
@@ -11,11 +11,17 @@ CONFIG_PATH='/root/configuration-files'
 # Configuration from the following modules will be imported to the sysrepo datastore.
 # 1. Each module's configuration file should be placed under the $CONFIG_PATH folder with .xml extension, e.g. ietf-truststore.xml.
 # 2. Script will replace all variable placeholders with corresponding environment variables, e.g. $CALL_HOME_SERVER_IP.
-# Please, note that following environment variables will be set according to the provided keys(under the $CONFIG_PATH folder):
+# Please, note that following environment variables will be set according to the provided keys and certificates(under the $CONFIG_PATH/certs folder):
 #  - $NP_PRIVKEY
 #  - $NP_PUBKEY
+#  - $NP_CA_CERT
+#  - $NP_CLIENT_CERT
+#  - $NP_SERVER_PRIVATE_KEY
+#  - $NP_SERVER_PUBLIC_KEY
+#  - $NP_SERVER_CERTIFICATE
+#  - $NP_CLIENT_CERT_FINGERPRINT
 # 3. Modules must be provided in the correct order.
-MODULES_LIST=("ietf-keystore" "ietf-netconf-server")
+MODULES_LIST=("ietf-truststore" "ietf-keystore" "ietf-netconf-server")
 
 import_module()
 {
@@ -50,6 +56,15 @@ SAVEIFS=$IFS
 IFS=
 export NP_PRIVKEY=`cat /etc/ssh/ssh_host_rsa_key | sed -u '1d; $d'`
 export NP_PUBKEY=`openssl rsa -in /etc/ssh/ssh_host_rsa_key -pubout | sed -u '1d; $d'`
+
+if [ -d "$CONFIG_PATH/certs" ]; then
+    export NP_CA_CERT=`sed -u '1d; $d' $CONFIG_PATH/certs/ca.pem`
+    export NP_CLIENT_CERT=`sed -u '1d; $d' $CONFIG_PATH/certs/client.crt`
+    export NP_SERVER_PRIVATE_KEY=`sed -u '1d; $d' $CONFIG_PATH/certs/server.key`
+    export NP_SERVER_PUBLIC_KEY=`sed -u '1d; $d' $CONFIG_PATH/certs/server.pub`
+    export NP_SERVER_CERTIFICATE=`sed -u '1d; $d' $CONFIG_PATH/certs/server.crt`
+    export NP_CLIENT_CERT_FINGERPRINT=`openssl x509 -noout -fingerprint -in $CONFIG_PATH/certs/ca.pem -sha1 | cut -d'=' -f2-`
+fi
 IFS=$SAVEIFS
 
 # Import all provided configuration files for netopeer
diff --git a/csit/variables/netconf/callhome/json/apiv2/add_keystore_entry.json b/csit/variables/netconf/callhome/json/apiv2/add_keystore_entry.json
new file mode 100644 (file)
index 0000000..6618168
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "input": {
+        "key-credential": [
+            {
+                "key-id": "tls-device-key",
+                "private-key": "{base64-client-key}",
+                "passphrase": ""
+            }
+        ]
+    }
+}
diff --git a/csit/variables/netconf/callhome/json/apiv2/add_private_key.json b/csit/variables/netconf/callhome/json/apiv2/add_private_key.json
new file mode 100644 (file)
index 0000000..d823e8b
--- /dev/null
@@ -0,0 +1,13 @@
+{
+    "input": {
+        "private-key": [
+            {
+                "name": "tls-device-key",
+                "data": "{client-key}",
+                "certificate-chain": [
+                    "{certificate-chain}"
+                ]
+            }
+        ]
+    }
+}
diff --git a/csit/variables/netconf/callhome/json/apiv2/add_trusted_certificate.json b/csit/variables/netconf/callhome/json/apiv2/add_trusted_certificate.json
new file mode 100644 (file)
index 0000000..f7143ee
--- /dev/null
@@ -0,0 +1,14 @@
+{
+    "input": {
+        "trusted-certificate": [
+            {
+                "name": "ca",
+                "certificate": "{ca-certificate}"
+            },
+            {
+                "name": "tls-device-certificate",
+                "certificate": "{device-certificate}"
+            }
+        ]
+    }
+}
diff --git a/csit/variables/netconf/callhome/json/apiv2/create_tls_device.json b/csit/variables/netconf/callhome/json/apiv2/create_tls_device.json
new file mode 100644 (file)
index 0000000..198e70b
--- /dev/null
@@ -0,0 +1,9 @@
+{
+    "device": {
+        "unique-id": "{device_name}",
+        "tls-client-params": {
+            "key-id": "{key_id}",
+            "certificate-id": "{certificate_id}"
+        }
+    }
+}
diff --git a/csit/variables/netconf/callhome/x509_v3.cfg b/csit/variables/netconf/callhome/x509_v3.cfg
new file mode 100644 (file)
index 0000000..4177a0c
--- /dev/null
@@ -0,0 +1,4 @@
+basicConstraints=CA:FALSE
+nsComment="OpenSSL generated certificate for Netopeer2"
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid