
Research
Security News
Malicious npm Packages Use Telegram to Exfiltrate BullX Credentials
Socket uncovers an npm Trojan stealing crypto wallets and BullX credentials via obfuscated code and Telegram exfiltration.
A read-only Zope3 GroupFolder implementation that reflects groups on an LDAP server. Needs ldappas
This is an AuthenticatorPlugin that implements a read-only GroupFolder reflecting the groups as defined on an LDAP server. It relies on the registration as a named ILDAPAuthentation utility of an ldappas plugin. It works in tandem with ldappas: ldappas authenticates users, while ldapgroups looks up their groups and adds the users to the groups
>>> from ldappas.authentication import LDAPAuthentication
>>> from zope import component
>>> from ldappas.interfaces import ILDAPAuthentication
>>> users = LDAPAuthentication()
>>> component.provideUtility(users, ILDAPAuthentication, 'ldap-users')
LDAPAuthentication needs an LDAP adapter, registered as a named ILDAPAdapter utility. There's a fake one in the tests module.
>>> from ldapgroups.tests.fakeadapter import FakeLDAPAdapter
>>> adapter = FakeLDAPAdapter()
>>> from ldapadapter.interfaces import ILDAPAdapter
>>> component.provideUtility(adapter, ILDAPAdapter, 'ldap-adapter')
Let's configure the LDAPAuthentication plugin:
>>> users.adapterName = u'ldap-adapter'
>>> users.searchBase = u'ou=users,dc=test'
>>> users.searchScope = u'sub'
>>> users.loginAttribute = u'cn'
>>> users.principalIdPrefix = u'ldap.'
>>> users.titleAttribute = u'sn'
There's no need to fill in the group-related attributes on the LDAPAuthentication plugin, as LDAPGroups uses its own. For the idAttribute, you should use the attribute that yields the Distinguished Name of the user, as LDAP uses this to link users to groups:
>>> users.idAttribute = u'dn'
(For ActiveDirectory, this apparently is 'distinguishedName', so use an LDAP browser to check) There may be a way around this restriction with advanced queries, but is not (yet?) implemented.
Let's get our LDAP GroupFolder up and running
>>> from ldapgroups.groupfolder import LDAPGroups
>>> groups = LDAPGroups(u'ldap-users', u'group.ldap.')
>>> groups.groupsSearchBase = u'ou=groups,dc=test'
>>> groups.groupsSearchScope = u'sub'
>>> groups.groupTitleAttribute = u'cn'
>>> groups.groupIdAttribute = u'dn'
>>> groups.groupDescriptionAttribute = u'description'
Do some registration tests
groups.getLDAPAuthenticator() == users True users.getLDAPAdapter() == adapter True
Groups can't authenticate
groups.authenticateCredentials({'login':u'Domain Users','password':u'pwd'}) is None True
We can lookup groups as principals
principal = groups.principalInfo(u'group.ldap.cn=Domain Users,ou=groups,dc=test') principal LDAPGroupInformation(u'group.ldap.cn=Domain Users,ou=groups,dc=test') from zope.pluggableauth.interfaces import IPrincipalInfo IPrincipalInfo.providedBy(principal) True
It also provides IReadGroupInformation, which can be used to get the principals
from ldapgroups.interfaces import IReadGroupInformation IReadGroupInformation.providedBy(principal) True principal.principals [u'ldap.cn=Andr\xe9 de Chimpansee,ou=users,dc=test', u'ldap.cn=Louis Kolibri,ou=users,dc=test']
len(groups) 2 groups.keys() [u'Administrators', u'Domain Users'] 'Administrators' in groups True groups.has_key('Administrators') True groups.values() [LDAPGroupInformation(u'group.ldap.cn=Administrators,ou=groups,dc=test'), LDAPGroupInformation(u'group.ldap.cn=Domain Users,ou=groups,dc=test')] groups.items() == zip(groups.keys(), groups.values()) True group = groups['Domain Users'] group LDAPGroupInformation(u'group.ldap.cn=Domain Users,ou=groups,dc=test') group.description u'Users with a domain account' group == groups.get('Domain Users') True groups.get('grupo sportivo') is None True groups['grupo sportivo'] # doctest: +ELLIPSIS Traceback (most recent call last): ... KeyError
groups.search({'cn':'Domain Users'}) [u'group.ldap.cn=Domain Users,ou=groups,dc=test'] groups.search({'cn':'Users'}) []
Registers them all to the PAU
from zope.pluggableauth.interfaces import IAuthenticatorPlugin component.provideUtility(users, provides=IAuthenticatorPlugin, name='ldap-users') component.provideUtility(groups, provides=IAuthenticatorPlugin, name='ldap-groups')
We also need a credentials plugin that will extract the credentials from the request:
import zope.interface from zope.pluggableauth.interfaces import ICredentialsPlugin
class MyCredentialsPlugin: ... ... zope.interface.implements(ICredentialsPlugin) ... ... def extractCredentials(self, request): ... return request.get('credentials') ... ... def challenge(self, request): ... pass # challenge is a no-op for this plugin ... ... def logout(request): ... pass # logout is a no-op for this plugin
creds = MyCredentialsPlugin() component.provideUtility(creds, name='simple-creds')
Register the principalFactory
import zope.component.event from zope.pluggableauth import factories component.provideAdapter(factories.AuthenticatedPrincipalFactory) component.provideAdapter(factories.FoundPrincipalFactory)
We are finally ready to create a pluggable authentication utility and register the two plugins with it:
from zope.pluggableauth import PluggableAuthentication pau = PluggableAuthentication() pau['ldap-users'] = users pau['ldap-groups'] = groups pau['simple-creds'] = creds pau.credentialsPlugins = ('simple-creds', ) pau.authenticatorPlugins = ('ldap-users', 'ldap-groups')
Let's authenticate some users
from zope.publisher.browser import TestRequest request = TestRequest(credentials={'login': 'Louis Kolibri', 'password': 'louis2000'}) louis = pau.authenticate(request) louis Principal(u'ldap.cn=Louis Kolibri,ou=users,dc=test')
Groups are set by the setGroupsForPrincipal event subscriber
louis.groups [] class PrincipalCreatedEvent: ... def init(self, authentication, principal): ... self.authentication = authentication ... self.principal = principal from ldapgroups.groupfolder import setGroupsForPrincipal setGroupsForPrincipal(PrincipalCreatedEvent(pau, louis)) louis.groups [u'group.ldap.cn=Domain Users,ou=groups,dc=test'] component.provideHandler(setGroupsForPrincipal) request = TestRequest(credentials={'login': u'Andr\xe9 de Chimpansee', 'password': 'dreten'}) andre = pau.authenticate(request) andre Principal(u'ldap.cn=Andr\xe9 de Chimpansee,ou=users,dc=test') andre.groups [u'group.ldap.cn=Administrators,ou=groups,dc=test', u'group.ldap.cn=Domain Users,ou=groups,dc=test']
There's an ISized adapter available for the zmi view.
from ldapgroups.groupfolder import LDAPGroupSize from zope.size.interfaces import ISized component.provideAdapter(LDAPGroupSize) ISized(group).sizeForSorting() ('item', 2)
The view's iteminfos function gathers all info about the goups in a groupfolder
from ldapgroups.browser.contents import LDAPGroupFolderContents view = LDAPGroupFolderContents(groups, request) view.iteminfos() [{'url': 'Administrators', 'name': u'Administrators', 'size': u'${items} items'}, {'url': 'Domain%20Users', 'name': u'Domain Users', 'size': u'${items} items'}]
FAQs
A read-only Zope3 GroupFolder implementation that reflects groups on an LDAP server. Needs ldappas
We found that ldapgroups demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket uncovers an npm Trojan stealing crypto wallets and BullX credentials via obfuscated code and Telegram exfiltration.
Research
Security News
Malicious npm packages posing as developer tools target macOS Cursor IDE users, stealing credentials and modifying files to gain persistent backdoor access.
Security News
AI-generated slop reports are making bug bounty triage harder, wasting maintainer time, and straining trust in vulnerability disclosure programs.