Constrained Delegation

Simo Sorce simo at redhat.com
Sat Sep 7 14:07:50 EDT 2013


On Sat, 2013-09-07 at 00:59 -0600, Shawn M Emery wrote:
> We were wanting to provide additional checks beyond constrained 
> delegations where the proxy principal has access controls associated for 
> which client principals are allowed to be delegated from.  I know that 
> this could be controlled by creating authz data that the subsequent 
> target service can check, but this seems rather inefficient in a 
> non-cross-realm case in which the KDC can easily make these policy checks.
> 
> My draft proposal includes a new LDAP attribute of the proxy principal:
> 
>      krbAllowedToDelegateFor
> 
> which would define the various client principals in which the proxy 
> principal is allowed to delegate for.  Perhaps this could be tied into 
> group memberships in order to reduce redundant definitions across proxy 
> principals.  The ordering of checks by the KDC would be to check to make 
> sure that the target principal is in the krbAllowedToDelegateTo set and 
> if so then infer the krbAllowedToDelegateFor for the client principal.  
> If not defined then then fall-back to the existing behavior of success 
> else if the client is found in the krbAllowedToDelegateFor set then 
> succeed else fail.  The pseudo-code would like the following:
> 
>      {DelegateTo} == proxy && {DelegateFor} == client -> succeed
>      {DelegateTo} == proxy && {DelegateFor} == NULL -> succeed
>      {DelegateTo} == proxy && {DelegateFor} != client -> fail
> 
> The code-points would entail the following:
> 
> /* Constrained delegation for */
> #define KRB5_KDB_FLAG_CONSTRAINED_DELEGATION_4 0x00000400
> #define KRB5_KDB_FLAGS_S4U \
>    ( KRB5_KDB_FLAG_PROTOCOL_TRANSITION | 
> KRB5_KDB_FLAG_CONSTRAINED_DELEGATION | \
>      KRB5_KDB_FLAG_CONSTRAINED_DELEGATION_4 )
> 
> #define KRB5_TL_CONSTRAINED_DELEGATION4_ACL 0x0700 /* Each entry is a 
> permitted UPN */
> 
> ##### A list of principals to which a service principal can delegate for.
> dn: cn=schema
> changetype: modify
> add: attributetypes
> attributetypes:  ( 1.3.6.1.4.1.5322.21.2.4
>                  NAME 'krbAllowedToDelegateFor'
>                  EQUALITY caseExactIA5Match
>                  SUBSTR caseExactSubstringsMatch
>                  SYNTAX 1.3.6.1.4.1.1466.115.121.1.26)
> 
> I just wanted to get your thoughts on the idea before I consider this 
> further.


Hi Shawn, we've address this problem in FreeIPA using a slightly more
complex scheme in order to be able to handle groupings which makes the
feature actually usable (having to list all principals in multiple rules
quickly becomes unmaintainable).

We added 3 attributes and 2 objectclasses:

attributeTypes: ( 2.16.840.1.113730.3.8.11.20
		 NAME 'memberPrincipal'
		 DESC 'Principal names member of a groupOfPrincipals group'
		 EQUALITY caseIgnoreMatch
		 SUBSTR caseIgnoreSubstringsMatch
		 SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'IPA-v3')
objectClasses: ( 2.16.840.1.113730.3.8.12.6
		 NAME 'groupOfPrincipals'
		 SUP top AUXILIARY
		 MUST ( cn )
		 MAY ( memberPrincipal )
		 X-ORIGIN 'IPA v3' )

attributeTypes: ( 2.16.840.1.113730.3.8.11.21
		  NAME 'ipaAllowToImpersonate'
		  DESC 'Principals that can be impersonated'
		  SUP distinguishedName X-ORIGIN 'IPA-v3')
attributeTypes: ( 2.16.840.1.113730.3.8.11.22
		  NAME 'ipaAllowedTarget'
		  DESC 'Target principals alowed to get a ticket for'
		  SUP distinguishedName X-ORIGIN 'IPA-v3')
objectClasses: ( 2.16.840.1.113730.3.8.12.7
		 NAME 'ipaKrb5DelegationACL'
		 SUP groupOfPrincipals STRUCTURAL
		 MAY ( ipaAllowToImpersonate $ ipaAllowedTarget )
		 X-ORIGIN 'IPA v3' )

The way it works is by creating first a groupOfPrincipals (may contain a
single principal) for clients and targets, and then joining all together
into an 'ACL object'.

Example: we want to allow our HTTP server cluster to impersonate 2 users
(shawn and simo) against the LDAP server cluster:

First we create a group of users:

dn: cn=allowed-users,SUFFIX
objectclass: groupOfPrincipals
cn: cn=allowed-users
memberPrincipal: shawn at KERBEROS.ORG
memberPrincipal: simo at KERBEROS.ORG

Then a group of target servers (we assume there may be multiple copies
all equally accessible):

dn: cn=LDAP-Servers,SUFFIX
objectclass: groupOfPrincipals
cn: LDAP-Servers
memberPrincipal: ldap/ldap-server-1.kerberos.org at KERBEROS.ORG
memberPrincipal: ldap/ldap-server-2.kerberos.org at KERBEROS.ORG

Finally we create the allow rule which binds clients, targets and the
proxying service:

dn: cn=http-ldap-delegation,SUFFIX
objectclass: groupOfPrincipals
objectclass: ipaKrb5DelegationACL
cn: http-ldap-delegation
ipaAllowToImpersonate: cn=allowed-users,SUFFIX
ipaAllowedTarget: cn=LDAP-Servers,SUFFIX
memberPrincipal: HTTP/http-proxy-1.kerberos.org at KERBEROS.ORG
memberPrincipal: HTTP/http-proxy-2.kerberos.org at KERBEROS.ORG
memberPrincipal: HTTP/http-proxy-3.kerberos.org at KERBEROS.ORG


Note that in our schema lack of ipaAllowToImpersonate means ALL clients
can be impersonated. We haven't implemented it yet but also you could
have regexes in memberPrincipal for additional flexibility.

This schema allows us to resolve the ACL using a single LDAP query (if
your LDAP server supports the dereference control).

We find this schema was the optimal compromise between the flexibility
we needed and the complexity we wanted to allow, and simpler ones would
prevent us from doing what's needed in a useful manner.


The only drawback is that you cannot fit this into kadmin as it is,
because it requires to be able to represent grouping mechanism and ACL
objects, it would be nice if kadimn could be extended so that it is
flexible enough to allow this kind of representation.

HTH,
Simo.

-- 
Simo Sorce * Red Hat, Inc * New York



More information about the krbdev mailing list