summaryrefslogtreecommitdiffstats
path: root/ipaserver/plugins/krbtpolicy.py
diff options
context:
space:
mode:
Diffstat (limited to 'ipaserver/plugins/krbtpolicy.py')
-rw-r--r--ipaserver/plugins/krbtpolicy.py243
1 files changed, 243 insertions, 0 deletions
diff --git a/ipaserver/plugins/krbtpolicy.py b/ipaserver/plugins/krbtpolicy.py
new file mode 100644
index 000000000..7cf587661
--- /dev/null
+++ b/ipaserver/plugins/krbtpolicy.py
@@ -0,0 +1,243 @@
+# Authors:
+# Pavel Zuna <pzuna@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, either version 3 of the License, or
+# (at your option) any later version.
+#
+# 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, see <http://www.gnu.org/licenses/>.
+
+from ipalib import api, errors, output, _
+from ipalib import Int, Str
+from . import baseldap
+from .baseldap import entry_to_dict, pkey_to_value
+from ipalib.plugable import Registry
+from ipapython.dn import DN
+
+__doc__ = _("""
+Kerberos ticket policy
+
+There is a single Kerberos ticket policy. This policy defines the
+maximum ticket lifetime and the maximum renewal age, the period during
+which the ticket is renewable.
+
+You can also create a per-user ticket policy by specifying the user login.
+
+For changes to the global policy to take effect, restarting the KDC service
+is required, which can be achieved using:
+
+service krb5kdc restart
+
+Changes to per-user policies take effect immediately for newly requested
+tickets (e.g. when the user next runs kinit).
+
+EXAMPLES:
+
+ Display the current Kerberos ticket policy:
+ ipa krbtpolicy-show
+
+ Reset the policy to the default:
+ ipa krbtpolicy-reset
+
+ Modify the policy to 8 hours max life, 1-day max renewal:
+ ipa krbtpolicy-mod --maxlife=28800 --maxrenew=86400
+
+ Display effective Kerberos ticket policy for user 'admin':
+ ipa krbtpolicy-show admin
+
+ Reset per-user policy for user 'admin':
+ ipa krbtpolicy-reset admin
+
+ Modify per-user policy for user 'admin':
+ ipa krbtpolicy-mod admin --maxlife=3600
+""")
+
+register = Registry()
+
+# FIXME: load this from a config file?
+_default_values = {
+ 'krbmaxticketlife': 86400,
+ 'krbmaxrenewableage': 604800,
+}
+
+
+@register()
+class krbtpolicy(baseldap.LDAPObject):
+ """
+ Kerberos Ticket Policy object
+ """
+ container_dn = DN(('cn', api.env.realm), ('cn', 'kerberos'))
+ object_name = _('kerberos ticket policy settings')
+ default_attributes = ['krbmaxticketlife', 'krbmaxrenewableage']
+ limit_object_classes = ['krbticketpolicyaux']
+ # permission_filter_objectclasses is deliberately missing,
+ # so it is not possible to create a permission of `--type krbtpolicy`.
+ # This is because we need two permissions to cover both global and per-user
+ # policies.
+ managed_permissions = {
+ 'System: Read Default Kerberos Ticket Policy': {
+ 'non_object': True,
+ 'replaces_global_anonymous_aci': True,
+ 'ipapermtargetfilter': ['(objectclass=krbticketpolicyaux)'],
+ 'ipapermlocation': DN(container_dn, api.env.basedn),
+ 'ipapermright': {'read', 'search', 'compare'},
+ 'ipapermdefaultattr': {
+ 'krbdefaultencsalttypes', 'krbmaxrenewableage',
+ 'krbmaxticketlife', 'krbsupportedencsalttypes',
+ 'objectclass',
+ },
+ 'default_privileges': {
+ 'Kerberos Ticket Policy Readers',
+ },
+ },
+ 'System: Read User Kerberos Ticket Policy': {
+ 'non_object': True,
+ 'replaces_global_anonymous_aci': True,
+ 'ipapermlocation': DN(api.env.container_user, api.env.basedn),
+ 'ipapermtargetfilter': ['(objectclass=krbticketpolicyaux)'],
+ 'ipapermright': {'read', 'search', 'compare'},
+ 'ipapermdefaultattr': {
+ 'krbmaxrenewableage', 'krbmaxticketlife',
+ },
+ 'default_privileges': {
+ 'Kerberos Ticket Policy Readers',
+ },
+ },
+ }
+
+ label = _('Kerberos Ticket Policy')
+ label_singular = _('Kerberos Ticket Policy')
+
+ takes_params = (
+ Str('uid?',
+ cli_name='user',
+ label=_('User name'),
+ doc=_('Manage ticket policy for specific user'),
+ primary_key=True,
+ ),
+ Int('krbmaxticketlife?',
+ cli_name='maxlife',
+ label=_('Max life'),
+ doc=_('Maximum ticket life (seconds)'),
+ minvalue=1,
+ ),
+ Int('krbmaxrenewableage?',
+ cli_name='maxrenew',
+ label=_('Max renew'),
+ doc=_('Maximum renewable age (seconds)'),
+ minvalue=1,
+ ),
+ )
+
+ def get_dn(self, *keys, **kwargs):
+ if keys[-1] is not None:
+ return self.api.Object.user.get_dn(*keys, **kwargs)
+ return DN(self.container_dn, api.env.basedn)
+
+
+@register()
+class krbtpolicy_mod(baseldap.LDAPUpdate):
+ __doc__ = _('Modify Kerberos ticket policy.')
+
+ def execute(self, uid=None, **options):
+ return super(krbtpolicy_mod, self).execute(uid, **options)
+
+ def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
+ assert isinstance(dn, DN)
+ # disable all flag
+ # ticket policies are attached to objects with unrelated attributes
+ if options.get('all'):
+ options['all'] = False
+ return dn
+
+
+@register()
+class krbtpolicy_show(baseldap.LDAPRetrieve):
+ __doc__ = _('Display the current Kerberos ticket policy.')
+
+ def execute(self, uid=None, **options):
+ return super(krbtpolicy_show, self).execute(uid, **options)
+
+ def pre_callback(self, ldap, dn, attrs_list, *keys, **options):
+ assert isinstance(dn, DN)
+ # disable all flag
+ # ticket policies are attached to objects with unrelated attributes
+ if options.get('all'):
+ options['all'] = False
+ return dn
+
+ def post_callback(self, ldap, dn, entry, *keys, **options):
+ default_entry = None
+ rights = None
+ for attrname in self.obj.default_attributes:
+ if attrname not in entry:
+ if keys[-1] is not None:
+ # User entry doesn't override the attribute.
+ # Check if this is caused by insufficient read rights
+ if rights is None:
+ rights = baseldap.get_effective_rights(
+ ldap, dn, self.obj.default_attributes)
+ if 'r' not in rights.get(attrname.lower(), ''):
+ raise errors.ACIError(
+ info=_('Ticket policy for %s could not be read') %
+ keys[-1])
+ # Fallback to the default
+ if default_entry is None:
+ try:
+ default_dn = self.obj.get_dn(None)
+ default_entry = ldap.get_entry(default_dn)
+ except errors.NotFound:
+ default_entry = {}
+ if attrname in default_entry:
+ entry[attrname] = default_entry[attrname]
+ if attrname not in entry:
+ raise errors.ACIError(
+ info=_('Default ticket policy could not be read'))
+ return dn
+
+
+@register()
+class krbtpolicy_reset(baseldap.LDAPQuery):
+ __doc__ = _('Reset Kerberos ticket policy to the default values.')
+
+ has_output = output.standard_entry
+
+ def execute(self, uid=None, **options):
+ ldap = self.obj.backend
+
+ dn = self.obj.get_dn(uid, **options)
+
+ def_values = {}
+ # if reseting policy for a user - just his values
+ if uid is not None:
+ for a in self.obj.default_attributes:
+ def_values[a] = None
+ # if reseting global policy - set values to default
+ else:
+ def_values = _default_values
+
+ entry = ldap.get_entry(dn, def_values.keys())
+ entry.update(def_values)
+ try:
+ ldap.update_entry(entry)
+ except errors.EmptyModlist:
+ pass
+
+ if uid is not None:
+ # policy for user was deleted, retrieve global policy
+ dn = self.obj.get_dn(None)
+ entry_attrs = ldap.get_entry(dn, self.obj.default_attributes)
+
+ entry_attrs = entry_to_dict(entry_attrs, **options)
+
+ return dict(result=entry_attrs, value=pkey_to_value(uid, options))