Я нахожусь в среде, где информация о пользователях / группах хранится в файлах / etc / passwd и / etc / group, которые смонтированы по NFS. Это хорошо, потому что мы можем просто редактировать плоские файлы, чтобы изменить информацию о пользователе / группе. Однако машинам OS X в нашей установке это не очень нравится, потому что службы каталогов не реагируют на изменение этих файлов.
Поэтому я планирую настроить задание cron для запуска чего-то вроде этого один раз в день или около того:
dsimport -g /etc/group /Local/Default O -T xDSStandardGroup -u $ADMIN_USER -p $ADMIN_PASS
Проблема в этих двух последних аргументах в конце: пользователь и пароль. Я хочу избегать записи паролей в скриптах, чтобы снизить риск их взлома. Есть ли способ использовать dscl или dsimport без необходимости указывать пароль, а вместо этого просто использовать привилегии пользователя, выполняющего команду? (Вы знаете, как это делает каждая стандартная команда Unix.) Или есть какой-то другой способ сделать это без написания паролей в открытом виде?
Просто просматриваю свои заметки о dscl, которые я написал довольно подробно. Я почти уверен, что ответ отрицательный, нет способа избежать ввода пароля. Единственное исключение может быть, если вы были root в локальном ящике (что в вашем примере действительно так). [Я почти всегда вносил изменения по сети.]
Если вы используете ожидать или ожидание, вы можете закодировать пароль в сценарии (обратимым образом), а затем вызвать нужную программу. [Я придумал способ кодирования / декодирования чего-то, что выглядит как чепуха, но, боюсь, это безопасность через неясность.]
Для использования pexpect что-то в этом роде будет работать [обратите внимание, что в этом примере используется dscl, а не dsimport! (Я полагаю, что это можно было бы немного упростить для ваших целей; включение команды ведения журнала для дочернего элемента dscl помогает при настройке)]:
#!/usr/bin/env python
import pexpect
# If you don't have pexpect, you should be able to run
# 'sudo easy_install pexpect' to get it
### Fill in these variables
diradmin = "diradmin"
host = "host"
directory = '/Local/Default' # '/LDAPv3/127.0.0.1'
# Note: it is possible to encode the data here so it is not in plain text!
password = "password"
DSCL_PROMPT = " > " # Don't change this (unless the dscl tool changes)
def ReplyOnGoodResult(child, desired, reply):
"""Helps analyze the results as we try to set passwords.
child = a pexpect child process
desired = The value we hope to see
reply = text to send if we get the desired result (or None for no reply)
If we do get the desired result, we send the reply and return true.
If not, we return false."""
expectations = [ pexpect.EOF, pexpect.TIMEOUT, '(?i)error', desired ]
desired_index = len(expectations) - 1
index = child.expect(expectations)
if index == desired_index:
if reply:
child.sendline(reply)
return True
else:
return False
def RunDSCLCommand(dscl_child, command):
"""Issues one dscl command; returns if it succeeded or failed.
command = the command to be sent to dscl, such as 'passwd Users/foo newpword'
"""
assert dscl_child is not None, "No connection successfully established"
# We should be logged in with a prompt awaiting us
expected_list = [ pexpect.EOF, pexpect.TIMEOUT,
'(?i)error', 'Invalid Path', DSCL_PROMPT ]
desired_index = len(expected_list) - 1
invalid_path_index = desired_index - 1
dscl_child.sendline(command)
reply_index = dscl_child.expect(expected_list)
if reply_index == desired_index:
return True
# Find the next prompt so that on the next call to a command like this
# one, we will know we are at a consistent starting place
# Looking at the self.dscl_child.before will likely contain
# the error that occured, but for now:
dscl_child.expect(DSCL_PROMPT)
if invalid_path_is_success and reply_index == invalid_path_index:
# The item doesn't exist, but we will still count it
# as a success. (Most likely we were told to delete the item).
return True
# one of the error conditions was triggered
return False
# Here is the part of the program where we start doing things
prompt = DSCL_PROMPT
dscl_child = pexpect.spawn("dscl -u %s -p %s" % (diradmin, host))
#dscl_child.logfile = file("dscl_child.log", "w") # log what is going on
success = False
if (ReplyOnGoodResult(self.dscl_child, "Password:", password) and
ReplyOnGoodResult(self.dscl_child, prompt, "cd %s" % directory) and
ReplyOnGoodResult(self.dscl_child, prompt, "auth %s %s" % (diradmin, password)) and
ReplyOnGoodResult(self.dscl_child, prompt, None)):
success = True
if success:
# Now issue a command
success = RunDSCLCommand(dscl_child, 'passwd Users/foo newpword')
dscl_child.close()
Я опубликовал часть кода, который использую Вот; Я боюсь, что он совершенно не поддерживается (и опубликован в группе pymacadmin об этом Вот. К сожалению, похоже, что я ничего не писал о том, как его использовать :(