Advertisement
Guest User

Untitled

a guest
Nov 23rd, 2017
67
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.81 KB | None | 0 0
  1. #!/usr/bin/env python
  2. # coding=utf-8
  3. #
  4. # Copyright © 2014 Splunk, Inc. All Rights Reserved
  5.  
  6. from __future__ import absolute_import, division, print_function, unicode_literals
  7. import default
  8. import app
  9. import ldap3
  10.  
  11. from splunklib.searchcommands import dispatch, StreamingCommand, Configuration, Option, validators
  12.  
  13.  
  14. @Configuration()
  15. class LdapFilterCommand(StreamingCommand):
  16. """ Filters and augments events with information from Active Directory.
  17.  
  18. This command follows a search or similar command in the pipeline so that you can feed it events:
  19.  
  20. .. code-block:: text
  21. eventtype=msad-user-logons
  22. | ldapfilter domain=$dest_nt_domain$ search="(objectClass=$src_user$)" attrs="telephoneNumber,displayName"
  23.  
  24. """
  25. # region Command options
  26.  
  27. search = Option(
  28. doc=''' Specifies an RFC 2254 compliant search string.
  29. ''',
  30. require=True)
  31.  
  32. domain = Option(
  33. doc=''' Specifies the Active Directory domain to search.
  34. ''',
  35. default='default')
  36.  
  37. attrs = Option(
  38. doc=''' Specifies a comma separated list of attributes to return as fields.
  39. **Default:** '*', specifying that all attributes should be returned as fields.
  40. ''',
  41. default=[ldap3.ALL_ATTRIBUTES], validate=validators.List())
  42.  
  43. basedn = Option(
  44. doc=''' Specifies the starting point for the search.
  45. Default: The value of `basedn` as specified in the configuration stanza for `domain`.
  46. ''')
  47.  
  48. scope = Option(
  49. doc=''' Specifies the scope of the search to be one of `base`, `one`, or `sub`.
  50. **Default:** sub.
  51. ''',
  52. default='sub', validate=validators.Map(
  53. base=ldap3.SEARCH_SCOPE_BASE_OBJECT,
  54. one=ldap3.SEARCH_SCOPE_SINGLE_LEVEL,
  55. sub=ldap3.SEARCH_SCOPE_WHOLE_SUBTREE
  56. ))
  57.  
  58. decode = Option(
  59. doc=''' True, if Active Directory formatting rules should be applied to attribute types.
  60. **Default:** The value of decode as specified in the configuration stanza for domain.
  61. ''',
  62. default=True, validate=validators.Boolean())
  63.  
  64. limit = Option(
  65. doc=''' Specifies an upper bound on the number of matching entries returned by the search.
  66. **Default:** 0, specifying that there is no upper bound on the number of entries returned by the search.
  67. ''',
  68. default=0, validate=validators.Integer(minimum=0))
  69.  
  70. debug = Option(
  71. doc=''' True, if the logging_level should be set to DEBUG; otherwise False.
  72. **Default:** The current value of logging_level.
  73. ''',
  74. default=False, validate=validators.Boolean())
  75.  
  76. # endregion
  77.  
  78. # region Command implementation
  79.  
  80. def stream(self, records):
  81. """
  82. :param records: An iterable stream of events from the command pipeline.
  83. :return: `None`.
  84.  
  85. """
  86. configuration = app.Configuration(self, is_expanded=True)
  87. expanded_domain = app.ExpandedString(self.domain)
  88. expanded_search_filter = app.ExpandedString(self.search, converter=app.escape_assertion_value)
  89.  
  90. try:
  91. with configuration.open_connection_pool(self.attrs) as connection_pool:
  92.  
  93. for record in records:
  94.  
  95. domain = expanded_domain.get_value(record)
  96.  
  97. if domain is None:
  98. continue
  99.  
  100. search_filter = expanded_search_filter.get_value(record)
  101.  
  102. if len(search_filter) == 0:
  103. continue
  104.  
  105. connection = connection_pool.select(domain)
  106.  
  107. if not connection:
  108. self.logger.warning('search="%s": domain="%s" is not configured', search_filter, domain)
  109. continue
  110.  
  111. search_base = app.ExpandedString(self.basedn).get_value(record) # must be instantiated here
  112.  
  113. entry_generator = connection.extend.standard.paged_search(
  114. search_base=search_base, search_filter=search_filter, search_scope=self.scope,
  115. attributes=connection_pool.attributes, paged_size=configuration.paged_size)
  116.  
  117. for entry in entry_generator:
  118. attributes = app.get_attributes(self, entry)
  119. if not attributes:
  120. continue
  121. for name in connection_pool.attributes:
  122. record[name] = attributes.get(name, '')
  123. yield record
  124.  
  125. pass
  126.  
  127. except ldap3.LDAPException as error:
  128. self.error_exit(error, app.get_ldap_error_message(error, configuration))
  129.  
  130. return
  131.  
  132. # endregion
  133.  
  134. dispatch(LdapFilterCommand, module_name=__name__)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement