Skip to content

Commit

Permalink
Add tests for certificate info extraction.
Browse files Browse the repository at this point in the history
  • Loading branch information
felixfontein committed Apr 29, 2024
1 parent efa636d commit 8a68b8c
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 14 deletions.
25 changes: 11 additions & 14 deletions plugins/module_utils/acme/backends.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
__metaclass__ = type


from collections import namedtuple
import abc

from ansible.module_utils import six
Expand All @@ -18,20 +19,16 @@
)


class CertificateInformation(object):
def __init__(
self,
not_valid_after,
not_valid_before,
serial_number,
subject_key_identifier=None,
authority_key_identifier=None,
):
self.not_valid_after = not_valid_after
self.not_valid_before = not_valid_before
self.serial_number = serial_number
self.subject_key_identifier = subject_key_identifier
self.authority_key_identifier = authority_key_identifier
CertificateInformation = namedtuple(
'CertificateInformation',
(
'not_valid_after',
'not_valid_before',
'serial_number',
'subject_key_identifier',
'authority_key_identifier',
),
)


@six.add_metaclass(abc.ABCMeta)
Expand Down
25 changes: 25 additions & 0 deletions tests/unit/plugins/module_utils/acme/backend_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import os

from ansible_collections.community.crypto.plugins.module_utils.acme.backends import (
CertificateInformation,
CryptoBackend,
)

Expand Down Expand Up @@ -81,13 +82,31 @@ def load_fixture(name):
TEST_CERT = load_fixture("cert_1.pem")


TEST_CERT_OPENSSL_OUTPUT = load_fixture("cert_1.txt")


TEST_CERT_DAYS = [
(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 = [
(
TEST_CERT,
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',
authority_key_identifier=None,
),
TEST_CERT_OPENSSL_OUTPUT,
),
]


class FakeBackend(CryptoBackend):
def parse_key(self, key_file=None, key_content=None, passphrase=None):
raise BackendException('Not implemented in fake backend')
Expand All @@ -98,6 +117,9 @@ def sign(self, payload64, protected64, key_data):
def create_mac_key(self, alg, key):
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')

def get_csr_identifiers(self, csr_filename=None, csr_content=None):
raise BackendException('Not implemented in fake backend')

Expand All @@ -106,3 +128,6 @@ def get_cert_days(self, cert_filename=None, cert_content=None, now=None):

def create_chain_matcher(self, criterium):
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')
38 changes: 38 additions & 0 deletions tests/unit/plugins/module_utils/acme/fixtures/cert_1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 1 (0x1)
Signature Algorithm: ecdsa-with-SHA256
Issuer: CN=ansible.com
Validity
Not Before: Nov 25 15:28:23 2018 GMT
Not After : Nov 26 15:28:24 2018 GMT
Subject: CN=ansible.com
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
04:00:9c:f4:c8:00:17:03:01:26:3a:14:d1:92:35:
f1:c2:07:9d:6d:63:ba:82:86:d8:33:79:56:b3:3a:
d2:eb:c1:bc:41:2c:e1:5d:1e:80:99:0d:c8:cd:90:
e2:9a:74:d3:5c:ee:d7:85:5c:a5:0d:3f:12:2f:31:
38:e3:f1:29:9b
ASN1 OID: prime256v1
NIST CURVE: P-256
X509v3 extensions:
X509v3 Subject Alternative Name:
DNS:example.com, DNS:example.org
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Key Usage: critical
Digital Signature
X509v3 Extended Key Usage:
TLS Web Server Authentication
X509v3 Subject Key Identifier:
98:D2:FD:3C:CC:CD:69:45:FB:E2:8C:30:2C:54:62:18:34:B7:07:73
Signature Algorithm: ecdsa-with-SHA256
Signature Value:
30:46:02:21:00:bc:fb:52:bf:7a:93:2d:0e:7c:ce:43:f4:cc:
05:98:28:36:8d:c7:2a:9b:f5:20:94:62:3d:fb:82:9e:38:42:
32:02:21:00:c0:55:f8:b5:d9:65:41:2a:dd:d4:76:3f:8c:cb:
07:c1:d2:b9:c0:7d:c9:90:af:fd:f9:f1:b0:c9:13:f5:d5:52
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
SPDX-License-Identifier: GPL-3.0-or-later
SPDX-FileCopyrightText: Ansible Project
28 changes: 28 additions & 0 deletions tests/unit/plugins/module_utils/acme/test_backend_cryptography.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,20 @@
CryptographyBackend,
)

from ansible_collections.community.crypto.plugins.module_utils.crypto.support import (
ensure_utc_timezone,
)

from ansible_collections.community.crypto.plugins.module_utils.crypto.cryptography_support import (
CRYPTOGRAPHY_TIMEZONE,
)

from .backend_data import (
TEST_KEYS,
TEST_CSRS,
TEST_CERT,
TEST_CERT_DAYS,
TEST_CERT_INFO,
)


Expand Down Expand Up @@ -64,3 +73,22 @@ def test_certdays_cryptography(now, expected_days, tmpdir):
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)
def test_get_cert_information(cert_content, expected_cert_info, openssl_output, tmpdir):
fn = tmpdir / 'test-cert.pem'
fn.write(cert_content)
module = MagicMock()
backend = CryptographyBackend(module)

if CRYPTOGRAPHY_TIMEZONE:
expected_cert_info = expected_cert_info._replace(
not_valid_after=ensure_utc_timezone(expected_cert_info.not_valid_after),
not_valid_before=ensure_utc_timezone(expected_cert_info.not_valid_before),
)

cert_info = backend.get_cert_information(cert_filename=str(fn))
assert cert_info == expected_cert_info
cert_info = backend.get_cert_information(cert_content=cert_content)
assert cert_info == expected_cert_info
30 changes: 30 additions & 0 deletions tests/unit/plugins/module_utils/acme/test_backend_openssl_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
from .backend_data import (
TEST_KEYS,
TEST_CSRS,
TEST_CERT,
TEST_CERT_OPENSSL_OUTPUT,
TEST_CERT_DAYS,
TEST_CERT_INFO,
)


Expand Down Expand Up @@ -61,3 +65,29 @@ def test_normalize_ip(ip, result):
module = MagicMock()
backend = OpenSSLCLIBackend(module, openssl_binary='openssl')
assert backend._normalize_ip(ip) == result


@pytest.mark.parametrize("now, expected_days", TEST_CERT_DAYS)
def test_certdays_cryptography(now, expected_days, tmpdir):
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')
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)
def test_get_cert_information(cert_content, expected_cert_info, openssl_output, tmpdir):
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')
cert_info = backend.get_cert_information(cert_filename=str(fn))
assert cert_info == expected_cert_info
cert_info = backend.get_cert_information(cert_content=cert_content)
assert cert_info == expected_cert_info

0 comments on commit 8a68b8c

Please sign in to comment.