forked from ibmresilient/resilient-community-apps
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Hugh Pyle
committed
Sep 26, 2018
1 parent
4d85343
commit f246613
Showing
106 changed files
with
17,365 additions
and
2,140 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
include README.md | ||
include fn_ldap_utilities/util/* | ||
include fn_ldap_utilities/LICENSE | ||
include docs/* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
# Resilient LDAP Utilities v1.0.0 | ||
|
||
This Python Package is comprised of various Resilient Functions that allow you to manage users in your Directory Service, without having to leave the UI of Resilient | ||
|
||
See [Detailed PDF Documentation here](./docs/Resilient%20Integration%20LDAP%20Utility%20Function.pdf) | ||
|
||
## ldap_utilities_search | ||
* Supports **Active Directory** and **OpenLDAP** | ||
* When using with **Microsoft Active Directory** server | ||
* Set the following in the **app.config file**: | ||
```python | ||
[fn_ldap_utilities] | ||
ldap_port=636 | ||
ldap_use_ssl=True | ||
ldap_is_active_directory=True | ||
``` | ||
|
||
The LDAP search requires **4 input parameters**. The parameters are setup from a Resilient systems workflow on the Resilient console. | ||
The following are examples of setup of each parameter using a simple workflow pre-processing script. The %param% token | ||
will be replaced by the actual inputs.param value at time of execution. | ||
|
||
``` | ||
inputs.ldap_search_base = "dc=example,dc=com" | ||
inputs.ldap_search_filter = "(&(objectClass=person)(uid=%ldap_param%))" | ||
inputs.ldap_search_attributes = "cn,sn,mail,telephoneNumber" | ||
inputs.ldap_search_param = artifact.value | ||
``` | ||
The results returned to Resilient will be in JSON format and will consist of a list of | ||
entries where each entry has a 'dn' entry and a set of attributes | ||
``` | ||
{ | ||
"entries": [ | ||
{"dn': "entry1_dn1_value", "entry1_attribute2", "entry1_attribute3", ... }, | ||
{"dn": "entry2_dn2_value", "entry2_attribute2", "entry2_attribute3", ... } | ||
... | ||
] | ||
} | ||
``` | ||
## ldap_utilities_set_password | ||
* Supports **Active Directory** and **OpenLDAP** | ||
* When using with **Microsoft Active Directory** server | ||
* Set the following in the **app.config file**: | ||
```python | ||
[fn_ldap_utilities] | ||
ldap_port=636 | ||
ldap_use_ssl=True | ||
ldap_is_active_directory=True | ||
``` | ||
* Must use a secure connection | ||
* Microsoft does not allow you to change an user's password unless using a secure connection | ||
* Microsoft have their own ldap3 function to change the password of an entry in the Active Directory [see here](https://ldap3.readthedocs.io/microsoft.html) | ||
* For other directory services using LDAP (i.e. **OpenLDAP**) | ||
* Set the following in the **app.config file**: | ||
```python | ||
[fn_ldap_utilities] | ||
ldap_is_active_directory=False | ||
``` | ||
## ldap_utilities_update | ||
* Supports **Active Directory** and **OpenLDAP** | ||
* Takes the name of the attribute you want to update and an list of values to update that attribute with | ||
* The function input `ldap_attribute_values` must be a **string representation of an list:** | ||
```python | ||
inputs.ldap_attribute_values = "['stringValue1', 1234, 'stringValue2']" | ||
``` | ||
* Uses **MODIFY_REPLACE** as documented [here](https://ldap3.readthedocs.io/modify.html) | ||
* _"Replace all existing values of the specified attribute with the new values listed"_ | ||
* _"Creates the attribute if it does not already exist"_ | ||
* _"It is ignored if the attribute does not exist"_ | ||
|
||
## ldap_utilities_toggle_access | ||
* Supports only **Active Directory**. | ||
* Set the following in the **app.config file**: | ||
```python | ||
[fn_ldap_utilities] | ||
ldap_port=636 | ||
ldap_use_ssl=True | ||
ldap_is_active_directory=True | ||
``` | ||
* Enables or Disables an **Active Directory** user | ||
* Requires the DN of the user you wish to toggle access for | ||
* Example shows how to use with **LDAP Utilities: Search Function** to toggle access for a user using their email address | ||
|
||
## ldap_utilities_add_to_groups / ldap_utilities_remove_from_groups | ||
* Supports only **Active Directory**. | ||
* Set the following in the **app.config file**: | ||
```python | ||
[fn_ldap_utilities] | ||
ldap_port=636 | ||
ldap_use_ssl=True | ||
ldap_is_active_directory=True | ||
``` | ||
* The function inputs `ldap_multiple_user_dn` and `ldap_multiple_group_dn` must be **string representation of a list:** | ||
```python | ||
# Pre-Processing Script:: | ||
inputs.ldap_multiple_user_dn = "['dn=user1,dc=example,dc=com', 'dn=user2,dc=example,dc=com']" | ||
inputs.ldap_multiple_group_dn = "['dn=Accounts Group,dc=example,dc=com', 'dn=IT Group,dc=example,dc=com']" | ||
``` |
Binary file added
BIN
+299 KB
fn_ldap_utilities/docs/Resilient Integration LDAP Utility Function.docx
Binary file not shown.
Binary file added
BIN
+558 KB
fn_ldap_utilities/docs/Resilient Integration LDAP Utility Function.pdf
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
Copyright © IBM Corporation 2010, 2018 | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copyof this software and associated documentation files (the "Software"), to | ||
deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included inall copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THEAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
IN THE SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import pkg_resources | ||
try: | ||
__version__ = pkg_resources.get_distribution(__name__).version | ||
except pkg_resources.DistributionNotFound: | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# |
90 changes: 90 additions & 0 deletions
90
fn_ldap_utilities/fn_ldap_utilities/components/ldap_utilities_add_to_groups.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
# -*- coding: utf-8 -*- | ||
# (c) Copyright IBM Corp. 2018. All Rights Reserved. | ||
# pragma pylint: disable=unused-argument, no-self-use | ||
"""Function implementation""" | ||
|
||
import logging | ||
from resilient_circuits import ResilientComponent, function, handler, StatusMessage, FunctionResult, FunctionError | ||
from fn_ldap_utilities.util.helper import LDAPUtilitiesHelper | ||
from ast import literal_eval | ||
from ldap3.extend.microsoft.addMembersToGroups import ad_add_members_to_groups as ad_add_members_to_groups | ||
|
||
class FunctionComponent(ResilientComponent): | ||
"""Component that implements Resilient function 'ldap_utilities_add_to_groups""" | ||
|
||
def __init__(self, opts): | ||
"""constructor provides access to the configuration options""" | ||
super(FunctionComponent, self).__init__(opts) | ||
self.options = opts.get("fn_ldap_utilities", {}) | ||
|
||
@handler("reload") | ||
def _reload(self, event, opts): | ||
"""Configuration options have changed, save new values""" | ||
self.options = opts.get("fn_ldap_utilities", {}) | ||
|
||
@function("ldap_utilities_add_to_groups") | ||
def _ldap_utilities_add_to_groups_function(self, event, *args, **kwargs): | ||
"""Function: A function that allows adding multiple users to multiple groups""" | ||
log = logging.getLogger(__name__) | ||
try: | ||
yield StatusMessage("Starting ldap_utilities_add_to_groups") | ||
|
||
# Instansiate helper (which gets appconfigs from file) | ||
helper = LDAPUtilitiesHelper(self.options) | ||
yield StatusMessage("Appconfig Settings OK") | ||
|
||
# Get function inputs | ||
input_ldap_multiple_user_dn_asString = helper.get_function_input(kwargs, "ldap_multiple_user_dn") # text (required) [string repersentation of an array] | ||
input_ldap_multiple_group_dn_asString = helper.get_function_input(kwargs, "ldap_multiple_group_dn") # text (required) [string repersentation of an array] | ||
yield StatusMessage("Function Inputs OK") | ||
|
||
if not helper.LDAP_IS_ACTIVE_DIRECTORY: | ||
raise FunctionError("This function only supports an Active Directory connection. Make sure ldap_is_active_directory is set to True in the app.config file") | ||
|
||
try: | ||
# Try converting input to an array | ||
input_ldap_multiple_user_dn = literal_eval(input_ldap_multiple_user_dn_asString) | ||
input_ldap_multiple_group_dn = literal_eval(input_ldap_multiple_group_dn_asString) | ||
|
||
except Exception: | ||
raise ValueError("""input_ldap_multiple_user_dn and input_ldap_multiple_group_dn must be a string repersenation of an array e.g. "['dn=Accounts Group,dc=example,dc=com', 'dn=IT Group,dc=example,dc=com']" """) | ||
|
||
# Instansiate LDAP Server and Connection | ||
c = helper.get_ldap_connection() | ||
|
||
try: | ||
# Bind to the connection | ||
c.bind() | ||
except: | ||
raise ValueError("Cannot connect to LDAP Server. Ensure credentials are correct") | ||
|
||
# Inform user | ||
msg = "Connected to {0}".format("Active Directory") | ||
yield StatusMessage(msg) | ||
|
||
res = False | ||
|
||
try: | ||
yield StatusMessage("Attempting to add user(s) to group(s)") | ||
# perform the removeMermbersFromGroups operation | ||
res = ad_add_members_to_groups(c, input_ldap_multiple_user_dn, input_ldap_multiple_group_dn, True) | ||
|
||
except Exception: | ||
raise ValueError("Ensure all user and group DNs exist") | ||
|
||
finally: | ||
# Unbind connection | ||
c.unbind() | ||
|
||
results = { | ||
"success": res, | ||
"users_dn": input_ldap_multiple_user_dn, | ||
"groups_dn": input_ldap_multiple_group_dn | ||
} | ||
|
||
log.info("Completed") | ||
|
||
# Produce a FunctionResult with the results | ||
yield FunctionResult(results) | ||
except Exception: | ||
yield FunctionError() |
96 changes: 96 additions & 0 deletions
96
fn_ldap_utilities/fn_ldap_utilities/components/ldap_utilities_remove_from_groups.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
# -*- coding: utf-8 -*- | ||
# (c) Copyright IBM Corp. 2018. All Rights Reserved. | ||
# pragma pylint: disable=unused-argument, no-self-use | ||
"""Function implementation""" | ||
|
||
import logging | ||
from resilient_circuits import ResilientComponent, function, handler, StatusMessage, FunctionResult, FunctionError | ||
from fn_ldap_utilities.util.helper import LDAPUtilitiesHelper | ||
from ast import literal_eval | ||
from ldap3.extend.microsoft.removeMembersFromGroups import ad_remove_members_from_groups as ad_remove_members_from_groups | ||
|
||
class FunctionComponent(ResilientComponent): | ||
"""Component that implements Resilient function 'ldap_utilities_remove_from_groups""" | ||
|
||
def __init__(self, opts): | ||
"""constructor provides access to the configuration options""" | ||
super(FunctionComponent, self).__init__(opts) | ||
self.options = opts.get("fn_ldap_utilities", {}) | ||
|
||
@handler("reload") | ||
def _reload(self, event, opts): | ||
"""Configuration options have changed, save new values""" | ||
self.options = opts.get("fn_ldap_utilities", {}) | ||
|
||
@function("ldap_utilities_remove_from_groups") | ||
def _ldap_utilities_remove_from_groups_function(self, event, *args, **kwargs): | ||
"""Function: A function that allows you to remove multiple from multiple groups""" | ||
log = logging.getLogger(__name__) | ||
|
||
try: | ||
yield StatusMessage("Starting ldap_utilities_remove_from_groups") | ||
|
||
# Instansiate helper (which gets appconfigs from file) | ||
helper = LDAPUtilitiesHelper(self.options) | ||
yield StatusMessage("Appconfig Settings OK") | ||
|
||
# Get function inputs | ||
input_ldap_multiple_user_dn_asString = helper.get_function_input(kwargs, "ldap_multiple_user_dn") # text (required) [string repersentation of an array] | ||
input_ldap_multiple_group_dn_asString = helper.get_function_input(kwargs, "ldap_multiple_group_dn") # text (required) [string repersentation of an array] | ||
yield StatusMessage("Function Inputs OK") | ||
|
||
if not helper.LDAP_IS_ACTIVE_DIRECTORY: | ||
raise FunctionError("This function only supports an Active Directory connection. Make sure ldap_is_active_directory is set to True in the app.config file") | ||
|
||
try: | ||
# Try converting input to an array | ||
input_ldap_multiple_user_dn = literal_eval(input_ldap_multiple_user_dn_asString) | ||
input_ldap_multiple_group_dn = literal_eval(input_ldap_multiple_group_dn_asString) | ||
|
||
except Exception: | ||
raise ValueError("""input_ldap_multiple_user_dn and input_ldap_multiple_group_dn must be a string repersenation of an array e.g. "['dn=Accounts Group,dc=example,dc=com', 'dn=IT Group,dc=example,dc=com']" """) | ||
|
||
# Instansiate LDAP Server and Connection | ||
c = helper.get_ldap_connection() | ||
|
||
try: | ||
# Bind to the connection | ||
c.bind() | ||
except: | ||
raise ValueError("Cannot connect to LDAP Server. Ensure credentials are correct") | ||
|
||
# Inform user | ||
msg = "Connected to {0}".format("Active Directory") | ||
yield StatusMessage(msg) | ||
|
||
res = False | ||
users_dn = [] | ||
|
||
try: | ||
yield StatusMessage("Attempting to remove user(s) from group(s)") | ||
# perform the removeMermbersFromGroups operation | ||
res = ad_remove_members_from_groups(c, input_ldap_multiple_user_dn, input_ldap_multiple_group_dn, True) | ||
|
||
# Return list of users that were removed, and ignore users that do not exist, not valid, or not member of group | ||
if res and "changes" in c.request: | ||
users_dn = c.request["changes"][0]["attribute"]["value"] | ||
|
||
except Exception: | ||
raise ValueError("Ensure all group DNs exist") | ||
|
||
finally: | ||
# Unbind connection | ||
c.unbind() | ||
|
||
results = { | ||
"success": res, | ||
"users_dn": users_dn if len(users_dn) > 0 else None, | ||
"groups_dn": input_ldap_multiple_group_dn | ||
} | ||
|
||
log.info("Completed") | ||
|
||
# Produce a FunctionResult with the results | ||
yield FunctionResult(results) | ||
except Exception: | ||
yield FunctionError() |
Oops, something went wrong.