In part 1 of this blog series, we talked about centralized authentication in Linux and covered some basic use cases. Part 2 discussed System Security Services Daemon (SSSD) and why it’s becoming so important to centralized authentication in the Linux space.
In part 3, our final post in the series, we’ll discuss authorization and different approaches to automating or centralizing provisioning and de-provisioning across an environment.
There’s a not-insignificant issue around authorization when working with Linux systems. Who should be able to access a given directory, application, or file? Linux has incredibly robust user/group support at a local level (as well as granular read/write/execute permissions), but the goal is to ensure these access privileges are the same across an environment. For example, people who perform administration work should have access to administration tools, the auditing team should have access to the auditing tools, neither group should necessarily have access to each other’s tools, and each group may need a common toolset on the hosts they work across.
In very small environments, manually configuring these settings (creating users, groups, and performing the relevant file permission actions) is doable. It is time consuming, and prone to errors and omissions, but it is doable. However, with each host added we quickly run into an issue where maintaining and extending infrastructure becomes more of a task than the actual use of that infrastructure under a manual model (not an ideal state).
What’s the goal, then? Ideally, we want to mitigate administrative overhead by automating or centralizing activities. Adding and removing users is low-hanging fruit; if we can reduce the number of places that need to change from dozens, hundreds, or thousands of hosts to just one by means of centralization, it can save a lot of time and effort.
For the sake of discussion, let’s say we set up an LDAP server and we use SSSD to connect to the LDAP server for our hosts. Users can authenticate, we’re done.
Not so fast. As mentioned previously, not all users need access to everything on a given host. It would be pretty terrifying if every user had access to, say, superuser privileges on every host they had access to. So we need to be able to perform authorization activities as well, and not just authorization activities, but be able to step up a given session based on whether or not they are a member of a sudo group. On top of using groups in the LDAP server for RBAC, there are two ways we can do this:
1.) Rely on LDAP sudo configuration (which was touched upon briefly in past articles). This can require a lot of setup.
2.) Enumerate groups and call them in the sudoers file. This requires less setup at the LDAP level, but requires a more sophisticated system management platform.
Both approaches have their pros and cons, and both approaches are valid depending on what your organization intends to get out of a sudoers implementation, so let’s talk about both.
LDAP, Sudo rules, and SSSD
Assuming that your sudo LDAP configuration has been appropriately done (Which I would highly recommend reading the documentation on at all steps of implementation), working through sudoer configuration in SSSD is straightforward. The steps boil down to configuring SSSD to manage sudo, and to configure NSS to route to SSSD. Because groups are enumerated via SSSD, SSSD caches groups, and so we can rely on remotely managed groups for sudo. It does this through LDAP filters, which, if you are proficient in LDAP filter syntax it isn’t a difficult task.
Assuming both your SSSD environment as well as your LDAP sudo configuration is properly set up, you can find a rundown for configuration in the Redhat deployment guide. Keep in mind that if you are attempting to do this work around sudoer schemas in Active Directory, you will need to add custom schema elements to Active Directory. Jakub Hrozek comes through again with a blog on how to do this here.
Group Enumeration and Modifying Host Sudo Files
As previously mentioned, SSSD, when used in conjunction with a properly configured LDAP server, will return back what groups a user is a member of. This means is we can use this group information to perform access management to files, applications, and directories… which is what we started off wanting to do and is fantastic. It also means that we can leverage these same groups to determine who gets sudoer access and who does not by just treating them as local groups.
What this looks like in practice might be something like this.. let’s say we have a test user (appropriately named testuser), who is a part of a group called _sudoers. Here’s what that group might look like:
This group is a group we want to use for access determination when sudo checks its configuration. Provided SSSD is properly configured, all we need to do is add the following to our sudoers file. Here’s what that might look like:
Pros and Cons
Both paths forward have upsides and downsides, so let’s go over them. These lists are by no means exhaustive, and you could probably come up with a few more good ones. Hopefully this will get you thinking and headed off in the right direction.
Pros for SUDO LDAP:
- Even more centralized management: Being able to manage even more aspects of a wide range of hosts is powerful. Taking menial tasks away from system administrators so they can focus on more important (and interesting!) issues is usually a good thing.
- Can be audited via certification/recertification processes: A great thing about centralized stores and the entitlements they possess is that certification and recertification processes can be constructed to ensure “group creep” doesn’t happen (I’m looking at you, Sailpoint!). This can entirely mitigate situations where long-standing organizational members end up with access that is nearly on par with that of administrative accounts and is generally a good thing.
- Allows for full control of privileges on a host via LDAP: In environments where sudo file modifications happen often, centralizing sudo information is a godsend. Instead of having to directly modify all hosts, the LDAP server is modified and the hosts are aware of the change on the next query. Meaning no configuration pushes to hosts; the systems at play act accordingly.
- Less overall files to alter: This goes back to the idea of centralization. By keeping it in the LDAP store, you’re left with no work to do in a host’s respective sudo files, just SSSD once your LDAP components are set. Given a properly configured CI/CD workflow that tests this, it can reduce complexity with regards to configuration management.
Cons for Sudo LDAP:
- No guarantees that local sudoer files haven’t been messed with:
- A feature of SSSD is that it relies on local configurations first and foremost. This can be problematic, as it can mean that local changes can be made to a sudoers file, and those changes will override the data that may be out in the LDAP data source. This is a classic example of configuration drift, and some sort of solution needs to be in place to mitigate this.
- Need to have a full understanding of who can modify sudoer privileges: With great power comes great responsibility. Accounts that can modify this space in your LDAP’s DIT should be watched like a hawk. Every account should be accounted for.
- Allows for full control of sudoer privileges on a host via group modification: This is a double-edged sword. Any central authentication store is a ripe target to an attacker, and misconfigured or unhardened LDAP systems (or even systems that store credentials in memory for retrieval via tools such as Mimikatz) can give an attacker not only the keys to the kingdom (via accounts) but a map to the kingdom (via logs and sudoer rules).
- Requires modifying/adding schema: Any time custom schema gets involved in an LDAP server, you add complexity to the LDAP server. This isn’t necessarily a bad thing, and indeed creating custom schema, objectclasses, and attributes is part of why LDAP is awesome. However, this becomes another element that needs to be tracked, managed, and accounted for.
- If you aren’t using TLS, raw LDAP is problematic: Any protocol that is not secured can leak information that could be used to attack an organization. LDAP is particularly terrifying in this regard, due to the fact that it deals with user credentials and in most cases personally identifiable information. TLS should be used whenever possible – and if it is not possible, you may wish to look at getting that fixed ASAP. Defense in depth is crucial.
Pros for Host-side Sudo:
- Extremely easy to implement and test: Host-side sudoer changes that use LDAP-provided groups are as simple as can be- you add the group to the sudoers file, have a member of that group SSH into the box, and attempt to sudo. If it works, you’re done.
- Well-supported use case: Linux group use in sudo is a mature and well-documented feature. Applying it to groups that are being provided via an LDAP datasource (PAM, NSS, and SSSD ensure those groups are treated as they should be) makes sense.
- You already need configuration management:
- In a medium or large environment a CI/CD pipeline that includes configuration management is a must. If a system is already going to have configurations pushed to it (via Ansible/Chef) or pulled in via agent (Puppet, etc.) it stands to reason that a properly configured sudoers file could be a part of the SSSD configuration and even baked into baremetal provisioning processes. These are mostly solved problems, the question is which path does your organization want to go down.
- Still achieves flexibility from LDAP-based group membership: Because sudoers relies on group membership in this case, users can be entitled and disentitled from groups rapidly. This means if a user has been taken off of a project, the only change that needs to be made is at the group on the LDAP server.
Cons for Host-side Sudo:
- Your CI/CD chain needs to be secure: Because this method relies upon a CI/CD infrastructure that utilizes configuration management when at scale, it stands to reason that additional care should be taken here. That means hardening, monitoring, auditing, alerts, etc. Enforce least privilege whenever possible in your CI/CD environment, as the supply chain becomes crucial to manage in this case.
- Requires solid auditing practices: To drive the point home here, local sudo rules win. What this means is that if an attacker has gained persistence on a host and modified sudo, the well-constructed rules to point to specific groups you may have placed in there are irrelevant. That is why it is crucial to monitor the state of this (and other) system files to ensure their veracity and integrity.
- Granularity and changes increase overhead: While sudo privileges may not change all that often once established, over the course of a host’s lifetime it’s a possibility, which means a modification must be pushed out to each host that is impacted. Whereas in a sudo LDAP implementation these changes could be made at the LDAP server, here, this can be problematic unless properly handled. Additionally, if sudo rules become particularly complicated (or are complicated by being assigned on a per “application group” basis) this approach can be difficult to keep track of. Simple, essentially complex access rules can help mitigate this.
Generally, host-side implementation of sudo makes more sense for most small and medium (even some large) Linux host setups unless…
~ the environment is complex (and requires a great deal of constant fiddling in sudoers)
~ you do not trust your CI/CD infrastructure (man-in-the-middle attacks can and do happen)
~ or you don’t have good good monitoring and alerting in your environment (which should be addressed no matter which way you go).
This does not mean that one implementation is necessarily superior to the other, rather it means you have the tools and path forward to make sudo management simpler in a Linux environment.