我处于一个环境中,用户/组信息保存在NFS挂载的/ etc / passwd和/ etc / group文件中。 这很好,因为我们可以编辑平面文件来更改用户/组信息。 但是,我们的设置中的OS X机器不太喜欢这一点,因为目录服务在这些文件发生更改时不会启动。
因此,我打算设置一个cron工作来每天运行一次这样的事情:
dsimport -g /etc/group /Local/Default O -T xDSStandardGroup -u $ADMIN_USER -p $ADMIN_PASS
问题是最后两个参数:用户名和密码。 我想避免在脚本中写出密码,以减less被泄露的风险。 有没有使用dscl或dsimport的方法,而不必提供密码,而是让他们只使用运行命令的用户的权限? (你知道,每一个标准的Unix命令的做法。)还是有没有其他的方式来完成这个没有用明文写出密码?
只需浏览我在dscl上的笔记,我已经相当广泛地编写了脚本。 我相当肯定答案是否定的,没有办法避免提供密码。 唯一的例外可能是,如果你是在本地的根(在你的例子中,确实如此)的根。 [我几乎完全通过networking做了改变。]
如果您使用expect或pexpect ,则可以将密码编码到脚本中(以可逆方式),然后调用您需要的程序。 [我已经想出了一种方法来编码/解码看起来像gobbledygook的东西,但恐惧的是通过默默无闻的安全。]
对于使用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小组,不幸的是,它看起来不像我写了什么关于如何使用它:(