summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPetr Vobornik <pvoborni@redhat.com>2015-07-08 22:04:45 +0200
committerPetr Vobornik <pvoborni@redhat.com>2015-07-09 10:58:40 +0200
commit7c481b1e90dbb6821b71707c4012b3857adb84e2 (patch)
tree134b099acdec8d327d14a91a2fc3b25c9b3c8e74
parentcd3ca94ff2ef738cb3a9eae502193413058f976d (diff)
downloadfreeipa-7c481b1e90dbb6821b71707c4012b3857adb84e2.tar.gz
freeipa-7c481b1e90dbb6821b71707c4012b3857adb84e2.tar.xz
freeipa-7c481b1e90dbb6821b71707c4012b3857adb84e2.zip
webui: cert-request improvements
Certificate request action and dialog now supports 'profile_id', 'add' and 'principal' options. 'add' and 'principal' are disaplayed only if certificate is added from certificate search facet. Certificate search facet allows to add a certificate. User details facet allows to add a certificate. part of https://fedorahosted.org/freeipa/ticket/5046 Reviewed-By: Martin Basti <mbasti@redhat.com>
-rwxr-xr-xinstall/ui/src/freeipa/certificate.js137
-rw-r--r--install/ui/src/freeipa/host.js6
-rw-r--r--install/ui/src/freeipa/service.js6
-rw-r--r--install/ui/src/freeipa/user.js45
-rw-r--r--install/ui/test/data/ipa_init.json4
-rw-r--r--ipalib/plugins/internal.py4
6 files changed, 168 insertions, 34 deletions
diff --git a/install/ui/src/freeipa/certificate.js b/install/ui/src/freeipa/certificate.js
index 28d0407db..71f0dfbf5 100755
--- a/install/ui/src/freeipa/certificate.js
+++ b/install/ui/src/freeipa/certificate.js
@@ -21,6 +21,7 @@
define([
'dojo/_base/lang',
+ './builder',
'./metadata',
'./ipa',
'./jquery',
@@ -30,7 +31,9 @@ define([
'./rpc',
'./text',
'./dialog'],
- function(lang, metadata_provider, IPA, $, menu, phases, reg, rpc, text) {
+ function(
+ lang, builder, metadata_provider, IPA, $, menu,
+ phases, reg, rpc, text) {
var exp = IPA.cert = {};
@@ -395,11 +398,42 @@ IPA.cert.request_dialog = function(spec) {
spec = spec || {};
+ spec.sections = spec.sections || [];
+ var section = { fields: [] };
+ spec.sections.push(section);
+
+ if (spec.show_principal) {
+ section.fields.push(
+ {
+ $type: 'text',
+ name: 'principal',
+ label: '@mc-opt:cert_request:principal:label',
+ required: true
+ },
+ {
+ $type: 'checkbox',
+ name: 'add',
+ label: '@i18n:objects.cert.add_principal',
+ tooltip: '@mc-opt:cert_request:add:doc'
+ }
+ );
+ }
+ section.fields.push(
+ {
+ $type: 'entity_select',
+ name: 'profile_id',
+ other_entity: 'certprofile',
+ other_field: 'cn',
+ label: '@mc-opt:cert_request:profile_id:label'
+ }
+ );
+
var that = IPA.dialog(spec);
that.width = spec.width || 600;
that.height = spec.height || 480;
that.message = text.get(spec.message);
+ that.show_principal = spec.show_principal;
that.request = spec.request;
@@ -408,8 +442,10 @@ IPA.cert.request_dialog = function(spec) {
label: '@i18n:buttons.issue',
click: function() {
var values = {};
+ that.save(values);
var request = $.trim(that.textarea.val());
values.request = IPA.cert.pem_csr_format(request);
+
if (that.request) {
that.request(values);
}
@@ -426,11 +462,16 @@ IPA.cert.request_dialog = function(spec) {
});
that.create_content = function() {
- that.container.append(that.message);
-
+ that.dialog_create_content();
+ var node = $("<div/>", {
+ 'class': 'col-sm-12'
+ });
+ node.append(that.message);
that.textarea = $('<textarea/>', {
'class': 'certificate'
- }).appendTo(that.container);
+ }).appendTo(node);
+ that.body_node.append(node);
+ return that.body_node;
};
return that;
@@ -444,10 +485,13 @@ IPA.cert.loader = function(spec) {
that.get_pkey = spec.get_pkey;
that.get_name = spec.get_name;
that.get_principal = spec.get_principal;
- that.get_hostname = spec.get_hostname;
+ that.get_cn = spec.get_cn;
+ that.get_cn_name = spec.get_cn_name;
+ that.adapter = builder.build('adapter', spec.adapter || 'adapter', {});
- that.load = function (result) {
+ that.load = function (data) {
+ var result = that.adapter.get_record(data);
var certificate = {
issuer: result.issuer,
certificate: result.certificate,
@@ -474,7 +518,8 @@ IPA.cert.loader = function(spec) {
if (that.get_pkey) info.pkey = that.get_pkey(result);
if (that.get_name) info.name = that.get_name(result);
if (that.get_principal) info.principal = that.get_principal(result);
- if (that.get_hostname) info.hostname = that.get_hostname(result);
+ if (that.get_cn_name) info.cn_name = that.get_cn_name(result);
+ if (that.get_cn) info.cn = that.get_cn(result);
certificate.entity_info = info;
@@ -492,7 +537,9 @@ IPA.cert.load_policy = function(spec) {
get_pkey: spec.get_pkey,
get_name: spec.get_name,
get_principal: spec.get_principal,
- get_hostname: spec.get_hostname
+ get_cn: spec.get_cn,
+ get_cn_name: spec.get_cn_name,
+ adapter: spec.adapter
};
var that = IPA.facet_policy();
@@ -502,7 +549,7 @@ IPA.cert.load_policy = function(spec) {
that.post_load = function(data) {
// update cert info in facet (show at least something)
- var certificate = that.loader.load(data.result.result);
+ var certificate = that.loader.load(data);
//store cert directly to facet. FIXME: introduce concept of models
that.container.certificate = certificate;
@@ -518,6 +565,8 @@ IPA.cert.load_policy = function(spec) {
};
that.load_revocation_reason = function(serial_number) {
+ if (serial_number === null || serial_number === undefined) return;
+
rpc.command({
entity: 'cert',
method: 'show',
@@ -622,41 +671,59 @@ IPA.cert.request_action = function(spec) {
var that = IPA.action(spec);
that.entity_label = spec.entity_label;
+ that.generic = spec.generic !== undefined ? spec.generic : false;
that.execute_action = function(facet) {
- var certificate = facet.certificate;
- if (!certificate) facet.refresh();
+ var entity_principal = null;
+ var cn_name = 'common name';
+ var cn = '&ltcommon name&gt';
+ var title = text.get('@i18n:objects.cert.issue_certificate_generic');
+ if (!that.generic) {
+ var certificate = facet.certificate;
+ if (!certificate) facet.refresh();
- var entity_principal = certificate.entity_info.principal;
- var entity_label = that.entity_label || facet.entity.metadata.label_singular;
- var entity_name = certificate.entity_info.name;
- var hostname = certificate.entity_info.hostname;
+ var entity_label = that.entity_label || facet.entity.metadata.label_singular;
- var title = text.get('@i18n:objects.cert.issue_certificate');
- title = title.replace('${entity}', entity_label);
- title = title.replace('${primary_key}', entity_name);
+ entity_principal = certificate.entity_info.principal;
+ var entity_name = certificate.entity_info.name;
+ cn = certificate.entity_info.cn || cn;
+ cn_name = certificate.entity_info.cn_name || cn_name;
+
+ title = text.get('@i18n:objects.cert.issue_certificate');
+ title = title.replace('${entity}', entity_label);
+ title = title.replace('${primary_key}', entity_name);
+ }
var request_message = text.get('@i18n:objects.cert.request_message');
- request_message = request_message.replace(/\$\{hostname\}/g, hostname);
+ request_message = request_message.replace(/\$\{cn_name\}/g, cn_name);
+ request_message = request_message.replace(/\$\{cn\}/g, cn);
request_message = request_message.replace(/\$\{realm\}/g, IPA.env.realm);
var dialog = IPA.cert.request_dialog({
title: title,
message: request_message,
+ show_principal: !entity_principal,
request: function(values) {
+ var options = {
+ 'principal': entity_principal
+ };
+ if (values.profile_id) options.profile_id = values.profile_id[0];
+ if (values.principal) options.principal = values.principal[0];
+ if (values.add) options.add = values.add[0];
+
rpc.command({
entity: 'cert',
method: 'request',
args: [values.request],
- options: {
- 'principal': entity_principal
- },
+ options: options,
on_success: function(data, text_status, xhr) {
facet.refresh();
IPA.notify_success('@i18n:objects.cert.requested');
- facet.certificate_updated.notify([], that.facet);
+ if (facet.certificate_updated) {
+ facet.certificate_updated.notify([], that.facet);
+ }
}
}).execute();
}
@@ -1052,6 +1119,12 @@ return {
source_facet: 'details',
dest_entity: 'service',
dest_facet: 'details'
+ },
+ {
+ $factory: IPA.cert.cert_update_policy,
+ source_facet: 'details',
+ dest_entity: 'user',
+ dest_facet: 'details'
}
],
enable_test: function() {
@@ -1080,6 +1153,20 @@ return {
width: '120px'
}
],
+ control_buttons: [
+ {
+ name: 'request_cert',
+ label: '@i18n:buttons.issue',
+ icon: 'fa-plus'
+ }
+ ],
+ actions: [
+ {
+ $type: 'cert_request',
+ enable_cond: [],
+ generic: true
+ }
+ ],
search_options: [
{
value: 'subject',
@@ -1322,8 +1409,6 @@ exp.register = function() {
var f = reg.field;
var a = reg.action;
- e.register({type: 'cert', spec: exp.entity_spec});
-
w.register('certificate_status', IPA.cert.status_widget);
f.register('certificate_status', IPA.cert.status_field);
@@ -1335,6 +1420,8 @@ exp.register = function() {
a.register('cert_request', IPA.cert.request_action);
a.register('cert_revoke', IPA.cert.revoke_action);
a.register('cert_restore', IPA.cert.restore_action);
+
+ e.register({type: 'cert', spec: exp.entity_spec});
};
phases.on('registration', exp.register);
diff --git a/install/ui/src/freeipa/host.js b/install/ui/src/freeipa/host.js
index 1120c82e7..17fe423e5 100644
--- a/install/ui/src/freeipa/host.js
+++ b/install/ui/src/freeipa/host.js
@@ -912,7 +912,11 @@ IPA.host.certificate_policy = function(spec) {
return values ? values[0] : null;
};
- spec.get_hostname = spec.get_hostname || spec.get_name;
+ spec.get_cn = spec.get_cn || spec.get_name;
+
+ spec.get_cn_name = spec.get_cn_name || function(result) {
+ return "hostname";
+ };
var that = IPA.cert.load_policy(spec);
return that;
diff --git a/install/ui/src/freeipa/service.js b/install/ui/src/freeipa/service.js
index 5c28e939d..5b469b5e1 100644
--- a/install/ui/src/freeipa/service.js
+++ b/install/ui/src/freeipa/service.js
@@ -554,7 +554,7 @@ IPA.service.certificate_policy = function(spec) {
spec.get_principal = spec.get_principal || get_pkey;
- spec.get_hostname = spec.get_hostname || function(result) {
+ spec.get_cn = spec.get_cn || function(result) {
var value = get_pkey(result);
if (value) {
value = value.replace(/@.*$/, '').replace(/^.*\//, '');
@@ -562,6 +562,10 @@ IPA.service.certificate_policy = function(spec) {
return value;
};
+ spec.get_cn_name = spec.get_cn_name || function(result) {
+ return "hostname";
+ };
+
var that = IPA.cert.load_policy(spec);
return that;
};
diff --git a/install/ui/src/freeipa/user.js b/install/ui/src/freeipa/user.js
index bf84ba3ac..33bc6ec10 100644
--- a/install/ui/src/freeipa/user.js
+++ b/install/ui/src/freeipa/user.js
@@ -340,9 +340,16 @@ return {
name: 'automember_rebuild',
hide_cond: ['preserved-user'],
label: '@i18n:actions.automember_rebuild'
+ },
+ {
+ $type: 'cert_request',
+ hide_cond: ['preserved-user']
}
],
- header_actions: ['reset_password', 'enable', 'disable', 'delete', 'unlock', 'add_otptoken', 'automember_rebuild'],
+ header_actions: [
+ 'reset_password', 'enable', 'disable', 'delete',
+ 'unlock', 'add_otptoken', 'automember_rebuild', 'request_cert'
+ ],
state: {
evaluators: [
{
@@ -358,7 +365,8 @@ return {
attribute: 'userpassword'
},
IPA.user.self_service_other_user_evaluator,
- IPA.user.preserved_user_evaluator
+ IPA.user.preserved_user_evaluator,
+ IPA.cert.certificate_evaluator
],
summary_conditions: [
{
@@ -372,7 +380,8 @@ return {
]
},
policies: [
- IPA.user.preserved_user_policy
+ IPA.user.preserved_user_policy,
+ IPA.user.certificate_policy
]
},
{
@@ -451,11 +460,13 @@ return {
}
};};
-IPA.user.details_facet = function(spec) {
+IPA.user.details_facet = function(spec, no_init) {
spec = spec || {};
- var that = IPA.details_facet(spec);
+ var that = IPA.details_facet(spec, true);
+ that.certificate_loaded = IPA.observer();
+ that.certificate_updated = IPA.observer();
that.create_refresh_command = function() {
@@ -513,6 +524,8 @@ IPA.user.details_facet = function(spec) {
return batch;
};
+ if (!no_init) that.init_details_facet();
+
return that;
};
@@ -703,6 +716,28 @@ IPA.user.add_otptoken_action = function(spec) {
return that;
};
+IPA.user.certificate_policy = function(spec) {
+
+ spec = spec || {};
+
+ function get_pkey(result) {
+ var values = result.uid;
+ return values ? values[0] : null;
+ }
+
+ spec.adapter = { result_index: 0 };
+ spec.get_pkey = spec.get_pkey || get_pkey;
+ spec.get_name = spec.get_name || get_pkey;
+ spec.get_principal = spec.get_principal || get_pkey;
+ spec.get_cn = spec.get_cn || get_pkey;
+ spec.get_cn_name = spec.get_cn_name || function(result) {
+ return "uid";
+ };
+
+ var that = IPA.cert.load_policy(spec);
+ return that;
+};
+
IPA.user.self_service_other_user_evaluator = function(spec) {
spec = spec || {};
diff --git a/install/ui/test/data/ipa_init.json b/install/ui/test/data/ipa_init.json
index f253c57fe..21b12f144 100644
--- a/install/ui/test/data/ipa_init.json
+++ b/install/ui/test/data/ipa_init.json
@@ -218,6 +218,7 @@
},
"cert": {
"aa_compromise": "AA Compromise",
+ "add_principal": "Add principal",
"affiliation_changed": "Affiliation Changed",
"ca_compromise": "CA Compromise",
"certificate": "Certificate",
@@ -240,6 +241,7 @@
"find_validnotbefore_from": "Valid not before from",
"find_validnotbefore_to": "Valid not before to",
"get_certificate": "Get Certificate",
+ "issue_certificate_generic": "Issue New Certificate",
"issue_certificate": "Issue New Certificate for ${entity} ${primary_key}",
"issued_by": "Issued By",
"issued_on": "Issued On",
@@ -254,7 +256,7 @@
"privilege_withdrawn": "Privilege Withdrawn",
"reason": "Reason for Revocation",
"remove_from_crl": "Remove from CRL",
- "request_message": "<ol> <li>Create a certificate database or use an existing one. To create a new database:<br/> <code># certutil -N -d &lt;database path&gt;</code> </li> <li>Create a CSR with subject <em>CN=&lt;hostname&gt;,O=&lt;realm&gt;</em>, for example:<br/> <code># certutil -R -d &lt;database path&gt; -a -g &lt;key size&gt; -s 'CN=${hostname},O=${realm}'</code> </li> <li> Copy and paste the CSR (from <em>-----BEGIN NEW CERTIFICATE REQUEST-----</em> to <em>-----END NEW CERTIFICATE REQUEST-----</em>) into the text area below: </li> </ol>",
+ "request_message": "<ol> <li>Create a certificate database or use an existing one. To create a new database:<br/> <code># certutil -N -d &lt;database path&gt;</code> </li> <li>Create a CSR with subject <em>CN=&lt;${cn_name}&gt;,O=&lt;realm&gt;</em>, for example:<br/> <code># certutil -R -d &lt;database path&gt; -a -g &lt;key size&gt; -s 'CN=${cn},O=${realm}'</code> </li> <li> Copy and paste the CSR (from <em>-----BEGIN NEW CERTIFICATE REQUEST-----</em> to <em>-----END NEW CERTIFICATE REQUEST-----</em>) into the text area below: </li> </ol>",
"requested": "Certificate requested",
"restore_certificate": "Restore Certificate for ${entity} ${primary_key}",
"restore_certificate_simple": "Restore Certificate",
diff --git a/ipalib/plugins/internal.py b/ipalib/plugins/internal.py
index 653d866da..ae019e7ef 100644
--- a/ipalib/plugins/internal.py
+++ b/ipalib/plugins/internal.py
@@ -362,6 +362,7 @@ class i18n_messages(Command):
},
"cert": {
"aa_compromise": _("AA Compromise"),
+ "add_principal": _("Add principal"),
"affiliation_changed": _("Affiliation Changed"),
"ca_compromise": _("CA Compromise"),
"certificate": _("Certificate"),
@@ -385,6 +386,7 @@ class i18n_messages(Command):
"fingerprints": _("Fingerprints"),
"get_certificate": _("Get Certificate"),
"issue_certificate": _("Issue New Certificate for ${entity} ${primary_key}"),
+ "issue_certificate_generic": _("Issue New Certificate"),
"issued_by": _("Issued By"),
"issued_on": _("Issued On"),
"issued_to": _("Issued To"),
@@ -398,7 +400,7 @@ class i18n_messages(Command):
"privilege_withdrawn": _("Privilege Withdrawn"),
"reason": _("Reason for Revocation"),
"remove_from_crl": _("Remove from CRL"),
- "request_message": _("<ol> <li>Create a certificate database or use an existing one. To create a new database:<br/> <code># certutil -N -d &lt;database path&gt;</code> </li> <li>Create a CSR with subject <em>CN=&lt;hostname&gt;,O=&lt;realm&gt;</em>, for example:<br/> <code># certutil -R -d &lt;database path&gt; -a -g &lt;key size&gt; -s 'CN=${hostname},O=${realm}'</code> </li> <li> Copy and paste the CSR (from <em>-----BEGIN NEW CERTIFICATE REQUEST-----</em> to <em>-----END NEW CERTIFICATE REQUEST-----</em>) into the text area below: </li> </ol>"),
+ "request_message": _("<ol> <li>Create a certificate database or use an existing one. To create a new database:<br/> <code># certutil -N -d &lt;database path&gt;</code> </li> <li>Create a CSR with subject <em>CN=&lt;${cn_name}&gt;,O=&lt;realm&gt;</em>, for example:<br/> <code># certutil -R -d &lt;database path&gt; -a -g &lt;key size&gt; -s 'CN=${cn},O=${realm}'</code> </li> <li> Copy and paste the CSR (from <em>-----BEGIN NEW CERTIFICATE REQUEST-----</em> to <em>-----END NEW CERTIFICATE REQUEST-----</em>) into the text area below: </li> </ol>"),
"requested": _("Certificate requested"),
"restore_certificate": _("Restore Certificate for ${entity} ${primary_key}"),
"restore_certificate_simple": _("Restore Certificate"),