Tag Archives: PAM

MariaDB with Active Directory authentication via PAM module

I needed to get mariadb authenticating users via Active Directory at work. Configuration was confusing until I stumbled across this article saying you can just tie into the system’s PAM configuration., which in my case is already configured for AD authentication. Awesome!

First, enable PAM plugin and restart mariadb:

/etc/my.cnf, anywhere in the mysqld section

plugin-load=auth_pam.so

Restart mariadb:

sudo systemctl restart mariadb

Next, configure a PAM file to interface with mariadb:

sudo vi /etc/pam.d/mysql
auth include system-auth 
account required pam_nologin.so 
account include system-auth 
password include system-auth 
session optional pam_keyinit.so force revoke 
session include system-auth 
session required pam_loginuid.so

Create catch all user in MariaDB and configure to use your PAM configuration:

CREATE USER ''@'%' IDENTIFIED VIA pam USING 'mysql';

Lastly, grant permissions in mariadb being sure to specify pam as the mechanism:

GRANT ALL PRIVILEGES on <database>.* to '<user>'@'<host>' IDENTIFIED VIA pam;

Profit.


Update 4-23-2019

You can use the pam_user_map module to grant permission to AD groups. This allows using Active Directory groups to completely manage permissions instead of creating users manually in the database. The procedure is outlined here.

Compile & Install pam_user_map module

sudo yum -y install gcc pam-devel  
wget https://raw.githubusercontent.com/MariaDB/server/10.4/plugin/auth_pam/mapper/pam_user_map.c
gcc pam_user_map.c -shared -lpam -fPIC -o pam_user_map.so
sudo install --mode=0755 pam_user_map.so /lib64/security/

Create mysql user and grant it permissions you would like your group to have

CREATE USER '<DBUSER>'@'%' IDENTIFIED BY 'strongpassword';
GRANT ALL PRIVILEGES ON *.* TO '<DBUSER>'@'%' ;

CREATE USER ''@'%' IDENTIFIED VIA pam USING 'mariadb';
GRANT PROXY ON '<DBUSER>'@'%' TO ''@'%';

Configure pam_user_map user/group mappings by creating /etc/security/user_map.conf and add with group mappings. Note pam_user_map doesn’t tolerate special characters, such as the carat sign, which powerbroker uses to indicate spaces. I ended up just renaming the group to not have any spaces in it.

#/etc/security/user_map.conf  
@orig_pam_group_name: mapped_mariadb_user_name

Configure PAM to include pam_user_map.so as the last step in the process. Note the process I uploaded earlier doesn’t work well with groups, so here is my new process (I’m using Powerbroker Open for AD mapping)

auth        required      pam_lsass.so      try_first_pass
auth required pam_user_map.so debug
account required pam_permit.so

Note I’ve also included pam_permit.so so I didn’t need to create AD groups to match what I’ve configured in user_map.conf above.

Linux two factor user exception

Two factor authentication is much more security than simply password authentication. There are times, though, that you will want to create an exception for a specific user. In my case, I wanted to allow a vulnerability scanner to scan my systems. Rather than turn  two factor off for the duration of the scan, I set out to learn how to add an exception for a specific user. I accomplished this on CentOS 6 Linux, but it works an any Linux version using PAM.

The solution to my problem is the pam_listfile PAM module. Pam_listfile allows you to specify a text file that contains a list of either users or groups. You then tell PAM what to do with the file (allow, deny) as well as how to handle what to do if it can’t read the file for some reason.

Thanks to this site I learned the details of what to do. In my case I want a single username to not be prompted for a 2nd authentication factor. All other users must use two factors. I created the file /etc/scan_user and added the username I wanted to have the exception:

echo "scanuser" > /etc/scanuser

Then I modified /etc/pam.d/password-auth and placed it after the first authentication factor, but before the second.

vi /etc/pam.d/password-auth
#First authentication factor
auth        required    pam_unix.so

#pam_listfile to check username and see if it's allowed with only one factor or must provide a second
auth        sufficient  pam_listfile.so onerr=fail item=user sense=allow file=/etc/qualys_user

#Second authentication factor. This is only reached if the user is not on the list provided in pam_listfile.
auth        required   pam_google_authenticator.so

The PAM configuration is as follows:

  • First factor required for everyone (pam_unix)
  • pam_listfile sufficient for anyone who matches the provided list.
  • Second factor required for everyone else (anyone who wasn’t on the pam_listfile list

My vulnerability scanner is now happy and I still have two factor authentication enabled for every other user in the system. Success.

 

Troubleshoot RSA SecurID in CentOS 6

Unexpected error from ACE/Agent API.

In following this guide for configuring a CentOS 6 system to authenticate with RSA SecurID I came across an unusual error message that had me scratching my head:

Unexpected error from ACE/Agent API.

The problem stemmed from having an incorrect value in the /var/ace/sdopts.rec file for CLIENT_IP. For some reason I had put the IP address of the RSA authentication server in there. CLIENT_IP is the IP address of the RSA client, or rather, the machine you’re working on. The client uses whatever’s in that file to report to the RSA server what its IP address is. If the RSA server gets an invalid IP response from the client, it won’t authenticate.

SELinux issues

Much blood and tears were shed in dealing with getting SELinux to exist harmoniously with RSA SecurID. The problem was exacerbated my the fact that there is a lot of half solutions and misinformation floating out there on the internet. This will hopefully help fix that.

The message entry does not exist for Message ID: 1001

At this point acetest worked beautifully but I could not use an RSA passcode to SSH into the system. Digging into the log revealed this error message:

sshd[2135]: ACEAGENT: The message entry does not exist for Message ID: 1001

Thanks to this post, I realized it was due to selinux. Modifying the selinux config information to allow /var/ace to be read, per the commands below, seemed to fix the issue.

setenforce 0
chcon -Rv --type=sshd_t /var/ace/
setenforce 1

But alas! The solution was not a very good one. The commands above have two problems with them: first, the chcon command is temporary and does not survive selinux policy relabels; second, it assigns the type sshd_t, which does allow SSH to access it, but revokes RSA SecurID’s ability to write to the directory. This is a problem if you ever need to clear node secrets. The server will initiate the wipe but the client will not be able to modify that directory, resulting in node secret mismatches.

I finally decided to RTFM and landed on this documentation page, which explained the issue I was having: selinux mislabeling. The proper solution to this problem is use a label that both SecurID and SSHD can write / read to. Thanks to this SELinux Manpage (it really pays to RTFM!) I discovered that the label I want is var_auth_t (the default label applied when creating /var/ace is var_t, which SSH can’t read.) 

To survive relabeling, use the semanage command, which is not installed by default. Thanks to this site I learned I must install policycoreutils-pithon:

yum install policycoreutils-python

Once semanage is installed, use it to change the label for /var/ace and everything inside it to var_auth_t, then apply the changes with restorecon:

semanage fcontext -a -t var_auth_t "/var/ace(/.*)?"
restorecon -R -v /var/ace

Finally, both RSA SecurID and OpenSSH can read what they need to and authentication is successful.

First acetest succeeds but subsequent ones fail

If you followed the bad advice of relabeling /var/ace to sshd_t you might run across a very frustrating issue where acetest would succeed, but any attempts to SSH into the box or even run acetest again would fail. The error message on the RSA SecurID server was

Node secret mismatch: cleared on server but not on agent

The problem is due to the improper SELinux labeling mentioned above. The fix is the same:

yum install policycoreutils-python
semanage fcontext -a -t var_auth_t "/var/ace(/.*)?"
restorecon -R -v /var/ace

SSH access denied even with successful acetest

If acetest succeeds and you’ve loaded the module into PAM but still get access denied, it could be due to your SSH configuration. Ensure the following options are set:

ChallengeResponseAuthentication yes 
UsePrivilegeSeparation no

Victory.