summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--install/static/Makefile.am1
-rwxr-xr-xinstall/static/certificate.js381
-rw-r--r--install/static/index.xhtml1
-rw-r--r--install/static/service.js250
-rw-r--r--install/static/test/data/cert_remove_hold.json9
-rw-r--r--install/static/test/data/cert_request.json17
-rw-r--r--install/static/test/data/cert_revoke.json9
-rw-r--r--install/static/test/data/json_metadata.json176
-rw-r--r--install/static/test/data/service_show.json9
-rw-r--r--ipalib/plugins/service.py41
10 files changed, 861 insertions, 33 deletions
diff --git a/install/static/Makefile.am b/install/static/Makefile.am
index 8071d25f..ee8384c7 100644
--- a/install/static/Makefile.am
+++ b/install/static/Makefile.am
@@ -20,6 +20,7 @@ app_DATA = \
jquery-ui.js \
jquery.ba-bbq.js \
jquery-ui.css \
+ certificate.js \
group.js \
host.js \
hostgroup.js \
diff --git a/install/static/certificate.js b/install/static/certificate.js
new file mode 100755
index 00000000..4302e2f8
--- /dev/null
+++ b/install/static/certificate.js
@@ -0,0 +1,381 @@
+/* Authors:
+ * Endi Sukma Dewata <edewata@redhat.com>
+ *
+ * Copyright (C) 2010 Red Hat
+ * see file 'COPYING' for use and warranty information
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 only
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+var BEGIN_CERTIFICATE_REQUEST = '-----BEGIN CERTIFICATE REQUEST-----';
+var END_CERTIFICATE_REQUEST = '-----END CERTIFICATE REQUEST-----';
+
+var CRL_REASON = [
+ 'Unspecified',
+ 'Key Compromise',
+ 'CA Compromise',
+ 'Affiliation Changed',
+ 'Superseded',
+ 'Cessation of Operation',
+ 'Certificate Hold',
+ null,
+ 'Remove from CRL',
+ 'Privilege Withdrawn',
+ 'AA Compromise'
+];
+
+function certificate_parse_dn(dn) {
+
+ var result = {};
+
+ // TODO: Use proper LDAP DN parser
+ var rdns = dn.split(',');
+ for (var i=0; i<rdns.length; i++) {
+ var rdn = rdns[i];
+ var parts = rdn.split('=');
+ var name = parts[0].toLowerCase();
+ var value = parts[1];
+
+ result[name] = value;
+ }
+
+ return result;
+}
+
+function certificate_confirmation_dialog(spec) {
+ var that = {};
+ spec = spec || {};
+
+ var dialog = $('<div/>', {
+ 'title': spec.title
+ });
+
+ dialog.append(spec.message);
+
+ that.open = function() {
+ dialog.dialog({
+ modal: true,
+ width: 300,
+ height: 150,
+ buttons: {
+ 'Close': function() {
+ dialog.dialog('destroy');
+ }
+ }
+ });
+ };
+
+ return that;
+}
+
+function certificate_get_dialog(spec) {
+ var that = {};
+ spec = spec || {};
+
+ var dialog = $('<div/>', {
+ 'title': spec.title
+ });
+
+ var textarea = $('<textarea/>', {
+ readonly: 'yes',
+ style: 'width: 100%; height: 275px;'
+ }).appendTo(dialog);
+
+ textarea.val(
+ BEGIN_CERTIFICATE_REQUEST+'\n'+
+ spec.usercertificate+'\n'+
+ END_CERTIFICATE_REQUEST
+ );
+
+ that.open = function() {
+ dialog.dialog({
+ modal: true,
+ width: 500,
+ height: 400,
+ buttons: {
+ 'Close': function() {
+ dialog.dialog('destroy');
+ }
+ }
+ });
+ };
+
+ return that;
+}
+
+function certificate_revoke_dialog(spec) {
+ var that = {};
+ spec = spec || {};
+
+ var dialog = $('<div/>', {
+ 'title': spec.title
+ });
+
+ var table = $('<table/>').appendTo(dialog);
+
+ var tr = $('<tr/>').appendTo(table);
+
+ var td = $('<td/>').appendTo(tr);
+ td.append('Note:');
+
+ td = $('<td/>').appendTo(tr);
+ td.append(
+ 'To confirm your intention to revoke this certificate, '+
+ 'select a reason from the pull-down list, and click '+
+ 'the "Revoke" button.');
+
+ tr = $('<tr/>').appendTo(table);
+
+ td = $('<td/>').appendTo(tr);
+ td.append('Reason for Revocation:');
+
+ td = $('<td/>').appendTo(tr);
+
+ var select = $('<select/>').appendTo(td);
+ for (var i=0; i<CRL_REASON.length; i++) {
+ if (!CRL_REASON[i]) continue;
+ $('<option/>', {
+ 'value': i,
+ 'html': CRL_REASON[i]
+ }).appendTo(select);
+ }
+
+ that.open = function() {
+ dialog.dialog({
+ modal: true,
+ width: 500,
+ height: 300,
+ buttons: {
+ 'Revoke': function() {
+ var values = {};
+ values['reason'] = select.val();
+ if (spec.revoke) {
+ spec.revoke(values);
+ }
+ dialog.dialog('destroy');
+ },
+ 'Cancel': function() {
+ dialog.dialog('destroy');
+ }
+ }
+ });
+ };
+
+ return that;
+}
+
+function certificate_restore_dialog(spec) {
+ var that = {};
+ spec = spec || {};
+
+ var dialog = $('<div/>', {
+ 'title': spec.title
+ });
+
+ dialog.append(
+ 'To confirm your intention to restore this certificate, '+
+ 'click the "Restore" button.');
+
+ that.open = function() {
+ dialog.dialog({
+ modal: true,
+ width: 400,
+ height: 200,
+ buttons: {
+ 'Restore': function() {
+ var values = {};
+ if (spec.restore) {
+ spec.restore(values);
+ }
+ dialog.dialog('destroy');
+ },
+ 'Cancel': function() {
+ dialog.dialog('destroy');
+ }
+ }
+ });
+ };
+
+ return that;
+}
+
+function certificate_view_dialog(spec) {
+ var that = {};
+ spec = spec || {};
+
+ that.subject = certificate_parse_dn(spec.subject);
+ that.issuer = certificate_parse_dn(spec.issuer);
+
+ var dialog = $('<div/>', {
+ 'title': spec.title
+ });
+
+ var table = $('<table/>').appendTo(dialog);
+
+ var tr = $('<tr/>').appendTo(table);
+ $('<td/>', {
+ 'colspan': 2,
+ 'html': '<h3>Issued To</h3>'
+ }).appendTo(tr);
+
+ tr = $('<tr/>').appendTo(table);
+ $('<td>Common Name:</td>').appendTo(tr);
+ $('<td/>', {
+ 'html': that.subject.cn
+ }).appendTo(tr);
+
+ tr = $('<tr/>').appendTo(table);
+ $('<td>Organization:</td>').appendTo(tr);
+ $('<td/>', {
+ 'html': that.subject.o
+ }).appendTo(tr);
+
+ tr = $('<tr/>').appendTo(table);
+ $('<td>Organizational Unit:</td>').appendTo(tr);
+ $('<td/>', {
+ 'html': that.subject.ou
+ }).appendTo(tr);
+
+ tr = $('<tr/>').appendTo(table);
+ $('<td>Serial Number:</td>').appendTo(tr);
+ $('<td/>', {
+ 'html': spec.serial_number
+ }).appendTo(tr);
+
+ tr = $('<tr/>').appendTo(table);
+ $('<td/>', {
+ 'colspan': 2,
+ 'html': '<h3>Issued By</h3>'
+ }).appendTo(tr);
+
+ tr = $('<tr/>').appendTo(table);
+ $('<td>Common Name:</td>').appendTo(tr);
+ $('<td/>', {
+ 'html': that.issuer.cn
+ }).appendTo(tr);
+
+ tr = $('<tr/>').appendTo(table);
+ $('<td>Organization:</td>').appendTo(tr);
+ $('<td/>', {
+ 'html': that.issuer.o
+ }).appendTo(tr);
+
+ tr = $('<tr/>').appendTo(table);
+ $('<td>Organizational Unit:</td>').appendTo(tr);
+ $('<td/>', {
+ 'html': that.issuer.ou
+ }).appendTo(tr);
+
+ tr = $('<tr/>').appendTo(table);
+ $('<td/>', {
+ 'colspan': 2,
+ 'html': '<h3>Validity</h3>'
+ }).appendTo(tr);
+
+ tr = $('<tr/>').appendTo(table);
+ $('<td>Issued On:</td>').appendTo(tr);
+ $('<td/>', {
+ 'html': spec.issued_on
+ }).appendTo(tr);
+
+ tr = $('<tr/>').appendTo(table);
+ $('<td>Expires On:</td>').appendTo(tr);
+ $('<td/>', {
+ 'html': spec.expires_on
+ }).appendTo(tr);
+
+ tr = $('<tr/>').appendTo(table);
+ $('<td/>', {
+ 'colspan': 2,
+ 'html': '<h3>Fingerprints</h3>'
+ }).appendTo(tr);
+
+ tr = $('<tr/>').appendTo(table);
+ $('<td>SHA1 Fingerprint:</td>').appendTo(tr);
+ $('<td/>', {
+ 'html': spec.sha1_fingerprint
+ }).appendTo(tr);
+
+ tr = $('<tr/>').appendTo(table);
+ $('<td>MD5 Fingerprint:</td>').appendTo(tr);
+ $('<td/>', {
+ 'html': spec.md5_fingerprint
+ }).appendTo(tr);
+
+ that.open = function() {
+ dialog.dialog({
+ modal: true,
+ width: 600,
+ height: 500,
+ buttons: {
+ 'Close': function() {
+ dialog.dialog('destroy');
+ }
+ }
+ });
+ };
+
+ return that;
+}
+
+function certificate_request_dialog(spec) {
+ var that = {};
+ spec = spec || {};
+
+ var dialog = $('<div/>', {
+ 'title': spec.title
+ });
+
+ dialog.append('Copy and paste the Base64-encoded CSR below:');
+ dialog.append('<br/>');
+ dialog.append('<br/>');
+
+ dialog.append(BEGIN_CERTIFICATE_REQUEST);
+ dialog.append('<br/>');
+
+ var textarea = $('<textarea/>', {
+ style: 'width: 100%; height: 225px;'
+ }).appendTo(dialog);
+
+ dialog.append('<br/>');
+ dialog.append(END_CERTIFICATE_REQUEST);
+
+ that.open = function() {
+ dialog.dialog({
+ modal: true,
+ width: 500,
+ height: 400,
+ buttons: {
+ 'Issue': function() {
+ var values = {};
+ var request = textarea.val();
+ request =
+ BEGIN_CERTIFICATE_REQUEST+'\n'+
+ $.trim(request)+'\n'+
+ END_CERTIFICATE_REQUEST+'\n';
+ values['request'] = request;
+ if (spec.request) {
+ spec.request(values);
+ }
+ dialog.dialog('destroy');
+ },
+ 'Cancel': function() {
+ dialog.dialog('destroy');
+ }
+ }
+ });
+ };
+
+ return that;
+}
diff --git a/install/static/index.xhtml b/install/static/index.xhtml
index 338ddbb6..58c631e8 100644
--- a/install/static/index.xhtml
+++ b/install/static/index.xhtml
@@ -19,6 +19,7 @@
<script type="text/javascript" src="entity.js"></script>
<script type="text/javascript" src="navigation.js"></script>
+ <script type="text/javascript" src="certificate.js"></script>
<script type="text/javascript" src="user.js"></script>
<script type="text/javascript" src="group.js"></script>
<script type="text/javascript" src="host.js"></script>
diff --git a/install/static/service.js b/install/static/service.js
index 7b81c4d2..d688b9ad 100644
--- a/install/static/service.js
+++ b/install/static/service.js
@@ -34,16 +34,19 @@ ipa_entity_set_add_definition('service', [
]);
ipa_entity_set_details_definition('service', [
- ipa_stanza({name:'identity', label:'Service Details'}).
+ ipa_stanza({name:'details', label:'Service Details'}).
input({name:'krbprincipalname',
label:'Principal',
setup:service_krbprincipalname_setup,
load:service_krbprincipalname_load}).
input({name:'service', label:'Service', load:service_service_load}).
- input({name:'host', label:'Host Name', load:service_host_load}).
- input({name:'usercertificate', label:'Certificate',
- load:service_usercertificate_load,
- save:service_usercertificate_save})
+ input({name:'host', label:'Host Name', load:service_host_load}),
+ ipa_stanza({name:'provisioning', label:'Provisioning'}).
+ input({name:'provisioning_status', label:'Status',
+ load:service_provisioning_status_load}),
+ ipa_stanza({name:'certificate', label:'Service Certificate'}).
+ input({name:'certificate_status', label:'Status',
+ load:service_usercertificate_load})
]);
function service_add_krbprincipalname(add_dialog, mode) {
@@ -76,45 +79,234 @@ function service_service_load(container, dt, result) {
function service_host_load(container, dt, result) {
var krbprincipalname = result['krbprincipalname'][0];
- var host = krbprincipalname.replace(/^.*\//, '');
+ var host = krbprincipalname.replace(/^.*\//, '').replace(/@.*$/, '');
var dd = ipa_create_first_dd(this.name, host);
dt.after(dd);
}
-function service_usercertificate_load(container, dt, result) {
- var textarea = $("<textarea/>", {
- title: 'usercertificate',
- style: 'width: 300px; height: 200px;'
+function service_provisioning_status_load(container, dt, result) {
+ // skip provisioning_status
+}
+
+function service_usercertificate_get(result) {
+
+ var usercertificate = result['usercertificate'];
+ if (!usercertificate) {
+ alert('Service has no usercertificate.');
+ return;
+ }
+
+ var krbprincipalname = result['krbprincipalname'][0];
+ var service_name = krbprincipalname.replace(/@.*$/, '');
+
+ var dialog = certificate_get_dialog({
+ 'title': 'Certificate for Service '+service_name,
+ 'usercertificate': usercertificate[0].__base64__
});
- var dd = ipa_create_first_dd(this.name, textarea);
- dt.after(dd);
+ dialog.open();
+}
+
+function service_usercertificate_view(result) {
var usercertificate = result['usercertificate'];
- if (!usercertificate) return;
+ if (!usercertificate) {
+ alert('Service has no usercertificate.');
+ return;
+ }
+
+ var krbprincipalname = result['krbprincipalname'][0];
+ var service_name = krbprincipalname.replace(/@.*$/, '');
+
+ var dialog = certificate_view_dialog({
+ 'title': 'Certificate for Service '+service_name,
+ 'subject': result['subject'],
+ 'serial_number': result['serial_number'],
+ 'issuer': result['issuer'],
+ 'issued_on': result['valid_not_before'],
+ 'expires_on': result['valid_not_after'],
+ 'md5_fingerprint': result['md5_fingerprint'],
+ 'sha1_fingerprint': result['sha1_fingerprint']
+ });
- var value = usercertificate[0].__base64__;
- textarea.val(value);
+ dialog.open();
}
-function service_usercertificate_save(container) {
- var field = this;
- var values = [];
+function service_usercertificate_revoke(result) {
- var dd = $('dd[title='+field.name+']', container);
- dd.each(function () {
- var textarea = $('textarea', dd);
- if (!textarea.length) return;
+ var usercertificate = result['usercertificate'];
+ if (!usercertificate) {
+ alert('Service has no usercertificate.');
+ return;
+ }
+
+ var krbprincipalname = result['krbprincipalname'][0];
+ var service_name = krbprincipalname.replace(/@.*$/, '');
+
+ var serial_number = result['serial_number'];
- var value = $.trim(textarea.val());
- if (value) {
- value = {'__base64__': value};
- } else {
- value = '';
+ var dialog = certificate_revoke_dialog({
+ 'title': 'Revoke Certificate for Service '+service_name,
+ 'revoke': function(values) {
+ var reason = values['reason'];
+
+ ipa_cmd(
+ 'cert_revoke',
+ [serial_number],
+ {
+ 'revocation_reason': reason
+ },
+ function(data, text_status, xhr) {
+ var dialog = certificate_confirmation_dialog({
+ title: 'Success',
+ message: 'Certificate has been revoked successfully.'
+ });
+ dialog.open();
+ }
+ );
}
+ });
+
+ dialog.open();
+}
- values.push(value);
+function service_usercertificate_restore(result) {
+
+ var usercertificate = result['usercertificate'];
+ if (!usercertificate) {
+ alert('Service has no usercertificate.');
+ return;
+ }
+
+ var krbprincipalname = result['krbprincipalname'][0];
+ var service_name = krbprincipalname.replace(/@.*$/, '');
+
+ var serial_number = result['serial_number'];
+
+ var dialog = certificate_restore_dialog({
+ 'title': 'Restore Certificate for Service '+service_name,
+ 'restore': function(values) {
+ ipa_cmd(
+ 'cert_remove_hold',
+ [serial_number],
+ { },
+ function(data, text_status, xhr) {
+ var dialog = certificate_confirmation_dialog({
+ title: 'Success',
+ message: 'Certificate has been restored successfully.'
+ });
+ dialog.open();
+ }
+ );
+ }
});
- return values;
+ dialog.open();
+}
+
+function service_usercertificate_request(result) {
+
+ var krbprincipalname = result['krbprincipalname'][0];
+ var service_name = krbprincipalname.replace(/@.*$/, '');
+
+ var dialog = certificate_request_dialog({
+ 'title': 'Issue New Certificate for Service '+service_name,
+ 'request': function(values) {
+ var request = values['request'];
+
+ ipa_cmd(
+ 'cert_request',
+ [request],
+ {
+ 'principal': krbprincipalname
+ }
+ );
+ }
+ });
+
+ dialog.open();
+}
+
+function service_usercertificate_load(container, dt, result) {
+
+ var krbprincipalname = result['krbprincipalname'][0];
+
+ var table = $('<table/>');
+
+ var tr = $('<tr/>').appendTo(table);
+
+ var td = $('<td/>').appendTo(tr);
+ td.append('Valid Certificate Present:');
+
+ td = $('<td/>').appendTo(tr);
+ $('<input/>', {
+ type: 'button',
+ value: 'Get',
+ click: function() {
+ ipa_cmd('service_show', [krbprincipalname], {},
+ function(data, text_status, xhr) {
+ service_usercertificate_get(data.result.result);
+ }
+ );
+ }
+ }).appendTo(td);
+
+ $('<input/>', {
+ type: 'button',
+ value: 'Revoke',
+ click: function() {
+ ipa_cmd('service_show', [krbprincipalname], {},
+ function(data, text_status, xhr) {
+ service_usercertificate_revoke(data.result.result);
+ }
+ );
+ }
+ }).appendTo(td);
+
+ $('<input/>', {
+ type: 'button',
+ value: 'View',
+ click: function() {
+ ipa_cmd('service_show', [krbprincipalname], {},
+ function(data, text_status, xhr) {
+ service_usercertificate_view(data.result.result);
+ }
+ );
+ }
+ }).appendTo(td);
+
+ tr = $('<tr/>').appendTo(table);
+
+ td = $('<td/>').appendTo(tr);
+ td.append('Certificate Revoked:');
+
+ td = $('<td/>').appendTo(tr);
+ $('<input/>', {
+ type: 'button',
+ value: 'Restore',
+ click: function() {
+ ipa_cmd('service_show', [krbprincipalname], {},
+ function(data, text_status, xhr) {
+ service_usercertificate_restore(data.result.result);
+ }
+ );
+ }
+ }).appendTo(td);
+
+ tr = $('<tr/>').appendTo(table);
+
+ td = $('<td/>').appendTo(tr);
+ td.append('No Valid Certificate:');
+
+ td = $('<td/>').appendTo(tr);
+ $('<input/>', {
+ type: 'button',
+ value: 'New Certificate',
+ click: function() {
+ service_usercertificate_request(result);
+ }
+ }).appendTo(td);
+
+ var dd = ipa_create_first_dd(this.name, table);
+ dt.after(dd);
}
diff --git a/install/static/test/data/cert_remove_hold.json b/install/static/test/data/cert_remove_hold.json
new file mode 100644
index 00000000..12548cb2
--- /dev/null
+++ b/install/static/test/data/cert_remove_hold.json
@@ -0,0 +1,9 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": {
+ "unrevoked": true
+ }
+ }
+}
diff --git a/install/static/test/data/cert_request.json b/install/static/test/data/cert_request.json
new file mode 100644
index 00000000..190a4443
--- /dev/null
+++ b/install/static/test/data/cert_request.json
@@ -0,0 +1,17 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": {
+ "certificate": "MIIC2DCCAcCgAwIBAgIBFTANBgkqhkiG9w0BAQsFADAuMQwwCgYDVQQKEwNJUEExHjAcBgNVBAMTFUNlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0xMDEwMTUwNTE3MzZaFw0xMTA0MTMwNTE3MzZaMCgxDDAKBgNVBAoTA0lQQTEYMBYGA1UEAxMPZGV2LmV4YW1wbGUuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDk18o/IK1Qe0Y/eURWsIHcJ/TmGdNy1h2fhzGIILtv8Qgq1K3U4T9eGAZVambpo1SUnJY+k+AAo43TyavSU05se4DIsw00XrrOyD5UunwsW+b+cIUCWbBJLFy9ODsVDJduXrj0RZGHEyta3VuO/gJBtdI9anjVvgegqXUBkenjPwIDAQABo4GKMIGHMB8GA1UdIwQYMBaAFCv9XyGV5ijtHriYMcECVmnNiMMAMD8GCCsGAQUFBwEBBDMwMTAvBggrBgEFBQcwAYYjaHR0cDovL2Rldi5leGFtcGxlLmNvbTo5MTgwL2NhL29jc3AwDgYDVR0PAQH/BAQDAgTwMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA0GCSqGSIb3DQEBCwUAA4IBAQB/OtoBZUYuGD0KZWpNdzIVdCxCTzZAetHA+o97cZCdufiBckZfZ9LEkQdL2MWvcnLlXOnRnQO/BnEAAtYVe4dpmizuzPn1+JTmK9+7q2HhQhXuU2NcsWutgYySNme7eNmfqi8uDoQ8FOPX4LvxLQDyKjkOogs6cEMZePMK8RE60ulHKdYfI23rRNtIExOl1zLJXkpExuXNq1flshyaLLu84B9zwE5FhSD/XAjPyAqYP97IPIkUfWpMyEs3N12JVCVNm0/753CDI946RPnyPpsULZufBV/8sdhDnULHfPIUMPgdOYemm9cYTP/V1uhwwCnFemhSAXSM/g6e9Xm4hH7s",
+ "issuer": "CN=Certificate Authority,O=IPA",
+ "md5_fingerprint": "87:ca:33:52:e3:07:4c:82:76:24:8d:53:ba:da:b3:fe",
+ "request_id": "50",
+ "serial_number": "1",
+ "sha1_fingerprint": "9f:fc:d3:e2:3b:f0:c1:1d:fc:5c:09:fa:f4:10:de:7b:b2:25:ae:7c",
+ "subject": "CN=dev.example.com,O=IPA",
+ "valid_not_after": "Wed Apr 13 05:17:36 2011 UTC",
+ "valid_not_before": "Fri Oct 15 05:17:36 2010 UTC"
+ }
+ }
+}
diff --git a/install/static/test/data/cert_revoke.json b/install/static/test/data/cert_revoke.json
new file mode 100644
index 00000000..3fca1ee6
--- /dev/null
+++ b/install/static/test/data/cert_revoke.json
@@ -0,0 +1,9 @@
+{
+ "error": null,
+ "id": 0,
+ "result": {
+ "result": {
+ "revoked": true
+ }
+ }
+}
diff --git a/install/static/test/data/json_metadata.json b/install/static/test/data/json_metadata.json
index cd617b48..e1cbffb5 100644
--- a/install/static/test/data/json_metadata.json
+++ b/install/static/test/data/json_metadata.json
@@ -2976,6 +2976,180 @@
"query": false,
"required": false,
"type": "str"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "issuer",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Issuer",
+ "exclude": null,
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Issuer",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "issuer",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "valid_not_before",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Not Before",
+ "exclude": null,
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Not Before",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "valid_not_before",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "valid_not_after",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Not After",
+ "exclude": null,
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Not After",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "valid_not_after",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "md5_fingerprint",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Fingerprint (MD5)",
+ "exclude": null,
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Fingerprint (MD5)",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "md5_fingerprint",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "sha1_fingerprint",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Fingerprint (SHA1)",
+ "exclude": null,
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Fingerprint (SHA1)",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "sha1_fingerprint",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
+ },
+ {
+ "attribute": false,
+ "autofill": false,
+ "class": "Str",
+ "cli_name": "serial_number",
+ "cli_short_name": null,
+ "default": null,
+ "doc": "Serial number",
+ "exclude": null,
+ "flags": [
+ "no_update",
+ "no_create",
+ "no_search"
+ ],
+ "hint": null,
+ "include": null,
+ "label": "Serial number",
+ "length": null,
+ "maxlength": null,
+ "minlength": null,
+ "multivalue": false,
+ "name": "serial_number",
+ "pattern": null,
+ "pattern_errmsg": null,
+ "primary_key": false,
+ "query": false,
+ "required": false,
+ "type": "unicode"
}
],
"uuid_attribute": "ipauniqueid"
@@ -4163,4 +4337,4 @@
}
}
}
-} \ No newline at end of file
+}
diff --git a/install/static/test/data/service_show.json b/install/static/test/data/service_show.json
index 7ab778e1..d01f8585 100644
--- a/install/static/test/data/service_show.json
+++ b/install/static/test/data/service_show.json
@@ -5,17 +5,24 @@
"result": {
"dn": "krbprincipalname=test/dev.example.com@dev.example.com,cn=services,cn=accounts,dc=dev,dc=example,dc=com",
"has_keytab": false,
+ "issuer": "CN=IPA Test Certificate Authority",
"krbprincipalname": [
"test/dev.example.com@DEV.EXAMPLE.COM"
],
"managedby_host": [
"dev.example.com"
],
+ "md5_fingerprint": "08:86:a9:f9:87:af:0d:d7:42:01:e0:5f:12:9b:32:7f",
+ "serial_number": "1052",
+ "sha1_fingerprint": "b8:4c:4b:79:4f:13:03:79:47:08:fa:6b:52:63:3d:f9:15:8e:7e:dc",
+ "subject": "CN=dev.example.com,O=IPA",
"usercertificate": [
{
"__base64__": "MIICAjCCAWugAwIBAgICBAswDQYJKoZIhvcNAQEFBQAwKTEnMCUGA1UEAxMeSVBBIFRlc3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTEwMTAwNzIzMzk0NFoXDTE1MTAwNzIzMzk0NFowKDEMMAoGA1UECgwDSVBBMRgwFgYDVQQDDA9kZXYuZXhhbXBsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOTXyj8grVB7Rj95RFawgdwn9OYZ03LWHZ+HMYggu2/xCCrUrdThP14YBlVqZumjVJSclj6T4ACjjdPJq9JTTmx7gMizDTReus7IPlS6fCxb5v5whQJZsEksXL04OxUMl25euPRFkYcTK1rdW47+AkG10j1qeNW+B6CpdQGR6eM/AgMBAAGjOjA4MBEGCWCGSAGG+EIBAQQEAwIGQDATBgNVHSUEDDAKBggrBgEFBQcDATAOBgNVHQ8BAf8EBAMCBPAwDQYJKoZIhvcNAQEFBQADgYEASIhq723VL5xP0q51MYXFlGU1boD7pPD1pIQspD/MjCIEupcbH2kAo4wf+EiKsXR0rs+WZkaSgvFqaM4OQ2kWSFTiqmFXFDBEi6EFr68yLg7IpQpNTzVBXERd8B4GwNL9wrRw60jPXlUK29DPBsdGq8fDgX18l39wKkWXv7p1to4="
}
- ]
+ ],
+ "valid_not_after": "Tue Oct 13 01:59:32 2015 UTC",
+ "valid_not_before": "Wed Oct 13 01:59:32 2010 UTC"
},
"summary": null,
"value": "test/dev.example.com@DEV.EXAMPLE.COM"
diff --git a/ipalib/plugins/service.py b/ipalib/plugins/service.py
index 1e1dcd82..8ccdaeac 100644
--- a/ipalib/plugins/service.py
+++ b/ipalib/plugins/service.py
@@ -76,6 +76,7 @@ from ipalib.plugins.baseldap import *
from ipalib import x509
from ipalib import _, ngettext
from ipalib import util
+import nss.nss as nss
from nss.error import NSPRError
@@ -203,7 +204,7 @@ class service(LDAPObject):
cli_name='certificate',
label=_('Certificate'),
doc=_('Base-64 encoded server certificate'),
- ),
+ )
)
api.register(service)
@@ -357,7 +358,33 @@ class service_show(LDAPRetrieve):
"""
member_attributes = ['managedby']
takes_options = LDAPRetrieve.takes_options
- has_output_params = LDAPRetrieve.has_output_params + output_params
+
+ has_output_params = LDAPRetrieve.has_output_params + output_params + (
+ Str('subject',
+ label=_('Subject'),
+ ),
+ Str('serial_number',
+ label=_('Serial Number'),
+ ),
+ Str('issuer',
+ label=_('Issuer'),
+ ),
+ Str('valid_not_before',
+ label=_('Not Before'),
+ ),
+ Str('valid_not_after',
+ label=_('Not After'),
+ ),
+ Str('md5_fingerprint',
+ label=_('Fingerprint (MD5)'),
+ ),
+ Str('sha1_fingerprint',
+ label=_('Fingerprint (SHA1)'),
+ ),
+ Str('revocation_reason?',
+ label=_('Revocation reason'),
+ )
+ )
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
if 'krblastpwdchange' in entry_attrs:
@@ -367,6 +394,16 @@ class service_show(LDAPRetrieve):
else:
entry_attrs['has_keytab'] = False
+ if 'usercertificate' in entry_attrs:
+ cert = x509.load_certificate(entry_attrs['usercertificate'][0], datatype=x509.DER)
+ entry_attrs['subject'] = unicode(cert.subject)
+ entry_attrs['serial_number'] = unicode(cert.serial_number)
+ entry_attrs['issuer'] = unicode(cert.issuer)
+ entry_attrs['valid_not_before'] = unicode(cert.valid_not_before_str)
+ entry_attrs['valid_not_after'] = unicode(cert.valid_not_after_str)
+ entry_attrs['md5_fingerprint'] = unicode(nss.data_to_hex(nss.md5_digest(cert.der_data), 64)[0])
+ entry_attrs['sha1_fingerprint'] = unicode(nss.data_to_hex(nss.sha1_digest(cert.der_data), 64)[0])
+
return dn
api.register(service_show)