[Freeipa-devel] [PATCH] 0024..0025 Add missing certprofile features

Fraser Tweedale ftweedal at redhat.com
Fri Jul 3 12:34:07 UTC 2015


On Thu, Jul 02, 2015 at 08:12:12PM +1000, Fraser Tweedale wrote:
> On Thu, Jul 02, 2015 at 11:23:49AM +0200, Jan Cholasta wrote:
> > Hi,
> > 
> > Dne 2.7.2015 v 11:15 Fraser Tweedale napsal(a):
> > >Attached patches fix a couple of important gaps in certprofile
> > >plugin:
> > >
> > >- Add --out option to export Dogtag profile data to file
> > >   https://fedorahosted.org/freeipa/ticket/5091
> > >
> > >- Add --file option to update existing profile in Dogtag
> > >   https://fedorahosted.org/freeipa/ticket/5093
> > >
> > 
> > Just a couple nitpicks:
> > 
> > +    takes_options = LDAPUpdate.takes_options + (
> > +        File('file?',
> > +            label=_('File containing profile configuration'),
> > +            cli_name='file',
> > +            flags=('virtual_attribute',),
> > +        ),
> > +    )
> > 
> > 1) Don't set cli_name if it's the same as name.
> > 
> > 2) The virtual_attribute flag is meaningless in Commands.
> > 
> > 3) Add "include='cli'" to denote that the option is specific to CLI (applies
> > to --out as well).
> > 
> > Honza
> > 
> > -- 
> > Jan Cholasta
> >
> Thanks, updated patches attached.  Interdiff below.
> 
> diff --git a/ipalib/plugins/certprofile.py b/ipalib/plugins/certprofile.py
> index 7323565..08a0d1c 100644
> --- a/ipalib/plugins/certprofile.py
> +++ b/ipalib/plugins/certprofile.py
> @@ -185,6 +185,7 @@ class certprofile_show(LDAPRetrieve):
>      takes_options = LDAPRetrieve.takes_options + (
>          Str('out?',
>              doc=_('Write profile configuration to file'),
> +            include='cli',
>          ),
>      )
>  
> @@ -284,8 +285,7 @@ class certprofile_mod(LDAPUpdate):
>      takes_options = LDAPUpdate.takes_options + (
>          File('file?',
>              label=_('File containing profile configuration'),
> -            cli_name='file',
> -            flags=('virtual_attribute',),
> +            include='cli',
>          ),
>      )
>  
NACK on patchset v2; does not work (even after makeapi, which I
forgot to include in updated patchset).  I keep getting error
``ipa: ERROR: Unknown option: file''.  Need to investigate why,
but other patches are taking priority right now.

Here is patchset v3, which is just v1 rebased on latest master.

Thanks,
Fraser
-------------- next part --------------
From 258f0cbea42b482871d360c33c252ad173c2b0e0 Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftweedal at redhat.com>
Date: Thu, 2 Jul 2015 03:31:31 -0400
Subject: [PATCH 24/25] certprofile: add option to export profile config

Add the `--out=FILENAME' option to `certprofile-show'.  When given,
it exports the profile configuration from Dogtag and writes it to
the named file.

Fixes: https://fedorahosted.org/freeipa/ticket/5091
---
 API.txt                       |  3 ++-
 VERSION                       |  4 ++--
 ipalib/plugins/certprofile.py | 39 ++++++++++++++++++++++++++++++++++++---
 ipaserver/plugins/dogtag.py   |  8 ++++++++
 4 files changed, 48 insertions(+), 6 deletions(-)

diff --git a/API.txt b/API.txt
index e226712d3b8f8eda721a906927cd7fac01eac39f..22ae9bb88710366736ee915e6fe6f2f1c09f2449 100644
--- a/API.txt
+++ b/API.txt
@@ -747,9 +747,10 @@ output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDA
 output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
 output: PrimaryKey('value', None, None)
 command: certprofile_show
-args: 1,4,3
+args: 1,5,3
 arg: Str('cn', attribute=True, cli_name='id', multivalue=False, primary_key=True, query=True, required=True)
 option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
+option: Str('out?')
 option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
 option: Flag('rights', autofill=True, default=False)
 option: Str('version?', exclude='webui')
diff --git a/VERSION b/VERSION
index 266a04af1a61132637112611b7e86649ff818c2a..5827f05a4b6b07afb91bd193ff8d7bdecdcc5f9a 100644
--- a/VERSION
+++ b/VERSION
@@ -90,5 +90,5 @@ IPA_DATA_VERSION=20100614120000
 #                                                      #
 ########################################################
 IPA_API_VERSION_MAJOR=2
-IPA_API_VERSION_MINOR=137
-# Last change: mbabinsk: Commands to manage user/host/service certificates
+IPA_API_VERSION_MINOR=138
+# Last change: ftweedal: add certprofile-show --out option
diff --git a/ipalib/plugins/certprofile.py b/ipalib/plugins/certprofile.py
index 9e1e47e943f5c14a7e7ce418d3fc2d095331a38a..abb62434eee4cb87356da5568b8a1bb12b762f67 100644
--- a/ipalib/plugins/certprofile.py
+++ b/ipalib/plugins/certprofile.py
@@ -5,7 +5,7 @@
 import re
 
 from ipalib import api, Bool, File, Str
-from ipalib import output
+from ipalib import output, util
 from ipalib.plugable import Registry
 from ipalib.plugins.virtual import VirtualCommand
 from ipalib.plugins.baseldap import (
@@ -175,9 +175,42 @@ class certprofile_find(LDAPSearch):
 class certprofile_show(LDAPRetrieve):
     __doc__ = _("Display the properties of a Certificate Profile.")
 
-    def execute(self, *args, **kwargs):
+    has_output_params = LDAPRetrieve.has_output_params + (
+        Str('config',
+            label=_('Profile configuration'),
+        ),
+    )
+
+    takes_options = LDAPRetrieve.takes_options + (
+        Str('out?',
+            doc=_('Write profile configuration to file'),
+        ),
+    )
+
+    def execute(self, *keys, **options):
         ca_enabled_check()
-        return super(certprofile_show, self).execute(*args, **kwargs)
+        result = super(certprofile_show, self).execute(*keys, **options)
+
+        if 'out' in options:
+            with self.api.Backend.ra_certprofile as profile_api:
+                result['result']['config'] = profile_api.read_profile(keys[0])
+
+        return result
+
+    def forward(self, *keys, **options):
+        if 'out' in options:
+            util.check_writable_file(options['out'])
+
+        result = super(certprofile_show, self).forward(*keys, **options)
+        if 'out' in options and 'config' in result['result']:
+            with open(options['out'], 'w') as f:
+                f.write(result['result'].pop('config'))
+            result['summary'] = (
+                _("Profile configuration stored in file '%(file)s'")
+                % dict(file=options['out'])
+            )
+
+        return result
 
 
 @register()
diff --git a/ipaserver/plugins/dogtag.py b/ipaserver/plugins/dogtag.py
index 3dc8f5c93a85a8035921af9ec622c2bcbcc498e0..eb2a6ae8413362ae2a443c672f806ff97356448f 100644
--- a/ipaserver/plugins/dogtag.py
+++ b/ipaserver/plugins/dogtag.py
@@ -2081,6 +2081,14 @@ class ra_certprofile(RestClient):
             body=profile_data
         )
 
+    def read_profile(self, profile_id):
+        """
+        Read the profile configuration from Dogtag
+        """
+        status, status_text, resp_headers, resp_body = self._ssldo(
+            'GET', profile_id + '/raw')
+        return resp_body
+
     def enable_profile(self, profile_id):
         """
         Enable the profile in Dogtag
-- 
2.1.0

-------------- next part --------------
From 120f18b55ec3f348065b3e293b43dc69a960dff2 Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftweedal at redhat.com>
Date: Thu, 2 Jul 2015 04:09:31 -0400
Subject: [PATCH 25/25] certprofile: add ability to update profile config in
 Dogtag

Add the `--file=FILENAME' option to `certprofile-mod' which, when
given, will update the profile configuration in Dogtag to the
contents of the file.

Fixes: https://fedorahosted.org/freeipa/ticket/5093
---
 API.txt                       |  3 ++-
 VERSION                       |  4 ++--
 ipalib/plugins/certprofile.py | 33 ++++++++++++++++++++++++++++++---
 ipaserver/plugins/dogtag.py   | 12 ++++++++++++
 4 files changed, 46 insertions(+), 6 deletions(-)

diff --git a/API.txt b/API.txt
index 22ae9bb88710366736ee915e6fe6f2f1c09f2449..e03b8fb54f7ba128227f37179f5715de86dffdef 100644
--- a/API.txt
+++ b/API.txt
@@ -731,12 +731,13 @@ output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDA
 output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
 output: PrimaryKey('value', None, None)
 command: certprofile_mod
-args: 1,10,3
+args: 1,11,3
 arg: Str('cn', attribute=True, cli_name='id', multivalue=False, primary_key=True, query=True, required=True)
 option: Str('addattr*', cli_name='addattr', exclude='webui')
 option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
 option: Str('delattr*', cli_name='delattr', exclude='webui')
 option: Str('description', attribute=True, autofill=False, cli_name='desc', multivalue=False, required=False)
+option: File('file?', cli_name='file')
 option: Bool('ipacertprofilestoreissued', attribute=True, autofill=False, cli_name='store', default=True, multivalue=False, required=False)
 option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
 option: Str('rename', cli_name='rename', multivalue=False, primary_key=True, required=False)
diff --git a/VERSION b/VERSION
index 5827f05a4b6b07afb91bd193ff8d7bdecdcc5f9a..5956d3dbf629c61d485d84524960a3f298a9da11 100644
--- a/VERSION
+++ b/VERSION
@@ -90,5 +90,5 @@ IPA_DATA_VERSION=20100614120000
 #                                                      #
 ########################################################
 IPA_API_VERSION_MAJOR=2
-IPA_API_VERSION_MINOR=138
-# Last change: ftweedal: add certprofile-show --out option
+IPA_API_VERSION_MINOR=139
+# Last change: ftweedal: add certprofile-mod --file option
diff --git a/ipalib/plugins/certprofile.py b/ipalib/plugins/certprofile.py
index abb62434eee4cb87356da5568b8a1bb12b762f67..7323565da6783b5300333a5eb2dac6c8dd9f9da6 100644
--- a/ipalib/plugins/certprofile.py
+++ b/ipalib/plugins/certprofile.py
@@ -13,6 +13,7 @@ from ipalib.plugins.baseldap import (
     LDAPDelete, LDAPUpdate, LDAPRetrieve)
 from ipalib import ngettext
 from ipalib.text import _
+from ipapython.version import API_VERSION
 
 from ipalib import errors
 
@@ -245,7 +246,6 @@ class certprofile_import(LDAPCreate):
     def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
         """Import the profile into Dogtag and enable it.
 
-        If the operation succeeds, update the LDAP entry to 'enabled'.
         If the operation fails, remove the LDAP entry.
         """
         try:
@@ -281,6 +281,33 @@ class certprofile_mod(LDAPUpdate):
     __doc__ = _("Modify Certificate Profile configuration.")
     msg_summary = _('Modified Certificate Profile "%(value)s"')
 
-    def execute(self, *args, **kwargs):
+    takes_options = LDAPUpdate.takes_options + (
+        File('file?',
+            label=_('File containing profile configuration'),
+            cli_name='file',
+            flags=('virtual_attribute',),
+        ),
+    )
+
+    def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
         ca_enabled_check()
-        return super(certprofile_mod, self).execute(*args, **kwargs)
+        if 'file' in options:
+            with self.api.Backend.ra_certprofile as profile_api:
+                profile_api.disable_profile(keys[0])
+                profile_api.update_profile(keys[0], options['file'])
+                profile_api.enable_profile(keys[0])
+
+        return dn
+
+    def execute(self, *keys, **options):
+        try:
+            return super(certprofile_mod, self).execute(*keys, **options)
+        except errors.EmptyModlist:
+            if 'file' in options:
+                # The profile data in Dogtag was updated.
+                # Do not fail; return result of certprofile-show instead
+                return self.api.Command.certprofile_show(keys[0],
+                    version=API_VERSION)
+            else:
+                # This case is actually an error; re-raise
+                raise
diff --git a/ipaserver/plugins/dogtag.py b/ipaserver/plugins/dogtag.py
index eb2a6ae8413362ae2a443c672f806ff97356448f..47279921a5428f388f84967b7bbe05d758e475bd 100644
--- a/ipaserver/plugins/dogtag.py
+++ b/ipaserver/plugins/dogtag.py
@@ -2089,6 +2089,18 @@ class ra_certprofile(RestClient):
             'GET', profile_id + '/raw')
         return resp_body
 
+    def update_profile(self, profile_id, profile_data):
+        """
+        Update the profile configuration in Dogtag
+        """
+        self._ssldo('PUT', profile_id + '/raw',
+            headers={
+                'Content-type': 'application/xml',
+                'Accept': 'application/json',
+            },
+            body=profile_data
+        )
+
     def enable_profile(self, profile_id):
         """
         Enable the profile in Dogtag
-- 
2.1.0



More information about the Freeipa-devel mailing list