python-tuf/tests/test_formats.py
Joshua Lock ecb6d26206 Remove deprecated securesystemslib.formats schemas
TUF specific schemas have moved to tuf.formats, ensure they are used
throughout and remove stray references to no longer supported schemas
in securesystemslib.format

Signed-off-by: Joshua Lock <jlock@vmware.com>
2019-09-17 10:28:10 +01:00

933 lines
35 KiB
Python
Executable file

#!/usr/bin/env python
# Copyright 2012 - 2017, New York University and the TUF contributors
# SPDX-License-Identifier: MIT OR Apache-2.0
"""
<Program Name>
test_formats.py
<Author>
Vladimir Diaz <vladimir.v.diaz@gmail.com>
<Started>
October 2012.
<Copyright>
See LICENSE-MIT OR LICENSE for licensing information.
<Purpose>
Unit test for 'formats.py'
"""
# Help with Python 3 compatibility, where the print statement is a function, an
# implicit relative import is invalid, and the '/' operator performs true
# division. Example: print 'hello world' raises a 'SyntaxError' exception.
from __future__ import print_function
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
import unittest
import datetime
import tuf
import tuf.formats
import securesystemslib
import six
class TestFormats(unittest.TestCase):
def setUp(self):
pass
def tearDown(self):
pass
def test_schemas(self):
# Test conditions for valid schemas.
valid_schemas = {
'ISO8601_DATETIME_SCHEMA': (securesystemslib.formats.ISO8601_DATETIME_SCHEMA,
'1985-10-21T13:20:00Z'),
'UNIX_TIMESTAMP_SCHEMA': (securesystemslib.formats.UNIX_TIMESTAMP_SCHEMA, 499137720),
'HASH_SCHEMA': (securesystemslib.formats.HASH_SCHEMA, 'A4582BCF323BCEF'),
'HASHDICT_SCHEMA': (securesystemslib.formats.HASHDICT_SCHEMA,
{'sha256': 'A4582BCF323BCEF'}),
'HEX_SCHEMA': (securesystemslib.formats.HEX_SCHEMA, 'A4582BCF323BCEF'),
'KEYID_SCHEMA': (securesystemslib.formats.KEYID_SCHEMA, '123456789abcdef'),
'KEYIDS_SCHEMA': (securesystemslib.formats.KEYIDS_SCHEMA,
['123456789abcdef', '123456789abcdef']),
'SCHEME_SCHEMA': (securesystemslib.formats.SCHEME_SCHEMA, 'rsassa-pss-sha256'),
'RELPATH_SCHEMA': (tuf.formats.RELPATH_SCHEMA, 'metadata/root/'),
'RELPATHS_SCHEMA': (tuf.formats.RELPATHS_SCHEMA,
['targets/role1/', 'targets/role2/']),
'PATH_SCHEMA': (securesystemslib.formats.PATH_SCHEMA, '/home/someuser/'),
'PATHS_SCHEMA': (securesystemslib.formats.PATHS_SCHEMA,
['/home/McFly/', '/home/Tannen/']),
'URL_SCHEMA': (securesystemslib.formats.URL_SCHEMA,
'https://www.updateframework.com/'),
'VERSION_SCHEMA': (tuf.formats.VERSION_SCHEMA,
{'major': 1, 'minor': 0, 'fix': 8}),
'LENGTH_SCHEMA': (tuf.formats.LENGTH_SCHEMA, 8),
'NAME_SCHEMA': (securesystemslib.formats.NAME_SCHEMA, 'Marty McFly'),
'BOOLEAN_SCHEMA': (securesystemslib.formats.BOOLEAN_SCHEMA, True),
'THRESHOLD_SCHEMA': (tuf.formats.THRESHOLD_SCHEMA, 1),
'ROLENAME_SCHEMA': (tuf.formats.ROLENAME_SCHEMA, 'Root'),
'RSAKEYBITS_SCHEMA': (securesystemslib.formats.RSAKEYBITS_SCHEMA, 4096),
'PASSWORD_SCHEMA': (securesystemslib.formats.PASSWORD_SCHEMA, 'secret'),
'PASSWORDS_SCHEMA': (securesystemslib.formats.PASSWORDS_SCHEMA, ['pass1', 'pass2']),
'KEYVAL_SCHEMA': (securesystemslib.formats.KEYVAL_SCHEMA,
{'public': 'pubkey', 'private': 'privkey'}),
'KEY_SCHEMA': (securesystemslib.formats.KEY_SCHEMA,
{'keytype': 'rsa',
'scheme': 'rsassa-pss-sha256',
'keyval': {'public': 'pubkey',
'private': 'privkey'}}),
'RSAKEY_SCHEMA': (securesystemslib.formats.RSAKEY_SCHEMA,
{'keytype': 'rsa',
'scheme': 'rsassa-pss-sha256',
'keyid': '123456789abcdef',
'keyval': {'public': 'pubkey',
'private': 'privkey'}}),
'FILEINFO_SCHEMA': (tuf.formats.FILEINFO_SCHEMA,
{'length': 1024,
'hashes': {'sha256': 'A4582BCF323BCEF'},
'custom': {'type': 'paintjob'}}),
'FILEDICT_SCHEMA': (tuf.formats.FILEDICT_SCHEMA,
{'metadata/root.json': {'length': 1024,
'hashes': {'sha256': 'ABCD123'},
'custom': {'type': 'metadata'}}}),
'TARGETINFO_SCHEMA': (tuf.formats.TARGETINFO_SCHEMA,
{'filepath': 'targets/target1.gif',
'fileinfo': {'length': 1024,
'hashes': {'sha256': 'ABCD123'},
'custom': {'type': 'target'}}}),
'TARGETINFOS_SCHEMA': (tuf.formats.TARGETINFOS_SCHEMA,
[{'filepath': 'targets/target1.gif',
'fileinfo': {'length': 1024,
'hashes': {'sha256': 'ABCD123'},
'custom': {'type': 'target'}}}]),
'SIGNATURE_SCHEMA': (securesystemslib.formats.SIGNATURE_SCHEMA,
{'keyid': '123abc',
'sig': 'A4582BCF323BCEF'}),
'SIGNATURESTATUS_SCHEMA': (tuf.formats.SIGNATURESTATUS_SCHEMA,
{'threshold': 1,
'good_sigs': ['123abc'],
'bad_sigs': ['123abc'],
'unknown_sigs': ['123abc'],
'untrusted_sigs': ['123abc'],
'unknown_signing_schemes': ['123abc']}),
'SIGNABLE_SCHEMA': (tuf.formats.SIGNABLE_SCHEMA,
{'signed': 'signer',
'signatures': [{'keyid': '123abc',
'sig': 'A4582BCF323BCEF'}]}),
'KEYDICT_SCHEMA': (securesystemslib.formats.KEYDICT_SCHEMA,
{'123abc': {'keytype': 'rsa',
'scheme': 'rsassa-pss-sha256',
'keyval': {'public': 'pubkey',
'private': 'privkey'}}}),
'KEYDB_SCHEMA': (tuf.formats.KEYDB_SCHEMA,
{'123abc': {'keytype': 'rsa',
'scheme': 'rsassa-pss-sha256',
'keyid': '123456789abcdef',
'keyval': {'public': 'pubkey',
'private': 'privkey'}}}),
'SCPCONFIG_SCHEMA': (tuf.formats.SCPCONFIG_SCHEMA,
{'general': {'transfer_module': 'scp',
'metadata_path': '/path/meta.json',
'targets_directory': '/targets'},
'scp': {'host': 'http://localhost:8001',
'user': 'McFly',
'identity_file': '/home/.ssh/file',
'remote_directory': '/home/McFly'}}),
'RECEIVECONFIG_SCHEMA': (tuf.formats.RECEIVECONFIG_SCHEMA,
{'general': {'transfer_module': 'scp',
'pushroots': ['/pushes'],
'repository_directory': '/repo',
'metadata_directory': '/repo/meta',
'targets_directory': '/repo/targets',
'backup_directory': '/repo/backup'}}),
'ROLE_SCHEMA': (tuf.formats.ROLE_SCHEMA,
{'keyids': ['123abc'],
'threshold': 1,
'paths': ['path1/', 'path2']}),
'ROLEDICT_SCHEMA': (tuf.formats.ROLEDICT_SCHEMA,
{'root': {'keyids': ['123abc'],
'threshold': 1,
'paths': ['path1/', 'path2']}}),
'ROOT_SCHEMA': (tuf.formats.ROOT_SCHEMA,
{'_type': 'root',
'spec_version': '1.0.0',
'version': 8,
'consistent_snapshot': False,
'expires': '1985-10-21T13:20:00Z',
'keys': {'123abc': {'keytype': 'rsa',
'scheme': 'rsassa-pss-sha256',
'keyval': {'public': 'pubkey',
'private': 'privkey'}}},
'roles': {'root': {'keyids': ['123abc'],
'threshold': 1,
'paths': ['path1/', 'path2']}}}),
'TARGETS_SCHEMA': (tuf.formats.TARGETS_SCHEMA,
{'_type': 'targets',
'spec_version': '1.0.0',
'version': 8,
'expires': '1985-10-21T13:20:00Z',
'targets': {'metadata/targets.json': {'length': 1024,
'hashes': {'sha256': 'ABCD123'},
'custom': {'type': 'metadata'}}},
'delegations': {'keys': {'123abc': {'keytype':'rsa',
'scheme': 'rsassa-pss-sha256',
'keyval': {'public': 'pubkey',
'private': 'privkey'}}},
'roles': [{'name': 'root', 'keyids': ['123abc'],
'threshold': 1,
'paths': ['path1/', 'path2']}]}}),
'SNAPSHOT_SCHEMA': (tuf.formats.SNAPSHOT_SCHEMA,
{'_type': 'snapshot',
'spec_version': '1.0.0',
'version': 8,
'expires': '1985-10-21T13:20:00Z',
'meta': {'snapshot.json': {'version': 1024}}}),
'TIMESTAMP_SCHEMA': (tuf.formats.TIMESTAMP_SCHEMA,
{'_type': 'timestamp',
'spec_version': '1.0.0',
'version': 8,
'expires': '1985-10-21T13:20:00Z',
'meta': {'metadattimestamp.json': {'length': 1024,
'hashes': {'sha256': 'AB1245'}}}}),
'MIRROR_SCHEMA': (tuf.formats.MIRROR_SCHEMA,
{'url_prefix': 'http://localhost:8001',
'metadata_path': 'metadata/',
'targets_path': 'targets/',
'confined_target_dirs': ['path1/', 'path2/'],
'custom': {'type': 'mirror'}}),
'MIRRORDICT_SCHEMA': (tuf.formats.MIRRORDICT_SCHEMA,
{'mirror1': {'url_prefix': 'http://localhost:8001',
'metadata_path': 'metadata/',
'targets_path': 'targets/',
'confined_target_dirs': ['path1/', 'path2/'],
'custom': {'type': 'mirror'}}}),
'MIRRORLIST_SCHEMA': (tuf.formats.MIRRORLIST_SCHEMA,
{'_type': 'mirrors',
'version': 8,
'spec_version': '1.0.0',
'expires': '1985-10-21T13:20:00Z',
'mirrors': [{'url_prefix': 'http://localhost:8001',
'metadata_path': 'metadata/',
'targets_path': 'targets/',
'confined_target_dirs': ['path1/', 'path2/'],
'custom': {'type': 'mirror'}}]})}
# Iterate 'valid_schemas', ensuring each 'valid_schema' correctly matches
# its respective 'schema_type'.
for schema_name, (schema_type, valid_schema) in six.iteritems(valid_schemas):
if not schema_type.matches(valid_schema):
print('bad schema: ' + repr(valid_schema))
self.assertEqual(True, schema_type.matches(valid_schema))
# Test conditions for invalid schemas.
# Set the 'valid_schema' of 'valid_schemas' to an invalid
# value and test that it does not match 'schema_type'.
for schema_name, (schema_type, valid_schema) in six.iteritems(valid_schemas):
invalid_schema = 0xBAD
if isinstance(schema_type, securesystemslib.schema.Integer):
invalid_schema = 'BAD'
self.assertEqual(False, schema_type.matches(invalid_schema))
def test_specfication_version_schema(self):
"""Test valid and invalid SPECIFICATION_VERSION_SCHEMAs, using examples
from 'regex101.com/r/Ly7O1x/3/', referenced by
'semver.org/spec/v2.0.0.html'. """
valid_schemas = [
"0.0.4",
"1.2.3",
"10.20.30",
"1.1.2-prerelease+meta",
"1.1.2+meta",
"1.1.2+meta-valid",
"1.0.0-alpha",
"1.0.0-beta",
"1.0.0-alpha.beta",
"1.0.0-alpha.beta.1",
"1.0.0-alpha.1",
"1.0.0-alpha0.valid",
"1.0.0-alpha.0valid",
"1.0.0-alpha-a.b-c-somethinglong+build.1-aef.1-its-okay",
"1.0.0-rc.1+build.1",
"2.0.0-rc.1+build.123",
"1.2.3-beta",
"10.2.3-DEV-SNAPSHOT",
"1.2.3-SNAPSHOT-123",
"1.0.0",
"2.0.0",
"1.1.7",
"2.0.0+build.1848",
"2.0.1-alpha.1227",
"1.0.0-alpha+beta",
"1.2.3----RC-SNAPSHOT.12.9.1--.12+788",
"1.2.3----R-S.12.9.1--.12+meta",
"1.2.3----RC-SNAPSHOT.12.9.1--.12",
"1.0.0+0.build.1-rc.10000aaa-kk-0.1",
"99999999999999999999999.999999999999999999.99999999999999999",
"1.0.0-0A.is.legal"]
for valid_schema in valid_schemas:
self.assertTrue(
tuf.formats.SPECIFICATION_VERSION_SCHEMA.matches(valid_schema),
"'{}' should match 'SPECIFICATION_VERSION_SCHEMA'.".format(
valid_schema))
invalid_schemas = [
"1",
"1.2",
"1.2.3-0123",
"1.2.3-0123.0123",
"1.1.2+.123",
"+invalid",
"-invalid",
"-invalid+invalid",
"-invalid.01",
"alpha",
"alpha.beta",
"alpha.beta.1",
"alpha.1",
"alpha+beta",
"alpha_beta",
"alpha.",
"alpha..",
"beta",
"1.0.0-alpha_beta",
"-alpha.",
"1.0.0-alpha..",
"1.0.0-alpha..1",
"1.0.0-alpha...1",
"1.0.0-alpha....1",
"1.0.0-alpha.....1",
"1.0.0-alpha......1",
"1.0.0-alpha.......1",
"01.1.1",
"1.01.1",
"1.1.01",
"1.2",
"1.2.3.DEV",
"1.2-SNAPSHOT",
"1.2.31.2.3----RC-SNAPSHOT.12.09.1--..12+788",
"1.2-RC-SNAPSHOT",
"-1.0.3-gamma+b7718",
"+justmeta",
"9.8.7+meta+meta",
"9.8.7-whatever+meta+meta",
"99999999999999999999999.999999999999999999.99999999999999999----RC-SNAPSHOT.12.09.1--------------------------------..12"]
for invalid_schema in invalid_schemas:
self.assertFalse(
tuf.formats.SPECIFICATION_VERSION_SCHEMA.matches(invalid_schema),
"'{}' should not match 'SPECIFICATION_VERSION_SCHEMA'.".format(
invalid_schema))
def test_build_dict_conforming_to_schema(self):
# Test construction of a few metadata formats using
# build_dict_conforming_to_schema().
# Try the wrong type of schema object.
STRING_SCHEMA = securesystemslib.schema.AnyString()
with self.assertRaises(ValueError):
tuf.formats.build_dict_conforming_to_schema(
STRING_SCHEMA, string='some string')
# Try building Timestamp metadata.
spec_version = tuf.SPECIFICATION_VERSION
version = 8
length = 88
hashes = {'sha256': '3c7fe3eeded4a34'}
expires = '1985-10-21T13:20:00Z'
filedict = {'snapshot.json': {'length': length, 'hashes': hashes}}
# Try with and without _type and spec_version, both of which are
# automatically populated if they are not included.
self.assertTrue(tuf.formats.TIMESTAMP_SCHEMA.matches( # both
tuf.formats.build_dict_conforming_to_schema(
tuf.formats.TIMESTAMP_SCHEMA,
_type='timestamp',
spec_version=spec_version,
version=version,
expires=expires,
meta=filedict)))
self.assertTrue(tuf.formats.TIMESTAMP_SCHEMA.matches( # neither
tuf.formats.build_dict_conforming_to_schema(
tuf.formats.TIMESTAMP_SCHEMA,
version=version,
expires=expires,
meta=filedict)))
self.assertTrue(tuf.formats.TIMESTAMP_SCHEMA.matches( # one
tuf.formats.build_dict_conforming_to_schema(
tuf.formats.TIMESTAMP_SCHEMA,
spec_version=spec_version,
version=version,
expires=expires,
meta=filedict)))
self.assertTrue(tuf.formats.TIMESTAMP_SCHEMA.matches( # the other
tuf.formats.build_dict_conforming_to_schema(
tuf.formats.TIMESTAMP_SCHEMA,
_type='timestamp',
version=version,
expires=expires,
meta=filedict)))
# Try test arguments for invalid Timestamp creation.
bad_spec_version = 123
bad_version = 'eight'
bad_expires = '2000'
bad_filedict = 123
with self.assertRaises(securesystemslib.exceptions.FormatError):
tuf.formats.build_dict_conforming_to_schema(
tuf.formats.TIMESTAMP_SCHEMA,
_type='timestamp',
spec_version=bad_spec_version,
version=version,
expires=expires,
meta=filedict)
with self.assertRaises(securesystemslib.exceptions.FormatError):
tuf.formats.build_dict_conforming_to_schema(
tuf.formats.TIMESTAMP_SCHEMA,
_type='timestamp',
spec_version=spec_version,
version=bad_version,
expires=expires,
meta=filedict)
with self.assertRaises(securesystemslib.exceptions.FormatError):
tuf.formats.build_dict_conforming_to_schema(
tuf.formats.TIMESTAMP_SCHEMA,
_type='timestamp',
spec_version=spec_version,
version=version,
expires=bad_expires,
meta=filedict)
with self.assertRaises(securesystemslib.exceptions.FormatError):
tuf.formats.build_dict_conforming_to_schema(
tuf.formats.TIMESTAMP_SCHEMA,
_type='timestamp',
spec_version=spec_version,
version=version,
expires=expires,
meta=bad_filedict)
with self.assertRaises(ValueError):
tuf.formats.build_dict_conforming_to_schema(123)
# Try building Root metadata.
consistent_snapshot = False
keydict = {'123abc': {'keytype': 'rsa',
'scheme': 'rsassa-pss-sha256',
'keyval': {'public': 'pubkey',
'private': 'privkey'}}}
roledict = {'root': {'keyids': ['123abc'],
'threshold': 1,
'paths': ['path1/', 'path2']}}
self.assertTrue(tuf.formats.ROOT_SCHEMA.matches(
tuf.formats.build_dict_conforming_to_schema(
tuf.formats.ROOT_SCHEMA,
_type='root',
spec_version=spec_version,
version=version,
expires=expires,
keys=keydict,
roles=roledict,
consistent_snapshot=consistent_snapshot)))
# Additional test arguments for invalid Root creation.
bad_keydict = 123
bad_roledict = 123
# TODO: Later on, write a test looper that takes pairs of key-value args
# to substitute in on each run to shorten this.... There's a lot of
# test code that looks like this, and it'd be easier to use a looper.
with self.assertRaises(securesystemslib.exceptions.FormatError):
tuf.formats.build_dict_conforming_to_schema(
tuf.formats.ROOT_SCHEMA,
_type='root',
spec_version=bad_spec_version,
version=version,
expires=expires,
keys=keydict,
roles=roledict,
consistent_snapshot=consistent_snapshot)
with self.assertRaises(securesystemslib.exceptions.FormatError):
tuf.formats.build_dict_conforming_to_schema(
tuf.formats.ROOT_SCHEMA,
_type='root',
spec_version=spec_version,
version=bad_version,
expires=expires,
keys=keydict,
roles=roledict,
consistent_snapshot=consistent_snapshot)
with self.assertRaises(securesystemslib.exceptions.FormatError):
tuf.formats.build_dict_conforming_to_schema(
tuf.formats.ROOT_SCHEMA,
_type='root',
spec_version=spec_version,
version=version,
expires=bad_expires,
keys=keydict,
roles=roledict,
consistent_snapshot=consistent_snapshot)
with self.assertRaises(securesystemslib.exceptions.FormatError):
tuf.formats.build_dict_conforming_to_schema(
tuf.formats.ROOT_SCHEMA,
_type='root',
spec_version=spec_version,
version=version,
expires=expires,
keys=bad_keydict,
roles=roledict,
consistent_snapshot=consistent_snapshot)
with self.assertRaises(securesystemslib.exceptions.FormatError):
tuf.formats.build_dict_conforming_to_schema(
tuf.formats.ROOT_SCHEMA,
_type='root',
spec_version=spec_version,
version=version,
expires=expires,
keys=keydict,
roles=bad_roledict,
consistent_snapshot=consistent_snapshot)
with self.assertRaises(TypeError):
tuf.formats.build_dict_conforming_to_schema(
tuf.formats.ROOT_SCHEMA, 'bad')
with self.assertRaises(ValueError):
tuf.formats.build_dict_conforming_to_schema(
'bad',
_type='root',
spec_version=spec_version,
version=version,
expires=expires,
keys=keydict,
roles=roledict,
consistent_snapshot=consistent_snapshot)
# Try building Snapshot metadata.
versiondict = {'targets.json' : {'version': version}}
self.assertTrue(tuf.formats.SNAPSHOT_SCHEMA.matches(
tuf.formats.build_dict_conforming_to_schema(
tuf.formats.SNAPSHOT_SCHEMA,
_type='snapshot',
spec_version=spec_version,
version=version,
expires=expires,
meta=versiondict)))
# Additional test arguments for invalid Snapshot creation.
bad_versiondict = 123
with self.assertRaises(securesystemslib.exceptions.FormatError):
tuf.formats.build_dict_conforming_to_schema(
tuf.formats.SNAPSHOT_SCHEMA,
_type='snapshot',
spec_version=bad_spec_version,
version=version,
expires=expires,
meta=versiondict)
with self.assertRaises(securesystemslib.exceptions.FormatError):
tuf.formats.build_dict_conforming_to_schema(
tuf.formats.SNAPSHOT_SCHEMA,
_type='snapshot',
spec_version=spec_version,
version=bad_version,
expires=expires,
meta=versiondict)
with self.assertRaises(securesystemslib.exceptions.FormatError):
tuf.formats.build_dict_conforming_to_schema(
tuf.formats.SNAPSHOT_SCHEMA,
_type='snapshot',
spec_version=spec_version,
version=version,
expires=bad_expires,
meta=versiondict)
with self.assertRaises(securesystemslib.exceptions.FormatError):
tuf.formats.build_dict_conforming_to_schema(
tuf.formats.SNAPSHOT_SCHEMA,
_type='snapshot',
spec_version=spec_version,
version=version,
expires=expires,
meta=bad_versiondict)
# Try building Targets metadata.
filedict = {'metadata/targets.json': {'length': 1024,
'hashes': {'sha256': 'ABCD123'},
'custom': {'type': 'metadata'}}}
delegations = {'keys': {'123abc': {'keytype':'rsa',
'scheme': 'rsassa-pss-sha256',
'keyval': {'public': 'pubkey',
'private': 'privkey'}}},
'roles': [{'name': 'root', 'keyids': ['123abc'],
'threshold': 1, 'paths': ['path1/', 'path2']}]}
self.assertTrue(tuf.formats.TARGETS_SCHEMA.matches(
tuf.formats.build_dict_conforming_to_schema(
tuf.formats.TARGETS_SCHEMA,
_type='targets',
spec_version=spec_version,
version=version,
expires=expires,
targets=filedict,
delegations=delegations)))
# Try with no delegations included (should work, since they're optional).
self.assertTrue(tuf.formats.TARGETS_SCHEMA.matches(
tuf.formats.build_dict_conforming_to_schema(
tuf.formats.TARGETS_SCHEMA,
_type='targets',
spec_version=spec_version,
version=version,
expires=expires,
targets=filedict)))
# Additional test arguments for invalid Targets creation.
bad_filedict = 123
bad_delegations = 123
with self.assertRaises(securesystemslib.exceptions.FormatError):
tuf.formats.build_dict_conforming_to_schema(
tuf.formats.TARGETS_SCHEMA,
_type='targets',
spec_version=spec_version,
version=bad_version,
expires=expires,
targets=filedict,
delegations=delegations)
with self.assertRaises(securesystemslib.exceptions.FormatError):
tuf.formats.build_dict_conforming_to_schema(
tuf.formats.TARGETS_SCHEMA,
_type='targets',
spec_version=spec_version,
version=version,
expires=bad_expires,
targets=filedict,
delegations=delegations)
with self.assertRaises(securesystemslib.exceptions.FormatError):
tuf.formats.build_dict_conforming_to_schema(
tuf.formats.TARGETS_SCHEMA,
_type='targets',
spec_version=spec_version,
version=version,
expires=expires,
targets=bad_filedict,
delegations=delegations)
with self.assertRaises(securesystemslib.exceptions.FormatError):
tuf.formats.build_dict_conforming_to_schema(
tuf.formats.TARGETS_SCHEMA,
_type='targets',
spec_version=spec_version,
version=version,
expires=expires,
targets=filedict,
delegations=bad_delegations)
def test_unix_timestamp_to_datetime(self):
# Test conditions for valid arguments.
UNIX_TIMESTAMP_SCHEMA = securesystemslib.formats.UNIX_TIMESTAMP_SCHEMA
self.assertTrue(datetime.datetime, tuf.formats.unix_timestamp_to_datetime(499137720))
datetime_object = datetime.datetime(1985, 10, 26, 1, 22)
self.assertEqual(datetime_object, tuf.formats.unix_timestamp_to_datetime(499137720))
# Test conditions for invalid arguments.
self.assertRaises(securesystemslib.exceptions.FormatError, tuf.formats.unix_timestamp_to_datetime, 'bad')
self.assertRaises(securesystemslib.exceptions.FormatError, tuf.formats.unix_timestamp_to_datetime, 1000000000000000000000)
self.assertRaises(securesystemslib.exceptions.FormatError, tuf.formats.unix_timestamp_to_datetime, -1)
self.assertRaises(securesystemslib.exceptions.FormatError, tuf.formats.unix_timestamp_to_datetime, ['5'])
def test_datetime_to_unix_timestamp(self):
# Test conditions for valid arguments.
datetime_object = datetime.datetime(2015, 10, 21, 19, 28)
self.assertEqual(1445455680, tuf.formats.datetime_to_unix_timestamp(datetime_object))
# Test conditions for invalid arguments.
self.assertRaises(securesystemslib.exceptions.FormatError, tuf.formats.datetime_to_unix_timestamp, 'bad')
self.assertRaises(securesystemslib.exceptions.FormatError, tuf.formats.datetime_to_unix_timestamp, 1000000000000000000000)
self.assertRaises(securesystemslib.exceptions.FormatError, tuf.formats.datetime_to_unix_timestamp, ['1'])
def test_format_base64(self):
# Test conditions for valid arguments.
data = 'updateframework'.encode('utf-8')
self.assertEqual('dXBkYXRlZnJhbWV3b3Jr', tuf.formats.format_base64(data))
self.assertTrue(isinstance(tuf.formats.format_base64(data), six.string_types))
# Test conditions for invalid arguments.
self.assertRaises(securesystemslib.exceptions.FormatError, tuf.formats.format_base64, 123)
self.assertRaises(securesystemslib.exceptions.FormatError, tuf.formats.format_base64, True)
self.assertRaises(securesystemslib.exceptions.FormatError, tuf.formats.format_base64, ['123'])
def test_parse_base64(self):
# Test conditions for valid arguments.
base64 = 'dXBkYXRlZnJhbWV3b3Jr'
self.assertEqual(b'updateframework', tuf.formats.parse_base64(base64))
self.assertTrue(isinstance(tuf.formats.parse_base64(base64), six.binary_type))
# Test conditions for invalid arguments.
self.assertRaises(securesystemslib.exceptions.FormatError, tuf.formats.parse_base64, 123)
self.assertRaises(securesystemslib.exceptions.FormatError, tuf.formats.parse_base64, True)
self.assertRaises(securesystemslib.exceptions.FormatError, tuf.formats.parse_base64, ['123'])
self.assertRaises(securesystemslib.exceptions.FormatError, tuf.formats.parse_base64, '/')
def test_make_signable(self):
# Test conditions for expected make_signable() behavior.
root = {'_type': 'root',
'spec_version': '1.0.0',
'version': 8,
'consistent_snapshot': False,
'expires': '1985-10-21T13:20:00Z',
'keys': {'123abc': {'keytype': 'rsa',
'scheme': 'rsassa-pss-sha256',
'keyval': {'public': 'pubkey',
'private': 'privkey'}}},
'roles': {'root': {'keyids': ['123abc'],
'threshold': 1,
'paths': ['path1/', 'path2']}}}
SIGNABLE_SCHEMA = tuf.formats.SIGNABLE_SCHEMA
self.assertTrue(SIGNABLE_SCHEMA.matches(tuf.formats.make_signable(root)))
signable = tuf.formats.make_signable(root)
self.assertEqual('root', tuf.formats.check_signable_object_format(signable))
self.assertEqual(signable, tuf.formats.make_signable(signable))
# Test conditions for miscellaneous arguments.
self.assertTrue(SIGNABLE_SCHEMA.matches(tuf.formats.make_signable('123')))
self.assertTrue(SIGNABLE_SCHEMA.matches(tuf.formats.make_signable(123)))
def test_make_fileinfo(self):
# Test conditions for valid arguments.
length = 1024
hashes = {'sha256': 'A4582BCF323BCEF', 'sha512': 'A4582BCF323BFEF'}
version = 8
custom = {'type': 'paintjob'}
FILEINFO_SCHEMA = tuf.formats.FILEINFO_SCHEMA
make_fileinfo = tuf.formats.make_fileinfo
self.assertTrue(FILEINFO_SCHEMA.matches(make_fileinfo(length, hashes, version, custom)))
self.assertTrue(FILEINFO_SCHEMA.matches(make_fileinfo(length, hashes)))
# Test conditions for invalid arguments.
bad_length = 'bad'
bad_hashes = 'bad'
bad_custom = 'bad'
self.assertRaises(securesystemslib.exceptions.FormatError, make_fileinfo, bad_length, hashes, custom)
self.assertRaises(securesystemslib.exceptions.FormatError, make_fileinfo, length, bad_hashes, custom)
self.assertRaises(securesystemslib.exceptions.FormatError, make_fileinfo, length, hashes, bad_custom)
self.assertRaises(securesystemslib.exceptions.FormatError, make_fileinfo, bad_length, hashes)
self.assertRaises(securesystemslib.exceptions.FormatError, make_fileinfo, length, bad_hashes)
def test_make_versioninfo(self):
# Test conditions for valid arguments.
version_number = 8
versioninfo = {'version': version_number}
VERSIONINFO_SCHEMA = tuf.formats.VERSIONINFO_SCHEMA
make_versioninfo = tuf.formats.make_versioninfo
self.assertTrue(VERSIONINFO_SCHEMA.matches(make_versioninfo(version_number)))
# Test conditions for invalid arguments.
bad_version_number = '8'
self.assertRaises(securesystemslib.exceptions.FormatError, make_versioninfo, bad_version_number)
def test_expected_meta_rolename(self):
# Test conditions for valid arguments.
expected_rolename = tuf.formats.expected_meta_rolename
self.assertEqual('root', expected_rolename('Root'))
self.assertEqual('targets', expected_rolename('Targets'))
self.assertEqual('snapshot', expected_rolename('Snapshot'))
self.assertEqual('timestamp', expected_rolename('Timestamp'))
self.assertEqual('mirrors', expected_rolename('Mirrors'))
self.assertEqual('targets role', expected_rolename('Targets Role'))
self.assertEqual('root', expected_rolename('Root'))
# Test conditions for invalid arguments.
self.assertRaises(securesystemslib.exceptions.FormatError, expected_rolename, 123)
self.assertRaises(securesystemslib.exceptions.FormatError, expected_rolename, tuf.formats.ROOT_SCHEMA)
self.assertRaises(securesystemslib.exceptions.FormatError, expected_rolename, True)
def test_check_signable_object_format(self):
# Test condition for a valid argument.
root = {'_type': 'root',
'spec_version': '1.0.0',
'version': 8,
'consistent_snapshot': False,
'expires': '1985-10-21T13:20:00Z',
'keys': {'123abc': {'keytype': 'rsa',
'scheme': 'rsassa-pss-sha256',
'keyval': {'public': 'pubkey',
'private': 'privkey'}}},
'roles': {'root': {'keyids': ['123abc'],
'threshold': 1,
'paths': ['path1/', 'path2']}}}
root = tuf.formats.make_signable(root)
self.assertEqual('root', tuf.formats.check_signable_object_format(root))
# Test conditions for invalid arguments.
check_signable = tuf.formats.check_signable_object_format
self.assertRaises(securesystemslib.exceptions.FormatError, check_signable, 'root')
self.assertRaises(securesystemslib.exceptions.FormatError, check_signable, 123)
self.assertRaises(securesystemslib.exceptions.FormatError, check_signable, tuf.formats.ROOT_SCHEMA)
self.assertRaises(securesystemslib.exceptions.FormatError, check_signable, True)
saved_type = root['signed']['_type']
del root['signed']['_type']
self.assertRaises(securesystemslib.exceptions.FormatError, check_signable, root)
root['signed']['_type'] = saved_type
root['signed']['_type'] = 'Root'
self.assertRaises(securesystemslib.exceptions.FormatError, check_signable, root)
root['signed']['_type'] = 'root'
del root['signed']['expires']
self.assertRaises(securesystemslib.exceptions.FormatError, check_signable, root)
def test_encode_canonical(self):
# Test conditions for valid arguments.
encode = securesystemslib.formats.encode_canonical
result = []
output = result.append
bad_output = 123
self.assertEqual('""', encode(""))
self.assertEqual('[1,2,3]', encode([1, 2, 3]))
self.assertEqual('[1,2,3]', encode([1,2,3]))
self.assertEqual('[]', encode([]))
self.assertEqual('{"A":[99]}', encode({"A": [99]}))
self.assertEqual('{"x":3,"y":2}', encode({"x": 3, "y": 2}))
self.assertEqual('{"x":3,"y":null}', encode({"x": 3, "y": None}))
# Condition where 'encode()' sends the result to the callable
# 'output'.
self.assertEqual(None, encode([1, 2, 3], output))
self.assertEqual('[1,2,3]', ''.join(result))
# Test conditions for invalid arguments.
self.assertRaises(securesystemslib.exceptions.FormatError, encode, tuf.formats.ROOT_SCHEMA)
self.assertRaises(securesystemslib.exceptions.FormatError, encode, 8.0)
self.assertRaises(securesystemslib.exceptions.FormatError, encode, {"x": 8.0})
self.assertRaises(securesystemslib.exceptions.FormatError, encode, 8.0, output)
self.assertRaises(securesystemslib.exceptions.FormatError, encode, {"x": securesystemslib.exceptions.FormatError})
# Run unit test.
if __name__ == '__main__':
unittest.main()