summaryrefslogtreecommitdiffstats
path: root/install
diff options
context:
space:
mode:
authorBen Lipton <blipton@redhat.com>2016-07-05 14:19:35 -0400
committerJan Cholasta <jcholast@redhat.com>2017-01-31 10:20:28 +0100
commit10ef5947860f5098182b1f95c08c1158e2da15f9 (patch)
tree360f7bb40f2eab2dcc2a1fa2c8460643c77524ec /install
parent87400cdec1054971f50f90a0c63f18ab045f3833 (diff)
downloadfreeipa-10ef5947860f5098182b1f95c08c1158e2da15f9.tar.gz
freeipa-10ef5947860f5098182b1f95c08c1158e2da15f9.tar.xz
freeipa-10ef5947860f5098182b1f95c08c1158e2da15f9.zip
csrgen: Add code to generate scripts that generate CSRs
Adds a library that uses jinja2 to format a script that, when run, will build a CSR. Also adds a CLI command, 'cert-get-requestdata', that uses this library and builds the script for a given principal. The rules are read from json files in /usr/share/ipa/csr, but the rule provider is a separate class so that it can be replaced easily. https://fedorahosted.org/freeipa/ticket/4899 Reviewed-By: Jan Cholasta <jcholast@redhat.com>
Diffstat (limited to 'install')
-rw-r--r--install/share/Makefile.am1
-rw-r--r--install/share/csr/templates/ipa_macros.tmpl42
-rw-r--r--install/share/csrgen/Makefile.am27
-rw-r--r--install/share/csrgen/templates/certutil_base.tmpl14
-rw-r--r--install/share/csrgen/templates/openssl_base.tmpl35
-rw-r--r--install/share/csrgen/templates/openssl_macros.tmpl29
6 files changed, 148 insertions, 0 deletions
diff --git a/install/share/Makefile.am b/install/share/Makefile.am
index 10de84d08..715912d8b 100644
--- a/install/share/Makefile.am
+++ b/install/share/Makefile.am
@@ -2,6 +2,7 @@ NULL =
SUBDIRS = \
advise \
+ csrgen \
profiles \
schema.d \
$(NULL)
diff --git a/install/share/csr/templates/ipa_macros.tmpl b/install/share/csr/templates/ipa_macros.tmpl
new file mode 100644
index 000000000..e790d4eb5
--- /dev/null
+++ b/install/share/csr/templates/ipa_macros.tmpl
@@ -0,0 +1,42 @@
+{% set rendersyntax = {} %}
+
+{% set renderdata = {} %}
+
+{# Wrapper for syntax rules. We render the contents of the rule into a
+variable, so that if we find that none of the contained data rules rendered we
+can suppress the whole syntax rule. That is, a syntax rule is rendered either
+if no data rules are specified (unusual) or if at least one of the data rules
+rendered successfully. #}
+{% macro syntaxrule() -%}
+{% do rendersyntax.update(none=true, any=false) -%}
+{% set contents -%}
+{{ caller() -}}
+{% endset -%}
+{% if rendersyntax['none'] or rendersyntax['any'] -%}
+{{ contents -}}
+{% endif -%}
+{% endmacro %}
+
+{# Wrapper for data rules. A data rule is rendered only when all of the data
+fields it contains have data available. #}
+{% macro datarule() -%}
+{% do rendersyntax.update(none=false) -%}
+{% do renderdata.update(all=true) -%}
+{% set contents -%}
+{{ caller() -}}
+{% endset -%}
+{% if renderdata['all'] -%}
+{% do rendersyntax.update(any=true) -%}
+{{ contents -}}
+{% endif -%}
+{% endmacro %}
+
+{# Wrapper for fields in data rules. If any value wrapped by this macro
+produces an empty string, the entire data rule will be suppressed. #}
+{% macro datafield(value) -%}
+{% if value -%}
+{{ value -}}
+{% else -%}
+{% do renderdata.update(all=false) -%}
+{% endif -%}
+{% endmacro %}
diff --git a/install/share/csrgen/Makefile.am b/install/share/csrgen/Makefile.am
new file mode 100644
index 000000000..7b718cca1
--- /dev/null
+++ b/install/share/csrgen/Makefile.am
@@ -0,0 +1,27 @@
+NULL =
+
+profiledir = $(IPA_DATA_DIR)/csrgen/profiles
+profile_DATA = \
+ $(NULL)
+
+ruledir = $(IPA_DATA_DIR)/csrgen/rules
+rule_DATA = \
+ $(NULL)
+
+templatedir = $(IPA_DATA_DIR)/csrgen/templates
+template_DATA = \
+ templates/certutil_base.tmpl \
+ templates/openssl_base.tmpl \
+ templates/openssl_macros.tmpl \
+ templates/ipa_macros.tmpl \
+ $(NULL)
+
+EXTRA_DIST = \
+ $(profile_DATA) \
+ $(rule_DATA) \
+ $(template_DATA) \
+ $(NULL)
+
+MAINTAINERCLEANFILES = \
+ *~ \
+ Makefile.in
diff --git a/install/share/csrgen/templates/certutil_base.tmpl b/install/share/csrgen/templates/certutil_base.tmpl
new file mode 100644
index 000000000..6c6425fc0
--- /dev/null
+++ b/install/share/csrgen/templates/certutil_base.tmpl
@@ -0,0 +1,14 @@
+{% raw -%}
+{% import "ipa_macros.tmpl" as ipa -%}
+{%- endraw %}
+#!/bin/bash -e
+
+if [[ $# -lt 1 ]]; then
+echo "Usage: $0 <outfile> [<any> <certutil> <args>]"
+echo "Called as: $0 $@"
+exit 1
+fi
+
+CSR="$1"
+shift
+certutil -R -a -z <(head -c 4096 /dev/urandom) -o "$CSR" {{ options|join(' ') }} "$@"
diff --git a/install/share/csrgen/templates/openssl_base.tmpl b/install/share/csrgen/templates/openssl_base.tmpl
new file mode 100644
index 000000000..597577bcd
--- /dev/null
+++ b/install/share/csrgen/templates/openssl_base.tmpl
@@ -0,0 +1,35 @@
+{% raw -%}
+{% import "openssl_macros.tmpl" as openssl -%}
+{% import "ipa_macros.tmpl" as ipa -%}
+{%- endraw %}
+#!/bin/bash -e
+
+if [[ $# -ne 2 ]]; then
+echo "Usage: $0 <outfile> <keyfile>"
+echo "Called as: $0 $@"
+exit 1
+fi
+
+CONFIG="$(mktemp)"
+CSR="$1"
+shift
+
+echo \
+{% raw %}{% filter quote %}{% endraw -%}
+[ req ]
+prompt = no
+encrypt_key = no
+
+{{ parameters|join('\n') }}
+{% raw %}{% set rendered_extensions -%}{% endraw %}
+{{ extensions|join('\n') }}
+{% raw -%}
+{%- endset -%}
+{% if rendered_extensions -%}
+req_extensions = {% call openssl.section() %}{{ rendered_extensions }}{% endcall %}
+{% endif %}
+{{ openssl.openssl_sections|join('\n\n') }}
+{% endfilter %}{%- endraw %} > "$CONFIG"
+
+openssl req -new -config "$CONFIG" -out "$CSR" -key $1
+rm "$CONFIG"
diff --git a/install/share/csrgen/templates/openssl_macros.tmpl b/install/share/csrgen/templates/openssl_macros.tmpl
new file mode 100644
index 000000000..d31b8fef5
--- /dev/null
+++ b/install/share/csrgen/templates/openssl_macros.tmpl
@@ -0,0 +1,29 @@
+{# List containing rendered sections to be included at end #}
+{% set openssl_sections = [] %}
+
+{#
+List containing one entry for each section name allocated. Because of
+scoping rules, we need to use a list so that it can be a "per-render global"
+that gets updated in place. Real globals are shared by all templates with the
+same environment, and variables defined in the macro don't persist after the
+macro invocation ends.
+#}
+{% set openssl_section_num = [] %}
+
+{% macro section() -%}
+{% set name -%}
+sec{{ openssl_section_num|length -}}
+{% endset -%}
+{% do openssl_section_num.append('') -%}
+{% set contents %}{{ caller() }}{% endset -%}
+{% if contents -%}
+{% set sectiondata = formatsection(name, contents) -%}
+{% do openssl_sections.append(sectiondata) -%}
+{% endif -%}
+{{ name -}}
+{% endmacro %}
+
+{% macro formatsection(name, contents) -%}
+[ {{ name }} ]
+{{ contents -}}
+{% endmacro %}