1# (c) 2019 Telstra Corporation Limited
2#
3# This file is part of Ansible
4#
5# Ansible is free software: you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation, either version 3 of the License, or
8# (at your option) any later version.
9#
10# Ansible is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
17
18from __future__ import (absolute_import, division, print_function)
19__metaclass__ = type
20from ansible_collections.community.aws.plugins.modules.aws_acm import pem_chain_split, chain_compare
21from ansible.module_utils._text import to_bytes, to_text
22from pprint import pprint
23
24
25def test_chain_compare():
26
27    # The functions we're testing take module as an argument
28    # Just so they can call module.fail_json
29    # Let's just use None for the unit tests,
30    # Because they shouldn't fail
31    # And if they do, fail_json is not applicable
32    module = None
33
34    fixture_suffix = 'tests/unit/plugins/modules/fixtures/certs'
35
36    # Test chain split function on super simple (invalid) certs
37    expected = ['aaa', 'bbb', 'ccc']
38
39    for fname in ['simple-chain-a.cert', 'simple-chain-b.cert']:
40        path = fixture_suffix + '/' + fname
41        with open(path, 'r') as f:
42            pem = to_text(f.read())
43        actual = pem_chain_split(module, pem)
44        actual = [a.strip() for a in actual]
45        if actual != expected:
46            print("Expected:")
47            pprint(expected)
48            print("Actual:")
49            pprint(actual)
50            raise AssertionError("Failed to properly split %s" % fname)
51
52    # Now test real chains
53    # chains with same same_as should be considered equal
54    test_chains = [
55        {  # Original Cert chain
56            'path': fixture_suffix + '/chain-1.0.cert',
57            'same_as': 1,
58            'length': 3
59        },
60        {  # Same as 1.0, but longer PEM lines
61            'path': fixture_suffix + '/chain-1.1.cert',
62            'same_as': 1,
63            'length': 3
64        },
65        {  # Same as 1.0, but without the stuff before each --------
66            'path': fixture_suffix + '/chain-1.2.cert',
67            'same_as': 1,
68            'length': 3
69        },
70        {  # Same as 1.0, but in a different order, so should be considered different
71            'path': fixture_suffix + '/chain-1.3.cert',
72            'same_as': 2,
73            'length': 3
74        },
75        {  # Same as 1.0, but with last link missing
76            'path': fixture_suffix + '/chain-1.4.cert',
77            'same_as': 3,
78            'length': 2
79        },
80        {  # Completely different cert chain to all the others
81            'path': fixture_suffix + '/chain-4.cert',
82            'same_as': 4,
83            'length': 3
84        },
85        {  # Single cert
86            'path': fixture_suffix + '/a.pem',
87            'same_as': 5,
88            'length': 1
89        },
90        {  # a different, single cert
91            'path': fixture_suffix + '/b.pem',
92            'same_as': 6,
93            'length': 1
94        }
95    ]
96
97    for chain in test_chains:
98        with open(chain['path'], 'r') as f:
99            chain['pem_text'] = to_text(f.read())
100
101        # Test to make sure our regex isn't too greedy
102        chain['split'] = pem_chain_split(module, chain['pem_text'])
103        if len(chain['split']) != chain['length']:
104            print("Cert before split")
105            print(chain['pem_text'])
106            print("Cert after split")
107            pprint(chain['split'])
108            print("path: %s" % chain['path'])
109            print("Expected chain length: %d" % chain['length'])
110            print("Actual chain length: %d" % len(chain['split']))
111            raise AssertionError("Chain %s was not split properly" % chain['path'])
112
113    for chain_a in test_chains:
114        for chain_b in test_chains:
115            expected = (chain_a['same_as'] == chain_b['same_as'])
116
117            # Now test the comparison function
118            actual = chain_compare(module, chain_a['pem_text'], chain_b['pem_text'])
119            if expected != actual:
120                print("Error, unexpected comparison result between \n%s\nand\n%s" % (chain_a['path'], chain_b['path']))
121                print("Expected %s got %s" % (str(expected), str(actual)))
122            assert(expected == actual)
123