freeipa/doc/designs/rbcd.md
Alexander Bokovoy 0bf0b2d251 doc/designs/rbcd.md: document use of S-1-18-* SIDs
Fixes: https://pagure.io/freeipa/issue/9354

Signed-off-by: Alexander Bokovoy <abokovoy@redhat.com>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
2023-04-05 14:55:22 -04:00

503 lines
25 KiB
Markdown

# Constrained delegation for Kerberos services
## Overview
The purpose of this document is to describe an integration of two constrained
delegation mechanisms FreeIPA provides for Kerberos services:
- general constrained delegation, available since FreeIPA 3.0.0;
- resource-based constrained delegation, introduced with this design document.
Both constrained delegation mechanisms apply when Kerberos services implement
S4U2Proxy extensions as described in
[MS-SFU](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-sfu/3bff5864-8135-400e-bdd9-33b552051d94)
specification. MIT Kerberos project has its own page that describes
[Services for User](http://k5wiki.kerberos.org/wiki/Projects/Services4User) integration.
FreeIPA work relies on the MIT Kerberos facilities to support S4U extensions,
including S4U2Proxy.
A general constrained delegation mechanism described here for the sake of
completeness. The description is based on the original design document published
originally at [FreeIPA wiki page](https://www.freeipa.org/page/V4/Service_Constraint_Delegation).
A general overview of a constrained delegation from Microsoft point of view can
be found in [this document](https://learn.microsoft.com/en-us/windows-server/security/kerberos/kerberos-constrained-delegation-overview).
## Introduction
Services for User extensions were introduced as a part of Kerberos
implementation in Microsoft's Active Directory. They aim to achieve two
specific goals:
- allow Kerberos services to accept requests authenticated via a different
protocol. A Kerberos service can ask the Kerberos KDC to issue a ticket to
itself on behalf of a user, thus performing a protocol transition. The
resulting service ticket is issued to the service itself, hence S4U2Self
extension name.
- allow a Kerberos service to request a service ticket to a different
Kerberos service on behalf of the original user, hence S4U2Proxy extension
name. The original service ticket must be forwardable. The resulting ticket
can be presented in the communication to that different Kerberos service and
will show both the original user principal and a Kerberos service operating on
its behalf.
The S4U2Proxy feature eliminates the need for the user to delegate their ticket
granting ticket (TGT). FreeIPA uses the S4U2Proxy feature to allow the web
server framework to obtain an LDAP service ticket on the user's behalf.
Similarly, it is also used by the FreeIPA's trust to Active Directory feature
to allow the web server framework to obtain an SMB service ticket on the user's
behalf when configuring Samba and a trust to Active Directory through Samba.
Kerberos KDC has control over the issuance of service tickets for both S4U2Self
and S4U2Proxy extensions. The usage of S4U2Proxy is called "constrained
delegation"; the two mechanisms that represent constrained delegation usage
have different rules associated with them.
The access control for general constrained delegation is controlled by several
LDAP entries, rules and targets, contained in `cn=s4u2proxy,cn=etc,$SUFFIX`.
Rule LDAP entry defines two elements:
- Kerberos principals to be impersonated (defaults to every principal),
- Kerberos services that can impersonate them.
Target LDAP entry defines the list of Kerberos services to which the
impersonator Kerberos services can delegate credentials.
These rules are controlled by the administrators of FreeIPA and cannot be
controlled by the services themselves.
The access control for the resource-based constrained delegation rules is
placed within the LDAP entries of the target Kerberos services. Kerberos
service which supports resource-based constrained delegation will only be able
to request a service ticket to a Kerberos service that explicitly allows this
service to ask for a constrained delegation for itself. The rules are
controlled by the services' administrators (by default, the host service
controls services associated with the host). This reduces an administrative
overhead and delegates decision-making to the application administrators.
## Use cases
The table below summarizes three types of the Kerberos delegation approaches.
A 'forest' concept in the table is an Active Directory term. FreeIPA does not
have a mechanism to place multiple AD-like domains into the same forest. All
systems which deployed to the same FreeIPA deployment are part of the same
FreeIPA domain and the same FreeIPA forest. In terms of Active Directory,
FreeIPA forest represents a single Active Directory domain, the root domain of
the forest. In Kerberos terms all these domains represent separate Kerberos
realms, within or across multiple forests.
Impersonator account in the table corresponds to the application which is
using the delegated credential. In case of a constrained delegation, it is an
application performing S4U2Proxy request.
Resource-based constrained delegation is only supported when FreeIPA is
compiled against MIT Kerberos 1.19 or later.
| | TGT forwarding, unconstrained (by policy) | General constrained delegation | Resource-based constrained delegation |
|---|---|---|---|
|Delegation attributes set on and managed by admin of | Impersonator account (to anyone) | Impersonator account (to a list of resources) | Resource account (to a list of impersonators)|
|Delegation within a domain, client from the local forest | yes | yes | yes |
|Delegation within a domain, client from another forest | yes [1] | yes | yes |
|Delegation across a domain trust within the same forest, client from the local forest | yes | no | yes |
|Delegation across a domain trust within the same forest, client from another forest | yes [1] | no | yes |
|Delegation across forest trust, client from the forest of the impersonator | yes | no | yes |
|Delegation across forest trust, client from the forest of the resource | yes [1] | no | no [2] |
- [1] With Windows updates in 2019, tgt-forwarding when the client and
impersonator are in different forests no longer works unless explicitly
allowed. Microsoft has [issued a guidance](https://support.microsoft.com/en-us/help/4490425/updates-to-tgt-delegation-across-incoming-trusts-in-windows-server)
that details the behavior. Additionally, there is a Microsoft Word document
describing [a KDC behavior](https://aka.ms/kcdpaper).
- [2] Refer to the KDC paper from above for the description of "round-trip
authentication across trusts".
### General constrained delegation
General constrained delegation is often utilized in a multi-service environment
where a frontend service acts on behalf of a user against backend services.
For example, the server side implementation of IPA API framework uses the
delegation of a ticket presented to the web service to act on behalf of this
user when talking to LDAP service.
### Use cases for resource-based constrained delegation
Typical use case is to allow users from the trusted Active Directory forest to
access their network shares while logging into FreeIPA client systems. NFS
server would be enrolled either into Active Directory or the FreeIPA
deployment, FreeIPA client system would be enrolled into FreeIPA deployment.
On FreeIPA client, a user's home directory would be configured to automount NFS
share for the user and use GSSAPI authentication with the help of GSSProxy.
GSSProxy can be configured to use both S4U2Self and S4U2Proxy. This use case is
described in detail in [GSSProxy documentation](https://github.com/gssapi/gssproxy/blob/main/docs/NFS.md#user-impersonation-via-constrained-delegation).
When NFS server is located in the same Kerberos realm as the FreeIPA client
system, this use case can be implemented with general constrained delegation.
When the target service (NFS server) and the proxy service (NFS client) are in
different realms, MS-SFU specification prevents issuance of a service ticket
using S4U2Proxy extension unless there is a resource-based constrained
delegation rule defined for the target service, as outlined in the [MS-SFU 3.2.5.2.3](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-sfu/dd1b47f9-580c-4c4e-8f34-4485b9728331).
As a result, in order to allow delegation of user credentials across the forest
boundary, resource-based constrained delegation must be supported both by the
impersonating (proxy) service and by the KDC of the user forest.
## Design
MS-SFU specification defines that for full support of all S4U functionality an
account database needs to support four elements of information for each
principal, as outlined in [MS-SFU 3.2.1](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-sfu/0b4d13c4-d459-4598-8f08-1584ca1e24c9).
FreeIPA account database is not compatible with Active Directory on LDAP level,
thus implementation is slightly different.
### Unconstrained delegation
IPA API provides a way to record unconstrained delegation permission in both
host and service command families. The following commands have option
`--ok-as-delegate=BOOL`:
- `ipa host-add` and `ipa service-add`
- `ipa host-mod` and `ipa service-mod`
### S4U2Self design
Kerberos service is allowed to request a service ticket to itself on behalf of
any user. However, to make it usable for S4U2Proxy (constrained delegation),
the service ticket must be forwardable. In such case the Kerberos service would
be able to impersonate user and requires an explicit administrative permission.
IPA API provides a way to record this permission in both host and service
command families. The following commands have option
`--ok-to-auth-as-delegate=BOOL`:
- `ipa host-add` and `ipa service-add`
- `ipa host-mod` and `ipa service-mod`
This flag is equivalent to MS-SFU's `TrustedToAuthenticationForDelegation`
boolean setting.
### General constrained delegation design
General constrained delegation uses two objects: a rule and a target.
All entries are stored in the same LDAP container and the only real
distinguishing feature between a rule and a target is the objectClass
`ipaKrb5DelegationACL`:
- a rule will have these objectClasses: `top`, `groupOfPrincipals`,
`ipaKrb5DelegationACL`.
- a target will have these objectClasses: `top`, `groupOfPrincipals`.
Kerberos KDC database driver (KDB) uses a special filter to exclude
`ipaKrb5DelegationACL` when searching for the target.
Both a rule and a target specify affected principals with `memberPrincipal`
attribute.
This combination of rules and targets allows FreeIPA to implement an equivalent
of MS-SFU's `ServicesAllowedToSendForwardedTicketsTo` information.
Management of the general constrained delegation rules and targets is done with
`ipa servicedelegation` commands.
|Command |Description |
|--------------------------------------|------------------------------------------------------------|
|servicedelegationrule-add |Create a new service delegation rule. |
|servicedelegationrule-add-member |Add member to a named service delegation rule. |
|servicedelegationrule-add-target |Add target to a named service delegation rule. |
|servicedelegationrule-del |Delete service delegation. |
|servicedelegationrule-find |Search for service delegations rule. |
|servicedelegationrule-remove-member |Remove member from a named service delegation rule. |
|servicedelegationrule-remove-target |Remove target from a named service delegation rule. |
|servicedelegationrule-show |Display information about a named service delegation rule. |
|servicedelegationtarget-add |Create a new service delegation target. |
|servicedelegationtarget-add-member |Add member to a named service delegation target. |
|servicedelegationtarget-del |Delete service delegation target. |
|servicedelegationtarget-find |Search for service delegation target. |
|servicedelegationtarget-remove-member |Remove member from a named service delegation target. |
|servicedelegationtarget-show |Display information about a named service delegation target.|
### Resource-based constrained delegation design
Resource-based constrained delegation stores information in the target service
LDAP entry. This information is represented with `memberPrincipal` attribute
and is allowed with objectClass `resourceDelegation`. If a Kerberos principal
is mentioned in the `memberPrincipal` attribute of the LDAP entry and
objectClass `resourceDelegation` is present in the same entry, KDB driver will
use information from the `memberPrincipal` attribute to check whether a service
asking for S4U2Proxy extension is allowed to send a forwarded user ticket to
this service.
This approach allows implementing MS-SFU's `ServicesAllowedToReceiveForwardedTicketsFrom`
information.
Management of the resource-based constrained delegation is integrated into `ipa
host` and `ipa service` commands.
|Command |Description |
|--------------------------------|------------------------------------------------------------|
|service-add-delegation |Add new resource delegation to a service |
|service-allow-add-delegation |Allow users, groups, hosts or host groups to handle a resource delegation of this service.|
|service-disallow-add-delegation |Disallow users, groups, hosts or host groups to handle a resource delegation of this service.|
|service-remove-delegation |Remove resource delegation from a service|
|host-add-delegation |Add new resource delegation to a host|
|host-allow-add-delegation |Allow users, groups, hosts or host groups to handle a resource delegation of this host.|
|host-disallow-add-delegation |Disallow users, groups, hosts or host groups to handle a resource delegation of this host.|
|host-remove-delegation |Remove resource delegation from a host|
The `*-allow-add-delegation` and `*-disallow-add-delegation` commands aim to
provide a way to extend list of actors allowed defining delegation access
control. By default, only host and service owners (the host and service
themselves, as well as those objects defined by `managedBy` attribute) allowed
to control the delegation. Additional users, groups, hosts or host groups can
be allowed to set the delegation ACL. The purpose of these commands is to allow
a flexible management without giving a control over the whole host or service
entry.
### Implementation
#### IPA API commands
In both general constrained delegation and resource-based constrained
delegation rules, targets, and delegation permission details are expressed with
`memberPrincipal` attribute. Since IPA's standard `LDAPAddMember` and
`LDAPRemoveMember` classes operate on DNs for the members, they need to be
overridden to represent Kerberos principals. The principal might be not present
in the IPA realm and thus cannot be represented as an LDAP object to which DN
could be constructed.
##### Management of a general constrained delegation
In case of general constrained delegation a special handling is added to
`LDAPAddMember` and `LDAPRemoveMember` classes to handle `memberPrincipal`.
The add/remove methods assume, and require via asserts, that all members be a
DN. `get_member_dns()` needs to ignore any `memberPrincipal` values and return
only the DN-based values when adding targets to rules to let the standard
mechanics of `LDAP*Member` do their work.
In order to handle the `memberPrincipal` values a `post_callback()` is required.
This also means that there be at worst two writes per membership update.
Given that this feature is not expected to be frequently used then speed and
efficiency are not a factor.
Similarly, we enforce that only a target is a member of a rule, and not
another rule. That would be an undefined relationship. To do this each member
needs to be retrieved and evaluated before adding as a member.
A referential integrity rule is needed for `ipaallowedtarget`.
A referential integrity rule is needed, but is not possible, for
`memberPrincipal`. It is not possible because it is not a DN. This adds the
potential to have dangling pointers. In practice, this has not been a problem
for S4U2Proxy usage as administrators rarely add the constrained delegation
rules.
The ACL system also provides a means of limiting which user's a ticket may be
obtained for using the `ipaAllowToImpersonate` attribute. This is not
implemented.
In order to maintain basic functionality, FreeIPA must have entries for
S4U2Proxy operations between IPA API framework, LDAP service, and CIFS service
on IPA server. These entries are `ipa-http-delegation` rule and
`ipa-ldap-delegation-targets` and `ipa-cifs-delegation-targets` targets.
To grant this access, two LDAP entries are required. The first is a
rule which defines the ACL:
```
dn: cn=ipa-http-delegation,...
objectClass: ipaKrb5DelegationACL
objectClass: groupOfPrincipals
cn: ipa-http-delegation
memberPrincipal: HTTP/ipaserver.example.com@EXAMPLE.COM
ipaAllowedTarget: cn=ipa-ldap-delegation-targets,...
```
The second LDAP entry is a target of this rule which defines which principals
may be obtained:
```
dn: cn=ipa-ldap-delegation-targets,...
objectClass: groupOfPrincipals
cn: ipa-ldap-delegation-targets
memberPrincipal: ldap/ipaserver.example.com@EXAMPLE.COM
```
Both types of entries contain members in the form of `memberPrincipal`. In the
case of a rule these are the members that the rule applies to. In the case of a
target the members are the targets of the delegation. In this case the rule has
a member of `HTTP/ipaserver.example.com@EXAMPLE.COM` and a rule with a member
of `ldap/ipaserver.example.com@EXAMPLE.COM` which means that the HTTP principal
can obtain an LDAP service ticket on behalf of the bound user.
The same approach is used to allow the IPA API framework to obtain a service
ticket on behalf of a user to Samba when a trust to Active Directory is
established. In this case, instead of `ldap/ipaserver.example.com@EXAMPLE.COM`,
a target principal of `cifs/ipaserver.example.com@EXAMPLE.COM` is used.
These two rules are configured by default in the FreeIPA deployment.
##### Resource-based constrained delegation
Resource-based constrained delegation relies on a `memberPrincipal` attribute
in the target service's LDAP object. To manage this attribute, we extend
`LDAPAddAttribute` and `LDAPRemoveAttribute` classes. Both classes were added
after general constrained delegation was implemented and present a better
abstraction to handle member principals.
To control validity of the member principals, a method that checks realms
against a list of trusted domains is added. This allows to set up
resource-based constrained delegation for cross-forest services.
Access control for resource-based constrained delegation is performed in the
following way. A service can modify own delegation list and specify which
Kerberos principals are allowed to delegate to the service. Host where service
is located can manage the service as well.
Administrators can grant other users, groups, hosts, or services permissions to
handle resource-based constrained delegation of a host or a service.
#### Kerberos KDC implementation
KDB API provides two callbacks for the database drivers to implement access
control checks for constrained delegation.
General constrained delegation callback `check_allowed_to_delegate()` allows
checking whether a server is allowed to obtain tickets from client to a target
service. This is implemented by loading constrained delegation LDAP rules and
targets associated with the target service and the proxy server and checking
that they match.
Resource-based constrained delegation callback `allowed_to_delegate_from()`
allows checking whether a target service allows a server to delegate a ticket.
This is implemented in two parts:
- first, `memberPrincipal` attribute in the principal is loaded and added to TL
data of the principal object in KDC under `KRB5_TL_CONSTRAINED_DELEGATION_ACL` type.
- second, the resource-based constrained delegation callback retrieves
`KRB5_TL_CONSTRAINED_DELEGATION_ACL` TL data and validates that a server is
present in the list of principals.
Since `KRB5_TL_CONSTRAINED_DELEGATION_ACL` TL data might be present in the
Kerberos principal KDC object, destructor for the Kerberos principal is
extended to free the associated memory.
Finally, KDB driver follows requirements for [MS-SFU 3.2.5.1.2](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-sfu/ad98268b-f75b-42c3-b09b-959282770642)
and adds SIDs `S-1-18-1` or `S-1-18-2` to the MS-PAC structure's `extraSids`
field depending on how identity was verified:
* for non-S4U2Self operation initial PAC structure population includes a SID
`S-1-18-1`, as a `AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY`,
* for S4U operation, instead, a SID `S-1-18-2` is added, as a `SERVICE_ASSERTED_IDENTITY`.
### Test Plan
General constrained delegation is already used by the IPA management framework
and thus being tested with every IPA API call.
For resource-based constrained delegation cases defined in the use case summary
table. Since FreeIPA currently does not have support for IPA to IPA trust and
does not provide a working two-way trust with Active Directory, it is not
possible to test a scenario where RBCD is applied cross-realm by FreeIPA itself
but the proxy service is in a trusted realm. When IPA to IPA trust or proper
two-way trust to Active Directory would be implemented, this scenario could be
tested.
Thus, a primary RBCD scenario to test is an interoperability with another
RBCD-enabled realm (e.g. Active Directory) where IPA client is used to
initiate the S4U2Proxy operation against a resource (service) in a trusted
realm. In this case Kerberos library on the IPA client should set RBCD support
flag in the PAC structure and trigger S4U2Proxy request. A trusted realm's KDC
will do its check and allow or deny the access request.
#### Usage examples for RBCD
##### Setup RBCD for a service
Let's consider a case where a web frontend needs to connect to an internal
SMB server running on another IPA server on behalf of a user. This is similar
to a default setup in FreeIPA with general constrained delegation but on a
different host and using a different service.
* a host `web-service.example.test` would run a web server and use
`HTTP/web-service.example.test` service principal.
* a host `file.example.test` would be a Samba server running on IPA-enrolled
client. Its SMB server uses `cifs/file.example.test` service principal.
In RBCD model, the control over who can delegate user resources to the service
would be defined at the service side, in this case at `cifs/file.example.test`.
An RBCD access control for `cifs/file.example.test` would need to mention
`HTTP/web-service.example.test` principal to allow the web server to delegate
user's credentials to the Samba server.
Example 1: Administrator can set RBCD ACL directly:
```
$ kinit admin
$ ipa service-add-delegation cifs/file.example.test HTTP/web-service.example.test
```
Example 2: Host `file.example.test` can use a host keytab to define RBCD ACL
directly because a host always manages the services running on it:
```
# kinit -k
# ipa service-add-delegation cifs/file.example.test HTTP/web-service.example.test
```
Example 3: Allow users from a group `storage-admins` to define RBCD ACLs to
`cifs/file.example.test`:
```
$ kinit admin
$ ipa service-allow-add-delegation cifs/file.example.test --groups=storage-admins
```
Then, a user `some-user` from `storage-admins` group can add a delegation ACL:
```
$ kinit some-user
$ ipa service-add-delegation cifs/file.example.test HTTP/web-service.example.test
```
Example 4: Remove permission to add RBCD ACLs for `cifs/file.example.test` from
members of the `storage-admins` group:
```
$ kinit admin
$ ipa service-disallow-add-delegation cifs/file.example.test --groups=storage-admins
```
Now a user `some-user` from `storage-admins` group cannot add a delegation ACL:
```
$ kinit some-user
$ ipa service-add-delegation cifs/file.example.test HTTP/web-service.example.test
.. ERROR ..
```
Example 5: Test RBCD access by service `HTTP/web-service.example.test` to
`cifs/file.example.test`. In this example we assume that an RBCD ACL created in
examples 1-3 exists, there is a keytab `/path/to/web-service.keytab` for
`HTTP/web-service.example.test`, and a `cifs/file.example.test` service was
created with `ipa-install-samba` tool which ensures a keytab was obtained for
Samba service as well. The presence of keytabs ensures corresponding Kerberos
services have all needed Kerberos keys so that service tickets can be created
by KDC.
In the example below we are delegating user `some-user` credentials to the
service `cifs/file.example.test`. First, we pretend our web service has
authenticated the user with some mechanism. Then we aquire a service ticket to
ourselves (`HTTP/web-service.example.test`) with the help of `kvno -U username`
command. Finally, we use `kvno -P` option to ask for S4U2Proxy operation and
specify for which services tickets will be asked using constrained delegation.
```
# kvno -U some-user -k /path/to/web-service.keytab \
-P HTTP/web-service.example.test cifs/file.example.test
```