Imported Upstream version 4.7.2

This commit is contained in:
Mario Fetka
2021-08-09 20:54:00 +02:00
parent 3bfaa6e020
commit a791de49a2
2175 changed files with 1764288 additions and 331861 deletions

View File

@@ -19,13 +19,17 @@
"""
Test `adtrustinstance`
"""
import os
import nose
import pytest
import six
from ipaserver.install import adtrustinstance
class test_adtrustinstance:
if six.PY3:
unicode = str
@pytest.mark.tier0
class test_adtrustinstance(object):
"""
Test `adtrustinstance`.
"""

View File

@@ -0,0 +1,96 @@
#
# Copyright (C) 2018 FreeIPA Contributors. See COPYING for license
#
from __future__ import absolute_import
import tempfile
import pytest
from ipaplatform.paths import paths
from ipaserver.install.server.upgrade import named_add_crypto_policy
try:
from unittest.mock import patch # pylint: disable=import-error
except ImportError:
from mock import patch # pylint: disable=import-error
TEST_CONFIG = """
options {
\tdnssec-enable yes;
\tdnssec-validation yes;
};
include "random/file";
"""
EXPECTED_CONFIG = """
options {
\tdnssec-enable yes;
\tdnssec-validation yes;
\tinclude "/etc/crypto-policies/back-ends/bind.config";
};
include "random/file";
"""
# bindinstance.named_conf_exists() looks for a section like this
IPA_DYNDB_CONFIG = """
dyndb "ipa" "/usr/lib/bind/ldap.so" {
};
"""
POLICY_FILE = "/etc/crypto-policies/back-ends/bind.config"
@pytest.fixture
def namedconf():
with tempfile.NamedTemporaryFile('w+') as f:
with patch.multiple(paths,
NAMED_CONF=f.name,
NAMED_CRYPTO_POLICY_FILE=POLICY_FILE):
yield f.name
@patch('ipaserver.install.sysupgrade.get_upgrade_state')
@patch('ipaserver.install.sysupgrade.set_upgrade_state')
def test_add_crypto_policy(m_set, m_get, namedconf):
m_get.return_value = False
with open(namedconf, 'w') as f:
f.write(TEST_CONFIG)
f.write(IPA_DYNDB_CONFIG)
result = named_add_crypto_policy()
assert result
m_get.assert_called_with('named.conf', 'add_crypto_policy')
m_set.assert_called_with('named.conf', 'add_crypto_policy', True)
with open(namedconf) as f:
content = f.read()
assert content == ''.join([EXPECTED_CONFIG, IPA_DYNDB_CONFIG])
m_get.reset_mock()
m_set.reset_mock()
m_get.return_value = True
named_add_crypto_policy()
m_get.assert_called_with('named.conf', 'add_crypto_policy')
m_set.assert_not_called()
@patch('ipaserver.install.sysupgrade.get_upgrade_state')
@patch('ipaserver.install.sysupgrade.set_upgrade_state')
def test_add_crypto_policy_no_ipa(m_set, m_get, namedconf):
# Test if the update step is skipped when named.conf doesn't contain
# IPA related settings.
m_get.return_value = False
with open(namedconf, 'w') as f:
f.write(TEST_CONFIG)
result = named_add_crypto_policy()
assert not result
m_get.assert_not_called()
m_set.assert_not_called()

View File

@@ -0,0 +1,125 @@
#
# Copyright (C) 2017 FreeIPA Contributors see COPYING for license
#
from binascii import hexlify
import pickle
# pylint: disable=import-error
from six.moves.configparser import RawConfigParser
# pylint: enable=import-error
from six import StringIO
import pytest
from ipaserver.install import cainstance
pytestmark = pytest.mark.tier0
class test_ExternalCAProfile(object):
def test_MSCSTemplateV1_good(self):
o = cainstance.MSCSTemplateV1("MySubCA")
assert hexlify(o.get_ext_data()) == b'1e0e004d007900530075006200430041'
def test_MSCSTemplateV1_bad(self):
with pytest.raises(ValueError):
cainstance.MSCSTemplateV1("MySubCA:1")
def test_MSCSTemplateV1_pickle_roundtrip(self):
o = cainstance.MSCSTemplateV1("MySubCA")
s = pickle.dumps(o)
assert o.get_ext_data() == pickle.loads(s).get_ext_data()
def test_MSCSTemplateV2_too_few_parts(self):
with pytest.raises(ValueError):
cainstance.MSCSTemplateV2("1.2.3.4")
def test_MSCSTemplateV2_too_many_parts(self):
with pytest.raises(ValueError):
cainstance.MSCSTemplateV2("1.2.3.4:100:200:300")
def test_MSCSTemplateV2_bad_oid(self):
with pytest.raises(ValueError):
cainstance.MSCSTemplateV2("not_an_oid:1")
def test_MSCSTemplateV2_non_numeric_major_version(self):
with pytest.raises(ValueError):
cainstance.MSCSTemplateV2("1.2.3.4:major:200")
def test_MSCSTemplateV2_non_numeric_minor_version(self):
with pytest.raises(ValueError):
cainstance.MSCSTemplateV2("1.2.3.4:100:minor")
def test_MSCSTemplateV2_major_version_lt_zero(self):
with pytest.raises(ValueError):
cainstance.MSCSTemplateV2("1.2.3.4:-1:200")
def test_MSCSTemplateV2_minor_version_lt_zero(self):
with pytest.raises(ValueError):
cainstance.MSCSTemplateV2("1.2.3.4:100:-1")
def test_MSCSTemplateV2_major_version_gt_max(self):
with pytest.raises(ValueError):
cainstance.MSCSTemplateV2("1.2.3.4:4294967296:200")
def test_MSCSTemplateV2_minor_version_gt_max(self):
with pytest.raises(ValueError):
cainstance.MSCSTemplateV2("1.2.3.4:100:4294967296")
def test_MSCSTemplateV2_good_major(self):
o = cainstance.MSCSTemplateV2("1.2.3.4:4294967295")
assert hexlify(o.get_ext_data()) == b'300c06032a0304020500ffffffff'
def test_MSCSTemplateV2_good_major_minor(self):
o = cainstance.MSCSTemplateV2("1.2.3.4:4294967295:0")
assert hexlify(o.get_ext_data()) \
== b'300f06032a0304020500ffffffff020100'
def test_MSCSTemplateV2_pickle_roundtrip(self):
o = cainstance.MSCSTemplateV2("1.2.3.4:4294967295:0")
s = pickle.dumps(o)
assert o.get_ext_data() == pickle.loads(s).get_ext_data()
def test_ExternalCAProfile_dispatch(self):
"""
Test that constructing ExternalCAProfile actually returns an
instance of the appropriate subclass.
"""
assert isinstance(
cainstance.ExternalCAProfile("MySubCA"),
cainstance.MSCSTemplateV1)
assert isinstance(
cainstance.ExternalCAProfile("1.2.3.4:100"),
cainstance.MSCSTemplateV2)
def test_write_pkispawn_config_file_MSCSTemplateV1(self):
template = cainstance.MSCSTemplateV1(u"SubCA")
expected = (
'[CA]\n'
'pki_req_ext_oid = 1.3.6.1.4.1.311.20.2\n'
'pki_req_ext_data = 1e0a00530075006200430041\n\n'
)
self._test_write_pkispawn_config_file(template, expected)
def test_write_pkispawn_config_file_MSCSTemplateV2(self):
template = cainstance.MSCSTemplateV2(u"1.2.3.4:4294967295")
expected = (
'[CA]\n'
'pki_req_ext_oid = 1.3.6.1.4.1.311.21.7\n'
'pki_req_ext_data = 300c06032a0304020500ffffffff\n\n'
)
self._test_write_pkispawn_config_file(template, expected)
def _test_write_pkispawn_config_file(self, template, expected):
"""
Test that the values we read from an ExternalCAProfile
object can be used to produce a reasonable-looking pkispawn
configuration.
"""
config = RawConfigParser()
config.optionxform = str
config.add_section("CA")
config.set("CA", "pki_req_ext_oid", template.ext_oid)
config.set("CA", "pki_req_ext_data",
hexlify(template.get_ext_data()).decode('ascii'))
out = StringIO()
config.write(out)
assert out.getvalue() == expected

View File

@@ -0,0 +1,147 @@
#
# Copyright (C) 2018 FreeIPA Contributors. See COPYING for license
#
from __future__ import absolute_import
import six
from abc import ABCMeta, abstractproperty
from collections import namedtuple
import itertools
from ipatests.util import assert_equal
from ipaserver.install.ipa_replica_install import ReplicaInstall
Keyval = namedtuple('Keyval', ['option', 'value'])
class InstallerTestBase(six.with_metaclass(ABCMeta, object)):
OPTS_DICT = {}
# don't allow creating classes with tested_cls unspecified
@abstractproperty
def tested_cls(self):
return None
def setup_class(self):
"""Initializes the tested class so that it can be used later on
"""
self.tested_cls.make_parser()
assert \
getattr(self.tested_cls, 'option_parser', False), \
("Unable to generate option parser for {}"
.format(self.tested_cls.__name__))
self._populate_opts_dict()
@classmethod
def _populate_opts_dict(cls):
"""Populate the class-owned OPTS_DICT with available options
"""
if not getattr(cls.tested_cls, 'option_parser', False):
raise RuntimeError("You need to create the parser of the tested "
"class first.")
# add all options from the option groups
# pylint: disable=no-member
for opt_group in cls.tested_cls.option_parser.option_groups:
for opt in opt_group.option_list:
cls.OPTS_DICT[opt.dest] = opt._short_opts + opt._long_opts
# add options outside groups
for opt in cls.tested_cls.option_parser.option_list:
cls.OPTS_DICT[opt.dest] = opt._short_opts + opt._long_opts
def parse_cli_args(self, args):
"""Parses the CLI-like arguments and returns them in python objects
:param args: A string representing the CLI arguments
:returns: dictionary and a list of parsed options and arguments
"""
return self.tested_cls.option_parser.parse_args(args.split())
def get_installer_instance(self, args):
"""Get instance of the configuring class
"""
parsed_opts = self.parse_cli_args(args)
cls = self.tested_cls.get_command_class(*parsed_opts)
command_instance = cls(*parsed_opts)
return command_instance.init_configurator()
def combine_options(self, *args):
return ' '.join(args)
def all_option_permutations(self, *key_val):
"""Gets all short-option/long-option permutations
:param key_val: Keyval tuples specifying the options to grab from
OPTS_DICT along with the values to assign to them
:returns: list or list of lists of all permutations
"""
if len(key_val) == 0:
return []
elif len(key_val) == 1:
val = key_val[0].value
return ['{opt} {val}'.format(opt=opt, val=val)
for opt in self.OPTS_DICT[key_val[0].option]]
permutation_lists = [self.OPTS_DICT[k.option] for k in key_val]
permutation = itertools.product(*permutation_lists)
ret = []
for p in permutation:
opt_vals = []
for i, kv in enumerate(key_val):
opt_vals.append(
'{opt} {val}'.format(
opt=p[i], val=kv.value))
ret.append(opt_vals)
return ret
class TestReplicaInstaller(InstallerTestBase):
tested_cls = ReplicaInstall
PASSWORD = Keyval("auto_password",
"c3ca2246bcf309d1b636581ce429da3522a8aec4")
ADMIN_PASSWORD = Keyval("admin_password", "milan_je_buh123")
PRINCIPAL = Keyval("principal", "ubercool_guy")
def test_password_option_DL1(self):
# OTP enrollment
for passwd_opt in self.all_option_permutations(self.PASSWORD):
ic = self.get_installer_instance(passwd_opt)
assert_equal(ic.password, self.PASSWORD.value)
# admin principal enrollment
for adm_password_opt in (
self.all_option_permutations(self.ADMIN_PASSWORD)
):
ic = self.get_installer_instance(adm_password_opt)
assert_equal(ic.password, None)
assert_equal(ic.admin_password, self.ADMIN_PASSWORD.value)
# if principal is set, we interpret --password as that principal's
for passwd_opt, principal_opt in (
self.all_option_permutations(self.PASSWORD, self.PRINCIPAL)
):
ic = self.get_installer_instance(
self.combine_options(passwd_opt, principal_opt))
assert_equal(ic.password, None)
assert_equal(ic.principal, self.PRINCIPAL.value)
assert_equal(ic.admin_password, self.PASSWORD.value)
# if principal is set, we interpret --password as that principal's
# unless admin-password is also specified, in which case it's once
# again an OTP
for adm_password_opt, passwd_opt, principal_opt in (
self.all_option_permutations(
self.ADMIN_PASSWORD, self.PASSWORD, self.PRINCIPAL)
):
ic = self.get_installer_instance(
self.combine_options(
adm_password_opt, passwd_opt, principal_opt))
assert_equal(ic.password, self.PASSWORD.value)
assert_equal(ic.principal, self.PRINCIPAL.value)
assert_equal(ic.admin_password, self.ADMIN_PASSWORD.value)

View File

@@ -0,0 +1,152 @@
#
# Copyright (C) 2017 FreeIPA Contributors. See COPYING for license
#
from __future__ import absolute_import
import binascii
import os
import re
import shutil
import subprocess
import tempfile
import textwrap
import pytest
from ipaplatform.paths import paths
from ipapython import ipautil
from ipaserver.install import installutils
from ipaserver.install import ipa_backup
from ipaserver.install import ipa_restore
@pytest.fixture
def tempdir(request):
tempdir = tempfile.mkdtemp()
def fin():
shutil.rmtree(tempdir)
request.addfinalizer(fin)
return tempdir
GPG_GENKEY = textwrap.dedent("""
%echo Generating a standard key
Key-Type: RSA
Key-Length: 2048
Name-Real: IPA Backup
Name-Comment: IPA Backup
Name-Email: root@example.com
Expire-Date: 0
Passphrase: {passphrase}
%commit
%echo done
""")
@pytest.fixture
def gpgkey(request, tempdir):
passphrase = "Secret123"
gnupghome = os.path.join(tempdir, "gnupg")
os.makedirs(gnupghome, 0o700)
# provide clean env for gpg test
env = os.environ.copy()
orig_gnupghome = env.get('GNUPGHOME')
env['GNUPGHOME'] = gnupghome
env['LC_ALL'] = 'C.UTF-8'
env['LANGUAGE'] = 'C'
devnull = open(os.devnull, 'w')
# allow passing passphrases to agent
with open(os.path.join(gnupghome, "gpg-agent.conf"), 'w') as f:
f.write("verbose\n")
f.write("allow-preset-passphrase\n")
# run agent in background
agent = subprocess.Popen(
[paths.GPG_AGENT, '--batch', '--daemon'],
env=env, stdout=devnull, stderr=devnull
)
def fin():
if orig_gnupghome is not None:
os.environ['GNUPGHOME'] = orig_gnupghome
else:
os.environ.pop('GNUPGHOME', None)
agent.kill()
agent.wait()
request.addfinalizer(fin)
# create public / private key pair
keygen = os.path.join(gnupghome, 'keygen')
with open(keygen, 'w') as f:
f.write(GPG_GENKEY.format(passphrase=passphrase))
subprocess.check_call(
[paths.GPG2, '--batch', '--gen-key', keygen],
env=env, stdout=devnull, stderr=devnull
)
# get keygrip of private key
out = subprocess.check_output(
[paths.GPG2, "--list-secret-keys", "--with-keygrip"],
env=env, stderr=subprocess.STDOUT
)
mo = re.search("Keygrip = ([A-Z0-9]{32,})", out.decode('utf-8'))
if mo is None:
raise ValueError(out.decode('utf-8'))
keygrip = mo.group(1)
# unlock private key
cmd = "PRESET_PASSPHRASE {} -1 {}".format(
keygrip,
binascii.hexlify(passphrase.encode('utf-8')).decode('utf-8')
)
subprocess.check_call(
[paths.GPG_CONNECT_AGENT, cmd, "/bye"],
env=env, stdout=devnull, stderr=devnull
)
# set env for the rest of the progress
os.environ['GNUPGHOME'] = gnupghome
def test_gpg_encrypt(tempdir):
src = os.path.join(tempdir, "data.txt")
encrypted = os.path.join(tempdir, "data.gpg")
decrypted = os.path.join(tempdir, "data.out")
passwd = 'Secret123'
payload = 'Dummy text\n'
with open(src, 'w') as f:
f.write(payload)
installutils.encrypt_file(src, encrypted, password=passwd)
assert os.path.isfile(encrypted)
installutils.decrypt_file(encrypted, decrypted, password=passwd)
assert os.path.isfile(decrypted)
with open(decrypted) as f:
assert f.read() == payload
with pytest.raises(ipautil.CalledProcessError):
installutils.decrypt_file(encrypted, decrypted, password='invalid')
def test_gpg_asymmetric(tempdir, gpgkey):
src = os.path.join(tempdir, "asymmetric.txt")
encrypted = src + ".gpg"
payload = 'Dummy text\n'
with open(src, 'w') as f:
f.write(payload)
ipa_backup.encrypt_file(src, remove_original=True)
assert os.path.isfile(encrypted)
assert not os.path.exists(src)
ipa_restore.decrypt_file(tempdir, encrypted)
assert os.path.isfile(src)
with open(src) as f:
assert f.read() == payload

View File

@@ -22,8 +22,10 @@ Tests for the `ipaserver.service` module.
"""
from ipaserver.install import service
import pytest
@pytest.mark.tier0
def test_format_seconds():
assert service.format_seconds(0) == '0 seconds'
assert service.format_seconds(1) == '1 second'