FreeIPA – Granting Sudo Access to SELinux Confined User

freeipaselinuxsudo

I'm using freeIPA to define RBAC, HBAC and sudo rules, as well as SELinux user mappings for a domain of a couple hundred virtual machines, where I need to grant different levels of access to several teams (developers, database administrators, system administrators, management, …).

Currently, the SELinux policy on these machines is set to targeted, and I'm pondering the possibility of deleting the unconfined_u SELinux user in order to make these systems run under a strict policy.

In order to do that, one of the requirements is to make transparent to the end user the fact that he/she has been 'demoted' from unconfined_u to staff_u. The problem resides in the way sudo interoperates with the SELinux user mappings. Some facts:

  1. if you want to use a confined SELinux user and you want to still be able to use sudo, you need to use staff_u, as this is the SELinux user with access to SETUID executables.

  2. when a user logs into a system, he/she is assigned a SELinux user mapping. That mapping does not change even in the case the SELinux user can run su (unconfined_u) or sudo (unconfined_u, staff_u).

  3. the SELinux Spec for sudo currently contains facilities to run commands in defined types and roles, but lacks the possibility of specifying the user too. Further reference can be found here.

  4. the machines involved in this deployment are all freeIPA clients and their sudo policies are managed by freeIPA, but they also have a puppet managed, customized /etc/sudoers file, provided as a fallback in case of a freeIPA failure.

My first attempt to solve this problem involved witting a policy module containing the needed rules to allow staff_u access to the unmodified sudorules. This approach has proven to be wrong, because the policy can grow indefinitely and finally what you are doing is punching a hole in the policy.

So the way I have dealt with this these facts so far has been rewriting the sudorules to explicitly contain a call to runcon to switch to the appropriate SELinux user, so a typical developer now needs to run, for example:

$ sudo -u jboss runcon -u sysadm_u jboss_cli.sh

This has the drawback of having to modify all the existing sudorules and forcing the user to change the way the usually run stuff. So the questions are:

  • is there a way to explicitly define the SELinux user in a Runas_Spec definition?
  • if not possible via sudoers, is it possible to define, or otherwise bind, a sudorule to a SELinux user mapping in freeIPA?

Consider this scenario:

# ipa sudorule-show services_4_operators_3
  Rule name: services_4_operators_3
  Description: Operator Level 3 access to service management commands
  Enabled: TRUE
  User Groups: operators_3
  Host Groups: all-hosts
  Sudo Allow Command Groups: services
  Sudo Option: type=sysadm_t, role=sysadm_r

# ipa sudocmdgroup-show services
  Sudo Command Group: services
  Description: commands for services and daemons management
  Member Sudo commands: /sbin/service, /sbin/chkconfig

If I try:

$ sudo service sshd status
sudo: unable to open /var/log/sudo-io/seq: Permission denied
time->Wed Sep 11 09:57:30 2013
type=PATH msg=audit(1378886250.584:46644668): item=0 name="/var/log/sudo-io/seq" inode=154 dev=fd:0c mode=0100600 ouid=0 ogid=1168000009 rdev=00:00 obj=unconfined_u:object_r:var_log_t:s0
type=CWD msg=audit(1378886250.584:46644668):  cwd="/home/some_user"
type=SYSCALL msg=audit(1378886250.584:46644668): arch=c000003e syscall=2 success=no exit=-13 a0=7fff2e7ab970 a1=42 a2=180 a3=0 items=1 ppid=2374 pid=2442 auid=1168000009 uid=1168000009 gid=1168000009 euid=0 suid=0 fsuid=0 egid=1168000009 sgid=1168000009 fsgid=1168000009 tty=pts0 ses=6459 comm="sudo" exe="/usr/bin/sudo" subj=staff_u:staff_r:staff_sudo_t:s0-s0:c0.c1023 key="access"
type=AVC msg=audit(1378886250.584:46644668): avc:  denied  { read write } for  pid=2442 comm="sudo" name="seq" dev=dm-12 ino=154 scontext=staff_u:staff_r:staff_sudo_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:var_log_t:s0 tclass=file

Because I'm using log_output in Defaults and:

# ll -dZ /var/log/sudo-io
drwx------. root root system_u:object_r:var_log_t:s0   /var/log/sudo-io/

Trying to "fix" this AVC denial will result in the aforementioned infinite policy module, because allowing:

allow staff_sudo_t var_log_t:file { open read write lock create };
allow staff_sudo_t var_log_t:dir { write add_name create search };

is a spurious problem, as shown when enabling such permissions:

$ sudo service sshd status
env: /etc/init.d/sshd: Permission denied
time->Wed Sep 11 11:00:53 2013
type=PATH msg=audit(1378890053.185:46646934): item=0 name="/etc/init.d/sshd" inode=5490 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 obj=system_u:object_r:sshd_initrc_exec_t:s0
type=CWD msg=audit(1378890053.185:46646934):  cwd="/"
type=SYSCALL msg=audit(1378890053.185:46646934): arch=c000003e syscall=59 success=no exit=-13 a0=7fffc0829862 a1=7fffc0829578 a2=607030 a3=ffffe000 items=1 ppid=6715 pid=6720 auid=1168000009 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts2 ses=6459 comm="env" exe="/bin/env" subj=staff_u:sysadm_r:sysadm_t:s0-s0:c0.c1023 key=(null)
type=AVC msg=audit(1378890053.185:46646934): avc:  denied  { execute } for  pid=6720 comm="env" name="sshd" dev=dm-1 ino=5490 scontext=staff_u:sysadm_r:sysadm_t:s0-s0:c0.c1023 tcontext=system_u:object_r:sshd_initrc_exec_t:s0 tclass=file

FINAL EDIT

I have finally adopted a mid-term solution. I have configured my IPA server as follows:

$ sudo -u dsastrem ipa config-show
  Maximum username length: 32
  Home directory base: /home
  Default shell: /bin/rbash
  Default users group: ipausers
  Default e-mail domain: company.com
  Search time limit: 2
  Search size limit: 100
  User search fields: uid,givenname,sn,telephonenumber,ou,title
  Group search fields: cn,description
  Enable migration mode: FALSE
  Certificate Subject base: O=COMPANY.COM
  Password Expiration Notification (days): 4
  Password plugin features: AllowNThash
  SELinux user map order: guest_u:s0$xguest_u:s0$user_u:s0$staff_u:s0-s0:c0.c1023$unconfined_u:s0-s0:c0.c1023
  Default SELinux user: guest_u:s0
  Default PAC types: MS-PAC

and I have defined some SELinux user mappings similar to this one that bind some RBACs to a SELinux user (staff_u).

$ sudo -u dsastrem ipa selinuxusermap-find
---------------------------
X SELinux User Maps matched
---------------------------
  ....

  Rule name: semap_operators_3_mad
  SELinux User: staff_u:s0-s0:c0.c1023
  HBAC Rule: operators_3_access
  Description: SELinux user mapping for MAD level 3 operators
  Enabled: TRUE

  ....
----------------------------
Number of entries returned X
----------------------------

My sudo rules now look like this one:

  Rule name: services_4_operators_3
  Description: Operator Level 3 access to service management commands
  Enabled: TRUE
  User Groups: operators_3
  Host Groups: all-hosts
  Sudo Allow Command Groups: services
  Sudo Option: role=unconfined_r

This is not my final goal, as I wanted to completely eliminate unconfined_u, but it's a good step forward, as it enhances a little bit the overall security. Of course, Matthew's answer is correct, as staff_u should be able to transition to a higher privileged domain via sudo options; but there's still the problem of system_u not being completely equipped to replace unconfined_u. Maybe because it is not intended to do so.

Best Answer

You are aware that you can move into the sysadm_r role as staff_u right?

For example, the following below would work.

myuser  ALL=(ALL)   TYPE=sysadm_t ROLE=sysadm_r PASSWD: ALL

This will allow you to do (almost) what you can do as root as unconfined.

Oh and one final tip. Using su is a bit tricky with RBAC (it does a lot of stuff which gets it into all sorts of places). Instead you can use the runuser command which does the same thing without a lot of su overheads.

I actually restrict su use in sudoers like so;

%wheel   ALL=(ALL)   TYPE=sysadm_t ROLE=sysadm_r NOPASSWD: ALL, ! /bin/su

Because by default the SELinux policy doesn't allow the sudo transition to manage the necessary signals. Really people should probably just use sudo -i anyway.

I normally hardlink runuser to ru as a two-letter replacement for people who prefer to run sudo su - out of a bad habit (like me!).