Fixes: https://pagure.io/freeipa/issue/3226 Signed-off-by: Alexander Bokovoy <abokovoy@redhat.com> Reviewed-By: Christian Heimes <cheimes@redhat.com> Reviewed-By: Rob Crittenden <rcritten@redhat.com> Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
8.7 KiB
Include users and groups from a trusted Active Directory domain into SUDO rules
Allow users and groups from trusted Active Directory forests to be directly added to SUDO rules.
Use Cases
- As an FreeIPA administrator, I want to add AD users and groups directly to SUDO rules without creating an indirect POSIX group membership for them.
Design
FreeIPA integration
FreeIPA manages and stores SUDO rules in LDAP and SSSD retrieves the rules related to the specific host it runs on. The rules are then provided to SUDO via a special SUDOERS plugin which is talking to SSSD.
SUDOERS allows multiple ways of expressing users and groups as a part of the rule.
According to the SUDOERS manual page, the following syntax is supported:
User ::= '!'* user name |
'!'* #uid |
'!'* %group |
'!'* %#gid |
'!'* +netgroup |
'!'* %:nonunix_group |
'!'* %:#nonunix_gid |
'!'* User_Alias
A
User_List
is made up of one or more user names, user-IDs (prefixed with ‘#’), system group names and IDs (prefixed with%
and%#
respectively), netgroups (prefixed with ‘+’), non-Unix group names and IDs (prefixed with%:
and%:#
respectively) andUser_Aliases
. Each list item may be prefixed with zero or more!
operators. An odd number of!
operators negate the value of the item; an even number just cancel each other out. User netgroups are matched using the user and domain members only; the host member is not used when matching.
As can be seen from the SUDOERs definition of a User
, any object that maps
into a user or a group is allowed. LDAP schema used to model SUDO rules in
FreeIPA does require SUDO User
references to be real LDAP objects. In order
to support non-LDAP objects both FreeIPA and SSSD support a special attribute
externalUser
. externalUser
is a string that is merged with other User
references at SSSD side.
SSSD already supports querying with first five forms. When SUDO rules are
retrieved from FreeIPA, the references for groups are converted to %group
format in SSSD database. Correspondingly, ID-based forms (#uid
and %#gid
)
are added as well. It does not, however, support queries for non-Unix group
names and IDs.
SSSD team decided to not support %:nonunix_group
and %:nonunix_gid
syntax.
Without changes on SSSD side it will be not possible to support them.
Since in FreeIPA environment all AD users and groups resolvable by SSSD will have POSIX attributes, they can be queried with the first four name forms.
Implementation
FreeIPA framework's LDAP abstraction layer allows to validate and transform membership information when members are added to 'group' objects or removed from them. SUDO rules represent one such 'group' object.
LDAP abstraction layer provides add_external_pre_callback()
method that
allows to redefine validators used to validate member names. Originally this
was done to allow hostname validation and reused default validators associated
with a parameter type associated with a specific parameter.
We extend add_external_pre_callback()
to provide per-object validator
callbacks.
Validator callbacks can be extended to allow a fine grained validation strategy. This is helpful to apply an alternative validation strategy in the case a default validator fails.
New validators can be added to member_validator
registry in a similar
way to how API objects are registered:
from .baseldap import member_validator
@member_validator(membertype='foo')
def my_new_validator(ldap, dn, keys, options, value):
<validate value here>
Arguments passed to the validator are arguments passed to the
add_external_pre_callback()
augmented with the value to validate.
This approach provides a general method to extend validation mechanism for any parameter. The feature utilizes existing infrastructure for resolving objects from trusted Active Directory forests provided by ID views plugin. Any user or group from a trusted Active Directory domain can be resolved in the validator and mapped to a user or group member type for SUDO rule inclusion.
Since options
dictionary is the only object shared between the caller to
add_external_pre_callback()
and the member type validator, ID views' member
type validator returns all validated values as a list stored as a
trusted_objects
element of the options
dictionary.
SUDO rule plugin implementation then processes the translated trusted object
members reported after calling the add_external_pre_callback()
. Each
translated member is the one not found in LDAP as a direct reference and found
in a trusted domain. All these members are then added to externalUser
attribute.
Note that direct manipulation of externalUser
attribute through IPA
parameters is not allowed since 2011 (FreeIPA tickets
https://pagure.io/freeipa/issue/1320). With membership validation method SUDO
rules can now handle those members through the normal --users
mechanism.
Same approach is used to provide handling of RunAs_Member
specification
which is mapped to either ipaSudoRunAsExtUser
or ipaSudoRunAsExtGroup
.
Web UI
Web UI already allows to specify external users and groups in SUDO rules. Names provided by the user weren't validated, now they are verified to belong to trusted domains.
Upgrade and migration
The changes to plugins do not require any schema updates because there are no LDAP schema changes.
Usage
In order to add an Active Directory user to a SUDO rule, there must be a trust established to the Active Directory forest where a domain of the user is located. Any modification of SUDO rules with Active Directory users and groups should happen on Trust Controllers or Trust Agents because other IPA replica types are unable to validate AD users and group.
Sample usage
Below example shows a generic usage of SUDO rules with AD users. It assumes we want to allow an Active Directory user(s) ability to operate on all hosts and all commands without authentication. In real life it is not recommended to grant so wide access.
- As admin, create an HBAC rule to permit all users to run SUDO on all hosts:
ipa hbacrule-add hbacrule --usercat=all --hostcat=all
ipa hbacrule-add-service hbacrule --hbacsvcs=sudo
- As an admin, create SUDO rule that allows to run all commands on all hosts:
ipa sudocmd-add ALL
ipa sudorule-add sudorule --hostcat=all
ipa sudorule-add-option sudorule --sudooption '!authenticate'
ipa sudorule-add-allow-command sudorule --sudocmds ALL
- Add
ad-user\@ad.example.test
to the SUDO rule:
ipa sudorule-add-user sudorule --users ad-user@ad.example.test
- Alternatively, add an Active Directory group
somegroup@ad.example.test
to the SUDO rule:
ipa sudorule-add-user sudorule --groups 'somegroup@ad.example.test'
- On an IPA-enrolled client, perform SUDO access as an Active Directory user:
# su - ad-user@ad.example.test -c 'sudo -l'
Matching Defaults entries for ad-user@ad.example.test on client:
!visiblepw, always_set_home, match_group_by_gid, always_query_group_plugin,
env_reset, env_keep="COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS",
env_keep+="MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE",
env_keep+="LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES",
env_keep+="LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE",
env_keep+="LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY",
secure_path=/sbin\:/bin\:/usr/sbin\:/usr/bin
User ad-user@ad.example.test may run the following commands on master:
(root) NOPASSWD: ALL
- To limit rule execution to a specific user and/or group,
runAsUser
andrunAsGroup
properties can be set individually:
ipa sudorule-add-runasuser sudorule --users 'ad-user@ad.example.test'
ipa sudorule-add-runasgroup sudorule --groups 'somegroup@ad.example.test'
- The limits will be reflected in
sudo -l
output:
# su - ad-user@ad.example.test -c 'sudo -l'
Matching Defaults entries for ad-user@ad.example.test on client:
!visiblepw, always_set_home, match_group_by_gid, always_query_group_plugin,
env_reset, env_keep="COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS",
env_keep+="MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE",
env_keep+="LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES",
env_keep+="LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE",
env_keep+="LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY",
secure_path=/sbin\:/bin\:/usr/sbin\:/usr/bin
User ad-user@ad.example.test may run the following commands on master:
(ad-user@ad.example.test : "%somegroup@ad.example.test") NOPASSWD: ALL