Imported Upstream version 4.3.1
This commit is contained in:
8
ipatests/test_ipaserver/test_install/test_adtrustinstance.py
Normal file → Executable file
8
ipatests/test_ipaserver/test_install/test_adtrustinstance.py
Normal file → Executable file
@@ -19,8 +19,12 @@
|
||||
"""
|
||||
Test `adtrustinstance`
|
||||
"""
|
||||
import pytest
|
||||
|
||||
import os
|
||||
|
||||
import six
|
||||
import nose
|
||||
import pytest
|
||||
|
||||
from ipaserver.install import adtrustinstance
|
||||
|
||||
@@ -29,7 +33,7 @@ if six.PY3:
|
||||
|
||||
|
||||
@pytest.mark.tier0
|
||||
class test_adtrustinstance(object):
|
||||
class test_adtrustinstance:
|
||||
"""
|
||||
Test `adtrustinstance`.
|
||||
"""
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
#
|
||||
# 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()
|
||||
@@ -1,125 +0,0 @@
|
||||
#
|
||||
# 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
|
||||
@@ -1,147 +0,0 @@
|
||||
#
|
||||
# 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)
|
||||
@@ -1,152 +0,0 @@
|
||||
#
|
||||
# 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
|
||||
Reference in New Issue
Block a user