Skip to content

Commit

Permalink
feat(pre_encrypted_ota): Added HTTPS server in pytest
Browse files Browse the repository at this point in the history
1. Added the python based HTTPS server in pytest to start the https
server locally.
2. Updated the README.md file
3. Fixed some cosmetic changes in test_local_server_ota.c
  • Loading branch information
hrushikesh430 committed Jan 6, 2025
1 parent eef3909 commit a3d119e
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 29 deletions.
12 changes: 12 additions & 0 deletions esp_encrypted_img/examples/pre_encrypted_ota/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,18 @@ idf.py build flash

* An encrypted image is automatically generated by build system. Upload the generated encrypted image (`build/pre_encrypted_ota_secure.bin`) to a server for performing OTA update.

## Python based HTTPS server

After the successful build, start the local python based HTTPS server using the certificate and key present in the 'server_cert' directory (certificate: ca_cert.pem and key: ca_key.pem).

To start the server use the following command -
```
python pytest_pre_encrypted_ota.py build 8070 server_cert
```

1. build - build directory (where the new firmware image is present) will be exposed
2. 8070 - server port (user can use any port)
3. server_cert - cert directory where the certificate and key is present (here same ca_cert.pem is used in main/pre_encrypted_ota.c and server_cert dir). If user wants to use own certificate and key just pass the directory name, in which the certificate and key is present.

## Configuration

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ if(CONFIG_EXAMPLE_ENABLE_CI_TEST)
list(APPEND SRCS
"tests/test_local_server_ota.c")
list(APPEND INCLUDE_DIRS "tests")
list(APPEND EMBED_TXTFILES "tests/certs/servercert.pem"
"tests/certs/prvtkey.pem")
list(APPEND EMBED_TXTFILES "../server_certs/ca_cert.pem"
"../server_certs/ca_key.pem")
endif()

idf_component_register(SRCS "pre_encrypted_ota.c" ${SRCS}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -145,13 +145,13 @@ static esp_err_t root_head_handler(httpd_req_t *req)
return httpd_resp_send(req, NULL, binary_size); // No body for HEAD method
}

static const httpd_uri_t root = {
static const httpd_uri_t get_root = {
.uri = "/",
.method = HTTP_GET,
.handler = root_get_handler
};

static const httpd_uri_t root1 = {
static const httpd_uri_t head_root = {
.uri = "/",
.method = HTTP_HEAD,
.handler = root_head_handler
Expand All @@ -166,13 +166,13 @@ esp_err_t example_test_start_webserver(void)

httpd_ssl_config_t conf = HTTPD_SSL_CONFIG_DEFAULT();

extern const unsigned char servercert_start[] asm("_binary_servercert_pem_start");
extern const unsigned char servercert_end[] asm("_binary_servercert_pem_end");
extern const unsigned char servercert_start[] asm("_binary_ca_cert_pem_start");
extern const unsigned char servercert_end[] asm("_binary_ca_cert_pem_end");
conf.servercert = servercert_start;
conf.servercert_len = servercert_end - servercert_start;

extern const unsigned char prvtkey_pem_start[] asm("_binary_prvtkey_pem_start");
extern const unsigned char prvtkey_pem_end[] asm("_binary_prvtkey_pem_end");
extern const unsigned char prvtkey_pem_start[] asm("_binary_ca_key_pem_start");
extern const unsigned char prvtkey_pem_end[] asm("_binary_ca_key_pem_end");
conf.prvtkey_pem = prvtkey_pem_start;
conf.prvtkey_len = prvtkey_pem_end - prvtkey_pem_start;

Expand All @@ -184,7 +184,7 @@ esp_err_t example_test_start_webserver(void)

// Set URI handlers
ESP_LOGI(TAG, "Registering URI handlers");
httpd_register_uri_handler(server, &root);
httpd_register_uri_handler(server, &root1);
httpd_register_uri_handler(server, &get_root);
httpd_register_uri_handler(server, &head_root);
return ESP_OK;
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@
import http.server
import multiprocessing
import os
import sys

import socket
import ssl
from typing import Optional
from typing import Callable

import pexpect
Expand All @@ -17,6 +20,78 @@
host_ip = '127.0.0.1'
server_port = 443

server_cert = '-----BEGIN CERTIFICATE-----\n'\
'MIIDKzCCAhOgAwIBAgIUBxM3WJf2bP12kAfqhmhhjZWv0ukwDQYJKoZIhvcNAQEL\n'\
'BQAwJTEjMCEGA1UEAwwaRVNQMzIgSFRUUFMgc2VydmVyIGV4YW1wbGUwHhcNMTgx\n'\
'MDE3MTEzMjU3WhcNMjgxMDE0MTEzMjU3WjAlMSMwIQYDVQQDDBpFU1AzMiBIVFRQ\n'\
'UyBzZXJ2ZXIgZXhhbXBsZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\n'\
'ALBint6nP77RCQcmKgwPtTsGK0uClxg+LwKJ3WXuye3oqnnjqJCwMEneXzGdG09T\n'\
'sA0SyNPwrEgebLCH80an3gWU4pHDdqGHfJQa2jBL290e/5L5MB+6PTs2NKcojK/k\n'\
'qcZkn58MWXhDW1NpAnJtjVniK2Ksvr/YIYSbyD+JiEs0MGxEx+kOl9d7hRHJaIzd\n'\
'GF/vO2pl295v1qXekAlkgNMtYIVAjUy9CMpqaQBCQRL+BmPSJRkXBsYk8GPnieS4\n'\
'sUsp53DsNvCCtWDT6fd9D1v+BB6nDk/FCPKhtjYOwOAZlX4wWNSZpRNr5dfrxKsb\n'\
'jAn4PCuR2akdF4G8WLUeDWECAwEAAaNTMFEwHQYDVR0OBBYEFMnmdJKOEepXrHI/\n'\
'ivM6mVqJgAX8MB8GA1UdIwQYMBaAFMnmdJKOEepXrHI/ivM6mVqJgAX8MA8GA1Ud\n'\
'EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBADiXIGEkSsN0SLSfCF1VNWO3\n'\
'emBurfOcDq4EGEaxRKAU0814VEmU87btIDx80+z5Dbf+GGHCPrY7odIkxGNn0DJY\n'\
'W1WcF+DOcbiWoUN6DTkAML0SMnp8aGj9ffx3x+qoggT+vGdWVVA4pgwqZT7Ybntx\n'\
'bkzcNFW0sqmCv4IN1t4w6L0A87ZwsNwVpre/j6uyBw7s8YoJHDLRFT6g7qgn0tcN\n'\
'ZufhNISvgWCVJQy/SZjNBHSpnIdCUSJAeTY2mkM4sGxY0Widk8LnjydxZUSxC3Nl\n'\
'hb6pnMh3jRq4h0+5CZielA4/a+TdrNPv/qok67ot/XJdY3qHCCd8O2b14OVq9jo=\n'\
'-----END CERTIFICATE-----\n'

server_key = '-----BEGIN PRIVATE KEY-----\n'\
'MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCwYp7epz++0QkH\n'\
'JioMD7U7BitLgpcYPi8Cid1l7snt6Kp546iQsDBJ3l8xnRtPU7ANEsjT8KxIHmyw\n'\
'h/NGp94FlOKRw3ahh3yUGtowS9vdHv+S+TAfuj07NjSnKIyv5KnGZJ+fDFl4Q1tT\n'\
'aQJybY1Z4itirL6/2CGEm8g/iYhLNDBsRMfpDpfXe4URyWiM3Rhf7ztqZdveb9al\n'\
'3pAJZIDTLWCFQI1MvQjKamkAQkES/gZj0iUZFwbGJPBj54nkuLFLKedw7DbwgrVg\n'\
'0+n3fQ9b/gQepw5PxQjyobY2DsDgGZV+MFjUmaUTa+XX68SrG4wJ+DwrkdmpHReB\n'\
'vFi1Hg1hAgMBAAECggEAaTCnZkl/7qBjLexIryC/CBBJyaJ70W1kQ7NMYfniWwui\n'\
'f0aRxJgOdD81rjTvkINsPp+xPRQO6oOadjzdjImYEuQTqrJTEUnntbu924eh+2D9\n'\
'Mf2CAanj0mglRnscS9mmljZ0KzoGMX6Z/EhnuS40WiJTlWlH6MlQU/FDnwC6U34y\n'\
'JKy6/jGryfsx+kGU/NRvKSru6JYJWt5v7sOrymHWD62IT59h3blOiP8GMtYKeQlX\n'\
'49om9Mo1VTIFASY3lrxmexbY+6FG8YO+tfIe0tTAiGrkb9Pz6tYbaj9FjEWOv4Vc\n'\
'+3VMBUVdGJjgqvE8fx+/+mHo4Rg69BUPfPSrpEg7sQKBgQDlL85G04VZgrNZgOx6\n'\
'pTlCCl/NkfNb1OYa0BELqWINoWaWQHnm6lX8YjrUjwRpBF5s7mFhguFjUjp/NW6D\n'\
'0EEg5BmO0ePJ3dLKSeOA7gMo7y7kAcD/YGToqAaGljkBI+IAWK5Su5yldrECTQKG\n'\
'YnMKyQ1MWUfCYEwHtPvFvE5aPwKBgQDFBWXekpxHIvt/B41Cl/TftAzE7/f58JjV\n'\
'MFo/JCh9TDcH6N5TMTRS1/iQrv5M6kJSSrHnq8pqDXOwfHLwxetpk9tr937VRzoL\n'\
'CuG1Ar7c1AO6ujNnAEmUVC2DppL/ck5mRPWK/kgLwZSaNcZf8sydRgphsW1ogJin\n'\
'7g0nGbFwXwKBgQCPoZY07Pr1TeP4g8OwWTu5F6dSvdU2CAbtZthH5q98u1n/cAj1\n'\
'noak1Srpa3foGMTUn9CHu+5kwHPIpUPNeAZZBpq91uxa5pnkDMp3UrLIRJ2uZyr8\n'\
'4PxcknEEh8DR5hsM/IbDcrCJQglM19ZtQeW3LKkY4BsIxjDf45ymH407IQKBgE/g\n'\
'Ul6cPfOxQRlNLH4VMVgInSyyxWx1mODFy7DRrgCuh5kTVh+QUVBM8x9lcwAn8V9/\n'\
'nQT55wR8E603pznqY/jX0xvAqZE6YVPcw4kpZcwNwL1RhEl8GliikBlRzUL3SsW3\n'\
'q30AfqEViHPE3XpE66PPo6Hb1ymJCVr77iUuC3wtAoGBAIBrOGunv1qZMfqmwAY2\n'\
'lxlzRgxgSiaev0lTNxDzZkmU/u3dgdTwJ5DDANqPwJc6b8SGYTp9rQ0mbgVHnhIB\n'\
'jcJQBQkTfq6Z0H6OoTVi7dPs3ibQJFrtkoyvYAbyk36quBmNRjVh6rc8468bhXYr\n'\
'v/t+MeGJP/0Zw8v/X2CFll96\n'\
'-----END PRIVATE KEY-----\n'

def start_https_server(ota_image_dir: str, server_ip: str, port: int, server_file: Optional[str] = None, key_file: Optional[str] = None) -> None:
os.chdir(ota_image_dir)

if server_file is None:
server_file = os.path.join(ota_image_dir, 'server_cert.pem')
cert_file_handle = open(server_file, 'w+')
cert_file_handle.write(server_cert)
cert_file_handle.close()

if key_file is None:
key_file = os.path.join(ota_image_dir, 'server_key.pem')
key_file_handle = open('server_key.pem', 'w+')
key_file_handle.write(server_key)
key_file_handle.close()

httpd = http.server.HTTPServer((server_ip, port), http.server.SimpleHTTPRequestHandler)

ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
ssl_context.load_cert_chain(certfile=server_file, keyfile=key_file)

httpd.socket = ssl_context.wrap_socket(httpd.socket, server_side=True)
httpd.serve_forever()

@pytest.mark.generic
def test_examples_protocol_pre_encrypted_ota_example(dut: Dut) -> None:
bin_path = os.path.join(dut.app.binary_path, enc_bin_name)
Expand All @@ -36,3 +111,16 @@ def test_examples_protocol_pre_encrypted_ota_example(dut: Dut) -> None:
finally:
pass

if __name__ == '__main__':
if sys.argv[2:]: # if two or more arguments are provided
# Usage: python pytest_pre_encrypted_ota.py <image_dir> <server_port> <cert_dir>
this_dir = os.path.dirname(os.path.realpath(__file__))
bin_dir = os.path.join(this_dir, sys.argv[1])
port = int(sys.argv[2])
cert_dir = bin_dir if not sys.argv[3:] else os.path.join(this_dir, sys.argv[3]) # optional argument
print(f'Starting HTTPS server at "https://0.0.0.0:{port}"')
start_https_server(bin_dir, '', port,
server_file=os.path.join(cert_dir, 'ca_cert.pem'),
key_file=os.path.join(cert_dir, 'ca_key.pem'))


0 comments on commit a3d119e

Please sign in to comment.