Skip to content

Commit

Permalink
test: Add mtls test for download and streaming installation
Browse files Browse the repository at this point in the history
Based on the work of Florain Bezannier.
Changes are that the client key and certificate are now provided to the
rauc_dbus_dummy by rauc-hawkbit-updater through arguments of the
InstallBundle method call (for streaming installations).
This also removes the need for a separate mtls rauc_dbus_dummy fixture.

Signed-off-by: Robin van der Gracht <[email protected]>
  • Loading branch information
rvdgracht committed Mar 13, 2024
1 parent 66c8a96 commit 36b6361
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 8 deletions.
17 changes: 17 additions & 0 deletions test/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -416,3 +416,20 @@ def _mtls_certificates():
assert mtls_config.client_cert_exist()
return mtls_config
return _mtls_certificates

@pytest.fixture
def mtls_download_port(nginx_proxy, mtls_certificates):
"""
Runs an nginx proxy. HTTPS requests are forwarded to port 8080
(default port of the docker hawkBit instance). Returns the port the proxy is running on. This
port can be set in the rauc-hawkbit-updater config to test partial downloads.
"""
mtls_cert = mtls_certificates()
hash_issuer = mtls_cert.get_issuer_hash()
location_options = {"proxy_set_header X-Ssl-Issuer-Hash-1": hash_issuer}
server_options = {
"ssl_certificate": mtls_cert.ca_cert,
"ssl_certificate_key": mtls_cert.ca_key,
"ssl_client_certificate": mtls_cert.ca_cert,
}
return nginx_proxy(location_options, server_options, mtls=True)
26 changes: 18 additions & 8 deletions test/rauc_dbus_dummy.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ def _get_bundle_sha1(bundle):
return sha1.hexdigest()

@staticmethod
def _get_http_bundle_sha1(url, auth_header):
def _get_http_bundle_sha1(url, auth_header, cert=None, verify=True):
"""Download file from URL using HTTP range requests and compute its sha1 checksum."""
sha1 = hashlib.sha1()
headers = auth_header
Expand All @@ -112,7 +112,7 @@ def _get_http_bundle_sha1(url, auth_header):
offset = 0
while True:
headers['Range'] = f'bytes={offset}-{offset + range_size - 1}'
r = requests.get(url, headers=headers)
r = requests.get(url, headers=headers, cert=cert, verify=verify)
try:
r.raise_for_status()
sha1.update(r.content)
Expand All @@ -130,20 +130,30 @@ def _check_install_requirements(self, source, args):
Check that required headers are set, bundle is accessible (HTTP or locally) and its
checksum matches.
"""
if 'http-headers' in args:
if 'tls-key' in args and 'tls-cert' in args:
cert = (args['tls-cert'], args['tls-key'])
if 'tls-no-verify' in args and args['tls-no-verify']:
verify = False
elif 'tls-ca' in args:
verify = args['tls-ca']
else:
verify = True
source_sha1 = self._get_http_bundle_sha1(source, {}, cert, verify)

elif 'http-headers' in args:
assert len(args['http-headers']) == 1

[auth_header] = args['http-headers']
key, value = auth_header.split(': ', maxsplit=1)
http_bundle_sha1 = self._get_http_bundle_sha1(source, {key: value})
assert http_bundle_sha1 == self._get_bundle_sha1(self._bundle)
source_sha1 = self._get_http_bundle_sha1(source, {key: value})

# assume ssl_verify=false is set in test setup
assert args['tls-no-verify'] is True

else:
# check bundle checksum matches expected checksum
assert self._get_bundle_sha1(source) == self._get_bundle_sha1(self._bundle)
source_sha1 = self._get_bundle_sha1(source)

# check bundle checksum matches expected checksum
assert source_sha1 == self._get_bundle_sha1(self._bundle)

@property
def Operation(self):
Expand Down
40 changes: 40 additions & 0 deletions test/test_mtls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import pytest

from helper import run

@pytest.mark.parametrize('mode', ('download','streaming'))
def test_install_success_mtls(hawkbit, adjust_config, bundle_assigned,
mtls_download_port, mtls_config,
rauc_dbus_install_success, mode):
"""
Assign bundle to target and test successful download and installation via MTLS. Make sure installation
result is received correctly by hawkBit.
"""
config = adjust_config(
{'client': {
'hawkbit_server': f'localhost:{mtls_download_port}',
"ssl": "true",
"ssl_key": mtls_config.client_key,
"ssl_cert": mtls_config.client_cert,
"ssl_verify": "false",
'stream_bundle': 'true' if mode == 'streaming' else "false"}
},
remove={'client': ['bundle_download_location','auth_token']} if mode == 'streaming'else {'client':'auth_token'}
)

hawkbit.set_config("authentication.header.authority", mtls_config.get_issuer_hash())
hawkbit.set_config("authentication.header.enabled",True)

out, err, exitcode = run(f'rauc-hawkbit-updater -c "{config}" -r')

assert 'New software ready for download' in out

if mode == 'download':
assert 'Download complete' in out

assert 'Software bundle installed successfully.' in out
assert err == ''
assert exitcode == 0

status = hawkbit.get_action_status()
assert status[0]['type'] == 'finished'

0 comments on commit 36b6361

Please sign in to comment.