def _create_user(self, username, password, name, surname): # FIXME ms windows stores strings as UTF-8 while mmc base module waits for ascii # them so we decode # username = username.decode('utf-8)') # name = name.decode('utf-8)').encode('ascii', errors='replace') # surname = surname.decode('utf-8)').encode('ascii', errors='replace') logger.debug('calling ldapUserGroupControl().addUser(%s, %s, %s, %s)', username, password, name, surname) ldapUserGroupControl().addUser(username, password, name, surname)
def getACLOnShare(self, name): """ Return a list with all the groups that have rwx access to the share. @param name: name of the share (last component of the path) @type name: str @rtype: tuple @return: tuple of groups, users that have rwx access to the share. """ path = self.getContent(name, "path") ret = ([], []) ldapobj = ldapUserGroupControl() acl1 = posix1e.ACL(file=path) for e in acl1: if e.permset.write: if e.tag_type == posix1e.ACL_GROUP: res = ldapobj.getDetailedGroupById(str(e.qualifier)) if res: ret[0].append(res['cn'][0]) else: ret[0].append(grp.getgrgid(e.qualifier).gr_name) if e.tag_type == posix1e.ACL_USER: res = ldapobj.getDetailedUserById(str(e.qualifier)) if res: ret[1].append(res['uid'][0]) else: ret[1].append(pwd.getpwuid(e.qualifier).pw_name) return ret
def _cbProvisioning(self, auth, authtoken): """ Provision the MMC user account with ACLs """ if not auth: self.logger.warning("User authentication with GLPI web interface failed, but going on with provisioning") profiles = Glpi().getUserProfiles(authtoken.getLogin()) self.logger.debug("User %s GLPI profiles: %s" % (authtoken.getLogin(), str(profiles))) selected = None for profile in self.config.profilesOrder: if profile in profiles: selected = profile break if not selected: self.logger.info("User GLPI profile can't be applied") else: self.logger.debug("Selected GLPI profile is %s" % selected) try: acls = self.config.profilesAcl[selected.lower()] except KeyError: acls = None if not acls: self.logger.info("No ACL to apply for the GLPI profile %s" % selected) else: l = ldapUserGroupControl() self.logger.info("Setting MMC ACL corresponding to GLPI profile %s: %s" % (selected, acls)) uid = authtoken.getLogin() entry = l.getDetailedUser(uid) if not "lmcUserObject" in entry["objectClass"]: entry["objectClass"].append("lmcUserObject") l.changeUserAttributes(uid, "objectClass", entry["objectClass"]) l.changeUserAttributes(authtoken.getLogin(), "lmcAcl", acls) return authtoken
def setUp(self): cleanLdap() self.l = ldapUserGroupControl("tests-mds/basetest.ini") self.l.addGroup("grouptestA") self.l.addGroup("grouptestB") os.system("cp contrib/samba/smb.conf /etc/samba/smb.conf") self.s = smbConf(conffile = "tests-mds/sambatest.ini", conffilebase = "tests-mds/basetest.ini") os.system("rm -fr %s" % self.s.defaultSharesPath)
def setUp(self): cleanLdap() self.l = ldapUserGroupControl("tests-mds/basetest.ini") self.l.addGroup("grouptestA") self.l.addGroup("grouptestB") os.system("cp contrib/samba/smb.conf /etc/samba/smb.conf") self.s = smbConf(conffile="tests-mds/sambatest.ini", conffilebase="tests-mds/basetest.ini") os.system("rm -fr %s" % self.s.defaultSharesPath)
def activate(): ldapObj = ldapUserGroupControl() logger = logging.getLogger() config = MailConfig("mail") if config.disabled: logger.warning("Plugin mail: disabled by configuration.") return False mailSchema = { "mailAccount": [ "mail", "mailalias", "maildrop", "mailenable", "mailbox", "mailuserquota", "mailhost", "mailproxy", "mailhidden" ], "mailGroup": ["mail"], "mailDomain": ["virtualdomain", "virtualdomaindescription", "mailuserquota"], } # Additional LDAP classes/attributes to check for ZARAFA support if config.zarafa: mailSchema['zarafa-user'] = [ 'zarafaAdmin', 'zarafaSharedStoreOnly', 'zarafaAccount', 'zarafaSendAsPrivilege', 'zarafaHidden' ] mailSchema['zarafa-group'] = [] # Additional LDAP classes for virtual aliases if config.vAliasesSupport: mailSchema['mailAlias'] = ['mailaliasmember'] for objectClass in mailSchema: schema = ldapObj.getSchema(objectClass) if not len(schema): logger.error( "LDAP mail schema is not up to date: %s objectClass is not included in LDAP directory" % objectClass) return False for attribute in mailSchema[objectClass]: if attribute not in schema: logger.error( "LDAP mail schema is not up to date: %s attribute is not included in LDAP directory" % attribute) return False if config.vAliasesSupport: # Create required OU head, path = config.vAliasesDN.split(",", 1) ouName = head.split("=")[1] ldapObj.addOu(ouName, path) if config.vDomainSupport: # Create required OU head, path = config.vDomainDN.split(",", 1) ouName = head.split("=")[1] ldapObj.addOu(ouName, path) return True
def setUp(self): cleanLdap() self.l = ldapUserGroupControl("tests-mds/basetest.ini") self.l.addGroup("allusers") os.system("cp contrib/samba/smb.conf /etc/samba/smb.conf") os.system("/etc/init.d/samba stop") os.system("/usr/bin/smbpasswd -w secret") os.system("/etc/init.d/samba start") self.s = sambaLdapControl(conffile = "tests-mds/sambatest.ini", conffilebase = "tests-mds/basetest.ini")
def setUp(self): cleanLdap() self.l = ldapUserGroupControl("tests-mds/basetest.ini") self.l.addGroup("allusers") os.system("cp contrib/samba/smb.conf /etc/samba/smb.conf") os.system("/etc/init.d/samba stop") os.system("/usr/bin/smbpasswd -w secret") os.system("/etc/init.d/samba start") self.s = sambaLdapControl(conffile="tests-mds/sambatest.ini", conffilebase="tests-mds/basetest.ini")
def doProvisioning(self, authtoken): from mmc.plugins.base import ldapUserGroupControl self.logger.debug(str(authtoken.getInfos())) l = ldapUserGroupControl() userentry = authtoken.getInfos()[1] uid = userentry[self.config.ldap_uid][0] if l.existUser(uid): self.logger.debug("User %s already exists, so this user won't be added" % uid) else: givenName = userentry[self.config.ldap_givenName][0].decode("utf-8") sn = userentry[self.config.ldap_sn][0].decode("utf-8") l.addUser(uid, authtoken.getPassword(), givenName, sn) if self.config.profileAttr and self.config.profilesAcl: # Set or update the user right try: profile = userentry[self.config.profileAttr][0].lower() except KeyError: self.logger.info("No profile information for user %s in attribute %s" % (uid, self.config.profileAttr)) profile = "" profile = profile.strip() try: acls = self.config.profilesAcl[profile] except KeyError: self.logger.info("No ACL defined in configuration file for profile '%s'" % profile) self.logger.info("Setting ACL to empty") acls = None if profile and acls: self.logger.info("Setting MMC ACL corresponding to user profile %s: %s" % (profile, str(acls))) entry = l.getDetailedUser(uid) if not "lmcUserObject" in entry["objectClass"]: entry["objectClass"].append("lmcUserObject") l.changeUserAttributes(uid, "objectClass", entry["objectClass"]) l.changeUserAttributes(uid, "lmcAcl", acls) if self.config.profileGroupMapping: # Set user group membership according to mapping for prof in self.config.profilesAcl: groupname = self.config.profileGroupPrefix + prof if prof != profile: # Delete the user from a group not belonging to her/his # profile try: l.delUserFromGroup(groupname, uid) self.logger.debug('Deleting user %s from group %s' % (uid, groupname)) except ldap.NO_SUCH_OBJECT: # The group does not exist pass else: # Add the user to this group try: l.addGroup(groupname) except ldap.ALREADY_EXISTS: # This group already exists pass self.logger.debug('Adding user %s to group %s' % (uid, groupname)) l.addUserToGroup(groupname, uid)
def activate(): ldapObj = ldapUserGroupControl() logger = logging.getLogger() config = MailConfig("mail") if config.disabled: logger.warning("Plugin mail: disabled by configuration.") return False mailSchema = { "mailAccount" : ["mail", "mailalias", "maildrop", "mailenable", "mailbox", "mailuserquota", "mailhost", "mailproxy"], "mailGroup" : ["mail"], "mailDomain" : ["virtualdomain", "virtualdomaindescription", "mailuserquota"], } # Additional LDAP classes/attributes to check for ZARAFA support if config.zarafa: mailSchema['zarafa-user'] = ['zarafaAdmin', 'zarafaSharedStoreOnly', 'zarafaAccount', 'zarafaSendAsPrivilege', 'zarafaHidden'] mailSchema['zarafa-group'] = [] # Additional LDAP classes for virtual aliases if config.vAliasesSupport: mailSchema['mailAlias'] = ['mailaliasmember'] for objectClass in mailSchema: schema = ldapObj.getSchema(objectClass) if not len(schema): logger.error("LDAP mail schema is not up to date: %s objectClass is not included in LDAP directory" % objectClass) return False for attribute in mailSchema[objectClass]: if not attribute in schema: logger.error("LDAP mail schema is not up to date: %s attribute is not included in LDAP directory" % attribute) return False if config.vAliasesSupport: # Create required OU head, path = config.vAliasesDN.split(",", 1) ouName = head.split("=")[1] ldapObj.addOu(ouName, path) if config.vDomainSupport: # Create required OU head, path = config.vDomainDN.split(",", 1) ouName = head.split("=")[1] ldapObj.addOu(ouName, path) return True
def activate(): ldapObj = ldapUserGroupControl() logger = logging.getLogger() config = UserSshKeyConfig("sshlpk") if config.disabled: logger.warning("Plugin sshlpk: disabled by configuration.") return False sshkeySchema = ['posixAccount', 'ldapPublicKey'] for objectClass in sshkeySchema: schema = ldapObj.getSchema(objectClass) if not len(schema): logger.error("OpenSSH LDAP public key schema is not available: %s objectClass is not included in LDAP directory" % objectClass) return False return True
def activate(): ldapObj = ldapUserGroupControl() logger = logging.getLogger() config = UserSshKeyConfig("sshlpk") if config.disabled: logger.warning("Plugin sshlpk: disabled by configuration.") return False sshkeySchema = ['posixAccount', 'ldapPublicKey'] for objectClass in sshkeySchema: schema = ldapObj.getSchema(objectClass) if not len(schema): logger.error("OpenSSH LDAP public key schema is not available: %s objectClass is not included in LDAP directory" % objectClass); return False return True
def getACLOnShare(self, name): """ Return a list with all the groups that have rwx access to the share. @param name: name of the share (last component of the path) @type name: str @rtype: dict @return: dict of permissions: [list of users/groups] """ ldapobj = ldapUserGroupControl(self.conffilebase) path = self.getContent(name, "path") public = self.getContent(name, "public") perms = {'rx': [], 'rwx': []} if path is False: return perms if public == "yes": return {'rwx': ['@all']} acls = posix1e.ACL(file=path) for e in acls: permset = zip(['r', 'w', 'x'], [e.permset.read, e.permset.write, e.permset.execute]) perm = ''.join([r for r, b in permset if b is True]) entity = "" if e.tag_type == posix1e.ACL_GROUP: res = ldapobj.getDetailedGroupById(str(e.qualifier)) if res: entity = '@' + res['cn'][0] else: entity = '@' + grp.getgrgid(e.qualifier).gr_name if e.tag_type == posix1e.ACL_USER: res = ldapobj.getDetailedUserById(str(e.qualifier)) if res: entity = res['uid'][0] else: entity = pwd.getpwuid(e.qualifier).pw_name if perm not in perms and entity: perms[perm] = [entity] elif entity: perms[perm].append(entity) return perms
def activate(): ldapObj = ldapUserGroupControl() logger = logging.getLogger() config = RadiusConfig("radius") if config.disabled: logger.warning("Plugin radius: disabled by configuration.") return False radiusSchema = ['posixAccount', 'radiusprofile'] for objectClass in radiusSchema: schema = ldapObj.getSchema(objectClass) if not len(schema): logger.error("Radius schema is not available: %s objectClass is \ not included in LDAP directory" % objectClass) return False return True
def cleanLdap(): # Wipe out /home os.system("rm -fr /home/*") # Wipe out LDAP os.system("/etc/init.d/slapd stop") os.system("killall -9 slapd") os.system("rm -f /var/lib/ldap/*") os.system("rm -fr /var/backups/*.ldapdb") os.system("cp contrib/ldap/*.schema /etc/ldap/schema") os.system("echo slapd slapd/password1 string secret | debconf-set-selections") os.system("echo slapd slapd/password2 string secret | debconf-set-selections") os.system("dpkg-reconfigure -pcritical slapd") os.system("cp contrib/ldap/slapd.conf /etc/ldap") os.system("/etc/init.d/slapd restart") time.sleep(5) # Create Base OU l = ldapUserGroupControl("tests-mds/basetest.ini") l.addOu("Groups", "dc=mandriva,dc=com") l.addOu("Users", "dc=mandriva,dc=com")
def _cbProvisioning(self, auth, authtoken): """ Provision the MMC user account with ACLs """ if not auth: self.logger.warning( "User authentication with GLPI web interface failed, but going on with provisioning" ) profiles = Glpi().getUserProfiles(authtoken.getLogin()) self.logger.debug("User '%s' GLPI's profiles: %s" % (authtoken.getLogin(), str(profiles))) self.logger.debug("Profiles order (from ini configuration): %s" % (self.config.profilesOrder)) selected = None for profile in self.config.profilesOrder: if profile in profiles: selected = profile break if not selected: self.logger.info("User GLPI's profile can't be applied") else: self.logger.debug("Selected GLPI profile is %s" % selected) try: acls = self.config.profilesAcl[selected.lower()] except KeyError: acls = None if not acls: self.logger.info("No ACL to apply for the GLPI profile %s" % selected) else: l = ldapUserGroupControl() self.logger.info( "Setting MMC ACL corresponding to GLPI profile %s: %s" % (selected, acls)) uid = authtoken.getLogin() entry = l.getDetailedUser(uid) if not "lmcUserObject" in entry["objectClass"]: entry["objectClass"].append("lmcUserObject") l.changeUserAttributes(uid, "objectClass", entry["objectClass"]) l.changeUserAttributes(authtoken.getLogin(), "lmcAcl", acls) return authtoken
def activate(): ldapObj = ldapUserGroupControl() config = PPolicyConfig("ppolicy") if config.disabled: logger.warning("Plugin ppolicy: disabled by configuration.") return False ppolicySchema = ['pwdPolicy', 'device'] for objectClass in ppolicySchema: schema = ldapObj.getSchema(objectClass) if not len(schema): logger.error("LDAP Password Policy schema is not included in LDAP directory: %s objectClass is not available" % objectClass) return False # Register default password policy into the LDAP if it does not exist PPolicy().addPPolicy() return True
def cleanLdap(): # Wipe out /home os.system("rm -fr /home/*") # Wipe out LDAP os.system("/etc/init.d/slapd stop") os.system("killall -9 slapd") os.system("rm -f /var/lib/ldap/*") os.system("rm -fr /var/backups/*.ldapdb") os.system("cp contrib/ldap/*.schema /etc/ldap/schema") os.system("echo slapd slapd/password1 string secret | debconf-set-selections") os.system("echo slapd slapd/password2 string secret | debconf-set-selections") os.system("dpkg-reconfigure -pcritical slapd") os.system("cp contrib/ldap/slapd.conf.samba /etc/ldap/slapd.conf") os.system("/etc/init.d/slapd restart") time.sleep(5) # Create Base OU l = ldapUserGroupControl("tests-mds/basetest.ini") l.addOu("Groups", "dc=mandriva,dc=com") l.addOu("Users", "dc=mandriva,dc=com") l.addOu("Computers", "dc=mandriva,dc=com")
def activate(): config = UserQuotaConfig("userquota") if config.disabled: logger.warning("Plugin userquota: disabled by configuration.") return False try: ldapObj = ldapUserGroupControl() except ldap.INVALID_CREDENTIALS: logger.error("Can't bind to LDAP: invalid credentials.") return False # Test if the quota LDAP schema is available in the directory try: schema = ldapObj.getSchema("systemQuotas") if len(schema) <= 0: logger.error("Quota schema is not included in LDAP directory") return False except: logger.exception("Invalid schema") return False # Check local file systems if config.runquotascript == "/bin/sh": for device in getDevicemap(): dev, blocksize, name = device.split(':') if not os.path.exists(dev): logger.error("%s does not exists") return False code, out, err = mmctools.shlaunch( "quotaon -aup | grep '%s) is on'" % dev) if code != 0 or not len(out) == 1: logger.error("User quotas are not enabled on %s" % dev) return False return True
def activate(): config = UserQuotaConfig("userquota") if config.disabled: logger.warning("Plugin userquota: disabled by configuration.") return False try: ldapObj = ldapUserGroupControl() except ldap.INVALID_CREDENTIALS: logger.error("Can't bind to LDAP: invalid credentials.") return False # Test if the quota LDAP schema is available in the directory try: schema = ldapObj.getSchema("systemQuotas") if len(schema) <= 0: logger.error("Quota schema is not included in LDAP directory"); return False except: logger.exception("Invalid schema") return False # Check local file systems if config.runquotascript == "/bin/sh": for device in getDevicemap(): dev, blocksize, name = device.split(':') if not os.path.exists(dev): logger.error("%s does not exists"); return False code, out, err = mmctools.shlaunch("quotaon -aup | grep '%s) is on'" % dev) if code != 0 or not len(out) == 1: logger.error("User quotas are not enabled on %s" % dev); return False return True
def _create_group(self, name, description=None): logger.debug('calling ldapUserGroupControl().addGroup(%s)', name) ldapUserGroupControl().addGroup(name)
# Add and set default mask to rwx # This is needed by the ACL system, else the ACLs won't be valid e = acl1.append() e.permset.add(posix1e.ACL_READ) e.permset.add(posix1e.ACL_WRITE) e.permset.add(posix1e.ACL_EXECUTE) e.tag_type = posix1e.ACL_MASK # For each specified group, we add rwx access for group in usergroups: e = acl1.append() e.permset.add(posix1e.ACL_READ) e.permset.add(posix1e.ACL_WRITE) e.permset.add(posix1e.ACL_EXECUTE) e.tag_type = posix1e.ACL_GROUP # Search the gid number corresponding to the given group ldapobj = ldapUserGroupControl(self.conffilebase) try: gidNumber = ldapobj.getDetailedGroup(group)['gidNumber'][0] except ldap.NO_SUCH_OBJECT: gidNumber = grp.getgrnam(group).gr_gid e.qualifier = int(gidNumber) # FIXME # howto use posix1e for this ? shlaunch("setfacl -d -m g:%s:rwx %s" % (str(gidNumber), path)) for user in users: e = acl1.append() e.permset.add(posix1e.ACL_READ) e.permset.add(posix1e.ACL_WRITE) e.permset.add(posix1e.ACL_EXECUTE) e.tag_type = posix1e.ACL_USER # Search the gid number corresponding to the given group
def setUp(self): cleanLdap() self.l = ldapUserGroupControl("tests-mds/basetest.ini") self.assertEqual(self.l.addGroup("allusers"), 10001)
def setUp(self): cleanLdap() self.l = ldapUserGroupControl("tests-mds/basetest.ini")
def activate(): config = NetworkConfig("network") logger = logging.getLogger() if config.disabled: logger.warning("Plugin network: disabled by configuration.") return False if not config.dhcpEnable and not config.dnsEnable: logger.warning("Plugin network: disabled by configuration.") return False try: ldapObj = ldapUserGroupControl() except ldap.INVALID_CREDENTIALS: logger.error("Can't bind to LDAP: invalid credentials.") return False if config.dhcpEnable: # Test if the DHCP/LDAP schema is available in the directory try: schema = ldapObj.getSchema("dhcpServer") if len(schema) <= 0: logger.error("DHCP schema is not included in LDAP directory") return False # Test if DHCP/LDAP schema contains the dhcpComments attribute if "dhcpComments" not in schema: logger.error( "DHCP/LDAP schema does not support the dhcpComments attribute. Please use the latest version of DCHP/LDAP schema." ) return False except: logger.exception("invalid schema") return False else: logger.info("DHCP submodule is disabled") if config.dnsEnable: # Test if the DNS/LDAP schema is available in the directory serverType = config.dnsType if serverType == "pdns": try: schema = ldapObj.getSchema("dNSDomain2") if len(schema) <= 0: logger.error( "DNS zone schema (dnsdomain2.schema) is not included in LDAP directory" ) return False except: logger.exception("invalid DNS schema") return False elif serverType == "bind": try: schema = ldapObj.getSchema("dNSZone") if len(schema) <= 0: logger.error( "DNS zone schema (dnszone.schema) is not included in LDAP directory" ) return False except: logger.exception("invalid DNS schema") return False else: logger.error("%s : Unknown DNS server." % serverType) return False else: logger.info("DNS submodule is disabled") if config.dhcpEnable: # Create DHCP ou head, path = config.dhcpDN.split(",", 1) ouName = head.split("=")[1] ldapObj.addOu(ouName, path) # Create DHCP config base structure d = Dhcp() try: d.addServiceConfig("DHCP config") logger.info("Created DHCP config object") except ldap.ALREADY_EXISTS: pass hostname = d.configDhcp.dhcpHostname try: d.addServer(hostname) d.setServiceConfigStatement("not", "authoritative") logging.info("The DHCP server '%s' was added." % hostname) except ldap.ALREADY_EXISTS: pass d.setServiceServerStatus(hostname, "primary") logging.info( "The server '%s' has been set as the primary DHCP server" % hostname) # Create DNS config base structure if config.dnsEnable: # Create DNS ou head, path = config.dnsDN.split(",", 1) ouName = head.split("=")[1] ldapObj.addOu(ouName, path) if serverType == "bind": try: gidNumber = grp.getgrnam(config.bindGroup) except KeyError: logger.error('The group "%s" does not exist.' % config.bindGroup) return False gidNumber = gidNumber[2] try: os.mkdir(config.bindLdapDir) os.chmod(config.bindLdapDir, 02750) os.chown(config.bindLdapDir, -1, gidNumber) except OSError, e: # errno = 17 is "File exists" if e.errno != 17: raise if not os.path.exists(config.bindLdap): f = open(config.bindLdap, "w") f.close() os.chmod(config.bindLdap, 0640) os.chown(config.bindLdap, -1, gidNumber)
def doProvisioning(self, authtoken): from mmc.plugins.base import ldapUserGroupControl self.logger.debug(str(authtoken.getInfos())) l = ldapUserGroupControl() userentry = authtoken.getInfos()[1] uid = userentry[self.config.ldap_uid][0] if l.existUser(uid): self.logger.debug( "User %s already exists, so this user won't be added" % uid) else: givenName = userentry[self.config.ldap_givenName][0].decode( "utf-8") sn = userentry[self.config.ldap_sn][0].decode("utf-8") l.addUser(uid, authtoken.getPassword(), givenName, sn) if self.config.profileAttr and self.config.profilesAcl: # Set or update the user right try: profile = userentry[self.config.profileAttr][0].lower() except KeyError: self.logger.info( "No profile information for user %s in attribute %s" % (uid, self.config.profileAttr)) profile = "" profile = profile.strip() try: acls = self.config.profilesAcl[profile] except KeyError: self.logger.info( "No ACL defined in configuration file for profile '%s'" % profile) self.logger.info("Setting ACL to empty") acls = None if profile and acls: self.logger.info( "Setting MMC ACL corresponding to user profile %s: %s" % (profile, str(acls))) entry = l.getDetailedUser(uid) if not "lmcUserObject" in entry["objectClass"]: entry["objectClass"].append("lmcUserObject") l.changeUserAttributes(uid, "objectClass", entry["objectClass"]) l.changeUserAttributes(uid, "lmcAcl", acls) if self.config.profileGroupMapping: # Set user group membership according to mapping for prof in self.config.profilesAcl: groupname = self.config.profileGroupPrefix + prof if prof != profile: # Delete the user from a group not belonging to her/his # profile try: l.delUserFromGroup(groupname, uid) self.logger.debug( 'Deleting user %s from group %s' % (uid, groupname)) except ldap.NO_SUCH_OBJECT: # The group does not exist pass else: # Add the user to this group try: l.addGroup(groupname) except ldap.ALREADY_EXISTS: # This group already exists pass self.logger.debug('Adding user %s to group %s' % (uid, groupname)) l.addUserToGroup(groupname, uid)
def activate(): config = NetworkConfig("network") logger = logging.getLogger() if config.disabled: logger.warning("Plugin network: disabled by configuration.") return False try: ldapObj = ldapUserGroupControl() except ldap.INVALID_CREDENTIALS: logger.error("Can't bind to LDAP: invalid credentials.") return False # Test if the DHCP/LDAP schema is available in the directory try: schema = ldapObj.getSchema("dhcpServer") if len(schema) <= 0: logger.error("DHCP schema is not included in LDAP directory"); return False # Test if DHCP/LDAP schema contains the dhcpComments attribute if "dhcpComments" not in schema: logger.error("DHCP/LDAP schema does not support the dhcpComments attribute. Please use the latest version of DCHP/LDAP schema.") return False except: logger.exception("invalid schema") return False # Test if the DNS/LDAP schema is available in the directory serverType = config.dnsType if serverType == "pdns": try: schema = ldapObj.getSchema("dNSDomain2") if len(schema) <= 0: logger.error("DNS zone schema (dnsdomain2.schema) is not included in LDAP directory"); return False except: logger.exception("invalid DNS schema") return False elif serverType == "bind": try: schema = ldapObj.getSchema("dNSZone") if len(schema) <= 0: logger.error("DNS zone schema (dnszone.schema) is not included in LDAP directory"); return False except: logger.exception("invalid DNS schema") return False else: logger.error("%s : Unknown DNS server."%serverType); return False # Create required OUs config = NetworkConfig("network") for dn in [config.dhcpDN, config.dnsDN]: head, path = dn.split(",", 1) ouName = head.split("=")[1] ldapObj.addOu(ouName, path) # Create DHCP config base structure d = Dhcp() try: d.addServiceConfig("DHCP config") logger.info("Created DHCP config object") except ldap.ALREADY_EXISTS: pass hostname = d.configDhcp.dhcpHostname try: d.addServer(hostname) d.setServiceConfigStatement("not", "authoritative") logging.info("The DHCP server '%s' was added." % hostname) except ldap.ALREADY_EXISTS: pass d.setServiceServerStatus(hostname, "primary") logging.info("The server '%s' has been set as the primary DHCP server" % hostname) # Create DNS config base structure if serverType == "bind": try: gidNumber = grp.getgrnam(config.bindGroup) except KeyError: logger.error('The group "%s" does not exist.' % config.bindGroup) return False gidNumber = gidNumber[2] try: os.mkdir(config.bindLdapDir) os.chmod(config.bindLdapDir, 02750) os.chown(config.bindLdapDir, -1, gidNumber) except OSError, e: # errno = 17 is "File exists" if e.errno != 17: raise if not os.path.exists(config.bindLdap): f = open(config.bindLdap, "w") f.close() os.chmod(config.bindLdap, 0640) os.chown(config.bindLdap, -1, gidNumber)
def _create_user(self, username, password, name, surname): ldapUserGroupControl().addUser(username, password, name, surname)
class SambaConf: """ Handle smb.conf file for Samba 4 """ supportedGlobalOptions = ['realm', 'workgroup', 'netbios name', 'server role', 'logon path', 'logon drive', 'logon home', 'logon script', 'ldap passwd sync', 'wins support', 'dns forwarder'] KRB5_CONF_PATH = '/etc/krb5.conf' def __init__(self): config = Samba4Config("samba4") self.smb_conf_path = config.conf_file self.default_shares_path = config.defaultSharesPath self.authorizedSharePaths = config.authorizedSharePaths self.prefix = config.samba_prefix self.db_dir = config.db_dir try: self.config = ConfigObj(self.smb_conf_path, interpolation=False, list_values=False, write_empty_values=True, encoding='utf8') except ParseError as e: logger.error("Failed to parse %s : %s ", self.smb_conf_path, e) def private_dir(self): return os.path.join(self.db_dir, 'private') def validate(self, conf_file): """ Validate SAMBA configuration file with testparm. Try also to parse the configuration with ConfigObj. @return: Whether smb.conf has been validated or not @rtype: boolean """ cmd = shLaunch("%s/bin/testparm -s %s" % (self.prefix, shellquote(conf_file))) if cmd.exitCode: ret = False elif ("Unknown" in cmd.err or "ERROR:" in cmd.err or "Ignoring badly formed line" in cmd.err): ret = False else: ret = True try: ConfigObj(conf_file, interpolation=False, list_values=False) except ParseError: ret = False return ret def isValueTrue(self, string): """ @param string: a string @type string: str @return: Return 1 if string is yes/true/1 (case insensitive), return 0 if string is no/false/0 (case insensitive), else return -1 @rtype: int """ string = str(string).lower() if string in ["yes", "true", "1", "on"]: return 1 elif string in ["no", "false", "0"]: return 0 else: return -1 def getContent(self, section, option): try: return self.config[section][option] except KeyError: return False def setContent(self, section, option, value): try: self.config[section][option] = value except KeyError: self.config[section] = {} self.setContent(section, option, value) def getGlobalInfo(self): """ return main information about global section """ resArray = {} for option in self.supportedGlobalOptions: resArray[option] = self.getContent('global', option) resArray['hashomes'] = 'homes' in self.config return resArray def workgroupFromRealm(self, realm): return realm.split('.')[0][:15].upper() def writeSambaConfig(self, mode, netbios_name, realm, description, logon_path='', dns_forwarder=None, hashomes=True): """ Write SAMBA configuration file (smb.conf) to disk. @return values used to write the smb.conf template @rtype: dict """ openchange = False # FIXME openchange_conf = self.prefix + 'etc/openchange.conf' workgroup = self.workgroupFromRealm(realm) netbios_name = netbios_name.lower() realm = realm.upper() domain = realm.lower() params = {'workgroup': workgroup, 'realm': realm, 'netbios_name': netbios_name, 'description': description, 'mode': mode, 'sysvol_path': os.path.join(self.db_dir, 'sysvol'), 'openchange': openchange, 'openchange_conf': openchange_conf, 'domain': domain, 'interfaces': get_internal_interfaces(), 'logon_path': logon_path, 'dns_forwarder': dns_forwarder, 'hashomes': hashomes} smb_conf_template = env.get_template("smb.conf") with open(self.smb_conf_path, 'w') as f: f.write(smb_conf_template.render(params)) if openchange: openchange_conf_template = env.get_template("openchange.conf") with open(openchange_conf, 'w') as f: f.write(openchange_conf_template.render()) return params def writeKrb5Config(self, realm): params = {'realm': realm.upper()} krb5_conf_template = env.get_template('krb5.conf') with open(self.KRB5_CONF_PATH, 'w') as f: f.write(krb5_conf_template.render(params)) def getDetailedShares(self): """Return detailed list of shares""" return [self.getDetailedShare(section) for section in self._getSharesSectionList()] def getDetailedShare(self, section): guest = (self.isValueTrue(self.getContent(section, 'public')) == 1 or self.isValueTrue(self.getContent(section, 'guest ok')) == 1) enabled = (not self.getContent(section, 'browseable') or self.isValueTrue(self.getContent(section, 'browseable')) == 1) share_detail = { 'shareName': section, 'sharePath': self.getContent(section, 'path'), 'shareEnable': enabled, 'shareDescription': self.getContent(section, 'comment') or '', 'shareGuest': guest } # return share_detail return [share_detail['shareName'], share_detail['sharePath'], share_detail['shareEnable'], share_detail['shareDescription'], share_detail['shareGuest']] def _getSharesSectionList(self): return [k for k, _ in self.config.items() if k not in ("global", "printers", "print$")] def save(self): """ Write SAMBA configuration file (smb.conf) to disk """ _, tmpfname = tempfile.mkstemp("mmc") self.config.filename = tmpfname self.config.write() if not self.validate(tmpfname): raise Exception("smb.conf file is not valid (%s)" % tmpfname) shutil.copy(tmpfname, self.smb_conf_path) os.remove(tmpfname) return True def delShare(self, name, remove): """ Delete a share from SAMBA configuration, and maybe delete the share directory from disk. The save method must be called to update smb.conf. @param name: Name of the share @param remove: If true, we physically remove the directory """ r = AF().log(PLUGIN_NAME, AA.SAMBA4_DEL_SHARE, [(name, AT.SHARE)], remove) path = self.getContent(name, 'path') if not path: raise Exception('Share "%s" does not exist' % name) del self.config[name] if remove: if os.path.exists(path): shutil.rmtree(path) else: logger.error('The "%s" share path does not exist.' % path) r.commit() def shareInfo(self, name): """ Get information about a share """ ret = {} ret['desc'] = self.getContent(name, 'comment') if not ret['desc']: ret['desc'] = "" ret['sharePath'] = self.getContent(name, 'path') if self.isValueTrue(self.getContent(name, 'public')) == 1: ret['permAll'] = 1 elif self.isValueTrue(self.getContent(name, 'guest ok')) == 1: ret['permAll'] = 1 else: ret['permAll'] = 0 # If we cannot find it if not self.getContent(name, 'vfs objects'): ret['antivirus'] = 0 else: ret['antivirus'] = 1 if not self.getContent(name, 'browseable'): ret["browseable"] = 1 elif self.isValueTrue(self.getContent(name, 'browseable')): ret["browseable"] = 1 else: ret["browseable"] = 0 # Get the directory group owner if os.path.exists(str(ret['sharePath'])): stat_info = os.stat(ret['sharePath']) gid = stat_info.st_gid try: ret['group'] = grp.getgrgid(gid)[0] except: logger.error("Can't find the primary group of %s. " "Check your libnss settings." % ret['sharePath']) return False return ret def addShare(self, name, path, comment, browseable, permAll, usergroups, users, mod=False): """ Add a share in smb.conf and create it physically """ if mod: action = AA.SAMBA4_MOD_SHARE oldPath = self.config[name]['path'] else: action = AA.SAMBA4_ADD_SHARE r = AF().log(PLUGIN_NAME, action, [(name, AT.SHARE)], path) if name in self.config and not mod: raise Exception('This share already exist') if not name in self.config and mod: raise Exception('This share does not exist') # If no path is given, create a default one if not path: path = os.path.join(self.default_shares_path, name) path = os.path.realpath(path) # Check that the path is authorized # FIXME: handle correctly archives in base plugin if not self.isAuthorizedSharePath(path) and "/home/archives" not in path: raise Exception("%s is not an authorized share path." % path) # Create or move samba share directory, if it does not exist try: if mod: os.renames(oldPath, path) else: os.makedirs(path) except OSError, (errno, strerror): # Raise exception if error is not "File exists" if errno != 17: raise OSError(errno, strerror + ' ' + path) else: pass # Directory is owned by root os.chown(path, 0, 0) if mod: # Delete the old share del self.config[name] # create table and fix permission tmpInsert = {'comment': comment} if permAll: tmpInsert['public'] = 'yes' shlaunch("setfacl -b %s" % shellquote(path)) os.chmod(path, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) else: tmpInsert['public'] = 'no' os.chmod(path, stat.S_IRWXU | stat.S_IRWXG) # flush ACLs shlaunch("setfacl -b %s" % path) acl1 = posix1e.ACL(file=path) # Add and set default mask to rwx # This is needed by the ACL system, else the ACLs won't be valid e = acl1.append() e.permset.add(posix1e.ACL_READ) e.permset.add(posix1e.ACL_WRITE) e.permset.add(posix1e.ACL_EXECUTE) e.tag_type = posix1e.ACL_MASK # For each specified group, we add rwx access for group in usergroups: e = acl1.append() e.permset.add(posix1e.ACL_READ) e.permset.add(posix1e.ACL_WRITE) e.permset.add(posix1e.ACL_EXECUTE) e.tag_type = posix1e.ACL_GROUP # Search the gid number corresponding to the given group ldapobj = ldapUserGroupControl() try: gidNumber = ldapobj.getDetailedGroup(group)['gidNumber'][0] except ldap.NO_SUCH_OBJECT: gidNumber = grp.getgrnam(group).gr_gid e.qualifier = int(gidNumber) # FIXME howto use posix1e for this ? shlaunch("setfacl -d -m g:%s:rwx %s" % (str(gidNumber), path)) for user in users: e = acl1.append() e.permset.add(posix1e.ACL_READ) e.permset.add(posix1e.ACL_WRITE) e.permset.add(posix1e.ACL_EXECUTE) e.tag_type = posix1e.ACL_USER # Search the gid number corresponding to the given group ldapobj = ldapUserGroupControl() try: uidNumber = ldapobj.getDetailedUser(user)['uidNumber'][0] except KeyError: uidNumber = pwd.getpwnam(user).pw_uid e.qualifier = int(uidNumber) # FIXME howto use posix1e for this ? shlaunch("setfacl -d -m u:%s:rwx %s" % (str(uidNumber), path)) # Test if our ACLs are valid if acl1.valid(): acl1.applyto(path) else: logger.error("Cannot save ACL on folder " + path) tmpInsert['writeable'] = 'yes' if not browseable: tmpInsert['browseable'] = 'No' tmpInsert['path'] = path self.config[name] = tmpInsert info = self.shareInfo(name) # FIXME are this signals used? if mod and share_modified: share_modified.send(sender=self, share_name=name, share_info=info) elif not mod and share_created: share_created.send(sender=self, share_name=name, share_info=info) r.commit()
def _create_group(self, name, description=None): ldapUserGroupControl().addGroup(name)
def setUp(self): cleanLdap() self.l = ldapUserGroupControl("tests-mds/basetest.ini") self.l.addGroup("allusers") self.u = UserQuotaControl(conffile="tests-mds/userquotatest.ini", conffilebase="tests-mds/basetest.ini")
def activate(): """ this function define if the module "base" can be activated. @return: return True if this module can be activate @rtype: boolean """ config = SambaConfig("samba") if config.disabled: logger.info("samba plugin disabled by configuration.") return False if config.defaultSharesPath: if config.defaultSharesPath.endswith("/"): logger.error("Trailing / is not allowed in defaultSharesPath") return False if not os.path.exists(config.defaultSharesPath): logger.error("The default shares path '%s' does not exist" % config.defaultSharesPath) return False for cpath in config.authorizedSharePaths: if cpath.endswith("/"): logger.error("Trailing / is not allowed in authorizedSharePaths") return False if not os.path.exists(cpath): logger.error("The authorized share path '%s' does not exist" % cpath) return False # Verify if samba conf file exist conf = config.samba_conf_file if not os.path.exists(conf): logger.error(conf + " does not exist") return False # validate smb.conf smbconf = SambaConf() if not smbconf.validate(conf): logger.error("SAMBA configuration file is not valid") return False # For each share, test if it sharePath exists for share in getDetailedShares(): shareName = share[0] infos = shareInfo(shareName) if infos: sharePath = infos["sharePath"] if sharePath and not "%" in sharePath and not os.path.exists(sharePath): # only show error logger.error("The samba share path '%s' does not exist." % sharePath) else: return False try: ldapObj = ldapUserGroupControl() except ldap.INVALID_CREDENTIALS: logger.error("Can't bind to LDAP: invalid credentials.") return False # Test if the Samba LDAP schema is available in the directory try: schema = ldapObj.getSchema("sambaSamAccount") if len(schema) <= 0: logger.error("Samba schema is not included in LDAP directory") return False except: logger.exception("invalid schema") return False # Verify if init script exist init = config.samba_init_script if not os.path.exists(init): logger.error(init + " does not exist") return False # If SAMBA is defined as a PDC, make extra checks if smbconf.isPdc(): samba = SambaLDAP() # Create SAMBA computers account OU if it doesn't exist head, path = samba.baseComputersDN.split(",", 1) ouName = head.split("=")[1] samba.addOu(ouName, path) # Check that a sambaDomainName entry is in LDAP directory domainInfos = samba.getDomain() # Set domain policy samba.setDomainPolicy() if not domainInfos: logger.error( "Can't find sambaDomainName entry in LDAP for domain %s. Please check your SAMBA LDAP configuration." % smbconf.getContent("global", "workgroup") ) return False smbconfbasesuffix = smbconf.getContent("global", "ldap suffix") if not smbconfbasesuffix: logger.error("SAMBA 'ldap suffix' option is not setted.") return False if ldap.explode_dn(samba.baseDN) != ldap.explode_dn(smbconfbasesuffix): logger.error("SAMBA 'ldap suffix' option is not equal to MMC 'baseDN' option.") return False # Check that SAMBA and MMC given OU are in sync for option in [ ("ldap user suffix", "baseUsersDN", samba.baseUsersDN), ("ldap group suffix", "baseGroupsDN", samba.baseGroupsDN), ("ldap machine suffix", "baseComputersDN", samba.baseComputersDN), ]: smbconfsuffix = smbconf.getContent("global", option[0]) if not smbconfsuffix: logger.error("SAMBA '" + option[0] + "' option is not setted") return False # Do a case insensitive comparison of the corresponding MMC / SAMBA options if ldap.explode_rdn(smbconfsuffix)[0].lower() != ldap.explode_rdn(option[2])[0].lower(): logger.error("SAMBA option '" + option[0] + "' is not equal to MMC '" + option[1] + "' option.") return False # Check that "ldap delete dn" SAMBA option is set to "No" smbconfdeletedn = smbconf.isValueTrue(smbconf.getContent("global", "ldap delete dn")) if smbconfdeletedn == 1: logger.error("SAMBA option 'ldap delete dn' must be disabled.") return False # Check that Domain Computers group exists # We need it to put a machine account in the right group when joigning it to the domain if not samba.getDomainComputersGroup(): logger.error( "Can't find sambaGroupMapping entry in LDAP corresponding to 'Domain Computers' group. Please check your SAMBA LDAP configuration." ) return False # Check that Domain Admins group exists if not samba.getDomainAdminsGroup(): logger.error( "Can't find sambaGroupMapping entry in LDAP corresponding to 'Domain Admins' group. Please check your SAMBA LDAP configuration." ) return False # Check that Domain Guests group exists if not samba.getDomainGuestsGroup(): logger.error( "Can't find sambaGroupMapping entry in LDAP corresponding to 'Domain Guests' group. Please check your SAMBA LDAP configuration." ) return False # Check that Domain Users group exists if not samba.getDomainUsersGroup(): logger.error( "Can't find sambaGroupMapping entry in LDAP corresponding to 'Domain Users' group. Please check your SAMBA LDAP configuration." ) return False # Check that add machine script option is set, and that the given script exist addMachineScript = smbconf.getContent("global", "add machine script") if not addMachineScript: logger.error("SAMBA 'add machine script' option is not set.") return False else: script = addMachineScript.split(" ")[0] if not os.path.exists(script): logger.error("SAMBA 'add machine script' option is set to a non existing file: " + script) return False # Issue a warning if NSCD is running if ( os.path.exists("/var/run/nscd.pid") or os.path.exists("/var/run/.nscd_socket") or os.path.exists("/var/run/nscd") ): logger.warning("Looks like NSCD is installed on your system. You should not run NSCD on a SAMBA server.") # Check that os level is set to 255 oslevel = smbconf.getContent("global", "os level") if int(oslevel) < 255: logger.debug("Set SAMBA os level to 255.") smbconf.setContent("global", "os level", "255") smbconf.save() reloadSamba() try: from mmc.plugins.dashboard.manager import DashboardManager from mmc.plugins.samba.panel import SambaPanel DM = DashboardManager() DM.register_panel(SambaPanel("samba")) except ImportError: pass return True
def activate(): """ this function define if the module "base" can be activated. @return: return True if this module can be activate @rtype: boolean """ config = SambaConfig("samba") if config.disabled: logger.info("samba plugin disabled by configuration.") return False if config.defaultSharesPath: if config.defaultSharesPath.endswith("/"): logger.error("Trailing / is not allowed in defaultSharesPath") return False if not os.path.exists(config.defaultSharesPath): logger.error("The default shares path '%s' does not exist" % config.defaultSharesPath) return False for cpath in config.authorizedSharePaths: if cpath.endswith("/"): logger.error("Trailing / is not allowed in authorizedSharePaths") return False if not os.path.exists(cpath): logger.error("The authorized share path '%s' does not exist" % cpath) return False # Verify if samba conf file exist conf = config.samba_conf_file if not os.path.exists(conf): logger.error(conf + " does not exist") return False # validate smb.conf smbconf = SambaConf() if not smbconf.validate(conf): logger.error("SAMBA configuration file is not valid") return False # For each share, test if it sharePath exists for share in getDetailedShares(): shareName = share[0] infos = shareInfo(shareName) if infos: sharePath = infos['sharePath'] if sharePath and not '%' in sharePath and not os.path.exists( sharePath): # only show error logger.error("The samba share path '%s' does not exist." % sharePath) else: return False try: ldapObj = ldapUserGroupControl() except ldap.INVALID_CREDENTIALS: logger.error("Can't bind to LDAP: invalid credentials.") return False # Test if the Samba LDAP schema is available in the directory try: schema = ldapObj.getSchema("sambaSamAccount") if len(schema) <= 0: logger.error("Samba schema is not included in LDAP directory") return False except: logger.exception("invalid schema") return False # Verify if init script exist init = config.samba_init_script if not os.path.exists(init): logger.error(init + " does not exist") return False # If SAMBA is defined as a PDC, make extra checks if smbconf.isPdc(): samba = SambaLDAP() # Create SAMBA computers account OU if it doesn't exist head, path = samba.baseComputersDN.split(",", 1) ouName = head.split("=")[1] samba.addOu(ouName, path) # Check that a sambaDomainName entry is in LDAP directory domainInfos = samba.getDomain() # Set domain policy samba.setDomainPolicy() if not domainInfos: logger.error( "Can't find sambaDomainName entry in LDAP for domain %s. Please check your SAMBA LDAP configuration." % smbconf.getContent("global", "workgroup")) return False smbconfbasesuffix = smbconf.getContent("global", "ldap suffix") if not smbconfbasesuffix: logger.error("SAMBA 'ldap suffix' option is not setted.") return False if ldap.explode_dn(samba.baseDN) != ldap.explode_dn(smbconfbasesuffix): logger.error( "SAMBA 'ldap suffix' option is not equal to MMC 'baseDN' option." ) return False # Check that SAMBA and MMC given OU are in sync for option in [ ("ldap user suffix", "baseUsersDN", samba.baseUsersDN), ("ldap group suffix", "baseGroupsDN", samba.baseGroupsDN), ("ldap machine suffix", "baseComputersDN", samba.baseComputersDN) ]: smbconfsuffix = smbconf.getContent("global", option[0]) if not smbconfsuffix: logger.error("SAMBA '" + option[0] + "' option is not setted") return False # Do a case insensitive comparison of the corresponding MMC / SAMBA options if ldap.explode_rdn(smbconfsuffix)[0].lower() != ldap.explode_rdn( option[2])[0].lower(): logger.error("SAMBA option '" + option[0] + "' is not equal to MMC '" + option[1] + "' option.") return False # Check that "ldap delete dn" SAMBA option is set to "No" smbconfdeletedn = smbconf.isValueTrue( smbconf.getContent("global", "ldap delete dn")) if smbconfdeletedn == 1: logger.error("SAMBA option 'ldap delete dn' must be disabled.") return False # Check that Domain Computers group exists # We need it to put a machine account in the right group when joigning it to the domain if not samba.getDomainComputersGroup(): logger.error( "Can't find sambaGroupMapping entry in LDAP corresponding to 'Domain Computers' group. Please check your SAMBA LDAP configuration." ) return False # Check that Domain Admins group exists if not samba.getDomainAdminsGroup(): logger.error( "Can't find sambaGroupMapping entry in LDAP corresponding to 'Domain Admins' group. Please check your SAMBA LDAP configuration." ) return False # Check that Domain Guests group exists if not samba.getDomainGuestsGroup(): logger.error( "Can't find sambaGroupMapping entry in LDAP corresponding to 'Domain Guests' group. Please check your SAMBA LDAP configuration." ) return False # Check that Domain Users group exists if not samba.getDomainUsersGroup(): logger.error( "Can't find sambaGroupMapping entry in LDAP corresponding to 'Domain Users' group. Please check your SAMBA LDAP configuration." ) return False # Check that add machine script option is set, and that the given script exist addMachineScript = smbconf.getContent("global", "add machine script") if not addMachineScript: logger.error("SAMBA 'add machine script' option is not set.") return False else: script = addMachineScript.split(" ")[0] if not os.path.exists(script): logger.error( "SAMBA 'add machine script' option is set to a non existing file: " + script) return False # Issue a warning if NSCD is running if os.path.exists("/var/run/nscd.pid") or os.path.exists( "/var/run/.nscd_socket") or os.path.exists("/var/run/nscd"): logger.warning( "Looks like NSCD is installed on your system. You should not run NSCD on a SAMBA server." ) # Check that os level is set to 255 oslevel = smbconf.getContent("global", "os level") if int(oslevel) < 255: logger.debug("Set SAMBA os level to 255.") smbconf.setContent("global", "os level", "255") smbconf.save() reloadSamba() try: from mmc.plugins.dashboard.manager import DashboardManager from mmc.plugins.samba.panel import SambaPanel DM = DashboardManager() DM.register_panel(SambaPanel("samba")) except ImportError: pass return True
def doProvisioning(self, authtoken): from mmc.plugins.base import ldapUserGroupControl self.logger.debug(str(authtoken.getInfos())) l = ldapUserGroupControl() userentry = authtoken.getInfos()[1] uid = userentry[self.config.ldap_uid][0] if l.existUser(uid): self.logger.debug("User %s already exists, so this user won't be added" % uid) else: givenName = userentry[self.config.ldap_givenName][0].decode("utf-8") sn = userentry[self.config.ldap_sn][0].decode("utf-8") l.addUser(uid, authtoken.getPassword(), givenName, sn) if self.config.profileAttr and self.config.profilesAcl: # Set or update the user right try: profile = userentry[self.config.profileAttr][0].lower() except KeyError: self.logger.info("No profile information for user %s in attribute %s" % (uid, self.config.profileAttr)) profile = "" profile = profile.strip() try: entities = self.config.profilesEntity[profile].split() self.logger.info("*******ENTITE '%s' " % (entities)) except KeyError: if self.config.profilesEntity.has_key("default"): entities = self.config.profilesEntity["default"].split() self.logger.info("Set the default profile to user.") profile = 'default' else: self.logger.info("No entity defined in configuration file for profile '%s'" % profile) self.logger.info("Setting user's entity to empty") entities = [] if profile and entities: tmp = [] for entity in entities: if entity.startswith('%') and entity.endswith('%'): attr = entity.strip('%') if attr in userentry: tmp.extend(userentry[attr]) else: self.logger.info("The user '%s' doesn't have an attribute '%s'" % (uid, attr)) elif entity.startswith('plugin:'): plugin = entity.replace('plugin:', '') searchpath = os.path.join(os.path.dirname(__file__), 'provisioning_plugins') try: f, p, d = imp.find_module(plugin, [searchpath]) mod = imp.load_module(plugin, f, p, d) klass = mod.PluginEntities found = klass().get(authtoken) if found: self.logger.info("Plugin '%s' found these entities: %s" % (plugin, found)) else: self.logger.info("Plugin '%s' found no matching entity" % plugin) tmp.extend(found) except ImportError: self.logger.error("The plugin '%s' can't be imported" % plugin) except Exception, e: self.logger.error("Error while using the plugin '%s'" % plugin) self.logger.exception(e) else: tmp.append(entity) entities = tmp[:] self.logger.info("****Setting user '%s' entities corresponding to user profile '%s': %s" % (uid, profile, str(entities))) from pulse2.database.inventory import Inventory Inventory().setUserEntities(uid, entities) try: acls = self.config.profilesAcl[profile] except KeyError: self.logger.info("No ACL defined in configuration file for profile '%s'" % profile) self.logger.info("Setting ACL to empty") acls = None if profile and acls: self.logger.info("Setting MMC ACL corresponding to user profile %s: %s" % (profile, str(acls))) entry = l.getDetailedUser(uid) if not "lmcUserObject" in entry["objectClass"]: entry["objectClass"].append("lmcUserObject") l.changeUserAttributes(uid, "objectClass", entry["objectClass"]) l.changeUserAttributes(uid, "lmcAcl", acls) if self.config.profileGroupMapping: # Set user group membership according to mapping for prof in self.config.profilesAcl: groupname = self.config.profileGroupPrefix + prof if prof != profile: # Delete the user from a group not belonging to her/his # profile try: l.delUserFromGroup(groupname, uid) self.logger.debug('Deleting user %s from group %s' % (uid, groupname)) except ldap.NO_SUCH_OBJECT: # The group does not exist pass else: # Add the user to this group try: l.addGroup(groupname) except ldap.ALREADY_EXISTS: # This group already exists pass self.logger.debug('Adding user %s to group %s' % (uid, groupname)) l.addUserToGroup(groupname, uid)
def setUp(self): cleanLdap() self.l = ldapUserGroupControl("tests-mds/basetest.ini") self.l.addGroup("allusers") self.u = UserQuotaControl(conffile = "tests-mds/userquotatest.ini", conffilebase = "tests-mds/basetest.ini")
tmpInsert['writeable'] = 'yes' os.chmod(path, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) else: tmpInsert['public'] = 'no' tmpInsert['writeable'] = 'no' os.chmod(path, stat.S_IRWXU | stat.S_IRWXG) acls = posix1e.ACL(file=path) # Add and set default mask to rwx # This is needed by the ACL system, else the ACLs won't be valid e = acls.append() e.permset.add(posix1e.ACL_READ) e.permset.add(posix1e.ACL_WRITE) e.permset.add(posix1e.ACL_EXECUTE) e.tag_type = posix1e.ACL_MASK # For each specified group, we add rwx access ldapobj = ldapUserGroupControl(self.conffilebase) def add_acl_permset(acl, entity, rights): e = acls.append() if 'r' in rights: e.permset.add(posix1e.ACL_READ) if 'w' in rights: e.permset.add(posix1e.ACL_WRITE) if 'x' in rights: e.permset.add(posix1e.ACL_EXECUTE) if entity.startswith('@'): e.tag_type = posix1e.ACL_GROUP try: gidNumber = ldapobj.getDetailedGroup(entity[1:])['gidNumber'][0] except ldap.NO_SUCH_OBJECT: gidNumber = grp.getgrnam(entity[1:]).gr_gid