mirror of
https://github.com/ansible-collections/community.crypto.git
synced 2026-03-26 21:33:25 +00:00
Reformat everything with black.
I had to undo the u string prefix removals to not drop Python 2 compatibility. That's why black isn't enabled in antsibull-nox.toml yet.
This commit is contained in:
@@ -25,60 +25,60 @@ from ..test_time import TIMEZONES, cartesian_product
|
||||
|
||||
|
||||
def load_fixture(name):
|
||||
with open(os.path.join(os.path.dirname(__file__), 'fixtures', name)) as f:
|
||||
with open(os.path.join(os.path.dirname(__file__), "fixtures", name)) as f:
|
||||
return f.read()
|
||||
|
||||
|
||||
TEST_PEM_DERS = [
|
||||
(
|
||||
load_fixture('privatekey_1.pem'),
|
||||
base64.b64decode('MHcCAQEEIDWajU0PyhYKeulfy/luNtkAve7DkwQ01bXJ97zbxB66oAo'
|
||||
'GCCqGSM49AwEHoUQDQgAEAJz0yAAXAwEmOhTRkjXxwgedbWO6gobYM3'
|
||||
'lWszrS68G8QSzhXR6AmQ3IzZDimnTTXO7XhVylDT8SLzE44/Epmw==')
|
||||
load_fixture("privatekey_1.pem"),
|
||||
base64.b64decode(
|
||||
"MHcCAQEEIDWajU0PyhYKeulfy/luNtkAve7DkwQ01bXJ97zbxB66oAo"
|
||||
"GCCqGSM49AwEHoUQDQgAEAJz0yAAXAwEmOhTRkjXxwgedbWO6gobYM3"
|
||||
"lWszrS68G8QSzhXR6AmQ3IzZDimnTTXO7XhVylDT8SLzE44/Epmw=="
|
||||
),
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
TEST_KEYS = [
|
||||
(
|
||||
load_fixture('privatekey_1.pem'),
|
||||
load_fixture("privatekey_1.pem"),
|
||||
{
|
||||
'alg': 'ES256',
|
||||
'hash': 'sha256',
|
||||
'jwk': {
|
||||
'crv': 'P-256',
|
||||
'kty': 'EC',
|
||||
'x': 'AJz0yAAXAwEmOhTRkjXxwgedbWO6gobYM3lWszrS68E',
|
||||
'y': 'vEEs4V0egJkNyM2Q4pp001zu14VcpQ0_Ei8xOOPxKZs',
|
||||
"alg": "ES256",
|
||||
"hash": "sha256",
|
||||
"jwk": {
|
||||
"crv": "P-256",
|
||||
"kty": "EC",
|
||||
"x": "AJz0yAAXAwEmOhTRkjXxwgedbWO6gobYM3lWszrS68E",
|
||||
"y": "vEEs4V0egJkNyM2Q4pp001zu14VcpQ0_Ei8xOOPxKZs",
|
||||
},
|
||||
'point_size': 32,
|
||||
'type': 'ec',
|
||||
"point_size": 32,
|
||||
"type": "ec",
|
||||
},
|
||||
load_fixture('privatekey_1.txt'),
|
||||
load_fixture("privatekey_1.txt"),
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
TEST_CSRS = [
|
||||
(
|
||||
load_fixture('csr_1.pem'),
|
||||
set([
|
||||
('dns', 'ansible.com'),
|
||||
('dns', 'example.com'),
|
||||
('dns', 'example.org')
|
||||
]),
|
||||
load_fixture('csr_1.txt'),
|
||||
load_fixture("csr_1.pem"),
|
||||
set([("dns", "ansible.com"), ("dns", "example.com"), ("dns", "example.org")]),
|
||||
load_fixture("csr_1.txt"),
|
||||
),
|
||||
(
|
||||
load_fixture('csr_2.pem'),
|
||||
set([
|
||||
('dns', 'ansible.com'),
|
||||
('ip', '127.0.0.1'),
|
||||
('ip', '::1'),
|
||||
('ip', '2001:d88:ac10:fe01::'),
|
||||
('ip', '2001:1234:5678:abcd:9876:5432:10fe:dcba')
|
||||
]),
|
||||
load_fixture('csr_2.txt'),
|
||||
load_fixture("csr_2.pem"),
|
||||
set(
|
||||
[
|
||||
("dns", "ansible.com"),
|
||||
("ip", "127.0.0.1"),
|
||||
("ip", "::1"),
|
||||
("ip", "2001:d88:ac10:fe01::"),
|
||||
("ip", "2001:1234:5678:abcd:9876:5432:10fe:dcba"),
|
||||
]
|
||||
),
|
||||
load_fixture("csr_2.txt"),
|
||||
),
|
||||
]
|
||||
|
||||
@@ -92,18 +92,21 @@ TEST_CERT_OPENSSL_OUTPUT_2 = load_fixture("cert_2.txt") # OpenSSL 3.3.0 output
|
||||
TEST_CERT_OPENSSL_OUTPUT_2B = load_fixture("cert_2-b.txt") # OpenSSL 1.1.1f output
|
||||
|
||||
|
||||
TEST_CERT_DAYS = cartesian_product(TIMEZONES, [
|
||||
(datetime.datetime(2018, 11, 15, 1, 2, 3), 11),
|
||||
(datetime.datetime(2018, 11, 25, 15, 20, 0), 1),
|
||||
(datetime.datetime(2018, 11, 25, 15, 30, 0), 0),
|
||||
])
|
||||
TEST_CERT_DAYS = cartesian_product(
|
||||
TIMEZONES,
|
||||
[
|
||||
(datetime.datetime(2018, 11, 15, 1, 2, 3), 11),
|
||||
(datetime.datetime(2018, 11, 25, 15, 20, 0), 1),
|
||||
(datetime.datetime(2018, 11, 25, 15, 30, 0), 0),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
TEST_CERT_INFO = CertificateInformation(
|
||||
not_valid_after=datetime.datetime(2018, 11, 26, 15, 28, 24),
|
||||
not_valid_before=datetime.datetime(2018, 11, 25, 15, 28, 23),
|
||||
serial_number=1,
|
||||
subject_key_identifier=b'\x98\xD2\xFD\x3C\xCC\xCD\x69\x45\xFB\xE2\x8C\x30\x2C\x54\x62\x18\x34\xB7\x07\x73',
|
||||
subject_key_identifier=b"\x98\xd2\xfd\x3c\xcc\xcd\x69\x45\xfb\xe2\x8c\x30\x2c\x54\x62\x18\x34\xb7\x07\x73",
|
||||
authority_key_identifier=None,
|
||||
)
|
||||
|
||||
@@ -112,8 +115,8 @@ TEST_CERT_INFO_2 = CertificateInformation(
|
||||
not_valid_before=datetime.datetime(2024, 5, 4, 20, 42, 21),
|
||||
not_valid_after=datetime.datetime(2029, 5, 4, 20, 42, 20),
|
||||
serial_number=4218235397573492796,
|
||||
subject_key_identifier=b'\x17\xE5\x83\x22\x14\xEF\x74\xD3\xBE\x7E\x30\x76\x56\x1F\x51\x74\x65\x1F\xE9\xF0',
|
||||
authority_key_identifier=b'\x13\xC3\x4C\x3E\x59\x45\xDD\xE3\x63\x51\xA3\x46\x80\xC4\x08\xC7\x14\xC0\x64\x4E',
|
||||
subject_key_identifier=b"\x17\xe5\x83\x22\x14\xef\x74\xd3\xbe\x7e\x30\x76\x56\x1f\x51\x74\x65\x1f\xe9\xf0",
|
||||
authority_key_identifier=b"\x13\xc3\x4c\x3e\x59\x45\xdd\xe3\x63\x51\xa3\x46\x80\xc4\x08\xc7\x14\xc0\x64\x4e",
|
||||
)
|
||||
|
||||
|
||||
@@ -124,77 +127,112 @@ TEST_CERT_INFO = [
|
||||
]
|
||||
|
||||
|
||||
TEST_PARSE_ACME_TIMESTAMP = cartesian_product(TIMEZONES, [
|
||||
(
|
||||
'2024-01-01T00:11:22Z',
|
||||
dict(year=2024, month=1, day=1, hour=0, minute=11, second=22),
|
||||
),
|
||||
(
|
||||
'2024-01-01T00:11:22.123Z',
|
||||
dict(year=2024, month=1, day=1, hour=0, minute=11, second=22, microsecond=123000),
|
||||
),
|
||||
(
|
||||
'2024-04-17T06:54:13.333333334Z',
|
||||
dict(year=2024, month=4, day=17, hour=6, minute=54, second=13, microsecond=333333),
|
||||
),
|
||||
])
|
||||
TEST_PARSE_ACME_TIMESTAMP = cartesian_product(
|
||||
TIMEZONES,
|
||||
[
|
||||
(
|
||||
"2024-01-01T00:11:22Z",
|
||||
dict(year=2024, month=1, day=1, hour=0, minute=11, second=22),
|
||||
),
|
||||
(
|
||||
"2024-01-01T00:11:22.123Z",
|
||||
dict(
|
||||
year=2024,
|
||||
month=1,
|
||||
day=1,
|
||||
hour=0,
|
||||
minute=11,
|
||||
second=22,
|
||||
microsecond=123000,
|
||||
),
|
||||
),
|
||||
(
|
||||
"2024-04-17T06:54:13.333333334Z",
|
||||
dict(
|
||||
year=2024,
|
||||
month=4,
|
||||
day=17,
|
||||
hour=6,
|
||||
minute=54,
|
||||
second=13,
|
||||
microsecond=333333,
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
if sys.version_info >= (3, 5):
|
||||
TEST_PARSE_ACME_TIMESTAMP.extend(cartesian_product(TIMEZONES, [
|
||||
(
|
||||
'2024-01-01T00:11:22+0100',
|
||||
dict(year=2023, month=12, day=31, hour=23, minute=11, second=22),
|
||||
),
|
||||
(
|
||||
'2024-01-01T00:11:22.123+0100',
|
||||
dict(year=2023, month=12, day=31, hour=23, minute=11, second=22, microsecond=123000),
|
||||
),
|
||||
]))
|
||||
TEST_PARSE_ACME_TIMESTAMP.extend(
|
||||
cartesian_product(
|
||||
TIMEZONES,
|
||||
[
|
||||
(
|
||||
"2024-01-01T00:11:22+0100",
|
||||
dict(year=2023, month=12, day=31, hour=23, minute=11, second=22),
|
||||
),
|
||||
(
|
||||
"2024-01-01T00:11:22.123+0100",
|
||||
dict(
|
||||
year=2023,
|
||||
month=12,
|
||||
day=31,
|
||||
hour=23,
|
||||
minute=11,
|
||||
second=22,
|
||||
microsecond=123000,
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
TEST_INTERPOLATE_TIMESTAMP = cartesian_product(TIMEZONES, [
|
||||
(
|
||||
dict(year=2024, month=1, day=1, hour=0, minute=0, second=0),
|
||||
dict(year=2024, month=1, day=1, hour=1, minute=0, second=0),
|
||||
0.0,
|
||||
dict(year=2024, month=1, day=1, hour=0, minute=0, second=0),
|
||||
),
|
||||
(
|
||||
dict(year=2024, month=1, day=1, hour=0, minute=0, second=0),
|
||||
dict(year=2024, month=1, day=1, hour=1, minute=0, second=0),
|
||||
0.5,
|
||||
dict(year=2024, month=1, day=1, hour=0, minute=30, second=0),
|
||||
),
|
||||
(
|
||||
dict(year=2024, month=1, day=1, hour=0, minute=0, second=0),
|
||||
dict(year=2024, month=1, day=1, hour=1, minute=0, second=0),
|
||||
1.0,
|
||||
dict(year=2024, month=1, day=1, hour=1, minute=0, second=0),
|
||||
),
|
||||
])
|
||||
TEST_INTERPOLATE_TIMESTAMP = cartesian_product(
|
||||
TIMEZONES,
|
||||
[
|
||||
(
|
||||
dict(year=2024, month=1, day=1, hour=0, minute=0, second=0),
|
||||
dict(year=2024, month=1, day=1, hour=1, minute=0, second=0),
|
||||
0.0,
|
||||
dict(year=2024, month=1, day=1, hour=0, minute=0, second=0),
|
||||
),
|
||||
(
|
||||
dict(year=2024, month=1, day=1, hour=0, minute=0, second=0),
|
||||
dict(year=2024, month=1, day=1, hour=1, minute=0, second=0),
|
||||
0.5,
|
||||
dict(year=2024, month=1, day=1, hour=0, minute=30, second=0),
|
||||
),
|
||||
(
|
||||
dict(year=2024, month=1, day=1, hour=0, minute=0, second=0),
|
||||
dict(year=2024, month=1, day=1, hour=1, minute=0, second=0),
|
||||
1.0,
|
||||
dict(year=2024, month=1, day=1, hour=1, minute=0, second=0),
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
class FakeBackend(CryptoBackend):
|
||||
def parse_key(self, key_file=None, key_content=None, passphrase=None):
|
||||
raise BackendException('Not implemented in fake backend')
|
||||
raise BackendException("Not implemented in fake backend")
|
||||
|
||||
def sign(self, payload64, protected64, key_data):
|
||||
raise BackendException('Not implemented in fake backend')
|
||||
raise BackendException("Not implemented in fake backend")
|
||||
|
||||
def create_mac_key(self, alg, key):
|
||||
raise BackendException('Not implemented in fake backend')
|
||||
raise BackendException("Not implemented in fake backend")
|
||||
|
||||
def get_ordered_csr_identifiers(self, csr_filename=None, csr_content=None):
|
||||
raise BackendException('Not implemented in fake backend')
|
||||
raise BackendException("Not implemented in fake backend")
|
||||
|
||||
def get_csr_identifiers(self, csr_filename=None, csr_content=None):
|
||||
raise BackendException('Not implemented in fake backend')
|
||||
raise BackendException("Not implemented in fake backend")
|
||||
|
||||
def get_cert_days(self, cert_filename=None, cert_content=None, now=None):
|
||||
raise BackendException('Not implemented in fake backend')
|
||||
raise BackendException("Not implemented in fake backend")
|
||||
|
||||
def create_chain_matcher(self, criterium):
|
||||
raise BackendException('Not implemented in fake backend')
|
||||
raise BackendException("Not implemented in fake backend")
|
||||
|
||||
def get_cert_information(self, cert_filename=None, cert_content=None):
|
||||
raise BackendException('Not implemented in fake backend')
|
||||
raise BackendException("Not implemented in fake backend")
|
||||
|
||||
@@ -39,26 +39,26 @@ from .backend_data import (
|
||||
|
||||
|
||||
if not HAS_CURRENT_CRYPTOGRAPHY:
|
||||
pytest.skip('cryptography not found')
|
||||
pytest.skip("cryptography not found")
|
||||
|
||||
|
||||
@pytest.mark.parametrize("pem, result, dummy", TEST_KEYS)
|
||||
def test_eckeyparse_cryptography(pem, result, dummy, tmpdir):
|
||||
fn = tmpdir / 'test.pem'
|
||||
fn = tmpdir / "test.pem"
|
||||
fn.write(pem)
|
||||
module = MagicMock()
|
||||
backend = CryptographyBackend(module)
|
||||
key = backend.parse_key(key_file=str(fn))
|
||||
key.pop('key_obj')
|
||||
key.pop("key_obj")
|
||||
assert key == result
|
||||
key = backend.parse_key(key_content=pem)
|
||||
key.pop('key_obj')
|
||||
key.pop("key_obj")
|
||||
assert key == result
|
||||
|
||||
|
||||
@pytest.mark.parametrize("csr, result, openssl_output", TEST_CSRS)
|
||||
def test_csridentifiers_cryptography(csr, result, openssl_output, tmpdir):
|
||||
fn = tmpdir / 'test.csr'
|
||||
fn = tmpdir / "test.csr"
|
||||
fn.write(csr)
|
||||
module = MagicMock()
|
||||
backend = CryptographyBackend(module)
|
||||
@@ -71,7 +71,7 @@ def test_csridentifiers_cryptography(csr, result, openssl_output, tmpdir):
|
||||
@pytest.mark.parametrize("timezone, now, expected_days", TEST_CERT_DAYS)
|
||||
def test_certdays_cryptography(timezone, now, expected_days, tmpdir):
|
||||
with freeze_time("2024-02-03 04:05:06", tz_offset=timezone):
|
||||
fn = tmpdir / 'test-cert.pem'
|
||||
fn = tmpdir / "test-cert.pem"
|
||||
fn.write(TEST_CERT)
|
||||
module = MagicMock()
|
||||
backend = CryptographyBackend(module)
|
||||
@@ -81,9 +81,11 @@ def test_certdays_cryptography(timezone, now, expected_days, tmpdir):
|
||||
assert days == expected_days
|
||||
|
||||
|
||||
@pytest.mark.parametrize("cert_content, expected_cert_info, openssl_output", TEST_CERT_INFO)
|
||||
@pytest.mark.parametrize(
|
||||
"cert_content, expected_cert_info, openssl_output", TEST_CERT_INFO
|
||||
)
|
||||
def test_get_cert_information(cert_content, expected_cert_info, openssl_output, tmpdir):
|
||||
fn = tmpdir / 'test-cert.pem'
|
||||
fn = tmpdir / "test-cert.pem"
|
||||
fn.write(cert_content)
|
||||
module = MagicMock()
|
||||
backend = CryptographyBackend(module)
|
||||
@@ -103,7 +105,9 @@ def test_get_cert_information(cert_content, expected_cert_info, openssl_output,
|
||||
# @pytest.mark.parametrize("timezone", TIMEZONES)
|
||||
# Due to a bug in freezegun (https://github.com/spulec/freezegun/issues/348, https://github.com/spulec/freezegun/issues/553)
|
||||
# this only works with timezone = UTC if CRYPTOGRAPHY_TIMEZONE is truish
|
||||
@pytest.mark.parametrize("timezone", [datetime.timedelta(hours=0)] if CRYPTOGRAPHY_TIMEZONE else TIMEZONES)
|
||||
@pytest.mark.parametrize(
|
||||
"timezone", [datetime.timedelta(hours=0)] if CRYPTOGRAPHY_TIMEZONE else TIMEZONES
|
||||
)
|
||||
def test_now(timezone):
|
||||
with freeze_time("2024-02-03 04:05:06", tz_offset=timezone):
|
||||
module = MagicMock()
|
||||
@@ -127,7 +131,9 @@ def test_parse_acme_timestamp(timezone, input, expected):
|
||||
assert ts_expected == timestamp
|
||||
|
||||
|
||||
@pytest.mark.parametrize("timezone, start, end, percentage, expected", TEST_INTERPOLATE_TIMESTAMP)
|
||||
@pytest.mark.parametrize(
|
||||
"timezone, start, end, percentage, expected", TEST_INTERPOLATE_TIMESTAMP
|
||||
)
|
||||
def test_interpolate_timestamp(timezone, start, end, percentage, expected):
|
||||
with freeze_time("2024-02-03 04:05:06", tz_offset=timezone):
|
||||
module = MagicMock()
|
||||
|
||||
@@ -51,23 +51,23 @@ TEST_IPS = [
|
||||
|
||||
@pytest.mark.parametrize("pem, result, openssl_output", TEST_KEYS)
|
||||
def test_eckeyparse_openssl(pem, result, openssl_output, tmpdir):
|
||||
fn = tmpdir / 'test.key'
|
||||
fn = tmpdir / "test.key"
|
||||
fn.write(pem)
|
||||
module = MagicMock()
|
||||
module.run_command = MagicMock(return_value=(0, openssl_output, 0))
|
||||
backend = OpenSSLCLIBackend(module, openssl_binary='openssl')
|
||||
backend = OpenSSLCLIBackend(module, openssl_binary="openssl")
|
||||
key = backend.parse_key(key_file=str(fn))
|
||||
key.pop('key_file')
|
||||
key.pop("key_file")
|
||||
assert key == result
|
||||
|
||||
|
||||
@pytest.mark.parametrize("csr, result, openssl_output", TEST_CSRS)
|
||||
def test_csridentifiers_openssl(csr, result, openssl_output, tmpdir):
|
||||
fn = tmpdir / 'test.csr'
|
||||
fn = tmpdir / "test.csr"
|
||||
fn.write(csr)
|
||||
module = MagicMock()
|
||||
module.run_command = MagicMock(return_value=(0, openssl_output, 0))
|
||||
backend = OpenSSLCLIBackend(module, openssl_binary='openssl')
|
||||
backend = OpenSSLCLIBackend(module, openssl_binary="openssl")
|
||||
identifiers = backend.get_csr_identifiers(str(fn))
|
||||
assert identifiers == result
|
||||
|
||||
@@ -75,31 +75,33 @@ def test_csridentifiers_openssl(csr, result, openssl_output, tmpdir):
|
||||
@pytest.mark.parametrize("ip, result", TEST_IPS)
|
||||
def test_normalize_ip(ip, result):
|
||||
module = MagicMock()
|
||||
backend = OpenSSLCLIBackend(module, openssl_binary='openssl')
|
||||
backend = OpenSSLCLIBackend(module, openssl_binary="openssl")
|
||||
assert backend._normalize_ip(ip) == result
|
||||
|
||||
|
||||
@pytest.mark.parametrize("timezone, now, expected_days", TEST_CERT_DAYS)
|
||||
def test_certdays_cryptography(timezone, now, expected_days, tmpdir):
|
||||
with freeze_time("2024-02-03 04:05:06", tz_offset=timezone):
|
||||
fn = tmpdir / 'test-cert.pem'
|
||||
fn = tmpdir / "test-cert.pem"
|
||||
fn.write(TEST_CERT)
|
||||
module = MagicMock()
|
||||
module.run_command = MagicMock(return_value=(0, TEST_CERT_OPENSSL_OUTPUT, 0))
|
||||
backend = OpenSSLCLIBackend(module, openssl_binary='openssl')
|
||||
backend = OpenSSLCLIBackend(module, openssl_binary="openssl")
|
||||
days = backend.get_cert_days(cert_filename=str(fn), now=now)
|
||||
assert days == expected_days
|
||||
days = backend.get_cert_days(cert_content=TEST_CERT, now=now)
|
||||
assert days == expected_days
|
||||
|
||||
|
||||
@pytest.mark.parametrize("cert_content, expected_cert_info, openssl_output", TEST_CERT_INFO)
|
||||
@pytest.mark.parametrize(
|
||||
"cert_content, expected_cert_info, openssl_output", TEST_CERT_INFO
|
||||
)
|
||||
def test_get_cert_information(cert_content, expected_cert_info, openssl_output, tmpdir):
|
||||
fn = tmpdir / 'test-cert.pem'
|
||||
fn = tmpdir / "test-cert.pem"
|
||||
fn.write(cert_content)
|
||||
module = MagicMock()
|
||||
module.run_command = MagicMock(return_value=(0, openssl_output, 0))
|
||||
backend = OpenSSLCLIBackend(module, openssl_binary='openssl')
|
||||
backend = OpenSSLCLIBackend(module, openssl_binary="openssl")
|
||||
|
||||
expected_cert_info = expected_cert_info._replace(
|
||||
not_valid_after=ensure_utc_timezone(expected_cert_info.not_valid_after),
|
||||
@@ -119,7 +121,7 @@ def test_get_cert_information(cert_content, expected_cert_info, openssl_output,
|
||||
def test_now(timezone):
|
||||
with freeze_time("2024-02-03 04:05:06", tz_offset=timezone):
|
||||
module = MagicMock()
|
||||
backend = OpenSSLCLIBackend(module, openssl_binary='openssl')
|
||||
backend = OpenSSLCLIBackend(module, openssl_binary="openssl")
|
||||
now = backend.get_now()
|
||||
assert now.tzinfo is not None
|
||||
assert now == datetime.datetime(2024, 2, 3, 4, 5, 6, tzinfo=UTC)
|
||||
@@ -129,17 +131,19 @@ def test_now(timezone):
|
||||
def test_parse_acme_timestamp(timezone, input, expected):
|
||||
with freeze_time("2024-02-03 04:05:06", tz_offset=timezone):
|
||||
module = MagicMock()
|
||||
backend = OpenSSLCLIBackend(module, openssl_binary='openssl')
|
||||
backend = OpenSSLCLIBackend(module, openssl_binary="openssl")
|
||||
ts_expected = backend.get_utc_datetime(**expected)
|
||||
timestamp = backend.parse_acme_timestamp(input)
|
||||
assert ts_expected == timestamp
|
||||
|
||||
|
||||
@pytest.mark.parametrize("timezone, start, end, percentage, expected", TEST_INTERPOLATE_TIMESTAMP)
|
||||
@pytest.mark.parametrize(
|
||||
"timezone, start, end, percentage, expected", TEST_INTERPOLATE_TIMESTAMP
|
||||
)
|
||||
def test_interpolate_timestamp(timezone, start, end, percentage, expected):
|
||||
with freeze_time("2024-02-03 04:05:06", tz_offset=timezone):
|
||||
module = MagicMock()
|
||||
backend = OpenSSLCLIBackend(module, openssl_binary='openssl')
|
||||
backend = OpenSSLCLIBackend(module, openssl_binary="openssl")
|
||||
ts_start = backend.get_utc_datetime(**start)
|
||||
ts_end = backend.get_utc_datetime(**end)
|
||||
ts_expected = backend.get_utc_datetime(**expected)
|
||||
|
||||
@@ -25,16 +25,16 @@ from ansible_collections.community.internal_test_tools.tests.unit.compat.mock im
|
||||
|
||||
|
||||
def test_combine_identifier():
|
||||
assert combine_identifier('', '') == ':'
|
||||
assert combine_identifier('a', 'b') == 'a:b'
|
||||
assert combine_identifier("", "") == ":"
|
||||
assert combine_identifier("a", "b") == "a:b"
|
||||
|
||||
|
||||
def test_split_identifier():
|
||||
assert split_identifier(':') == ['', '']
|
||||
assert split_identifier('a:b') == ['a', 'b']
|
||||
assert split_identifier('a:b:c') == ['a', 'b:c']
|
||||
assert split_identifier(":") == ["", ""]
|
||||
assert split_identifier("a:b") == ["a", "b"]
|
||||
assert split_identifier("a:b:c") == ["a", "b:c"]
|
||||
with pytest.raises(ModuleFailException) as exc:
|
||||
split_identifier('a')
|
||||
split_identifier("a")
|
||||
assert exc.value.msg == 'Identifier "a" is not of the form <type>:<identifier>'
|
||||
|
||||
|
||||
@@ -42,43 +42,43 @@ def test_challenge_from_to_json():
|
||||
client = MagicMock()
|
||||
|
||||
data = {
|
||||
'url': 'xxx',
|
||||
'type': 'type',
|
||||
'status': 'valid',
|
||||
"url": "xxx",
|
||||
"type": "type",
|
||||
"status": "valid",
|
||||
}
|
||||
client.version = 2
|
||||
challenge = Challenge.from_json(client, data)
|
||||
assert challenge.data == data
|
||||
assert challenge.type == 'type'
|
||||
assert challenge.url == 'xxx'
|
||||
assert challenge.status == 'valid'
|
||||
assert challenge.type == "type"
|
||||
assert challenge.url == "xxx"
|
||||
assert challenge.status == "valid"
|
||||
assert challenge.token is None
|
||||
assert challenge.to_json() == data
|
||||
|
||||
data = {
|
||||
'type': 'type',
|
||||
'status': 'valid',
|
||||
'token': 'foo',
|
||||
"type": "type",
|
||||
"status": "valid",
|
||||
"token": "foo",
|
||||
}
|
||||
challenge = Challenge.from_json(None, data, url='xxx')
|
||||
challenge = Challenge.from_json(None, data, url="xxx")
|
||||
assert challenge.data == data
|
||||
assert challenge.type == 'type'
|
||||
assert challenge.url == 'xxx'
|
||||
assert challenge.status == 'valid'
|
||||
assert challenge.token == 'foo'
|
||||
assert challenge.type == "type"
|
||||
assert challenge.url == "xxx"
|
||||
assert challenge.status == "valid"
|
||||
assert challenge.token == "foo"
|
||||
assert challenge.to_json() == data
|
||||
|
||||
data = {
|
||||
'uri': 'xxx',
|
||||
'type': 'type',
|
||||
'status': 'valid',
|
||||
"uri": "xxx",
|
||||
"type": "type",
|
||||
"status": "valid",
|
||||
}
|
||||
client.version = 1
|
||||
challenge = Challenge.from_json(client, data)
|
||||
assert challenge.data == data
|
||||
assert challenge.type == 'type'
|
||||
assert challenge.url == 'xxx'
|
||||
assert challenge.status == 'valid'
|
||||
assert challenge.type == "type"
|
||||
assert challenge.url == "xxx"
|
||||
assert challenge.status == "valid"
|
||||
assert challenge.token is None
|
||||
assert challenge.to_json() == data
|
||||
|
||||
@@ -88,93 +88,93 @@ def test_authorization_from_to_json():
|
||||
client.version = 2
|
||||
|
||||
data = {
|
||||
'challenges': [],
|
||||
'status': 'valid',
|
||||
'identifier': {
|
||||
'type': 'dns',
|
||||
'value': 'example.com',
|
||||
"challenges": [],
|
||||
"status": "valid",
|
||||
"identifier": {
|
||||
"type": "dns",
|
||||
"value": "example.com",
|
||||
},
|
||||
}
|
||||
authz = Authorization.from_json(client, data, 'xxx')
|
||||
assert authz.url == 'xxx'
|
||||
assert authz.status == 'valid'
|
||||
assert authz.identifier == 'example.com'
|
||||
assert authz.identifier_type == 'dns'
|
||||
authz = Authorization.from_json(client, data, "xxx")
|
||||
assert authz.url == "xxx"
|
||||
assert authz.status == "valid"
|
||||
assert authz.identifier == "example.com"
|
||||
assert authz.identifier_type == "dns"
|
||||
assert authz.challenges == []
|
||||
assert authz.to_json() == {
|
||||
'uri': 'xxx',
|
||||
'challenges': [],
|
||||
'status': 'valid',
|
||||
'identifier': {
|
||||
'type': 'dns',
|
||||
'value': 'example.com',
|
||||
"uri": "xxx",
|
||||
"challenges": [],
|
||||
"status": "valid",
|
||||
"identifier": {
|
||||
"type": "dns",
|
||||
"value": "example.com",
|
||||
},
|
||||
}
|
||||
|
||||
data = {
|
||||
'challenges': [
|
||||
"challenges": [
|
||||
{
|
||||
'url': 'xxxyyy',
|
||||
'type': 'type',
|
||||
'status': 'valid',
|
||||
"url": "xxxyyy",
|
||||
"type": "type",
|
||||
"status": "valid",
|
||||
}
|
||||
],
|
||||
'status': 'valid',
|
||||
'identifier': {
|
||||
'type': 'dns',
|
||||
'value': 'example.com',
|
||||
"status": "valid",
|
||||
"identifier": {
|
||||
"type": "dns",
|
||||
"value": "example.com",
|
||||
},
|
||||
'wildcard': True,
|
||||
"wildcard": True,
|
||||
}
|
||||
authz = Authorization.from_json(client, data, 'xxx')
|
||||
assert authz.url == 'xxx'
|
||||
assert authz.status == 'valid'
|
||||
assert authz.identifier == '*.example.com'
|
||||
assert authz.identifier_type == 'dns'
|
||||
authz = Authorization.from_json(client, data, "xxx")
|
||||
assert authz.url == "xxx"
|
||||
assert authz.status == "valid"
|
||||
assert authz.identifier == "*.example.com"
|
||||
assert authz.identifier_type == "dns"
|
||||
assert len(authz.challenges) == 1
|
||||
assert authz.challenges[0].data == {
|
||||
'url': 'xxxyyy',
|
||||
'type': 'type',
|
||||
'status': 'valid',
|
||||
"url": "xxxyyy",
|
||||
"type": "type",
|
||||
"status": "valid",
|
||||
}
|
||||
assert authz.to_json() == {
|
||||
'uri': 'xxx',
|
||||
'challenges': [
|
||||
"uri": "xxx",
|
||||
"challenges": [
|
||||
{
|
||||
'url': 'xxxyyy',
|
||||
'type': 'type',
|
||||
'status': 'valid',
|
||||
"url": "xxxyyy",
|
||||
"type": "type",
|
||||
"status": "valid",
|
||||
}
|
||||
],
|
||||
'status': 'valid',
|
||||
'identifier': {
|
||||
'type': 'dns',
|
||||
'value': 'example.com',
|
||||
"status": "valid",
|
||||
"identifier": {
|
||||
"type": "dns",
|
||||
"value": "example.com",
|
||||
},
|
||||
'wildcard': True,
|
||||
"wildcard": True,
|
||||
}
|
||||
|
||||
client.version = 1
|
||||
|
||||
data = {
|
||||
'challenges': [],
|
||||
'identifier': {
|
||||
'type': 'dns',
|
||||
'value': 'example.com',
|
||||
"challenges": [],
|
||||
"identifier": {
|
||||
"type": "dns",
|
||||
"value": "example.com",
|
||||
},
|
||||
}
|
||||
authz = Authorization.from_json(client, data, 'xxx')
|
||||
assert authz.url == 'xxx'
|
||||
assert authz.status == 'pending'
|
||||
assert authz.identifier == 'example.com'
|
||||
assert authz.identifier_type == 'dns'
|
||||
authz = Authorization.from_json(client, data, "xxx")
|
||||
assert authz.url == "xxx"
|
||||
assert authz.status == "pending"
|
||||
assert authz.identifier == "example.com"
|
||||
assert authz.identifier_type == "dns"
|
||||
assert authz.challenges == []
|
||||
assert authz.to_json() == {
|
||||
'uri': 'xxx',
|
||||
'challenges': [],
|
||||
'identifier': {
|
||||
'type': 'dns',
|
||||
'value': 'example.com',
|
||||
"uri": "xxx",
|
||||
"challenges": [],
|
||||
"identifier": {
|
||||
"type": "dns",
|
||||
"value": "example.com",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -184,60 +184,60 @@ def test_authorization_create_error():
|
||||
client.version = 2
|
||||
client.directory.directory = {}
|
||||
with pytest.raises(ACMEProtocolException) as exc:
|
||||
Authorization.create(client, 'dns', 'example.com')
|
||||
Authorization.create(client, "dns", "example.com")
|
||||
|
||||
assert exc.value.msg == 'ACME endpoint does not support pre-authorization.'
|
||||
assert exc.value.msg == "ACME endpoint does not support pre-authorization."
|
||||
|
||||
|
||||
def test_wait_for_validation_error():
|
||||
client = MagicMock()
|
||||
client.version = 2
|
||||
data = {
|
||||
'challenges': [
|
||||
"challenges": [
|
||||
{
|
||||
'url': 'xxxyyy1',
|
||||
'type': 'dns-01',
|
||||
'status': 'invalid',
|
||||
'error': {
|
||||
'type': 'dns-failed',
|
||||
'subproblems': [
|
||||
"url": "xxxyyy1",
|
||||
"type": "dns-01",
|
||||
"status": "invalid",
|
||||
"error": {
|
||||
"type": "dns-failed",
|
||||
"subproblems": [
|
||||
{
|
||||
'type': 'subproblem',
|
||||
'detail': 'example.com DNS-01 validation failed',
|
||||
"type": "subproblem",
|
||||
"detail": "example.com DNS-01 validation failed",
|
||||
},
|
||||
]
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
'url': 'xxxyyy2',
|
||||
'type': 'http-01',
|
||||
'status': 'invalid',
|
||||
'error': {
|
||||
'type': 'http-failed',
|
||||
'subproblems': [
|
||||
"url": "xxxyyy2",
|
||||
"type": "http-01",
|
||||
"status": "invalid",
|
||||
"error": {
|
||||
"type": "http-failed",
|
||||
"subproblems": [
|
||||
{
|
||||
'type': 'subproblem',
|
||||
'detail': 'example.com HTTP-01 validation failed',
|
||||
"type": "subproblem",
|
||||
"detail": "example.com HTTP-01 validation failed",
|
||||
},
|
||||
]
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
'url': 'xxxyyy3',
|
||||
'type': 'something-else',
|
||||
'status': 'valid',
|
||||
"url": "xxxyyy3",
|
||||
"type": "something-else",
|
||||
"status": "valid",
|
||||
},
|
||||
],
|
||||
'status': 'invalid',
|
||||
'identifier': {
|
||||
'type': 'dns',
|
||||
'value': 'example.com',
|
||||
"status": "invalid",
|
||||
"identifier": {
|
||||
"type": "dns",
|
||||
"value": "example.com",
|
||||
},
|
||||
}
|
||||
client.get_request = MagicMock(return_value=(data, {}))
|
||||
authz = Authorization.from_json(client, data, 'xxx')
|
||||
authz = Authorization.from_json(client, data, "xxx")
|
||||
with pytest.raises(ACMEProtocolException) as exc:
|
||||
authz.wait_for_validation(client, 'dns')
|
||||
authz.wait_for_validation(client, "dns")
|
||||
|
||||
assert exc.value.msg == (
|
||||
'Failed to validate challenge for dns:example.com: Status is "invalid". Challenge dns-01: Error dns-failed Subproblems:\n'
|
||||
@@ -245,8 +245,8 @@ def test_wait_for_validation_error():
|
||||
'(http-01.0) Error subproblem: "example.com HTTP-01 validation failed".'
|
||||
)
|
||||
data = data.copy()
|
||||
data['uri'] = 'xxx'
|
||||
data["uri"] = "xxx"
|
||||
assert exc.value.module_fail_args == {
|
||||
'identifier': 'dns:example.com',
|
||||
'authorization': data,
|
||||
"identifier": "dns:example.com",
|
||||
"authorization": data,
|
||||
}
|
||||
|
||||
@@ -21,97 +21,78 @@ from ansible_collections.community.internal_test_tools.tests.unit.compat.mock im
|
||||
TEST_FORMAT_ERROR_PROBLEM = [
|
||||
(
|
||||
{
|
||||
'type': 'foo',
|
||||
"type": "foo",
|
||||
},
|
||||
'',
|
||||
'Error foo'
|
||||
"",
|
||||
"Error foo",
|
||||
),
|
||||
({"type": "foo", "title": "bar"}, "", 'Error "bar" (foo)'),
|
||||
({"type": "foo", "detail": "bar baz"}, "", 'Error foo: "bar baz"'),
|
||||
({"type": "foo", "subproblems": []}, "", "Error foo Subproblems:"),
|
||||
(
|
||||
{
|
||||
'type': 'foo',
|
||||
'title': 'bar'
|
||||
},
|
||||
'',
|
||||
'Error "bar" (foo)'
|
||||
),
|
||||
(
|
||||
{
|
||||
'type': 'foo',
|
||||
'detail': 'bar baz'
|
||||
},
|
||||
'',
|
||||
'Error foo: "bar baz"'
|
||||
),
|
||||
(
|
||||
{
|
||||
'type': 'foo',
|
||||
'subproblems': []
|
||||
},
|
||||
'',
|
||||
'Error foo Subproblems:'
|
||||
),
|
||||
(
|
||||
{
|
||||
'type': 'foo',
|
||||
'subproblems': [
|
||||
"type": "foo",
|
||||
"subproblems": [
|
||||
{
|
||||
'type': 'bar',
|
||||
"type": "bar",
|
||||
},
|
||||
]
|
||||
],
|
||||
},
|
||||
'',
|
||||
'Error foo Subproblems:\n(0) Error bar'
|
||||
"",
|
||||
"Error foo Subproblems:\n(0) Error bar",
|
||||
),
|
||||
(
|
||||
{
|
||||
'type': 'foo',
|
||||
'subproblems': [
|
||||
"type": "foo",
|
||||
"subproblems": [
|
||||
{
|
||||
'type': 'bar',
|
||||
'subproblems': [
|
||||
"type": "bar",
|
||||
"subproblems": [
|
||||
{
|
||||
'type': 'baz',
|
||||
"type": "baz",
|
||||
},
|
||||
]
|
||||
],
|
||||
},
|
||||
]
|
||||
],
|
||||
},
|
||||
'',
|
||||
'Error foo Subproblems:\n(0) Error bar Subproblems:\n(0.0) Error baz'
|
||||
"",
|
||||
"Error foo Subproblems:\n(0) Error bar Subproblems:\n(0.0) Error baz",
|
||||
),
|
||||
(
|
||||
{
|
||||
'type': 'foo',
|
||||
'title': 'Foo Error',
|
||||
'detail': 'Foo went wrong',
|
||||
'subproblems': [
|
||||
"type": "foo",
|
||||
"title": "Foo Error",
|
||||
"detail": "Foo went wrong",
|
||||
"subproblems": [
|
||||
{
|
||||
'type': 'bar',
|
||||
'detail': 'Bar went wrong',
|
||||
'subproblems': [
|
||||
"type": "bar",
|
||||
"detail": "Bar went wrong",
|
||||
"subproblems": [
|
||||
{
|
||||
'type': 'baz',
|
||||
'title': 'Baz Error',
|
||||
"type": "baz",
|
||||
"title": "Baz Error",
|
||||
},
|
||||
]
|
||||
],
|
||||
},
|
||||
{
|
||||
'type': 'bar2',
|
||||
'title': 'Bar 2 Error',
|
||||
'detail': 'Bar really went wrong'
|
||||
"type": "bar2",
|
||||
"title": "Bar 2 Error",
|
||||
"detail": "Bar really went wrong",
|
||||
},
|
||||
]
|
||||
],
|
||||
},
|
||||
'X.',
|
||||
"X.",
|
||||
'Error "Foo Error" (foo): "Foo went wrong" Subproblems:\n'
|
||||
'(X.0) Error bar: "Bar went wrong" Subproblems:\n'
|
||||
'(X.0.0) Error "Baz Error" (baz)\n'
|
||||
'(X.1) Error "Bar 2 Error" (bar2): "Bar really went wrong"'
|
||||
'(X.1) Error "Bar 2 Error" (bar2): "Bar really went wrong"',
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("problem, subproblem_prefix, result", TEST_FORMAT_ERROR_PROBLEM)
|
||||
@pytest.mark.parametrize(
|
||||
"problem, subproblem_prefix, result", TEST_FORMAT_ERROR_PROBLEM
|
||||
)
|
||||
def test_format_error_problem(problem, subproblem_prefix, result):
|
||||
res = format_error_problem(problem, subproblem_prefix)
|
||||
assert res == result
|
||||
@@ -119,14 +100,14 @@ def test_format_error_problem(problem, subproblem_prefix, result):
|
||||
|
||||
def create_regular_response(response_text):
|
||||
response = MagicMock()
|
||||
response.read = MagicMock(return_value=response_text.encode('utf-8'))
|
||||
response.read = MagicMock(return_value=response_text.encode("utf-8"))
|
||||
response.closed = False
|
||||
return response
|
||||
|
||||
|
||||
def create_error_response():
|
||||
response = MagicMock()
|
||||
response.read = MagicMock(side_effect=AttributeError('read'))
|
||||
response.read = MagicMock(side_effect=AttributeError("read"))
|
||||
response.closed = True
|
||||
return response
|
||||
|
||||
@@ -142,220 +123,219 @@ TEST_ACME_PROTOCOL_EXCEPTION = [
|
||||
(
|
||||
{},
|
||||
None,
|
||||
'ACME request failed.',
|
||||
{
|
||||
},
|
||||
"ACME request failed.",
|
||||
{},
|
||||
),
|
||||
(
|
||||
{
|
||||
'msg': 'Foo',
|
||||
'extras': {
|
||||
'foo': 'bar',
|
||||
"msg": "Foo",
|
||||
"extras": {
|
||||
"foo": "bar",
|
||||
},
|
||||
},
|
||||
None,
|
||||
'Foo.',
|
||||
"Foo.",
|
||||
{
|
||||
'foo': 'bar',
|
||||
"foo": "bar",
|
||||
},
|
||||
),
|
||||
(
|
||||
{
|
||||
'info': {
|
||||
'url': 'https://ca.example.com/foo',
|
||||
'status': 201,
|
||||
"info": {
|
||||
"url": "https://ca.example.com/foo",
|
||||
"status": 201,
|
||||
},
|
||||
},
|
||||
None,
|
||||
'ACME request failed for https://ca.example.com/foo with HTTP status 201 Created.',
|
||||
"ACME request failed for https://ca.example.com/foo with HTTP status 201 Created.",
|
||||
{
|
||||
'http_url': 'https://ca.example.com/foo',
|
||||
'http_status': 201,
|
||||
"http_url": "https://ca.example.com/foo",
|
||||
"http_status": 201,
|
||||
},
|
||||
),
|
||||
(
|
||||
{
|
||||
'info': {
|
||||
'url': 'https://ca.example.com/foo',
|
||||
'status': 201,
|
||||
"info": {
|
||||
"url": "https://ca.example.com/foo",
|
||||
"status": 201,
|
||||
},
|
||||
'response': create_regular_response('xxx'),
|
||||
},
|
||||
None,
|
||||
'ACME request failed for https://ca.example.com/foo with HTTP status 201 Created. The raw error result: xxx',
|
||||
{
|
||||
'http_url': 'https://ca.example.com/foo',
|
||||
'http_status': 201,
|
||||
},
|
||||
),
|
||||
(
|
||||
{
|
||||
'info': {
|
||||
'url': 'https://ca.example.com/foo',
|
||||
'status': 201,
|
||||
},
|
||||
'response': create_regular_response('xxx'),
|
||||
},
|
||||
create_decode_error('yyy'),
|
||||
'ACME request failed for https://ca.example.com/foo with HTTP status 201 Created. The raw error result: xxx',
|
||||
{
|
||||
'http_url': 'https://ca.example.com/foo',
|
||||
'http_status': 201,
|
||||
},
|
||||
),
|
||||
(
|
||||
{
|
||||
'info': {
|
||||
'url': 'https://ca.example.com/foo',
|
||||
'status': 201,
|
||||
},
|
||||
'response': create_regular_response('xxx'),
|
||||
},
|
||||
lambda content: dict(foo='bar'),
|
||||
"ACME request failed for https://ca.example.com/foo with HTTP status 201 Created. The JSON error result: {'foo': 'bar'}",
|
||||
{
|
||||
'http_url': 'https://ca.example.com/foo',
|
||||
'http_status': 201,
|
||||
},
|
||||
),
|
||||
(
|
||||
{
|
||||
'info': {
|
||||
'url': 'https://ca.example.com/foo',
|
||||
'status': 201,
|
||||
},
|
||||
'response': create_error_response(),
|
||||
},
|
||||
None,
|
||||
'ACME request failed for https://ca.example.com/foo with HTTP status 201 Created.',
|
||||
{
|
||||
'http_url': 'https://ca.example.com/foo',
|
||||
'http_status': 201,
|
||||
},
|
||||
),
|
||||
(
|
||||
{
|
||||
'info': {
|
||||
'url': 'https://ca.example.com/foo',
|
||||
'status': 201,
|
||||
'body': 'xxx',
|
||||
},
|
||||
'response': create_error_response(),
|
||||
},
|
||||
lambda content: dict(foo='bar'),
|
||||
"ACME request failed for https://ca.example.com/foo with HTTP status 201 Created. The JSON error result: {'foo': 'bar'}",
|
||||
{
|
||||
'http_url': 'https://ca.example.com/foo',
|
||||
'http_status': 201,
|
||||
},
|
||||
),
|
||||
(
|
||||
{
|
||||
'info': {
|
||||
'url': 'https://ca.example.com/foo',
|
||||
'status': 201,
|
||||
},
|
||||
'content': 'xxx',
|
||||
"response": create_regular_response("xxx"),
|
||||
},
|
||||
None,
|
||||
"ACME request failed for https://ca.example.com/foo with HTTP status 201 Created. The raw error result: xxx",
|
||||
{
|
||||
'http_url': 'https://ca.example.com/foo',
|
||||
'http_status': 201,
|
||||
"http_url": "https://ca.example.com/foo",
|
||||
"http_status": 201,
|
||||
},
|
||||
),
|
||||
(
|
||||
{
|
||||
'info': {
|
||||
'url': 'https://ca.example.com/foo',
|
||||
'status': 400,
|
||||
"info": {
|
||||
"url": "https://ca.example.com/foo",
|
||||
"status": 201,
|
||||
},
|
||||
'content_json': {
|
||||
'foo': 'bar',
|
||||
"response": create_regular_response("xxx"),
|
||||
},
|
||||
create_decode_error("yyy"),
|
||||
"ACME request failed for https://ca.example.com/foo with HTTP status 201 Created. The raw error result: xxx",
|
||||
{
|
||||
"http_url": "https://ca.example.com/foo",
|
||||
"http_status": 201,
|
||||
},
|
||||
),
|
||||
(
|
||||
{
|
||||
"info": {
|
||||
"url": "https://ca.example.com/foo",
|
||||
"status": 201,
|
||||
},
|
||||
"response": create_regular_response("xxx"),
|
||||
},
|
||||
lambda content: dict(foo="bar"),
|
||||
"ACME request failed for https://ca.example.com/foo with HTTP status 201 Created. The JSON error result: {'foo': 'bar'}",
|
||||
{
|
||||
"http_url": "https://ca.example.com/foo",
|
||||
"http_status": 201,
|
||||
},
|
||||
),
|
||||
(
|
||||
{
|
||||
"info": {
|
||||
"url": "https://ca.example.com/foo",
|
||||
"status": 201,
|
||||
},
|
||||
"response": create_error_response(),
|
||||
},
|
||||
None,
|
||||
"ACME request failed for https://ca.example.com/foo with HTTP status 201 Created.",
|
||||
{
|
||||
"http_url": "https://ca.example.com/foo",
|
||||
"http_status": 201,
|
||||
},
|
||||
),
|
||||
(
|
||||
{
|
||||
"info": {
|
||||
"url": "https://ca.example.com/foo",
|
||||
"status": 201,
|
||||
"body": "xxx",
|
||||
},
|
||||
"response": create_error_response(),
|
||||
},
|
||||
lambda content: dict(foo="bar"),
|
||||
"ACME request failed for https://ca.example.com/foo with HTTP status 201 Created. The JSON error result: {'foo': 'bar'}",
|
||||
{
|
||||
"http_url": "https://ca.example.com/foo",
|
||||
"http_status": 201,
|
||||
},
|
||||
),
|
||||
(
|
||||
{
|
||||
"info": {
|
||||
"url": "https://ca.example.com/foo",
|
||||
"status": 201,
|
||||
},
|
||||
"content": "xxx",
|
||||
},
|
||||
None,
|
||||
"ACME request failed for https://ca.example.com/foo with HTTP status 201 Created. The raw error result: xxx",
|
||||
{
|
||||
"http_url": "https://ca.example.com/foo",
|
||||
"http_status": 201,
|
||||
},
|
||||
),
|
||||
(
|
||||
{
|
||||
"info": {
|
||||
"url": "https://ca.example.com/foo",
|
||||
"status": 400,
|
||||
},
|
||||
"content_json": {
|
||||
"foo": "bar",
|
||||
},
|
||||
"extras": {
|
||||
"bar": "baz",
|
||||
},
|
||||
'extras': {
|
||||
'bar': 'baz',
|
||||
}
|
||||
},
|
||||
None,
|
||||
"ACME request failed for https://ca.example.com/foo with HTTP status 400 Bad Request. The JSON error result: {'foo': 'bar'}",
|
||||
{
|
||||
'http_url': 'https://ca.example.com/foo',
|
||||
'http_status': 400,
|
||||
'bar': 'baz',
|
||||
"http_url": "https://ca.example.com/foo",
|
||||
"http_status": 400,
|
||||
"bar": "baz",
|
||||
},
|
||||
),
|
||||
(
|
||||
{
|
||||
'info': {
|
||||
'url': 'https://ca.example.com/foo',
|
||||
'status': 201,
|
||||
"info": {
|
||||
"url": "https://ca.example.com/foo",
|
||||
"status": 201,
|
||||
},
|
||||
'content_json': {
|
||||
'type': 'foo',
|
||||
"content_json": {
|
||||
"type": "foo",
|
||||
},
|
||||
},
|
||||
None,
|
||||
"ACME request failed for https://ca.example.com/foo with HTTP status 201 Created. The JSON error result: {'type': 'foo'}",
|
||||
{
|
||||
'http_url': 'https://ca.example.com/foo',
|
||||
'http_status': 201,
|
||||
"http_url": "https://ca.example.com/foo",
|
||||
"http_status": 201,
|
||||
},
|
||||
),
|
||||
(
|
||||
{
|
||||
'info': {
|
||||
'url': 'https://ca.example.com/foo',
|
||||
'status': 400,
|
||||
"info": {
|
||||
"url": "https://ca.example.com/foo",
|
||||
"status": 400,
|
||||
},
|
||||
'content_json': {
|
||||
'type': 'foo',
|
||||
"content_json": {
|
||||
"type": "foo",
|
||||
},
|
||||
},
|
||||
None,
|
||||
"ACME request failed for https://ca.example.com/foo with status 400 Bad Request. Error foo.",
|
||||
{
|
||||
'http_url': 'https://ca.example.com/foo',
|
||||
'http_status': 400,
|
||||
'problem': {
|
||||
'type': 'foo',
|
||||
"http_url": "https://ca.example.com/foo",
|
||||
"http_status": 400,
|
||||
"problem": {
|
||||
"type": "foo",
|
||||
},
|
||||
'subproblems': [],
|
||||
"subproblems": [],
|
||||
},
|
||||
),
|
||||
(
|
||||
{
|
||||
'info': {
|
||||
'url': 'https://ca.example.com/foo',
|
||||
'status': 400,
|
||||
"info": {
|
||||
"url": "https://ca.example.com/foo",
|
||||
"status": 400,
|
||||
},
|
||||
'content_json': {
|
||||
'type': 'foo',
|
||||
'title': 'Foo Error',
|
||||
'subproblems': [
|
||||
"content_json": {
|
||||
"type": "foo",
|
||||
"title": "Foo Error",
|
||||
"subproblems": [
|
||||
{
|
||||
'type': 'bar',
|
||||
'detail': 'This is a bar error',
|
||||
'details': 'Details.',
|
||||
"type": "bar",
|
||||
"detail": "This is a bar error",
|
||||
"details": "Details.",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
None,
|
||||
"ACME request failed for https://ca.example.com/foo with status 400 Bad Request. Error \"Foo Error\" (foo). Subproblems:\n"
|
||||
"(0) Error bar: \"This is a bar error\".",
|
||||
'ACME request failed for https://ca.example.com/foo with status 400 Bad Request. Error "Foo Error" (foo). Subproblems:\n'
|
||||
'(0) Error bar: "This is a bar error".',
|
||||
{
|
||||
'http_url': 'https://ca.example.com/foo',
|
||||
'http_status': 400,
|
||||
'problem': {
|
||||
'type': 'foo',
|
||||
'title': 'Foo Error',
|
||||
"http_url": "https://ca.example.com/foo",
|
||||
"http_status": 400,
|
||||
"problem": {
|
||||
"type": "foo",
|
||||
"title": "Foo Error",
|
||||
},
|
||||
'subproblems': [
|
||||
"subproblems": [
|
||||
{
|
||||
'type': 'bar',
|
||||
'detail': 'This is a bar error',
|
||||
'details': 'Details.',
|
||||
"type": "bar",
|
||||
"detail": "This is a bar error",
|
||||
"details": "Details.",
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -22,14 +22,14 @@ TEST_TEXT = r"""1234
|
||||
|
||||
|
||||
def test_read_file(tmpdir):
|
||||
fn = tmpdir / 'test.txt'
|
||||
fn = tmpdir / "test.txt"
|
||||
fn.write(TEST_TEXT)
|
||||
assert read_file(str(fn), 't') == TEST_TEXT
|
||||
assert read_file(str(fn), 'b') == TEST_TEXT.encode('utf-8')
|
||||
assert read_file(str(fn), "t") == TEST_TEXT
|
||||
assert read_file(str(fn), "b") == TEST_TEXT.encode("utf-8")
|
||||
|
||||
|
||||
def test_write_file(tmpdir):
|
||||
fn = tmpdir / 'test.txt'
|
||||
fn = tmpdir / "test.txt"
|
||||
module = MagicMock()
|
||||
write_file(module, str(fn), TEST_TEXT.encode('utf-8'))
|
||||
write_file(module, str(fn), TEST_TEXT.encode("utf-8"))
|
||||
assert fn.read() == TEST_TEXT
|
||||
|
||||
@@ -22,15 +22,15 @@ def test_order_from_json():
|
||||
client = MagicMock()
|
||||
|
||||
data = {
|
||||
'status': 'valid',
|
||||
'identifiers': [],
|
||||
'authorizations': [],
|
||||
"status": "valid",
|
||||
"identifiers": [],
|
||||
"authorizations": [],
|
||||
}
|
||||
client.version = 2
|
||||
order = Order.from_json(client, data, 'xxx')
|
||||
order = Order.from_json(client, data, "xxx")
|
||||
assert order.data == data
|
||||
assert order.url == 'xxx'
|
||||
assert order.status == 'valid'
|
||||
assert order.url == "xxx"
|
||||
assert order.status == "valid"
|
||||
assert order.identifiers == []
|
||||
assert order.finalize_uri is None
|
||||
assert order.certificate_uri is None
|
||||
@@ -43,15 +43,17 @@ def test_wait_for_finalization_error():
|
||||
client.version = 2
|
||||
|
||||
data = {
|
||||
'status': 'invalid',
|
||||
'identifiers': [],
|
||||
'authorizations': [],
|
||||
"status": "invalid",
|
||||
"identifiers": [],
|
||||
"authorizations": [],
|
||||
}
|
||||
order = Order.from_json(client, data, 'xxx')
|
||||
order = Order.from_json(client, data, "xxx")
|
||||
|
||||
client.get_request = MagicMock(return_value=(data, {}))
|
||||
with pytest.raises(ACMEProtocolException) as exc:
|
||||
order.wait_for_finalization(client)
|
||||
|
||||
assert exc.value.msg.startswith('Failed to wait for order to complete; got status "invalid". The JSON result: ')
|
||||
assert exc.value.msg.startswith(
|
||||
'Failed to wait for order to complete; got status "invalid". The JSON result: '
|
||||
)
|
||||
assert exc.value.module_fail_args == {}
|
||||
|
||||
@@ -39,38 +39,34 @@ TEST_LINKS_HEADER = [
|
||||
[],
|
||||
),
|
||||
(
|
||||
{
|
||||
'link': '<foo>; rel="bar"'
|
||||
},
|
||||
{"link": '<foo>; rel="bar"'},
|
||||
[
|
||||
('foo', 'bar'),
|
||||
("foo", "bar"),
|
||||
],
|
||||
),
|
||||
(
|
||||
{"link": '<foo>; rel="bar", <baz>; rel="bam"'},
|
||||
[
|
||||
("foo", "bar"),
|
||||
("baz", "bam"),
|
||||
],
|
||||
),
|
||||
(
|
||||
{
|
||||
'link': '<foo>; rel="bar", <baz>; rel="bam"'
|
||||
"link": '<https://one.example.com>; rel="preconnect", <https://two.example.com>; rel="preconnect", <https://three.example.com>; rel="preconnect"'
|
||||
},
|
||||
[
|
||||
('foo', 'bar'),
|
||||
('baz', 'bam'),
|
||||
],
|
||||
),
|
||||
(
|
||||
{
|
||||
'link': '<https://one.example.com>; rel="preconnect", <https://two.example.com>; rel="preconnect", <https://three.example.com>; rel="preconnect"'
|
||||
},
|
||||
[
|
||||
('https://one.example.com', 'preconnect'),
|
||||
('https://two.example.com', 'preconnect'),
|
||||
('https://three.example.com', 'preconnect'),
|
||||
("https://one.example.com", "preconnect"),
|
||||
("https://two.example.com", "preconnect"),
|
||||
("https://three.example.com", "preconnect"),
|
||||
],
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
TEST_RETRY_AFTER_HEADER = [
|
||||
('120', datetime.datetime(2024, 4, 29, 0, 2, 0)),
|
||||
('Wed, 21 Oct 2015 07:28:00 GMT', datetime.datetime(2015, 10, 21, 7, 28, 0)),
|
||||
("120", datetime.datetime(2024, 4, 29, 0, 2, 0)),
|
||||
("Wed, 21 Oct 2015 07:28:00 GMT", datetime.datetime(2015, 10, 21, 7, 28, 0)),
|
||||
]
|
||||
|
||||
|
||||
@@ -81,9 +77,9 @@ TEST_COMPUTE_CERT_ID = [
|
||||
not_valid_before=datetime.datetime(2018, 11, 25, 15, 28, 23),
|
||||
serial_number=1,
|
||||
subject_key_identifier=None,
|
||||
authority_key_identifier=b'\x00\xff',
|
||||
authority_key_identifier=b"\x00\xff",
|
||||
),
|
||||
'AP8.AQ',
|
||||
"AP8.AQ",
|
||||
),
|
||||
(
|
||||
# AKI, serial number, and expected result taken from
|
||||
@@ -93,21 +89,21 @@ TEST_COMPUTE_CERT_ID = [
|
||||
not_valid_before=datetime.datetime(2018, 11, 25, 15, 28, 23),
|
||||
serial_number=0x87654321,
|
||||
subject_key_identifier=None,
|
||||
authority_key_identifier=b'\x69\x88\x5B\x6B\x87\x46\x40\x41\xE1\xB3\x7B\x84\x7B\xA0\xAE\x2C\xDE\x01\xC8\xD4',
|
||||
authority_key_identifier=b"\x69\x88\x5b\x6b\x87\x46\x40\x41\xe1\xb3\x7b\x84\x7b\xa0\xae\x2c\xde\x01\xc8\xd4",
|
||||
),
|
||||
'aYhba4dGQEHhs3uEe6CuLN4ByNQ.AIdlQyE',
|
||||
"aYhba4dGQEHhs3uEe6CuLN4ByNQ.AIdlQyE",
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("value, result", NOPAD_B64)
|
||||
def test_nopad_b64(value, result):
|
||||
assert nopad_b64(value.encode('utf-8')) == result
|
||||
assert nopad_b64(value.encode("utf-8")) == result
|
||||
|
||||
|
||||
@pytest.mark.parametrize("pem, der", TEST_PEM_DERS)
|
||||
def test_pem_to_der(pem, der, tmpdir):
|
||||
fn = tmpdir / 'test.pem'
|
||||
fn = tmpdir / "test.pem"
|
||||
fn.write(pem)
|
||||
assert pem_to_der(str(fn)) == der
|
||||
|
||||
@@ -126,7 +122,9 @@ def test_process_links(value, expected_result):
|
||||
|
||||
@pytest.mark.parametrize("value, expected_result", TEST_RETRY_AFTER_HEADER)
|
||||
def test_parse_retry_after(value, expected_result):
|
||||
assert expected_result == parse_retry_after(value, now=datetime.datetime(2024, 4, 29, 0, 0, 0))
|
||||
assert expected_result == parse_retry_after(
|
||||
value, now=datetime.datetime(2024, 4, 29, 0, 0, 0)
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("cert_info, expected_result", TEST_COMPUTE_CERT_ID)
|
||||
|
||||
@@ -21,52 +21,89 @@ from ansible_collections.community.crypto.plugins.module_utils.crypto._asn1 impo
|
||||
|
||||
|
||||
TEST_CASES = [
|
||||
('UTF8:Hello World', b'\x0c\x0b\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64'),
|
||||
|
||||
('EXPLICIT:10,UTF8:Hello World', b'\xaa\x0d\x0c\x0b\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64'),
|
||||
('EXPLICIT:12U,UTF8:Hello World', b'\x0c\x0b\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64'),
|
||||
('EXPLICIT:10A,UTF8:Hello World', b'\x6a\x0d\x0c\x0b\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64'),
|
||||
('EXPLICIT:10P,UTF8:Hello World', b'\xea\x0d\x0c\x0b\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64'),
|
||||
('EXPLICIT:10C,UTF8:Hello World', b'\xaa\x0d\x0c\x0b\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64'),
|
||||
('EXPLICIT:1024P,UTF8:Hello World', b'\xff\x88\x00\x0d\x0c\x0b\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64'),
|
||||
|
||||
('IMPLICIT:10,UTF8:Hello World', b'\x8a\x0b\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64'),
|
||||
('IMPLICIT:12U,UTF8:Hello World', b'\x0c\x0b\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64'),
|
||||
('IMPLICIT:10A,UTF8:Hello World', b'\x4a\x0b\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64'),
|
||||
('IMPLICIT:10P,UTF8:Hello World', b'\xca\x0b\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64'),
|
||||
('IMPLICIT:10C,UTF8:Hello World', b'\x8a\x0b\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64'),
|
||||
('IMPLICIT:1024P,UTF8:Hello World', b'\xdf\x88\x00\x0b\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64'),
|
||||
|
||||
("UTF8:Hello World", b"\x0c\x0b\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64"),
|
||||
(
|
||||
"EXPLICIT:10,UTF8:Hello World",
|
||||
b"\xaa\x0d\x0c\x0b\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64",
|
||||
),
|
||||
(
|
||||
"EXPLICIT:12U,UTF8:Hello World",
|
||||
b"\x0c\x0b\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64",
|
||||
),
|
||||
(
|
||||
"EXPLICIT:10A,UTF8:Hello World",
|
||||
b"\x6a\x0d\x0c\x0b\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64",
|
||||
),
|
||||
(
|
||||
"EXPLICIT:10P,UTF8:Hello World",
|
||||
b"\xea\x0d\x0c\x0b\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64",
|
||||
),
|
||||
(
|
||||
"EXPLICIT:10C,UTF8:Hello World",
|
||||
b"\xaa\x0d\x0c\x0b\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64",
|
||||
),
|
||||
(
|
||||
"EXPLICIT:1024P,UTF8:Hello World",
|
||||
b"\xff\x88\x00\x0d\x0c\x0b\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64",
|
||||
),
|
||||
(
|
||||
"IMPLICIT:10,UTF8:Hello World",
|
||||
b"\x8a\x0b\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64",
|
||||
),
|
||||
(
|
||||
"IMPLICIT:12U,UTF8:Hello World",
|
||||
b"\x0c\x0b\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64",
|
||||
),
|
||||
(
|
||||
"IMPLICIT:10A,UTF8:Hello World",
|
||||
b"\x4a\x0b\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64",
|
||||
),
|
||||
(
|
||||
"IMPLICIT:10P,UTF8:Hello World",
|
||||
b"\xca\x0b\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64",
|
||||
),
|
||||
(
|
||||
"IMPLICIT:10C,UTF8:Hello World",
|
||||
b"\x8a\x0b\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64",
|
||||
),
|
||||
(
|
||||
"IMPLICIT:1024P,UTF8:Hello World",
|
||||
b"\xdf\x88\x00\x0b\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64",
|
||||
),
|
||||
# Tests large data lengths, special logic for the length octet encoding.
|
||||
('UTF8:' + ('A' * 600), b'\x0c\x82\x02\x58' + (b'\x41' * 600)),
|
||||
|
||||
("UTF8:" + ("A" * 600), b"\x0c\x82\x02\x58" + (b"\x41" * 600)),
|
||||
# This isn't valid with openssl asn1parse but has been validated against an ASN.1 parser. OpenSSL seems to read the
|
||||
# data u"café" encoded as UTF-8 bytes b"caf\xc3\xa9", decodes that internally with latin-1 (or similar variant) as
|
||||
# u"café" then encodes that to UTF-8 b"caf\xc3\x83\xc2\xa9" for the UTF8String. Ultimately openssl is wrong here
|
||||
# so we keep our assertion happening.
|
||||
(u'UTF8:café', b'\x0c\x05\x63\x61\x66\xc3\xa9'),
|
||||
(u"UTF8:café", b"\x0c\x05\x63\x61\x66\xc3\xa9"),
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.parametrize('value, expected', TEST_CASES)
|
||||
@pytest.mark.parametrize("value, expected", TEST_CASES)
|
||||
def test_serialize_asn1_string_as_der(value, expected):
|
||||
actual = serialize_asn1_string_as_der(value)
|
||||
print("%s | %s" % (value, base64.b16encode(actual).decode()))
|
||||
assert actual == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize('value', [
|
||||
'invalid',
|
||||
'EXPLICIT,UTF:value',
|
||||
])
|
||||
@pytest.mark.parametrize(
|
||||
"value",
|
||||
[
|
||||
"invalid",
|
||||
"EXPLICIT,UTF:value",
|
||||
],
|
||||
)
|
||||
def test_serialize_asn1_string_as_der_invalid_format(value):
|
||||
expected = "The ASN.1 serialized string must be in the format [modifier,]type[:value]"
|
||||
expected = (
|
||||
"The ASN.1 serialized string must be in the format [modifier,]type[:value]"
|
||||
)
|
||||
with pytest.raises(ValueError, match=re.escape(expected)):
|
||||
serialize_asn1_string_as_der(value)
|
||||
|
||||
|
||||
def test_serialize_asn1_string_as_der_invalid_type():
|
||||
expected = "The ASN.1 serialized string is not a known type \"OID\", only UTF8 types are supported"
|
||||
expected = 'The ASN.1 serialized string is not a known type "OID", only UTF8 types are supported'
|
||||
with pytest.raises(ValueError, match=re.escape(expected)):
|
||||
serialize_asn1_string_as_der("OID:1.2.3.4")
|
||||
|
||||
@@ -77,17 +114,23 @@ def test_pack_asn_invalid_class():
|
||||
|
||||
|
||||
@pytest.mark.skip() # This is to just to build the test case assertions and shouldn't run normally.
|
||||
@pytest.mark.parametrize('value, expected', TEST_CASES)
|
||||
@pytest.mark.parametrize("value, expected", TEST_CASES)
|
||||
def test_test_cases(value, expected, tmp_path):
|
||||
test_file = tmp_path / 'test.der'
|
||||
subprocess.run(['openssl', 'asn1parse', '-genstr', value, '-noout', '-out', test_file], check=True)
|
||||
test_file = tmp_path / "test.der"
|
||||
subprocess.run(
|
||||
["openssl", "asn1parse", "-genstr", value, "-noout", "-out", test_file],
|
||||
check=True,
|
||||
)
|
||||
|
||||
with open(test_file, mode='rb') as fd:
|
||||
with open(test_file, mode="rb") as fd:
|
||||
b_data = fd.read()
|
||||
|
||||
hex_str = base64.b16encode(b_data).decode().lower()
|
||||
print("%s | \\x%s" % (value, "\\x".join([hex_str[i:i + 2] for i in range(0, len(hex_str), 2)])))
|
||||
print(
|
||||
"%s | \\x%s"
|
||||
% (value, "\\x".join([hex_str[i : i + 2] for i in range(0, len(hex_str), 2)]))
|
||||
)
|
||||
|
||||
# This is a know edge case where openssl asn1parse does not work properly.
|
||||
if value != u'UTF8:café':
|
||||
if value != u"UTF8:café":
|
||||
assert b_data == expected
|
||||
|
||||
@@ -28,100 +28,147 @@ from ansible_collections.community.crypto.plugins.module_utils.version import (
|
||||
from cryptography.x509 import NameAttribute, oid
|
||||
|
||||
|
||||
@pytest.mark.parametrize('unicode, idna, cycled_unicode', [
|
||||
(u'..', u'..', None),
|
||||
(u'foo.com', u'foo.com', None),
|
||||
(u'.foo.com.', u'.foo.com.', None),
|
||||
(u'*.foo.com', u'*.foo.com', None),
|
||||
(u'straße', u'xn--strae-oqa', None),
|
||||
(u'ffóò.ḃâŗ.çøṁ', u'xn--ff-3jad.xn--2ca8uh37e.xn--7ca8a981n', u'ffóò.ḃâŗ.çøṁ'),
|
||||
(u'*.☺.', u'*.xn--74h.', None),
|
||||
])
|
||||
@pytest.mark.parametrize(
|
||||
"unicode, idna, cycled_unicode",
|
||||
[
|
||||
(u"..", u"..", None),
|
||||
(u"foo.com", u"foo.com", None),
|
||||
(u".foo.com.", u".foo.com.", None),
|
||||
(u"*.foo.com", u"*.foo.com", None),
|
||||
(u"straße", u"xn--strae-oqa", None),
|
||||
(u"ffóò.ḃâŗ.çøṁ", u"xn--ff-3jad.xn--2ca8uh37e.xn--7ca8a981n", u"ffóò.ḃâŗ.çøṁ"),
|
||||
(u"*.☺.", u"*.xn--74h.", None),
|
||||
],
|
||||
)
|
||||
def test_adjust_idn(unicode, idna, cycled_unicode):
|
||||
if cycled_unicode is None:
|
||||
cycled_unicode = unicode
|
||||
|
||||
result = _adjust_idn(unicode, 'ignore')
|
||||
result = _adjust_idn(unicode, "ignore")
|
||||
print(result, unicode)
|
||||
assert result == unicode
|
||||
|
||||
result = _adjust_idn(idna, 'ignore')
|
||||
result = _adjust_idn(idna, "ignore")
|
||||
print(result, idna)
|
||||
assert result == idna
|
||||
|
||||
result = _adjust_idn(unicode, 'unicode')
|
||||
result = _adjust_idn(unicode, "unicode")
|
||||
print(result, unicode)
|
||||
assert result == unicode
|
||||
|
||||
result = _adjust_idn(idna, 'unicode')
|
||||
result = _adjust_idn(idna, "unicode")
|
||||
print(result, cycled_unicode)
|
||||
assert result == cycled_unicode
|
||||
|
||||
result = _adjust_idn(unicode, 'idna')
|
||||
result = _adjust_idn(unicode, "idna")
|
||||
print(result, idna)
|
||||
assert result == idna
|
||||
|
||||
result = _adjust_idn(idna, 'idna')
|
||||
result = _adjust_idn(idna, "idna")
|
||||
print(result, idna)
|
||||
assert result == idna
|
||||
|
||||
|
||||
@pytest.mark.parametrize('value, idn_rewrite, message', [
|
||||
(u'bar', 'foo', re.escape(u'Invalid value for idn_rewrite: "foo"')),
|
||||
])
|
||||
@pytest.mark.parametrize(
|
||||
"value, idn_rewrite, message",
|
||||
[
|
||||
(u"bar", "foo", re.escape(u'Invalid value for idn_rewrite: "foo"')),
|
||||
],
|
||||
)
|
||||
def test_adjust_idn_fail_valueerror(value, idn_rewrite, message):
|
||||
with pytest.raises(ValueError, match=message):
|
||||
_adjust_idn(value, idn_rewrite)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('value, idn_rewrite, message', [
|
||||
(
|
||||
u'xn--a',
|
||||
'unicode',
|
||||
u'''^Error while transforming part u?"xn\\-\\-a" of IDNA DNS name u?"xn\\-\\-a" to Unicode\\.'''
|
||||
u''' IDNA2008 transformation resulted in "Codepoint U\\+0080 at position 1 of u?'\\\\x80' not allowed",'''
|
||||
u''' IDNA2003 transformation resulted in "(decoding with 'idna' codec failed'''
|
||||
u''' \\(UnicodeError: |'idna' codec can't decode byte 0x78 in position 0: )?Invalid character u?'\\\\x80'\\)?"\\.$'''
|
||||
),
|
||||
])
|
||||
@pytest.mark.parametrize(
|
||||
"value, idn_rewrite, message",
|
||||
[
|
||||
(
|
||||
u"xn--a",
|
||||
"unicode",
|
||||
u"""^Error while transforming part u?"xn\\-\\-a" of IDNA DNS name u?"xn\\-\\-a" to Unicode\\."""
|
||||
u""" IDNA2008 transformation resulted in "Codepoint U\\+0080 at position 1 of u?'\\\\x80' not allowed","""
|
||||
u""" IDNA2003 transformation resulted in "(decoding with 'idna' codec failed"""
|
||||
u""" \\(UnicodeError: |'idna' codec can't decode byte 0x78 in position 0: )?Invalid character u?'\\\\x80'\\)?"\\.$""",
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_adjust_idn_fail_user_error(value, idn_rewrite, message):
|
||||
with pytest.raises(OpenSSLObjectError, match=message):
|
||||
_adjust_idn(value, idn_rewrite)
|
||||
|
||||
|
||||
def test_cryptography_get_name_invalid_prefix():
|
||||
with pytest.raises(OpenSSLObjectError, match="^Cannot parse Subject Alternative Name"):
|
||||
cryptography_get_name('fake:value')
|
||||
with pytest.raises(
|
||||
OpenSSLObjectError, match="^Cannot parse Subject Alternative Name"
|
||||
):
|
||||
cryptography_get_name("fake:value")
|
||||
|
||||
|
||||
def test_cryptography_get_name_other_name_no_oid():
|
||||
with pytest.raises(OpenSSLObjectError, match="Cannot parse Subject Alternative Name otherName"):
|
||||
cryptography_get_name('otherName:value')
|
||||
with pytest.raises(
|
||||
OpenSSLObjectError, match="Cannot parse Subject Alternative Name otherName"
|
||||
):
|
||||
cryptography_get_name("otherName:value")
|
||||
|
||||
|
||||
def test_cryptography_get_name_other_name_utfstring():
|
||||
actual = cryptography_get_name('otherName:1.3.6.1.4.1.311.20.2.3;UTF8:Hello World')
|
||||
assert actual.type_id.dotted_string == '1.3.6.1.4.1.311.20.2.3'
|
||||
assert actual.value == b'\x0c\x0bHello World'
|
||||
actual = cryptography_get_name("otherName:1.3.6.1.4.1.311.20.2.3;UTF8:Hello World")
|
||||
assert actual.type_id.dotted_string == "1.3.6.1.4.1.311.20.2.3"
|
||||
assert actual.value == b"\x0c\x0bHello World"
|
||||
|
||||
|
||||
@pytest.mark.parametrize('name, options, expected', [
|
||||
(b'CN=x ', {}, (NameAttribute(oid.NameOID.COMMON_NAME, u'x '), b'')),
|
||||
(b'CN=\\ ', {}, (NameAttribute(oid.NameOID.COMMON_NAME, u' '), b'')),
|
||||
(b'CN=\\#', {}, (NameAttribute(oid.NameOID.COMMON_NAME, u'#'), b'')),
|
||||
(b'CN=#402032', {}, (NameAttribute(oid.NameOID.COMMON_NAME, u'@ 2'), b'')),
|
||||
(b'CN = x ', {}, (NameAttribute(oid.NameOID.COMMON_NAME, u'x '), b'')),
|
||||
(b'CN = x\\, ', {}, (NameAttribute(oid.NameOID.COMMON_NAME, u'x, '), b'')),
|
||||
(b'CN = x\\40 ', {}, (NameAttribute(oid.NameOID.COMMON_NAME, u'x@ '), b'')),
|
||||
(b'CN = \\ , / ', {}, (NameAttribute(oid.NameOID.COMMON_NAME, u' '), b', / ')),
|
||||
(b'CN = \\ , / ', {'sep': b'/'}, (NameAttribute(oid.NameOID.COMMON_NAME, u' , '), b'/ ')),
|
||||
(b'CN = \\ , / ', {'decode_remainder': False}, (NameAttribute(oid.NameOID.COMMON_NAME, u'\\ , / '), b'')),
|
||||
# Some examples from https://datatracker.ietf.org/doc/html/rfc4514#section-4:
|
||||
(b'CN=James \\"Jim\\" Smith\\, III', {}, (NameAttribute(oid.NameOID.COMMON_NAME, u'James "Jim" Smith, III'), b'')),
|
||||
(b'CN=Before\\0dAfter', {}, (NameAttribute(oid.NameOID.COMMON_NAME, u'Before\x0dAfter'), b'')),
|
||||
(b'1.3.6.1.4.1.1466.0=#04024869', {}, (NameAttribute(oid.ObjectIdentifier(u'1.3.6.1.4.1.1466.0'), u'\x04\x02Hi'), b'')),
|
||||
(b'CN=Lu\\C4\\8Di\\C4\\87', {}, (NameAttribute(oid.NameOID.COMMON_NAME, u'Lučić'), b'')),
|
||||
])
|
||||
@pytest.mark.parametrize(
|
||||
"name, options, expected",
|
||||
[
|
||||
(b"CN=x ", {}, (NameAttribute(oid.NameOID.COMMON_NAME, u"x "), b"")),
|
||||
(b"CN=\\ ", {}, (NameAttribute(oid.NameOID.COMMON_NAME, u" "), b"")),
|
||||
(b"CN=\\#", {}, (NameAttribute(oid.NameOID.COMMON_NAME, u"#"), b"")),
|
||||
(b"CN=#402032", {}, (NameAttribute(oid.NameOID.COMMON_NAME, u"@ 2"), b"")),
|
||||
(b"CN = x ", {}, (NameAttribute(oid.NameOID.COMMON_NAME, u"x "), b"")),
|
||||
(b"CN = x\\, ", {}, (NameAttribute(oid.NameOID.COMMON_NAME, u"x, "), b"")),
|
||||
(b"CN = x\\40 ", {}, (NameAttribute(oid.NameOID.COMMON_NAME, u"x@ "), b"")),
|
||||
(
|
||||
b"CN = \\ , / ",
|
||||
{},
|
||||
(NameAttribute(oid.NameOID.COMMON_NAME, u" "), b", / "),
|
||||
),
|
||||
(
|
||||
b"CN = \\ , / ",
|
||||
{"sep": b"/"},
|
||||
(NameAttribute(oid.NameOID.COMMON_NAME, u" , "), b"/ "),
|
||||
),
|
||||
(
|
||||
b"CN = \\ , / ",
|
||||
{"decode_remainder": False},
|
||||
(NameAttribute(oid.NameOID.COMMON_NAME, u"\\ , / "), b""),
|
||||
),
|
||||
# Some examples from https://datatracker.ietf.org/doc/html/rfc4514#section-4:
|
||||
(
|
||||
b'CN=James \\"Jim\\" Smith\\, III',
|
||||
{},
|
||||
(NameAttribute(oid.NameOID.COMMON_NAME, u'James "Jim" Smith, III'), b""),
|
||||
),
|
||||
(
|
||||
b"CN=Before\\0dAfter",
|
||||
{},
|
||||
(NameAttribute(oid.NameOID.COMMON_NAME, u"Before\x0dAfter"), b""),
|
||||
),
|
||||
(
|
||||
b"1.3.6.1.4.1.1466.0=#04024869",
|
||||
{},
|
||||
(
|
||||
NameAttribute(oid.ObjectIdentifier("1.3.6.1.4.1.1466.0"), u"\x04\x02Hi"),
|
||||
b"",
|
||||
),
|
||||
),
|
||||
(
|
||||
b"CN=Lu\\C4\\8Di\\C4\\87",
|
||||
{},
|
||||
(NameAttribute(oid.NameOID.COMMON_NAME, u"Lučić"), b""),
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_parse_dn_component(name, options, expected):
|
||||
result = _parse_dn_component(name, **options)
|
||||
print(result, expected)
|
||||
@@ -131,42 +178,77 @@ def test_parse_dn_component(name, options, expected):
|
||||
# Cryptography < 2.9 does not allow empty strings
|
||||
# (https://github.com/pyca/cryptography/commit/87b2749c52e688c809f1861e55d958c64147493c)
|
||||
# Cryptoraphy 43.0.0+ also doesn't allow this anymore
|
||||
if LooseVersion('2.9') <= LooseVersion(cryptography.__version__) < LooseVersion('43.0.0'):
|
||||
@pytest.mark.parametrize('name, options, expected', [
|
||||
(b'CN=', {}, (NameAttribute(oid.NameOID.COMMON_NAME, u''), b'')),
|
||||
(b'CN= ', {}, (NameAttribute(oid.NameOID.COMMON_NAME, u''), b'')),
|
||||
])
|
||||
if (
|
||||
LooseVersion("2.9")
|
||||
<= LooseVersion(cryptography.__version__)
|
||||
< LooseVersion("43.0.0")
|
||||
):
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"name, options, expected",
|
||||
[
|
||||
(b"CN=", {}, (NameAttribute(oid.NameOID.COMMON_NAME, u""), b"")),
|
||||
(b"CN= ", {}, (NameAttribute(oid.NameOID.COMMON_NAME, u""), b"")),
|
||||
],
|
||||
)
|
||||
def test_parse_dn_component_not_py26(name, options, expected):
|
||||
result = _parse_dn_component(name, **options)
|
||||
print(result, expected)
|
||||
assert result == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize('name, options, message', [
|
||||
(b'CN=\\0', {}, u'Hex escape sequence "\\0" incomplete at end of string'),
|
||||
(b'CN=\\0,', {}, u'Hex escape sequence "\\0," has invalid second letter'),
|
||||
(b'CN=#0,', {}, u'Invalid hex sequence entry "0,"'),
|
||||
])
|
||||
@pytest.mark.parametrize(
|
||||
"name, options, message",
|
||||
[
|
||||
(b"CN=\\0", {}, u'Hex escape sequence "\\0" incomplete at end of string'),
|
||||
(b"CN=\\0,", {}, u'Hex escape sequence "\\0," has invalid second letter'),
|
||||
(b"CN=#0,", {}, u'Invalid hex sequence entry "0,"'),
|
||||
],
|
||||
)
|
||||
def test_parse_dn_component_failure(name, options, message):
|
||||
with pytest.raises(OpenSSLObjectError, match=u'^%s$' % re.escape(message)):
|
||||
with pytest.raises(OpenSSLObjectError, match=u"^%s$" % re.escape(message)):
|
||||
_parse_dn_component(name, **options)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('name, expected', [
|
||||
(b'CN=foo', [NameAttribute(oid.NameOID.COMMON_NAME, u'foo')]),
|
||||
(b'CN=foo,CN=bar', [NameAttribute(oid.NameOID.COMMON_NAME, u'foo'), NameAttribute(oid.NameOID.COMMON_NAME, u'bar')]),
|
||||
(b'CN = foo , CN = bar', [NameAttribute(oid.NameOID.COMMON_NAME, u'foo '), NameAttribute(oid.NameOID.COMMON_NAME, u'bar')]),
|
||||
])
|
||||
@pytest.mark.parametrize(
|
||||
"name, expected",
|
||||
[
|
||||
(b"CN=foo", [NameAttribute(oid.NameOID.COMMON_NAME, u"foo")]),
|
||||
(
|
||||
b"CN=foo,CN=bar",
|
||||
[
|
||||
NameAttribute(oid.NameOID.COMMON_NAME, u"foo"),
|
||||
NameAttribute(oid.NameOID.COMMON_NAME, u"bar"),
|
||||
],
|
||||
),
|
||||
(
|
||||
b"CN = foo , CN = bar",
|
||||
[
|
||||
NameAttribute(oid.NameOID.COMMON_NAME, u"foo "),
|
||||
NameAttribute(oid.NameOID.COMMON_NAME, u"bar"),
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_parse_dn(name, expected):
|
||||
result = _parse_dn(name)
|
||||
print(result, expected)
|
||||
assert result == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize('name, message', [
|
||||
(b'CN=\\0', u'Error while parsing distinguished name "CN=\\0": Hex escape sequence "\\0" incomplete at end of string'),
|
||||
(b'CN=x,', u'Error while parsing distinguished name "CN=x,": unexpected end of string'),
|
||||
])
|
||||
@pytest.mark.parametrize(
|
||||
"name, message",
|
||||
[
|
||||
(
|
||||
b"CN=\\0",
|
||||
u'Error while parsing distinguished name "CN=\\0": Hex escape sequence "\\0" incomplete at end of string',
|
||||
),
|
||||
(
|
||||
b"CN=x,",
|
||||
u'Error while parsing distinguished name "CN=x,": unexpected end of string',
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_parse_dn_failure(name, message):
|
||||
with pytest.raises(OpenSSLObjectError, match=u'^%s$' % re.escape(message)):
|
||||
with pytest.raises(OpenSSLObjectError, match=u"^%s$" % re.escape(message)):
|
||||
_parse_dn(name)
|
||||
|
||||
@@ -20,98 +20,116 @@ from ansible_collections.community.crypto.plugins.module_utils.crypto.math impor
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('f, e, m, result', [
|
||||
(0, 0, 5, 1),
|
||||
(0, 1, 5, 0),
|
||||
(2, 1, 5, 2),
|
||||
(2, 2, 5, 4),
|
||||
(2, 3, 5, 3),
|
||||
(2, 10, 5, 4),
|
||||
])
|
||||
@pytest.mark.parametrize(
|
||||
"f, e, m, result",
|
||||
[
|
||||
(0, 0, 5, 1),
|
||||
(0, 1, 5, 0),
|
||||
(2, 1, 5, 2),
|
||||
(2, 2, 5, 4),
|
||||
(2, 3, 5, 3),
|
||||
(2, 10, 5, 4),
|
||||
],
|
||||
)
|
||||
def test_binary_exp_mod(f, e, m, result):
|
||||
value = binary_exp_mod(f, e, m)
|
||||
print(value)
|
||||
assert value == result
|
||||
|
||||
|
||||
@pytest.mark.parametrize('a, b, result', [
|
||||
(0, -123, -123),
|
||||
(0, 123, 123),
|
||||
(-123, 0, -123),
|
||||
(123, 0, 123),
|
||||
(-123, 1, 1),
|
||||
(123, 1, 1),
|
||||
(1, -123, -1),
|
||||
(1, 123, 1),
|
||||
(1024, 10, 2),
|
||||
])
|
||||
@pytest.mark.parametrize(
|
||||
"a, b, result",
|
||||
[
|
||||
(0, -123, -123),
|
||||
(0, 123, 123),
|
||||
(-123, 0, -123),
|
||||
(123, 0, 123),
|
||||
(-123, 1, 1),
|
||||
(123, 1, 1),
|
||||
(1, -123, -1),
|
||||
(1, 123, 1),
|
||||
(1024, 10, 2),
|
||||
],
|
||||
)
|
||||
def test_simple_gcd(a, b, result):
|
||||
value = simple_gcd(a, b)
|
||||
print(value)
|
||||
assert value == result
|
||||
|
||||
|
||||
@pytest.mark.parametrize('n, result', [
|
||||
(-2, True),
|
||||
(0, True),
|
||||
(1, True),
|
||||
(2, False),
|
||||
(3, False),
|
||||
(4, True),
|
||||
(5, False),
|
||||
(6, True),
|
||||
(7, False),
|
||||
(8, True),
|
||||
(9, True),
|
||||
(10, True),
|
||||
(211, False), # the smallest prime number >= 200
|
||||
])
|
||||
@pytest.mark.parametrize(
|
||||
"n, result",
|
||||
[
|
||||
(-2, True),
|
||||
(0, True),
|
||||
(1, True),
|
||||
(2, False),
|
||||
(3, False),
|
||||
(4, True),
|
||||
(5, False),
|
||||
(6, True),
|
||||
(7, False),
|
||||
(8, True),
|
||||
(9, True),
|
||||
(10, True),
|
||||
(211, False), # the smallest prime number >= 200
|
||||
],
|
||||
)
|
||||
def test_quick_is_not_prime(n, result):
|
||||
value = quick_is_not_prime(n)
|
||||
print(value)
|
||||
assert value == result
|
||||
|
||||
|
||||
@pytest.mark.parametrize('no, count, result', [
|
||||
(0, None, b''),
|
||||
(0, 1, b'\x00'),
|
||||
(0, 2, b'\x00\x00'),
|
||||
(1, None, b'\x01'),
|
||||
(1, 2, b'\x00\x01'),
|
||||
(255, None, b'\xff'),
|
||||
(256, None, b'\x01\x00'),
|
||||
])
|
||||
@pytest.mark.parametrize(
|
||||
"no, count, result",
|
||||
[
|
||||
(0, None, b""),
|
||||
(0, 1, b"\x00"),
|
||||
(0, 2, b"\x00\x00"),
|
||||
(1, None, b"\x01"),
|
||||
(1, 2, b"\x00\x01"),
|
||||
(255, None, b"\xff"),
|
||||
(256, None, b"\x01\x00"),
|
||||
],
|
||||
)
|
||||
def test_convert_int_to_bytes(no, count, result):
|
||||
value = convert_int_to_bytes(no, count=count)
|
||||
print(value)
|
||||
assert value == result
|
||||
|
||||
|
||||
@pytest.mark.parametrize('no, digits, result', [
|
||||
(0, None, '0'),
|
||||
(1, None, '1'),
|
||||
(16, None, '10'),
|
||||
(1, 3, '001'),
|
||||
(255, None, 'ff'),
|
||||
(256, None, '100'),
|
||||
(256, 2, '100'),
|
||||
(256, 3, '100'),
|
||||
(256, 4, '0100'),
|
||||
])
|
||||
@pytest.mark.parametrize(
|
||||
"no, digits, result",
|
||||
[
|
||||
(0, None, "0"),
|
||||
(1, None, "1"),
|
||||
(16, None, "10"),
|
||||
(1, 3, "001"),
|
||||
(255, None, "ff"),
|
||||
(256, None, "100"),
|
||||
(256, 2, "100"),
|
||||
(256, 3, "100"),
|
||||
(256, 4, "0100"),
|
||||
],
|
||||
)
|
||||
def test_convert_int_to_hex(no, digits, result):
|
||||
value = convert_int_to_hex(no, digits=digits)
|
||||
print(value)
|
||||
assert value == result
|
||||
|
||||
|
||||
@pytest.mark.parametrize('data, result', [
|
||||
(b'', 0),
|
||||
(b'\x00', 0),
|
||||
(b'\x00\x01', 1),
|
||||
(b'\x01', 1),
|
||||
(b'\xff', 255),
|
||||
(b'\x01\x00', 256),
|
||||
])
|
||||
@pytest.mark.parametrize(
|
||||
"data, result",
|
||||
[
|
||||
(b"", 0),
|
||||
(b"\x00", 0),
|
||||
(b"\x00\x01", 1),
|
||||
(b"\x01", 1),
|
||||
(b"\xff", 255),
|
||||
(b"\x01\x00", 256),
|
||||
],
|
||||
)
|
||||
def test_convert_bytes_to_int(data, result):
|
||||
value = convert_bytes_to_int(data)
|
||||
print(value)
|
||||
|
||||
@@ -19,48 +19,48 @@ from ansible_collections.community.crypto.plugins.module_utils.crypto.pem import
|
||||
|
||||
|
||||
PEM_TEST_CASES = [
|
||||
(b'', [], False, 'raw'),
|
||||
(b'random stuff\nblabla', [], False, 'raw'),
|
||||
(b'-----BEGIN PRIVATE KEY-----', [], False, 'raw'),
|
||||
(b"", [], False, "raw"),
|
||||
(b"random stuff\nblabla", [], False, "raw"),
|
||||
(b"-----BEGIN PRIVATE KEY-----", [], False, "raw"),
|
||||
(
|
||||
b'-----BEGIN PRIVATE KEY-----\n-----END PRIVATE KEY-----',
|
||||
['-----BEGIN PRIVATE KEY-----\n-----END PRIVATE KEY-----'],
|
||||
b"-----BEGIN PRIVATE KEY-----\n-----END PRIVATE KEY-----",
|
||||
["-----BEGIN PRIVATE KEY-----\n-----END PRIVATE KEY-----"],
|
||||
True,
|
||||
'pkcs8',
|
||||
"pkcs8",
|
||||
),
|
||||
(
|
||||
b'foo=bar\n# random stuff\n-----BEGIN RSA PRIVATE KEY-----\nblabla\n-----END RSA PRIVATE KEY-----\nmore stuff\n',
|
||||
['-----BEGIN RSA PRIVATE KEY-----\nblabla\n-----END RSA PRIVATE KEY-----\n'],
|
||||
b"foo=bar\n# random stuff\n-----BEGIN RSA PRIVATE KEY-----\nblabla\n-----END RSA PRIVATE KEY-----\nmore stuff\n",
|
||||
["-----BEGIN RSA PRIVATE KEY-----\nblabla\n-----END RSA PRIVATE KEY-----\n"],
|
||||
True,
|
||||
'pkcs1',
|
||||
"pkcs1",
|
||||
),
|
||||
(
|
||||
b'foo=bar\n# random stuff\n-----BEGIN CERTIFICATE-----\nblabla\n-----END CERTIFICATE-----\nmore stuff\n'
|
||||
b'\n-----BEGIN CERTIFICATE-----\nfoobar\n-----END CERTIFICATE-----',
|
||||
b"foo=bar\n# random stuff\n-----BEGIN CERTIFICATE-----\nblabla\n-----END CERTIFICATE-----\nmore stuff\n"
|
||||
b"\n-----BEGIN CERTIFICATE-----\nfoobar\n-----END CERTIFICATE-----",
|
||||
[
|
||||
'-----BEGIN CERTIFICATE-----\nblabla\n-----END CERTIFICATE-----\n',
|
||||
'-----BEGIN CERTIFICATE-----\nfoobar\n-----END CERTIFICATE-----',
|
||||
"-----BEGIN CERTIFICATE-----\nblabla\n-----END CERTIFICATE-----\n",
|
||||
"-----BEGIN CERTIFICATE-----\nfoobar\n-----END CERTIFICATE-----",
|
||||
],
|
||||
True,
|
||||
'unknown-pem',
|
||||
"unknown-pem",
|
||||
),
|
||||
(
|
||||
b'-----BEGINCERTIFICATE-----\n-----BEGIN CERTIFICATE-----\n-----BEGINCERTIFICATE-----\n-----END CERTIFICATE-----\n-----BEGINCERTIFICATE-----\n',
|
||||
b"-----BEGINCERTIFICATE-----\n-----BEGIN CERTIFICATE-----\n-----BEGINCERTIFICATE-----\n-----END CERTIFICATE-----\n-----BEGINCERTIFICATE-----\n",
|
||||
[
|
||||
'-----BEGIN CERTIFICATE-----\n-----BEGINCERTIFICATE-----\n-----END CERTIFICATE-----\n',
|
||||
"-----BEGIN CERTIFICATE-----\n-----BEGINCERTIFICATE-----\n-----END CERTIFICATE-----\n",
|
||||
],
|
||||
True,
|
||||
'unknown-pem',
|
||||
"unknown-pem",
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.parametrize('data, pems, is_pem, private_key_type', PEM_TEST_CASES)
|
||||
@pytest.mark.parametrize("data, pems, is_pem, private_key_type", PEM_TEST_CASES)
|
||||
def test_pem_handling(data, pems, is_pem, private_key_type):
|
||||
assert identify_pem_format(data) == is_pem
|
||||
assert identify_private_key_format(data) == private_key_type
|
||||
try:
|
||||
text = data.decode('utf-8')
|
||||
text = data.decode("utf-8")
|
||||
assert split_pem_list(text) == pems
|
||||
first_pem = pems[0] if pems else None
|
||||
assert extract_first_pem(text) == first_pem
|
||||
|
||||
@@ -33,22 +33,22 @@ from ansible_collections.community.crypto.plugins.module_utils.openssh.certifica
|
||||
# permit-pty
|
||||
# permit-user-rc
|
||||
RSA_CERT_SIGNED_BY_DSA = (
|
||||
b'ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgY9CvhGpyvBB611Lmx6hHPD+CmeJ0oW' +
|
||||
b'SSK1q6K3h5CS4AAAADAQABAAABAQDKYIJtpFaWpTNNifmuV3DM9BBdngMG28jWPy4C/SoZg4EP7mkYUsG6hN+LgjOL17YEF7bKDEWPl9sQS' +
|
||||
b'92iD+AuAPrjnHVQ9VG5hbTYiQAaicj6hxqBoNqGQWxDzhZL4B35MgqmoUOBGnzYA/fKgqhRVzOXbWFxKLtzSJzB+Z+kmeoBzq+4MazL4Bko' +
|
||||
b'yPZMrIMnvxiluv+kqE9SWeJ/5e7WXdtbYTnSR4WN3gW/BMKEoKQk/UGwuPvCiRq+y8LorJP4B1Wfwlm/meqtbTidXyCcQPR9xWpce3rRjLL' +
|
||||
b'T6cimUjWrbx7Q1SlsypdkclgPSTu9Jg457am8tnQUgnL7VdetAAAAAAAAAAAAAAABAAAABHRlc3QAAAAAAAAAAAAAAAD//////////wAAAA' +
|
||||
b'AAAACCAAAAFXBlcm1pdC1YMTEtZm9yd2FyZGluZwAAAAAAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAAFnBlcm1pdC1wb3J0L' +
|
||||
b'WZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAAAAAAAAAAGxAAAAB3NzaC1kc3MAAACBAPV/' +
|
||||
b'b5FknU8e56TWAGLRQ0v3c3f5jAS0txcwqtYLHLulTqyMcLL0MyzWxXv77MpjTMwEjWXLbfNWdk/qmsjfBynzs2nSZ7clVsqt/ZOadcBFEhq' +
|
||||
b'ZM0l+1ZCPkhQiqsD2aodGbkVcJgqL5Z5krzB5MTey7c8rlAAxKOjfs70Bg8MPAAAAFQCW466dSEu2Pf0u8AA5SHgH0i/xuwAAAIBc23gfmv' +
|
||||
b'GC+oaUAXiak17kH6NvOSJXZBdk/8CyGK6yL+CHKrKyffe6BbiVXwC6sUIa9j4YsFeyYwPFGBtfLuNUmgyKYTJcCM2zJLBykmTIvjSdRaYGN' +
|
||||
b'Rkyi8GnzVV2lWxQ+4m4UGeTPbPN/OG4B0NwDbBJGbVJv0xJPq2EBKoUdgAAAIAyrFxGDLtOZFZ2fgONVaKaapEpJ5f3qPhLDXxVQ/BKVUkU' +
|
||||
b'RA4AHHyXF2AMiiOOiHLrO5xsEGUyW+OISFm+6m17cEPNixA7G1fBniLvyVv2woyYW3kaY4J9z266kAFzFWVNgwr+T7MY0hEvct8VFA97JMR' +
|
||||
b'Q7c8c/tNDaL7uqV46QQAAADcAAAAHc3NoLWRzcwAAAChaQ94wqca+KhkHtbkLpjvGsfu0Gy03SAb0+o11Shk/BXnK7N/cwEVD ' +
|
||||
b'ansible@ansible-host'
|
||||
b"ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgY9CvhGpyvBB611Lmx6hHPD+CmeJ0oW"
|
||||
+ b"SSK1q6K3h5CS4AAAADAQABAAABAQDKYIJtpFaWpTNNifmuV3DM9BBdngMG28jWPy4C/SoZg4EP7mkYUsG6hN+LgjOL17YEF7bKDEWPl9sQS"
|
||||
+ b"92iD+AuAPrjnHVQ9VG5hbTYiQAaicj6hxqBoNqGQWxDzhZL4B35MgqmoUOBGnzYA/fKgqhRVzOXbWFxKLtzSJzB+Z+kmeoBzq+4MazL4Bko"
|
||||
+ b"yPZMrIMnvxiluv+kqE9SWeJ/5e7WXdtbYTnSR4WN3gW/BMKEoKQk/UGwuPvCiRq+y8LorJP4B1Wfwlm/meqtbTidXyCcQPR9xWpce3rRjLL"
|
||||
+ b"T6cimUjWrbx7Q1SlsypdkclgPSTu9Jg457am8tnQUgnL7VdetAAAAAAAAAAAAAAABAAAABHRlc3QAAAAAAAAAAAAAAAD//////////wAAAA"
|
||||
+ b"AAAACCAAAAFXBlcm1pdC1YMTEtZm9yd2FyZGluZwAAAAAAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAAFnBlcm1pdC1wb3J0L"
|
||||
+ b"WZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAAAAAAAAAAGxAAAAB3NzaC1kc3MAAACBAPV/"
|
||||
+ b"b5FknU8e56TWAGLRQ0v3c3f5jAS0txcwqtYLHLulTqyMcLL0MyzWxXv77MpjTMwEjWXLbfNWdk/qmsjfBynzs2nSZ7clVsqt/ZOadcBFEhq"
|
||||
+ b"ZM0l+1ZCPkhQiqsD2aodGbkVcJgqL5Z5krzB5MTey7c8rlAAxKOjfs70Bg8MPAAAAFQCW466dSEu2Pf0u8AA5SHgH0i/xuwAAAIBc23gfmv"
|
||||
+ b"GC+oaUAXiak17kH6NvOSJXZBdk/8CyGK6yL+CHKrKyffe6BbiVXwC6sUIa9j4YsFeyYwPFGBtfLuNUmgyKYTJcCM2zJLBykmTIvjSdRaYGN"
|
||||
+ b"Rkyi8GnzVV2lWxQ+4m4UGeTPbPN/OG4B0NwDbBJGbVJv0xJPq2EBKoUdgAAAIAyrFxGDLtOZFZ2fgONVaKaapEpJ5f3qPhLDXxVQ/BKVUkU"
|
||||
+ b"RA4AHHyXF2AMiiOOiHLrO5xsEGUyW+OISFm+6m17cEPNixA7G1fBniLvyVv2woyYW3kaY4J9z266kAFzFWVNgwr+T7MY0hEvct8VFA97JMR"
|
||||
+ b"Q7c8c/tNDaL7uqV46QQAAADcAAAAHc3NoLWRzcwAAAChaQ94wqca+KhkHtbkLpjvGsfu0Gy03SAb0+o11Shk/BXnK7N/cwEVD "
|
||||
+ b"ansible@ansible-host"
|
||||
)
|
||||
RSA_FINGERPRINT = 'SHA256:SvUwwUer4AwsdePYseJR3LcZS8lnKi6BqiL51Dop030'
|
||||
RSA_FINGERPRINT = "SHA256:SvUwwUer4AwsdePYseJR3LcZS8lnKi6BqiL51Dop030"
|
||||
# Type: ssh-dss-cert-v01@openssh.com user certificate
|
||||
# Public key: DSA-CERT SHA256:YCdJ2lYU+FSkWUud7zg1SJszprXoRGNU/GVcqXUjgC8
|
||||
# Signing CA: ECDSA SHA256:w9lp4zGRJShhm4DzO3ulVm0BEcR0PMjrM6VanQo4C0w
|
||||
@@ -59,18 +59,18 @@ RSA_FINGERPRINT = 'SHA256:SvUwwUer4AwsdePYseJR3LcZS8lnKi6BqiL51Dop030'
|
||||
# Critical Options: (none)
|
||||
# Extensions: (none)
|
||||
DSA_CERT_SIGNED_BY_ECDSA_NO_OPTS = (
|
||||
b'ssh-dss-cert-v01@openssh.com AAAAHHNzaC1kc3MtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgsKvMxIv4viCNQX7z8K4/R5jronpZGf' +
|
||||
b'ydpoBoh2Cx5dgAAACBAPV/b5FknU8e56TWAGLRQ0v3c3f5jAS0txcwqtYLHLulTqyMcLL0MyzWxXv77MpjTMwEjWXLbfNWdk/qmsjfBynzs' +
|
||||
b'2nSZ7clVsqt/ZOadcBFEhqZM0l+1ZCPkhQiqsD2aodGbkVcJgqL5Z5krzB5MTey7c8rlAAxKOjfs70Bg8MPAAAAFQCW466dSEu2Pf0u8AA5' +
|
||||
b'SHgH0i/xuwAAAIBc23gfmvGC+oaUAXiak17kH6NvOSJXZBdk/8CyGK6yL+CHKrKyffe6BbiVXwC6sUIa9j4YsFeyYwPFGBtfLuNUmgyKYTJ' +
|
||||
b'cCM2zJLBykmTIvjSdRaYGNRkyi8GnzVV2lWxQ+4m4UGeTPbPN/OG4B0NwDbBJGbVJv0xJPq2EBKoUdgAAAIAyrFxGDLtOZFZ2fgONVaKaap' +
|
||||
b'EpJ5f3qPhLDXxVQ/BKVUkURA4AHHyXF2AMiiOOiHLrO5xsEGUyW+OISFm+6m17cEPNixA7G1fBniLvyVv2woyYW3kaY4J9z266kAFzFWVNg' +
|
||||
b'wr+T7MY0hEvct8VFA97JMRQ7c8c/tNDaL7uqV46QQAAAAAAAAAAAAAAAQAAAAR0ZXN0AAAAAAAAAAAAAAAA//////////8AAAAAAAAAAAAA' +
|
||||
b'AAAAAABoAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOf55Wc0yzaJPtxXxBGZKmAUozbYXwxZGFS1c/FaJbwLpq/' +
|
||||
b'wvanQKM01uU73swNIt+ZFra9kRSi21xjzgMPn7U0AAABkAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAABJAAAAIGmlKa/riG7+EpoW6dTJY6' +
|
||||
b'0N8BrEcniKgOxdRM1EPJ2DAAAAIQDnK4stvbvS+Bn0/42Was7uOfJtnLYXs5EuB2L3uejPcQ== ansible@ansible-host'
|
||||
b"ssh-dss-cert-v01@openssh.com AAAAHHNzaC1kc3MtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgsKvMxIv4viCNQX7z8K4/R5jronpZGf"
|
||||
+ b"ydpoBoh2Cx5dgAAACBAPV/b5FknU8e56TWAGLRQ0v3c3f5jAS0txcwqtYLHLulTqyMcLL0MyzWxXv77MpjTMwEjWXLbfNWdk/qmsjfBynzs"
|
||||
+ b"2nSZ7clVsqt/ZOadcBFEhqZM0l+1ZCPkhQiqsD2aodGbkVcJgqL5Z5krzB5MTey7c8rlAAxKOjfs70Bg8MPAAAAFQCW466dSEu2Pf0u8AA5"
|
||||
+ b"SHgH0i/xuwAAAIBc23gfmvGC+oaUAXiak17kH6NvOSJXZBdk/8CyGK6yL+CHKrKyffe6BbiVXwC6sUIa9j4YsFeyYwPFGBtfLuNUmgyKYTJ"
|
||||
+ b"cCM2zJLBykmTIvjSdRaYGNRkyi8GnzVV2lWxQ+4m4UGeTPbPN/OG4B0NwDbBJGbVJv0xJPq2EBKoUdgAAAIAyrFxGDLtOZFZ2fgONVaKaap"
|
||||
+ b"EpJ5f3qPhLDXxVQ/BKVUkURA4AHHyXF2AMiiOOiHLrO5xsEGUyW+OISFm+6m17cEPNixA7G1fBniLvyVv2woyYW3kaY4J9z266kAFzFWVNg"
|
||||
+ b"wr+T7MY0hEvct8VFA97JMRQ7c8c/tNDaL7uqV46QQAAAAAAAAAAAAAAAQAAAAR0ZXN0AAAAAAAAAAAAAAAA//////////8AAAAAAAAAAAAA"
|
||||
+ b"AAAAAABoAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOf55Wc0yzaJPtxXxBGZKmAUozbYXwxZGFS1c/FaJbwLpq/"
|
||||
+ b"wvanQKM01uU73swNIt+ZFra9kRSi21xjzgMPn7U0AAABkAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAABJAAAAIGmlKa/riG7+EpoW6dTJY6"
|
||||
+ b"0N8BrEcniKgOxdRM1EPJ2DAAAAIQDnK4stvbvS+Bn0/42Was7uOfJtnLYXs5EuB2L3uejPcQ== ansible@ansible-host"
|
||||
)
|
||||
DSA_FINGERPRINT = 'SHA256:YCdJ2lYU+FSkWUud7zg1SJszprXoRGNU/GVcqXUjgC8'
|
||||
DSA_FINGERPRINT = "SHA256:YCdJ2lYU+FSkWUud7zg1SJszprXoRGNU/GVcqXUjgC8"
|
||||
# Type: ecdsa-sha2-nistp256-cert-v01@openssh.com user certificate
|
||||
# Public key: ECDSA-CERT SHA256:w9lp4zGRJShhm4DzO3ulVm0BEcR0PMjrM6VanQo4C0w
|
||||
# Signing CA: ED25519 SHA256:NP4JdfkCopbjwMepq0aPrpMz13cNmEd+uDOxC/j9N40
|
||||
@@ -87,16 +87,16 @@ DSA_FINGERPRINT = 'SHA256:YCdJ2lYU+FSkWUud7zg1SJszprXoRGNU/GVcqXUjgC8'
|
||||
# permit-pty
|
||||
# permit-user-rc
|
||||
ECDSA_CERT_SIGNED_BY_ED25519_VALID_OPTS = (
|
||||
b'ecdsa-sha2-nistp256-cert-v01@openssh.com AAAAKGVjZHNhLXNoYTItbmlzdHAyNTYtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgtC' +
|
||||
b'ips7/sOOOTAgiawGlQhM6pb26t0FfQ1jG60m+tOg0AAAAIbmlzdHAyNTYAAABBBOf55Wc0yzaJPtxXxBGZKmAUozbYXwxZGFS1c/FaJbwLp' +
|
||||
b'q/wvanQKM01uU73swNIt+ZFra9kRSi21xjzgMPn7U0AAAAAAAAAAAAAAAEAAAAEdGVzdAAAAAAAAAAAAAAAAP//////////AAAAJQAAAA1m' +
|
||||
b'b3JjZS1jb21tYW5kAAAAEAAAAAwvdXNyL2Jpbi9jc2gAAACCAAAAFXBlcm1pdC1YMTEtZm9yd2FyZGluZwAAAAAAAAAXcGVybWl0LWFnZW5' +
|
||||
b'0LWZvcndhcmRpbmcAAAAAAAAAFnBlcm1pdC1wb3J0LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLX' +
|
||||
b'JjAAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAII3qYBforim0x87UXpaTDNFnhFTyb+TPCJVQpEAOHTL6AAAAUwAAAAtzc2gtZWQyN' +
|
||||
b'TUxOQAAAEAdp3eOLRN5t2wW29TBWbz604uuXg88jH4RA4HDhbRupa/x2rN3j6iZQ4VXPLA4JtdfIslHFkH6HUlxU8XsoJwP ' +
|
||||
b'ansible@ansible-host'
|
||||
b"ecdsa-sha2-nistp256-cert-v01@openssh.com AAAAKGVjZHNhLXNoYTItbmlzdHAyNTYtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgtC"
|
||||
+ b"ips7/sOOOTAgiawGlQhM6pb26t0FfQ1jG60m+tOg0AAAAIbmlzdHAyNTYAAABBBOf55Wc0yzaJPtxXxBGZKmAUozbYXwxZGFS1c/FaJbwLp"
|
||||
+ b"q/wvanQKM01uU73swNIt+ZFra9kRSi21xjzgMPn7U0AAAAAAAAAAAAAAAEAAAAEdGVzdAAAAAAAAAAAAAAAAP//////////AAAAJQAAAA1m"
|
||||
+ b"b3JjZS1jb21tYW5kAAAAEAAAAAwvdXNyL2Jpbi9jc2gAAACCAAAAFXBlcm1pdC1YMTEtZm9yd2FyZGluZwAAAAAAAAAXcGVybWl0LWFnZW5"
|
||||
+ b"0LWZvcndhcmRpbmcAAAAAAAAAFnBlcm1pdC1wb3J0LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLX"
|
||||
+ b"JjAAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAII3qYBforim0x87UXpaTDNFnhFTyb+TPCJVQpEAOHTL6AAAAUwAAAAtzc2gtZWQyN"
|
||||
+ b"TUxOQAAAEAdp3eOLRN5t2wW29TBWbz604uuXg88jH4RA4HDhbRupa/x2rN3j6iZQ4VXPLA4JtdfIslHFkH6HUlxU8XsoJwP "
|
||||
+ b"ansible@ansible-host"
|
||||
)
|
||||
ECDSA_FINGERPRINT = 'SHA256:w9lp4zGRJShhm4DzO3ulVm0BEcR0PMjrM6VanQo4C0w'
|
||||
ECDSA_FINGERPRINT = "SHA256:w9lp4zGRJShhm4DzO3ulVm0BEcR0PMjrM6VanQo4C0w"
|
||||
# Type: ssh-ed25519-cert-v01@openssh.com user certificate
|
||||
# Public key: ED25519-CERT SHA256:NP4JdfkCopbjwMepq0aPrpMz13cNmEd+uDOxC/j9N40
|
||||
# Signing CA: RSA SHA256:SvUwwUer4AwsdePYseJR3LcZS8lnKi6BqiL51Dop030
|
||||
@@ -109,57 +109,123 @@ ECDSA_FINGERPRINT = 'SHA256:w9lp4zGRJShhm4DzO3ulVm0BEcR0PMjrM6VanQo4C0w'
|
||||
# Extensions:
|
||||
# test UNKNOWN OPTION (len 0)
|
||||
ED25519_CERT_SIGNED_BY_RSA_INVALID_OPTS = (
|
||||
b'ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIP034YpKn6BDcwxqFnVrKt' +
|
||||
b'kNX7k6X7hxZ7lADp5LAxHrAAAAII3qYBforim0x87UXpaTDNFnhFTyb+TPCJVQpEAOHTL6AAAAAAAAAAAAAAABAAAABHRlc3QAAAAAAAAAA' +
|
||||
b'AAAAAD//////////wAAABkAAAAEdGVzdAAAAA0AAAAJdW5kZWZpbmVkAAAADAAAAAR0ZXN0AAAAAAAAAAAAAAEXAAAAB3NzaC1yc2EAAAAD' +
|
||||
b'AQABAAABAQDKYIJtpFaWpTNNifmuV3DM9BBdngMG28jWPy4C/SoZg4EP7mkYUsG6hN+LgjOL17YEF7bKDEWPl9sQS92iD+AuAPrjnHVQ9VG' +
|
||||
b'5hbTYiQAaicj6hxqBoNqGQWxDzhZL4B35MgqmoUOBGnzYA/fKgqhRVzOXbWFxKLtzSJzB+Z+kmeoBzq+4MazL4BkoyPZMrIMnvxiluv+kqE' +
|
||||
b'9SWeJ/5e7WXdtbYTnSR4WN3gW/BMKEoKQk/UGwuPvCiRq+y8LorJP4B1Wfwlm/meqtbTidXyCcQPR9xWpce3rRjLLT6cimUjWrbx7Q1Slsy' +
|
||||
b'pdkclgPSTu9Jg457am8tnQUgnL7VdetAAABDwAAAAdzc2gtcnNhAAABAMZLNacwOMNexYUaFK1nU0JPQTv4fM73QDG3xURtDsIbI6DAcA1y' +
|
||||
b'KkvgjJcxlZHx0APJ+i1lWNAvPeOmuPTioymjIEuwxi0VGuAoVKgjmIy6aXH2z3YMxy9cGOq6LNfI4c58iBHR5ejVHAzvIg3rowypVsCGugL' +
|
||||
b'7WJpz3eypBJt4TglwRTJpp54IMN2CyDQm0N97x9ris8jQQHlCF2EgZp1u4aOiZJTSJ5d4hapO0uZwXOI9AIWy/lmx0/6jX07MWrs4iXpfiF' +
|
||||
b'5T4s6kEn7YW4SaJ0Z7xGp3V0vDOxh+jwHZGD5GM449Il6QxQwDY5BSJq+iMR467yaIjw2g8Kt4ZiU= ansible@ansible-host'
|
||||
b"ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIP034YpKn6BDcwxqFnVrKt"
|
||||
+ b"kNX7k6X7hxZ7lADp5LAxHrAAAAII3qYBforim0x87UXpaTDNFnhFTyb+TPCJVQpEAOHTL6AAAAAAAAAAAAAAABAAAABHRlc3QAAAAAAAAAA"
|
||||
+ b"AAAAAD//////////wAAABkAAAAEdGVzdAAAAA0AAAAJdW5kZWZpbmVkAAAADAAAAAR0ZXN0AAAAAAAAAAAAAAEXAAAAB3NzaC1yc2EAAAAD"
|
||||
+ b"AQABAAABAQDKYIJtpFaWpTNNifmuV3DM9BBdngMG28jWPy4C/SoZg4EP7mkYUsG6hN+LgjOL17YEF7bKDEWPl9sQS92iD+AuAPrjnHVQ9VG"
|
||||
+ b"5hbTYiQAaicj6hxqBoNqGQWxDzhZL4B35MgqmoUOBGnzYA/fKgqhRVzOXbWFxKLtzSJzB+Z+kmeoBzq+4MazL4BkoyPZMrIMnvxiluv+kqE"
|
||||
+ b"9SWeJ/5e7WXdtbYTnSR4WN3gW/BMKEoKQk/UGwuPvCiRq+y8LorJP4B1Wfwlm/meqtbTidXyCcQPR9xWpce3rRjLLT6cimUjWrbx7Q1Slsy"
|
||||
+ b"pdkclgPSTu9Jg457am8tnQUgnL7VdetAAABDwAAAAdzc2gtcnNhAAABAMZLNacwOMNexYUaFK1nU0JPQTv4fM73QDG3xURtDsIbI6DAcA1y"
|
||||
+ b"KkvgjJcxlZHx0APJ+i1lWNAvPeOmuPTioymjIEuwxi0VGuAoVKgjmIy6aXH2z3YMxy9cGOq6LNfI4c58iBHR5ejVHAzvIg3rowypVsCGugL"
|
||||
+ b"7WJpz3eypBJt4TglwRTJpp54IMN2CyDQm0N97x9ris8jQQHlCF2EgZp1u4aOiZJTSJ5d4hapO0uZwXOI9AIWy/lmx0/6jX07MWrs4iXpfiF"
|
||||
+ b"5T4s6kEn7YW4SaJ0Z7xGp3V0vDOxh+jwHZGD5GM449Il6QxQwDY5BSJq+iMR467yaIjw2g8Kt4ZiU= ansible@ansible-host"
|
||||
)
|
||||
ED25519_FINGERPRINT = 'SHA256:NP4JdfkCopbjwMepq0aPrpMz13cNmEd+uDOxC/j9N40'
|
||||
ED25519_FINGERPRINT = "SHA256:NP4JdfkCopbjwMepq0aPrpMz13cNmEd+uDOxC/j9N40"
|
||||
# garbage
|
||||
INVALID_DATA = b'yDspTN+BJzvIK2Q+CRD3qBDVSi+YqSxwyz432VEaHKlXbuLURirY0QpuBCqgR6tCtWW5vEGkXKZ3'
|
||||
INVALID_DATA = (
|
||||
b"yDspTN+BJzvIK2Q+CRD3qBDVSi+YqSxwyz432VEaHKlXbuLURirY0QpuBCqgR6tCtWW5vEGkXKZ3"
|
||||
)
|
||||
|
||||
VALID_OPTS = [OpensshCertificateOption('critical', 'force-command', '/usr/bin/csh')]
|
||||
INVALID_OPTS = [OpensshCertificateOption('critical', 'test', 'undefined')]
|
||||
VALID_OPTS = [OpensshCertificateOption("critical", "force-command", "/usr/bin/csh")]
|
||||
INVALID_OPTS = [OpensshCertificateOption("critical", "test", "undefined")]
|
||||
VALID_EXTENSIONS = [
|
||||
OpensshCertificateOption('extension', 'permit-x11-forwarding', ''),
|
||||
OpensshCertificateOption('extension', 'permit-agent-forwarding', ''),
|
||||
OpensshCertificateOption('extension', 'permit-port-forwarding', ''),
|
||||
OpensshCertificateOption('extension', 'permit-pty', ''),
|
||||
OpensshCertificateOption('extension', 'permit-user-rc', ''),
|
||||
OpensshCertificateOption("extension", "permit-x11-forwarding", ""),
|
||||
OpensshCertificateOption("extension", "permit-agent-forwarding", ""),
|
||||
OpensshCertificateOption("extension", "permit-port-forwarding", ""),
|
||||
OpensshCertificateOption("extension", "permit-pty", ""),
|
||||
OpensshCertificateOption("extension", "permit-user-rc", ""),
|
||||
]
|
||||
INVALID_EXTENSIONS = [OpensshCertificateOption('extension', 'test', '')]
|
||||
INVALID_EXTENSIONS = [OpensshCertificateOption("extension", "test", "")]
|
||||
|
||||
VALID_TIME_PARAMETERS = [
|
||||
(0, "always", "always", 0,
|
||||
0xFFFFFFFFFFFFFFFF, "forever", "forever", 253402300800,
|
||||
""),
|
||||
("always", "always", "always", 0,
|
||||
"forever", "forever", "forever", 253402300800,
|
||||
""),
|
||||
(315532800, "1980-01-01T00:00:00", "19800101000000", 315532800,
|
||||
631152000, "1990-01-01T00:00:00", "19900101000000", 631152000,
|
||||
"19800101000000:19900101000000"),
|
||||
("1980-01-01", "1980-01-01T00:00:00", "19800101000000", 315532800,
|
||||
"1990-01-01", "1990-01-01T00:00:00", "19900101000000", 631152000,
|
||||
"19800101000000:19900101000000"),
|
||||
("1980-01-01 00:00:00", "1980-01-01T00:00:00", "19800101000000", 315532800,
|
||||
"1990-01-01 00:00:00", "1990-01-01T00:00:00", "19900101000000", 631152000,
|
||||
"19800101000000:19900101000000"),
|
||||
("1980-01-01T00:00:00", "1980-01-01T00:00:00", "19800101000000", 315532800,
|
||||
"1990-01-01T00:00:00", "1990-01-01T00:00:00", "19900101000000", 631152000,
|
||||
"19800101000000:19900101000000"),
|
||||
("always", "always", "always", 0,
|
||||
"1990-01-01T00:00:00", "1990-01-01T00:00:00", "19900101000000", 631152000,
|
||||
"always:19900101000000"),
|
||||
("1980-01-01", "1980-01-01T00:00:00", "19800101000000", 315532800,
|
||||
"forever", "forever", "forever", 253402300800,
|
||||
"19800101000000:forever"),
|
||||
(
|
||||
0,
|
||||
"always",
|
||||
"always",
|
||||
0,
|
||||
0xFFFFFFFFFFFFFFFF,
|
||||
"forever",
|
||||
"forever",
|
||||
253402300800,
|
||||
"",
|
||||
),
|
||||
(
|
||||
"always",
|
||||
"always",
|
||||
"always",
|
||||
0,
|
||||
"forever",
|
||||
"forever",
|
||||
"forever",
|
||||
253402300800,
|
||||
"",
|
||||
),
|
||||
(
|
||||
315532800,
|
||||
"1980-01-01T00:00:00",
|
||||
"19800101000000",
|
||||
315532800,
|
||||
631152000,
|
||||
"1990-01-01T00:00:00",
|
||||
"19900101000000",
|
||||
631152000,
|
||||
"19800101000000:19900101000000",
|
||||
),
|
||||
(
|
||||
"1980-01-01",
|
||||
"1980-01-01T00:00:00",
|
||||
"19800101000000",
|
||||
315532800,
|
||||
"1990-01-01",
|
||||
"1990-01-01T00:00:00",
|
||||
"19900101000000",
|
||||
631152000,
|
||||
"19800101000000:19900101000000",
|
||||
),
|
||||
(
|
||||
"1980-01-01 00:00:00",
|
||||
"1980-01-01T00:00:00",
|
||||
"19800101000000",
|
||||
315532800,
|
||||
"1990-01-01 00:00:00",
|
||||
"1990-01-01T00:00:00",
|
||||
"19900101000000",
|
||||
631152000,
|
||||
"19800101000000:19900101000000",
|
||||
),
|
||||
(
|
||||
"1980-01-01T00:00:00",
|
||||
"1980-01-01T00:00:00",
|
||||
"19800101000000",
|
||||
315532800,
|
||||
"1990-01-01T00:00:00",
|
||||
"1990-01-01T00:00:00",
|
||||
"19900101000000",
|
||||
631152000,
|
||||
"19800101000000:19900101000000",
|
||||
),
|
||||
(
|
||||
"always",
|
||||
"always",
|
||||
"always",
|
||||
0,
|
||||
"1990-01-01T00:00:00",
|
||||
"1990-01-01T00:00:00",
|
||||
"19900101000000",
|
||||
631152000,
|
||||
"always:19900101000000",
|
||||
),
|
||||
(
|
||||
"1980-01-01",
|
||||
"1980-01-01T00:00:00",
|
||||
"19800101000000",
|
||||
315532800,
|
||||
"forever",
|
||||
"forever",
|
||||
"forever",
|
||||
253402300800,
|
||||
"19800101000000:forever",
|
||||
),
|
||||
]
|
||||
|
||||
INVALID_TIME_PARAMETERS = [
|
||||
@@ -184,41 +250,53 @@ INVALID_VALIDITY_TEST = [
|
||||
]
|
||||
|
||||
VALID_OPTIONS = [
|
||||
("force-command=/usr/bin/csh", OpensshCertificateOption('critical', 'force-command', '/usr/bin/csh')),
|
||||
("Force-Command=/Usr/Bin/Csh", OpensshCertificateOption('critical', 'force-command', '/Usr/Bin/Csh')),
|
||||
("permit-x11-forwarding", OpensshCertificateOption('extension', 'permit-x11-forwarding', '')),
|
||||
("permit-X11-forwarding", OpensshCertificateOption('extension', 'permit-x11-forwarding', '')),
|
||||
("critical:foo=bar", OpensshCertificateOption('critical', 'foo', 'bar')),
|
||||
("extension:foo", OpensshCertificateOption('extension', 'foo', '')),
|
||||
(
|
||||
"force-command=/usr/bin/csh",
|
||||
OpensshCertificateOption("critical", "force-command", "/usr/bin/csh"),
|
||||
),
|
||||
(
|
||||
"Force-Command=/Usr/Bin/Csh",
|
||||
OpensshCertificateOption("critical", "force-command", "/Usr/Bin/Csh"),
|
||||
),
|
||||
(
|
||||
"permit-x11-forwarding",
|
||||
OpensshCertificateOption("extension", "permit-x11-forwarding", ""),
|
||||
),
|
||||
(
|
||||
"permit-X11-forwarding",
|
||||
OpensshCertificateOption("extension", "permit-x11-forwarding", ""),
|
||||
),
|
||||
("critical:foo=bar", OpensshCertificateOption("critical", "foo", "bar")),
|
||||
("extension:foo", OpensshCertificateOption("extension", "foo", "")),
|
||||
]
|
||||
|
||||
INVALID_OPTIONS = [
|
||||
"foobar",
|
||||
"foo=bar",
|
||||
'foo:bar=baz',
|
||||
"foo:bar=baz",
|
||||
[],
|
||||
]
|
||||
|
||||
|
||||
def test_rsa_certificate(tmpdir):
|
||||
cert_file = tmpdir / 'id_rsa-cert.pub'
|
||||
cert_file.write(RSA_CERT_SIGNED_BY_DSA, mode='wb')
|
||||
cert_file = tmpdir / "id_rsa-cert.pub"
|
||||
cert_file.write(RSA_CERT_SIGNED_BY_DSA, mode="wb")
|
||||
|
||||
cert = OpensshCertificate.load(str(cert_file))
|
||||
assert cert.key_id == 'test'
|
||||
assert cert.key_id == "test"
|
||||
assert cert.serial == 0
|
||||
assert cert.type_string == 'ssh-rsa-cert-v01@openssh.com'
|
||||
assert cert.type_string == "ssh-rsa-cert-v01@openssh.com"
|
||||
assert cert.public_key == RSA_FINGERPRINT
|
||||
assert cert.signing_key == DSA_FINGERPRINT
|
||||
|
||||
|
||||
def test_dsa_certificate(tmpdir):
|
||||
cert_file = tmpdir / 'id_dsa-cert.pub'
|
||||
cert_file = tmpdir / "id_dsa-cert.pub"
|
||||
cert_file.write(DSA_CERT_SIGNED_BY_ECDSA_NO_OPTS)
|
||||
|
||||
cert = OpensshCertificate.load(str(cert_file))
|
||||
|
||||
assert cert.type_string == 'ssh-dss-cert-v01@openssh.com'
|
||||
assert cert.type_string == "ssh-dss-cert-v01@openssh.com"
|
||||
assert cert.public_key == DSA_FINGERPRINT
|
||||
assert cert.signing_key == ECDSA_FINGERPRINT
|
||||
assert cert.critical_options == []
|
||||
@@ -226,11 +304,11 @@ def test_dsa_certificate(tmpdir):
|
||||
|
||||
|
||||
def test_ecdsa_certificate(tmpdir):
|
||||
cert_file = tmpdir / 'id_ecdsa-cert.pub'
|
||||
cert_file = tmpdir / "id_ecdsa-cert.pub"
|
||||
cert_file.write(ECDSA_CERT_SIGNED_BY_ED25519_VALID_OPTS)
|
||||
|
||||
cert = OpensshCertificate.load(str(cert_file))
|
||||
assert cert.type_string == 'ecdsa-sha2-nistp256-cert-v01@openssh.com'
|
||||
assert cert.type_string == "ecdsa-sha2-nistp256-cert-v01@openssh.com"
|
||||
assert cert.public_key == ECDSA_FINGERPRINT
|
||||
assert cert.signing_key == ED25519_FINGERPRINT
|
||||
assert cert.critical_options == VALID_OPTS
|
||||
@@ -238,11 +316,11 @@ def test_ecdsa_certificate(tmpdir):
|
||||
|
||||
|
||||
def test_ed25519_certificate(tmpdir):
|
||||
cert_file = tmpdir / 'id_ed25519-cert.pub'
|
||||
cert_file = tmpdir / "id_ed25519-cert.pub"
|
||||
cert_file.write(ED25519_CERT_SIGNED_BY_RSA_INVALID_OPTS)
|
||||
|
||||
cert = OpensshCertificate.load(str(cert_file))
|
||||
assert cert.type_string == 'ssh-ed25519-cert-v01@openssh.com'
|
||||
assert cert.type_string == "ssh-ed25519-cert-v01@openssh.com"
|
||||
assert cert.public_key == ED25519_FINGERPRINT
|
||||
assert cert.signing_key == RSA_FINGERPRINT
|
||||
assert cert.critical_options == INVALID_OPTS
|
||||
@@ -251,7 +329,7 @@ def test_ed25519_certificate(tmpdir):
|
||||
|
||||
def test_invalid_data(tmpdir):
|
||||
result = False
|
||||
cert_file = tmpdir / 'invalid-cert.pub'
|
||||
cert_file = tmpdir / "invalid-cert.pub"
|
||||
cert_file.write(INVALID_DATA)
|
||||
|
||||
try:
|
||||
@@ -262,17 +340,24 @@ def test_invalid_data(tmpdir):
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"valid_from,valid_from_hr,valid_from_openssh,valid_from_timestamp," +
|
||||
"valid_to,valid_to_hr,valid_to_openssh,valid_to_timestamp," +
|
||||
"validity_string",
|
||||
VALID_TIME_PARAMETERS
|
||||
"valid_from,valid_from_hr,valid_from_openssh,valid_from_timestamp,"
|
||||
+ "valid_to,valid_to_hr,valid_to_openssh,valid_to_timestamp,"
|
||||
+ "validity_string",
|
||||
VALID_TIME_PARAMETERS,
|
||||
)
|
||||
def test_valid_time_parameters(valid_from, valid_from_hr, valid_from_openssh, valid_from_timestamp,
|
||||
valid_to, valid_to_hr, valid_to_openssh, valid_to_timestamp,
|
||||
validity_string):
|
||||
def test_valid_time_parameters(
|
||||
valid_from,
|
||||
valid_from_hr,
|
||||
valid_from_openssh,
|
||||
valid_from_timestamp,
|
||||
valid_to,
|
||||
valid_to_hr,
|
||||
valid_to_openssh,
|
||||
valid_to_timestamp,
|
||||
validity_string,
|
||||
):
|
||||
time_parameters = OpensshCertificateTimeParameters(
|
||||
valid_from=valid_from,
|
||||
valid_to=valid_to
|
||||
valid_from=valid_from, valid_to=valid_to
|
||||
)
|
||||
assert time_parameters.valid_from(date_format="human_readable") == valid_from_hr
|
||||
assert time_parameters.valid_from(date_format="openssh") == valid_from_openssh
|
||||
@@ -296,7 +381,9 @@ def test_valid_validity_test(valid_from, valid_to, valid_at):
|
||||
|
||||
@pytest.mark.parametrize("valid_from,valid_to,valid_at", INVALID_VALIDITY_TEST)
|
||||
def test_invalid_validity_test(valid_from, valid_to, valid_at):
|
||||
assert not OpensshCertificateTimeParameters(valid_from, valid_to).within_range(valid_at)
|
||||
assert not OpensshCertificateTimeParameters(valid_from, valid_to).within_range(
|
||||
valid_at
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("option_string,option_object", VALID_OPTIONS)
|
||||
@@ -311,18 +398,18 @@ def test_invalid_options(option_string):
|
||||
|
||||
|
||||
def test_parse_option_list():
|
||||
critical_options, extensions = parse_option_list(['force-command=/usr/bin/csh'])
|
||||
critical_options, extensions = parse_option_list(["force-command=/usr/bin/csh"])
|
||||
|
||||
critical_option_objects = [
|
||||
OpensshCertificateOption.from_string('force-command=/usr/bin/csh'),
|
||||
OpensshCertificateOption.from_string("force-command=/usr/bin/csh"),
|
||||
]
|
||||
|
||||
extension_objects = [
|
||||
OpensshCertificateOption.from_string('permit-x11-forwarding'),
|
||||
OpensshCertificateOption.from_string('permit-agent-forwarding'),
|
||||
OpensshCertificateOption.from_string('permit-port-forwarding'),
|
||||
OpensshCertificateOption.from_string('permit-user-rc'),
|
||||
OpensshCertificateOption.from_string('permit-pty'),
|
||||
OpensshCertificateOption.from_string("permit-x11-forwarding"),
|
||||
OpensshCertificateOption.from_string("permit-agent-forwarding"),
|
||||
OpensshCertificateOption.from_string("permit-port-forwarding"),
|
||||
OpensshCertificateOption.from_string("permit-user-rc"),
|
||||
OpensshCertificateOption.from_string("permit-pty"),
|
||||
]
|
||||
|
||||
assert set(critical_options) == set(critical_option_objects)
|
||||
@@ -330,11 +417,13 @@ def test_parse_option_list():
|
||||
|
||||
|
||||
def test_parse_option_list_with_directives():
|
||||
critical_options, extensions = parse_option_list(['clear', 'no-pty', 'permit-pty', 'permit-user-rc'])
|
||||
critical_options, extensions = parse_option_list(
|
||||
["clear", "no-pty", "permit-pty", "permit-user-rc"]
|
||||
)
|
||||
|
||||
extension_objects = [
|
||||
OpensshCertificateOption.from_string('permit-user-rc'),
|
||||
OpensshCertificateOption.from_string('permit-pty'),
|
||||
OpensshCertificateOption.from_string("permit-user-rc"),
|
||||
OpensshCertificateOption.from_string("permit-pty"),
|
||||
]
|
||||
|
||||
assert set(critical_options) == set()
|
||||
@@ -342,10 +431,12 @@ def test_parse_option_list_with_directives():
|
||||
|
||||
|
||||
def test_parse_option_list_case_sensitivity():
|
||||
critical_options, extensions = parse_option_list(['CLEAR', 'no-X11-forwarding', 'permit-X11-forwarding'])
|
||||
critical_options, extensions = parse_option_list(
|
||||
["CLEAR", "no-X11-forwarding", "permit-X11-forwarding"]
|
||||
)
|
||||
|
||||
extension_objects = [
|
||||
OpensshCertificateOption.from_string('permit-x11-forwarding'),
|
||||
OpensshCertificateOption.from_string("permit-x11-forwarding"),
|
||||
]
|
||||
|
||||
assert set(critical_options) == set()
|
||||
|
||||
@@ -30,25 +30,25 @@ from ansible_collections.community.crypto.plugins.module_utils.openssh.cryptogra
|
||||
|
||||
DEFAULT_KEY_PARAMS = [
|
||||
(
|
||||
'rsa',
|
||||
"rsa",
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
),
|
||||
(
|
||||
'dsa',
|
||||
"dsa",
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
),
|
||||
(
|
||||
'ecdsa',
|
||||
"ecdsa",
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
),
|
||||
(
|
||||
'ed25519',
|
||||
"ed25519",
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
@@ -57,46 +57,46 @@ DEFAULT_KEY_PARAMS = [
|
||||
|
||||
VALID_USER_KEY_PARAMS = [
|
||||
(
|
||||
'rsa',
|
||||
"rsa",
|
||||
8192,
|
||||
'change_me'.encode('UTF-8'),
|
||||
'comment',
|
||||
"change_me".encode("UTF-8"),
|
||||
"comment",
|
||||
),
|
||||
(
|
||||
'dsa',
|
||||
"dsa",
|
||||
1024,
|
||||
'change_me'.encode('UTF-8'),
|
||||
'comment',
|
||||
"change_me".encode("UTF-8"),
|
||||
"comment",
|
||||
),
|
||||
(
|
||||
'ecdsa',
|
||||
"ecdsa",
|
||||
521,
|
||||
'change_me'.encode('UTF-8'),
|
||||
'comment',
|
||||
"change_me".encode("UTF-8"),
|
||||
"comment",
|
||||
),
|
||||
(
|
||||
'ed25519',
|
||||
"ed25519",
|
||||
256,
|
||||
'change_me'.encode('UTF-8'),
|
||||
'comment',
|
||||
"change_me".encode("UTF-8"),
|
||||
"comment",
|
||||
),
|
||||
]
|
||||
|
||||
INVALID_USER_KEY_PARAMS = [
|
||||
(
|
||||
'dne',
|
||||
"dne",
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
),
|
||||
(
|
||||
'rsa',
|
||||
"rsa",
|
||||
None,
|
||||
[1, 2, 3],
|
||||
'comment',
|
||||
"comment",
|
||||
),
|
||||
(
|
||||
'ecdsa',
|
||||
"ecdsa",
|
||||
None,
|
||||
None,
|
||||
[1, 2, 3],
|
||||
@@ -105,31 +105,31 @@ INVALID_USER_KEY_PARAMS = [
|
||||
|
||||
INVALID_KEY_SIZES = [
|
||||
(
|
||||
'rsa',
|
||||
"rsa",
|
||||
1023,
|
||||
None,
|
||||
None,
|
||||
),
|
||||
(
|
||||
'rsa',
|
||||
"rsa",
|
||||
16385,
|
||||
None,
|
||||
None,
|
||||
),
|
||||
(
|
||||
'dsa',
|
||||
"dsa",
|
||||
256,
|
||||
None,
|
||||
None,
|
||||
),
|
||||
(
|
||||
'ecdsa',
|
||||
"ecdsa",
|
||||
1024,
|
||||
None,
|
||||
None,
|
||||
),
|
||||
(
|
||||
'ed25519',
|
||||
"ed25519",
|
||||
1024,
|
||||
None,
|
||||
None,
|
||||
@@ -143,16 +143,20 @@ def test_default_key_params(keytype, size, passphrase, comment):
|
||||
result = True
|
||||
|
||||
default_sizes = {
|
||||
'rsa': 2048,
|
||||
'dsa': 1024,
|
||||
'ecdsa': 256,
|
||||
'ed25519': 256,
|
||||
"rsa": 2048,
|
||||
"dsa": 1024,
|
||||
"ecdsa": 256,
|
||||
"ed25519": 256,
|
||||
}
|
||||
|
||||
default_comment = "%s@%s" % (getuser(), gethostname())
|
||||
pair = OpensshKeypair.generate(keytype=keytype, size=size, passphrase=passphrase, comment=comment)
|
||||
pair = OpensshKeypair.generate(
|
||||
keytype=keytype, size=size, passphrase=passphrase, comment=comment
|
||||
)
|
||||
try:
|
||||
pair = OpensshKeypair.generate(keytype=keytype, size=size, passphrase=passphrase, comment=comment)
|
||||
pair = OpensshKeypair.generate(
|
||||
keytype=keytype, size=size, passphrase=passphrase, comment=comment
|
||||
)
|
||||
if pair.size != default_sizes[pair.key_type] or pair.comment != default_comment:
|
||||
result = False
|
||||
except Exception as e:
|
||||
@@ -168,7 +172,9 @@ def test_valid_user_key_params(keytype, size, passphrase, comment):
|
||||
result = True
|
||||
|
||||
try:
|
||||
pair = OpensshKeypair.generate(keytype=keytype, size=size, passphrase=passphrase, comment=comment)
|
||||
pair = OpensshKeypair.generate(
|
||||
keytype=keytype, size=size, passphrase=passphrase, comment=comment
|
||||
)
|
||||
if pair.key_type != keytype or pair.size != size or pair.comment != comment:
|
||||
result = False
|
||||
except Exception as e:
|
||||
@@ -184,7 +190,9 @@ def test_invalid_user_key_params(keytype, size, passphrase, comment):
|
||||
result = False
|
||||
|
||||
try:
|
||||
OpensshKeypair.generate(keytype=keytype, size=size, passphrase=passphrase, comment=comment)
|
||||
OpensshKeypair.generate(
|
||||
keytype=keytype, size=size, passphrase=passphrase, comment=comment
|
||||
)
|
||||
except (InvalidCommentError, InvalidKeyTypeError, InvalidPassphraseError):
|
||||
result = True
|
||||
except Exception as e:
|
||||
@@ -200,7 +208,9 @@ def test_invalid_key_sizes(keytype, size, passphrase, comment):
|
||||
result = False
|
||||
|
||||
try:
|
||||
OpensshKeypair.generate(keytype=keytype, size=size, passphrase=passphrase, comment=comment)
|
||||
OpensshKeypair.generate(
|
||||
keytype=keytype, size=size, passphrase=passphrase, comment=comment
|
||||
)
|
||||
except InvalidKeySizeError:
|
||||
result = True
|
||||
except Exception as e:
|
||||
@@ -221,7 +231,10 @@ def test_valid_comment_update():
|
||||
print(e)
|
||||
pass
|
||||
|
||||
assert pair.comment == new_comment and pair.public_key.split(b' ', 2)[2].decode() == new_comment
|
||||
assert (
|
||||
pair.comment == new_comment
|
||||
and pair.public_key.split(b" ", 2)[2].decode() == new_comment
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.skipif(not HAS_OPENSSH_SUPPORT, reason="requires cryptography")
|
||||
@@ -242,7 +255,7 @@ def test_invalid_comment_update():
|
||||
def test_valid_passphrase_update():
|
||||
result = False
|
||||
|
||||
passphrase = "change_me".encode('UTF-8')
|
||||
passphrase = "change_me".encode("UTF-8")
|
||||
|
||||
try:
|
||||
tmpdir = mkdtemp()
|
||||
@@ -254,7 +267,7 @@ def test_valid_passphrase_update():
|
||||
with open(keyfilename, "w+b") as keyfile:
|
||||
keyfile.write(pair1.private_key)
|
||||
|
||||
with open(keyfilename + '.pub', "w+b") as pubkeyfile:
|
||||
with open(keyfilename + ".pub", "w+b") as pubkeyfile:
|
||||
pubkeyfile.write(pair1.public_key)
|
||||
|
||||
pair2 = OpensshKeypair.load(path=keyfilename, passphrase=passphrase)
|
||||
@@ -264,8 +277,8 @@ def test_valid_passphrase_update():
|
||||
finally:
|
||||
if os.path.exists(keyfilename):
|
||||
remove(keyfilename)
|
||||
if os.path.exists(keyfilename + '.pub'):
|
||||
remove(keyfilename + '.pub')
|
||||
if os.path.exists(keyfilename + ".pub"):
|
||||
remove(keyfilename + ".pub")
|
||||
if os.path.exists(tmpdir):
|
||||
rmdir(tmpdir)
|
||||
|
||||
@@ -299,7 +312,7 @@ def test_invalid_privatekey():
|
||||
with open(keyfilename, "w+b") as keyfile:
|
||||
keyfile.write(pair.private_key[1:])
|
||||
|
||||
with open(keyfilename + '.pub', "w+b") as pubkeyfile:
|
||||
with open(keyfilename + ".pub", "w+b") as pubkeyfile:
|
||||
pubkeyfile.write(pair.public_key)
|
||||
|
||||
OpensshKeypair.load(path=keyfilename)
|
||||
@@ -308,8 +321,8 @@ def test_invalid_privatekey():
|
||||
finally:
|
||||
if os.path.exists(keyfilename):
|
||||
remove(keyfilename)
|
||||
if os.path.exists(keyfilename + '.pub'):
|
||||
remove(keyfilename + '.pub')
|
||||
if os.path.exists(keyfilename + ".pub"):
|
||||
remove(keyfilename + ".pub")
|
||||
if os.path.exists(tmpdir):
|
||||
rmdir(tmpdir)
|
||||
|
||||
@@ -330,7 +343,7 @@ def test_mismatched_keypair():
|
||||
with open(keyfilename, "w+b") as keyfile:
|
||||
keyfile.write(pair1.private_key)
|
||||
|
||||
with open(keyfilename + '.pub', "w+b") as pubkeyfile:
|
||||
with open(keyfilename + ".pub", "w+b") as pubkeyfile:
|
||||
pubkeyfile.write(pair2.public_key)
|
||||
|
||||
OpensshKeypair.load(path=keyfilename)
|
||||
@@ -339,8 +352,8 @@ def test_mismatched_keypair():
|
||||
finally:
|
||||
if os.path.exists(keyfilename):
|
||||
remove(keyfilename)
|
||||
if os.path.exists(keyfilename + '.pub'):
|
||||
remove(keyfilename + '.pub')
|
||||
if os.path.exists(keyfilename + ".pub"):
|
||||
remove(keyfilename + ".pub")
|
||||
if os.path.exists(tmpdir):
|
||||
rmdir(tmpdir)
|
||||
|
||||
@@ -350,54 +363,62 @@ def test_mismatched_keypair():
|
||||
@pytest.mark.skipif(not HAS_OPENSSH_SUPPORT, reason="requires cryptography")
|
||||
def test_keypair_comparison():
|
||||
assert OpensshKeypair.generate() != OpensshKeypair.generate()
|
||||
assert OpensshKeypair.generate() != OpensshKeypair.generate(keytype='dsa')
|
||||
assert OpensshKeypair.generate() != OpensshKeypair.generate(keytype='ed25519')
|
||||
assert OpensshKeypair.generate(keytype='ed25519') != OpensshKeypair.generate(keytype='ed25519')
|
||||
assert OpensshKeypair.generate() != OpensshKeypair.generate(keytype="dsa")
|
||||
assert OpensshKeypair.generate() != OpensshKeypair.generate(keytype="ed25519")
|
||||
assert OpensshKeypair.generate(keytype="ed25519") != OpensshKeypair.generate(
|
||||
keytype="ed25519"
|
||||
)
|
||||
try:
|
||||
tmpdir = mkdtemp()
|
||||
|
||||
keys = {
|
||||
'rsa': {
|
||||
'pair': OpensshKeypair.generate(),
|
||||
'filename': os.path.join(tmpdir, "id_rsa"),
|
||||
"rsa": {
|
||||
"pair": OpensshKeypair.generate(),
|
||||
"filename": os.path.join(tmpdir, "id_rsa"),
|
||||
},
|
||||
'dsa': {
|
||||
'pair': OpensshKeypair.generate(keytype='dsa', passphrase='change_me'.encode('UTF-8')),
|
||||
'filename': os.path.join(tmpdir, "id_dsa"),
|
||||
"dsa": {
|
||||
"pair": OpensshKeypair.generate(
|
||||
keytype="dsa", passphrase="change_me".encode("UTF-8")
|
||||
),
|
||||
"filename": os.path.join(tmpdir, "id_dsa"),
|
||||
},
|
||||
"ed25519": {
|
||||
"pair": OpensshKeypair.generate(keytype="ed25519"),
|
||||
"filename": os.path.join(tmpdir, "id_ed25519"),
|
||||
},
|
||||
'ed25519': {
|
||||
'pair': OpensshKeypair.generate(keytype='ed25519'),
|
||||
'filename': os.path.join(tmpdir, "id_ed25519"),
|
||||
}
|
||||
}
|
||||
|
||||
for v in keys.values():
|
||||
with open(v['filename'], "w+b") as keyfile:
|
||||
keyfile.write(v['pair'].private_key)
|
||||
with open(v['filename'] + '.pub', "w+b") as pubkeyfile:
|
||||
pubkeyfile.write(v['pair'].public_key)
|
||||
with open(v["filename"], "w+b") as keyfile:
|
||||
keyfile.write(v["pair"].private_key)
|
||||
with open(v["filename"] + ".pub", "w+b") as pubkeyfile:
|
||||
pubkeyfile.write(v["pair"].public_key)
|
||||
|
||||
assert keys['rsa']['pair'] == OpensshKeypair.load(path=keys['rsa']['filename'])
|
||||
assert keys["rsa"]["pair"] == OpensshKeypair.load(path=keys["rsa"]["filename"])
|
||||
|
||||
loaded_dsa_key = OpensshKeypair.load(path=keys['dsa']['filename'], passphrase='change_me'.encode('UTF-8'))
|
||||
assert keys['dsa']['pair'] == loaded_dsa_key
|
||||
loaded_dsa_key = OpensshKeypair.load(
|
||||
path=keys["dsa"]["filename"], passphrase="change_me".encode("UTF-8")
|
||||
)
|
||||
assert keys["dsa"]["pair"] == loaded_dsa_key
|
||||
|
||||
loaded_dsa_key.update_passphrase('change_me_again'.encode('UTF-8'))
|
||||
assert keys['dsa']['pair'] != loaded_dsa_key
|
||||
loaded_dsa_key.update_passphrase("change_me_again".encode("UTF-8"))
|
||||
assert keys["dsa"]["pair"] != loaded_dsa_key
|
||||
|
||||
loaded_dsa_key.update_passphrase('change_me'.encode('UTF-8'))
|
||||
assert keys['dsa']['pair'] == loaded_dsa_key
|
||||
loaded_dsa_key.update_passphrase("change_me".encode("UTF-8"))
|
||||
assert keys["dsa"]["pair"] == loaded_dsa_key
|
||||
|
||||
loaded_dsa_key.comment = "comment"
|
||||
assert keys['dsa']['pair'] != loaded_dsa_key
|
||||
assert keys["dsa"]["pair"] != loaded_dsa_key
|
||||
|
||||
assert keys['ed25519']['pair'] == OpensshKeypair.load(path=keys['ed25519']['filename'])
|
||||
assert keys["ed25519"]["pair"] == OpensshKeypair.load(
|
||||
path=keys["ed25519"]["filename"]
|
||||
)
|
||||
finally:
|
||||
for v in keys.values():
|
||||
if os.path.exists(v['filename']):
|
||||
remove(v['filename'])
|
||||
if os.path.exists(v['filename'] + '.pub'):
|
||||
remove(v['filename'] + '.pub')
|
||||
if os.path.exists(v["filename"]):
|
||||
remove(v["filename"])
|
||||
if os.path.exists(v["filename"] + ".pub"):
|
||||
remove(v["filename"] + ".pub")
|
||||
if os.path.exists(tmpdir):
|
||||
rmdir(tmpdir)
|
||||
assert OpensshKeypair.generate() != []
|
||||
|
||||
@@ -20,13 +20,8 @@ from ansible_collections.community.crypto.plugins.module_utils.openssh.utils imp
|
||||
SSH_VERSION_STRING = "OpenSSH_7.9p1, OpenSSL 1.1.0i-fips 14 Aug 2018"
|
||||
SSH_VERSION_NUMBER = "7.9"
|
||||
|
||||
VALID_BOOLEAN = [
|
||||
True,
|
||||
False
|
||||
]
|
||||
INVALID_BOOLEAN = [
|
||||
0x02
|
||||
]
|
||||
VALID_BOOLEAN = [True, False]
|
||||
INVALID_BOOLEAN = [0x02]
|
||||
VALID_UINT32 = [
|
||||
0x00,
|
||||
0x01,
|
||||
@@ -48,7 +43,7 @@ INVALID_UINT64 = [
|
||||
-1,
|
||||
]
|
||||
VALID_STRING = [
|
||||
b'test string',
|
||||
b"test string",
|
||||
]
|
||||
INVALID_STRING = [
|
||||
[],
|
||||
@@ -56,10 +51,10 @@ INVALID_STRING = [
|
||||
# See https://datatracker.ietf.org/doc/html/rfc4251#section-5 for examples source
|
||||
VALID_MPINT = [
|
||||
0x00,
|
||||
0x9a378f9b2e332a7,
|
||||
0x9A378F9B2E332A7,
|
||||
0x80,
|
||||
-0x1234,
|
||||
-0xdeadbeef,
|
||||
-0xDEADBEEF,
|
||||
# Additional large int test
|
||||
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,
|
||||
]
|
||||
@@ -107,7 +102,10 @@ def test_invalid_uint64(uint64):
|
||||
|
||||
@pytest.mark.parametrize("ssh_string", VALID_STRING)
|
||||
def test_valid_string(ssh_string):
|
||||
assert OpensshParser(_OpensshWriter().string(ssh_string).bytes()).string() == ssh_string
|
||||
assert (
|
||||
OpensshParser(_OpensshWriter().string(ssh_string).bytes()).string()
|
||||
== ssh_string
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("ssh_string", INVALID_STRING)
|
||||
@@ -128,7 +126,7 @@ def test_invalid_mpint(mpint):
|
||||
|
||||
|
||||
def test_valid_seek():
|
||||
buffer = bytearray(b'buffer')
|
||||
buffer = bytearray(b"buffer")
|
||||
parser = OpensshParser(buffer)
|
||||
parser.seek(len(buffer))
|
||||
assert parser.remaining_bytes() == 0
|
||||
@@ -137,7 +135,7 @@ def test_valid_seek():
|
||||
|
||||
|
||||
def test_invalid_seek():
|
||||
buffer = b'buffer'
|
||||
buffer = b"buffer"
|
||||
parser = OpensshParser(buffer)
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
@@ -148,5 +146,5 @@ def test_invalid_seek():
|
||||
|
||||
|
||||
def test_writer_bytes():
|
||||
buffer = bytearray(b'buffer')
|
||||
buffer = bytearray(b"buffer")
|
||||
assert _OpensshWriter(buffer).bytes() == buffer
|
||||
|
||||
@@ -39,259 +39,319 @@ def cartesian_product(list1, list2):
|
||||
result = []
|
||||
for item1 in list1:
|
||||
if not is_sequence(item1):
|
||||
item1 = (item1, )
|
||||
item1 = (item1,)
|
||||
elif not isinstance(item1, tuple):
|
||||
item1 = tuple(item1)
|
||||
for item2 in list2:
|
||||
if not is_sequence(item2):
|
||||
item2 = (item2, )
|
||||
item2 = (item2,)
|
||||
elif not isinstance(item2, tuple):
|
||||
item2 = tuple(item2)
|
||||
result.append(item1 + item2)
|
||||
return result
|
||||
|
||||
|
||||
TEST_REMOVE_TIMEZONE = cartesian_product(TIMEZONES, [
|
||||
(
|
||||
datetime.datetime(2024, 1, 1, 0, 1, 2, tzinfo=UTC),
|
||||
datetime.datetime(2024, 1, 1, 0, 1, 2),
|
||||
),
|
||||
(
|
||||
datetime.datetime(2024, 1, 1, 0, 1, 2),
|
||||
datetime.datetime(2024, 1, 1, 0, 1, 2),
|
||||
),
|
||||
])
|
||||
TEST_REMOVE_TIMEZONE = cartesian_product(
|
||||
TIMEZONES,
|
||||
[
|
||||
(
|
||||
datetime.datetime(2024, 1, 1, 0, 1, 2, tzinfo=UTC),
|
||||
datetime.datetime(2024, 1, 1, 0, 1, 2),
|
||||
),
|
||||
(
|
||||
datetime.datetime(2024, 1, 1, 0, 1, 2),
|
||||
datetime.datetime(2024, 1, 1, 0, 1, 2),
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
TEST_UTC_TIMEZONE = cartesian_product(TIMEZONES, [
|
||||
(
|
||||
datetime.datetime(2024, 1, 1, 0, 1, 2),
|
||||
datetime.datetime(2024, 1, 1, 0, 1, 2, tzinfo=UTC),
|
||||
),
|
||||
(
|
||||
datetime.datetime(2024, 1, 1, 0, 1, 2, tzinfo=UTC),
|
||||
datetime.datetime(2024, 1, 1, 0, 1, 2, tzinfo=UTC),
|
||||
),
|
||||
])
|
||||
TEST_UTC_TIMEZONE = cartesian_product(
|
||||
TIMEZONES,
|
||||
[
|
||||
(
|
||||
datetime.datetime(2024, 1, 1, 0, 1, 2),
|
||||
datetime.datetime(2024, 1, 1, 0, 1, 2, tzinfo=UTC),
|
||||
),
|
||||
(
|
||||
datetime.datetime(2024, 1, 1, 0, 1, 2, tzinfo=UTC),
|
||||
datetime.datetime(2024, 1, 1, 0, 1, 2, tzinfo=UTC),
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
TEST_EPOCH_SECONDS = cartesian_product(TIMEZONES, [
|
||||
(0, dict(year=1970, day=1, month=1, hour=0, minute=0, second=0, microsecond=0)),
|
||||
(1E-6, dict(year=1970, day=1, month=1, hour=0, minute=0, second=0, microsecond=1)),
|
||||
(1E-3, dict(year=1970, day=1, month=1, hour=0, minute=0, second=0, microsecond=1000)),
|
||||
(3691.2, dict(year=1970, day=1, month=1, hour=1, minute=1, second=31, microsecond=200000)),
|
||||
])
|
||||
TEST_EPOCH_SECONDS = cartesian_product(
|
||||
TIMEZONES,
|
||||
[
|
||||
(0, dict(year=1970, day=1, month=1, hour=0, minute=0, second=0, microsecond=0)),
|
||||
(
|
||||
1e-6,
|
||||
dict(year=1970, day=1, month=1, hour=0, minute=0, second=0, microsecond=1),
|
||||
),
|
||||
(
|
||||
1e-3,
|
||||
dict(
|
||||
year=1970, day=1, month=1, hour=0, minute=0, second=0, microsecond=1000
|
||||
),
|
||||
),
|
||||
(
|
||||
3691.2,
|
||||
dict(
|
||||
year=1970,
|
||||
day=1,
|
||||
month=1,
|
||||
hour=1,
|
||||
minute=1,
|
||||
second=31,
|
||||
microsecond=200000,
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
TEST_EPOCH_TO_SECONDS = cartesian_product(TIMEZONES, [
|
||||
(datetime.datetime(1970, 1, 1, 0, 1, 2, 0), 62),
|
||||
(datetime.datetime(1970, 1, 1, 0, 1, 2, 0, tzinfo=UTC), 62),
|
||||
])
|
||||
TEST_EPOCH_TO_SECONDS = cartesian_product(
|
||||
TIMEZONES,
|
||||
[
|
||||
(datetime.datetime(1970, 1, 1, 0, 1, 2, 0), 62),
|
||||
(datetime.datetime(1970, 1, 1, 0, 1, 2, 0, tzinfo=UTC), 62),
|
||||
],
|
||||
)
|
||||
|
||||
TEST_CONVERT_RELATIVE_TO_DATETIME = cartesian_product(TIMEZONES, [
|
||||
(
|
||||
'+0',
|
||||
False,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||
),
|
||||
(
|
||||
'+1s',
|
||||
False,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC),
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 1),
|
||||
),
|
||||
(
|
||||
'-10w20d30h40m50s',
|
||||
False,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC),
|
||||
datetime.datetime(2023, 10, 1, 17, 19, 10),
|
||||
),
|
||||
(
|
||||
'+0',
|
||||
True,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC),
|
||||
),
|
||||
(
|
||||
'+1s',
|
||||
True,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC),
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 1, tzinfo=UTC),
|
||||
),
|
||||
(
|
||||
'-10w20d30h40m50s',
|
||||
True,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||
datetime.datetime(2023, 10, 1, 17, 19, 10, tzinfo=UTC),
|
||||
),
|
||||
])
|
||||
TEST_CONVERT_RELATIVE_TO_DATETIME = cartesian_product(
|
||||
TIMEZONES,
|
||||
[
|
||||
(
|
||||
"+0",
|
||||
False,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||
),
|
||||
(
|
||||
"+1s",
|
||||
False,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC),
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 1),
|
||||
),
|
||||
(
|
||||
"-10w20d30h40m50s",
|
||||
False,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC),
|
||||
datetime.datetime(2023, 10, 1, 17, 19, 10),
|
||||
),
|
||||
(
|
||||
"+0",
|
||||
True,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC),
|
||||
),
|
||||
(
|
||||
"+1s",
|
||||
True,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC),
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 1, tzinfo=UTC),
|
||||
),
|
||||
(
|
||||
"-10w20d30h40m50s",
|
||||
True,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||
datetime.datetime(2023, 10, 1, 17, 19, 10, tzinfo=UTC),
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
TEST_GET_RELATIVE_TIME_OPTION = cartesian_product(TIMEZONES, [
|
||||
(
|
||||
'+1d2h3m4s',
|
||||
'foo',
|
||||
'cryptography',
|
||||
False,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||
datetime.datetime(2024, 1, 2, 2, 3, 4),
|
||||
),
|
||||
(
|
||||
'-1w10d24h',
|
||||
'foo',
|
||||
'cryptography',
|
||||
False,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||
datetime.datetime(2023, 12, 14, 0, 0, 0),
|
||||
),
|
||||
(
|
||||
'20240102040506Z',
|
||||
'foo',
|
||||
'cryptography',
|
||||
False,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||
datetime.datetime(2024, 1, 2, 4, 5, 6),
|
||||
),
|
||||
(
|
||||
'202401020405Z',
|
||||
'foo',
|
||||
'cryptography',
|
||||
False,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||
datetime.datetime(2024, 1, 2, 4, 5, 0),
|
||||
),
|
||||
(
|
||||
'+1d2h3m4s',
|
||||
'foo',
|
||||
'cryptography',
|
||||
True,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||
datetime.datetime(2024, 1, 2, 2, 3, 4, tzinfo=UTC),
|
||||
),
|
||||
(
|
||||
'-1w10d24h',
|
||||
'foo',
|
||||
'cryptography',
|
||||
True,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||
datetime.datetime(2023, 12, 14, 0, 0, 0, tzinfo=UTC),
|
||||
),
|
||||
(
|
||||
'20240102040506Z',
|
||||
'foo',
|
||||
'cryptography',
|
||||
True,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||
datetime.datetime(2024, 1, 2, 4, 5, 6, tzinfo=UTC),
|
||||
),
|
||||
(
|
||||
'202401020405Z',
|
||||
'foo',
|
||||
'cryptography',
|
||||
True,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||
datetime.datetime(2024, 1, 2, 4, 5, 0, tzinfo=UTC),
|
||||
),
|
||||
(
|
||||
'+1d2h3m4s',
|
||||
'foo',
|
||||
'pyopenssl',
|
||||
False,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||
'20240102020304Z',
|
||||
),
|
||||
(
|
||||
'-1w10d24h',
|
||||
'foo',
|
||||
'pyopenssl',
|
||||
False,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||
'20231214000000Z',
|
||||
),
|
||||
(
|
||||
'20240102040506Z',
|
||||
'foo',
|
||||
'pyopenssl',
|
||||
False,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||
'20240102040506Z',
|
||||
),
|
||||
(
|
||||
'202401020405Z',
|
||||
'foo',
|
||||
'pyopenssl',
|
||||
False,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||
'202401020405Z',
|
||||
),
|
||||
])
|
||||
TEST_GET_RELATIVE_TIME_OPTION = cartesian_product(
|
||||
TIMEZONES,
|
||||
[
|
||||
(
|
||||
"+1d2h3m4s",
|
||||
"foo",
|
||||
"cryptography",
|
||||
False,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||
datetime.datetime(2024, 1, 2, 2, 3, 4),
|
||||
),
|
||||
(
|
||||
"-1w10d24h",
|
||||
"foo",
|
||||
"cryptography",
|
||||
False,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||
datetime.datetime(2023, 12, 14, 0, 0, 0),
|
||||
),
|
||||
(
|
||||
"20240102040506Z",
|
||||
"foo",
|
||||
"cryptography",
|
||||
False,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||
datetime.datetime(2024, 1, 2, 4, 5, 6),
|
||||
),
|
||||
(
|
||||
"202401020405Z",
|
||||
"foo",
|
||||
"cryptography",
|
||||
False,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||
datetime.datetime(2024, 1, 2, 4, 5, 0),
|
||||
),
|
||||
(
|
||||
"+1d2h3m4s",
|
||||
"foo",
|
||||
"cryptography",
|
||||
True,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||
datetime.datetime(2024, 1, 2, 2, 3, 4, tzinfo=UTC),
|
||||
),
|
||||
(
|
||||
"-1w10d24h",
|
||||
"foo",
|
||||
"cryptography",
|
||||
True,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||
datetime.datetime(2023, 12, 14, 0, 0, 0, tzinfo=UTC),
|
||||
),
|
||||
(
|
||||
"20240102040506Z",
|
||||
"foo",
|
||||
"cryptography",
|
||||
True,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||
datetime.datetime(2024, 1, 2, 4, 5, 6, tzinfo=UTC),
|
||||
),
|
||||
(
|
||||
"202401020405Z",
|
||||
"foo",
|
||||
"cryptography",
|
||||
True,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||
datetime.datetime(2024, 1, 2, 4, 5, 0, tzinfo=UTC),
|
||||
),
|
||||
(
|
||||
"+1d2h3m4s",
|
||||
"foo",
|
||||
"pyopenssl",
|
||||
False,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||
"20240102020304Z",
|
||||
),
|
||||
(
|
||||
"-1w10d24h",
|
||||
"foo",
|
||||
"pyopenssl",
|
||||
False,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||
"20231214000000Z",
|
||||
),
|
||||
(
|
||||
"20240102040506Z",
|
||||
"foo",
|
||||
"pyopenssl",
|
||||
False,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||
"20240102040506Z",
|
||||
),
|
||||
(
|
||||
"202401020405Z",
|
||||
"foo",
|
||||
"pyopenssl",
|
||||
False,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||
"202401020405Z",
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
if sys.version_info >= (3, 5):
|
||||
ONE_HOUR_PLUS = datetime.timezone(datetime.timedelta(hours=1))
|
||||
|
||||
TEST_REMOVE_TIMEZONE.extend(cartesian_product(TIMEZONES, [
|
||||
(
|
||||
datetime.datetime(2024, 1, 1, 0, 1, 2, tzinfo=ONE_HOUR_PLUS),
|
||||
datetime.datetime(2023, 12, 31, 23, 1, 2),
|
||||
),
|
||||
]))
|
||||
TEST_UTC_TIMEZONE.extend(cartesian_product(TIMEZONES, [
|
||||
(
|
||||
datetime.datetime(2024, 1, 1, 0, 1, 2, tzinfo=ONE_HOUR_PLUS),
|
||||
datetime.datetime(2023, 12, 31, 23, 1, 2, tzinfo=UTC),
|
||||
),
|
||||
]))
|
||||
TEST_EPOCH_TO_SECONDS.extend(cartesian_product(TIMEZONES, [
|
||||
(datetime.datetime(1970, 1, 1, 0, 1, 2, 0, tzinfo=ONE_HOUR_PLUS), 62 - 3600),
|
||||
]))
|
||||
TEST_GET_RELATIVE_TIME_OPTION.extend(cartesian_product(TIMEZONES, [
|
||||
(
|
||||
'20240102040506+0100',
|
||||
'foo',
|
||||
'cryptography',
|
||||
False,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||
datetime.datetime(2024, 1, 2, 3, 5, 6),
|
||||
),
|
||||
(
|
||||
'202401020405+0100',
|
||||
'foo',
|
||||
'cryptography',
|
||||
False,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||
datetime.datetime(2024, 1, 2, 3, 5, 0),
|
||||
),
|
||||
(
|
||||
'20240102040506+0100',
|
||||
'foo',
|
||||
'cryptography',
|
||||
True,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||
datetime.datetime(2024, 1, 2, 3, 5, 6, tzinfo=UTC),
|
||||
),
|
||||
(
|
||||
'202401020405+0100',
|
||||
'foo',
|
||||
'cryptography',
|
||||
True,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||
datetime.datetime(2024, 1, 2, 3, 5, 0, tzinfo=UTC),
|
||||
),
|
||||
(
|
||||
'20240102040506+0100',
|
||||
'foo',
|
||||
'pyopenssl',
|
||||
False,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||
'20240102040506+0100',
|
||||
),
|
||||
(
|
||||
'202401020405+0100',
|
||||
'foo',
|
||||
'pyopenssl',
|
||||
False,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||
'202401020405+0100',
|
||||
),
|
||||
]))
|
||||
TEST_REMOVE_TIMEZONE.extend(
|
||||
cartesian_product(
|
||||
TIMEZONES,
|
||||
[
|
||||
(
|
||||
datetime.datetime(2024, 1, 1, 0, 1, 2, tzinfo=ONE_HOUR_PLUS),
|
||||
datetime.datetime(2023, 12, 31, 23, 1, 2),
|
||||
),
|
||||
],
|
||||
)
|
||||
)
|
||||
TEST_UTC_TIMEZONE.extend(
|
||||
cartesian_product(
|
||||
TIMEZONES,
|
||||
[
|
||||
(
|
||||
datetime.datetime(2024, 1, 1, 0, 1, 2, tzinfo=ONE_HOUR_PLUS),
|
||||
datetime.datetime(2023, 12, 31, 23, 1, 2, tzinfo=UTC),
|
||||
),
|
||||
],
|
||||
)
|
||||
)
|
||||
TEST_EPOCH_TO_SECONDS.extend(
|
||||
cartesian_product(
|
||||
TIMEZONES,
|
||||
[
|
||||
(
|
||||
datetime.datetime(1970, 1, 1, 0, 1, 2, 0, tzinfo=ONE_HOUR_PLUS),
|
||||
62 - 3600,
|
||||
),
|
||||
],
|
||||
)
|
||||
)
|
||||
TEST_GET_RELATIVE_TIME_OPTION.extend(
|
||||
cartesian_product(
|
||||
TIMEZONES,
|
||||
[
|
||||
(
|
||||
"20240102040506+0100",
|
||||
"foo",
|
||||
"cryptography",
|
||||
False,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||
datetime.datetime(2024, 1, 2, 3, 5, 6),
|
||||
),
|
||||
(
|
||||
"202401020405+0100",
|
||||
"foo",
|
||||
"cryptography",
|
||||
False,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||
datetime.datetime(2024, 1, 2, 3, 5, 0),
|
||||
),
|
||||
(
|
||||
"20240102040506+0100",
|
||||
"foo",
|
||||
"cryptography",
|
||||
True,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||
datetime.datetime(2024, 1, 2, 3, 5, 6, tzinfo=UTC),
|
||||
),
|
||||
(
|
||||
"202401020405+0100",
|
||||
"foo",
|
||||
"cryptography",
|
||||
True,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||
datetime.datetime(2024, 1, 2, 3, 5, 0, tzinfo=UTC),
|
||||
),
|
||||
(
|
||||
"20240102040506+0100",
|
||||
"foo",
|
||||
"pyopenssl",
|
||||
False,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||
"20240102040506+0100",
|
||||
),
|
||||
(
|
||||
"202401020405+0100",
|
||||
"foo",
|
||||
"pyopenssl",
|
||||
False,
|
||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||
"202401020405+0100",
|
||||
),
|
||||
],
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("timezone, input, expected", TEST_REMOVE_TIMEZONE)
|
||||
@@ -338,7 +398,7 @@ def test_epoch_seconds(timezone, seconds, timestamp):
|
||||
ts_wo_tz = datetime.datetime(**timestamp)
|
||||
assert seconds == get_epoch_seconds(ts_wo_tz)
|
||||
timestamp_w_tz = dict(timestamp)
|
||||
timestamp_w_tz['tzinfo'] = UTC
|
||||
timestamp_w_tz["tzinfo"] = UTC
|
||||
ts_w_tz = datetime.datetime(**timestamp_w_tz)
|
||||
assert seconds == get_epoch_seconds(ts_w_tz)
|
||||
output_1 = from_epoch_seconds(seconds, with_timezone=False)
|
||||
@@ -353,15 +413,33 @@ def test_epoch_to_seconds(timezone, timestamp, expected_seconds):
|
||||
assert expected_seconds == get_epoch_seconds(timestamp)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("timezone, relative_time_string, with_timezone, now, expected", TEST_CONVERT_RELATIVE_TO_DATETIME)
|
||||
def test_convert_relative_to_datetime(timezone, relative_time_string, with_timezone, now, expected):
|
||||
@pytest.mark.parametrize(
|
||||
"timezone, relative_time_string, with_timezone, now, expected",
|
||||
TEST_CONVERT_RELATIVE_TO_DATETIME,
|
||||
)
|
||||
def test_convert_relative_to_datetime(
|
||||
timezone, relative_time_string, with_timezone, now, expected
|
||||
):
|
||||
with freeze_time("2024-02-03 04:05:06", tz_offset=timezone):
|
||||
output = convert_relative_to_datetime(relative_time_string, with_timezone=with_timezone, now=now)
|
||||
output = convert_relative_to_datetime(
|
||||
relative_time_string, with_timezone=with_timezone, now=now
|
||||
)
|
||||
assert expected == output
|
||||
|
||||
|
||||
@pytest.mark.parametrize("timezone, input_string, input_name, backend, with_timezone, now, expected", TEST_GET_RELATIVE_TIME_OPTION)
|
||||
def test_get_relative_time_option(timezone, input_string, input_name, backend, with_timezone, now, expected):
|
||||
@pytest.mark.parametrize(
|
||||
"timezone, input_string, input_name, backend, with_timezone, now, expected",
|
||||
TEST_GET_RELATIVE_TIME_OPTION,
|
||||
)
|
||||
def test_get_relative_time_option(
|
||||
timezone, input_string, input_name, backend, with_timezone, now, expected
|
||||
):
|
||||
with freeze_time("2024-02-03 04:05:06", tz_offset=timezone):
|
||||
output = get_relative_time_option(input_string, input_name, backend=backend, with_timezone=with_timezone, now=now)
|
||||
output = get_relative_time_option(
|
||||
input_string,
|
||||
input_name,
|
||||
backend=backend,
|
||||
with_timezone=with_timezone,
|
||||
now=now,
|
||||
)
|
||||
assert expected == output
|
||||
|
||||
@@ -25,11 +25,13 @@ class DummyModule(object):
|
||||
|
||||
# ===== Handler & CryptHandler methods tests =====
|
||||
|
||||
|
||||
def test_generate_luks_name(monkeypatch):
|
||||
module = DummyModule()
|
||||
module.params["passphrase_encoding"] = "text"
|
||||
monkeypatch.setattr(luks_device.Handler, "_run_command",
|
||||
lambda x, y: [0, "UUID", ""])
|
||||
monkeypatch.setattr(
|
||||
luks_device.Handler, "_run_command", lambda x, y: [0, "UUID", ""]
|
||||
)
|
||||
crypt = luks_device.CryptHandler(module)
|
||||
assert crypt.generate_luks_name("/dev/dummy") == "luks-UUID"
|
||||
|
||||
@@ -37,8 +39,11 @@ def test_generate_luks_name(monkeypatch):
|
||||
def test_get_container_name_by_device(monkeypatch):
|
||||
module = DummyModule()
|
||||
module.params["passphrase_encoding"] = "text"
|
||||
monkeypatch.setattr(luks_device.Handler, "_run_command",
|
||||
lambda x, y: [0, "crypt container_name", ""])
|
||||
monkeypatch.setattr(
|
||||
luks_device.Handler,
|
||||
"_run_command",
|
||||
lambda x, y: [0, "crypt container_name", ""],
|
||||
)
|
||||
crypt = luks_device.CryptHandler(module)
|
||||
assert crypt.get_container_name_by_device("/dev/dummy") == "container_name"
|
||||
|
||||
@@ -46,8 +51,11 @@ def test_get_container_name_by_device(monkeypatch):
|
||||
def test_get_container_device_by_name(monkeypatch):
|
||||
module = DummyModule()
|
||||
module.params["passphrase_encoding"] = "text"
|
||||
monkeypatch.setattr(luks_device.Handler, "_run_command",
|
||||
lambda x, y: [0, "device: /dev/luksdevice", ""])
|
||||
monkeypatch.setattr(
|
||||
luks_device.Handler,
|
||||
"_run_command",
|
||||
lambda x, y: [0, "device: /dev/luksdevice", ""],
|
||||
)
|
||||
crypt = luks_device.CryptHandler(module)
|
||||
assert crypt.get_container_device_by_name("dummy") == "/dev/luksdevice"
|
||||
|
||||
@@ -60,15 +68,11 @@ def test_run_luks_remove(monkeypatch):
|
||||
|
||||
module = DummyModule()
|
||||
module.params["passphrase_encoding"] = "text"
|
||||
monkeypatch.setattr(luks_device.CryptHandler,
|
||||
"get_container_name_by_device",
|
||||
lambda x, y: None)
|
||||
monkeypatch.setattr(luks_device.Handler,
|
||||
"_run_command",
|
||||
run_command_check)
|
||||
monkeypatch.setattr(luks_device,
|
||||
"wipe_luks_headers",
|
||||
lambda device: True)
|
||||
monkeypatch.setattr(
|
||||
luks_device.CryptHandler, "get_container_name_by_device", lambda x, y: None
|
||||
)
|
||||
monkeypatch.setattr(luks_device.Handler, "_run_command", run_command_check)
|
||||
monkeypatch.setattr(luks_device, "wipe_luks_headers", lambda device: True)
|
||||
crypt = luks_device.CryptHandler(module)
|
||||
crypt.run_luks_remove("dummy")
|
||||
|
||||
@@ -95,14 +99,16 @@ LUKS_CREATE_DATA = (
|
||||
("dummy", None, "corge", "present", True, None, "dummy", "dummy", False),
|
||||
("dummy", "key", None, "present", False, None, None, None, True),
|
||||
("dummy", "key", None, "present", False, None, None, "dummy", True),
|
||||
("dummy", "key", None, "present", False, None, "dummy", None, True))
|
||||
("dummy", "key", None, "present", False, None, "dummy", None, True),
|
||||
)
|
||||
|
||||
# device, state, is_luks, expected
|
||||
LUKS_REMOVE_DATA = (
|
||||
("dummy", "absent", True, True),
|
||||
(None, "absent", True, False),
|
||||
("dummy", "present", True, False),
|
||||
("dummy", "absent", False, False))
|
||||
("dummy", "absent", False, False),
|
||||
)
|
||||
|
||||
# device, key, passphrase, state, name, name_by_dev, expected
|
||||
LUKS_OPEN_DATA = (
|
||||
@@ -121,7 +127,8 @@ LUKS_OPEN_DATA = (
|
||||
(None, None, "quux", "opened", "name", None, False),
|
||||
("dummy", None, None, "opened", "name", None, False),
|
||||
("dummy", None, "quuz", "opened", "name", "name", False),
|
||||
("dummy", None, "corge", "opened", "beer", "name", "exception"))
|
||||
("dummy", None, "corge", "opened", "beer", "name", "exception"),
|
||||
)
|
||||
|
||||
# device, dev_by_name, name, name_by_dev, state, label, expected
|
||||
LUKS_CLOSE_DATA = (
|
||||
@@ -131,7 +138,8 @@ LUKS_CLOSE_DATA = (
|
||||
("dummy", "dummy", "name", "name", "closed", None, True),
|
||||
(None, "dummy", "name", "name", "closed", None, True),
|
||||
("dummy", "dummy", None, "name", "closed", None, True),
|
||||
(None, "dummy", None, "name", "closed", None, False))
|
||||
(None, "dummy", None, "name", "closed", None, False),
|
||||
)
|
||||
|
||||
# device, key, passphrase, new_key, new_passphrase, state, label, expected
|
||||
LUKS_ADD_KEY_DATA = (
|
||||
@@ -150,7 +158,8 @@ LUKS_ADD_KEY_DATA = (
|
||||
("dummy", "key", None, None, None, "present", None, False),
|
||||
("dummy", "key", None, None, "new_pass", "absent", None, "exception"),
|
||||
("dummy", None, "pass", None, "new_pass", "present", None, True),
|
||||
(None, None, "pass", None, "new_pass", "present", "labelName", True))
|
||||
(None, None, "pass", None, "new_pass", "present", "labelName", True),
|
||||
)
|
||||
|
||||
# device, remove_key, remove_passphrase, state, label, expected
|
||||
LUKS_REMOVE_KEY_DATA = (
|
||||
@@ -163,15 +172,26 @@ LUKS_REMOVE_KEY_DATA = (
|
||||
(None, None, "foo", None, "present", None, False),
|
||||
(None, None, "foo", None, "present", "labelName", True),
|
||||
("dummy", None, None, None, "present", None, False),
|
||||
("dummy", None, "foo", None, "absent", None, "exception"))
|
||||
("dummy", None, "foo", None, "absent", None, "exception"),
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("device, keyfile, passphrase, state, is_luks, " +
|
||||
"label, cipher, hash_, expected",
|
||||
((d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8])
|
||||
for d in LUKS_CREATE_DATA))
|
||||
def test_luks_create(device, keyfile, passphrase, state, is_luks, label, cipher, hash_,
|
||||
expected, monkeypatch):
|
||||
@pytest.mark.parametrize(
|
||||
"device, keyfile, passphrase, state, is_luks, " + "label, cipher, hash_, expected",
|
||||
((d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8]) for d in LUKS_CREATE_DATA),
|
||||
)
|
||||
def test_luks_create(
|
||||
device,
|
||||
keyfile,
|
||||
passphrase,
|
||||
state,
|
||||
is_luks,
|
||||
label,
|
||||
cipher,
|
||||
hash_,
|
||||
expected,
|
||||
monkeypatch,
|
||||
):
|
||||
module = DummyModule()
|
||||
|
||||
module.params["device"] = device
|
||||
@@ -183,12 +203,14 @@ def test_luks_create(device, keyfile, passphrase, state, is_luks, label, cipher,
|
||||
module.params["cipher"] = cipher
|
||||
module.params["hash"] = hash_
|
||||
|
||||
monkeypatch.setattr(luks_device.CryptHandler, "is_luks",
|
||||
lambda x, y: is_luks)
|
||||
monkeypatch.setattr(luks_device.CryptHandler, "is_luks", lambda x, y: is_luks)
|
||||
crypt = luks_device.CryptHandler(module)
|
||||
if device is None:
|
||||
monkeypatch.setattr(luks_device.Handler, "get_device_by_label",
|
||||
lambda x, y: [0, "/dev/dummy", ""])
|
||||
monkeypatch.setattr(
|
||||
luks_device.Handler,
|
||||
"get_device_by_label",
|
||||
lambda x, y: [0, "/dev/dummy", ""],
|
||||
)
|
||||
try:
|
||||
conditions = luks_device.ConditionsHandler(module, crypt)
|
||||
assert conditions.luks_create() == expected
|
||||
@@ -196,9 +218,10 @@ def test_luks_create(device, keyfile, passphrase, state, is_luks, label, cipher,
|
||||
assert expected == "exception"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("device, state, is_luks, expected",
|
||||
((d[0], d[1], d[2], d[3])
|
||||
for d in LUKS_REMOVE_DATA))
|
||||
@pytest.mark.parametrize(
|
||||
"device, state, is_luks, expected",
|
||||
((d[0], d[1], d[2], d[3]) for d in LUKS_REMOVE_DATA),
|
||||
)
|
||||
def test_luks_remove(device, state, is_luks, expected, monkeypatch):
|
||||
module = DummyModule()
|
||||
|
||||
@@ -206,8 +229,7 @@ def test_luks_remove(device, state, is_luks, expected, monkeypatch):
|
||||
module.params["passphrase_encoding"] = "text"
|
||||
module.params["state"] = state
|
||||
|
||||
monkeypatch.setattr(luks_device.CryptHandler, "is_luks",
|
||||
lambda x, y: is_luks)
|
||||
monkeypatch.setattr(luks_device.CryptHandler, "is_luks", lambda x, y: is_luks)
|
||||
crypt = luks_device.CryptHandler(module)
|
||||
try:
|
||||
conditions = luks_device.ConditionsHandler(module, crypt)
|
||||
@@ -216,12 +238,13 @@ def test_luks_remove(device, state, is_luks, expected, monkeypatch):
|
||||
assert expected == "exception"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("device, keyfile, passphrase, state, name, "
|
||||
"name_by_dev, expected",
|
||||
((d[0], d[1], d[2], d[3], d[4], d[5], d[6])
|
||||
for d in LUKS_OPEN_DATA))
|
||||
def test_luks_open(device, keyfile, passphrase, state, name, name_by_dev,
|
||||
expected, monkeypatch):
|
||||
@pytest.mark.parametrize(
|
||||
"device, keyfile, passphrase, state, name, name_by_dev, expected",
|
||||
((d[0], d[1], d[2], d[3], d[4], d[5], d[6]) for d in LUKS_OPEN_DATA),
|
||||
)
|
||||
def test_luks_open(
|
||||
device, keyfile, passphrase, state, name, name_by_dev, expected, monkeypatch
|
||||
):
|
||||
module = DummyModule()
|
||||
module.params["device"] = device
|
||||
module.params["keyfile"] = keyfile
|
||||
@@ -230,14 +253,17 @@ def test_luks_open(device, keyfile, passphrase, state, name, name_by_dev,
|
||||
module.params["state"] = state
|
||||
module.params["name"] = name
|
||||
|
||||
monkeypatch.setattr(luks_device.CryptHandler,
|
||||
"get_container_name_by_device",
|
||||
lambda x, y: name_by_dev)
|
||||
monkeypatch.setattr(luks_device.CryptHandler,
|
||||
"get_container_device_by_name",
|
||||
lambda x, y: device)
|
||||
monkeypatch.setattr(luks_device.Handler, "_run_command",
|
||||
lambda x, y: [0, device, ""])
|
||||
monkeypatch.setattr(
|
||||
luks_device.CryptHandler,
|
||||
"get_container_name_by_device",
|
||||
lambda x, y: name_by_dev,
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
luks_device.CryptHandler, "get_container_device_by_name", lambda x, y: device
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
luks_device.Handler, "_run_command", lambda x, y: [0, device, ""]
|
||||
)
|
||||
crypt = luks_device.CryptHandler(module)
|
||||
try:
|
||||
conditions = luks_device.ConditionsHandler(module, crypt)
|
||||
@@ -246,12 +272,13 @@ def test_luks_open(device, keyfile, passphrase, state, name, name_by_dev,
|
||||
assert expected == "exception"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("device, dev_by_name, name, name_by_dev, "
|
||||
"state, label, expected",
|
||||
((d[0], d[1], d[2], d[3], d[4], d[5], d[6])
|
||||
for d in LUKS_CLOSE_DATA))
|
||||
def test_luks_close(device, dev_by_name, name, name_by_dev, state,
|
||||
label, expected, monkeypatch):
|
||||
@pytest.mark.parametrize(
|
||||
"device, dev_by_name, name, name_by_dev, state, label, expected",
|
||||
((d[0], d[1], d[2], d[3], d[4], d[5], d[6]) for d in LUKS_CLOSE_DATA),
|
||||
)
|
||||
def test_luks_close(
|
||||
device, dev_by_name, name, name_by_dev, state, label, expected, monkeypatch
|
||||
):
|
||||
module = DummyModule()
|
||||
module.params["device"] = device
|
||||
module.params["name"] = name
|
||||
@@ -259,12 +286,16 @@ def test_luks_close(device, dev_by_name, name, name_by_dev, state,
|
||||
module.params["state"] = state
|
||||
module.params["label"] = label
|
||||
|
||||
monkeypatch.setattr(luks_device.CryptHandler,
|
||||
"get_container_name_by_device",
|
||||
lambda x, y: name_by_dev)
|
||||
monkeypatch.setattr(luks_device.CryptHandler,
|
||||
"get_container_device_by_name",
|
||||
lambda x, y: dev_by_name)
|
||||
monkeypatch.setattr(
|
||||
luks_device.CryptHandler,
|
||||
"get_container_name_by_device",
|
||||
lambda x, y: name_by_dev,
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
luks_device.CryptHandler,
|
||||
"get_container_device_by_name",
|
||||
lambda x, y: dev_by_name,
|
||||
)
|
||||
crypt = luks_device.CryptHandler(module)
|
||||
try:
|
||||
conditions = luks_device.ConditionsHandler(module, crypt)
|
||||
@@ -273,12 +304,22 @@ def test_luks_close(device, dev_by_name, name, name_by_dev, state,
|
||||
assert expected == "exception"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("device, keyfile, passphrase, new_keyfile, " +
|
||||
"new_passphrase, state, label, expected",
|
||||
((d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7])
|
||||
for d in LUKS_ADD_KEY_DATA))
|
||||
def test_luks_add_key(device, keyfile, passphrase, new_keyfile, new_passphrase,
|
||||
state, label, expected, monkeypatch):
|
||||
@pytest.mark.parametrize(
|
||||
"device, keyfile, passphrase, new_keyfile, "
|
||||
+ "new_passphrase, state, label, expected",
|
||||
((d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7]) for d in LUKS_ADD_KEY_DATA),
|
||||
)
|
||||
def test_luks_add_key(
|
||||
device,
|
||||
keyfile,
|
||||
passphrase,
|
||||
new_keyfile,
|
||||
new_passphrase,
|
||||
state,
|
||||
label,
|
||||
expected,
|
||||
monkeypatch,
|
||||
):
|
||||
module = DummyModule()
|
||||
module.params["device"] = device
|
||||
module.params["keyfile"] = keyfile
|
||||
@@ -290,10 +331,12 @@ def test_luks_add_key(device, keyfile, passphrase, new_keyfile, new_passphrase,
|
||||
module.params["state"] = state
|
||||
module.params["label"] = label
|
||||
|
||||
monkeypatch.setattr(luks_device.Handler, "get_device_by_label",
|
||||
lambda x, y: [0, "/dev/dummy", ""])
|
||||
monkeypatch.setattr(luks_device.CryptHandler, "luks_test_key",
|
||||
lambda x, y, z, w: False)
|
||||
monkeypatch.setattr(
|
||||
luks_device.Handler, "get_device_by_label", lambda x, y: [0, "/dev/dummy", ""]
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
luks_device.CryptHandler, "luks_test_key", lambda x, y, z, w: False
|
||||
)
|
||||
|
||||
crypt = luks_device.CryptHandler(module)
|
||||
try:
|
||||
@@ -303,12 +346,21 @@ def test_luks_add_key(device, keyfile, passphrase, new_keyfile, new_passphrase,
|
||||
assert expected == "exception"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("device, remove_keyfile, remove_passphrase, remove_keyslot, " +
|
||||
"state, label, expected",
|
||||
((d[0], d[1], d[2], d[3], d[4], d[5], d[6])
|
||||
for d in LUKS_REMOVE_KEY_DATA))
|
||||
def test_luks_remove_key(device, remove_keyfile, remove_passphrase, remove_keyslot, state,
|
||||
label, expected, monkeypatch):
|
||||
@pytest.mark.parametrize(
|
||||
"device, remove_keyfile, remove_passphrase, remove_keyslot, "
|
||||
+ "state, label, expected",
|
||||
((d[0], d[1], d[2], d[3], d[4], d[5], d[6]) for d in LUKS_REMOVE_KEY_DATA),
|
||||
)
|
||||
def test_luks_remove_key(
|
||||
device,
|
||||
remove_keyfile,
|
||||
remove_passphrase,
|
||||
remove_keyslot,
|
||||
state,
|
||||
label,
|
||||
expected,
|
||||
monkeypatch,
|
||||
):
|
||||
|
||||
module = DummyModule()
|
||||
module.params["device"] = device
|
||||
@@ -319,12 +371,15 @@ def test_luks_remove_key(device, remove_keyfile, remove_passphrase, remove_keysl
|
||||
module.params["state"] = state
|
||||
module.params["label"] = label
|
||||
|
||||
monkeypatch.setattr(luks_device.Handler, "get_device_by_label",
|
||||
lambda x, y: [0, "/dev/dummy", ""])
|
||||
monkeypatch.setattr(luks_device.Handler, "_run_command",
|
||||
lambda x, y: [0, device, ""])
|
||||
monkeypatch.setattr(luks_device.CryptHandler, "luks_test_key",
|
||||
lambda x, y, z, w: True)
|
||||
monkeypatch.setattr(
|
||||
luks_device.Handler, "get_device_by_label", lambda x, y: [0, "/dev/dummy", ""]
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
luks_device.Handler, "_run_command", lambda x, y: [0, device, ""]
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
luks_device.CryptHandler, "luks_test_key", lambda x, y, z, w: True
|
||||
)
|
||||
|
||||
crypt = luks_device.CryptHandler(module)
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user