[Freeipa-devel] [freeipa PR#433][synchronized] csrgen: Allow some certificate fields to be specified by the user
URL: https://github.com/freeipa/freeipa/pull/433 Author: LiptonB Title: #433: csrgen: Allow some certificate fields to be specified by the user Action: synchronized To pull the PR as Git branch: git remote add ghfreeipa https://github.com/freeipa/freeipa git fetch ghfreeipa pull/433/head:pr433 git checkout pr433 From bf80c8e7c5ae1e67a497b06819ef56bfedc4339a Mon Sep 17 00:00:00 2001 From: Ben LiptonDate: Thu, 28 Jul 2016 16:21:44 -0400 Subject: [PATCH 1/3] csrgen: Implement fields that prompt user for data Allows some data to be user-specified rather than coming out of the database. The provided data can be formatted with jinja2 rules just as database values can. https://fedorahosted.org/freeipa/ticket/4899 --- ipaclient/csrgen.py| 35 -- ipaclient/csrgen/rules/dataEmailUserSpecified.json | 16 ++ ipaclient/plugins/csrgen.py| 10 +-- ipatests/test_ipaclient/test_csrgen.py | 11 +++ 4 files changed, 63 insertions(+), 9 deletions(-) create mode 100644 ipaclient/csrgen/rules/dataEmailUserSpecified.json diff --git a/ipaclient/csrgen.py b/ipaclient/csrgen.py index 0f52a8b..67442f6 100644 --- a/ipaclient/csrgen.py +++ b/ipaclient/csrgen.py @@ -372,8 +372,9 @@ def __init__(self, rule_provider, formatter_class=OpenSSLFormatter): self.rule_provider = rule_provider self.formatter = formatter_class() -def csr_config(self, principal, config, profile_id): -render_data = {'subject': principal, 'config': config} +def csr_config(self, principal, config, userdata, profile_id): +render_data = { +'subject': principal, 'config': config, 'userdata': userdata} rules = self.rule_provider.rules_for_profile(profile_id) template = self.formatter.build_template(rules) @@ -387,6 +388,36 @@ def csr_config(self, principal, config, profile_id): return config +def get_user_prompts(self, profile_id): +prompts = {} +rules = self.rule_provider.rules_for_profile(profile_id) + +for field_mapping in rules: +for rule in field_mapping.data_rules: +if 'prompt' in rule.options: +try: +var = rule.options['data_source'] +except KeyError: +raise errors.CSRTemplateError(reason=_( +'Certificate mapping rule %(rule)s has a prompt' +' but no data_source set') % {'rule': rule.name}) +if var in prompts: +raise errors.CSRTemplateError(reason=_( +'More than one data rule in this profile prompts' +' for the %(item)s data item') % {'item': var}) +var_parts = var.split('.') +if len(var_parts) != 2 or var_parts[0] != 'userdata': +raise errors.CSRTemplateError( +reason=_( +'Format of variable name in rule %(rule)s is' +' incorrect. Rules that prompt for data must' +' use a variable "userdata."') % +{'rule': rule.name}) + +prompts[var_parts[1]] = rule.options['prompt'] + +return prompts + class CSRLibraryAdaptor(object): def get_subject_public_key_info(self): diff --git a/ipaclient/csrgen/rules/dataEmailUserSpecified.json b/ipaclient/csrgen/rules/dataEmailUserSpecified.json new file mode 100644 index 000..3fb2fb1 --- /dev/null +++ b/ipaclient/csrgen/rules/dataEmailUserSpecified.json @@ -0,0 +1,16 @@ +{ + "rules": [ +{ + "helper": "openssl", + "template": "email = {{userdata.email}}" +}, +{ + "helper": "certutil", + "template": "email:{{userdata.email|quote}}" +} + ], + "options": { +"data_source": "userdata.email", +"prompt": "Email address" + } +} diff --git a/ipaclient/plugins/csrgen.py b/ipaclient/plugins/csrgen.py index 568a79f..6503f57 100644 --- a/ipaclient/plugins/csrgen.py +++ b/ipaclient/plugins/csrgen.py @@ -90,6 +90,9 @@ def execute(self, *args, **options): if not backend.isconnected(): backend.connect() +generator = csrgen.CSRGenerator(csrgen.FileRuleProvider()) +prompts = generator.get_user_prompts(profile_id, helper) + try: if principal.is_host: principal_obj = api.Command.host_show( @@ -106,9 +109,12 @@ def execute(self, *args, **options): principal_obj = principal_obj['result'] config = api.Command.config_show()['result'] -generator = csrgen.CSRGenerator(csrgen.FileRuleProvider()) +userdata = {} +for name, prompt in prompts.items(): +userdata[name] = self.Backend.textui.prompt(prompt) -
[Freeipa-devel] [freeipa PR#433][synchronized] csrgen: Allow some certificate fields to be specified by the user
URL: https://github.com/freeipa/freeipa/pull/433 Author: LiptonB Title: #433: csrgen: Allow some certificate fields to be specified by the user Action: synchronized To pull the PR as Git branch: git remote add ghfreeipa https://github.com/freeipa/freeipa git fetch ghfreeipa pull/433/head:pr433 git checkout pr433 From 61a825b57f923ca7b641bca5f436d4b41f3acfb8 Mon Sep 17 00:00:00 2001 From: Ben LiptonDate: Thu, 28 Jul 2016 16:21:44 -0400 Subject: [PATCH 1/3] csrgen: Implement fields that prompt user for data Allows some data to be user-specified rather than coming out of the database. The provided data can be formatted with jinja2 rules just as database values can. https://fedorahosted.org/freeipa/ticket/4899 --- ipaclient/csrgen.py| 35 -- ipaclient/csrgen/rules/dataEmailUserSpecified.json | 16 ++ ipaclient/plugins/csrgen.py| 9 -- ipatests/test_ipaclient/test_csrgen.py | 15 +- 4 files changed, 64 insertions(+), 11 deletions(-) create mode 100644 ipaclient/csrgen/rules/dataEmailUserSpecified.json diff --git a/ipaclient/csrgen.py b/ipaclient/csrgen.py index 8fb0b32..41a4352 100644 --- a/ipaclient/csrgen.py +++ b/ipaclient/csrgen.py @@ -381,8 +381,9 @@ class CSRGenerator(object): def __init__(self, rule_provider): self.rule_provider = rule_provider -def csr_script(self, principal, config, profile_id, helper): -render_data = {'subject': principal, 'config': config} +def csr_script(self, principal, config, userdata, profile_id, helper): +render_data = { +'subject': principal, 'config': config, 'userdata': userdata} formatter = self.FORMATTERS[helper]() rules = self.rule_provider.rules_for_profile(profile_id, helper) @@ -396,3 +397,33 @@ def csr_script(self, principal, config, profile_id, helper): 'Template error when formatting certificate data')) return script + +def get_user_prompts(self, profile_id, helper): +prompts = {} +rules = self.rule_provider.rules_for_profile(profile_id, helper) + +for field_mapping in rules: +for rule in field_mapping.data_rules: +if 'prompt' in rule.options: +try: +var = rule.options['data_source'] +except KeyError: +raise errors.CSRTemplateError(reason=_( +'Certificate mapping rule %(rule)s has a prompt' +' but no data_source set') % {'rule': rule.name}) +if var in prompts: +raise errors.CSRTemplateError(reason=_( +'More than one data rule in this profile prompts' +' for the %(item)s data item') % {'item': var}) +var_parts = var.split('.') +if len(var_parts) != 2 or var_parts[0] != 'userdata': +raise errors.CSRTemplateError( +reason=_( +'Format of variable name in rule %(rule)s is' +' incorrect. Rules that prompt for data must' +' use a variable "userdata."') % +{'rule': rule.name}) + +prompts[var_parts[1]] = rule.options['prompt'] + +return prompts diff --git a/ipaclient/csrgen/rules/dataEmailUserSpecified.json b/ipaclient/csrgen/rules/dataEmailUserSpecified.json new file mode 100644 index 000..3fb2fb1 --- /dev/null +++ b/ipaclient/csrgen/rules/dataEmailUserSpecified.json @@ -0,0 +1,16 @@ +{ + "rules": [ +{ + "helper": "openssl", + "template": "email = {{userdata.email}}" +}, +{ + "helper": "certutil", + "template": "email:{{userdata.email|quote}}" +} + ], + "options": { +"data_source": "userdata.email", +"prompt": "Email address" + } +} diff --git a/ipaclient/plugins/csrgen.py b/ipaclient/plugins/csrgen.py index a0d99ef..0cc67f7 100644 --- a/ipaclient/plugins/csrgen.py +++ b/ipaclient/plugins/csrgen.py @@ -87,6 +87,9 @@ def execute(self, *args, **options): if not backend.isconnected(): backend.connect() +generator = CSRGenerator(FileRuleProvider()) +prompts = generator.get_user_prompts(profile_id, helper) + try: if principal.is_host: principal_obj = api.Command.host_show( @@ -103,10 +106,12 @@ def execute(self, *args, **options): principal_obj = principal_obj['result'] config = api.Command.config_show()['result'] -generator = CSRGenerator(FileRuleProvider()) +userdata = {} +for name, prompt in prompts.items(): +userdata[name] = self.Backend.textui.prompt(prompt) script = generator.csr_script( -
[Freeipa-devel] [freeipa PR#433][synchronized] csrgen: Allow some certificate fields to be specified by the user
URL: https://github.com/freeipa/freeipa/pull/433 Author: LiptonB Title: #433: csrgen: Allow some certificate fields to be specified by the user Action: synchronized To pull the PR as Git branch: git remote add ghfreeipa https://github.com/freeipa/freeipa git fetch ghfreeipa pull/433/head:pr433 git checkout pr433 From 3da67abcba6af0409a1195efd60581f6b28ad217 Mon Sep 17 00:00:00 2001 From: Ben LiptonDate: Thu, 28 Jul 2016 16:21:44 -0400 Subject: [PATCH 1/3] csrgen: Implement fields that prompt user for data Allows some data to be user-specified rather than coming out of the database. The provided data can be formatted with jinja2 rules just as database values can. https://fedorahosted.org/freeipa/ticket/4899 --- install/share/csrgen/Makefile.am | 1 + .../share/csrgen/rules/dataEmailUserSpecified.json | 16 ++ ipaclient/csrgen.py| 35 -- ipaclient/plugins/csrgen.py| 9 -- ipatests/test_ipaclient/test_csrgen.py | 15 +- 5 files changed, 65 insertions(+), 11 deletions(-) create mode 100644 install/share/csrgen/rules/dataEmailUserSpecified.json diff --git a/install/share/csrgen/Makefile.am b/install/share/csrgen/Makefile.am index 12c62c4..ad4412e 100644 --- a/install/share/csrgen/Makefile.am +++ b/install/share/csrgen/Makefile.am @@ -10,6 +10,7 @@ ruledir = $(IPA_DATA_DIR)/csrgen/rules rule_DATA =\ rules/dataDNS.json \ rules/dataEmail.json \ + rules/dataEmailUserSpecified.json \ rules/dataHostCN.json \ rules/dataUsernameCN.json \ rules/dataSubjectBase.json \ diff --git a/install/share/csrgen/rules/dataEmailUserSpecified.json b/install/share/csrgen/rules/dataEmailUserSpecified.json new file mode 100644 index 000..3fb2fb1 --- /dev/null +++ b/install/share/csrgen/rules/dataEmailUserSpecified.json @@ -0,0 +1,16 @@ +{ + "rules": [ +{ + "helper": "openssl", + "template": "email = {{userdata.email}}" +}, +{ + "helper": "certutil", + "template": "email:{{userdata.email|quote}}" +} + ], + "options": { +"data_source": "userdata.email", +"prompt": "Email address" + } +} diff --git a/ipaclient/csrgen.py b/ipaclient/csrgen.py index 96100ae..f00cc10 100644 --- a/ipaclient/csrgen.py +++ b/ipaclient/csrgen.py @@ -345,8 +345,9 @@ class CSRGenerator(object): def __init__(self, rule_provider): self.rule_provider = rule_provider -def csr_script(self, principal, config, profile_id, helper): -render_data = {'subject': principal, 'config': config} +def csr_script(self, principal, config, userdata, profile_id, helper): +render_data = { +'subject': principal, 'config': config, 'userdata': userdata} formatter = self.FORMATTERS[helper]() rules = self.rule_provider.rules_for_profile(profile_id, helper) @@ -360,3 +361,33 @@ def csr_script(self, principal, config, profile_id, helper): 'Template error when formatting certificate data')) return script + +def get_user_prompts(self, profile_id, helper): +prompts = {} +rules = self.rule_provider.rules_for_profile(profile_id, helper) + +for field_mapping in rules: +for rule in field_mapping.data_rules: +if 'prompt' in rule.options: +try: +var = rule.options['data_source'] +except KeyError: +raise errors.CSRTemplateError(reason=_( +'Certificate mapping rule %(rule)s has a prompt' +' but no data_source set') % {'rule': rule.name}) +if var in prompts: +raise errors.CSRTemplateError(reason=_( +'More than one data rule in this profile prompts' +' for the %(item)s data item') % {'item': var}) +var_parts = var.split('.') +if len(var_parts) != 2 or var_parts[0] != 'userdata': +raise errors.CSRTemplateError( +reason=_( +'Format of variable name in rule %(rule)s is' +' incorrect. Rules that prompt for data must' +' use a variable "userdata."') % +{'rule': rule.name}) + +prompts[var_parts[1]] = rule.options['prompt'] + +return prompts diff --git a/ipaclient/plugins/csrgen.py b/ipaclient/plugins/csrgen.py index 0d6eca0..e8563e5 100644 --- a/ipaclient/plugins/csrgen.py +++ b/ipaclient/plugins/csrgen.py @@ -85,6 +85,9 @@ def execute(self, *args, **options): if not backend.isconnected(): backend.connect() +generator = CSRGenerator(FileRuleProvider()) +prompts = generator.get_user_prompts(profile_id, helper) +
[Freeipa-devel] [freeipa PR#433][synchronized] csrgen: Allow some certificate fields to be specified by the user
URL: https://github.com/freeipa/freeipa/pull/433 Author: LiptonB Title: #433: csrgen: Allow some certificate fields to be specified by the user Action: synchronized To pull the PR as Git branch: git remote add ghfreeipa https://github.com/freeipa/freeipa git fetch ghfreeipa pull/433/head:pr433 git checkout pr433 From 96f4e25a4770bd2076390301adcee53d55086fa2 Mon Sep 17 00:00:00 2001 From: Ben LiptonDate: Thu, 28 Jul 2016 16:21:44 -0400 Subject: [PATCH 1/5] csrgen: Implement fields that prompt user for data Allows some data to be user-specified rather than coming out of the database. The provided data can be formatted with jinja2 rules just as database values can. https://fedorahosted.org/freeipa/ticket/4899 --- install/share/csrgen/Makefile.am | 1 + .../share/csrgen/rules/dataEmailUserSpecified.json | 16 ++ ipaclient/csrgen.py| 36 -- ipaclient/plugins/csrgen.py| 9 -- ipatests/test_ipaclient/test_csrgen.py | 15 - 5 files changed, 66 insertions(+), 11 deletions(-) create mode 100644 install/share/csrgen/rules/dataEmailUserSpecified.json diff --git a/install/share/csrgen/Makefile.am b/install/share/csrgen/Makefile.am index 12c62c4..ad4412e 100644 --- a/install/share/csrgen/Makefile.am +++ b/install/share/csrgen/Makefile.am @@ -10,6 +10,7 @@ ruledir = $(IPA_DATA_DIR)/csrgen/rules rule_DATA =\ rules/dataDNS.json \ rules/dataEmail.json \ + rules/dataEmailUserSpecified.json \ rules/dataHostCN.json \ rules/dataUsernameCN.json \ rules/dataSubjectBase.json \ diff --git a/install/share/csrgen/rules/dataEmailUserSpecified.json b/install/share/csrgen/rules/dataEmailUserSpecified.json new file mode 100644 index 000..3fb2fb1 --- /dev/null +++ b/install/share/csrgen/rules/dataEmailUserSpecified.json @@ -0,0 +1,16 @@ +{ + "rules": [ +{ + "helper": "openssl", + "template": "email = {{userdata.email}}" +}, +{ + "helper": "certutil", + "template": "email:{{userdata.email|quote}}" +} + ], + "options": { +"data_source": "userdata.email", +"prompt": "Email address" + } +} diff --git a/ipaclient/csrgen.py b/ipaclient/csrgen.py index 96100ae..2c1c5fc 100644 --- a/ipaclient/csrgen.py +++ b/ipaclient/csrgen.py @@ -345,8 +345,9 @@ class CSRGenerator(object): def __init__(self, rule_provider): self.rule_provider = rule_provider -def csr_script(self, principal, config, profile_id, helper): -render_data = {'subject': principal, 'config': config} +def csr_script(self, principal, config, userdata, profile_id, helper): +render_data = { +'subject': principal, 'config': config, 'userdata': userdata} formatter = self.FORMATTERS[helper]() rules = self.rule_provider.rules_for_profile(profile_id, helper) @@ -360,3 +361,34 @@ def csr_script(self, principal, config, profile_id, helper): 'Template error when formatting certificate data')) return script + +def get_user_prompts(self, profile_id, helper): +prompts = {} +syntax_rules = [] +rules = self.rule_provider.rules_for_profile(profile_id, helper) + +for field_mapping in rules: +for rule in field_mapping.data_rules: +if 'prompt' in rule.options: +try: +var = rule.options['data_source'] +except KeyError: +raise errors.CertificateMappingError(reason=_( +'Certificate mapping rule %(rule)s has a prompt' +' but no data_source set') % {'rule': rule.name}) +if var in prompts: +raise errors.CertificateMappingError(reason=_( +'More than one data rule in this profile prompts' +' for the %(item)s data item') % {'item': var}) +var_parts = var.split('.') +if len(var_parts) != 2 or var_parts[0] != 'userdata': +raise errors.CertificateMappingError( +reason=_( +'Format of variable name in rule %(rule)s is' +' incorrect. Rules that prompt for data must' +' use a variable "userdata."') % +{'rule': rule.name}) + +prompts[var_parts[1]] = rule.options['prompt'] + +return prompts diff --git a/ipaclient/plugins/csrgen.py b/ipaclient/plugins/csrgen.py index 0669a47..d480946 100644 --- a/ipaclient/plugins/csrgen.py +++ b/ipaclient/plugins/csrgen.py @@ -82,6 +82,9 @@ def execute(self, *args, **options): if not backend.isconnected(): backend.connect() +generator = CSRGenerator(FileRuleProvider()) +prompts =