Devuan freeipa domain users control local devices

The Debian method of granting access to devices like the network cards, audio output, printers, etc., is to add a user to the appropriate system group. For domain users, however, do I have to add every single domain user to the local group? I have sought an answer to this problem for a long time. After a lot of research, and coming back to the problem, I finally have a solution I find acceptable for general use and for sharing.


You have to adjust pam, nsswitch, and the local groups themselves. However, no additional packages should be needed!


I did this with lightdm display manager, which calls pam. During my research, I read on one of those pages somewhere that not all DMs use pam. Just make sure yours does.
You have domain groups named netdev, plugdev, audio, etc. Making extra groups in the directory, with either nested groups or direct members, is a small price to pay for this goal!

The steps

Configure pam

You have to configure pam to include the pam_group library.

sudo touch "${tf}" ; sudo chmod 0644 "${tf}" ; sudo chown root.root "${tf}"
cat <<EOF | sudo tee "${tf}" 1>/dev/null
Name: activate /etc/security/group.conf
Default: yes
Priority: 900
Auth-Type: Primary
        required               use_first_pass

And run the debian pam-auth-update program. Obviously there is not a EL equivalent, but then you can’t have this problem on a EL derivative.


And select the option that we just wrote, “Activate /etc/security/group.conf”

Configure nsswitch.conf

Change the group: line in nsswitch.conf to the following:

group:      compat [SUCCESS=merge] sss

You can accomplish that with a sed oneliner:

sed -i -r -e '/^\s*group:/s/(compat|files) sss/\1 [SUCCESS=merge] sss/;' /etc/nsswitch.conf

Change the local groups

To take advantage of the glibc group merging, you have to be using glibc 2.24 or higher, and Devuan Ceres has 2.28 so we’re good. Also, the GIDs have to match exactly. Of course your GID range will be different from mine, but I wrote a general solution.

test -z "${LOGFILE}" && LOGFILE=/root/deploy.log
for word in netdev video audio dip ;
      tgid="$( getent group -s  sss  "${word}" | awk -F':' '{print $3}' )"
      ogid="$( getent group -s files "${word}" | awk -F':' '{print $3}' )"
   } 2>/dev/null
   # if group exists locally and in domain
   test -n "${ogid}" && test -n "${tgid}" && test ${ogid} -ne ${tgid} && {
      # use sed because groupmod fails because the new GID already exists
      sed -i -r -e "/^${word}:/s/:${ogid}:/:${tgid}:/;" /etc/group
      # log to stdout and logfile
      printf '%s %s\n' "$( date -u "+%FT%TZ" )" "Change ${word} from gid ${ogid} to ${tgid}" | tee -a "${LOGFILE}"

This snippet changes the gid of the requested local groups, to match the gid of the netgroups. A reboot is required to get the updated permissions on the device special files.


Web searches

pam_group add domain user to netdev


  1. pam – Add all network users to local group for specific hosts in CentOS7 – Server Fault
  2. OpenLDAP/SSSD Automatically Add User to Local Group – Server Fault
  3. LDAPClientAuthentication – Community Help Wiki []
  4. Proposals/GroupMerging – glibc wiki
  5. SystemGroups – Debian Wiki
  6. My question from a few months ago Grant domain user access like he is in netdev group []

Assigning permissions for Linux service account to add machines to AD

Create service account.

On the domain where the machines will be joined:
Open Active Directory Users and Computers. Enable Advanced Features on the “View” menu.

View the properties of the entire domain.

Select the Security tab, and select Advanced.

  • For this object and all descendant objects: Grant Create/Delete Computer objects
  • For descendant computer objects: Grant Reset password
  • For descendant computer objects: Read/write account restrictions
  • For descendant computer objects: Write all properties, Write all validated writes

A case study in wholistic computer system support

A case study in wholistic computer system support

A user emailed me directly asking for me to look at why his webapp isn’t starting. He was having trouble even looking at the logs with journalctl.

I had built the servers for the user, so he always tries to shortcut the support process of opening a ticket to the team queue, and just assigned it directly to me. I emailed the user back saying, “I’ve assigned it to the team queue for you.”

Well, within 5 minutes the level 1 support guy reached out to me saying he couldn’t find anything wrong. And yes, while nothing was wrong on the OS and filesystem level, the app still wasn’t starting.

The user, in the mean time, had remembered his service account that runs the app so he switched user to that and read the logs. It didn’t have permission to the parent directories, on the nfs mount point.

I set aside the tasks I had scheduled for this afternoon, and took a look. Aside from some setgid on the parent directory without g+rx, nothing looked amiss. The directory was owned by root.root which didn’t seem different from the other contents on the filesystem.

My manager approved just fixing the problem and we’ll sort out what caused it later. So the user and I ran chown -R appuser.appuser /mnt/appdir/subdir1 and then the application could get started again.

The investigation

I checked the sudoers history on the two application servers to see if any users ran sudo chown or sudo chmod even though it was locked down enough to prevent that. No activity with sudo looked related, so I then turned to the filesystem itself.

It is nfs, so it could be affected by other systems. After using mount | grep /mnt/appdir and showmount -e $SERVERNAME | grep $EXPORTNAME I had a list of the IP addresses that have access to this export from the nfs server.

I did a reverse dns lookup to get the hostnames because obviously those are easier to recognize than just a whole series of IP addresses. Immediately I recognized the systems as the other container proof of concept.

Before I even started checking bash history on those hosts, I reached out to the container research guy and he told that I think a reckless chown affected an nfs mount point that affected the app running on the original servers. He said yes, it was him, and he “was trying to set the permissions on the logs directory, but the container mounted the entire nfs.”

I thanked him for being honest, and reminded him that chown -R is serious business. He claimed that this is a further reason for having his own nfs mount point. Additionally, kubernetes has a known security flaw about the availability of an entire mount when mounting just a path of it to a container.

This second user made an additional rookie mistake last week when he changed network settings on a system over a network connection before confirming he had console access. Of course, it went offline and he had to get assistance fixing it.


Be very, very careful when you execute a chown -R! And you probably shouldn’t be doing that inside a container with any bind mounts…

Monitor owner and permissions changes

A user on the Fedora forum asked for assistance monitoring owner and permissions changes to files. I whipped up a general solution in shell.

It uses a compressed database to store the last run, and will show the changes of the requested attributes of each file.

Here’s some of the business logic.

   # not empty
   test -n "${CO_DEBUG}" && echo "Comparing ${CO_INPUT} to database ${CO_OUTPUT}"

   # learn current status
   scan_dir "${CO_INPUT}" > "${CO_TMPFILE}"

   # compare to database
   zcat "${CO_OUTPUT}" | diff -W300 --suppress-common-lines -y "-" "${CO_TMPFILE}"

   # replace database
   cat "${CO_TMPFILE}" | gzip > "${CO_OUTPUT}"

And the scan function is pretty simple. Just change what stat outputs if you want to monitor different file characteristics.

scan_dir() {
   # call: scan_dir "${CO_INPUT}"
   # output: listing of hash, owner+perm hash for each file
   local td="${1}"

   find "${td}" -exec stat -L -c '%u,%U,%g,%G,%a,%n' {} + 2>/dev/null | sort -t ',' -k6

The script stores its compressed databases in /var/cache/check-owners/, and it will make files named based on the base directory it scans, so /home would be db file /var/cache/check-owners/co.home.db.gz.

You could write a cron entry to call this once a day on a particular directory and email the output to you. A poor man’s AIDE, if you will.

Set word-read permissions on python libs

In an environment where the default umask is 0077 or similar, the pip utility for installing python libraries can set up new files that cannot be read by all users.

I dropped this script into my ~/bin dir so I can enforce other-read permissions easily on all the python libs. I wrote this script after hours and hours of troubleshooting python libs just to find out it’s an old-school permissions issue.

# File: /usr/local/bin/set-readable-python-libs
for word in /usr/{local/,}lib{,64}/python* ;
find ${word} ! -perm -o+rX -exec chmod g+rX,o+rX {} + 2>/dev/null