summaryrefslogtreecommitdiffstats
path: root/collections-debian-merged/ansible_collections/cyberark/pas/plugins
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-14 20:03:01 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-14 20:03:01 +0000
commita453ac31f3428614cceb99027f8efbdb9258a40b (patch)
treef61f87408f32a8511cbd91799f9cececb53e0374 /collections-debian-merged/ansible_collections/cyberark/pas/plugins
parentInitial commit. (diff)
downloadansible-a453ac31f3428614cceb99027f8efbdb9258a40b.tar.xz
ansible-a453ac31f3428614cceb99027f8efbdb9258a40b.zip
Adding upstream version 2.10.7+merged+base+2.10.8+dfsg.upstream/2.10.7+merged+base+2.10.8+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'collections-debian-merged/ansible_collections/cyberark/pas/plugins')
-rw-r--r--collections-debian-merged/ansible_collections/cyberark/pas/plugins/.DS_Storebin0 -> 6148 bytes
-rw-r--r--collections-debian-merged/ansible_collections/cyberark/pas/plugins/modules/.DS_Storebin0 -> 6148 bytes
-rw-r--r--collections-debian-merged/ansible_collections/cyberark/pas/plugins/modules/cyberark_account.py1378
-rw-r--r--collections-debian-merged/ansible_collections/cyberark/pas/plugins/modules/cyberark_authentication.py357
-rw-r--r--collections-debian-merged/ansible_collections/cyberark/pas/plugins/modules/cyberark_credential.py350
-rw-r--r--collections-debian-merged/ansible_collections/cyberark/pas/plugins/modules/cyberark_user.py619
6 files changed, 2704 insertions, 0 deletions
diff --git a/collections-debian-merged/ansible_collections/cyberark/pas/plugins/.DS_Store b/collections-debian-merged/ansible_collections/cyberark/pas/plugins/.DS_Store
new file mode 100644
index 00000000..22a721d7
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cyberark/pas/plugins/.DS_Store
Binary files differ
diff --git a/collections-debian-merged/ansible_collections/cyberark/pas/plugins/modules/.DS_Store b/collections-debian-merged/ansible_collections/cyberark/pas/plugins/modules/.DS_Store
new file mode 100644
index 00000000..5008ddfc
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cyberark/pas/plugins/modules/.DS_Store
Binary files differ
diff --git a/collections-debian-merged/ansible_collections/cyberark/pas/plugins/modules/cyberark_account.py b/collections-debian-merged/ansible_collections/cyberark/pas/plugins/modules/cyberark_account.py
new file mode 100644
index 00000000..65a3499a
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cyberark/pas/plugins/modules/cyberark_account.py
@@ -0,0 +1,1378 @@
+#!/usr/bin/python
+# Copyright: (c) 2017, Ansible Project
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+ANSIBLE_METADATA = {
+ "metadata_version": "1.1",
+ "status": ["preview"],
+ "supported_by": "community",
+}
+
+DOCUMENTATION = """
+---
+module: cyberark_account
+short_description: Module for CyberArk Account object creation, deletion, and
+ modification using PAS Web Services SDK.
+author:
+ - CyberArk BizDev (@cyberark-bizdev)
+ - Edward Nunez (@enunez-cyberark)
+ - James Stutes (@jimmyjamcabd)
+version_added: 2.4
+description:
+ - Creates a URI for adding, deleting, modifying a privileged credential
+ within the Cyberark Vault. The request uses the Privileged Account
+ Security Web Services SDK.
+
+
+options:
+ state:
+ description:
+ - Assert the desired state of the account C(present) to creat or
+ update and account object. Set to C(absent) for deletion of an
+ account object.
+ required: true
+ default: present
+ choices: [present, absent]
+ type: str
+ logging_level:
+ description:
+ - Parameter used to define the level of troubleshooting output to
+ the C(logging_file) value.
+ required: true
+ choices: [NOTSET, DEBUG, INFO]
+ type: str
+ logging_file:
+ description:
+ - Setting the log file name and location for troubleshooting logs.
+ required: false
+ default: /tmp/ansible_cyberark.log
+ type: str
+ api_base_url:
+ description:
+ - A string containing the base URL of the server hosting CyberArk's
+ Privileged Account Security Web Services SDK.
+ - Example U(https://<IIS_Server_Ip>/PasswordVault/api/)
+ required: true
+ type: str
+ validate_certs:
+ description:
+ - If C(false), SSL certificate chain will not be validated. This
+ should only set to C(true) if you have a root CA certificate
+ installed on each node.
+ required: false
+ default: true
+ type: bool
+ cyberark_session:
+ description:
+ - Dictionary set by a CyberArk authentication containing the
+ different values to perform actions on a logged-on CyberArk
+ session, please see M(cyberark_authentication) module for an
+ example of cyberark_session.
+ required: true
+ type: dict
+ identified_by:
+ description:
+ - When an API call is made to Get Accounts, often times the default
+ parameters passed will identify more than one account. This
+ parameter is used to confidently identify a single account when
+ the default query can return multiple results.
+ required: false
+ default: username,address,platform_id
+ type: str
+ safe:
+ description:
+ - The safe in the Vault where the privileged account is to be
+ located.
+ required: true
+ type: str
+ platform_id:
+ description:
+ - The PolicyID of the Platform that is to be managing the account
+ required: false
+ type: str
+ address:
+ description:
+ - The address of the endpoint where the privileged account is
+ located.
+ required: false
+ type: str
+ name:
+ description:
+ - The ObjectID of the account
+ required: false
+ type: str
+ secret_type:
+ description:
+ - The value that identifies what type of account it will be.
+ required: false
+ default: password
+ choices: [password, key]
+ type: str
+ secret:
+ description:
+ - The initial password for the creation of the account
+ required: false
+ type: str
+ new_secret:
+ description:
+ - The new secret/password to be stored in CyberArk Vault.
+ type: str
+ username:
+ description:
+ - The username associated with the account.
+ required: false
+ type: str
+ secret_management:
+ description:
+ - Set of parameters associated with the management of the
+ credential.
+ required: false
+ type: dict
+ suboptions:
+ automatic_management_enabled:
+ description:
+ - Parameter that indicates whether the CPM will manage
+ the password or not.
+ default: False
+ type: bool
+ manual_management_reason:
+ description:
+ - String value indicating why the CPM will NOT manage
+ the password.
+ type: str
+ management_action:
+ description:
+ - CPM action flag to be placed on the account object
+ for credential rotation.
+ choices: [change, change_immediately, reconcile]
+ type: str
+ new_secret:
+ description:
+ - The actual password value that will be assigned for
+ the CPM action to be taken.
+ type: str
+ perform_management_action:
+ description:
+ - C(always) will perform the management action in
+ every action.
+ - C(on_create) will only perform the management action
+ right after the account is created.
+ choices: [always, on_create]
+ default: always
+ type: str
+ remote_machines_access:
+ description:
+ - Set of parameters for defining PSM endpoint access targets.
+ required: false
+ type: dict
+ suboptions:
+ remote_machines:
+ description:
+ - List of targets allowed for this account.
+ type: str
+ access_restricted_to_remote_machines:
+ description:
+ - Whether or not to restrict access only to specified
+ remote machines.
+ type: bool
+ platform_account_properties:
+ description:
+ - Object containing key-value pairs to associate with the account,
+ as defined by the account platform. These properties are
+ validated against the mandatory and optional properties of the
+ specified platform's definition. Optional properties that do not
+ exist on the account will not be returned here. Internal
+ properties are not returned.
+ required: false
+ type: dict
+ suboptions:
+ KEY:
+ description:
+ - Freeform key value associated to the mandatory or
+ optional property assigned to the specified
+ Platform's definition.
+ aliases: [Port, ExtrPass1Name, database]
+ type: str
+"""
+
+EXAMPLES = """
+ collections:
+ - cyberark.pas
+
+ tasks:
+
+ - name: Logon to CyberArk Vault using PAS Web Services SDK
+ cyberark_authentication:
+ api_base_url: "http://components.cyberark.local"
+ validate_certs: no
+ username: "bizdev"
+ password: "Cyberark1"
+
+ - name: Creating an Account using the PAS WebServices SDK
+ cyberark_account:
+ logging_level: DEBUG
+ identified_by: "address,username"
+ safe: "Test"
+ address: "cyberark.local"
+ username: "administrator-x"
+ platform_id: WinServerLocal
+ secret: "@N&Ibl3!"
+ platform_account_properties:
+ LogonDomain: "cyberark"
+ OwnerName: "ansible_user"
+ secret_management:
+ automatic_management_enabled: true
+ state: present
+ cyberark_session: "{{ cyberark_session }}"
+ register: cyberarkaction
+
+ - name:
+ - Rotate credential via reconcile and providing the password to
+ bechanged to.
+ cyberark_account:
+ identified_by: "address,username"
+ safe: "Domain_Admins"
+ address: "prod.cyberark.local"
+ username: "admin"
+ platform_id: WinDomain
+ platform_account_properties:
+ LogonDomain: "PROD"
+ secret_management:
+ new_secret: "Ama123ah12@#!Xaamdjbdkl@#112"
+ management_action: "reconcile"
+ automatic_management_enabled: true
+ state: present
+ cyberark_session: "{{ cyberark_session }}"
+ register: reconcileaccount
+
+ - name: Logoff from CyberArk Vault
+ cyberark_authentication:
+ state: absent
+ cyberark_session: "{{ cyberark_session }}"
+
+"""
+RETURN = """
+changed:
+ description:
+ - Identify if the playbook run resulted in a change to the account in
+ any way.
+ returned: always
+ type: bool
+failed:
+ description: Whether playbook run resulted in a failure of any kind.
+ returned: always
+ type: bool
+status_code:
+ description: Result HTTP Status code.
+ returned: success
+ type: int
+ sample: "200, 201, -1, 204"
+result:
+ description: A json dump of the resulting action.
+ returned: success
+ type: complex
+ contains:
+ address:
+ description:
+ - The adress of the endpoint where the privileged account is
+ located.
+ returned: successful addition and modification
+ type: str
+ sample: dev.local
+ createdTime:
+ description:
+ - Timeframe calculation of the timestamp of account creation.
+ returned: successful addition and modification
+ type: int
+ sample: "1567824520"
+ id:
+ description: Internal ObjectID for the account object identified
+ returned: successful addition and modification
+ type: int
+ sample: "25_21"
+ name:
+ description: The external ObjectID of the account
+ returned: successful addition and modification
+ type: str
+ sample:
+ - Operating System-WinServerLocal-cyberark.local-administrator
+ platformAccountProperties:
+ description:
+ - Object containing key-value pairs to associate with the
+ account, as defined by the account platform.
+ returned: successful addition and modification
+ type: complex
+ contains:
+ KEY VALUE:
+ description:
+ - Object containing key-value pairs to associate with the
+ account, as defined by the account platform.
+ returned: successful addition and modification
+ type: str
+ sample:
+ - "LogonDomain": "cyberark"
+ - "Port": "22"
+ platformId:
+ description:
+ - The PolicyID of the Platform that is to be managing the
+ account.
+ returned: successful addition and modification
+ type: str
+ sample: WinServerLocal
+ safeName:
+ description:
+ - The safe in the Vault where the privileged account is to
+ be located.
+ returned: successful addition and modification
+ type: str
+ sample: Domain_Admins
+ secretManagement:
+ description:
+ - Set of parameters associated with the management of
+ the credential.
+ returned: successful addition and modification
+ type: complex
+ sample:
+ automaticManagementEnabled:
+ description:
+ - Parameter that indicates whether the CPM will manage
+ the password or not.
+ returned: successful addition and modification
+ type: bool
+ lastModifiedTime:
+ description:
+ - Timeframe calculation of the timestamp of account
+ modification.
+ returned: successful addition and modification
+ type: int
+ sample: "1567824520"
+ manualManagementReason:
+ description:
+ returned: if C(automaticManagementEnabled) is set to false
+ type: str
+ sample: This is a static account
+ secretType:
+ description:
+ - The value that identifies what type of account it will be
+ returned: successful addition and modification
+ type: list
+ sample:
+ - key
+ - password
+ userName:
+ description: The username associated with the account
+ returned: successful addition and modification
+ type: str
+ sample: administrator
+"""
+
+
+from ansible.module_utils._text import to_text
+from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils.urls import open_url
+from ansible.module_utils.six.moves.urllib.error import HTTPError
+import urllib
+
+import json
+try:
+ import httplib
+except ImportError:
+ # Python 3
+ import http.client as httplib
+import logging
+
+_empty = object()
+
+ansible_specific_parameters = [
+ "state",
+ "api_base_url",
+ "validate_certs",
+ "cyberark_session",
+ "identified_by",
+ "logging_level",
+ "logging_file",
+ "new_secret",
+ "secret_management.management_action",
+ "secret_management.new_secret",
+ "management_action",
+ "secret_management.perform_management_action",
+]
+
+cyberark_fixed_properties = [
+ "createdTime",
+ "id",
+ "name",
+ "lastModifiedTime",
+ "safeName",
+ "secretType",
+ "secret",
+]
+
+removal_value = "NO_VALUE"
+
+cyberark_reference_fieldnames = {
+ "username": "userName",
+ "safe": "safeName",
+ "platform_id": "platformId",
+ "secret_type": "secretType",
+ "platform_account_properties": "platformAccountProperties",
+ "secret_management": "secretManagement",
+ "manual_management_reason": "manualManagementReason",
+ "automatic_management_enabled": "automaticManagementEnabled",
+ "remote_machines_access": "remoteMachinesAccess",
+ "access_restricted_to_remote_machines": "accessRestrictedToRemoteMachines",
+ "remote_machines": "remoteMachines",
+}
+
+ansible_reference_fieldnames = {
+ "userName": "username",
+ "safeName": "safe",
+ "platformId": "platform_id",
+ "secretType": "secret_type",
+ "platformAccountProperties": "platform_account_properties",
+ "secretManagement": "secret_management",
+ "manualManagementReason": "manual_management_reason",
+ "automaticManagementEnabled": "automatic_management_enabled",
+ "remoteMachinesAccess": "remote_machines_access",
+ "accessRestrictedToRemoteMachines": "access_testricted_to_remoteMachines",
+ "remoteMachines": "remote_machines",
+}
+
+
+def equal_value(existing, parameter):
+ if isinstance(existing, str):
+ return existing == str(parameter)
+ elif isinstance(parameter, str):
+ return str(existing) == parameter
+ else:
+ return existing == parameter
+
+
+def update_account(module, existing_account):
+
+ logging.debug("Updating Account")
+
+ cyberark_session = module.params["cyberark_session"]
+ api_base_url = cyberark_session["api_base_url"]
+ validate_certs = cyberark_session["validate_certs"]
+
+ # Prepare result, end_point, and headers
+ result = {"result": existing_account}
+ changed = False
+ last_status_code = -1
+
+ HTTPMethod = "PATCH"
+ end_point = "/PasswordVault/api/Accounts/%s" % existing_account["id"]
+
+ headers = {
+ "Content-Type": "application/json",
+ "Authorization": cyberark_session["token"],
+ }
+
+ payload = {"Operations": []}
+
+ # Determining whether to add or update properties
+ for parameter_name in module.params.keys():
+ if (
+ parameter_name not in ansible_specific_parameters
+ and module.params[parameter_name] is not None
+ ):
+ module_parm_value = module.params[parameter_name]
+ cyberark_property_name = referenced_value(
+ parameter_name,
+ cyberark_reference_fieldnames,
+ default=parameter_name
+ )
+ existing_account_value = referenced_value(
+ cyberark_property_name,
+ existing_account,
+ keys=existing_account.keys()
+ )
+ if cyberark_property_name not in cyberark_fixed_properties:
+ if module_parm_value is not None and isinstance(
+ module_parm_value, dict
+ ):
+ # Internal child values
+ replacing = {}
+ adding = {}
+ removing = {}
+ for child_parm_name in module_parm_value.keys():
+ nested_parm_name = "%s.%s" % (
+ parameter_name,
+ child_parm_name)
+ if (
+ nested_parm_name not in ansible_specific_parameters
+ ):
+ child_module_parm_value = module_parm_value[
+ child_parm_name
+ ]
+ child_cyberark_property_name = referenced_value(
+ child_parm_name,
+ cyberark_reference_fieldnames,
+ default=child_parm_name,
+ )
+ child_existing_account_value = referenced_value(
+ child_cyberark_property_name,
+ existing_account_value,
+ existing_account_value.keys()
+ if existing_account_value is not None
+ else {},
+ )
+ path_value = "/%s/%s" % (
+ cyberark_property_name,
+ child_cyberark_property_name,
+ )
+ if child_existing_account_value is not None:
+ logging.debug(
+ ("child_module_parm_value: %s "
+ "child_existing_account_value=%s path=%s")
+ (
+ child_module_parm_value,
+ child_existing_account_value,
+ path_value,
+ )
+ )
+ if child_module_parm_value == removal_value:
+ removing.update(
+ {
+ child_cyberark_property_name:
+ child_existing_account_value
+ }
+ )
+ elif (
+ child_module_parm_value is not None
+ and not equal_value(
+ child_existing_account_value,
+ child_module_parm_value,
+ )
+ ):
+ # Updating a property
+ replacing.update(
+ {
+ child_cyberark_property_name:
+ child_module_parm_value
+ }
+ )
+ elif (
+ child_module_parm_value is not None
+ and child_module_parm_value != removal_value
+ ):
+ # Adding a property value
+ adding.update(
+ {
+ child_cyberark_property_name:
+ child_module_parm_value
+ }
+ )
+ logging.debug(
+ "parameter_name=%s value=%s existing=%s"
+ (
+ path_value,
+ child_module_parm_value,
+ child_existing_account_value,
+ )
+ )
+ # Processing child operations
+ if len(adding.keys()) > 0:
+ payload["Operations"].append(
+ {
+ "op": "add",
+ "path": "/%s" % cyberark_property_name,
+ "value": adding,
+ }
+ )
+ if len(replacing.keys()) > 0:
+ payload["Operations"].append(
+ {
+ "op": "replace",
+ "path": "/%s" % cyberark_property_name,
+ "value": replacing,
+ }
+ )
+ if len(removing) > 0:
+ payload["Operations"].append(
+ {
+ "op": "remove",
+ "path": "/%s" % cyberark_property_name,
+ "value": removing,
+ }
+ )
+ else:
+ if existing_account_value is not None:
+ if module_parm_value == removal_value:
+ payload["Operations"].append(
+ {"op": "remove", "path": "/%s" %
+ cyberark_property_name}
+ )
+ elif not equal_value(
+ existing_account_value,
+ module_parm_value
+ ):
+ # Updating a property
+ payload["Operations"].append(
+ {
+ "op": "replace",
+ "value": module_parm_value,
+ "path": "/%s" % cyberark_property_name,
+ }
+ )
+ elif module_parm_value != removal_value:
+ # Adding a property value
+ payload["Operations"].append(
+ {
+ "op": "add",
+ "value": module_parm_value,
+ "path": "/%s" % cyberark_property_name,
+ }
+ )
+ logging.debug(
+ "parameter_name=%s value=%s existing=%s"
+ (
+ parameter_name, module_parm_value,
+ existing_account_value
+ )
+ )
+
+ if len(payload["Operations"]) != 0:
+ if module.check_mode:
+ logging.debug("Proceeding with Update Account (CHECK_MODE)")
+ logging.debug("Operations => %s", json.dumps(payload))
+ result = {"result": existing_account}
+ changed = True
+ last_status_code = -1
+ else:
+ logging.debug("Proceeding with Update Account")
+
+ logging.debug(
+ "Processing invidual operations (%d) => %s",
+ len(payload["Operations"]),
+ json.dumps(payload)
+ )
+ for operation in payload["Operations"]:
+ individual_payload = [operation]
+ try:
+ logging.debug(" ==> %s", json.dumps([operation]))
+ response = open_url(
+ api_base_url + end_point,
+ method=HTTPMethod,
+ headers=headers,
+ data=json.dumps(individual_payload),
+ validate_certs=validate_certs,
+ )
+
+ result = {"result": json.loads(response.read())}
+ changed = True
+ last_status_code = response.getcode()
+
+ # return (True, result, response.getcode())
+
+ except (HTTPError, httplib.HTTPException) as http_exception:
+
+ if isinstance(http_exception, HTTPError):
+ res = json.load(http_exception)
+ else:
+ res = to_text(http_exception)
+
+ module.fail_json(
+ msg=(
+ "Error while performing update_account."
+ "Please validate parameters provided."
+ "\n*** end_point=%s%s\n ==> %s"
+ % (api_base_url, end_point, res)
+ ),
+ payload=individual_payload,
+ headers=headers,
+ status_code=http_exception.code,
+ )
+
+ except Exception as unknown_exception:
+
+ module.fail_json(
+ msg=(
+ "Unknown error while performing update_account."
+ "\n*** end_point=%s%s\n%s"
+ % (
+ api_base_url, end_point,
+ to_text(unknown_exception)
+ )
+ ),
+ payload=individual_payload,
+ headers=headers,
+ status_code=-1,
+ )
+
+ return (changed, result, last_status_code)
+
+
+def add_account(module):
+
+ logging.debug("Adding Account")
+
+ cyberark_session = module.params["cyberark_session"]
+ api_base_url = cyberark_session["api_base_url"]
+ validate_certs = cyberark_session["validate_certs"]
+
+ # Prepare result, end_point, and headers
+ result = {}
+ HTTPMethod = "POST"
+ end_point = "/PasswordVault/api/Accounts"
+
+ headers = {
+ "Content-Type": "application/json",
+ "Authorization": cyberark_session["token"],
+ }
+
+ payload = {"safeName": module.params["safe"]}
+
+ for parameter_name in module.params.keys():
+ if (
+ parameter_name not in ansible_specific_parameters
+ and module.params[parameter_name] is not None
+ ):
+ cyberark_property_name = referenced_value(
+ parameter_name,
+ cyberark_reference_fieldnames,
+ default=parameter_name
+ )
+ if isinstance(module.params[parameter_name], dict):
+ payload[cyberark_property_name] = {}
+ for dict_key in module.params[parameter_name].keys():
+ cyberark_child_property_name = referenced_value(
+ dict_key,
+ cyberark_reference_fieldnames,
+ default=dict_key
+ )
+ logging.debug(
+ ("parameter_name =%s.%s cyberark_property_name=%s "
+ "cyberark_child_property_name=%s"),
+ parameter_name,
+ dict_key,
+ cyberark_property_name,
+ cyberark_child_property_name,
+ )
+ if (
+ parameter_name + "." + dict_key
+ not in ansible_specific_parameters
+ and module.params[parameter_name][dict_key] is not None
+ ):
+ payload[cyberark_property_name][
+ cyberark_child_property_name
+ ] = deep_get(
+ module.params[parameter_name],
+ dict_key,
+ _empty,
+ False
+ )
+ else:
+ if parameter_name not in cyberark_reference_fieldnames:
+ module_parm_value = deep_get(
+ module.params, parameter_name, _empty, False
+ )
+ if (
+ module_parm_value is not None
+ and module_parm_value != removal_value
+ ):
+ payload[
+ parameter_name
+ ] = module_parm_value # module.params[parameter_name]
+ else:
+ module_parm_value = deep_get(
+ module.params, parameter_name, _empty, True
+ )
+ if (
+ module_parm_value is not None
+ and module_parm_value != removal_value
+ ):
+ payload[
+ cyberark_reference_fieldnames[parameter_name]
+ ] = module_parm_value # module.params[parameter_name]
+ logging.debug("parameter_name =%s", parameter_name)
+
+ logging.debug("Add Account Payload => %s", json.dumps(payload))
+
+ try:
+
+ if module.check_mode:
+ logging.debug("Proceeding with Add Account (CHECK_MODE)")
+ return (True, {"result": None}, -1)
+ else:
+ logging.debug("Proceeding with Add Account")
+ response = open_url(
+ api_base_url + end_point,
+ method=HTTPMethod,
+ headers=headers,
+ data=json.dumps(payload),
+ validate_certs=validate_certs,
+ )
+
+ result = {"result": json.loads(response.read())}
+
+ return (True, result, response.getcode())
+
+ except (HTTPError, httplib.HTTPException) as http_exception:
+
+ if isinstance(http_exception, HTTPError):
+ res = json.load(http_exception)
+ else:
+ res = to_text(http_exception)
+
+ module.fail_json(
+ msg=(
+ "Error while performing add_account."
+ "Please validate parameters provided."
+ "\n*** end_point=%s%s\n ==> %s" % (
+ api_base_url,
+ end_point,
+ res
+ )
+ ),
+ payload=payload,
+ headers=headers,
+ status_code=http_exception.code,
+ )
+
+ except Exception as unknown_exception:
+
+ module.fail_json(
+ msg=(
+ "Unknown error while performing add_account."
+ "\n*** end_point=%s%s\n%s"
+ % (api_base_url, end_point, to_text(unknown_exception))
+ ),
+ payload=payload,
+ headers=headers,
+ status_code=-1,
+ )
+
+
+def delete_account(module, existing_account):
+
+ if module.check_mode:
+ logging.debug("Deleting Account (CHECK_MODE)")
+ return (True, {"result": None}, -1)
+ else:
+ logging.debug("Deleting Account")
+
+ cyberark_session = module.params["cyberark_session"]
+ api_base_url = cyberark_session["api_base_url"]
+ validate_certs = cyberark_session["validate_certs"]
+
+ # Prepare result, end_point, and headers
+ result = {}
+ HTTPMethod = "DELETE"
+ end_point = "/PasswordVault/api/Accounts/%s" % existing_account["id"]
+
+ headers = {
+ "Content-Type": "application/json",
+ "Authorization": cyberark_session["token"],
+ }
+
+ try:
+
+ response = open_url(
+ api_base_url + end_point,
+ method=HTTPMethod,
+ headers=headers,
+ validate_certs=validate_certs,
+ )
+
+ result = {"result": None}
+
+ return (True, result, response.getcode())
+
+ except (HTTPError, httplib.HTTPException) as http_exception:
+
+ if isinstance(http_exception, HTTPError):
+ res = json.load(http_exception)
+ else:
+ res = to_text(http_exception)
+
+ module.fail_json(
+ msg=(
+ "Error while performing delete_account."
+ "Please validate parameters provided."
+ "\n*** end_point=%s%s\n ==> %s" % (
+ api_base_url,
+ end_point,
+ res
+ )
+ ),
+ headers=headers,
+ status_code=http_exception.code,
+ )
+
+ except Exception as unknown_exception:
+
+ module.fail_json(
+ msg=(
+ "Unknown error while performing delete_account."
+ "\n*** end_point=%s%s\n%s"
+ % (api_base_url, end_point, to_text(unknown_exception))
+ ),
+ headers=headers,
+ status_code=-1,
+ )
+
+
+def reset_account_if_needed(module, existing_account):
+
+ cyberark_session = module.params["cyberark_session"]
+ api_base_url = cyberark_session["api_base_url"]
+ validate_certs = cyberark_session["validate_certs"]
+
+ # Credential changes
+ management_action = deep_get(
+ module.params,
+ "secret_management.management_action",
+ "NOT_FOUND",
+ False
+ )
+ cpm_new_secret = deep_get(
+ module.params, "secret_management.new_secret", "NOT_FOUND", False
+ )
+ logging.debug(
+ "management_action: %s cpm_new_secret: %s",
+ management_action,
+ cpm_new_secret
+ )
+
+ # Prepare result, end_point, and headers
+ result = {}
+ end_point = None
+ payload = {}
+ existing_account_id = None
+ if existing_account is not None:
+ existing_account_id = existing_account["id"]
+ elif module.check_mode:
+ existing_account_id = 9999
+
+ if (
+ management_action == "change"
+ and cpm_new_secret is not None
+ and cpm_new_secret != "NOT_FOUND"
+ ):
+ logging.debug("CPM change secret for next CPM cycle")
+ end_point = (
+ "/PasswordVault/API/Accounts/%s/SetNextPassword"
+ ) % existing_account_id
+ payload["ChangeImmediately"] = False
+ payload["NewCredentials"] = cpm_new_secret
+ elif management_action == "change_immediately" and (
+ cpm_new_secret == "NOT_FOUND" or cpm_new_secret is None
+ ):
+ logging.debug("CPM change_immediately with random secret")
+ end_point = (
+ "/PasswordVault/API/Accounts/%s/Change"
+ ) % existing_account_id
+ payload["ChangeEntireGroup"] = True
+ elif management_action == "change_immediately" and (
+ cpm_new_secret is not None and cpm_new_secret != "NOT_FOUND"
+ ):
+ logging.debug("CPM change immediately secret for next CPM cycle")
+ end_point = (
+ "/PasswordVault/API/Accounts/%s/SetNextPassword"
+ ) % existing_account_id
+ payload["ChangeImmediately"] = True
+ payload["NewCredentials"] = cpm_new_secret
+ elif management_action == "reconcile":
+ logging.debug("CPM reconcile secret")
+ end_point = (
+ "/PasswordVault/API/Accounts/%s/Reconcile"
+ ) % existing_account_id
+ elif (
+ "new_secret" in module.params.keys()
+ and module.params["new_secret"] is not None
+ ):
+ logging.debug("Change Credential in Vault")
+ end_point = (
+ "/PasswordVault/API/Accounts/%s/Password/Update"
+ ) % existing_account_id
+ payload["ChangeEntireGroup"] = True
+ payload["NewCredentials"] = module.params["new_secret"]
+
+ if end_point is not None:
+
+ if module.check_mode:
+ logging.debug("Proceeding with Credential Rotation (CHECK_MODE)")
+ return (True, result, -1)
+ else:
+ logging.debug("Proceeding with Credential Rotation")
+
+ result = {"result": None}
+ headers = {
+ "Content-Type": "application/json",
+ "Authorization": cyberark_session["token"],
+ }
+ HTTPMethod = "POST"
+ try:
+
+ response = open_url(
+ api_base_url + end_point,
+ method=HTTPMethod,
+ headers=headers,
+ data=json.dumps(payload),
+ validate_certs=validate_certs,
+ )
+
+ return (True, result, response.getcode())
+
+ except (HTTPError, httplib.HTTPException) as http_exception:
+
+ if isinstance(http_exception, HTTPError):
+ res = json.load(http_exception)
+ else:
+ res = to_text(http_exception)
+
+ module.fail_json(
+ msg=(
+ "Error while performing reset_account."
+ "Please validate parameters provided."
+ "\n*** end_point=%s%s\n ==> %s"
+ ) % (api_base_url, end_point, res),
+ headers=headers,
+ payload=payload,
+ status_code=http_exception.code,
+ )
+
+ except Exception as unknown_exception:
+
+ module.fail_json(
+ msg=(
+ "Unknown error while performing delete_account."
+ "\n*** end_point=%s%s\n%s"
+ % (api_base_url, end_point, to_text(unknown_exception))
+ ),
+ headers=headers,
+ payload=payload,
+ status_code=-1,
+ )
+
+ else:
+ return (False, result, -1)
+
+
+def referenced_value(field, dct, keys=None, default=None):
+ return dct[field] if field in (
+ keys if keys is not None else dct
+ ) else default
+
+
+def deep_get(dct, dotted_path, default=_empty, use_reference_table=True):
+ result_dct = {}
+ for key in dotted_path.split("."):
+ try:
+ key_field = key
+ if use_reference_table:
+ key_field = referenced_value(
+ key, cyberark_reference_fieldnames, default=key
+ )
+
+ if len(result_dct.keys()) == 0: # No result_dct set yet
+ result_dct = dct
+
+ logging.debug(
+ "keys=%s key_field=>%s key=>%s",
+ ",".join(result_dct.keys()),
+ key_field,
+ key
+ )
+ result_dct = (
+ result_dct[key_field]
+ if key_field in result_dct.keys()
+ else result_dct[key]
+ )
+ if result_dct is None:
+ return default
+
+ except KeyError as e:
+ logging.debug("KeyError %s", to_text(e))
+ if default is _empty:
+ raise
+ return default
+ return result_dct
+
+
+def get_account(module):
+
+ logging.debug("Finding Account")
+
+ identified_by_fields = module.params["identified_by"].split(",")
+ logging.debug("Identified_by: %s", json.dumps(identified_by_fields))
+ safe_filter = (
+ urllib.quote("safeName eq ") + urllib.quote(module.params["safe"])
+ if "safe" in module.params and module.params["safe"] is not None
+ else None
+ )
+ search_string = None
+ for field in identified_by_fields:
+ if field not in ansible_specific_parameters:
+ search_string = "%s%s" % (
+ search_string + " " if search_string is not None else "",
+ deep_get(module.params, field, "NOT FOUND", False),
+ )
+
+ logging.debug("Search_String => %s", search_string)
+ logging.debug("Safe Filter => %s", safe_filter)
+
+ cyberark_session = module.params["cyberark_session"]
+ api_base_url = cyberark_session["api_base_url"]
+ validate_certs = cyberark_session["validate_certs"]
+
+ end_point = None
+ if search_string is not None and safe_filter is not None:
+ end_point = "/PasswordVault/api/accounts?filter=%s&search=%s" % (
+ safe_filter,
+ urllib.quote(search_string.lstrip()),
+ )
+ elif search_string is not None:
+ end_point = (
+ "/PasswordVault/api/accounts?search=%s"
+ ) % (search_string.lstrip())
+ else:
+ end_point = "/PasswordVault/api/accounts?filter=%s" % (safe_filter)
+
+ logging.debug("End Point => %s", end_point)
+
+ headers = {"Content-Type": "application/json"}
+ headers["Authorization"] = cyberark_session["token"]
+
+ try:
+
+ logging.debug("Executing: " + api_base_url + end_point)
+ response = open_url(
+ api_base_url + end_point,
+ method="GET",
+ headers=headers,
+ validate_certs=validate_certs,
+ )
+
+ result_string = response.read()
+ accounts_data = json.loads(result_string)
+
+ logging.debug("RESULT => %s", json.dumps(accounts_data))
+
+ if accounts_data["count"] == 0:
+ return (False, None, response.getcode())
+ else:
+ how_many = 0
+ first_record_found = None
+ for account_record in accounts_data["value"]:
+ logging.debug("Acct Record => %s", json.dumps(account_record))
+ found = False
+ for field in identified_by_fields:
+ record_field_value = deep_get(
+ account_record,
+ field,
+ "NOT FOUND"
+ )
+ logging.debug(
+ (
+ "Comparing field %s | record_field_name=%s "
+ "record_field_value=%s module.params_value=%s"
+ ),
+ field,
+ field,
+ record_field_value,
+ deep_get(module.params, field, "NOT FOUND")
+ )
+ if (
+ record_field_value != "NOT FOUND"
+ and (
+ record_field_value
+ == deep_get(
+ module.params,
+ field,
+ "NOT FOUND",
+ False
+ )
+ )
+ ):
+ found = True
+ else:
+ found = False
+ break
+ if found:
+ how_many = how_many + 1
+ if first_record_found is None:
+ first_record_found = account_record
+
+ logging.debug(
+ "How Many: %d First Record Found => %s",
+ how_many,
+ json.dumps(first_record_found)
+ )
+ if how_many > 1: # too many records found
+ module.fail_json(
+ msg=(
+ "Error while performing get_account. "
+ "Too many rows (%d) found matching your criteria!"
+ ) % how_many
+ )
+ else:
+ return (how_many == 1, first_record_found, response.getcode())
+
+ except (HTTPError, httplib.HTTPException) as http_exception:
+
+ if http_exception.code == 404:
+ return (False, None, http_exception.code)
+ else:
+ module.fail_json(
+ msg=(
+ "Error while performing get_account."
+ "Please validate parameters provided."
+ "\n*** end_point=%s%s\n ==> %s"
+ % (api_base_url, end_point, to_text(http_exception))
+ ),
+ headers=headers,
+ status_code=http_exception.code,
+ )
+
+ except Exception as unknown_exception:
+
+ module.fail_json(
+ msg=(
+ "Unknown error while performing get_account."
+ "\n*** end_point=%s%s\n%s"
+ % (api_base_url, end_point, to_text(unknown_exception))
+ ),
+ headers=headers,
+ status_code=-1,
+ )
+
+
+def main():
+
+ fields = {
+ "state": {
+ "type": "str",
+ "choices": ["present", "absent"],
+ "default": "present",
+ },
+ "logging_level": {
+ "type": "str",
+ "choices": ["NOTSET", "DEBUG", "INFO"]
+ },
+ "logging_file": {
+ "type": "str",
+ "default": "/tmp/ansible_cyberark.log"
+ },
+ "api_base_url": {"type": "str"},
+ "validate_certs": {"type": "bool", "default": "true"},
+ "cyberark_session": {"required": True, "type": "dict", "no_log": True},
+ "identified_by": {
+ "required": False,
+ "type": "str",
+ "default": "username,address,platform_id",
+ },
+ "safe": {"required": True, "type": "str"},
+ "platform_id": {"required": False, "type": "str"},
+ "address": {"required": False, "type": "str"},
+ "name": {"required": False, "type": "str"},
+ "secret_type": {
+ "required": False,
+ "type": "str",
+ "choices": ["password", "key"],
+ "default": "password",
+ },
+ "secret": {"required": False, "type": "str", "no_log": True},
+ "new_secret": {"required": False, "type": "str", "no_log": True},
+ "username": {"required": False, "type": "str"},
+ "secret_management": {
+ "required": False,
+ "type": "dict",
+ "options": {
+ "automatic_management_enabled": {"type": "bool"},
+ "manual_management_reason": {"type": "str"},
+ "management_action": {
+ "type": "str",
+ "choices": ["change", "change_immediately", "reconcile"],
+ },
+ "new_secret": {"type": "str", "no_log": True},
+ "perform_management_action": {
+ "type": "str",
+ "choices": ["on_create", "always"],
+ "default": "always",
+ },
+ },
+ },
+ "remote_machines_access": {
+ "required": False,
+ "type": "dict",
+ "options": {
+ "remote_machines": {"type": "str"},
+ "access_restricted_to_remote_machines": {"type": "bool"},
+ },
+ },
+ "platform_account_properties": {"required": False, "type": "dict"},
+ }
+
+ module = AnsibleModule(argument_spec=fields, supports_check_mode=True)
+
+ if module.params["logging_level"] is not None:
+ logging.basicConfig(
+ filename=module.params["logging_file"],
+ level=module.params["logging_level"]
+ )
+
+ logging.info("Starting Module")
+
+ state = module.params["state"]
+
+ (found, account_record, status_code) = get_account(module)
+ logging.debug(
+ "Account was %s, status_code=%s",
+ "FOUND" if found else "NOT FOUND",
+ status_code
+ )
+
+ changed = False
+ result = {"result": account_record}
+
+ if state == "present":
+
+ if found: # Account already exists
+ (changed, result, status_code) = update_account(
+ module,
+ account_record
+ )
+ else: # Account does not exist
+ (changed, result, status_code) = add_account(module)
+
+ perform_management_action = "always"
+ if "secret_management" in module.params.keys():
+ secret_management = module.params["secret_management"]
+ if (
+ secret_management is not None
+ and "perform_management_action" in secret_management.keys()
+ ):
+ perform_management_action = secret_management[
+ "perform_management_action"
+ ]
+
+ logging.debug("Result=>%s", json.dumps(result))
+ if (
+ perform_management_action == "always"
+ or (
+ perform_management_action == "on_create" and not found
+ )
+ ):
+ (account_reset, no_result, no_status_code) = reset_account_if_needed(
+ module,
+ result["result"]
+ )
+ if account_reset:
+ changed = True
+
+ elif found and state == "absent":
+ (changed, result, status_code) = delete_account(module, account_record)
+
+ module.exit_json(changed=changed, result=result, status_code=status_code)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cyberark/pas/plugins/modules/cyberark_authentication.py b/collections-debian-merged/ansible_collections/cyberark/pas/plugins/modules/cyberark_authentication.py
new file mode 100644
index 00000000..324abf65
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cyberark/pas/plugins/modules/cyberark_authentication.py
@@ -0,0 +1,357 @@
+#!/usr/bin/python
+# Copyright: (c) 2017, Ansible Project
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+ANSIBLE_METADATA = {
+ "metadata_version": "1.1",
+ "status": ["preview"],
+ "supported_by": "certified",
+}
+
+DOCUMENTATION = '''
+---
+module: cyberark_authentication
+short_description: CyberArk Authentication using PAS Web Services SDK.
+author:
+ - Edward Nunez (@enunez-cyberark) CyberArk BizDev
+ - Cyberark Bizdev (@cyberark-bizdev)
+ - Erasmo Acosta (@erasmix)
+version_added: 2.4
+description:
+ - Authenticates to CyberArk Vault using Privileged Account Security
+ Web Services SDK and creates a session fact that can be used by other
+ modules. It returns an Ansible fact called I(cyberark_session). Every
+ module can use this fact as C(cyberark_session) parameter.
+options:
+ state:
+ default: present
+ choices: [present, absent]
+ description:
+ - Specifies if an authentication logon/logoff and a
+ cyberark_session should be added/removed.
+ type: str
+ username:
+ description:
+ - The name of the user who will logon to the Vault.
+ type: str
+ password:
+ description:
+ - The password of the user.
+ type: str
+ new_password:
+ description:
+ - The new password of the user. This parameter is optional,
+ and enables you to change a password.
+ type: str
+ api_base_url:
+ description:
+ - A string containing the base URL of the server hosting
+ CyberArk's Privileged Account Security Web Services SDK.
+ type: str
+ validate_certs:
+ type: bool
+ default: 'yes'
+ description:
+ - If C(false), SSL certificates will not be validated. This
+ should only set to C(false) used on personally controlled
+ sites using self-signed certificates.
+ use_shared_logon_authentication:
+ type: bool
+ default: 'no'
+ description:
+ - Whether or not Shared Logon Authentication will be used.
+ use_radius_authentication:
+ type: bool
+ default: 'no'
+ description:
+ - Whether or not users will be authenticated via a RADIUS
+ server. Valid values are true/false.
+ connection_number:
+ type: int
+ description:
+ - To support multiple connections for same user specify
+ - different value for this parameter.
+ cyberark_session:
+ description:
+ - Dictionary set by a CyberArk authentication containing the
+ different values to perform actions on a logged-on CyberArk
+ session.
+ type: dict
+'''
+
+EXAMPLES = '''
+- name: Logon - use_shared_logon_authentication
+ cyberark_authentication:
+ api_base_url: "{{ web_services_base_url }}"
+ use_shared_logon_authentication: yes
+
+- name: Logon - Not use_shared_logon_authentication
+ cyberark_authentication:
+ api_base_url: "{{ web_services_base_url }}"
+ username: "{{ password_object.password }}"
+ password: "{{ password_object.passprops.username }}"
+ use_shared_logon_authentication: no
+
+- name: Logoff from CyberArk Vault
+ cyberark_authentication:
+ state: absent
+ cyberark_session: "{{ cyberark_session }}"
+'''
+
+RETURN = '''
+cyberark_session:
+ description: Authentication facts.
+ returned: success
+ type: complex
+ contains:
+ api_base_url:
+ description:
+ - Base URL for API calls. Returned in the cyberark_session,
+ so it can be used in subsequent calls.
+ type: str
+ returned: always
+ token:
+ description:
+ - The token that identifies the session, encoded in BASE 64.
+ type: str
+ returned: always
+ use_shared_logon_authentication:
+ description:
+ - Whether or not Shared Logon Authentication was used to
+ establish the session.
+ type: bool
+ returned: always
+ validate_certs:
+ description: Whether or not SSL certificates should be validated.
+ type: bool
+ returned: always
+'''
+
+from ansible.module_utils._text import to_text
+from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils.urls import open_url
+from ansible.module_utils.six.moves.urllib.error import HTTPError
+import json
+
+try:
+ import httplib
+except ImportError:
+ # Python 3
+ import http.client as httplib
+
+
+def processAuthentication(module):
+
+ # Getting parameters from module
+
+ api_base_url = module.params["api_base_url"]
+ validate_certs = module.params["validate_certs"]
+ username = module.params["username"]
+ password = module.params["password"]
+ new_password = module.params["new_password"]
+ use_shared_logon = module.params[
+ "use_shared_logon_authentication"
+ ]
+ use_radius = module.params["use_radius_authentication"]
+ connection_number = module.params["connection_number"]
+ state = module.params["state"]
+ cyberark_session = module.params["cyberark_session"]
+
+ # if in check mode it will not perform password changes
+ if module.check_mode and new_password is not None:
+ new_password = None
+
+ # Defining initial values for open_url call
+ headers = {"Content-Type": "application/json"}
+ payload = ""
+
+ if state == "present": # Logon Action
+
+ # Different end_points based on the use of shared logon authentication
+ if use_shared_logon:
+
+ end_point = ("/PasswordVault/WebServices/auth/Shared"
+ "/RestfulAuthenticationService.svc/Logon")
+
+ else:
+
+ end_point = ("/PasswordVault/WebServices/auth/Cyberark"
+ "/CyberArkAuthenticationService.svc/Logon")
+
+ # The payload will contain username, password
+ # and optionally use_radius_authentication and new_password
+ payload_dict = {"username": username, "password": password}
+
+ if use_radius:
+ payload_dict["useRadiusAuthentication"] = use_radius
+
+ if new_password is not None:
+ payload_dict["newPassword"] = new_password
+
+ if connection_number is not None:
+ payload_dict["connectionNumber"] = connection_number
+
+ payload = json.dumps(payload_dict)
+
+ else: # Logoff Action
+
+ # Get values from cyberark_session already established
+ api_base_url = cyberark_session["api_base_url"]
+ validate_certs = cyberark_session["validate_certs"]
+ use_shared_logon = cyberark_session[
+ "use_shared_logon_authentication"
+ ]
+ headers["Authorization"] = cyberark_session["token"]
+
+ # Different end_points based on the use of shared logon authentication
+ if use_shared_logon:
+ end_point = ("/PasswordVault/WebServices/auth/Shared"
+ "/RestfulAuthenticationService.svc/Logoff")
+ else:
+ end_point = ("/PasswordVault/WebServices/auth/Cyberark"
+ "/CyberArkAuthenticationService.svc/Logoff")
+
+ result = None
+ changed = False
+ response = None
+
+ try:
+
+ response = open_url(
+ api_base_url + end_point,
+ method="POST",
+ headers=headers,
+ data=payload,
+ validate_certs=validate_certs,
+ )
+
+ except (HTTPError, httplib.HTTPException) as http_exception:
+
+ module.fail_json(
+ msg=(
+ "Error while performing authentication."
+ "Please validate parameters provided, and ability to logon to "
+ "CyberArk.\n*** end_point=%s%s\n ==> %s"
+ ) % (api_base_url, end_point, to_text(http_exception)),
+ payload=payload,
+ headers=headers,
+ status_code=http_exception.code,
+ )
+
+ except Exception as unknown_exception:
+
+ module.fail_json(
+ msg=(
+ "Unknown error while performing authentication."
+ "\n*** end_point=%s%s\n%s"
+ % (api_base_url, end_point, to_text(unknown_exception))
+ ),
+ payload=payload,
+ headers=headers,
+ status_code=-1,
+ )
+
+ if response.getcode() == 200: # Success
+
+ if state == "present": # Logon Action
+
+ # Result token from REST Api uses a different key based
+ # the use of shared logon authentication
+ token = None
+ try:
+ if use_shared_logon:
+ token = json.loads(response.read())["LogonResult"]
+ else:
+ token = json.loads(response.read())["CyberArkLogonResult"]
+ except Exception as e:
+ module.fail_json(
+ msg="Error obtaining token\n%s" % (to_text(e)),
+ payload=payload,
+ headers=headers,
+ status_code=-1,
+ )
+
+ # Preparing result of the module
+ result = {
+ "cyberark_session": {
+ "token": token,
+ "api_base_url": api_base_url,
+ "validate_certs": validate_certs,
+ "use_shared_logon_authentication": use_shared_logon,
+ }
+ }
+
+ if new_password is not None:
+ # Only marks change if new_password was received resulting
+ # in a password change
+ changed = True
+
+ else: # Logoff Action clears cyberark_session
+
+ result = {"cyberark_session": {}}
+
+ return (changed, result, response.getcode())
+
+ else:
+ module.fail_json(
+ msg="error in end_point=>" + end_point, headers=headers
+ )
+
+
+def main():
+
+ fields = {
+ "api_base_url": {"type": "str"},
+ "validate_certs": {"type": "bool", "default": "true"},
+ "username": {"type": "str"},
+ "password": {"type": "str", "no_log": True},
+ "new_password": {"type": "str", "no_log": True},
+ "use_shared_logon_authentication": {"default": False, "type": "bool"},
+ "use_radius_authentication": {"default": False, "type": "bool"},
+ "connection_number": {"type": "int"},
+ "state": {
+ "type": "str",
+ "choices": ["present", "absent"],
+ "default": "present",
+ },
+ "cyberark_session": {"type": "dict"},
+ }
+
+ mutually_exclusive = [
+ ["use_shared_logon_authentication", "use_radius_authentication"],
+ ["use_shared_logon_authentication", "new_password"],
+ ["api_base_url", "cyberark_session"],
+ ["cyberark_session", "username", "use_shared_logon_authentication"],
+ ]
+
+ required_if = [
+ ("state", "present", ["api_base_url"]),
+ ("state", "absent", ["cyberark_session"]),
+ ]
+
+ required_together = [["username", "password"]]
+
+ module = AnsibleModule(
+ argument_spec=fields,
+ mutually_exclusive=mutually_exclusive,
+ required_if=required_if,
+ required_together=required_together,
+ supports_check_mode=True,
+ )
+
+ (changed, result, status_code) = processAuthentication(module)
+
+ module.exit_json(
+ changed=changed,
+ ansible_facts=result,
+ status_code=status_code
+ )
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cyberark/pas/plugins/modules/cyberark_credential.py b/collections-debian-merged/ansible_collections/cyberark/pas/plugins/modules/cyberark_credential.py
new file mode 100644
index 00000000..ab832192
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cyberark/pas/plugins/modules/cyberark_credential.py
@@ -0,0 +1,350 @@
+#!/usr/bin/python
+# Copyright: (c) 2017, Ansible Project
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+ANSIBLE_METADATA = {
+ "metadata_version": "1.1",
+ "status": ["preview"],
+ "supported_by": "community",
+}
+
+DOCUMENTATION = """
+---
+module: cyberark_credential
+short_description: Credential retrieval using AAM Central Credential Provider.
+author:
+ - Edward Nunez (@enunez-cyberark)
+ - CyberArk BizDev (@cyberark-bizdev)
+ - Erasmo Acosta (@erasmix)
+ - James Stutes (@JimmyJamCABD)
+version_added: 2.4
+description:
+ - Creates a URI for retrieving a credential from a password object stored
+ in the Cyberark Vault. The request uses the Privileged Account Security
+ Web Services SDK through the Central Credential Provider by requesting
+ access with an Application ID.
+
+options:
+ api_base_url:
+ type: str
+ required: true
+ description:
+ - A string containing the base URL of the server hosting the
+ Central Credential Provider.
+ validate_certs:
+ type: bool
+ required: false
+ default: true
+ description:
+ - If C(false), SSL certificate chain will not be validated. This
+ should only set to C(true) if you have a root CA certificate
+ installed on each node.
+ app_id:
+ type: str
+ required: true
+ description:
+ - A string containing the Application ID authorized for retrieving
+ the credential.
+ query:
+ type: str
+ required: true
+ description:
+ - A string containing details of the object being queried;
+ - Possible parameters could be Safe, Folder, Object
+ - (internal account name), UserName, Address, Database,
+ - PolicyID.
+ connection_timeout:
+ type: int
+ required: false
+ default: '30'
+ description:
+ - An integer value of the allowed time before the request returns
+ failed.
+ query_format:
+ type: str
+ required: false
+ default: Exact
+ choices: [Exact, Regexp]
+ description:
+ - The format for which your Query will be received by the CCP.
+ fail_request_on_password_change:
+ type: bool
+ required: false
+ default: false
+ description:
+ - A boolean parameter for completing the request in the middle of
+ a password change of the requested credential.
+ client_cert:
+ type: str
+ required: false
+ description:
+ - A string containing the file location and name of the client
+ certificate used for authentication.
+ client_key:
+ type: str
+ required: false
+ description:
+ - A string containing the file location and name of the private
+ key of the client certificate used for authentication.
+ reason:
+ type: str
+ required: false
+ description:
+ - Reason for requesting credential if required by policy;
+ - It must be specified if the Policy managing the object
+ - requires it.
+"""
+
+EXAMPLES = """
+ tasks:
+ - name: credential retrieval basic
+ cyberark_credential:
+ api_base_url: "http://10.10.0.1"
+ app_id: "TestID"
+ query: "Safe=test;UserName=admin"
+ register: result
+
+ - name: credential retrieval advanced
+ cyberark_credential:
+ api_base_url: "https://components.cyberark.local"
+ validate_certs: yes
+ client_cert: /etc/pki/ca-trust/source/client.pem
+ client_key: /etc/pki/ca-trust/source/priv-key.pem
+ app_id: "TestID"
+ query: "Safe=test;UserName=admin"
+ connection_timeout: 60
+ query_format: Exact
+ fail_request_on_password_change: True
+ reason: "requesting credential for Ansible deployment"
+ register: result
+
+"""
+
+RETURN = """
+changed:
+ description:
+ - Identify if the playbook run resulted in a change to the account in
+ any way.
+ returned: always
+ type: bool
+failed:
+ description: Whether playbook run resulted in a failure of any kind.
+ returned: always
+ type: bool
+status_code:
+ description: Result HTTP Status code.
+ returned: success
+ type: int
+ sample: "200, 201, -1, 204"
+result:
+ description: A json dump of the resulting action.
+ returned: success
+ type: complex
+ contains:
+ Address:
+ description: The target address of the credential being queried
+ type: str
+ returned: if required
+ Content:
+ description: The password for the object being queried
+ type: str
+ returned: always
+ CreationMethod:
+ description: This is how the object was created in the Vault
+ type: str
+ returned: always
+ DeviceType:
+ description:
+ - An internal File Category for more granular management of
+ Platforms.
+ type: str
+ returned: always
+ Folder:
+ description:
+ - The folder within the Safe where the credential is stored.
+ type: str
+ returned: always
+ Name:
+ description:
+ - The Cyberark unique object ID of the credential being
+ queried.
+ type: str
+ returned: always
+ PasswordChangeInProcess:
+ description: If the password has a change flag placed by the CPM
+ type: bool
+ returned: always
+ PolicyID:
+ description: Whether or not SSL certificates should be validated.
+ type: str
+ returned: if assigned to a policy
+ Safe:
+ description: The safe where the queried credential is stored
+ type: string
+ returned: always
+ Username:
+ description: The username of the credential being queried
+ type: str
+ returned: if required
+ LogonDomain:
+ description: The Address friendly name resolved by the CPM
+ type: str
+ returned: if populated
+ CPMDisabled:
+ description:
+ - A description of why this vaulted credential is not being
+ managed by the CPM.
+ type: str
+ returned: if CPM management is disabled and a reason is given
+"""
+
+from ansible.module_utils._text import to_text
+from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils.urls import open_url
+from ansible.module_utils.six.moves.urllib.error import HTTPError
+from ansible.module_utils.six.moves.urllib.parse import quote
+import json
+
+try:
+ import httplib
+except ImportError:
+ # Python 3
+ import http.client as httplib
+
+
+def retrieve_credential(module):
+
+ # Getting parameters from module
+
+ api_base_url = module.params["api_base_url"]
+ validate_certs = module.params["validate_certs"]
+ app_id = module.params["app_id"]
+ query = module.params["query"]
+ connection_timeout = module.params["connection_timeout"]
+ query_format = module.params["query_format"]
+ fail_request_on_password_change = module.params[
+ "fail_request_on_password_change"
+ ]
+ client_cert = None
+ client_key = None
+
+ if "client_cert" in module.params:
+ client_cert = module.params["client_cert"]
+ if "client_key" in module.params:
+ client_key = module.params["client_key"]
+
+ end_point = (
+ "/AIMWebService/api/Accounts?AppId=%s&Query=%s&"
+ "ConnectionTimeout=%s&QueryFormat=%s"
+ "&FailRequestOnPasswordChange=%s"
+ ) % (
+ quote(app_id),
+ quote(query),
+ connection_timeout,
+ query_format,
+ fail_request_on_password_change,
+ )
+
+ if "reason" in module.params and module.params["reason"] is not None:
+ reason = quote(module.params["reason"])
+ end_point = end_point + "&reason=%s" % reason
+
+ result = None
+ response = None
+
+ try:
+
+ response = open_url(
+ api_base_url + end_point,
+ method="GET",
+ validate_certs=validate_certs,
+ client_cert=client_cert,
+ client_key=client_key,
+ )
+
+ except (HTTPError, httplib.HTTPException) as http_exception:
+
+ module.fail_json(
+ msg=(
+ "Error while retrieving credential."
+ "Please validate parameters provided, and permissions for "
+ "the application and provider in CyberArk."
+ "\n*** end_point=%s%s\n ==> %s"
+ % (api_base_url, end_point, to_text(http_exception))
+ ),
+ status_code=http_exception.code,
+ )
+
+ except Exception as unknown_exception:
+
+ module.fail_json(
+ msg=(
+ "Unknown error while retrieving credential."
+ "\n*** end_point=%s%s\n%s"
+ % (api_base_url, end_point, to_text(unknown_exception))
+ ),
+ status_code=-1,
+ )
+
+ if response.getcode() == 200: # Success
+
+ # Result token from REST Api uses a different key based
+ try:
+ result = json.loads(response.read())
+ except Exception as exc:
+ module.fail_json(
+ msg=(
+ "Error obtain cyberark credential result "
+ "from http body\n%s"
+ ) % (to_text(exc)),
+ status_code=-1,
+ )
+
+ return (result, response.getcode())
+
+ else:
+ module.fail_json(msg="error in end_point=>" + end_point)
+
+
+def main():
+
+ fields = {
+ "api_base_url": {"required": True, "type": "str"},
+ "app_id": {"required": True, "type": "str"},
+ "query": {"required": True, "type": "str"},
+ "reason": {"required": False, "type": "str"},
+ "connection_timeout": {
+ "required": False,
+ "type": "int",
+ "default": 30
+ },
+ "query_format": {
+ "required": False,
+ "type": "str",
+ "choices": ["Exact", "Regexp"],
+ "default": "Exact",
+ },
+ "fail_request_on_password_change": {
+ "required": False,
+ "type": "bool",
+ "default": False,
+ },
+ "validate_certs": {"type": "bool", "default": True},
+ "client_cert": {"type": "str", "required": False},
+ "client_key": {"type": "str", "required": False},
+ }
+
+ module = AnsibleModule(argument_spec=fields, supports_check_mode=True)
+
+ (result, status_code) = retrieve_credential(module)
+
+ module.exit_json(changed=False, result=result, status_code=status_code)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cyberark/pas/plugins/modules/cyberark_user.py b/collections-debian-merged/ansible_collections/cyberark/pas/plugins/modules/cyberark_user.py
new file mode 100644
index 00000000..3939378a
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cyberark/pas/plugins/modules/cyberark_user.py
@@ -0,0 +1,619 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Copyright: (c) 2017, Ansible Project
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+ANSIBLE_METADATA = {
+ "metadata_version": "1.1",
+ "status": ["preview"],
+ "supported_by": "certified",
+}
+
+DOCUMENTATION = r"""
+---
+module: cyberark_user
+short_description: CyberArk User Management using PAS Web Services SDK.
+author:
+ - Edward Nunez (@enunez-cyberark)
+ - Cyberark Bizdev (@cyberark-bizdev)
+ - Erasmo Acosta (@erasmix)
+ - James Stutes (@jimmyjamcabd)
+version_added: 2.4
+description:
+ - CyberArk User Management using PAS Web Services SDK,
+ It currently supports the following actions Get User Details, Add User,
+ Update User, Delete User.
+
+options:
+ username:
+ description:
+ - The name of the user who will be queried (for details), added,
+ updated or deleted.
+ type: str
+ required: True
+ state:
+ description:
+ - Specifies the state needed for the user present for create user,
+ absent for delete user.
+ type: str
+ choices: [ absent, present ]
+ default: present
+ logging_level:
+ description:
+ - Parameter used to define the level of troubleshooting output to
+ the C(logging_file) value.
+ required: true
+ choices: [NOTSET, DEBUG, INFO]
+ default: NOTSET
+ type: str
+ logging_file:
+ description:
+ - Setting the log file name and location for troubleshooting logs.
+ required: false
+ default: /tmp/ansible_cyberark.log
+ type: str
+ cyberark_session:
+ description:
+ - Dictionary set by a CyberArk authentication containing the
+ different values to perform actions on a logged-on CyberArk
+ session, please see M(cyberark_authentication) module for an
+ example of cyberark_session.
+ type: dict
+ required: True
+ initial_password:
+ description:
+ - The password that the new user will use to log on the first time.
+ - This password must meet the password policy requirements.
+ - This parameter is required when state is present -- Add User.
+ type: str
+ new_password:
+ description:
+ - The user updated password. Make sure that this password meets
+ the password policy requirements.
+ type: str
+ email:
+ description:
+ - The user email address.
+ type: str
+ first_name:
+ description:
+ - The user first name.
+ type: str
+ last_name:
+ description:
+ - The user last name.
+ type: str
+ change_password_on_the_next_logon:
+ description:
+ - Whether or not the user must change their password in their
+ next logon.
+ type: bool
+ default: no
+ expiry_date:
+ description:
+ - The date and time when the user account will expire and become
+ disabled.
+ type: str
+ user_type_name:
+ description:
+ - The type of user.
+ - The parameter defaults to C(EPVUser).
+ type: str
+ disabled:
+ description:
+ - Whether or not the user will be disabled.
+ type: bool
+ default: no
+ location:
+ description:
+ - The Vault Location for the user.
+ type: str
+ group_name:
+ description:
+ - The name of the group the user will be added to.
+ type: str
+"""
+
+EXAMPLES = r"""
+- name: Logon to CyberArk Vault using PAS Web Services SDK
+ cyberark_authentication:
+ api_base_url: https://components.cyberark.local
+ use_shared_logon_authentication: yes
+
+- name: Create user & immediately add it to a group
+ cyberark_user:
+ username: username
+ initial_password: password
+ user_type_name: EPVUser
+ change_password_on_the_next_logon: no
+ group_name: GroupOfUser
+ state: present
+ cyberark_session: '{{ cyberark_session }}'
+
+- name: Make sure user is present and reset user credential if present
+ cyberark_user:
+ username: Username
+ new_password: password
+ disabled: no
+ state: present
+ cyberark_session: '{{ cyberark_session }}'
+
+- name: Logoff from CyberArk Vault
+ cyberark_authentication:
+ state: absent
+ cyberark_session: '{{ cyberark_session }}'
+"""
+
+RETURN = r"""
+changed:
+ description: Whether there was a change done.
+ type: bool
+ returned: always
+cyberark_user:
+ description: Dictionary containing result properties.
+ returned: always
+ type: complex
+ contains:
+ result:
+ description: user properties when state is present
+ type: dict
+ returned: success
+status_code:
+ description: Result HTTP Status code
+ returned: success
+ type: int
+ sample: 200
+"""
+
+import json
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils._text import to_text
+from ansible.module_utils.six.moves import http_client as httplib
+from ansible.module_utils.six.moves.urllib.error import HTTPError
+from ansible.module_utils.urls import open_url
+import logging
+import urllib
+
+
+def user_details(module):
+
+ # Get username from module parameters, and api base url
+ # along with validate_certs from the cyberark_session established
+ username = module.params["username"]
+ cyberark_session = module.params["cyberark_session"]
+ api_base_url = cyberark_session["api_base_url"]
+ validate_certs = cyberark_session["validate_certs"]
+
+ # Prepare result, end_point, and headers
+ result = {}
+ end_point = "/PasswordVault/WebServices/PIMServices.svc/Users/{0}".format(
+ username
+ )
+ headers = {"Content-Type": "application/json"}
+ headers["Authorization"] = cyberark_session["token"]
+
+ try:
+
+ response = open_url(
+ api_base_url + end_point,
+ method="GET",
+ headers=headers,
+ validate_certs=validate_certs,
+ )
+ result = {"result": json.loads(response.read())}
+
+ return (False, result, response.getcode())
+
+ except (HTTPError, httplib.HTTPException) as http_exception:
+
+ if http_exception.code == 404:
+ return (False, None, http_exception.code)
+ else:
+ module.fail_json(
+ msg=(
+ "Error while performing user_details."
+ "Please validate parameters provided."
+ "\n*** end_point=%s%s\n ==> %s"
+ % (api_base_url, end_point, to_text(http_exception))
+ ),
+ headers=headers,
+ status_code=http_exception.code,
+ )
+
+ except Exception as unknown_exception:
+
+ module.fail_json(
+ msg=(
+ "Unknown error while performing user_details."
+ "\n*** end_point=%s%s\n%s"
+ % (api_base_url, end_point, to_text(unknown_exception))
+ ),
+ headers=headers,
+ status_code=-1,
+ )
+
+
+def user_add_or_update(module, HTTPMethod, existing_info):
+
+ # Get username from module parameters, and api base url
+ # along with validate_certs from the cyberark_session established
+ username = module.params["username"]
+ cyberark_session = module.params["cyberark_session"]
+ api_base_url = cyberark_session["api_base_url"]
+ validate_certs = cyberark_session["validate_certs"]
+
+ # Prepare result, paylod, and headers
+ result = {}
+ payload = {}
+ headers = {
+ "Content-Type": "application/json",
+ "Authorization": cyberark_session["token"],
+ }
+
+ # end_point and payload sets different depending on POST/PUT
+ # for POST -- create -- payload contains username
+ # for PUT -- update -- username is part of the endpoint
+ if HTTPMethod == "POST":
+ end_point = "/PasswordVault/WebServices/PIMServices.svc/Users"
+ payload["UserName"] = username
+ if (
+ "initial_password" in module.params.keys()
+ and module.params["initial_password"] is not None
+ ):
+ payload["InitialPassword"] = module.params["initial_password"]
+
+ elif HTTPMethod == "PUT":
+ end_point = "/PasswordVault/WebServices/PIMServices.svc/Users/{0}"
+ end_point = end_point.format(username)
+
+ # --- Optionally populate payload based on parameters passed ---
+ if (
+ "new_password" in module.params
+ and module.params["new_password"] is not None
+ ):
+ payload["NewPassword"] = module.params["new_password"]
+
+ if "email" in module.params and module.params["email"] is not None:
+ payload["Email"] = module.params["email"]
+
+ if (
+ "first_name" in module.params
+ and module.params["first_name"] is not None
+ ):
+ payload["FirstName"] = module.params["first_name"]
+
+ if "last_name" in module.params and module.params["last_name"] is not None:
+ payload["LastName"] = module.params["last_name"]
+
+ if (
+ "change_password_on_the_next_logon" in module.params
+ and module.params["change_password_on_the_next_logon"] is not None
+ ):
+ payload["ChangePasswordOnTheNextLogon"] = module.params[
+ "change_password_on_the_next_logon"
+ ]
+
+ if (
+ "expiry_date" in module.params
+ and module.params["expiry_date"] is not None
+ ):
+ payload["ExpiryDate"] = module.params["expiry_date"]
+
+ if (
+ "user_type_name" in module.params
+ and module.params["user_type_name"] is not None
+ ):
+ payload["UserTypeName"] = module.params["user_type_name"]
+
+ if "disabled" in module.params and module.params["disabled"] is not None:
+ payload["Disabled"] = module.params["disabled"]
+
+ if "location" in module.params and module.params["location"] is not None:
+ payload["Location"] = module.params["location"]
+
+ # --------------------------------------------------------------
+ logging.debug(
+ "HTTPMethod = "
+ + HTTPMethod
+ + " module.params = "
+ + json.dumps(module.params)
+ )
+ logging.debug("Existing Info: %s", json.dumps(existing_info))
+ logging.debug("payload => %s", json.dumps(payload))
+
+ if HTTPMethod == "PUT" and (
+ "new_password" not in module.params
+ or module.params["new_password"] is None
+ ):
+ logging.info("Verifying if needs to be updated")
+ proceed = False
+ updateable_fields = [
+ "Email",
+ "FirstName",
+ "LastName",
+ "ChangePasswordOnTheNextLogon",
+ "ExpiryDate",
+ "UserTypeName",
+ "Disabled",
+ "Location",
+ ]
+ for field_name in updateable_fields:
+ logging.debug("#### field_name : %s", field_name)
+ if (
+ field_name in payload
+ and field_name in existing_info
+ and payload[field_name] != existing_info[field_name]
+ ):
+ logging.debug("Changing value for %s", field_name)
+ proceed = True
+ else:
+ proceed = True
+
+ if proceed:
+ logging.info("Proceeding to either update or create")
+ try:
+
+ # execute REST action
+ response = open_url(
+ api_base_url + end_point,
+ method=HTTPMethod,
+ headers=headers,
+ data=json.dumps(payload),
+ validate_certs=validate_certs,
+ )
+
+ result = {"result": json.loads(response.read())}
+
+ return (True, result, response.getcode())
+
+ except (HTTPError, httplib.HTTPException) as http_exception:
+
+ module.fail_json(
+ msg=(
+ "Error while performing user_add_or_update."
+ "Please validate parameters provided."
+ "\n*** end_point=%s%s\n ==> %s"
+ % (api_base_url, end_point, to_text(http_exception))
+ ),
+ payload=payload,
+ headers=headers,
+ status_code=http_exception.code,
+ )
+ except Exception as unknown_exception:
+
+ module.fail_json(
+ msg=(
+ "Unknown error while performing user_add_or_update."
+ "\n*** end_point=%s%s\n%s"
+ % (api_base_url, end_point, to_text(unknown_exception))
+ ),
+ payload=payload,
+ headers=headers,
+ status_code=-1,
+ )
+ else:
+ return (False, existing_info, 200)
+
+
+def user_delete(module):
+
+ # Get username from module parameters, and api base url
+ # along with validate_certs from the cyberark_session established
+ username = module.params["username"]
+ cyberark_session = module.params["cyberark_session"]
+ api_base_url = cyberark_session["api_base_url"]
+ validate_certs = cyberark_session["validate_certs"]
+
+ # Prepare result, end_point, and headers
+ result = {}
+ end_point = (
+ "/PasswordVault/WebServices/PIMServices.svc/Users/{0}"
+ ).format(username)
+
+ headers = {"Content-Type": "application/json"}
+ headers["Authorization"] = cyberark_session["token"]
+
+ try:
+
+ # execute REST action
+ response = open_url(
+ api_base_url + end_point,
+ method="DELETE",
+ headers=headers,
+ validate_certs=validate_certs,
+ )
+
+ result = {"result": {}}
+
+ return (True, result, response.getcode())
+
+ except (HTTPError, httplib.HTTPException) as http_exception:
+
+ exception_text = to_text(http_exception)
+ if http_exception.code == 404 and "ITATS003E" in exception_text:
+ # User does not exist
+ result = {"result": {}}
+ return (False, result, http_exception.code)
+ else:
+ module.fail_json(
+ msg=(
+ "Error while performing user_delete."
+ "Please validate parameters provided."
+ "\n*** end_point=%s%s\n ==> %s"
+ % (api_base_url, end_point, exception_text)
+ ),
+ headers=headers,
+ status_code=http_exception.code,
+ )
+
+ except Exception as unknown_exception:
+
+ module.fail_json(
+ msg=(
+ "Unknown error while performing user_delete."
+ "\n*** end_point=%s%s\n%s"
+ % (api_base_url, end_point, to_text(unknown_exception))
+ ),
+ headers=headers,
+ status_code=-1,
+ )
+
+
+def user_add_to_group(module):
+
+ # Get username, and groupname from module parameters, and api base url
+ # along with validate_certs from the cyberark_session established
+ username = module.params["username"]
+ group_name = module.params["group_name"]
+ cyberark_session = module.params["cyberark_session"]
+ api_base_url = cyberark_session["api_base_url"]
+ validate_certs = cyberark_session["validate_certs"]
+
+ # Prepare result, end_point, headers and payload
+ result = {}
+ end_point = (
+ "/PasswordVault/WebServices/PIMServices.svc/Groups/{0}/Users"
+ ).format(
+ urllib.quote(group_name)
+ )
+
+ headers = {"Content-Type": "application/json"}
+ headers["Authorization"] = cyberark_session["token"]
+ payload = {"UserName": username}
+
+ try:
+
+ # execute REST action
+ response = open_url(
+ api_base_url + end_point,
+ method="POST",
+ headers=headers,
+ data=json.dumps(payload),
+ validate_certs=validate_certs,
+ )
+
+ result = {"result": {}}
+
+ return (True, result, response.getcode())
+
+ except (HTTPError, httplib.HTTPException) as http_exception:
+
+ exception_text = to_text(http_exception)
+ if http_exception.code == 409 and "ITATS262E" in exception_text:
+ # User is already member of Group
+ return (False, None, http_exception.code)
+ else:
+ module.fail_json(
+ msg=(
+ "Error while performing user_add_to_group."
+ "Please validate parameters provided."
+ "\n*** end_point=%s%s\n ==> %s"
+ % (api_base_url, end_point, exception_text)
+ ),
+ payload=payload,
+ headers=headers,
+ status_code=http_exception.code,
+ )
+
+ except Exception as unknown_exception:
+
+ module.fail_json(
+ msg=(
+ "Unknown error while performing user_add_to_group."
+ "\n*** end_point=%s%s\n%s"
+ % (api_base_url, end_point, to_text(unknown_exception))
+ ),
+ payload=payload,
+ headers=headers,
+ status_code=-1,
+ )
+
+
+def main():
+
+ module = AnsibleModule(
+ argument_spec=dict(
+ username=dict(type="str", required=True),
+ state=dict(
+ type="str",
+ default="present",
+ choices=["absent", "present"]
+ ),
+ logging_level=dict(
+ type="str",
+ default="NOTSET",
+ choices=["NOTSET", "DEBUG", "INFO"]
+ ),
+ logging_file=dict(type="str", default="/tmp/ansible_cyberark.log"),
+ cyberark_session=dict(type="dict", required=True),
+ initial_password=dict(type="str", no_log=True),
+ new_password=dict(type="str", no_log=True),
+ email=dict(type="str"),
+ first_name=dict(type="str"),
+ last_name=dict(type="str"),
+ change_password_on_the_next_logon=dict(type="bool"),
+ expiry_date=dict(type="str"),
+ user_type_name=dict(type="str"),
+ disabled=dict(type="bool"),
+ location=dict(type="str"),
+ group_name=dict(type="str"),
+ )
+ )
+
+ if module.params["logging_level"] is not None:
+ logging.basicConfig(
+ filename=module.params["logging_file"],
+ level=module.params["logging_level"]
+ )
+
+ logging.info("Starting Module")
+
+ state = module.params["state"]
+ group_name = module.params["group_name"]
+
+ if state == "present":
+ (changed, result, status_code) = user_details(module)
+
+ if status_code == 200:
+ # User already exists
+
+ (changed, result, status_code) = user_add_or_update(
+ module, "PUT", result["result"]
+ )
+
+ if group_name is not None:
+ # If user exists, add to group if needed
+ (changed_group, no_result, no_status_code) = user_add_to_group(module)
+ changed = changed or changed_group
+
+ elif status_code == 404:
+ # User does not exist, proceed to create it
+ (changed, result, status_code) = user_add_or_update(
+ module,
+ "POST",
+ None
+ )
+
+ if status_code == 201 and group_name is not None:
+ # If user was created, add to group if needed
+ (changed, no_result, no_status_code) = user_add_to_group(module)
+
+ elif state == "absent":
+ (changed, result, status_code) = user_delete(module)
+
+ module.exit_json(
+ changed=changed,
+ cyberark_user=result,
+ status_code=status_code
+ )
+
+
+if __name__ == "__main__":
+ main()