The Identity, Policy and Audit system
Johnny Hughes
2018-05-14 ab4b7f7ca4a3a477df1cf61418f2d63755652dcc
commit | author | age
beb795 1 From 4f3522e47d1a1c26dc8283c6aa4fc72a33d7133e Mon Sep 17 00:00:00 2001
ac7d03 2 From: Jan Cholasta <jcholast@redhat.com>
CS 3 Date: Thu, 16 Mar 2017 09:44:21 +0000
4 Subject: [PATCH] Remove csrgen
5
6 This reverts commits:
7 * 72de679eb445c975ec70cd265d37d4927823ce5b
8 * 177f07e163d6d591a1e609d35e0a6f6f5347551e
9 * 80be18162921268be9c8981495c9e8a4de0c85cd
10 * 83e2c2b65eeb5a3aa4a59c0535e9177aac5e4637
11 * ada91c20588046bb147fc701718d3da4d2c080ca
12 * 4350dcdea22fd2284836315d0ae7d38733a7620e
13 * 39a5d9c5aae77687f67d9be02457733bdfb99ead
14 * a26cf0d7910dd4c0a4da08682b4be8d3d94ba520
15 * afd7c05d11432304bfdf183832a21d419f363689
16 * f1a1c6eca1b294f24174d7b0e1f78de46d9d5b05
17 * fc58eff6a3d7fe805e612b8b002304d8b9cd4ba9
18 * 10ef5947860f5098182b1f95c08c1158e2da15f9
19
20 https://bugzilla.redhat.com/show_bug.cgi?id=1432630
21 ---
22  freeipa.spec.in                                    |  18 -
23  ipaclient/csrgen.py                                | 398 ---------------------
24  ipaclient/csrgen/profiles/caIPAserviceCert.json    |  15 -
25  ipaclient/csrgen/profiles/userCert.json            |  15 -
26  ipaclient/csrgen/rules/dataDNS.json                |  15 -
27  ipaclient/csrgen/rules/dataEmail.json              |  15 -
28  ipaclient/csrgen/rules/dataHostCN.json             |  15 -
29  ipaclient/csrgen/rules/dataSubjectBase.json        |  15 -
30  ipaclient/csrgen/rules/dataUsernameCN.json         |  15 -
31  ipaclient/csrgen/rules/syntaxSAN.json              |  15 -
32  ipaclient/csrgen/rules/syntaxSubject.json          |  16 -
33  ipaclient/csrgen/templates/certutil_base.tmpl      |  11 -
34  ipaclient/csrgen/templates/openssl_base.tmpl       |  35 --
35  ipaclient/csrgen/templates/openssl_macros.tmpl     |  29 --
36  ipaclient/plugins/cert.py                          |  96 +----
37  ipaclient/plugins/csrgen.py                        | 120 -------
3f51ca 38  ipaclient/setup.py                                 |   7 -
ac7d03 39  ipalib/errors.py                                   |  28 --
CS 40  ipatests/setup.py                                  |   2 -
41  ipatests/test_ipaclient/__init__.py                |   7 -
42  .../data/test_csrgen/profiles/profile.json         |   8 -
43  .../data/test_csrgen/rules/basic.json              |  12 -
44  .../data/test_csrgen/rules/options.json            |  18 -
45  .../scripts/caIPAserviceCert_certutil.sh           |  11 -
46  .../scripts/caIPAserviceCert_openssl.sh            |  34 --
47  .../data/test_csrgen/scripts/userCert_certutil.sh  |  11 -
48  .../data/test_csrgen/scripts/userCert_openssl.sh   |  34 --
49  .../data/test_csrgen/templates/identity_base.tmpl  |   1 -
50  ipatests/test_ipaclient/test_csrgen.py             | 298 ---------------
3f51ca 51  29 files changed, 1 insertion(+), 1313 deletions(-)
ac7d03 52  delete mode 100644 ipaclient/csrgen.py
CS 53  delete mode 100644 ipaclient/csrgen/profiles/caIPAserviceCert.json
54  delete mode 100644 ipaclient/csrgen/profiles/userCert.json
55  delete mode 100644 ipaclient/csrgen/rules/dataDNS.json
56  delete mode 100644 ipaclient/csrgen/rules/dataEmail.json
57  delete mode 100644 ipaclient/csrgen/rules/dataHostCN.json
58  delete mode 100644 ipaclient/csrgen/rules/dataSubjectBase.json
59  delete mode 100644 ipaclient/csrgen/rules/dataUsernameCN.json
60  delete mode 100644 ipaclient/csrgen/rules/syntaxSAN.json
61  delete mode 100644 ipaclient/csrgen/rules/syntaxSubject.json
62  delete mode 100644 ipaclient/csrgen/templates/certutil_base.tmpl
63  delete mode 100644 ipaclient/csrgen/templates/openssl_base.tmpl
64  delete mode 100644 ipaclient/csrgen/templates/openssl_macros.tmpl
65  delete mode 100644 ipaclient/plugins/csrgen.py
66  delete mode 100644 ipatests/test_ipaclient/__init__.py
67  delete mode 100644 ipatests/test_ipaclient/data/test_csrgen/profiles/profile.json
68  delete mode 100644 ipatests/test_ipaclient/data/test_csrgen/rules/basic.json
69  delete mode 100644 ipatests/test_ipaclient/data/test_csrgen/rules/options.json
70  delete mode 100644 ipatests/test_ipaclient/data/test_csrgen/scripts/caIPAserviceCert_certutil.sh
71  delete mode 100644 ipatests/test_ipaclient/data/test_csrgen/scripts/caIPAserviceCert_openssl.sh
72  delete mode 100644 ipatests/test_ipaclient/data/test_csrgen/scripts/userCert_certutil.sh
73  delete mode 100644 ipatests/test_ipaclient/data/test_csrgen/scripts/userCert_openssl.sh
74  delete mode 100644 ipatests/test_ipaclient/data/test_csrgen/templates/identity_base.tmpl
75  delete mode 100644 ipatests/test_ipaclient/test_csrgen.py
76
77 diff --git a/freeipa.spec.in b/freeipa.spec.in
beb795 78 index 86189d56ded05dac695d3a7a19f726e197979dc5..3cefeeced78de60ced36759acce5ab5c1a0ddd0d 100644
ac7d03 79 --- a/freeipa.spec.in
CS 80 +++ b/freeipa.spec.in
3f51ca 81 @@ -198,7 +198,6 @@ BuildRequires:  python-sssdconfig
ac7d03 82  BuildRequires:  python-nose
CS 83  BuildRequires:  python-paste
84  BuildRequires:  systemd-python
85 -BuildRequires:  python2-jinja2
86  BuildRequires:  python-augeas
87  
88  %if 0%{?with_python3}
3f51ca 89 @@ -236,7 +235,6 @@ BuildRequires:  python3-libsss_nss_idmap
ac7d03 90  BuildRequires:  python3-nose
CS 91  BuildRequires:  python3-paste
92  BuildRequires:  python3-systemd
93 -BuildRequires:  python3-jinja2
94  BuildRequires:  python3-augeas
95  %endif # with_python3
96  %endif # with_lint
beb795 97 @@ -544,7 +542,6 @@ Requires: %{name}-client-common = %{version}-%{release}
ac7d03 98  Requires: %{name}-common = %{version}-%{release}
CS 99  Requires: python2-ipalib = %{version}-%{release}
100  Requires: python-dns >= 1.15
101 -Requires: python2-jinja2
102  
103  %description -n python2-ipaclient
104  IPA is an integrated solution to provide centrally managed Identity (users,
beb795 105 @@ -567,7 +564,6 @@ Requires: %{name}-client-common = %{version}-%{release}
ac7d03 106  Requires: %{name}-common = %{version}-%{release}
CS 107  Requires: python3-ipalib = %{version}-%{release}
108  Requires: python3-dns >= 1.15
109 -Requires: python3-jinja2
110  
111  %description -n python3-ipaclient
112  IPA is an integrated solution to provide centrally managed Identity (users,
beb795 113 @@ -1433,13 +1429,6 @@ fi
ac7d03 114  %{python_sitelib}/ipaclient/remote_plugins/*.py*
3f51ca 115  %dir %{python_sitelib}/ipaclient/remote_plugins/2_*
ac7d03 116  %{python_sitelib}/ipaclient/remote_plugins/2_*/*.py*
CS 117 -%dir %{python_sitelib}/ipaclient/csrgen
118 -%dir %{python_sitelib}/ipaclient/csrgen/profiles
119 -%{python_sitelib}/ipaclient/csrgen/profiles/*.json
120 -%dir %{python_sitelib}/ipaclient/csrgen/rules
121 -%{python_sitelib}/ipaclient/csrgen/rules/*.json
122 -%dir %{python_sitelib}/ipaclient/csrgen/templates
123 -%{python_sitelib}/ipaclient/csrgen/templates/*.tmpl
124  %{python_sitelib}/ipaclient-*.egg-info
125  
126  
beb795 127 @@ -1464,13 +1453,6 @@ fi
3f51ca 128  %dir %{python3_sitelib}/ipaclient/remote_plugins/2_*
ac7d03 129  %{python3_sitelib}/ipaclient/remote_plugins/2_*/*.py
CS 130  %{python3_sitelib}/ipaclient/remote_plugins/2_*/__pycache__/*.py*
131 -%dir %{python3_sitelib}/ipaclient/csrgen
132 -%dir %{python3_sitelib}/ipaclient/csrgen/profiles
133 -%{python3_sitelib}/ipaclient/csrgen/profiles/*.json
134 -%dir %{python3_sitelib}/ipaclient/csrgen/rules
135 -%{python3_sitelib}/ipaclient/csrgen/rules/*.json
136 -%dir %{python3_sitelib}/ipaclient/csrgen/templates
137 -%{python3_sitelib}/ipaclient/csrgen/templates/*.tmpl
138  %{python3_sitelib}/ipaclient-*.egg-info
139  
140  %endif # with_python3
141 diff --git a/ipaclient/csrgen.py b/ipaclient/csrgen.py
142 deleted file mode 100644
143 index 8fb0b32c05490812b75f87db69f9df1ca38107f7..0000000000000000000000000000000000000000
144 --- a/ipaclient/csrgen.py
145 +++ /dev/null
146 @@ -1,398 +0,0 @@
147 -#
148 -# Copyright (C) 2016  FreeIPA Contributors see COPYING for license
149 -#
150 -
151 -import collections
152 -import errno
153 -import json
154 -import os.path
155 -import pipes
156 -import traceback
157 -
158 -import pkg_resources
159 -
160 -import jinja2
161 -import jinja2.ext
162 -import jinja2.sandbox
163 -import six
164 -
165 -from ipalib import api
166 -from ipalib import errors
167 -from ipalib.text import _
168 -from ipapython.ipa_log_manager import log_mgr
169 -
170 -if six.PY3:
171 -    unicode = str
172 -
173 -__doc__ = _("""
174 -Routines for constructing certificate signing requests using IPA data and
175 -stored templates.
176 -""")
177 -
178 -logger = log_mgr.get_logger(__name__)
179 -
180 -
181 -class IndexableUndefined(jinja2.Undefined):
182 -    def __getitem__(self, key):
183 -        return jinja2.Undefined(
184 -            hint=self._undefined_hint, obj=self._undefined_obj,
185 -            name=self._undefined_name, exc=self._undefined_exception)
186 -
187 -
188 -class IPAExtension(jinja2.ext.Extension):
189 -    """Jinja2 extension providing useful features for CSR generation rules."""
190 -
191 -    def __init__(self, environment):
192 -        super(IPAExtension, self).__init__(environment)
193 -
194 -        environment.filters.update(
195 -            quote=self.quote,
196 -            required=self.required,
197 -        )
198 -
199 -    def quote(self, data):
200 -        return pipes.quote(data)
201 -
202 -    def required(self, data, name):
203 -        if not data:
204 -            raise errors.CSRTemplateError(
205 -                reason=_('Required CSR generation rule %(name)s is missing data') %
206 -                {'name': name})
207 -        return data
208 -
209 -
210 -class Formatter(object):
211 -    """
212 -    Class for processing a set of CSR generation rules into a template.
213 -
214 -    The template can be rendered with user and database data to produce a
215 -    script, which generates a CSR when run.
216 -
217 -    Subclasses of Formatter should set the value of base_template_name to the
218 -    filename of a base template with spaces for the processed rules.
219 -    Additionally, they should override the _get_template_params method to
220 -    produce the correct output for the base template.
221 -    """
222 -    base_template_name = None
223 -
224 -    def __init__(self, csr_data_dir=None):
225 -        # chain loaders:
226 -        # 1) csr_data_dir/templates
227 -        # 2) /etc/ipa/csrgen/templates
228 -        # 3) ipaclient/csrgen/templates
229 -        loaders = []
230 -        if csr_data_dir is not None:
231 -            loaders.append(jinja2.FileSystemLoader(
232 -                os.path.join(csr_data_dir, 'templates'))
233 -            )
234 -        loaders.append(jinja2.FileSystemLoader(
235 -            os.path.join(api.env.confdir, 'csrgen/templates'))
236 -        )
237 -        loaders.append(jinja2.PackageLoader('ipaclient', 'csrgen/templates'))
238 -
239 -        self.jinja2 = jinja2.sandbox.SandboxedEnvironment(
240 -            loader=jinja2.ChoiceLoader(loaders),
241 -            extensions=[jinja2.ext.ExprStmtExtension, IPAExtension],
242 -            keep_trailing_newline=True, undefined=IndexableUndefined)
243 -
244 -        self.passthrough_globals = {}
245 -
246 -    def _define_passthrough(self, call):
247 -        """Some macros are meant to be interpreted during the final render, not
248 -        when data rules are interpolated into syntax rules. This method allows
249 -        those macros to be registered so that calls to them are passed through
250 -        to the prepared rule rather than interpreted.
251 -        """
252 -
253 -        def passthrough(caller):
254 -            return u'{%% call %s() %%}%s{%% endcall %%}' % (call, caller())
255 -
256 -        parts = call.split('.')
257 -        current_level = self.passthrough_globals
258 -        for part in parts[:-1]:
259 -            if part not in current_level:
260 -                current_level[part] = {}
261 -            current_level = current_level[part]
262 -        current_level[parts[-1]] = passthrough
263 -
264 -    def build_template(self, rules):
265 -        """
266 -        Construct a template that can produce CSR generator strings.
267 -
268 -        :param rules: list of FieldMapping to use to populate the template.
269 -
270 -        :returns: jinja2.Template that can be rendered to produce the CSR data.
271 -        """
272 -        syntax_rules = []
273 -        for field_mapping in rules:
274 -            data_rules_prepared = [
275 -                self._prepare_data_rule(rule)
276 -                for rule in field_mapping.data_rules]
277 -
278 -            data_sources = []
279 -            for rule in field_mapping.data_rules:
280 -                data_source = rule.options.get('data_source')
281 -                if data_source:
282 -                    data_sources.append(data_source)
283 -
284 -            syntax_rules.append(self._prepare_syntax_rule(
285 -                field_mapping.syntax_rule, data_rules_prepared,
286 -                field_mapping.description, data_sources))
287 -
288 -        template_params = self._get_template_params(syntax_rules)
289 -        base_template = self.jinja2.get_template(
290 -            self.base_template_name, globals=self.passthrough_globals)
291 -
292 -        try:
293 -            combined_template_source = base_template.render(**template_params)
294 -        except jinja2.UndefinedError:
295 -            logger.debug(traceback.format_exc())
296 -            raise errors.CSRTemplateError(reason=_(
297 -                'Template error when formatting certificate data'))
298 -
299 -        logger.debug(
300 -            'Formatting with template: %s' % combined_template_source)
301 -        combined_template = self.jinja2.from_string(combined_template_source)
302 -
303 -        return combined_template
304 -
305 -    def _wrap_conditional(self, rule, condition):
306 -        rule = '{%% if %s %%}%s{%% endif %%}' % (condition, rule)
307 -        return rule
308 -
309 -    def _wrap_required(self, rule, description):
310 -        template = '{%% filter required("%s") %%}%s{%% endfilter %%}' % (
311 -            description, rule)
312 -
313 -        return template
314 -
315 -    def _prepare_data_rule(self, data_rule):
316 -        template = data_rule.template
317 -
318 -        data_source = data_rule.options.get('data_source')
319 -        if data_source:
320 -            template = self._wrap_conditional(template, data_source)
321 -
322 -        return template
323 -
324 -    def _prepare_syntax_rule(
325 -            self, syntax_rule, data_rules, description, data_sources):
326 -        logger.debug('Syntax rule template: %s' % syntax_rule.template)
327 -        template = self.jinja2.from_string(
328 -            syntax_rule.template, globals=self.passthrough_globals)
329 -        is_required = syntax_rule.options.get('required', False)
330 -        try:
331 -            prepared_template = template.render(datarules=data_rules)
332 -        except jinja2.UndefinedError:
333 -            logger.debug(traceback.format_exc())
334 -            raise errors.CSRTemplateError(reason=_(
335 -                'Template error when formatting certificate data'))
336 -
337 -        if data_sources:
338 -            combinator = ' %s ' % syntax_rule.options.get(
339 -                'data_source_combinator', 'or')
340 -            condition = combinator.join(data_sources)
341 -            prepared_template = self._wrap_conditional(
342 -                prepared_template, condition)
343 -
344 -        if is_required:
345 -            prepared_template = self._wrap_required(
346 -                prepared_template, description)
347 -
348 -        return prepared_template
349 -
350 -    def _get_template_params(self, syntax_rules):
351 -        """
352 -        Package the syntax rules into fields expected by the base template.
353 -
354 -        :param syntax_rules: list of prepared syntax rules to be included in
355 -            the template.
356 -
357 -        :returns: dict of values needed to render the base template.
358 -        """
359 -        raise NotImplementedError('Formatter class must be subclassed')
360 -
361 -
362 -class OpenSSLFormatter(Formatter):
363 -    """Formatter class supporting the openssl command-line tool."""
364 -
365 -    base_template_name = 'openssl_base.tmpl'
366 -
367 -    # Syntax rules are wrapped in this data structure, to keep track of whether
368 -    # each goes in the extension or the root section
369 -    SyntaxRule = collections.namedtuple(
370 -        'SyntaxRule', ['template', 'is_extension'])
371 -
372 -    def __init__(self, *args, **kwargs):
373 -        super(OpenSSLFormatter, self).__init__(*args, **kwargs)
374 -        self._define_passthrough('openssl.section')
375 -
376 -    def _get_template_params(self, syntax_rules):
377 -        parameters = [rule.template for rule in syntax_rules
378 -                      if not rule.is_extension]
379 -        extensions = [rule.template for rule in syntax_rules
380 -                      if rule.is_extension]
381 -
382 -        return {'parameters': parameters, 'extensions': extensions}
383 -
384 -    def _prepare_syntax_rule(
385 -            self, syntax_rule, data_rules, description, data_sources):
386 -        """Overrides method to pull out whether rule is an extension or not."""
387 -        prepared_template = super(OpenSSLFormatter, self)._prepare_syntax_rule(
388 -            syntax_rule, data_rules, description, data_sources)
389 -        is_extension = syntax_rule.options.get('extension', False)
390 -        return self.SyntaxRule(prepared_template, is_extension)
391 -
392 -
393 -class CertutilFormatter(Formatter):
394 -    base_template_name = 'certutil_base.tmpl'
395 -
396 -    def _get_template_params(self, syntax_rules):
397 -        return {'options': syntax_rules}
398 -
399 -
400 -class FieldMapping(object):
401 -    """Representation of the rules needed to construct a complete cert field.
402 -
403 -    Attributes:
404 -        description: str, a name or description of this field, to be used in
405 -            messages
406 -        syntax_rule: Rule, the rule defining the syntax of this field
407 -        data_rules: list of Rule, the rules that produce data to be stored in
408 -            this field
409 -    """
410 -    __slots__ = ['description', 'syntax_rule', 'data_rules']
411 -
412 -    def __init__(self, description, syntax_rule, data_rules):
413 -        self.description = description
414 -        self.syntax_rule = syntax_rule
415 -        self.data_rules = data_rules
416 -
417 -
418 -class Rule(object):
419 -    __slots__ = ['name', 'template', 'options']
420 -
421 -    def __init__(self, name, template, options):
422 -        self.name = name
423 -        self.template = template
424 -        self.options = options
425 -
426 -
427 -class RuleProvider(object):
428 -    def rules_for_profile(self, profile_id, helper):
429 -        """
430 -        Return the rules needed to build a CSR using the given profile.
431 -
432 -        :param profile_id: str, name of the CSR generation profile to use
433 -        :param helper: str, name of tool (e.g. openssl, certutil) that will be
434 -            used to create CSR
435 -
436 -        :returns: list of FieldMapping, filled out with the appropriate rules
437 -        """
438 -        raise NotImplementedError('RuleProvider class must be subclassed')
439 -
440 -
441 -class FileRuleProvider(RuleProvider):
442 -    def __init__(self, csr_data_dir=None):
443 -        self.rules = {}
444 -        self._csrgen_data_dirs = []
445 -        if csr_data_dir is not None:
446 -            self._csrgen_data_dirs.append(csr_data_dir)
447 -        self._csrgen_data_dirs.append(
448 -            os.path.join(api.env.confdir, 'csrgen')
449 -        )
450 -        self._csrgen_data_dirs.append(
451 -            pkg_resources.resource_filename('ipaclient', 'csrgen')
452 -        )
453 -
454 -    def _open(self, subdir, filename):
455 -        for data_dir in self._csrgen_data_dirs:
456 -            path = os.path.join(data_dir, subdir, filename)
457 -            try:
458 -                return open(path)
459 -            except IOError as e:
460 -                if e.errno != errno.ENOENT:
461 -                    raise
462 -        raise IOError(
463 -            errno.ENOENT,
464 -            "'{}' not found in {}".format(
465 -                os.path.join(subdir, filename),
466 -                ", ".join(self._csrgen_data_dirs)
467 -            )
468 -        )
469 -
470 -    def _rule(self, rule_name, helper):
471 -        if (rule_name, helper) not in self.rules:
472 -            try:
473 -                with self._open('rules', '%s.json' % rule_name) as f:
474 -                    ruleset = json.load(f)
475 -            except IOError:
476 -                raise errors.NotFound(
477 -                    reason=_('Ruleset %(ruleset)s does not exist.') %
478 -                    {'ruleset': rule_name})
479 -
480 -            matching_rules = [r for r in ruleset['rules']
481 -                              if r['helper'] == helper]
482 -            if len(matching_rules) == 0:
483 -                raise errors.EmptyResult(
484 -                    reason=_('No transformation in "%(ruleset)s" rule supports'
485 -                             ' helper "%(helper)s"') %
486 -                    {'ruleset': rule_name, 'helper': helper})
487 -            elif len(matching_rules) > 1:
488 -                raise errors.RedundantMappingRule(
489 -                    ruleset=rule_name, helper=helper)
490 -            rule = matching_rules[0]
491 -
492 -            options = {}
493 -            if 'options' in ruleset:
494 -                options.update(ruleset['options'])
495 -            if 'options' in rule:
496 -                options.update(rule['options'])
497 -
498 -            self.rules[(rule_name, helper)] = Rule(
499 -                rule_name, rule['template'], options)
500 -
501 -        return self.rules[(rule_name, helper)]
502 -
503 -    def rules_for_profile(self, profile_id, helper):
504 -        try:
505 -            with self._open('profiles', '%s.json' % profile_id) as f:
506 -                profile = json.load(f)
507 -        except IOError:
508 -            raise errors.NotFound(
509 -                reason=_('No CSR generation rules are defined for profile'
510 -                         ' %(profile_id)s') % {'profile_id': profile_id})
511 -
512 -        field_mappings = []
513 -        for field in profile:
514 -            syntax_rule = self._rule(field['syntax'], helper)
515 -            data_rules = [self._rule(name, helper) for name in field['data']]
516 -            field_mappings.append(FieldMapping(
517 -                syntax_rule.name, syntax_rule, data_rules))
518 -        return field_mappings
519 -
520 -
521 -class CSRGenerator(object):
522 -    FORMATTERS = {
523 -        'openssl': OpenSSLFormatter,
524 -        'certutil': CertutilFormatter,
525 -    }
526 -
527 -    def __init__(self, rule_provider):
528 -        self.rule_provider = rule_provider
529 -
530 -    def csr_script(self, principal, config, profile_id, helper):
531 -        render_data = {'subject': principal, 'config': config}
532 -
533 -        formatter = self.FORMATTERS[helper]()
534 -        rules = self.rule_provider.rules_for_profile(profile_id, helper)
535 -        template = formatter.build_template(rules)
536 -
537 -        try:
538 -            script = template.render(render_data)
539 -        except jinja2.UndefinedError:
540 -            logger.debug(traceback.format_exc())
541 -            raise errors.CSRTemplateError(reason=_(
542 -                'Template error when formatting certificate data'))
543 -
544 -        return script
545 diff --git a/ipaclient/csrgen/profiles/caIPAserviceCert.json b/ipaclient/csrgen/profiles/caIPAserviceCert.json
546 deleted file mode 100644
547 index 114d2ffd4e0d8eae833eaa594f6a17a79da909be..0000000000000000000000000000000000000000
548 --- a/ipaclient/csrgen/profiles/caIPAserviceCert.json
549 +++ /dev/null
550 @@ -1,15 +0,0 @@
551 -[
552 -    {
553 -        "syntax": "syntaxSubject",
554 -        "data": [
555 -            "dataHostCN",
556 -            "dataSubjectBase"
557 -        ]
558 -    },
559 -    {
560 -        "syntax": "syntaxSAN",
561 -        "data": [
562 -            "dataDNS"
563 -        ]
564 -    }
565 -]
566 diff --git a/ipaclient/csrgen/profiles/userCert.json b/ipaclient/csrgen/profiles/userCert.json
567 deleted file mode 100644
568 index d6cf5cfffcfadd604fc3e8283d1be15767278c7a..0000000000000000000000000000000000000000
569 --- a/ipaclient/csrgen/profiles/userCert.json
570 +++ /dev/null
571 @@ -1,15 +0,0 @@
572 -[
573 -    {
574 -        "syntax": "syntaxSubject",
575 -        "data": [
576 -            "dataUsernameCN",
577 -            "dataSubjectBase"
578 -        ]
579 -    },
580 -    {
581 -        "syntax": "syntaxSAN",
582 -        "data": [
583 -            "dataEmail"
584 -        ]
585 -    }
586 -]
587 diff --git a/ipaclient/csrgen/rules/dataDNS.json b/ipaclient/csrgen/rules/dataDNS.json
588 deleted file mode 100644
589 index 2663f114123a5a73b23f6a41c1b9b3162f157ea1..0000000000000000000000000000000000000000
590 --- a/ipaclient/csrgen/rules/dataDNS.json
591 +++ /dev/null
592 @@ -1,15 +0,0 @@
593 -{
594 -  "rules": [
595 -    {
596 -      "helper": "openssl",
597 -      "template": "DNS = {{subject.krbprincipalname.0.partition('/')[2].partition('@')[0]}}"
598 -    },
599 -    {
600 -      "helper": "certutil",
601 -      "template": "dns:{{subject.krbprincipalname.0.partition('/')[2].partition('@')[0]|quote}}"
602 -    }
603 -  ],
604 -  "options": {
605 -    "data_source": "subject.krbprincipalname.0.partition('/')[2].partition('@')[0]"
606 -  }
607 -}
608 diff --git a/ipaclient/csrgen/rules/dataEmail.json b/ipaclient/csrgen/rules/dataEmail.json
609 deleted file mode 100644
610 index 2eae9fb25e4f09d52ec5e29e2643236641c5cecd..0000000000000000000000000000000000000000
611 --- a/ipaclient/csrgen/rules/dataEmail.json
612 +++ /dev/null
613 @@ -1,15 +0,0 @@
614 -{
615 -  "rules": [
616 -    {
617 -      "helper": "openssl",
618 -      "template": "email = {{subject.mail.0}}"
619 -    },
620 -    {
621 -      "helper": "certutil",
622 -      "template": "email:{{subject.mail.0|quote}}"
623 -    }
624 -  ],
625 -  "options": {
626 -    "data_source": "subject.mail.0"
627 -  }
628 -}
629 diff --git a/ipaclient/csrgen/rules/dataHostCN.json b/ipaclient/csrgen/rules/dataHostCN.json
630 deleted file mode 100644
631 index 5c415bb8cf8911ad8c24820d2466beb57f0d9a82..0000000000000000000000000000000000000000
632 --- a/ipaclient/csrgen/rules/dataHostCN.json
633 +++ /dev/null
634 @@ -1,15 +0,0 @@
635 -{
636 -  "rules": [
637 -    {
638 -      "helper": "openssl",
639 -      "template": "CN={{subject.krbprincipalname.0.partition('/')[2].partition('@')[0]}}"
640 -    },
641 -    {
642 -      "helper": "certutil",
643 -      "template": "CN={{subject.krbprincipalname.0.partition('/')[2].partition('@')[0]|quote}}"
644 -    }
645 -  ],
646 -  "options": {
647 -    "data_source": "subject.krbprincipalname.0.partition('/')[2].partition('@')[0]"
648 -  }
649 -}
650 diff --git a/ipaclient/csrgen/rules/dataSubjectBase.json b/ipaclient/csrgen/rules/dataSubjectBase.json
651 deleted file mode 100644
652 index 309dfb1ed57b0dfe282386181a4c887228545c55..0000000000000000000000000000000000000000
653 --- a/ipaclient/csrgen/rules/dataSubjectBase.json
654 +++ /dev/null
655 @@ -1,15 +0,0 @@
656 -{
657 -  "rules": [
658 -    {
659 -      "helper": "openssl",
660 -      "template": "{{config.ipacertificatesubjectbase.0}}"
661 -    },
662 -    {
663 -      "helper": "certutil",
664 -      "template": "{{config.ipacertificatesubjectbase.0|quote}}"
665 -    }
666 -  ],
667 -  "options": {
668 -    "data_source": "config.ipacertificatesubjectbase.0"
669 -  }
670 -}
671 diff --git a/ipaclient/csrgen/rules/dataUsernameCN.json b/ipaclient/csrgen/rules/dataUsernameCN.json
672 deleted file mode 100644
673 index 37e7e0113ef3146a97383355285dc1d319029e0e..0000000000000000000000000000000000000000
674 --- a/ipaclient/csrgen/rules/dataUsernameCN.json
675 +++ /dev/null
676 @@ -1,15 +0,0 @@
677 -{
678 -  "rules": [
679 -    {
680 -      "helper": "openssl",
681 -      "template": "CN={{subject.uid.0}}"
682 -    },
683 -    {
684 -      "helper": "certutil",
685 -      "template": "CN={{subject.uid.0|quote}}"
686 -    }
687 -  ],
688 -  "options": {
689 -    "data_source": "subject.uid.0"
690 -  }
691 -}
692 diff --git a/ipaclient/csrgen/rules/syntaxSAN.json b/ipaclient/csrgen/rules/syntaxSAN.json
693 deleted file mode 100644
694 index 122eb12443e053490ac50a3984d02a62be61e7aa..0000000000000000000000000000000000000000
695 --- a/ipaclient/csrgen/rules/syntaxSAN.json
696 +++ /dev/null
697 @@ -1,15 +0,0 @@
698 -{
699 -  "rules": [
700 -    {
701 -      "helper": "openssl",
702 -      "template": "subjectAltName = @{% call openssl.section() %}{{ datarules|join('\n') }}{% endcall %}",
703 -      "options": {
704 -        "extension": true
705 -      }
706 -    },
707 -    {
708 -      "helper": "certutil",
709 -      "template": "--extSAN {{ datarules|join(',') }}"
710 -    }
711 -  ]
712 -}
713 diff --git a/ipaclient/csrgen/rules/syntaxSubject.json b/ipaclient/csrgen/rules/syntaxSubject.json
714 deleted file mode 100644
715 index af6ec03d3390ba8f9fac99ed3b6c485f4c1cd64f..0000000000000000000000000000000000000000
716 --- a/ipaclient/csrgen/rules/syntaxSubject.json
717 +++ /dev/null
718 @@ -1,16 +0,0 @@
719 -{
720 -  "rules": [
721 -    {
722 -      "helper": "openssl",
723 -      "template": "distinguished_name = {% call openssl.section() %}{{ datarules|reverse|join('\n') }}{% endcall %}"
724 -    },
725 -    {
726 -      "helper": "certutil",
727 -      "template": "-s {{ datarules|join(',') }}"
728 -    }
729 -  ],
730 -  "options": {
731 -    "required": true,
732 -    "data_source_combinator": "and"
733 -  }
734 -}
735 diff --git a/ipaclient/csrgen/templates/certutil_base.tmpl b/ipaclient/csrgen/templates/certutil_base.tmpl
736 deleted file mode 100644
737 index a5556fda0e6ed854dfe67b816044b36db77d5f76..0000000000000000000000000000000000000000
738 --- a/ipaclient/csrgen/templates/certutil_base.tmpl
739 +++ /dev/null
740 @@ -1,11 +0,0 @@
741 -#!/bin/bash -e
742 -
743 -if [[ $# -lt 1 ]]; then
744 -echo "Usage: $0 <outfile> [<any> <certutil> <args>]"
745 -echo "Called as: $0 $@"
746 -exit 1
747 -fi
748 -
749 -CSR="$1"
750 -shift
751 -certutil -R -a -z <(head -c 4096 /dev/urandom) -o "$CSR" {{ options|join(' ') }} "$@"
752 diff --git a/ipaclient/csrgen/templates/openssl_base.tmpl b/ipaclient/csrgen/templates/openssl_base.tmpl
753 deleted file mode 100644
754 index 22b16862e88eb44c4176ee9c4580188f5b240854..0000000000000000000000000000000000000000
755 --- a/ipaclient/csrgen/templates/openssl_base.tmpl
756 +++ /dev/null
757 @@ -1,35 +0,0 @@
758 -{% raw -%}
759 -{% import "openssl_macros.tmpl" as openssl -%}
760 -{%- endraw %}
761 -#!/bin/bash -e
762 -
763 -if [[ $# -lt 2 ]]; then
764 -echo "Usage: $0 <outfile> <keyfile> <other openssl arguments>"
765 -echo "Called as: $0 $@"
766 -exit 1
767 -fi
768 -
769 -CONFIG="$(mktemp)"
770 -CSR="$1"
771 -KEYFILE="$2"
772 -shift; shift
773 -
774 -echo \
775 -{% raw %}{% filter quote %}{% endraw -%}
776 -[ req ]
777 -prompt = no
778 -encrypt_key = no
779 -
780 -{{ parameters|join('\n') }}
781 -{% raw %}{% set rendered_extensions -%}{% endraw %}
782 -{{ extensions|join('\n') }}
783 -{% raw -%}
784 -{%- endset -%}
785 -{% if rendered_extensions -%}
786 -req_extensions = {% call openssl.section() %}{{ rendered_extensions }}{% endcall %}
787 -{% endif %}
788 -{{ openssl.openssl_sections|join('\n\n') }}
789 -{% endfilter %}{%- endraw %} > "$CONFIG"
790 -
791 -openssl req -new -config "$CONFIG" -out "$CSR" -key "$KEYFILE" "$@"
792 -rm "$CONFIG"
793 diff --git a/ipaclient/csrgen/templates/openssl_macros.tmpl b/ipaclient/csrgen/templates/openssl_macros.tmpl
794 deleted file mode 100644
795 index d31b8fef5f2d85e1b3d5ecf425f00ec9c22ac301..0000000000000000000000000000000000000000
796 --- a/ipaclient/csrgen/templates/openssl_macros.tmpl
797 +++ /dev/null
798 @@ -1,29 +0,0 @@
799 -{# List containing rendered sections to be included at end #}
800 -{% set openssl_sections = [] %}
801 -
802 -{#
803 -List containing one entry for each section name allocated. Because of
804 -scoping rules, we need to use a list so that it can be a "per-render global"
805 -that gets updated in place. Real globals are shared by all templates with the
806 -same environment, and variables defined in the macro don't persist after the
807 -macro invocation ends.
808 -#}
809 -{% set openssl_section_num = [] %}
810 -
811 -{% macro section() -%}
812 -{% set name -%}
813 -sec{{ openssl_section_num|length -}}
814 -{% endset -%}
815 -{% do openssl_section_num.append('') -%}
816 -{% set contents %}{{ caller() }}{% endset -%}
817 -{% if contents -%}
818 -{% set sectiondata = formatsection(name, contents) -%}
819 -{% do openssl_sections.append(sectiondata) -%}
820 -{% endif -%}
821 -{{ name -}}
822 -{% endmacro %}
823 -
824 -{% macro formatsection(name, contents) -%}
825 -[ {{ name }} ]
826 -{{ contents -}}
827 -{% endmacro %}
828 diff --git a/ipaclient/plugins/cert.py b/ipaclient/plugins/cert.py
829 index 93cd3cef1a14925bc0795b32e97e44d69897be5c..8195e04fc43ffbd8ca6589d2652559198759d9e6 100644
830 --- a/ipaclient/plugins/cert.py
831 +++ b/ipaclient/plugins/cert.py
832 @@ -20,10 +20,6 @@
833  # along with this program.  If not, see <http://www.gnu.org/licenses/>.
834  
835  import base64
836 -import subprocess
837 -from tempfile import NamedTemporaryFile as NTF
838 -
839 -import six
840  
841  from ipaclient.frontend import MethodOverride
842  from ipalib import errors
843 @@ -33,9 +29,6 @@ from ipalib.parameters import File, Flag, Str
844  from ipalib.plugable import Registry
845  from ipalib.text import _
846  
847 -if six.PY3:
848 -    unicode = str
849 -
850  register = Registry()
851  
852  
853 @@ -77,99 +70,12 @@ class CertRetrieveOverride(MethodOverride):
854  
855  @register(override=True, no_fail=True)
856  class cert_request(CertRetrieveOverride):
857 -    takes_options = CertRetrieveOverride.takes_options + (
858 -        Str(
859 -            'database?',
860 -            label=_('Path to NSS database'),
861 -            doc=_('Path to NSS database to use for private key'),
862 -        ),
863 -        Str(
864 -            'private_key?',
865 -            label=_('Path to private key file'),
866 -            doc=_('Path to PEM file containing a private key'),
867 -        ),
868 -        Str(
869 -            'password_file?',
870 -            label=_(
871 -                'File containing a password for the private key or database'),
872 -        ),
873 -        Str(
874 -            'csr_profile_id?',
875 -            label=_('Name of CSR generation profile (if not the same as'
876 -                    ' profile_id)'),
877 -        ),
878 -    )
879 -
880      def get_args(self):
881          for arg in super(cert_request, self).get_args():
882              if arg.name == 'csr':
883 -                arg = arg.clone_retype(arg.name, File, required=False)
884 +                arg = arg.clone_retype(arg.name, File)
885              yield arg
886  
887 -    def forward(self, csr=None, **options):
888 -        database = options.pop('database', None)
889 -        private_key = options.pop('private_key', None)
890 -        csr_profile_id = options.pop('csr_profile_id', None)
891 -        password_file = options.pop('password_file', None)
892 -
893 -        if csr is None:
894 -            if database:
895 -                helper = u'certutil'
896 -                helper_args = ['-d', database]
897 -                if password_file:
898 -                    helper_args += ['-f', password_file]
899 -            elif private_key:
900 -                helper = u'openssl'
901 -                helper_args = [private_key]
902 -                if password_file:
903 -                    helper_args += ['-passin', 'file:%s' % password_file]
904 -            else:
905 -                raise errors.InvocationError(
906 -                    message=u"One of 'database' or 'private_key' is required")
907 -
908 -            with NTF() as scriptfile, NTF() as csrfile:
909 -                # If csr_profile_id is passed, that takes precedence.
910 -                # Otherwise, use profile_id. If neither are passed, the default
911 -                # in cert_get_requestdata will be used.
912 -                profile_id = csr_profile_id
913 -                if profile_id is None:
914 -                    profile_id = options.get('profile_id')
915 -
916 -                self.api.Command.cert_get_requestdata(
917 -                    profile_id=profile_id,
918 -                    principal=options.get('principal'),
919 -                    out=unicode(scriptfile.name),
920 -                    helper=helper)
921 -
922 -                helper_cmd = [
923 -                    'bash', '-e', scriptfile.name, csrfile.name] + helper_args
924 -
925 -                try:
926 -                    subprocess.check_output(helper_cmd)
927 -                except subprocess.CalledProcessError as e:
928 -                    raise errors.CertificateOperationError(
929 -                        error=(
930 -                            _('Error running "%(cmd)s" to generate CSR:'
931 -                              ' %(err)s') %
932 -                            {'cmd': ' '.join(helper_cmd), 'err': e.output}))
933 -
934 -                try:
935 -                    csr = unicode(csrfile.read())
936 -                except IOError as e:
937 -                    raise errors.CertificateOperationError(
938 -                        error=(_('Unable to read generated CSR file: %(err)s')
939 -                               % {'err': e}))
940 -                if not csr:
941 -                    raise errors.CertificateOperationError(
942 -                        error=(_('Generated CSR was empty')))
943 -        else:
944 -            if database is not None or private_key is not None:
945 -                raise errors.MutuallyExclusiveError(reason=_(
946 -                    "Options 'database' and 'private_key' are not compatible"
947 -                    " with 'csr'"))
948 -
949 -        return super(cert_request, self).forward(csr, **options)
950 -
951  
952  @register(override=True, no_fail=True)
953  class cert_show(CertRetrieveOverride):
954 diff --git a/ipaclient/plugins/csrgen.py b/ipaclient/plugins/csrgen.py
955 deleted file mode 100644
956 index a0d99ef06445de268cd1872a025d0613e245ae6c..0000000000000000000000000000000000000000
957 --- a/ipaclient/plugins/csrgen.py
958 +++ /dev/null
959 @@ -1,120 +0,0 @@
960 -#
961 -# Copyright (C) 2016  FreeIPA Contributors see COPYING for license
962 -#
963 -
964 -import six
965 -
966 -from ipaclient.csrgen import CSRGenerator, FileRuleProvider
967 -from ipalib import api
968 -from ipalib import errors
969 -from ipalib import output
970 -from ipalib import util
971 -from ipalib.frontend import Local, Str
972 -from ipalib.parameters import Principal
973 -from ipalib.plugable import Registry
974 -from ipalib.text import _
975 -from ipapython import dogtag
976 -
977 -if six.PY3:
978 -    unicode = str
979 -
980 -register = Registry()
981 -
982 -__doc__ = _("""
983 -Commands to build certificate requests automatically
984 -""")
985 -
986 -
987 -@register()
988 -class cert_get_requestdata(Local):
989 -    __doc__ = _('Gather data for a certificate signing request.')
990 -
991 -    NO_CLI = True
992 -
993 -    takes_options = (
994 -        Principal(
995 -            'principal',
996 -            label=_('Principal'),
997 -            doc=_('Principal for this certificate (e.g.'
998 -                  ' HTTP/test.example.com)'),
999 -        ),
1000 -        Str(
1001 -            'profile_id?',
1002 -            label=_('Profile ID'),
1003 -            doc=_('CSR Generation Profile to use'),
1004 -        ),
1005 -        Str(
1006 -            'helper',
1007 -            label=_('Name of CSR generation tool'),
1008 -            doc=_('Name of tool (e.g. openssl, certutil) that will be used to'
1009 -                  ' create CSR'),
1010 -        ),
1011 -        Str(
1012 -            'out?',
1013 -            doc=_('Write CSR generation script to file'),
1014 -        ),
1015 -    )
1016 -
1017 -    has_output = (
1018 -        output.Output(
1019 -            'result',
1020 -            type=dict,
1021 -            doc=_('Dictionary mapping variable name to value'),
1022 -        ),
1023 -    )
1024 -
1025 -    has_output_params = (
1026 -        Str(
1027 -            'script',
1028 -            label=_('Generation script'),
1029 -        )
1030 -    )
1031 -
1032 -    def execute(self, *args, **options):
1033 -        if 'out' in options:
1034 -            util.check_writable_file(options['out'])
1035 -
1036 -        principal = options.get('principal')
1037 -        profile_id = options.get('profile_id')
1038 -        if profile_id is None:
1039 -            profile_id = dogtag.DEFAULT_PROFILE
1040 -        helper = options.get('helper')
1041 -
1042 -        if self.api.env.in_server:
1043 -            backend = self.api.Backend.ldap2
1044 -        else:
1045 -            backend = self.api.Backend.rpcclient
1046 -        if not backend.isconnected():
1047 -            backend.connect()
1048 -
1049 -        try:
1050 -            if principal.is_host:
1051 -                principal_obj = api.Command.host_show(
1052 -                    principal.hostname, all=True)
1053 -            elif principal.is_service:
1054 -                principal_obj = api.Command.service_show(
1055 -                    unicode(principal), all=True)
1056 -            elif principal.is_user:
1057 -                principal_obj = api.Command.user_show(
1058 -                    principal.username, all=True)
1059 -        except errors.NotFound:
1060 -            raise errors.NotFound(
1061 -                reason=_("The principal for this request doesn't exist."))
1062 -        principal_obj = principal_obj['result']
1063 -        config = api.Command.config_show()['result']
1064 -
1065 -        generator = CSRGenerator(FileRuleProvider())
1066 -
1067 -        script = generator.csr_script(
1068 -            principal_obj, config, profile_id, helper)
1069 -
1070 -        result = {}
1071 -        if 'out' in options:
1072 -            with open(options['out'], 'wb') as f:
1073 -                f.write(script)
1074 -        else:
1075 -            result = dict(script=script)
1076 -
1077 -        return dict(
1078 -            result=result
1079 -        )
1080 diff --git a/ipaclient/setup.py b/ipaclient/setup.py
3f51ca 1081 index d39235ab237fb2dbf902866ddcc5e92f8767bcc8..9c6a1558a2d2eace9afbc008a4cb86939fb0047f 100644
ac7d03 1082 --- a/ipaclient/setup.py
CS 1083 +++ b/ipaclient/setup.py
3f51ca 1084 @@ -42,13 +42,6 @@ if __name__ == '__main__':
ac7d03 1085              "ipaclient.remote_plugins.2_156",
CS 1086              "ipaclient.remote_plugins.2_164",
1087          ],
1088 -        package_data={
1089 -            'ipaclient': [
1090 -                'csrgen/profiles/*.json',
1091 -                'csrgen/rules/*.json',
1092 -                'csrgen/templates/*.tmpl',
1093 -            ],
1094 -        },
1095          install_requires=[
1096              "cryptography",
1097              "ipalib",
1098 diff --git a/ipalib/errors.py b/ipalib/errors.py
1099 index 6aaca708a02e609f11c4aa5ef5fe2b4a8ae8a941..88707ac313fa7c5ec247b3f9b71f96925f5627e2 100644
1100 --- a/ipalib/errors.py
1101 +++ b/ipalib/errors.py
1102 @@ -1422,34 +1422,6 @@ class HTTPRequestError(RemoteRetrieveError):
1103      format = _('Request failed with status %(status)s: %(reason)s')
1104  
1105  
1106 -class RedundantMappingRule(SingleMatchExpected):
1107 -    """
1108 -    **4036** Raised when more than one rule in a CSR generation ruleset matches
1109 -    a particular helper.
1110 -
1111 -    For example:
1112 -
1113 -    >>> raise RedundantMappingRule(ruleset='syntaxSubject', helper='certutil')
1114 -    Traceback (most recent call last):
1115 -      ...
1116 -    RedundantMappingRule: Mapping ruleset "syntaxSubject" has more than one
1117 -    rule for the certutil helper.
1118 -    """
1119 -
1120 -    errno = 4036
1121 -    format = _('Mapping ruleset "%(ruleset)s" has more than one rule for the'
1122 -               ' %(helper)s helper')
1123 -
1124 -
1125 -class CSRTemplateError(ExecutionError):
1126 -    """
1127 -    **4037** Raised when evaluation of a CSR generation template fails
1128 -    """
1129 -
1130 -    errno = 4037
1131 -    format = _('%(reason)s')
1132 -
1133 -
1134  class BuiltinError(ExecutionError):
1135      """
1136      **4100** Base class for builtin execution errors (*4100 - 4199*).
1137 diff --git a/ipatests/setup.py b/ipatests/setup.py
3f51ca 1138 index c6c9cb69dbed0561365a10a08061ccc6fe0f372e..712576be6c7a523d3c23a23bdf55289e21ac8867 100644
ac7d03 1139 --- a/ipatests/setup.py
CS 1140 +++ b/ipatests/setup.py
3f51ca 1141 @@ -39,7 +39,6 @@ if __name__ == '__main__':
ac7d03 1142              "ipatests.test_cmdline",
CS 1143              "ipatests.test_install",
1144              "ipatests.test_integration",
1145 -            "ipatests.test_ipaclient",
1146              "ipatests.test_ipalib",
1147              "ipatests.test_ipapython",
1148              "ipatests.test_ipaserver",
3f51ca 1149 @@ -53,7 +52,6 @@ if __name__ == '__main__':
ac7d03 1150          package_data={
CS 1151              'ipatests.test_install': ['*.update'],
1152              'ipatests.test_integration': ['scripts/*'],
1153 -            'ipatests.test_ipaclient': ['data/*/*/*'],
1154              'ipatests.test_ipalib': ['data/*'],
1155              'ipatests.test_pkcs10': ['*.csr'],
1156              "ipatests.test_ipaserver": ['data/*'],
1157 diff --git a/ipatests/test_ipaclient/__init__.py b/ipatests/test_ipaclient/__init__.py
1158 deleted file mode 100644
1159 index 0c428910cabe103af3ac9bfe4cdde6678acd1585..0000000000000000000000000000000000000000
1160 --- a/ipatests/test_ipaclient/__init__.py
1161 +++ /dev/null
1162 @@ -1,7 +0,0 @@
1163 -#
1164 -# Copyright (C) 2016  FreeIPA Contributors see COPYING for license
1165 -#
1166 -
1167 -"""
1168 -Sub-package containing unit tests for `ipaclient` package.
1169 -"""
1170 diff --git a/ipatests/test_ipaclient/data/test_csrgen/profiles/profile.json b/ipatests/test_ipaclient/data/test_csrgen/profiles/profile.json
1171 deleted file mode 100644
1172 index 676f91bef696109976826e6e61be091718172798..0000000000000000000000000000000000000000
1173 --- a/ipatests/test_ipaclient/data/test_csrgen/profiles/profile.json
1174 +++ /dev/null
1175 @@ -1,8 +0,0 @@
1176 -[
1177 -    {
1178 -        "syntax": "basic",
1179 -        "data": [
1180 -            "options"
1181 -        ]
1182 -    }
1183 -]
1184 diff --git a/ipatests/test_ipaclient/data/test_csrgen/rules/basic.json b/ipatests/test_ipaclient/data/test_csrgen/rules/basic.json
1185 deleted file mode 100644
1186 index feba3e91e53c5c9becb44c0d2190b5a98c04a928..0000000000000000000000000000000000000000
1187 --- a/ipatests/test_ipaclient/data/test_csrgen/rules/basic.json
1188 +++ /dev/null
1189 @@ -1,12 +0,0 @@
1190 -{
1191 -  "rules": [
1192 -    {
1193 -      "helper": "openssl",
1194 -      "template": "openssl_rule"
1195 -    },
1196 -    {
1197 -      "helper": "certutil",
1198 -      "template": "certutil_rule"
1199 -    }
1200 -  ]
1201 -}
1202 diff --git a/ipatests/test_ipaclient/data/test_csrgen/rules/options.json b/ipatests/test_ipaclient/data/test_csrgen/rules/options.json
1203 deleted file mode 100644
1204 index 111a6d80c8faf27376dac342a18aede1fb1242ef..0000000000000000000000000000000000000000
1205 --- a/ipatests/test_ipaclient/data/test_csrgen/rules/options.json
1206 +++ /dev/null
1207 @@ -1,18 +0,0 @@
1208 -{
1209 -  "rules": [
1210 -    {
1211 -      "helper": "openssl",
1212 -      "template": "openssl_rule",
1213 -      "options": {
1214 -        "helper_option": true
1215 -      }
1216 -    },
1217 -    {
1218 -      "helper": "certutil",
1219 -      "template": "certutil_rule"
1220 -    }
1221 -  ],
1222 -  "options": {
1223 -    "global_option": true
1224 -  }
1225 -}
1226 diff --git a/ipatests/test_ipaclient/data/test_csrgen/scripts/caIPAserviceCert_certutil.sh b/ipatests/test_ipaclient/data/test_csrgen/scripts/caIPAserviceCert_certutil.sh
1227 deleted file mode 100644
1228 index 74a704c2dd1765c7b775fded8ed957715b264b91..0000000000000000000000000000000000000000
1229 --- a/ipatests/test_ipaclient/data/test_csrgen/scripts/caIPAserviceCert_certutil.sh
1230 +++ /dev/null
1231 @@ -1,11 +0,0 @@
1232 -#!/bin/bash -e
1233 -
1234 -if [[ $# -lt 1 ]]; then
1235 -echo "Usage: $0 <outfile> [<any> <certutil> <args>]"
1236 -echo "Called as: $0 $@"
1237 -exit 1
1238 -fi
1239 -
1240 -CSR="$1"
1241 -shift
1242 -certutil -R -a -z <(head -c 4096 /dev/urandom) -o "$CSR" -s CN=machine.example.com,O=DOMAIN.EXAMPLE.COM --extSAN dns:machine.example.com "$@"
1243 diff --git a/ipatests/test_ipaclient/data/test_csrgen/scripts/caIPAserviceCert_openssl.sh b/ipatests/test_ipaclient/data/test_csrgen/scripts/caIPAserviceCert_openssl.sh
1244 deleted file mode 100644
1245 index 811bfd763e27678adaf681a430e909b24680aeda..0000000000000000000000000000000000000000
1246 --- a/ipatests/test_ipaclient/data/test_csrgen/scripts/caIPAserviceCert_openssl.sh
1247 +++ /dev/null
1248 @@ -1,34 +0,0 @@
1249 -#!/bin/bash -e
1250 -
1251 -if [[ $# -lt 2 ]]; then
1252 -echo "Usage: $0 <outfile> <keyfile> <other openssl arguments>"
1253 -echo "Called as: $0 $@"
1254 -exit 1
1255 -fi
1256 -
1257 -CONFIG="$(mktemp)"
1258 -CSR="$1"
1259 -KEYFILE="$2"
1260 -shift; shift
1261 -
1262 -echo \
1263 -'[ req ]
1264 -prompt = no
1265 -encrypt_key = no
1266 -
1267 -distinguished_name = sec0
1268 -req_extensions = sec2
1269 -
1270 -[ sec0 ]
1271 -O=DOMAIN.EXAMPLE.COM
1272 -CN=machine.example.com
1273 -
1274 -[ sec1 ]
1275 -DNS = machine.example.com
1276 -
1277 -[ sec2 ]
1278 -subjectAltName = @sec1
1279 -' > "$CONFIG"
1280 -
1281 -openssl req -new -config "$CONFIG" -out "$CSR" -key "$KEYFILE" "$@"
1282 -rm "$CONFIG"
1283 diff --git a/ipatests/test_ipaclient/data/test_csrgen/scripts/userCert_certutil.sh b/ipatests/test_ipaclient/data/test_csrgen/scripts/userCert_certutil.sh
1284 deleted file mode 100644
1285 index 4aaeda07aabd4c36d277e339d0b761f7a8a54baf..0000000000000000000000000000000000000000
1286 --- a/ipatests/test_ipaclient/data/test_csrgen/scripts/userCert_certutil.sh
1287 +++ /dev/null
1288 @@ -1,11 +0,0 @@
1289 -#!/bin/bash -e
1290 -
1291 -if [[ $# -lt 1 ]]; then
1292 -echo "Usage: $0 <outfile> [<any> <certutil> <args>]"
1293 -echo "Called as: $0 $@"
1294 -exit 1
1295 -fi
1296 -
1297 -CSR="$1"
1298 -shift
1299 -certutil -R -a -z <(head -c 4096 /dev/urandom) -o "$CSR" -s CN=testuser,O=DOMAIN.EXAMPLE.COM --extSAN email:testuser@example.com "$@"
1300 diff --git a/ipatests/test_ipaclient/data/test_csrgen/scripts/userCert_openssl.sh b/ipatests/test_ipaclient/data/test_csrgen/scripts/userCert_openssl.sh
1301 deleted file mode 100644
1302 index 2edf067a528456877025f63dca76d68e7edde41e..0000000000000000000000000000000000000000
1303 --- a/ipatests/test_ipaclient/data/test_csrgen/scripts/userCert_openssl.sh
1304 +++ /dev/null
1305 @@ -1,34 +0,0 @@
1306 -#!/bin/bash -e
1307 -
1308 -if [[ $# -lt 2 ]]; then
1309 -echo "Usage: $0 <outfile> <keyfile> <other openssl arguments>"
1310 -echo "Called as: $0 $@"
1311 -exit 1
1312 -fi
1313 -
1314 -CONFIG="$(mktemp)"
1315 -CSR="$1"
1316 -KEYFILE="$2"
1317 -shift; shift
1318 -
1319 -echo \
1320 -'[ req ]
1321 -prompt = no
1322 -encrypt_key = no
1323 -
1324 -distinguished_name = sec0
1325 -req_extensions = sec2
1326 -
1327 -[ sec0 ]
1328 -O=DOMAIN.EXAMPLE.COM
1329 -CN=testuser
1330 -
1331 -[ sec1 ]
1332 -email = testuser@example.com
1333 -
1334 -[ sec2 ]
1335 -subjectAltName = @sec1
1336 -' > "$CONFIG"
1337 -
1338 -openssl req -new -config "$CONFIG" -out "$CSR" -key "$KEYFILE" "$@"
1339 -rm "$CONFIG"
1340 diff --git a/ipatests/test_ipaclient/data/test_csrgen/templates/identity_base.tmpl b/ipatests/test_ipaclient/data/test_csrgen/templates/identity_base.tmpl
1341 deleted file mode 100644
1342 index 79111ab686b4fe25227796509b3cd3fcb54af728..0000000000000000000000000000000000000000
1343 --- a/ipatests/test_ipaclient/data/test_csrgen/templates/identity_base.tmpl
1344 +++ /dev/null
1345 @@ -1 +0,0 @@
1346 -{{ options|join(";") }}
1347 diff --git a/ipatests/test_ipaclient/test_csrgen.py b/ipatests/test_ipaclient/test_csrgen.py
1348 deleted file mode 100644
1349 index 556f8e096976387d24057084c06d53bcb9998a69..0000000000000000000000000000000000000000
1350 --- a/ipatests/test_ipaclient/test_csrgen.py
1351 +++ /dev/null
1352 @@ -1,298 +0,0 @@
1353 -#
1354 -# Copyright (C) 2016  FreeIPA Contributors see COPYING for license
1355 -#
1356 -
1357 -import os
1358 -import pytest
1359 -
1360 -from ipaclient import csrgen
1361 -from ipalib import errors
1362 -
1363 -BASE_DIR = os.path.dirname(__file__)
1364 -CSR_DATA_DIR = os.path.join(BASE_DIR, 'data', 'test_csrgen')
1365 -
1366 -
1367 -@pytest.fixture
1368 -def formatter():
1369 -    return csrgen.Formatter(csr_data_dir=CSR_DATA_DIR)
1370 -
1371 -
1372 -@pytest.fixture
1373 -def rule_provider():
1374 -    return csrgen.FileRuleProvider(csr_data_dir=CSR_DATA_DIR)
1375 -
1376 -
1377 -@pytest.fixture
1378 -def generator():
1379 -    return csrgen.CSRGenerator(csrgen.FileRuleProvider())
1380 -
1381 -
1382 -class StubRuleProvider(csrgen.RuleProvider):
1383 -    def __init__(self):
1384 -        self.syntax_rule = csrgen.Rule(
1385 -            'syntax', '{{datarules|join(",")}}', {})
1386 -        self.data_rule = csrgen.Rule('data', 'data_template', {})
1387 -        self.field_mapping = csrgen.FieldMapping(
1388 -            'example', self.syntax_rule, [self.data_rule])
1389 -        self.rules = [self.field_mapping]
1390 -
1391 -    def rules_for_profile(self, profile_id, helper):
1392 -        return self.rules
1393 -
1394 -
1395 -class IdentityFormatter(csrgen.Formatter):
1396 -    base_template_name = 'identity_base.tmpl'
1397 -
1398 -    def __init__(self):
1399 -        super(IdentityFormatter, self).__init__(csr_data_dir=CSR_DATA_DIR)
1400 -
1401 -    def _get_template_params(self, syntax_rules):
1402 -        return {'options': syntax_rules}
1403 -
1404 -
1405 -class IdentityCSRGenerator(csrgen.CSRGenerator):
1406 -    FORMATTERS = {'identity': IdentityFormatter}
1407 -
1408 -
1409 -class test_Formatter(object):
1410 -    def test_prepare_data_rule_with_data_source(self, formatter):
1411 -        data_rule = csrgen.Rule('uid', '{{subject.uid.0}}',
1412 -                                {'data_source': 'subject.uid.0'})
1413 -        prepared = formatter._prepare_data_rule(data_rule)
1414 -        assert prepared == '{% if subject.uid.0 %}{{subject.uid.0}}{% endif %}'
1415 -
1416 -    def test_prepare_data_rule_no_data_source(self, formatter):
1417 -        """Not a normal case, but we should handle it anyway"""
1418 -        data_rule = csrgen.Rule('uid', 'static_text', {})
1419 -        prepared = formatter._prepare_data_rule(data_rule)
1420 -        assert prepared == 'static_text'
1421 -
1422 -    def test_prepare_syntax_rule_with_data_sources(self, formatter):
1423 -        syntax_rule = csrgen.Rule(
1424 -            'example', '{{datarules|join(",")}}', {})
1425 -        data_rules = ['{{subject.field1}}', '{{subject.field2}}']
1426 -        data_sources = ['subject.field1', 'subject.field2']
1427 -        prepared = formatter._prepare_syntax_rule(
1428 -            syntax_rule, data_rules, 'example', data_sources)
1429 -
1430 -        assert prepared == (
1431 -            '{% if subject.field1 or subject.field2 %}{{subject.field1}},'
1432 -            '{{subject.field2}}{% endif %}')
1433 -
1434 -    def test_prepare_syntax_rule_with_combinator(self, formatter):
1435 -        syntax_rule = csrgen.Rule('example', '{{datarules|join(",")}}',
1436 -                                  {'data_source_combinator': 'and'})
1437 -        data_rules = ['{{subject.field1}}', '{{subject.field2}}']
1438 -        data_sources = ['subject.field1', 'subject.field2']
1439 -        prepared = formatter._prepare_syntax_rule(
1440 -            syntax_rule, data_rules, 'example', data_sources)
1441 -
1442 -        assert prepared == (
1443 -            '{% if subject.field1 and subject.field2 %}{{subject.field1}},'
1444 -            '{{subject.field2}}{% endif %}')
1445 -
1446 -    def test_prepare_syntax_rule_required(self, formatter):
1447 -        syntax_rule = csrgen.Rule('example', '{{datarules|join(",")}}',
1448 -                                  {'required': True})
1449 -        data_rules = ['{{subject.field1}}']
1450 -        data_sources = ['subject.field1']
1451 -        prepared = formatter._prepare_syntax_rule(
1452 -            syntax_rule, data_rules, 'example', data_sources)
1453 -
1454 -        assert prepared == (
1455 -            '{% filter required("example") %}{% if subject.field1 %}'
1456 -            '{{subject.field1}}{% endif %}{% endfilter %}')
1457 -
1458 -    def test_prepare_syntax_rule_passthrough(self, formatter):
1459 -        """
1460 -        Calls to macros defined as passthrough are still call tags in the final
1461 -        template.
1462 -        """
1463 -        formatter._define_passthrough('example.macro')
1464 -
1465 -        syntax_rule = csrgen.Rule(
1466 -            'example',
1467 -            '{% call example.macro() %}{{datarules|join(",")}}{% endcall %}',
1468 -            {})
1469 -        data_rules = ['{{subject.field1}}']
1470 -        data_sources = ['subject.field1']
1471 -        prepared = formatter._prepare_syntax_rule(
1472 -            syntax_rule, data_rules, 'example', data_sources)
1473 -
1474 -        assert prepared == (
1475 -            '{% if subject.field1 %}{% call example.macro() %}'
1476 -            '{{subject.field1}}{% endcall %}{% endif %}')
1477 -
1478 -    def test_prepare_syntax_rule_no_data_sources(self, formatter):
1479 -        """Not a normal case, but we should handle it anyway"""
1480 -        syntax_rule = csrgen.Rule(
1481 -            'example', '{{datarules|join(",")}}', {})
1482 -        data_rules = ['rule1', 'rule2']
1483 -        data_sources = []
1484 -        prepared = formatter._prepare_syntax_rule(
1485 -            syntax_rule, data_rules, 'example', data_sources)
1486 -
1487 -        assert prepared == 'rule1,rule2'
1488 -
1489 -
1490 -class test_FileRuleProvider(object):
1491 -    def test_rule_basic(self, rule_provider):
1492 -        rule_name = 'basic'
1493 -
1494 -        rule1 = rule_provider._rule(rule_name, 'openssl')
1495 -        rule2 = rule_provider._rule(rule_name, 'certutil')
1496 -
1497 -        assert rule1.template == 'openssl_rule'
1498 -        assert rule2.template == 'certutil_rule'
1499 -
1500 -    def test_rule_global_options(self, rule_provider):
1501 -        rule_name = 'options'
1502 -
1503 -        rule1 = rule_provider._rule(rule_name, 'openssl')
1504 -        rule2 = rule_provider._rule(rule_name, 'certutil')
1505 -
1506 -        assert rule1.options['global_option'] is True
1507 -        assert rule2.options['global_option'] is True
1508 -
1509 -    def test_rule_helper_options(self, rule_provider):
1510 -        rule_name = 'options'
1511 -
1512 -        rule1 = rule_provider._rule(rule_name, 'openssl')
1513 -        rule2 = rule_provider._rule(rule_name, 'certutil')
1514 -
1515 -        assert rule1.options['helper_option'] is True
1516 -        assert 'helper_option' not in rule2.options
1517 -
1518 -    def test_rule_nosuchrule(self, rule_provider):
1519 -        with pytest.raises(errors.NotFound):
1520 -            rule_provider._rule('nosuchrule', 'openssl')
1521 -
1522 -    def test_rule_nosuchhelper(self, rule_provider):
1523 -        with pytest.raises(errors.EmptyResult):
1524 -            rule_provider._rule('basic', 'nosuchhelper')
1525 -
1526 -    def test_rules_for_profile_success(self, rule_provider):
1527 -        rules = rule_provider.rules_for_profile('profile', 'certutil')
1528 -
1529 -        assert len(rules) == 1
1530 -        field_mapping = rules[0]
1531 -        assert field_mapping.syntax_rule.name == 'basic'
1532 -        assert len(field_mapping.data_rules) == 1
1533 -        assert field_mapping.data_rules[0].name == 'options'
1534 -
1535 -    def test_rules_for_profile_nosuchprofile(self, rule_provider):
1536 -        with pytest.raises(errors.NotFound):
1537 -            rule_provider.rules_for_profile('nosuchprofile', 'certutil')
1538 -
1539 -
1540 -class test_CSRGenerator(object):
1541 -    def test_userCert_OpenSSL(self, generator):
1542 -        principal = {
1543 -            'uid': ['testuser'],
1544 -            'mail': ['testuser@example.com'],
1545 -        }
1546 -        config = {
1547 -            'ipacertificatesubjectbase': [
1548 -                'O=DOMAIN.EXAMPLE.COM'
1549 -            ],
1550 -        }
1551 -
1552 -        script = generator.csr_script(principal, config, 'userCert', 'openssl')
1553 -        with open(os.path.join(
1554 -                CSR_DATA_DIR, 'scripts', 'userCert_openssl.sh')) as f:
1555 -            expected_script = f.read()
1556 -        assert script == expected_script
1557 -
1558 -    def test_userCert_Certutil(self, generator):
1559 -        principal = {
1560 -            'uid': ['testuser'],
1561 -            'mail': ['testuser@example.com'],
1562 -        }
1563 -        config = {
1564 -            'ipacertificatesubjectbase': [
1565 -                'O=DOMAIN.EXAMPLE.COM'
1566 -            ],
1567 -        }
1568 -
1569 -        script = generator.csr_script(
1570 -            principal, config, 'userCert', 'certutil')
1571 -
1572 -        with open(os.path.join(
1573 -                CSR_DATA_DIR, 'scripts', 'userCert_certutil.sh')) as f:
1574 -            expected_script = f.read()
1575 -        assert script == expected_script
1576 -
1577 -    def test_caIPAserviceCert_OpenSSL(self, generator):
1578 -        principal = {
1579 -            'krbprincipalname': [
1580 -                'HTTP/machine.example.com@DOMAIN.EXAMPLE.COM'
1581 -            ],
1582 -        }
1583 -        config = {
1584 -            'ipacertificatesubjectbase': [
1585 -                'O=DOMAIN.EXAMPLE.COM'
1586 -            ],
1587 -        }
1588 -
1589 -        script = generator.csr_script(
1590 -            principal, config, 'caIPAserviceCert', 'openssl')
1591 -        with open(os.path.join(
1592 -                CSR_DATA_DIR, 'scripts', 'caIPAserviceCert_openssl.sh')) as f:
1593 -            expected_script = f.read()
1594 -        assert script == expected_script
1595 -
1596 -    def test_caIPAserviceCert_Certutil(self, generator):
1597 -        principal = {
1598 -            'krbprincipalname': [
1599 -                'HTTP/machine.example.com@DOMAIN.EXAMPLE.COM'
1600 -            ],
1601 -        }
1602 -        config = {
1603 -            'ipacertificatesubjectbase': [
1604 -                'O=DOMAIN.EXAMPLE.COM'
1605 -            ],
1606 -        }
1607 -
1608 -        script = generator.csr_script(
1609 -            principal, config, 'caIPAserviceCert', 'certutil')
1610 -        with open(os.path.join(
1611 -                CSR_DATA_DIR, 'scripts', 'caIPAserviceCert_certutil.sh')) as f:
1612 -            expected_script = f.read()
1613 -        assert script == expected_script
1614 -
1615 -
1616 -class test_rule_handling(object):
1617 -    def test_optionalAttributeMissing(self, generator):
1618 -        principal = {'uid': 'testuser'}
1619 -        rule_provider = StubRuleProvider()
1620 -        rule_provider.data_rule.template = '{{subject.mail}}'
1621 -        rule_provider.data_rule.options = {'data_source': 'subject.mail'}
1622 -        generator = IdentityCSRGenerator(rule_provider)
1623 -
1624 -        script = generator.csr_script(
1625 -            principal, {}, 'example', 'identity')
1626 -        assert script == '\n'
1627 -
1628 -    def test_twoDataRulesOneMissing(self, generator):
1629 -        principal = {'uid': 'testuser'}
1630 -        rule_provider = StubRuleProvider()
1631 -        rule_provider.data_rule.template = '{{subject.mail}}'
1632 -        rule_provider.data_rule.options = {'data_source': 'subject.mail'}
1633 -        rule_provider.field_mapping.data_rules.append(csrgen.Rule(
1634 -            'data2', '{{subject.uid}}', {'data_source': 'subject.uid'}))
1635 -        generator = IdentityCSRGenerator(rule_provider)
1636 -
1637 -        script = generator.csr_script(principal, {}, 'example', 'identity')
1638 -        assert script == ',testuser\n'
1639 -
1640 -    def test_requiredAttributeMissing(self):
1641 -        principal = {'uid': 'testuser'}
1642 -        rule_provider = StubRuleProvider()
1643 -        rule_provider.data_rule.template = '{{subject.mail}}'
1644 -        rule_provider.data_rule.options = {'data_source': 'subject.mail'}
1645 -        rule_provider.syntax_rule.options = {'required': True}
1646 -        generator = IdentityCSRGenerator(rule_provider)
1647 -
1648 -        with pytest.raises(errors.CSRTemplateError):
1649 -            _script = generator.csr_script(
1650 -                principal, {}, 'example', 'identity')
1651 -- 
beb795 1652 2.14.3
ac7d03 1653