Thursday, September 20, 2012

Keep Unix password in sync with Atlassian Crucible password

I developed a little app stack using Atlassian Crucible and Postfix+Dovecot for mail. I'm not using LDAP or any other SSO solution since that would be an over-kill solution for the few users that will be using my app stack. To keep the users passwords in sync from unix (for mail access) with Crucible, I simply have to have a utility to keep the passwords in sync. (BTW, Usermin would also be over-kill)

Since the users are already used to doing everything via a web GUI, I decided to keep the utility in a web page and use PHP for scripting the solution on the back-end.

There are 3 very simple parts to this solution. Firstly, we have the PHP script function update the user's Confluence login via the SOAP service provided in Confluence as follows:


 function change_confluence_password($user, $password, $new_password) {  
   // login to the Confluence SOAP service  
   $soapClient = new SoapClient("http://your-server.local/rpc/soap-axis/confluenceservice-v2?wsdl");  
   try {  
     $token = $soapClient->__soapCall("login", array('in0'=>$user,'in1'=>$password));  
     if (is_soap_fault($token)) { echo $token->faultstring; exit; }  
   } catch (SoapFault $e) {  
     echo $e->getMessage();  
     return 0;  
   }  
   // change the password:  
   // boolean changeMyPassword(String token, String oldPass, String newPass) - changes the current user's password  
   $params = array('in0'=>$token,'in1'=>$password,'in2'=>$new_password);  
   try {  
     $result = $soapClient->__soapCall("changeMyPassword", $params);  
   } catch (SoapFault $e) {  
     echo $e->getMessage();  
     return 0;  
   }  
   return $result;  
 }  


Next we have a PHP function to request a password change from my "rapchan" script. What is rapchan? rapchan is simply a little mechanism to Request A Password Change (rapchan). The solutions I have seen on the web for making a change to a password via PHP were not 100% satisfactory to me so I created a mechanism whereby a PHP script can request a password change and a cron job run as root can fulfill the request. Having the password change mechanism in the same PHP script as the request seems like a bad idea to me.

So how is the rapchan paradigm different? My solution involves having a script (PHP in this case) drop a special file in a special folder, which represents a request to have a password changed. For security purposes that folder may not be readable to anyone except root otherwise requested password changes would be leaked. Furthermore, rapchan does not allow password change requests for root. No-one one the sudo group can have their password changed via rapchan either, unless so configured (user beware).

How does it work? All the script (which requests a password change) needs to do, is drop a file into a certain folder. The filename must be formatted as [username][secret_file_suffix]. The "username" will be used to determine for what user we are requesting a password change. The contents of the file must contain a string on the first line which is what the new password should be.

Some security considerations: The secret suffix is a small security measure. It requires that the calling script add the required suffix at the end of the file in order for the request to be honored. The more important security consideration is that the folder where the file is dropped into, belongs to the "rapchan" group; the requesting application must be in the "rapchan" group and the folder permissions must be 720. That way only applications executed as users in the rapchan group are allowed to actually request password changes by dropping requests in to that folder. The script which contains the configurations settings and executes the actual password change, must be owned by the root user. The last security measure for a PHP script, would be to use Zend Optimizer for some obfuscation of the PHP script so that the secret suffix is harder to divulge.

How do I set this up?
1) Create a group named rapchan
2) Create a folder owned by root:rapchan and set the permissions to 720
3) Drop the following script code into a folder, which you script via cron to be executed as often as you need:
 #!/bin/bash  
 ############# CONFIGURATION ##############  
 QFOLDER="/etc/rapchan/queue"  
 OKFORSUDO="no"  
 SECRETSUFFIX=".rap"  
 ############## EXECUTION #################  
 # get the permissions on the folder  
 permissions_on_queue_folder="$(stat --format=%a $QFOLDER)"  
 # check the queue for files to process  
 for QFILE in $QFOLDER/*  
 do  
  # make sure the folder has the proper permissions  
  if [ $permissions_on_queue_folder != 720 ];  
  then  
   # log the problem if it does not  
   logger "rapchan error: skipping $QFILE. Queue folder permissions not 720"  
  else  
   # make sure the file has the SECRETSUFFIX  
   if [[ $QFILE == *$SECRETSUFFIX ]]; then  
    # get the username from the filepath  
    USER=${QFILE%$SECRETSUFFIX}  
    USER=${USER#$QFOLDER/}  
    # make sure there is a matching USER for the file, but not the root user  
    if [ -n "$(getent passwd $USER)" ] && [ $USER != "root" ]; then  
     # don't change passwords for sudo users unless allowed in config (above)  
     if [ $OKFORSUDO == "no" ] && [[ "$(id $USER)" == *"(sudo)"* ]]; then  
      logger "rapchan error: skipping $USER. User is in sudo group"  
     else  
      # change the password  
      PASS="$(head -n 1 $QFILE | sed 's/ *$//g' | sed 's/^ *//g')"  
      echo $USER:$PASS | /usr/sbin/chpasswd  
     fi  
    fi  
   fi  
  fi  
  # remove the file from the queue  
  rm -f $QFILE  
 done  

Finally just make sure that what ever user your PHP script will be running under, is in the rapchan group and have your PHP script write the requested password change into the rapchan queue:
 function rapchan($user, $new_password) {  
   file_put_contents("/etc/rapchan/queue/$user.rap", $new_password);  
 }  


There are some other obvious things you need to take care of such as making sure that you dont change the unix password unless the password change call to the Confluence web service was successful, but that level of detail is not covered here.

HTH!

No comments:

Post a Comment