Linux – puppet execution of a python script where os.system(…) command is not working

linuxpuppetpythonuser-management

I am trying to manage Unix users with puppet. Puppet provides enough tools to create accounts and provide authorized_keys files for instance, but no to set up user password, and it tell to the user.

What I have done is a python script which generate a random password and send it to the user by email. The problem is, it is not possible to launch passwd Unix command with python, I have then written a bash script with the command:

echo -ne "$password\n$password\n" | passwd $user
passwd -e $user

Launched manually, the script works fine and the created user has its password sent by email. But when puppet launches it, only the python script gets executed, as if the os.system('/bin/bash my_bash_script') is ignored. No error is displayed. And the user gets its password, but the passwd commands are not launched.

Is there any limitation with puppet preventing to perform what I described? Or, how can I otherwise change the user account, its expiration, and send password by email?

I can provide more information, but right now, I don't know which are accurate.

Many thanks!

EDIT: Here is a basic code with same symptoms:

python: setuserpassword.py

#!/usr/bin/python
import os
import sys

user = sys.argv[1]
mail = sys.argv[2]
os.system('/bin/bash /root/tools/setuserpassword.sh '+user+' '+mail)

bash: setuserpassword.sh

#!/bin/bash
# Password setup for the account
password=`pwgen -N1 --secure 10`
echo -ne "$password\n$password\n" | passwd $USER > /dev/null 2>&1
[[ $? -ne 0 ]] && exit 2

# Setup the expirancy label to make sure user
# change its password upon fist success login
chage -d0 $USER

# Email sending to inform user of his new password
echo -ne "Hello, $USER;\n
The password is:\n
$password\n" | mail -s "$USER account created" $MAIL

Here is the module (no problem on this side)

define add_user ( $email, $uid, $gid ) { 

$username = $title

user { $username:
  comment => "$email",
  home    => "/home/$username",
  shell   => "/bin/bash",
  uid     => $uid,
  gid     => $gid,
}   

exec { "/root/tools/setuserpassword.py $username $email":
   path           => "/bin:/usr/bin:/usr/sbin/sbin",
   refreshonly    => true,
   subscribe      => user[$username],
   onlyif         => "cat /etc/shadow | grep $username | grep '!'",
   require        => Package['pwgen'],
}   

Best Answer

No need to use a bash script, just use the next function I'm using for some other stuff to generate the shadow encrypted password:

 def shadow(self,password):
  SomeZolt="$6$"+''.join(random.choice(string.ascii_uppercase + string.digits) for x in range(9))+"$"
  return crypt.crypt(password, SomeZolt)

After which write additional functionality to your python script which will open the /etc/shadow file and write the encrypted password you get by using this function for this user thus making a line like:

some_user:!!:15579:0:99999:7:::

make look like:

some_user:$1$JShdquwdjsd38hSJhdqwdkwd:15579:0:99999:7:::

Thus some_user will have the assigned password.
Additionaly you can set the user directly in the puppet statement by changing it to:

user { $username:
  comment => "$email",
  home    => "/home/$username",
  shell   => "/bin/bash",
  uid     => $uid,
  gid     => $gid,
  password => "SomeAlreadyEncryptedPassword",
}   

You can use by the way the function specified to get the encrypted password and then insert it to the statement.