diff --git a/ACI.txt b/ACI.txt index 3dcf84fd6..541d4d2f3 100644 --- a/ACI.txt +++ b/ACI.txt @@ -185,9 +185,9 @@ aci: (targetattr = "cn || createtimestamp || entryusn || ipabaseid || ipabaserid dn: cn=views,cn=accounts,dc=ipa,dc=example aci: (targetattr = "cn || createtimestamp || description || entryusn || ipadomainresolutionorder || modifytimestamp || objectclass")(targetfilter = "(objectclass=nsContainer)")(version 3.0;acl "permission:System: Read ID Views";allow (compare,read,search) userdn = "ldap:///all";) dn: cn=IPA.EXAMPLE,cn=kerberos,dc=ipa,dc=example -aci: (targetattr = "createtimestamp || entryusn || krbdefaultencsalttypes || krbmaxrenewableage || krbmaxticketlife || krbsupportedencsalttypes || modifytimestamp || objectclass")(targetfilter = "(objectclass=krbticketpolicyaux)")(version 3.0;acl "permission:System: Read Default Kerberos Ticket Policy";allow (compare,read,search) groupdn = "ldap:///cn=System: Read Default Kerberos Ticket Policy,cn=permissions,cn=pbac,dc=ipa,dc=example";) +aci: (targetattr = "createtimestamp || entryusn || krbauthindmaxrenewableage || krbauthindmaxticketlife || krbdefaultencsalttypes || krbmaxrenewableage || krbmaxticketlife || krbsupportedencsalttypes || modifytimestamp || objectclass")(targetfilter = "(objectclass=krbticketpolicyaux)")(version 3.0;acl "permission:System: Read Default Kerberos Ticket Policy";allow (compare,read,search) groupdn = "ldap:///cn=System: Read Default Kerberos Ticket Policy,cn=permissions,cn=pbac,dc=ipa,dc=example";) dn: cn=users,cn=accounts,dc=ipa,dc=example -aci: (targetattr = "krbmaxrenewableage || krbmaxticketlife")(targetfilter = "(objectclass=krbticketpolicyaux)")(version 3.0;acl "permission:System: Read User Kerberos Ticket Policy";allow (compare,read,search) groupdn = "ldap:///cn=System: Read User Kerberos Ticket Policy,cn=permissions,cn=pbac,dc=ipa,dc=example";) +aci: (targetattr = "krbauthindmaxrenewableage || krbauthindmaxticketlife || krbmaxrenewableage || krbmaxticketlife")(targetfilter = "(objectclass=krbticketpolicyaux)")(version 3.0;acl "permission:System: Read User Kerberos Ticket Policy";allow (compare,read,search) groupdn = "ldap:///cn=System: Read User Kerberos Ticket Policy,cn=permissions,cn=pbac,dc=ipa,dc=example";) dn: cn=locations,cn=etc,dc=ipa,dc=example aci: (targetfilter = "(objectclass=ipaLocationObject)")(version 3.0;acl "permission:System: Add IPA Locations";allow (add) groupdn = "ldap:///cn=System: Add IPA Locations,cn=permissions,cn=pbac,dc=ipa,dc=example";) dn: cn=locations,cn=etc,dc=ipa,dc=example diff --git a/API.txt b/API.txt index a919e3a63..58c080ebd 100644 --- a/API.txt +++ b/API.txt @@ -3219,11 +3219,19 @@ output: Output('result', type=[]) output: Output('summary', type=[, ]) output: PrimaryKey('value') command: krbtpolicy_mod/1 -args: 1,9,3 +args: 1,17,3 arg: Str('uid?', cli_name='user') option: Str('addattr*', cli_name='addattr') option: Flag('all', autofill=True, cli_name='all', default=False) option: Str('delattr*', cli_name='delattr') +option: Int('krbauthindmaxrenewableage_hardened?', autofill=False, cli_name='hardened_maxrenew') +option: Int('krbauthindmaxrenewableage_otp?', autofill=False, cli_name='otp_maxrenew') +option: Int('krbauthindmaxrenewableage_pkinit?', autofill=False, cli_name='pkinit_maxrenew') +option: Int('krbauthindmaxrenewableage_radius?', autofill=False, cli_name='radius_maxrenew') +option: Int('krbauthindmaxticketlife_hardened?', autofill=False, cli_name='hardened_maxlife') +option: Int('krbauthindmaxticketlife_otp?', autofill=False, cli_name='otp_maxlife') +option: Int('krbauthindmaxticketlife_pkinit?', autofill=False, cli_name='pkinit_maxlife') +option: Int('krbauthindmaxticketlife_radius?', autofill=False, cli_name='radius_maxlife') option: Int('krbmaxrenewableage?', autofill=False, cli_name='maxrenew') option: Int('krbmaxticketlife?', autofill=False, cli_name='maxlife') option: Flag('raw', autofill=True, cli_name='raw', default=False) diff --git a/daemons/ipa-kdb/ipa_kdb.h b/daemons/ipa-kdb/ipa_kdb.h index 08c24ae64..7519f26e2 100644 --- a/daemons/ipa-kdb/ipa_kdb.h +++ b/daemons/ipa-kdb/ipa_kdb.h @@ -94,6 +94,14 @@ enum ipadb_user_auth { IPADB_USER_AUTH_HARDENED = 1 << 5, }; +enum ipadb_user_auth_idx { + IPADB_USER_AUTH_IDX_OTP = 0, + IPADB_USER_AUTH_IDX_RADIUS, + IPADB_USER_AUTH_IDX_PKINIT, + IPADB_USER_AUTH_IDX_HARDENED, + IPADB_USER_AUTH_IDX_MAX, +}; + struct ipadb_global_config { time_t last_update; bool disable_last_success; @@ -128,6 +136,11 @@ struct ipadb_context { struct ipadb_global_config config; }; +struct ipadb_e_pol_limits { + krb5_deltat max_life; + krb5_deltat max_renewable_life; +}; + #define IPA_E_DATA_MAGIC 0x0eda7a struct ipadb_e_data { int magic; @@ -142,6 +155,7 @@ struct ipadb_e_data { char **authz_data; bool has_tktpolaux; enum ipadb_user_auth user_auth; + struct ipadb_e_pol_limits pol_limits[IPADB_USER_AUTH_IDX_MAX]; }; struct ipadb_context *ipadb_get_context(krb5_context kcontext); diff --git a/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c b/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c index 6b61f162e..0b8aa668f 100644 --- a/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c +++ b/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c @@ -21,14 +21,13 @@ ipa_kdcpolicy_check_as(krb5_context context, krb5_kdcpolicy_moddata moddata, krb5_error_code kerr; enum ipadb_user_auth ua; struct ipadb_e_data *ied; + struct ipadb_e_pol_limits *pol_limits = NULL; int valid_auth_indicators = 0; *status = NULL; *lifetime_out = 0; *renew_lifetime_out = 0; - krb5_klog_syslog(LOG_INFO, "IPA kdcpolicy: checking AS-REQ."); - ied = (struct ipadb_e_data *)client->e_data; if (ied == NULL || ied->magic != IPA_E_DATA_MAGIC) { /* e-data is not availble, getting user auth from LDAP */ @@ -63,18 +62,21 @@ ipa_kdcpolicy_check_as(krb5_context context, krb5_kdcpolicy_moddata moddata, *status = "OTP pre-authentication not allowed for this user."; return KRB5KDC_ERR_POLICY; } + pol_limits = &(ied->pol_limits[IPADB_USER_AUTH_IDX_OTP]); } else if (strcmp(auth_indicator, "radius") == 0) { valid_auth_indicators++; if (!(ua & IPADB_USER_AUTH_RADIUS)) { *status = "OTP pre-authentication not allowed for this user."; return KRB5KDC_ERR_POLICY; } + pol_limits = &(ied->pol_limits[IPADB_USER_AUTH_IDX_RADIUS]); } else if (strcmp(auth_indicator, "pkinit") == 0) { valid_auth_indicators++; if (!(ua & IPADB_USER_AUTH_PKINIT)) { *status = "PKINIT pre-authentication not allowed for this user."; return KRB5KDC_ERR_POLICY; } + pol_limits = &(ied->pol_limits[IPADB_USER_AUTH_IDX_PKINIT]); } else if (strcmp(auth_indicator, "hardened") == 0) { valid_auth_indicators++; /* Allow hardened even if only password pre-auth is allowed */ @@ -82,6 +84,7 @@ ipa_kdcpolicy_check_as(krb5_context context, krb5_kdcpolicy_moddata moddata, *status = "Password pre-authentication not not allowed for this user."; return KRB5KDC_ERR_POLICY; } + pol_limits = &(ied->pol_limits[IPADB_USER_AUTH_IDX_HARDENED]); } } @@ -94,6 +97,18 @@ ipa_kdcpolicy_check_as(krb5_context context, krb5_kdcpolicy_moddata moddata, } } + /* If there were policy limits associated with the authentication indicators, + * apply them */ + if (pol_limits != NULL) { + if (pol_limits->max_life != 0) { + *lifetime_out = pol_limits->max_life; + } + + if (pol_limits->max_renewable_life != 0) { + *renew_lifetime_out = pol_limits->max_renewable_life; + } + } + return 0; } @@ -110,8 +125,6 @@ ipa_kdcpolicy_check_tgs(krb5_context context, krb5_kdcpolicy_moddata moddata, *lifetime_out = 0; *renew_lifetime_out = 0; - krb5_klog_syslog(LOG_INFO, "IPA kdcpolicy: checking TGS-REQ."); - return 0; } diff --git a/daemons/ipa-kdb/ipa_kdb_principals.c b/daemons/ipa-kdb/ipa_kdb_principals.c index b208d090a..73085e813 100644 --- a/daemons/ipa-kdb/ipa_kdb_principals.c +++ b/daemons/ipa-kdb/ipa_kdb_principals.c @@ -79,6 +79,8 @@ static char *std_principal_attrs[] = { IPA_KRB_AUTHZ_DATA_ATTR, IPA_USER_AUTH_TYPE, "ipatokenRadiusConfigLink", + "krbAuthIndMaxTicketLife", + "krbAuthIndMaxRenewableAge", "objectClass", NULL @@ -88,6 +90,8 @@ static char *std_tktpolicy_attrs[] = { "krbmaxticketlife", "krbmaxrenewableage", "krbticketflags", + "krbauthindmaxticketlife", + "krbauthindmaxrenewableage", NULL }; @@ -506,6 +510,66 @@ cleanup: return ret; } +static void ipadb_parse_authind_policies(krb5_context kcontext, + LDAP *lcontext, + LDAPMessage *lentry, + krb5_db_entry *entry, + enum ipadb_user_auth ua) +{ + int result; + int ret; + struct ipadb_e_data *ied; + const struct { + char *attribute; + enum ipadb_user_auth flag; + enum ipadb_user_auth_idx idx; + } life_authind_map[] = { + {"krbAuthIndMaxTicketLife;otp", + IPADB_USER_AUTH_OTP, IPADB_USER_AUTH_IDX_OTP}, + {"krbAuthIndMaxTicketLife;radius", + IPADB_USER_AUTH_RADIUS, IPADB_USER_AUTH_IDX_RADIUS}, + {"krbAuthIndMaxTicketLife;pkinit", + IPADB_USER_AUTH_PKINIT, IPADB_USER_AUTH_IDX_PKINIT}, + {"krbAuthIndMaxTicketLife;hardened", + IPADB_USER_AUTH_HARDENED, IPADB_USER_AUTH_IDX_HARDENED}, + {NULL, IPADB_USER_AUTH_NONE, IPADB_USER_AUTH_IDX_MAX}, + }, age_authind_map[] = { + {"krbAuthIndMaxRenewableAge;otp", + IPADB_USER_AUTH_OTP, IPADB_USER_AUTH_IDX_OTP}, + {"krbAuthIndMaxRenewableAge;radius", + IPADB_USER_AUTH_RADIUS, IPADB_USER_AUTH_IDX_RADIUS}, + {"krbAuthIndMaxRenewableAge;pkinit", + IPADB_USER_AUTH_PKINIT, IPADB_USER_AUTH_IDX_PKINIT}, + {"krbAuthIndMaxRenewableAge;hardened", + IPADB_USER_AUTH_HARDENED, IPADB_USER_AUTH_IDX_HARDENED}, + {NULL, IPADB_USER_AUTH_NONE, IPADB_USER_AUTH_IDX_MAX}, + }; + + ied = (struct ipadb_e_data *)entry->e_data; + if (ied == NULL) { + return; + } + + for (size_t i = 0; life_authind_map[i].attribute != NULL; i++) { + if (ua & life_authind_map[i].flag) { + ret = ipadb_ldap_attr_to_int(lcontext, lentry, + life_authind_map[i].attribute, + &result); + if (ret == 0) { + ied->pol_limits[life_authind_map[i].idx].max_life = result; + } + + ret = ipadb_ldap_attr_to_int(lcontext, lentry, + age_authind_map[i].attribute, + &result); + if (ret == 0) { + ied->pol_limits[age_authind_map[i].idx].max_renewable_life = result; + } + } + } +} + + static krb5_error_code ipadb_parse_ldap_entry(krb5_context kcontext, char *principal, LDAPMessage *lentry, @@ -861,6 +925,10 @@ static krb5_error_code ipadb_parse_ldap_entry(krb5_context kcontext, goto done; } + if (ua & ~IPADB_USER_AUTH_NONE) { + ipadb_parse_authind_policies(kcontext, lcontext, lentry, entry, ua); + } + kerr = 0; done: diff --git a/doc/designs/krb-ticket-policy.md b/doc/designs/krb-ticket-policy.md index 6346d775b..096104413 100644 --- a/doc/designs/krb-ticket-policy.md +++ b/doc/designs/krb-ticket-policy.md @@ -71,19 +71,17 @@ Tickets without an authentication indicator will have the default lifetime / ren Administrators can specify max life and renew for each auth indicator and global default via `ipa krbtpolicy-mod` command. -e.g. `ipa krbtpolicy-mod --setattr otp-maxlife=604800 pkinit-maxtime=604800` +e.g. `ipa krbtpolicy-mod --otp-maxlife=604800 --pkinit-maxlife=604800` Current `--maxlife` and `--maxrenew` options for `ipa krbtpolicy-mod` will set the default max life / renew respectively. After this, the output for `ipa krbtpolicy-show` will look like: ``` -Max life: - - default: 86400 - - otp: 604800 - - pkinit: 604800 -Max renew: - - default: 604800 +Max life: 86400 +OTP max life: 604800 +PKINIT max life: 604800 +Max renew: 604800 ``` #### WebUI Workflow: @@ -110,7 +108,14 @@ but ticket lifecycle policy will require LDAP to store relations between authent and lifetime information. We have global ticket lifetime and renew time setting stored as attribute `krbmaxticketlife` and `krbmaxrenewableage` inside the `cn=$REALM,cn=kerberos,$SUFFIX` subtree, which represents the default lifetime policy. -For each authentication indicator, there will be an attribute to store specific lifetime for that indicator, -such as `krbmaxticketlifetop`, `krbmaxrenewableagepkinit` -They are stored in the same location as default policy in LDAP. +Two new multi-valued attributes are added to store an authentication +indicator-specific maximum ticket life and ticket's maximum renewable age. The +type of authentication indicator is specified as LDAP attribute option: + +``` +krbAuthIndMaxTicketLife;otp: 604800 +krbAuthIndMaxRenewableAge;pkinit: 604800 +``` + +They are stored in the same policy object in LDAP. diff --git a/install/share/60kerberos.ldif b/install/share/60kerberos.ldif index 45bea2aef..2ceae711e 100644 --- a/install/share/60kerberos.ldif +++ b/install/share/60kerberos.ldif @@ -269,6 +269,10 @@ attributetypes: ( 1.3.6.1.4.1.5322.21.2.4 NAME 'krbAllowedToDelegateTo' EQUALITY ##### A list of authentication indicator strings, one of which must be satisfied ##### to authenticate to the principal as a service. attributetypes: ( 2.16.840.1.113730.3.8.15.2.1 NAME 'krbPrincipalAuthInd' EQUALITY caseExactMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15) +##### The maximum ticket lifetime for a principal based on authentication indicator in seconds. Indicator is specified as an attribute option +attributetypes: ( 2.16.840.1.113730.3.8.15.2.2 NAME 'krbAuthIndMaxTicketLife' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27) +##### Maximum renewable lifetime for a principal's ticket based on authentication indicator in seconds. Indicator is specified as an attribute option +attributetypes: ( 2.16.840.1.113730.3.8.15.2.3 NAME 'krbAuthIndMaxRenewableAge' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27) ######################################################################## # Object Class Definitions # ######################################################################## @@ -312,6 +316,6 @@ objectClasses: ( 2.16.840.1.113719.1.301.6.13.1 NAME 'krbAdmService' SUP ( krbSe objectClasses: ( 2.16.840.1.113719.1.301.6.14.1 NAME 'krbPwdPolicy' SUP top MUST ( cn ) MAY ( krbMaxPwdLife $ krbMinPwdLife $ krbPwdMinDiffChars $ krbPwdMinLength $ krbPwdHistoryLength $ krbPwdMaxFailure $ krbPwdFailureCountInterval $ krbPwdLockoutDuration $ krbPwdAttributes $ krbPwdMaxLife $ krbPwdMaxRenewableLife $ krbPwdAllowedKeysalts ) ) ##### The krbTicketPolicyAux holds Kerberos ticket policy attributes. ##### This class can be attached to a principal object or realm object. -objectClasses: ( 2.16.840.1.113719.1.301.6.16.1 NAME 'krbTicketPolicyAux' AUXILIARY MAY ( krbTicketFlags $ krbMaxTicketLife $ krbMaxRenewableAge ) ) +objectClasses: ( 2.16.840.1.113719.1.301.6.16.1 NAME 'krbTicketPolicyAux' AUXILIARY MAY ( krbTicketFlags $ krbMaxTicketLife $ krbMaxRenewableAge $ krbAuthIndMaxTicketLife $ krbAuthIndMaxRenewableAge ) ) ##### The krbTicketPolicy object is an effective ticket policy that is associated with a realm or a principal objectClasses: ( 2.16.840.1.113719.1.301.6.17.1 NAME 'krbTicketPolicy' SUP top MUST ( cn ) ) diff --git a/ipaserver/plugins/krbtpolicy.py b/ipaserver/plugins/krbtpolicy.py index a66bbace3..997fe7e81 100644 --- a/ipaserver/plugins/krbtpolicy.py +++ b/ipaserver/plugins/krbtpolicy.py @@ -70,6 +70,10 @@ _default_values = { 'krbmaxrenewableage': 604800, } +# These attributes never have non-optional values, so they should be +# ignored in post callbacks +_option_based_attrs = ('krbauthindmaxticketlife', 'krbauthindmaxrenewableage') +_supported_options = ('otp', 'radius', 'pkinit', 'hardened') @register() class krbtpolicy(baseldap.LDAPObject): @@ -78,7 +82,9 @@ class krbtpolicy(baseldap.LDAPObject): """ container_dn = DN(('cn', api.env.realm), ('cn', 'kerberos')) object_name = _('kerberos ticket policy settings') - default_attributes = ['krbmaxticketlife', 'krbmaxrenewableage'] + default_attributes = ['krbmaxticketlife', 'krbmaxrenewableage', + 'krbauthindmaxticketlife', + 'krbauthindmaxrenewableage'] limit_object_classes = ['krbticketpolicyaux'] # permission_filter_objectclasses is deliberately missing, # so it is not possible to create a permission of `--type krbtpolicy`. @@ -94,7 +100,8 @@ class krbtpolicy(baseldap.LDAPObject): 'ipapermdefaultattr': { 'krbdefaultencsalttypes', 'krbmaxrenewableage', 'krbmaxticketlife', 'krbsupportedencsalttypes', - 'objectclass', + 'objectclass', 'krbauthindmaxticketlife', + 'krbauthindmaxrenewableage', }, 'default_privileges': { 'Kerberos Ticket Policy Readers', @@ -108,6 +115,7 @@ class krbtpolicy(baseldap.LDAPObject): 'ipapermright': {'read', 'search', 'compare'}, 'ipapermdefaultattr': { 'krbmaxrenewableage', 'krbmaxticketlife', + 'krbauthindmaxticketlife', 'krbauthindmaxrenewableage', }, 'default_privileges': { 'Kerberos Ticket Policy Readers', @@ -137,6 +145,46 @@ class krbtpolicy(baseldap.LDAPObject): doc=_('Maximum renewable age (seconds)'), minvalue=1, ), + Int('krbauthindmaxticketlife_otp?', + cli_name='otp_maxlife', + label=_('OTP max life'), + doc=_('OTP token maximum ticket life (seconds)'), + minvalue=1), + Int('krbauthindmaxrenewableage_otp?', + cli_name='otp_maxrenew', + label=_('OTP max renew'), + doc=_('OTP token ticket maximum renewable age (seconds)'), + minvalue=1), + Int('krbauthindmaxticketlife_radius?', + cli_name='radius_maxlife', + label=_('RADIUS max life'), + doc=_('RADIUS maximum ticket life (seconds)'), + minvalue=1), + Int('krbauthindmaxrenewableage_radius?', + cli_name='radius_maxrenew', + label=_('RADIUS max renew'), + doc=_('RADIUS ticket maximum renewable age (seconds)'), + minvalue=1), + Int('krbauthindmaxticketlife_pkinit?', + cli_name='pkinit_maxlife', + label=_('PKINIT max life'), + doc=_('PKINIT maximum ticket life (seconds)'), + minvalue=1), + Int('krbauthindmaxrenewableage_pkinit?', + cli_name='pkinit_maxrenew', + label=_('PKINIT max renew'), + doc=_('PKINIT ticket maximum renewable age (seconds)'), + minvalue=1), + Int('krbauthindmaxticketlife_hardened?', + cli_name='hardened_maxlife', + label=_('Hardened max life'), + doc=_('Hardened ticket maximum ticket life (seconds)'), + minvalue=1), + Int('krbauthindmaxrenewableage_hardened?', + cli_name='hardened_maxrenew', + label=_('Hardened max renew'), + doc=_('Hardened ticket maximum renewable age (seconds)'), + minvalue=1), ) def get_dn(self, *keys, **kwargs): @@ -145,6 +193,27 @@ class krbtpolicy(baseldap.LDAPObject): return DN(self.container_dn, api.env.basedn) +def rename_authind_options_from_ldap(entry_attrs, options): + if options.get('raw', False): + return + + for subtype in _supported_options: + for attr in _option_based_attrs: + name = '{};{}'.format(attr, subtype) + if name in entry_attrs: + new_name = '{}_{}'.format(attr, subtype) + entry_attrs[new_name] = entry_attrs.pop(name) + + +def rename_authind_options_to_ldap(entry_attrs): + for subtype in _supported_options: + for attr in _option_based_attrs: + name = '{}_{}'.format(attr, subtype) + if name in entry_attrs: + new_name = '{};{}'.format(attr, subtype) + entry_attrs[new_name] = entry_attrs.pop(name) + + @register() class krbtpolicy_mod(baseldap.LDAPUpdate): __doc__ = _('Modify Kerberos ticket policy.') @@ -158,6 +227,15 @@ class krbtpolicy_mod(baseldap.LDAPUpdate): # ticket policies are attached to objects with unrelated attributes if options.get('all'): options['all'] = False + + # Rename authentication indicator-specific policy elements to LDAP + rename_authind_options_to_ldap(entry_attrs) + return dn + + def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) + # Rename authentication indicator-specific policy elements from LDAP + rename_authind_options_from_ldap(entry_attrs, options) return dn @@ -200,9 +278,18 @@ class krbtpolicy_show(baseldap.LDAPRetrieve): default_entry = {} if attrname in default_entry: entry[attrname] = default_entry[attrname] - if attrname not in entry: + elif attrname in _option_based_attrs: + # If default entry contains option-based default attrs, + # copy the options explicitly + attrs = [(a, a.split(';')[0]) for a in default_entry] + for a in attrs: + if a[1] == attrname and a[0] not in entry: + entry[a[0]] = default_entry[a[0]] + if attrname not in entry and attrname not in _option_based_attrs: raise errors.ACIError( info=_('Default ticket policy could not be read')) + # Rename authentication indicator-specific policy elements from LDAP + rename_authind_options_from_ldap(entry, options) return dn @@ -239,5 +326,6 @@ class krbtpolicy_reset(baseldap.LDAPQuery): entry_attrs = ldap.get_entry(dn, self.obj.default_attributes) entry_attrs = entry_to_dict(entry_attrs, **options) + rename_authind_options_from_ldap(entry_attrs, options) return dict(result=entry_attrs, value=pkey_to_value(uid, options)) diff --git a/ipatests/test_xmlrpc/test_krbtpolicy.py b/ipatests/test_xmlrpc/test_krbtpolicy.py index aab7b7820..929c6764b 100644 --- a/ipatests/test_xmlrpc/test_krbtpolicy.py +++ b/ipatests/test_xmlrpc/test_krbtpolicy.py @@ -117,6 +117,20 @@ class test_krbtpolicy(Declarative): ), + dict( + desc='Update user ticket policy for auth indicator pkinit', + command=('krbtpolicy_mod', [user1], + dict(krbauthindmaxticketlife_pkinit=3600)), + expected=dict( + value=user1, + summary=None, + result=dict( + krbmaxticketlife=[u'3600'], + krbauthindmaxticketlife_pkinit=[u'3600'], + ), + ), + ), + dict( desc='Try updating other user attribute', command=(