Я пытаюсь управлять пользователями Unix с помощью марионетки. Puppet предоставляет достаточно инструментов для создания учетных записей и предоставления файлов authorized_keys, например, но не для установки пароля пользователя, и он сообщает пользователю.
Я сделал скрипт на Python, который генерирует случайный пароль и отправляет его пользователю по электронной почте. Проблема в том, что невозможно запустить команду passwd Unix с помощью python, я написал сценарий bash с командой:
echo -ne "$password\n$password\n" | passwd $user
passwd -e $user
Запущенный вручную скрипт работает нормально, а пароль созданному пользователю отправляется по электронной почте. Но когда марионетка запускает его, выполняется только сценарий python, как если бы os.system ('/ bin / bash my_bash_script') игнорировалась. Ошибка не отображается. И пользователь получает свой пароль, но команды passwd не запускаются.
Есть ли какие-либо ограничения с марионеткой, мешающие выполнять то, что я описал? Или как иначе я могу изменить учетную запись пользователя, срок ее действия и отправить пароль по электронной почте?
Я могу предоставить дополнительную информацию, но сейчас я не знаю, какая из них точна.
Большое спасибо!
РЕДАКТИРОВАТЬ: вот базовый код с такими же симптомами:
питон: 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
Вот модуль (с этой стороны проблем нет)
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'],
}
Нет необходимости использовать bash-скрипт, просто используйте следующую функцию, которую я использую для других вещей, чтобы сгенерировать зашифрованный теневой пароль:
def shadow(self,password):
SomeZolt="$6$"+''.join(random.choice(string.ascii_uppercase + string.digits) for x in range(9))+"$"
return crypt.crypt(password, SomeZolt)
После этого напишите дополнительные функции в ваш скрипт python, который откроет файл / etc / shadow и запишет зашифрованный пароль, который вы получите с помощью этой функции для этого пользователя, таким образом сделав строку вроде:
some_user:!!:15579:0:99999:7:::
сделать вид:
some_user:$1$JShdquwdjsd38hSJhdqwdkwd:15579:0:99999:7:::
Таким образом some_user будет иметь назначенный пароль.
Кроме того, вы можете установить пользователя прямо в операторе марионетки, изменив его на:
user { $username:
comment => "$email",
home => "/home/$username",
shell => "/bin/bash",
uid => $uid,
gid => $gid,
password => "SomeAlreadyEncryptedPassword",
}
Вы можете использовать указанную функцию, чтобы получить зашифрованный пароль, а затем вставить его в оператор.
Спасибо за ваш ответ, я последовал вашему совету и закодировал def для генерации хэша пароля и поместил его в файл / etc / shadow.
Вот сценарий, который я написал, если кому-то может быть интересно:
class Unix_Account:
def __init__(self, user):
self.user = user
self.password = ''.join(
random.choice(
string.ascii_uppercase + string.ascii_lowercase + string.digits
) for x in range(password_length)
)
self.salt = '$6$'+''.join(
random.choice(string.ascii_uppercase + string.digits
) for x in range(9))+'$'
self.line = self.user+':'+crypt.crypt(self.password, self.salt)+':0:0:99999:7:::'
def change_password(self):
self.result = re.sub(self.user+".*", self.line, file('/etc/shadow', 'r').read())
file('/etc/shadow', 'w').write(self.result)
Затем другой класс отправляет пароль пользователю.
Дата истечения срока действия пароля установлена на 0, поэтому пользователь вынужден изменить его при первом подключении.
Подключение осуществляется по SSH, для установки пароля необходимо использовать соответствующий ключ. Пароль используется для команды sudo.
Еще раз спасибо!