我正在尝试通过 Python 中的 Ldap3 库创建一个服务帐户。服务帐户创建成功,但是有一个小问题。未选中“用户无法更改密码”复选框。
我做了一些研究,发现要设置此属性,我需要遵循此处给出的一些步骤:https://learn.microsoft.com/en-us/windows/win32/adsi/modifying-user-cannot-change - 密码 ldap-provider 。此链接中给出的逻辑采用与 Python 不同的编程语言,因此我尝试在 Python 中复制相同的逻辑。据我们了解,我已经实现了该功能,并且执行成功,但在 AD 服务器上没有看到预期的效果(“用户无法更改密码”复选框仍未选中)。
下面是用于创建 ACL 对象并将其添加到服务帐户的代码。
def create_object_ace(privguid, sid):
print("creating ace object")
nace = ldaptypes.ACE()
nace['AceType'] = ldaptypes.ACCESS_DENIED_OBJECT_ACE.ACE_TYPE
nace['AceFlags'] = 0x00
acedata = ldaptypes.ACCESS_DENIED_OBJECT_ACE()
acedata['Mask'] = ldaptypes.ACCESS_MASK()
acedata['Mask']['Mask'] = ldaptypes.ACCESS_ALLOWED_OBJECT_ACE.ADS_RIGHT_DS_CONTROL_ACCESS
acedata['ObjectType'] = string_to_bin(privguid)
acedata['InheritedObjectType'] = b''
acedata['Sid'] = ldaptypes.LDAP_SID()
acedata['Sid'].fromCanonical(sid)
assert sid == acedata['Sid'].formatCanonical()
acedata['Flags'] = ldaptypes.ACCESS_DENIED_OBJECT_ACE.ACE_OBJECT_TYPE_PRESENT
nace['Ace'] = acedata
return nace
s = Server('ad_server.com', get_info=ALL)
c = Connection(s, user="testdomain\\username", password="password", authentication=NTLM)
c.search(search_base="DC=testad,DC=com", search_filter="(CN=svc_account_47)",
search_scope=SUBTREE, attributes=['objectSid', 'sAMAccountName'])
entry = c.entries[0]
usersid = entry['objectSid'].value
controls = security_descriptor_control(sdflags=0x04)
c.search(search_base="DC=testahs,DC=com", search_filter='(&(objectCategory=domain))',
attributes=['SAMAccountName', 'nTSecurityDescriptor'], controls=controls)
entry = c.entries[0]
secDescData =. entry['nTSecurityDescriptor'].raw_values[0]
secDesc = ldaptypes.SR_SECURITY_DESCRIPTOR(data=secDescData)
secDesc['Dacl']['Data'].append(create_object_ace('ab721a53-1e2f-11d0-9819-00aa0040529b', usersid)) # This GUID is for 'User cannot change password'
dn = entry.entry_dn
data = secDesc.getData()
c.modify(dn, {'nTSecurityDescriptor': (ldap3.MODIFY_REPLACE, [data])}, controls=controls)
print(c.result)
# gives -> {'result': 0, 'description': 'success', 'dn': '', 'message': '', 'referrals': None, 'type': 'modifyResponse'}
Python代码参考来自以下链接:
有人可以帮助我吗?预先感谢。
我在 Python 中做到这一点的唯一方法是:
import uuid
import bonsai
from bonsai import LDAPClient
from bonsai.active_directory import SecurityDescriptor
def set_not_change_pass(self, userdn):
client = LDAPClient(f"ldap://{self._server}")
client.set_credentials("SIMPLE", user=f"CN={self._srvaccname},CN=Users,{self._dc}",
password=self._srvaccpass)
with client.connect() as conn:
entry = conn.search(
userdn, 0, attrlist=["ntSecurityDescriptor", "userAccountControl"]
)[0]
uac = bonsai.active_directory.UserAccountControl(entry["userAccountControl"][0])
sec_desc = bonsai.active_directory.SecurityDescriptor.from_binary(
entry["ntSecurityDescriptor"][0]
)
new_dacl_aces = []
for ace in sec_desc.dacl.aces:
if ace.object_type == uuid.UUID("ab721a53-1e2f-11d0-9819-00aa0040529b"):
# Find change password ACE and change it to deny.
new_ace = bonsai.active_directory.ACE(
bonsai.active_directory.ACEType.ACCESS_DENIED_OBJECT,
ace.flags,
ace.mask,
ace.trustee_sid,
ace.object_type,
ace.inherited_object_type,
ace.application_data,
)
# Insert new deny ACEs to the front of the list.
new_dacl_aces.insert(0, new_ace)
else:
new_dacl_aces.append(ace)
new_dacl = bonsai.active_directory.ACL(sec_desc.dacl.revision, new_dacl_aces)
new_sec_desc = bonsai.active_directory.SecurityDescriptor(
sec_desc.control,
sec_desc.owner_sid,
sec_desc.group_sid,
sec_desc.sacl,
new_dacl,
sec_desc.revision,
sec_desc.sbz1,
)
entry.change_attribute(
"ntSecurityDescriptor", bonsai.LDAPModOp.REPLACE, new_sec_desc.to_binary()
)
uac.properties["accountdisable"] = False
entry.change_attribute("userAccountControl", bonsai.LDAPModOp.REPLACE, uac.value)
entry.modify()