def ScpCreate( service_binding_info, service_class_name, # Service class string to store in SCP. account_name=None, # Logon account that needs access to SCP. container_name=None, keywords=None, object_class="serviceConnectionPoint", dns_name_type="A", dn=None, dns_name=None, ): container_name = container_name or service_class_name if not dns_name: # Get the DNS name of the local computer dns_name = win32api.GetComputerNameEx( win32con.ComputerNameDnsFullyQualified) # Get the distinguished name of the computer object for the local computer if dn is None: dn = win32api.GetComputerObjectName(win32con.NameFullyQualifiedDN) # Compose the ADSpath and bind to the computer object for the local computer comp = adsi.ADsGetObject("LDAP://" + dn, adsi.IID_IDirectoryObject) # Publish the SCP as a child of the computer object keywords = keywords or [] # Fill in the attribute values to be stored in the SCP. attrs = [ ("cn", ADS_ATTR_UPDATE, ADSTYPE_CASE_IGNORE_STRING, (container_name, )), ("objectClass", ADS_ATTR_UPDATE, ADSTYPE_CASE_IGNORE_STRING, (object_class, )), ("keywords", ADS_ATTR_UPDATE, ADSTYPE_CASE_IGNORE_STRING, keywords), ("serviceDnsName", ADS_ATTR_UPDATE, ADSTYPE_CASE_IGNORE_STRING, (dns_name, )), ( "serviceDnsNameType", ADS_ATTR_UPDATE, ADSTYPE_CASE_IGNORE_STRING, (dns_name_type, ), ), ( "serviceClassName", ADS_ATTR_UPDATE, ADSTYPE_CASE_IGNORE_STRING, (service_class_name, ), ), ( "serviceBindingInformation", ADS_ATTR_UPDATE, ADSTYPE_CASE_IGNORE_STRING, (service_binding_info, ), ), ] new = comp.CreateDSObject("cn=" + container_name, attrs) logger.info("New connection point is at %s", container_name) # Wrap in a usable IDispatch object. new = Dispatch(new) # And allow access to the SCP for the specified account name AllowAccessToScpProperties(account_name, new) return new
def _node_info_windows(_tm_env, runtime): """Generate a node information report for the scheduler. :param _tm_env: Treadmill application environment :type _tm_env: `appenv.AppEnvironment` :param runtime: Treadmill runtime in use :type runtime: `str` """ if runtime != 'docker': # Raising an exception will ensure windows is started with docker # runtime enabled raise NotImplementedError( 'Runtime {0} is not supported on Windows'.format(runtime)) info = _get_docker_node_info({ 'up_since': up_since(), }) dc_name = win32security.DsGetDcName() info.update({ 'nt.dc': dc_name['DomainControllerName'].replace('\\\\', '').lower(), 'nt.domain': dc_name['DomainName'].lower(), 'nt.dn': win32api.GetComputerObjectName(win32con.NameFullyQualifiedDN) }) return info
def ScpDelete(container_name, dn = None): if dn is None: dn = win32api.GetComputerObjectName(win32con.NameFullyQualifiedDN) logger.debug("Removing connection point '%s' from %s", container_name, dn) # Compose the ADSpath and bind to the computer object for the local computer comp = adsi.ADsGetObject("LDAP://" + dn, adsi.IID_IDirectoryObject) comp.DeleteDSObject("cn=" + container_name) logger.info("Deleted service connection point '%s'", container_name)
def __init__(self, tm_env): data = nodedata.get(tm_env.configs_dir) self._config = GMSAConfig(data['nt_group_ou'], data['nt_group_pattern']) dc_name = win32security.DsGetDcName() self._dc = dc_name['DomainControllerName'].replace('\\\\', '').lower() self._dn = win32api.GetComputerObjectName( win32con.NameFullyQualifiedDN).lower()
def AllowAccessToScpProperties( accountSAM, # Service account to allow access. scpObject, # The IADs SCP object. schemaIDGUIDs= # Attributes to allow write-access to. ( "{28630eb8-41d5-11d1-a9c1-0000f80367c1}", # serviceDNSName # serviceBindingInformation "{b7b1311c-b82e-11d0-afee-0000f80367c1}", )): # If no service account is specified, service runs under LocalSystem. # So allow access to the computer account of the service's host. if accountSAM: trustee = accountSAM else: # Get the SAM account name of the computer object for the server. trustee = win32api.GetComputerObjectName(win32con.NameSamCompatible) # Get the nTSecurityDescriptor attribute attribute = "nTSecurityDescriptor" sd = getattr(scpObject, attribute) acl = sd.DiscretionaryAcl for sguid in schemaIDGUIDs: ace = Dispatch(adsi.CLSID_AccessControlEntry) # Set the properties of the ACE. # Allow read and write access to the property. ace.AccessMask = ADS_RIGHT_DS_READ_PROP | ADS_RIGHT_DS_WRITE_PROP # Set the trustee, which is either the service account or the # host computer account. ace.Trustee = trustee # Set the ACE type. ace.AceType = ADS_ACETYPE_ACCESS_ALLOWED_OBJECT # Set AceFlags to zero because ACE is not inheritable. ace.AceFlags = 0 # Set Flags to indicate an ACE that protects a specified object. ace.Flags = ADS_FLAG_OBJECT_TYPE_PRESENT # Set ObjectType to the schemaIDGUID of the attribute. ace.ObjectType = sguid # Add the ACEs to the DACL. acl.AddAce(ace) # Write the modified DACL back to the security descriptor. sd.DiscretionaryAcl = acl # Write the ntSecurityDescriptor property to the property cache. setattr(scpObject, attribute, sd) # SetInfo updates the SCP object in the directory. scpObject.SetInfo() logger.info("Set security on object for account '%s'" % (trustee, ))
def __init__(self, tm_env): with io.open(os.path.join(tm_env.configs_dir, 'node.json')) as f: data = json.load(f) self._config = GMSAConfig(data['nt_group_ou'], data['nt_group_pattern']) dc_name = win32security.DsGetDcName() self._dc = dc_name['DomainControllerName'].replace('\\\\', '').lower() self._dn = win32api.GetComputerObjectName( win32con.NameFullyQualifiedDN).lower()
def SpnRegister( serviceAcctDN, # DN of the service's logon account spns, # List of SPNs to register operation, # Add, replace, or delete SPNs ): assert type(spns) not in [str, str] and hasattr(spns, "__iter__"), ( "spns must be a sequence of strings (got %r)" % spns) # Bind to a domain controller. # Get the domain for the current user. samName = win32api.GetUserNameEx(win32api.NameSamCompatible) samName = samName.split("\\", 1)[0] if not serviceAcctDN: # Get the SAM account name of the computer object for the server. serviceAcctDN = win32api.GetComputerObjectName( win32con.NameFullyQualifiedDN) logger.debug("SpnRegister using DN '%s'", serviceAcctDN) # Get the name of a domain controller in that domain. info = win32security.DsGetDcName( domainName=samName, flags=dscon.DS_IS_FLAT_NAME | dscon.DS_RETURN_DNS_NAME | dscon.DS_DIRECTORY_SERVICE_REQUIRED, ) # Bind to the domain controller. handle = win32security.DsBind(info["DomainControllerName"]) # Write the SPNs to the service account or computer account. logger.debug("DsWriteAccountSpn with spns %s") win32security.DsWriteAccountSpn( handle, # handle to the directory operation, # Add or remove SPN from account's existing SPNs serviceAcctDN, # DN of service account or computer account spns, ) # names # Unbind the DS in any case (but Python would do it anyway) handle.Close()