Init: mediaserver

This commit is contained in:
2023-02-08 12:13:28 +01:00
parent 848bc9739c
commit f7c23d4ba9
31914 changed files with 6175775 additions and 0 deletions

View File

@@ -0,0 +1,9 @@
# Contributing to the Ansible Security Automation Collection
Thanks for your interest in the Ansible Security Automation collection.
For general community guidelines, please see the [community repo](https://github.com/cyberark/community).
## Pull Request Workflow
Currently, this repository is source-available and not open to contributions. Please continue to follow this repository for updates and open-source availability

View File

@@ -0,0 +1,369 @@
{
"files": [
{
"name": ".",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
"name": "LICENSE",
"ftype": "file",
"chksum_type": "sha256",
"chksum_sha256": "f717ec697e01e78397a7c8a6f13b78070ea4503346ba65202ccaa055f34f0261",
"format": 1
},
{
"name": "plugins",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
"name": "plugins/modules",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
"name": "plugins/modules/cyberark_account.py",
"ftype": "file",
"chksum_type": "sha256",
"chksum_sha256": "bc4953fcb6bea1ebfbf2d5ae4ff98487878a78d19b192dc05b648ab5ad3eabc6",
"format": 1
},
{
"name": "plugins/modules/cyberark_user.py",
"ftype": "file",
"chksum_type": "sha256",
"chksum_sha256": "194444c4c46ea9e0c588bdaf23cdce10af7bee4cd2c58adc892336c2e04ba965",
"format": 1
},
{
"name": "plugins/modules/cyberark_credential.py",
"ftype": "file",
"chksum_type": "sha256",
"chksum_sha256": "17f8fdabe8b326f2d43a30c86a04bc20d759e91ae0b2bb441efe0b5068426467",
"format": 1
},
{
"name": "plugins/modules/cyberark_authentication.py",
"ftype": "file",
"chksum_type": "sha256",
"chksum_sha256": "2d22630ce495d3db4aa4e047a62785d65e2c24fe168585e939ab839120967d7c",
"format": 1
},
{
"name": "tests",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
"name": "tests/change_test.yml",
"ftype": "file",
"chksum_type": "sha256",
"chksum_sha256": "ade187fe39cb5d204e4a9f0157140a4490f4384d5a443cc834e6eba857a65052",
"format": 1
},
{
"name": "tests/provision_user.yml",
"ftype": "file",
"chksum_type": "sha256",
"chksum_sha256": "ef66351da4a194e922679fd7b8338ce4997841996f7adb9792ffc24d7fa5e58a",
"format": 1
},
{
"name": "tests/test.yml",
"ftype": "file",
"chksum_type": "sha256",
"chksum_sha256": "a84d2ad562594a7291bea6414d48431ceb4cea94a91e235b74acf5902582e667",
"format": 1
},
{
"name": "tests/provision_account.yml",
"ftype": "file",
"chksum_type": "sha256",
"chksum_sha256": "a8783ddd86efbad3b3764ed15eadbe74feca848e412baf6a6bb816a334fc3498",
"format": 1
},
{
"name": "tests/enable_user.yml",
"ftype": "file",
"chksum_type": "sha256",
"chksum_sha256": "2e2663f92ccbc4b660a4a02e51d3f0e8ad7d18ed09ba48df6c233844c33f994d",
"format": 1
},
{
"name": "tests/deprovision_user.yml",
"ftype": "file",
"chksum_type": "sha256",
"chksum_sha256": "8a9f1dc3ff7a408f0b130160a8e78c401b6e2514c8ee773df75bbc594bd40332",
"format": 1
},
{
"name": "tests/changepolicy.yml",
"ftype": "file",
"chksum_type": "sha256",
"chksum_sha256": "fb4ea3f8c3c322426eac081abc4eb86f0b997f17507451e1f5a064d2e23ce54a",
"format": 1
},
{
"name": "tests/reset_user_password.yml",
"ftype": "file",
"chksum_type": "sha256",
"chksum_sha256": "fdbc326414f4dfd2a546fc473bf4aeff8c8081fefbe82635473b22e07f165632",
"format": 1
},
{
"name": "tests/disable_user.yml",
"ftype": "file",
"chksum_type": "sha256",
"chksum_sha256": "d194efba14794c5c24125eb99805d519e8d12e5639312afe5f0d2ee2210e30e2",
"format": 1
},
{
"name": "tests/deprovision_account.yml",
"ftype": "file",
"chksum_type": "sha256",
"chksum_sha256": "56ce44093120aba1256a85956749990b0a4ef462052718fa7b22ad3fb0594150",
"format": 1
},
{
"name": "meta",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
"name": "meta/runtime.yml",
"ftype": "file",
"chksum_type": "sha256",
"chksum_sha256": "db1dfe098d05c998eb62c32cf99d3b7bbf93afc0a1f0b4704b024eaa7c7b6848",
"format": 1
},
{
"name": "roles",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
"name": "roles/aimprovider",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
"name": "roles/aimprovider/tasks",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
"name": "roles/aimprovider/tasks/uninstallAIMProvider.yml",
"ftype": "file",
"chksum_type": "sha256",
"chksum_sha256": "78f1021e529d735b61978908e1fb6ea9eabe53a44d445d39ae0e70fdf9367815",
"format": 1
},
{
"name": "roles/aimprovider/tasks/installAIMProvider.yml",
"ftype": "file",
"chksum_type": "sha256",
"chksum_sha256": "120db55c58df08aaf6d6a8daaa932746ff89d2317ecac12ee28cc15cc18ec365",
"format": 1
},
{
"name": "roles/aimprovider/tasks/main.yml",
"ftype": "file",
"chksum_type": "sha256",
"chksum_sha256": "696da801f4fdbc63b47118119077ecceced5cb1e50a2092842671c877aad744b",
"format": 1
},
{
"name": "roles/aimprovider/README.md",
"ftype": "file",
"chksum_type": "sha256",
"chksum_sha256": "f1d69c30a1131171ac7acad895d588ab08b20896751d1db2fcb510103b37bc5b",
"format": 1
},
{
"name": "roles/aimprovider/defaults",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
"name": "roles/aimprovider/defaults/main.yml",
"ftype": "file",
"chksum_type": "sha256",
"chksum_sha256": "56a96c0b8c7e35aed626b90d3b3020b0aa6b34ccd08cf1fdab08778b5c2f5839",
"format": 1
},
{
"name": "docs",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
"name": "docs/cyberark_account.md",
"ftype": "file",
"chksum_type": "sha256",
"chksum_sha256": "e6cc9b8071b126d37c1be152ccad42ca7463a44f2211c244ba51e9ebc0b731af",
"format": 1
},
{
"name": "docs/images",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
"name": "docs/images/platform_account_properties.JPG",
"ftype": "file",
"chksum_type": "sha256",
"chksum_sha256": "82e22cb050df050bd5af8680d341f61d48beafbf9c30cb40fe994c684151d8d4",
"format": 1
},
{
"name": "docs/images/full-cyberark-logo.jpg",
"ftype": "file",
"chksum_type": "sha256",
"chksum_sha256": "5d910c2159e7caded5286414d0329d7e0f084676fcb80610efffa5be7214452b",
"format": 1
},
{
"name": "docs/images/cyberark_logo.jpg",
"ftype": "file",
"chksum_type": "sha256",
"chksum_sha256": "535e69685a6e58c210d685abe0fb4f8990bdca029ef41f30c130000f9a596631",
"format": 1
},
{
"name": "docs/cyberark_credential.md",
"ftype": "file",
"chksum_type": "sha256",
"chksum_sha256": "16565cfb841903b25233ef1c0d08870ed12393e340ef10c3468e929e7256688a",
"format": 1
},
{
"name": "docs/aimprovider.md",
"ftype": "file",
"chksum_type": "sha256",
"chksum_sha256": "f1d69c30a1131171ac7acad895d588ab08b20896751d1db2fcb510103b37bc5b",
"format": 1
},
{
"name": "docs/cyberark_authentication.md",
"ftype": "file",
"chksum_type": "sha256",
"chksum_sha256": "3b9bb902769f667aaa85302dba29c7de0dfbc60213b2e29a981fcdc4edd30f24",
"format": 1
},
{
"name": "docs/cyberark_user.md",
"ftype": "file",
"chksum_type": "sha256",
"chksum_sha256": "3603085686d4db88a033acfa92d0f801bc8da65fc75d40b47b93ea0ca01c2090",
"format": 1
},
{
"name": "README.md",
"ftype": "file",
"chksum_type": "sha256",
"chksum_sha256": "eafe8882110fafc5ea2aad2e67eefd3322dd9bc3ae925e8bdb58b3b26800a756",
"format": 1
},
{
"name": ".gitignore",
"ftype": "file",
"chksum_type": "sha256",
"chksum_sha256": "dfc5692588b338148d1ae60d04cb5c2561f659e2efdb0a01813b5d1ef5605605",
"format": 1
},
{
"name": "CONTRIBUTING.md",
"ftype": "file",
"chksum_type": "sha256",
"chksum_sha256": "27344573191496c7506f67129c6b88d8a05ad8c99e069fa7c27f8f17f61bda57",
"format": 1
},
{
"name": ".github",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
"name": ".github/CODEOWNERS",
"ftype": "file",
"chksum_type": "sha256",
"chksum_sha256": "bddce55d10995835c4bca70664540737833e20d80d68025942d813b15ea878dd",
"format": 1
},
{
"name": ".github/workflows",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
"name": ".github/workflows/ci.yml",
"ftype": "file",
"chksum_type": "sha256",
"chksum_sha256": "e8f0b040ee81fe1e19ea5f2b6044ad01ed4ffcef1ed28eaaa3331bdb711f0bdd",
"format": 1
},
{
"name": "custom-cred-types",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
"name": "custom-cred-types/cyberark-pas-restapi",
"ftype": "dir",
"chksum_type": null,
"chksum_sha256": null,
"format": 1
},
{
"name": "custom-cred-types/cyberark-pas-restapi/input.yml",
"ftype": "file",
"chksum_type": "sha256",
"chksum_sha256": "f4adbb5b1da168dea98a8fd85d5a4b109c346b3deed95cfd06f160c5db4ce927",
"format": 1
},
{
"name": "custom-cred-types/cyberark-pas-restapi/injector.yml",
"ftype": "file",
"chksum_type": "sha256",
"chksum_sha256": "f61c7965c5570860c7345b15f5ce4eea14b7ea4e51548060e023f6dd75879b4c",
"format": 1
},
{
"name": "custom-cred-types/cyberark-pas-restapi/README.md",
"ftype": "file",
"chksum_type": "sha256",
"chksum_sha256": "a07b281e2ab653ee3b61a36a7cced24051b2c2a8a7b14fdc8632b2c34f31e2c5",
"format": 1
}
],
"format": 1
}

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2017 CyberArk
Permission is hereby granted, free of charge, to any person obtaining a copy
of 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 in all
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 THE
AUTHORS 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.

View File

@@ -0,0 +1,43 @@
{
"collection_info": {
"namespace": "cyberark",
"name": "pas",
"version": "1.0.17",
"authors": [
"CyberArk Business Development (@cyberark-bizdev)",
"Edward Nunez (@enunez-cyberark)",
"Joe Garcia (@infamousjoeg)"
],
"readme": "README.md",
"tags": [
"cyberark",
"access",
"security",
"account",
"epv",
"vault",
"identity",
"credential",
"secret",
"privileged"
],
"description": "This is a Collection of the CyberArk Ansible Security Automation toolkit.",
"license": [
"MIT"
],
"license_file": null,
"dependencies": {},
"repository": "https://github.com/cyberark/ansible-security-automation-collection",
"documentation": null,
"homepage": null,
"issues": "https://github.com/cyberark/ansible-security-automation-collection/issues"
},
"file_manifest_file": {
"name": "FILES.json",
"ftype": "file",
"chksum_type": "sha256",
"chksum_sha256": "d117311d0d2bd71bc019349727b04e4884f6997fd50aad6f37897476e54c19e9",
"format": 1
},
"format": 1
}

View File

@@ -0,0 +1,70 @@
<!-- please note this has to be a absolute URL since otherwise it will not show up on galaxy.ansible.com -->
![cyberark logo|](https://github.com/cyberark/ansible-security-automation-collection/blob/master/docs/images/full-cyberark-logo.jpg?raw=true)
## CyberArk Ansible Security Automation Collection
*************
## Collection
#### cyberark.pas
This collection is the CyberArk Ansible Security Automation project and can be found on [ansible galaxy](https://galaxy.ansible.com/cyberark/pas). This is aimed to enable the automation of securing privileged access by storing privileged accounts in the Enterprise Password Vault (EPV), controlling user's access to privileged accounts in EPV, and securely retreiving secrets using Application Access Manager (AAM). The following modules will allow CyberArk administrators to automate the following tasks:
#### Requirements
- CyberArk Privileged Account Security Web Services SDK
- CyberArk AAM Central Credential Provider (**Only required for cyberark_credential**)
#### Role Variables
None.
<br>
<br>
## Modules
#### cyberark_authentication
- Using the CyberArk Web Services SDK, authenticate and obtain an auth token to be passed as a variable in playbooks
- Logoff of an authenticated REST API session<br>
[Playbooks and Module Info](https://github.com/cyberark/ansible-security-automation-collection/blob/master/docs/cyberark_authentication.md)
#### cyberark_user
- Add a CyberArk User
- Delete a CyberArk User
- Update a CyberArk User's account parameters
- Enable/Disable, change password, mark for change at next login, etc
<br>[Playbooks and Module Info](https://github.com/cyberark/ansible-security-automation-collection/blob/master/docs/cyberark_user.md)<br/>
#### cyberark_account
- Add Privileged Account to the EPV
- Delete account objects
- Modify account properties
- Rotatate privileged credentials<br>
[Playbooks and Module Info](https://github.com/cyberark/ansible-security-automation-collection/blob/master/docs/cyberark_account.md)
#### cyberark_credential
- Using AAM Central Credential Provider (CCP), to securely retreive secrets and account properties from EPV to be registered for use in playbooks<br>
[Playbooks and Module Info](https://github.com/cyberark/ansible-security-automation-collection/blob/master/docs/cyberark_credential.md)
## Roles
#### aimprovider
- Install agent-based Credential Provider (AIM) on Linux hosts
[Playbooks and Module Info](https://github.com/cyberark/ansible-security-automation-collection/blob/master/docs/aimprovider.md)
#### Python3
- The modules will work with either python2 or python3.
#### Author Information
- CyberArk Business Development Technical Team
- @enunez-cyberark
- @eemotacyber
- @jimmyjamcabd

View File

@@ -0,0 +1,32 @@
# CyberArk PAS REST API
Custom Credential Type for Ansible Tower
## Installation
1. Login to Ansible Tower as a Tower Administrator.
2. Under Administration, click on Credential Type.
3. Click the green [ + ] in the top right-hand corner to create a new Custom Credential Type.
4. Set the name of your Credential Type. e.g. `CyberArk PAS REST API`
5. Under `Input Configuration` select `YAML`.
6. Copy and paste the [input.yml](input.yml) into the text field for `Input Configuration`.
7. Under `Injector Configuration` select `YAML`.
8. Copy and paste the [injector.yml](injector.yml) into the text field for `Injector Configuration`.
9. Click `Save` at the bottom to save the Custom Credential Type.
## Usage
Reference the following environment variables within your Ansible Playbook when using this Credential Type:
* `CYBERARK_API_URL` \
This is the Base URI of your CyberArk Password Vault Web Access (PVWA). _e.g. `https://pvwa.cyberark.com`_
* `CYBERARK_API_USERNAME` \
This is the username to use when logging into the CyberArk PAS Web Services SDK (REST API).
* `CYBERARK_API_PASSWORD` \
This is the password associated with the username provided for login.
## Maintainer
Joe Garcia, CISSP - DevOps Security Engineer, CyberArk - [@infamousjoeg](https://github.com/infamousjoeg)

View File

@@ -0,0 +1,4 @@
extra_vars:
CYBERARK_API_PASSWORD: '{{ password }}'
CYBERARK_API_URL: '{{ pvwa_url }}'
CYBERARK_API_USERNAME: '{{ username }}'

View File

@@ -0,0 +1,18 @@
fields:
- id: username
type: string
label: Username
help_text: CyberArk REST API Username
- id: password
type: string
label: Password
secret: true
help_text: CyberArk REST API Password
- id: pvwa_url
type: string
label: PVWA URL
help_text: 'CyberArk PVWA URL e.g. https://pvwa.cyberark.com'
required:
- username
- password
- pvwa_url

View File

@@ -0,0 +1,2 @@
---
requires_ansible: '>=2.9'

View File

@@ -0,0 +1,392 @@
#!/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)
version_added: '1.0.0'
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_ldap_authentication:
type: bool
default: 'no'
description:
- Whether or not LDAP will be used.
use_windows_authentication:
type: bool
default: 'no'
description:
- Whether or not Windows will be used.
use_cyberark_authentication:
type: bool
default: 'no'
description:
- Whether or not LDAP 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.
concurrentSession:
type: bool
default: False
description:
- Whether or not to allow concurrent sessions for the same user.
cyberark_session:
description:
- Dictionary set by a CyberArk authentication containing the
different values to perform actions on a logged-on CyberArk
session.
type: dict
timeout:
description:
- Allows you set a timeout for when your authenticating to Cyberark
default: 10
type: int
"""
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
from ansible.module_utils.six.moves.http_client import HTTPException
import json
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_radius = module.params["use_radius_authentication"]
use_ldap = module.params["use_ldap_authentication"]
use_windows = module.params["use_windows_authentication"]
use_cyberark = module.params["use_cyberark_authentication"]
# connection_number = module.params["connection_number"]
state = module.params["state"]
cyberark_session = module.params["cyberark_session"]
concurrentSession = module.params["concurrentSession"]
timeout = module.params["timeout"]
# 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",
"User-Agent": "CyberArk/1.0 (Ansible; cyberark.pas)"
}
payload = ""
if state == "present": # Logon Action
# Different end_points based on the use of desired method of auth
if use_ldap:
end_point = "/PasswordVault/API/Auth/LDAP/Logon"
payload_dict = {"username": username, "password": password}
elif use_radius:
end_point = "/PasswordVault/API/Auth/radius/Logon"
elif use_windows:
end_point = "/PasswordVault/API/auth/Windows/Logon"
else:
use_cyberark = True
end_point = "/PasswordVault/API/Auth/CyberArk/Logon"
# The payload will contain username, password
# and optionally use_radius_authentication and new_password
payload_dict = {"username": username, "password": password}
if new_password is not None and use_cyberark:
payload_dict["newPassword"] = new_password
# COMMENT: I dont know what this is for and the old api seems like it didnt have this field
# if connection_number is not None:
# payload_dict["connectionNumber"] = connection_number
if concurrentSession:
payload_dict["concurrentSession"] = True
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"]
headers["Authorization"] = cyberark_session["token"]
# All off the logoff with the same endpoint
end_point = "/PasswordVault/API/Auth/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,
timeout=timeout,
)
except (HTTPError, 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 = ""
try:
token = str(json.loads(response.read()))
# the new one just returns a token
# if use:
# 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,
}
}
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_radius_authentication": {"default": False, "type": "bool"},
"use_windows_authentication": {"default": False, "type": "bool"},
"use_ldap_authentication": {"default": False, "type": "bool"},
"use_cyberark_authentication": {"default": False, "type": "bool"},
"concurrentSession": {"default": False, "type": "bool"},
"connection_number": {"type": "int"},
"state": {
"type": "str",
"choices": ["present", "absent"],
"default": "present",
},
"cyberark_session": {"type": "dict"},
"timeout": {"default": 10, "type": "int"},
}
# cyberark and radius -> mutually_exclusive is cyberark and ldap
# ldap and radius
# windows has to be by itself
mutually_exclusive = [
[
"use_windows_authentication",
"use_ldap_authentication",
"use_cyberark_authentication",
"use_radius_authentication",
],
["use_radius_authentication", "new_password"],
["use_windows_authentication", "new_password"],
["use_ldap_authentication", "new_password"],
["api_base_url", "cyberark_session"],
]
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()

View File

@@ -0,0 +1,337 @@
#!/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: '1.0.0'
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: str
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
from ansible.module_utils.six.moves.http_client import HTTPException
import json
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, 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, "no_log": True},
}
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()

View File

@@ -0,0 +1,782 @@
#!/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: '1.0.0'
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: false
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.pas.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
domain_name:
description:
- The name of the user domain.
type: str
member_type:
description:
- The type of member.
type: str
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.
- Causes an additional lookup in cyberark
- Will be ignored if vault_id is used
- Will cause a failure if group is missing or more than one group with that name exists
type: str
timeout:
description:
- How long to wait for the server to send data before giving up
type: float
default: 10
vault_id:
description:
- The ID of the user group to add the user to
- Prefered over group_name
type: int
authorization:
description:
- A list of authorization options for this user.
- Options can include AddSafes and AuditUsers
- The default provides backwards compatability with older versions of the collection
type: list
elements: str
default:
- AddSafes
- AuditUsers
"""
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
from ansible.module_utils.six.moves.urllib.parse import quote
import logging
def construct_url(api_base_url, end_point):
return "{baseurl}/{endpoint}".format(baseurl=api_base_url.rstrip("/"), endpoint=end_point.lstrip("/"))
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/{pusername}".format(pusername=username)
url = construct_url(api_base_url, end_point)
headers = {
"Content-Type": "application/json",
"Authorization": cyberark_session["token"],
"User-Agent": "CyberArk/1.0 (Ansible; cyberark.pas)"
}
try:
response = open_url(
url,
method="GET",
headers=headers,
validate_certs=validate_certs,
timeout=module.params['timeout'],
)
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\n ==> %s"
% (url, 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\n%s"
% (url, 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"],
"User-Agent": "CyberArk/1.0 (Ansible; cyberark.pas)"
}
# 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/api/Users"
payload["UserName"] = username
if (
"initial_password" in list(module.params.keys())
and module.params["initial_password"] is not None
):
payload["InitialPassword"] = module.params["initial_password"]
elif HTTPMethod == "PUT":
# With the put in this old format, we can not update the vaultAuthorization
end_point = "/PasswordVault/WebServices/PIMServices.svc/Users/{pusername}".format(pusername=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"]
# In API V2 the parameter is called userType, V2 ignores the UserTypeName
payload["userType"] = 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"]
if module.params.get("authorization", None) is not None:
payload["vaultAuthorization"] = module.params["authorization"]
# --------------------------------------------------------------
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",
"UserTypeName",
"vaultAuthorization",
]
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")
url = construct_url(api_base_url, end_point)
try:
# execute REST action
response = open_url(
url,
method=HTTPMethod,
headers=headers,
data=json.dumps(payload),
validate_certs=validate_certs,
timeout=module.params['timeout'],
)
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\n ==> %s"
% (url, 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\n%s"
% (url, to_text(unknown_exception))
),
payload=payload,
headers=headers,
status_code=-1,
)
else:
return (False, existing_info, 200)
def resolve_username_to_id(module):
username = module.params["username"]
cyberark_session = module.params["cyberark_session"]
api_base_url = cyberark_session["api_base_url"]
validate_certs = cyberark_session["validate_certs"]
url = construct_url(api_base_url, "PasswordVault/api/Users?search={pusername}".format(pusername=username))
headers = {
"Content-Type": "application/json",
"Authorization": cyberark_session["token"],
"User-Agent": "CyberArk/1.0 (Ansible; cyberark.pas)"
}
try:
response = open_url(
url,
method="GET",
headers=headers,
validate_certs=validate_certs,
timeout=module.params['timeout'],
)
users = json.loads(response.read())
# Return None if the user does not exist
user_id = None
# Say we have two users: 'someone' and 'someoneelse', a search on someone will return both
# So we will lopp over and see if the username returned matches the username we searched for
# If so, and we somehow found more than one raise an error
for user in users['Users']:
if user['username'] == username:
if user_id is None:
user_id = user['id']
else:
module.fail_json(msg=("Found more than one user matching %s, this should be impossible" % (username)))
# If we made it here we had 1 or 0 users, return them
logging.debug("Resolved username {%s} to ID {%s}", username, user_id)
return user_id
except (HTTPError, httplib.HTTPException) as http_exception:
exception_text = to_text(http_exception)
module.fail_json(msg=(
"Error while performing user_search."
"Please validate parameters provided."
"\n*** end_point=%s\n ==> %s"
% (url, exception_text)),
headers=headers,
status_code=http_exception.code,
)
except Exception as unknown_exception:
module.fail_json(msg=(
"Unknown error while performing user search."
"\n*** end_point=%s\n%s"
% (url, to_text(unknown_exception))),
headers=headers,
status_code=-1,
)
def user_delete(module):
# Get username from module parameters, and api base url
# along with validate_certs from the cyberark_session established
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 = {}
vault_user_id = resolve_username_to_id(module)
# If the user was not found by username we can return unchanged
if vault_user_id is None:
return (False, result, None)
end_point = ("PasswordVault/api/Users/{pvaultuserid}").format(pvaultuserid=vault_user_id)
headers = {
"Content-Type": "application/json",
"Authorization": cyberark_session["token"],
"User-Agent": "CyberArk/1.0 (Ansible; cyberark.pas)"
}
url = construct_url(api_base_url, end_point)
try:
# execute REST action
response = open_url(
url,
method="DELETE",
headers=headers,
validate_certs=validate_certs,
timeout=module.params['timeout'],
)
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\n ==> %s"
% (url, 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\n%s"
% (url, to_text(unknown_exception))
),
headers=headers,
status_code=-1,
)
def resolve_group_name_to_id(module):
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"]
headers = {
"Content-Type": "application/json",
"Authorization": cyberark_session["token"],
"User-Agent": "CyberArk/1.0 (Ansible; cyberark.pas)"
}
url = construct_url(api_base_url, "/PasswordVault/api/UserGroups?search={pgroupname}".format(pgroupname=quote(group_name)))
try:
response = open_url(
url,
method="GET",
headers=headers,
validate_certs=validate_certs,
timeout=module.params['timeout'],
)
groups = json.loads(response.read())
# Return None if the user does not exist
group_id = None
# Say we have two groups: 'groupone' and 'grouptwo', a search on group will return both
# So we will lopp over and see if the groupname returned matches the groupsname we searched for
# If so, and we somehow found more than one raise an error
for group in groups['value']:
if group['groupName'] == group_name:
if group_id is None:
group_id = group['id']
else:
module.fail_json(msg=("Found more than one group matching %s. Use vault_id instead" % (group_name)))
# If we made it here we had 1 or 0 users, return them
logging.debug("Resolved group_name %s to ID %s", group_name, group_id)
return group_id
except (HTTPError, httplib.HTTPException) as http_exception:
module.fail_json(msg=(
"Error while looking up group %s.\n*** end_point=%s\n ==> %s"
% (group_name, url, to_text(http_exception))),
payload={},
headers=headers,
status_code=http_exception.code,
)
except Exception as unknown_exception:
module.fail_json(msg=(
"Unknown error while looking up group %s.\n*** end_point=%s\n%s"
% (group_name, url, to_text(unknown_exception))),
payload={},
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
# Not needed for new version
username = module.params["username"]
group_name = module.params["group_name"]
vault_id = module.params["vault_id"]
member_type = (
"Vault"
if module.params["member_type"] is None
else module.params["member_type"]
)
domain_name = module.params["domain_name"] if member_type == "domain" else None
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 = {}
headers = {
"Content-Type": "application/json",
"Authorization": cyberark_session["token"],
"User-Agent": "CyberArk/1.0 (Ansible; cyberark.pas)"
}
# If we went "old school" and were provided a group_name instead of a vault_id we need to resolve it
if group_name and not vault_id:
# If we were given a group_name we need to lookup the vault_id
vault_id = resolve_group_name_to_id(module)
if vault_id is None:
module.fail_json(msg="Unable to find a user group named {pgroupname}, please create that before adding a user to it".format(pgroupname=group_name))
end_point = ("/PasswordVault/api/UserGroups/{pvaultid}/Members").format(pvaultid=vault_id)
# For some reason the group add uses username instead of id
payload = {"memberId": username, "memberType": member_type}
if domain_name:
payload["domainName"] = domain_name
url = construct_url(api_base_url, end_point)
try:
# execute REST action
response = open_url(
url,
method="POST",
headers=headers,
data=json.dumps(payload),
validate_certs=validate_certs,
timeout=module.params['timeout'],
)
result = {"result": {}}
return (True, result, response.getcode())
except (HTTPError, httplib.HTTPException) as http_exception:
exception_text = to_text(http_exception)
exception_body = json.loads(http_exception.read().decode())
if http_exception.code == 409 and ("ITATS262E" in exception_text or exception_body.get("ErrorCode", "") == "PASWS213E"):
# 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\n ==> %s"
% (url, exception_text)
),
payload=payload,
headers=headers,
status_code=http_exception.code,
response=http_exception.read().decode(),
)
except Exception as unknown_exception:
module.fail_json(
msg=(
"Unknown error while performing user_add_to_group."
"\n*** end_point=%s\n%s"
% (url, 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", default=False),
expiry_date=dict(type="str"),
user_type_name=dict(type="str"),
disabled=dict(type="bool", default=False),
location=dict(type="str"),
group_name=dict(type="str"),
vault_id=dict(type="int"),
member_type=dict(type="str"),
domain_name=dict(type="str"),
timeout=dict(type="float", default=10),
authorization=dict(type="list", elements="str", required=False, default=['AddSafes', 'AuditUsers']),
)
)
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"]
vault_id = module.params["vault_id"]
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"]
)
elif status_code == 404:
# User does not exist, proceed to create it
(changed, result, status_code) = user_add_or_update(module, "POST", None)
# Add user to group if needed
if group_name is not None or vault_id is not None:
(group_change, no_result, no_status_code) = user_add_to_group(module)
changed = changed or group_change
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()

View File

@@ -0,0 +1,91 @@
cyberark.pas.aimprovider
====================
Role to install/uninstall CyberArk's AIM Credential Provider.
Requirements
------------
- CyberArk Privileged Account Security Web Services SDK.
- `cyberark.pas` Collection from Ansible Galaxy or Automation Hub
Role Variables
--------------
```
# CyberArk's Privileged Account Security Web Services SDK api base URL (example: https://components.cyberark.local)
rest_api_url: ""
# Whether to validate certificates for REST api calls. If false, SSL certificates will not be validated. This should only be used on personally controlled sites using self-signed certificates.
validate_certs: true
# Zip file with distribution of AIM Provider (example: /tmp/binaries/RHELinux x64-Rls-v9.8.zip); this file is located in the Ansible server, and it will be copied to the Ansible nodes. It should point to the current version of AIM distribution to be used when delivering to the nodes in a central folder within the Ansible server.
zip_file_name: ""
# Folder name within the ZIP file that will be used. By default, it's taken from zip file name, for example: "RHELinux x64"
folder_name: '{{zip_file_name.split("/")[-1].split("-Rls")[0]}}'
# CyberArk location for App Provider user to be created
app_provider_user_location: "\\Applications"
# CyberArk Vault Address
vault_address: ""
# Whether to use shared logon authentication. If true, it will use the "Shared Logon Authentication" as described in the CyberArk's document "Privileged Account Security Web Services SDK Implementation Guide"
use_shared_logon_authentication: false
# State - can be "present"/"absent" for install/uninstall.
state: "present"
```
Additionally:
- **app_provider_user_group**: The name of the group the Provider user will be added to.
Dependencies
------------
None.
Example Playbook
----------------
1) Install CyberArk AIM Provider.
```
---
- hosts: all
roles:
- role: cyberark.pas.aimprovider
api_base_url: "https://components.cyberark.local"
validate_certs: false
zip_file_name: "/tmp/binaries/RHELinux x64-Rls-v9.8.zip"
vault_address: "10.0.1.10"
use_shared_logon_authentication: true
```
2) Uninstall CyberArk AIM Provider.
```
---
- hosts: all
roles:
- role: cyberark.pas.aimprovider
api_base_url: "https://components.cyberark.local"
use_shared_logon_authentication: true
state: "absent"
validate_certs: false
```
License
-------
MIT
Author Information
------------------
- Edward Nunez (edward.nunez@cyberark.com)

View File

@@ -0,0 +1,27 @@
---
# Default values for possible input parameters
# CyberArk's Privileged Account Security Web Services SDK api base URL
rest_api_url: ""
# Whether to validate certificates for REST api calls
validate_certs: true
# Zip file with distribution of AIM Provider
zip_file_name: ""
# Folder name within the ZIP file that will be used by default is taken from zip file name.
folder_name: '{{zip_file_name.split("/")[-1].split("-Rls")[0]}}'
# CyberArk location for App Provider user to be created
app_provider_user_location: "\\Applications"
# CyberArk Vault Address
vault_address: ""
# Whether to use shared logon authentication
use_shared_logon_authentication: false
# State - the state of the provider: present mean installing the provide and Absent means uninstalling
state: "present"

View File

@@ -0,0 +1,152 @@
---
- name: Validating Role Parameters
assert:
that:
- zip_file_name != ''
- vault_address != ''
- api_base_url != ''
- folder_name != ''
- app_provider_user_location != ''
- state == "present"
- (not use_shared_logon_authentication|default(false) and password_object is defined) or
(use_shared_logon_authentication|default(false) and password_object is not defined)
- debug: msg="Installation params => zip_file_name = {{zip_file_name}} folder_name={{folder_name}}"
- block:
- name: Copy provider zip to target and unzip
unarchive: src="{{zip_file_name}}" dest=/tmp
- name: Rename aimparms and copy to var/tmp
command: cp "/tmp/{{folder_name}}/aimparms.sample" /var/tmp/aimparms
- name: Replace parameters" in /var/tmp/aimparms
replace:
dest: /var/tmp/aimparms
regexp: "{{item.regexp}}"
replace: "{{item.replace}}"
with_items:
- {regexp: '^AcceptCyberArkEULA=.*$', replace: 'AcceptCyberArkEULA=Yes'}
- {regexp: '^LicensedProducts=.*$', replace: 'LicensedProducts=AIM'}
- {regexp: '^.?CreateVaultEnvironment=.*$', replace: 'CreateVaultEnvironment=no'}
- {regexp: '^VaultFilePath=.*$', replace: 'VaultFilePath=/tmp/{{folder_name}}/Vault.ini'}
- name: Change Vault.ini to the right address
replace:
dest: "/tmp/{{folder_name}}/Vault.ini"
regexp: '^ADDRESS=.*$'
replace: 'ADDRESS={{vault_address}}'
- name: Change permission on createcredfile
file:
path: "/tmp/{{folder_name}}/CreateCredFile"
mode: 0755
- find:
paths: "/tmp/{{folder_name}}"
patterns: "CARKaim-*.rpm"
register: aimrpm
# debug: msg="{{aimrpm.files[0].path}}"
- name: Install Provider
package: name='{{aimrpm.files[0].path}}' state=present
- name: Verify status of service after installing Provider
command: service aimprv status
register: command_result
ignore_errors: yes
args:
warn: false
# debug: msg="status of service RC={{command_result.rc}}"
- name: Logon to CyberArk Vault using PAS Web Services SDK - use_shared_logon_authentication
cyberark.pas.cyberark_authentication:
api_base_url: "{{ api_base_url }}"
use_shared_logon_authentication: true
validate_certs: "{{ validate_certs }}"
changed_when: false
when: (command_result.rc != 0 and use_shared_logon_authentication|default(false))
- name: Logon to CyberArk Vault using PAS Web Services SDK - Not use_shared_logon_authentication
cyberark.pas.cyberark_authentication:
api_base_url: "{{ api_base_url }}"
username: "{{ password_object.password }}"
password: "{{ password_object.passprops.username }}"
validate_certs: "{{ validate_certs }}"
changed_when: false
when: (command_result.rc != 0 and not use_shared_logon_authentication|default(false))
# name: Debug message
# debug:
# msg: "{{ cyberark_session.token }}"
# when: (command_result.rc != 0)
- name: Create provider user
cyberark.pas.cyberark_user:
username: "Prov_{{ ansible_hostname }}"
initial_password: "Cyberark1"
user_type_name: "AppProvider"
location: "{{ app_provider_user_location }}"
group_name: "{{ app_provider_user_group }}"
change_password_on_the_next_logon: false
state: present
cyberark_session: "{{ cyberark_session }}"
register: cyberarkaction
when: (command_result.rc != 0)
# debug:
# msg: "USERCREATED => {{cyberarkaction}}"
# when: (command_result.rc != 0 and cyberarkaction.status_code == 201)
- name: Reset provider user credential
cyberark.pas.cyberark_user:
username: "Prov_{{ ansible_hostname }}"
new_password: "Cyberark1"
disabled: false
state: present
cyberark_session: "{{ cyberark_session }}"
register: cyberarkaction
when: (command_result.rc != 0 and cyberarkaction.status_code == 200)
- name: Logoff from CyberArk Vault
cyberark.pas.cyberark_authentication:
state: absent
cyberark_session: "{{ cyberark_session }}"
changed_when: false
when: (command_result.rc != 0)
- name: Create Provider Initial Cred File
command: /opt/CARKaim/bin/createcredfile /etc/opt/CARKaim/vault/appprovideruser.cred Password -Username Prov_{{ ansible_hostname }} -Password Cyberark1
when: (command_result.rc != 0)
- name: Set vault.ini Into Place
command: cp "/tmp/{{folder_name}}/Vault.ini" /etc/opt/CARKaim/vault/vault.ini
- name: Start Provider Service
service: name=aimprv state=started
when: (command_result.rc != 0)
- name: Remove /tmp/{{folder_name}}
file:
path: '/tmp/{{folder_name}}'
state: absent
- name: Remove /var/tmp/aimparms
file:
path: '/var/tmp/aimparms'
state: absent
rescue:
- name: Remove /tmp/{{folder_name}}
file:
path: '/tmp/{{folder_name}}'
state: absent
- fail:
msg: "AIM Credential Provider Installation failed!"

View File

@@ -0,0 +1,24 @@
---
- name: Validating Role Parameters
assert:
that:
- api_base_url != ''
- state in ["present", "absent"]
- (not use_shared_logon_authentication|default(false) and password_object is defined) or
(use_shared_logon_authentication|default(false) and password_object is not defined)
- name: Verify status of aimprv service initially
command: service aimprv status
register: service_already_running
ignore_errors: yes
changed_when: false
args:
warn: false
- debug: msg="status of service RC={{service_already_running.rc}}"
- import_tasks: installAIMProvider.yml
when: (state == "present" and service_already_running.rc != 0)
- import_tasks: uninstallAIMProvider.yml
when: (state == "absent" and service_already_running.rc == 0)

View File

@@ -0,0 +1,61 @@
---
- block:
- name: Uninstall Provider
package: name='CARKaim' state=absent
- name: Logon to CyberArk Vault using PAS Web Services SDK - use_shared_logon_authentication
cyberark.pas.cyberark_authentication:
api_base_url: "{{ api_base_url }}"
use_shared_logon_authentication: true
validate_certs: "{{ validate_certs }}"
when: (use_shared_logon_authentication)
- name: Logon to CyberArk Vault using PAS Web Services SDK - Not use_shared_logon_authentication
cyberark.pas.cyberark_authentication:
api_base_url: "{{ api_base_url }}"
username: "{{ password_object.password }}"
password: "{{ password_object.passprops.username }}"
validate_certs: "{{ validate_certs }}"
changed_when: false
when: (not use_shared_logon_authentication)
# name: Debug message
# debug:
# msg: "{{ cyberark_session }}"
# when: (cyberark_session.token is defined)
- name: Remove Provider User
cyberark.pas.cyberark_user:
username: "Prov_{{ansible_hostname}}"
state: absent
cyberark_session: "{{ cyberark_session }}"
register: cyberarkaction
ignore_errors: yes
when: (cyberark_session.token is defined)
# debug:
# msg: "USERDETAILS => {{cyberarkaction}}"
# when: (cyberarkaction.status_code == 200)
- name: Logoff from CyberArk Vault
cyberark.pas.cyberark_authentication:
state: absent
cyberark_session: "{{ cyberark_session }}"
changed_when: false
when: (cyberark_session.token is defined)
- name: Remove /etc/opt/CARKaim
file:
path: '/etc/opt/CARKaim'
state: absent
- name: Remove /var/opt/CARKaim
file:
path: '/var/opt/CARKaim'
state: absent
rescue:
- fail:
msg: "AIM Credential Provider Uninstall failed!"