diff --git a/README.md b/README.md index 9a65b90..1d4ef40 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,10 @@ The One Identity Privilege Manager Ansible Collection, referred to as `ansible-p * [`get_sudoers module`](roles/sudoers/README.md#plugins) Returns the list of sudoers files (the main sudoers and all other included sudoers files) and a single complete sudoers file in which all include directives have been replaced by the content of the included files. * [`save_sudoers module`](roles/sudoers/README.md#plugins) Saves the complete sudoers file on the controller node. +* [`sudo_policy_for_unix_host role`](roles/sudo_policy_for_unix_host/README.md): List the version of Privilege Manager for sudo plugins and the sudo policies in use on all client hosts that are joined to the policy group. + * [`get_sudo_policy_for_unix_host module`](roles/sudo_policy_for_unix_host/README.md#plugins): Runs pmsrvinfo binary and returns its results. + * [`latestsudopolicies filter`](roles/sudo_policy_for_unix_host/README.md#plugins) Selects the latest plugins for each host. + ## Installation ### Prerequisites diff --git a/examples/README.md b/examples/README.md index 19cc234..441255c 100644 --- a/examples/README.md +++ b/examples/README.md @@ -21,3 +21,7 @@ The [`join`](run_join.yml) role example shows use of the `join` role in an Ansbi ## `sudoers` Role Example The [`sudoers`](run_sudoers.yml) role example shows use of the `sudoers` role in an Ansbile playbook. The variables most likely to be overriden have been included in this playbook for your convenience even though many are still set to their default values. + +## `sudo_policy_for_unix_host` Role Example + +The [`sudo_policy_for_unix_host`](run_sudo_policy_for_unix_host.yml) role example shows use of the `sudo_policy_for_unix_host` role in an Ansbile playbook. The variables most likely to be overriden have been included in this playbook for your convenience even though many are still set to their default values. diff --git a/examples/run_sudo_policy_for_unix_host.yml b/examples/run_sudo_policy_for_unix_host.yml new file mode 100644 index 0000000..31f0a83 --- /dev/null +++ b/examples/run_sudo_policy_for_unix_host.yml @@ -0,0 +1,17 @@ +--- + +- hosts: all + gather_facts: false + + # The variables you would most likely want/need to override have been included + vars: + + # Facts + sudo_policy_for_unix_host_facts_generate: true + + # Reports + sudo_policy_for_unix_host_reports_generate: true + sudo_policy_for_unix_host_reports_backup: false + + roles: + - name: oneidentity.privilege_manager.sudo_policy_for_unix_host diff --git a/plugins/filter/sudo_policy_for_unix_host_filters.py b/plugins/filter/sudo_policy_for_unix_host_filters.py new file mode 100644 index 0000000..4a0f95e --- /dev/null +++ b/plugins/filter/sudo_policy_for_unix_host_filters.py @@ -0,0 +1,74 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# ------------------------------------------------------------------------------ +# Copyright (c) 2021, One Identity LLC +# File: sudo_policy_for_unix_host_filters.py +# Desc: Ansible filters for sudo_policy_for_unix_host role +# Auth: Laszlo Nagy +# Note: +# ------------------------------------------------------------------------------ + + +# ------------------------------------------------------------------------------ +# Imports +# ------------------------------------------------------------------------------ + +# Future module imports for consistency across Python versions +from __future__ import absolute_import, division, print_function + +# Want classes to be new type for consistency across Python versions +__metaclass__ = type + +from ansible.errors import AnsibleFilterError + + +# ------------------------------------------------------------------------------ +# Helper functions +# ------------------------------------------------------------------------------ + +# ------------------------------------------------------------------------------ +def get_latest_sudo_policies(sudo_policies_list): + """ + Example of sudo_policies_list: + [ + ['qpm-rhel6-64a', '/etc/opt/quest/qpm4u/policy/sudoers', '7.1.99.7-55-g787b0a37a', '1634124307'], + ['qpm-rhel6-64b', '/etc/opt/quest/qpm4u/policy/sudoers', '7.1.99.7-55-g787b0a37b', '1634124308'], + ['qpm-rhel6-64c', '/etc/opt/quest/qpm4u/policy/sudoers', '7.1.99.7-55-g787b0a37c', '1634124309'], + ['qpm-rhel6-64d', '/etc/opt/quest/qpm4u/policy/sudoers', '7.1.99.7-55-g787b0a37d', '1634124310'], + ['qpm-rhel6-64c', '/etc/opt/quest/qpm4u/policy/sudoers', '7.1.99.7-55-g787b0a37c', '1634124369'], + ['qpm-rhel6-64d', '/etc/opt/quest/qpm4u/policy/sudoers', '7.1.99.7-55-g787b0a37d', '1634124370'], + ['qpm-rhel6-64e', '/etc/opt/quest/qpm4u/policy/sudoers', '7.1.99.7-55-g787b0a37e', '1634124371'], + ['qpm-rhel6-64f', '/etc/opt/quest/qpm4u/policy/sudoers', '7.1.99.7-55-g787b0a37f', '1634124372'] + ] + """ + + latest_sudo_policies = {} + for sudo_policy in sudo_policies_list: + hostname = sudo_policy[0] + if hostname not in latest_sudo_policies: + latest_sudo_policies[hostname] = sudo_policy + else: + if int(latest_sudo_policies[hostname][3]) < int(sudo_policy[3]): + latest_sudo_policies[hostname] = sudo_policy + + latest_sudo_policies = list(latest_sudo_policies.values()) + + return latest_sudo_policies + + +# ------------------------------------------------------------------------------ +# Classes +# ------------------------------------------------------------------------------ + +# ------------------------------------------------------------------------------ +class FilterModule(object): + """ + sudo_policy_for_unix_host role jinja2 filters + """ + + def filters(self): + filters = { + 'latestsudopolicies': get_latest_sudo_policies, + } + return filters diff --git a/plugins/modules/get_sudo_policy_for_unix_host.py b/plugins/modules/get_sudo_policy_for_unix_host.py new file mode 100644 index 0000000..60b9830 --- /dev/null +++ b/plugins/modules/get_sudo_policy_for_unix_host.py @@ -0,0 +1,283 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# ------------------------------------------------------------------------------ +# Copyright (c) 2021, One Identity LLC +# File: get_sudo_policy_for_unix_host.py +# Desc: Ansible module for sudo_policy_for_unix_host role that runs pmsrvinfo +# and returns its results. +# Auth: Laszlo Nagy +# Note: +# ------------------------------------------------------------------------------ + + +# ------------------------------------------------------------------------------ +# Required Ansible documentation +# ------------------------------------------------------------------------------ + +ANSIBLE_METADATA = { + 'metadata_version': '0.2', + 'status': ['preview'], + 'supported_by': 'community' +} + +DOCUMENTATION = """ +--- +module: get_sudo_policy_for_unix_host.py + +short_description: > + Returns the sudo policy in use + +version_added: '2.9' + +description: > + Returns the version of Privilege Manager for sudo plugins and the sudo policies in use + +options: + facts: + description: + - Generate Ansible facts? + type: bool + required: false + default: true + facts_key: + description: + - Ansible facts key + type: str + required: false + default: 'sudo_policy_for_unix_host' + +author: + - Laszlo Nagy (laszlo.nagy@oneidentity.com) +""" + +EXAMPLES = """ +- name: Normal usage + get_sudo_policy_for_unix_host: + facts: true + register: get_sudo_policy_for_unix_host_result +""" + +RETURN = """ +ansible_facts: + description: All non-standard return values are placed in Ansible facts + type: dict + returned: when facts parameter is true + keys: + changed: + description: Did the state of the host change? + type: bool + returned: always + failed: + description: Did the module fail? + type: bool + returned: always + msg: + description: Additional information if failed + type: str + returned: always + params: + description: Parameters passed in + type: dict + returned: always + sudo_policy_for_unix_host: + description: hostname, policy plugin, version and timestamp of each host + type: list of lists + returned: always +""" + + +# ------------------------------------------------------------------------------ +# Imports +# ------------------------------------------------------------------------------ + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.common.text.converters import to_text +from io import StringIO +import csv +import platform +import subprocess +import sys +import traceback +import ansible_collections.oneidentity.authentication_services.plugins.module_utils.vastool as vt +import ansible_collections.oneidentity.authentication_services.plugins.module_utils.check_file_exec as cfe + + +# ------------------------------------------------------------------------------ +# Constants +# ------------------------------------------------------------------------------ + +# Arg defaults +FACTS_DEFAULT = True +FACTS_KEY_DEFAULT = 'sudo_policy_for_unix_host' + +PMSRVINFO_PATH = '/opt/quest/sbin/pmsrvinfo' + +# ------------------------------------------------------------------------------ +# Functions +# ------------------------------------------------------------------------------ + +# ------------------------------------------------------------------------------ +def run_module(): + """ + Main Ansible module function + """ + + # Module argument info + module_args = { + 'facts': { + 'type': 'bool', + 'required': False, + 'default': FACTS_DEFAULT + }, + 'facts_key': { + 'type': 'str', + 'required': False, + 'default': FACTS_KEY_DEFAULT + } + } + + # Seed result value + result = { + 'changed': False, + 'failed': False, + 'msg': '' + } + + # Lean on boilerplate code in AnsibleModule class + module = AnsibleModule( + argument_spec=module_args, + supports_check_mode=True + ) + + # Run logic + # NOTE: This module makes no changes so check mode doesn't need to be handled + # specially + err, result = run_normal(module.params, result) + + # Exit + module.exit_json(**result) + + +# ------------------------------------------------------------------------------ +def run_normal(params, result): + """ + Normal mode logic. + + params contains input parameters. + + result contains run results skeleton, will modify/add to and then return + this value along with an err value that contains None if no error or a string + describing the error. + """ + + # Return data + err = None + version = '' + sudo_policies = [] + + # Parameters + facts = params['facts'] + facts_key = params['facts_key'] if params['facts_key'] else FACTS_KEY_DEFAULT + + try: + + while True: + err, version = cfe.check_file_exec(PMSRVINFO_PATH, '') + if err is not None: + break + + err, sudo_policies = run_pmsrvinfo() + if err is not None: + break + + break + + except Exception: + tb = traceback.format_exc() + err = str(tb) + + # Build result + result['changed'] = False # this module never makes any changes to the host + result['failed'] = err is not None + result['msg'] = err if err is not None else '' + + # Create ansible_facts data + if facts: + result_facts = result.copy() + result_facts['params'] = params + result_facts['sudo_policy_for_unix_host'] = sudo_policies + result['ansible_facts'] = {facts_key: result_facts} + + # Return + return err, result + + +# ------------------------------------------------------------------------------ +def run_pmsrvinfo(): + + # Return values + err = None + sudo_policies = [] + + # Build pmsrvinfo command + cmd = [] + cmd += [PMSRVINFO_PATH] + cmd += ['-l'] + cmd += ['-c'] + + # Call asdcom + try: + p = subprocess.Popen(' '.join(cmd), stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) + rval_bytes, rval_err = p.communicate() + rval_bytes += rval_err + # This exception happens when the process exits with a non-zero return code + except subprocess.CalledProcessError as e: + # Just grab output bytes likes a normal exit, we'll parse it for errors anyway + rval_bytes = e.output + if p.returncode == 0: + # Popen returns list of bytes so we have to decode to get a string + rval_str = rval_bytes.decode(sys.stdout.encoding) + + # Parse pmsrvinfo return + err, sudo_policies = parse_pmsrvinfo_stdout(rval_str) + + # Return + return err, sudo_policies + + +# ------------------------------------------------------------------------------ +def parse_pmsrvinfo_stdout(stdout_str): + """ + Example result: + $ /opt/quest/sbin/pmsrvinfo -l -c + qpm-rhel6-64d,/etc/opt/quest/qpm4u/policy/sudoers,7.1.99.7-55-g787b0a37e,1634124307 + qpm-rhel6-64c,/etc/opt/quest/qpm4u/policy/sudoers,7.1.99.10-6-g8c6b6955d,1634124308 + """ + + # Return values + err = None + sudo_policies = [] + + text_stream = StringIO(stdout_str) + csv_reader = csv.reader(text_stream) + for row in csv_reader: + sudo_policies.append([ row[0], row[1], row[2], row[3] ]) + + # Return + return err, sudo_policies + + +# ------------------------------------------------------------------------------ +def main(): + """ + Main + """ + + run_module() + + +# When run from command line +# ------------------------------------------------------------------------------ +if __name__ == '__main__': + main() diff --git a/roles/sudo_policy_for_unix_host/README.md b/roles/sudo_policy_for_unix_host/README.md new file mode 100644 index 0000000..5c7863f --- /dev/null +++ b/roles/sudo_policy_for_unix_host/README.md @@ -0,0 +1,97 @@ +# `sudo_policy_for_unix_host` Role + +The `sudo_policy_for_unix_host` role creates CSV and HTML reports that list the version of Privilege Manager for sudo plugins and the sudo policies in use on all client hosts that are joined to the policy group. + +## Requirements + +The role requires the [Privilege Manager](https://www.oneidentity.com/products/privilege-manager-for-sudo/) policy server to be installed and configured on all managed nodes. + +The role requires [Privilege Manager](https://www.oneidentity.com/products/privilege-manager-for-sudo/) version 7.2.x or later. + +## Variables + +All of the variables shown below have a default value but can be overridden to suit your environment. Variable overriding can be done in playbooks, inventories, from the command line using the `-e` switch with the `ansible-playbook` command, or from Ansible Tower and AWX. See [Ansbile documentation](https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html) for further information. + +### Facts generation + +Facts generation variable defaults for all roles are set by variables in the [`common`](../common/README.md) role and can be overriden for all roles by setting the appropriate [`common`](../common/README.md) role variable. See [common role facts generation variables](../common/README.md#facts-generation) in the [`common`](../common/README.md) role. + +* `sudo_policy_for_unix_host_facts_generate` enables facts generation. Implicitely enabled if `sudo_policy_for_unix_host_reports_generate` is set. + + Default value is: + ```yaml + sudo_policy_for_unix_host_facts_generate: "{{ facts_generate }}" + ``` + +### Report generation + +Report generation variable defaults for all roles are set by variables in the [`common`](../common/README.md) role and can be overriden for all roles by setting the appropriate [`common`](../common/README.md) role variable. See [common role report generation variables](../common/README.md#report-generation) in the [`common`](../common/README.md) role. + +* `sudo_policy_for_unix_host_reports_generate` enables report generation. Reports are generated at the end of a `sudo_policy_for_unix_host` run for all hosts. + + Default value is: + ```yaml + sudo_policy_for_unix_host_reports_generate: "{{ reports_generate }}" + ``` + +* `sudo_policy_for_unix_host_reports_backup` enables backup of prior reports by renaming them with the date and time they were generated so that the latest reports do not override the previous reports. + + Default value is: + ```yaml + sudo_policy_for_unix_host_reports_backup: "{{ reports_backup }}" + + ``` + +* `sudo_policy_for_unix_host_reports_host` sets the host on which the reports should be generated. + + Default value is: + ```yaml + sudo_policy_for_unix_host_reports_host: "{{ reports_host }}" + ``` + +* `sudo_policy_for_unix_host_reports` is a list of dictionaries that define the reports to be generated. The default value creates a CSV and HTML report using the templates included with the `sudo_policy_for_unix_host` role. + + Default value is: + ```yaml + sudo_policy_for_unix_host_reports: + - src: sudo_policy_for_unix_host_report.csv.j2 + dest: sudo_policy_for_unix_host_report.csv + - src: sudo_policy_for_unix_host_report.html.j2 + dest: sudo_policy_for_unix_host_report.html + ``` + + The `src` key for each list entry is the report template file on the Ansible control node. With a relative path Ansible will look in the `sudo_policy_for_unix_host` role `template` directory. Use a absolute path to speciy templates located elsewhere on the Ansible control node. + + The `dest` key for each list entry is the report file on the machine specified in `sudo_policy_for_unix_host_reports_host`. If `sudo_policy_for_unix_host_reports_host` is set to the Ansible control node a relative path can be used and it will be relative to the directory from which the playbook is run. For other hosts, an absolute path must be used. In either case the containing directory must exist. + +## Plugins + +The `sudo_policy_for_unix_host` role contains two plugins to support operation of the role: + +* `get_sudo_policy_for_unix_host` module runs pmsrvinfo binary and returns its results. + +* `latestsudopolicies` filter takes a list of policy plugins and returns a new list of policy plugins that only includes the latest plugins for each host. + +## Usage + +Below is a sample playbook using the `sudo_policy_for_unix_host` role. + +```yaml +--- + +- hosts: all + + vars: + + # Facts + sudo_policy_for_unix_host_facts_generate: true + + # Reports + sudo_policy_for_unix_host_reports_generate: true + sudo_policy_for_unix_host_reports_backup: false + + roles: + - name: oneidentity.privilege_manager.sudo_policy_for_unix_host +``` + +For a copy of this and other sample playbooks see [examples](../../examples/README.md) diff --git a/roles/sudo_policy_for_unix_host/defaults/main.yml b/roles/sudo_policy_for_unix_host/defaults/main.yml new file mode 100644 index 0000000..ffea3dc --- /dev/null +++ b/roles/sudo_policy_for_unix_host/defaults/main.yml @@ -0,0 +1,32 @@ +--- + +# Facts settings +# ------------------------------------------------------------------------------ + +sudo_policy_for_unix_host_facts_generate: "{{ facts_generate }}" + + +# Reports settings +# ------------------------------------------------------------------------------ + +sudo_policy_for_unix_host_reports_generate: "{{ reports_generate }}" +sudo_policy_for_unix_host_reports_backup: "{{ reports_backup }}" + +# On which host should the reports be generated. +# TODO: This has only been tested on the Ansible control node (127.0.0.1) +sudo_policy_for_unix_host_reports_host: "{{ reports_host }}" + +# List of reports to generate +# src: Is the report template file on the Ansible control node. +# With no or relative path Ansible will look in the software role template directory. +# Full path to find the template files elsewhere on the Ansible control node. +# dest: Is the destination file on the host (sw_reports_host.) +# With no or relative path when the destination is the Ansible control node. +# (sw_reports_host = 127.0.0.1) relative to the playbook directory. +# Full path for other locations or on other hosts. +# In either case the directory must already exist. +sudo_policy_for_unix_host_reports: + - src: sudo_policy_for_unix_host_report.csv.j2 + dest: sudo_policy_for_unix_host_report.csv + - src: sudo_policy_for_unix_host_report.html.j2 + dest: sudo_policy_for_unix_host_report.html diff --git a/roles/sudo_policy_for_unix_host/meta/main.yml b/roles/sudo_policy_for_unix_host/meta/main.yml new file mode 100644 index 0000000..d046e9e --- /dev/null +++ b/roles/sudo_policy_for_unix_host/meta/main.yml @@ -0,0 +1,66 @@ +--- + +galaxy_info: + + author: Laszlo Nagy + + company: One Identity + + description: > + Lists the version of Privilege Manager for sudo plugins and the sudo policies in use on all client hosts that are joined to the policy group. + + issue_tracker_url: https://github.com/OneIdentity/ansible-privilege-manager/issues + + license: Apache-2.0 + + min_ansible_version: 2.9 + + # + # To view available platforms and versions (or releases), visit: + # https://galaxy.ansible.com/api/v1/platforms/ + # + platforms: + - name: Amazon + versions: + - all + - name: MacOSX + versions: + - 10.12 + - 10.13 + - 10.14 + - 10.15 + - name: EL + versions: + - all + - name: Debian + versions: + - all + - name: Fedora + versions: + - all + - name: FreeBSD + versions: + - all + - name: AIX + versions: + - 7.1 + - 7.2 + - name: opensuse + versions: + - all + - name: Solaris + versions: + - all + - name: SLES + versions: + - 11 + - 12 + - 15 + - name: Ubuntu + versions: + - all + + # galaxy_tags: [] + +dependencies: + - role: common diff --git a/roles/sudo_policy_for_unix_host/tasks/generate_reports.yml b/roles/sudo_policy_for_unix_host/tasks/generate_reports.yml new file mode 100644 index 0000000..6e4877a --- /dev/null +++ b/roles/sudo_policy_for_unix_host/tasks/generate_reports.yml @@ -0,0 +1,11 @@ +--- + +- name: generate reports + template: + src: "{{ item.src }}" + dest: "{{ item.dest }}" + backup: "{{ sudo_policy_for_unix_host_reports_backup }}" + with_items: "{{ sudo_policy_for_unix_host_reports }}" + delegate_to: "{{ sudo_policy_for_unix_host_reports_host }}" + run_once: true + changed_when: false diff --git a/roles/sudo_policy_for_unix_host/tasks/get_sudo_policy_for_unix_host.yml b/roles/sudo_policy_for_unix_host/tasks/get_sudo_policy_for_unix_host.yml new file mode 100644 index 0000000..7e44794 --- /dev/null +++ b/roles/sudo_policy_for_unix_host/tasks/get_sudo_policy_for_unix_host.yml @@ -0,0 +1,24 @@ +--- + +- name: Get Sudo Policy for Unix Host + get_sudo_policy_for_unix_host: + facts: "{{ sudo_policy_for_unix_host_facts_generate or sudo_policy_for_unix_host_reports_generate }}" + facts_key: sas_sudo_policy_for_unix_host + register: result + failed_when: false + +# Fail if there was a message returned +- fail: + msg: "{{ result.msg }}" + when: result.msg + +- set_fact: + sudo_policies: | + {%- set policy_list = [] %} + {%- for host in play_hosts %} + {%- if policy_list.extend(hostvars[host].ansible_facts.sas_sudo_policy_for_unix_host.sudo_policy_for_unix_host | default([])) %} + {%- endif %} + {%- endfor %} + {{ policy_list | oneidentity.privilege_manager.latestsudopolicies() }} + run_once: true + diff --git a/roles/sudo_policy_for_unix_host/tasks/main.yml b/roles/sudo_policy_for_unix_host/tasks/main.yml new file mode 100644 index 0000000..7b620a0 --- /dev/null +++ b/roles/sudo_policy_for_unix_host/tasks/main.yml @@ -0,0 +1,30 @@ +--- + +# ------------------------------------------------------------------------------ +# Main +# ------------------------------------------------------------------------------ + +- block: + + # Run get_sudo_policy_for_unix_host + - include_tasks: get_sudo_policy_for_unix_host.yml + + # We get here on success + - include_tasks: utils/set_fact_success.yml + + ignore_unreachable: true + + rescue: + + # Set unreachable status and fail + - include_tasks: utils/set_fact_unreachable.yml + when: result.unreachable is defined and result.unreachable == true + + # Set fail status and fail + - include_tasks: utils/set_fact_failed.yml + + always: + + # Generate reports + - include_tasks: generate_reports.yml + when: sudo_policy_for_unix_host_reports_generate diff --git a/roles/sudo_policy_for_unix_host/tasks/utils/set_fact_failed.yml b/roles/sudo_policy_for_unix_host/tasks/utils/set_fact_failed.yml new file mode 100644 index 0000000..f90eb04 --- /dev/null +++ b/roles/sudo_policy_for_unix_host/tasks/utils/set_fact_failed.yml @@ -0,0 +1,14 @@ +--- + +# Set failed +- set_fact: + cacheable: true + sas_sudo_policy_for_unix_host: + unreachable: false + failed: true + changed: false + when: sudo_policy_for_unix_host_reports_generate or sudo_policy_for_unix_host_facts_generate + +# Propogate fail +- fail: + msg: "{{ result.msg | default('Unexpected error') }}" diff --git a/roles/sudo_policy_for_unix_host/tasks/utils/set_fact_success.yml b/roles/sudo_policy_for_unix_host/tasks/utils/set_fact_success.yml new file mode 100644 index 0000000..a95dfe0 --- /dev/null +++ b/roles/sudo_policy_for_unix_host/tasks/utils/set_fact_success.yml @@ -0,0 +1,10 @@ +--- + +# Set success +- set_fact: + cacheable: true + sas_sudo_policy_for_unix_host: + unreachable: false + failed: false + changed: false + when: sudo_policy_for_unix_host_reports_generate or sudo_policy_for_unix_host_facts_generate diff --git a/roles/sudo_policy_for_unix_host/tasks/utils/set_fact_unreachable.yml b/roles/sudo_policy_for_unix_host/tasks/utils/set_fact_unreachable.yml new file mode 100644 index 0000000..4080639 --- /dev/null +++ b/roles/sudo_policy_for_unix_host/tasks/utils/set_fact_unreachable.yml @@ -0,0 +1,14 @@ +--- + +# Set unreachable +- set_fact: + cacheable: true + sas_sudo_policy_for_unix_host: + unreachable: true + failed: true + changed: false + when: sudo_policy_for_unix_host_reports_generate or sudo_policy_for_unix_host_facts_generate + +# Propogate fail +- fail: + msg: "{{ result.msg | default('Unexpected error') }}" diff --git a/roles/sudo_policy_for_unix_host/templates/Logo_2020-OneIdentity_FullColor_Horizontal.png b/roles/sudo_policy_for_unix_host/templates/Logo_2020-OneIdentity_FullColor_Horizontal.png new file mode 100644 index 0000000..d95f3f3 Binary files /dev/null and b/roles/sudo_policy_for_unix_host/templates/Logo_2020-OneIdentity_FullColor_Horizontal.png differ diff --git a/roles/sudo_policy_for_unix_host/templates/Logo_2020-OneIdentity_FullColor_Horizontal.txt b/roles/sudo_policy_for_unix_host/templates/Logo_2020-OneIdentity_FullColor_Horizontal.txt new file mode 100644 index 0000000..128f2ad --- /dev/null +++ b/roles/sudo_policy_for_unix_host/templates/Logo_2020-OneIdentity_FullColor_Horizontal.txt @@ -0,0 +1,249 @@ +iVBORw0KGgoAAAANSUhEUgAABWsAAAGQCAYAAADYyjIgAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJ +bWFnZVJlYWR5ccllPAAANv5JREFUeNrs3U9y01jbN2A9b2X+5F1BuyeZdlgBZgWEoiozimQFwAoC +KyCsIKaYpYoivQLMCjo9zaT9rODNM0/V9+mOT7pDCCDZsnQkXVeVygkotnz09/x8fKsoAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAGjAvzQBLG2dXuyWD9sVZl1c7e8stBgAAAAATRLWMni3Qthp+qeH6XGSpnWd +l9Nlmv5Mj/FvQl0AAAAAKhPWMhhbpxcRyEYwOy2n34plELubwaLNy2lRLIPc86v9nbm1BQAAAMBd +wlp6a+v0YlIsg9mH6XHSo8WPkbfzcvoSj1f7O5fWKAAAAMC4CWvpjTRydlpOj4v+hbM/cxPe/m7k +LQAAAMA4CWvJ2q3RsxHQ7o3kbcco27NiGdye2QoAAAAAxkFYS3bSCNoIZscU0H6P4BYAAABgJIS1 +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 +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAABir/y/AAPqmv1QA3VFPAAAAAElFTkSuQmCC diff --git a/roles/sudo_policy_for_unix_host/templates/sudo_policy_for_unix_host_report.csv.j2 b/roles/sudo_policy_for_unix_host/templates/sudo_policy_for_unix_host_report.csv.j2 new file mode 100644 index 0000000..cad5726 --- /dev/null +++ b/roles/sudo_policy_for_unix_host/templates/sudo_policy_for_unix_host_report.csv.j2 @@ -0,0 +1,9 @@ +Sudo Policy for Unix Host,"{{ now(fmt='%Y-%m-%d %H:%M:%S') }}", +Hostname,Policy Plugin,Version +{% for policy in sudo_policies | sort %} +{{ '"%s","%s","%s",' | format( +policy[0], +policy[1], +policy[2] +)}} +{% endfor %} diff --git a/roles/sudo_policy_for_unix_host/templates/sudo_policy_for_unix_host_report.html.j2 b/roles/sudo_policy_for_unix_host/templates/sudo_policy_for_unix_host_report.html.j2 new file mode 100644 index 0000000..dbfb66c --- /dev/null +++ b/roles/sudo_policy_for_unix_host/templates/sudo_policy_for_unix_host_report.html.j2 @@ -0,0 +1,45 @@ +{# Imports #} +{% import 'sudo_policy_for_unix_host_report_common.html.j2' as report with context %} + +{# Globals #} +{% set report_name = 'Sudo Policy for Unix Host Report' %} + +{# HTML head #} +{{ report.head(report_name) }} + +{# HTML body #} + + + {# Create overall page container #} +
+ + {# Title #} + {{ report.title(report_name) }} + + {# Data table #} + {{ report.table() }} + + {# Footer #} + {{ report.footer(collection_version, now(fmt='%Y-%m-%d %H:%M:%S')) }} + + {# JS libraries #} + {{ report.libraries() }} + + {# Table data #} + {{ report.table_data() }} + + {# Table detail formatter #} + {{ report.table_detail_formatter() }} + + {# Table detail copy tooltip #} + {{ report.table_detail_tooltip() }} + + {# Table cell style #} + {{ report.table_cell_style() }} + +
+ + + +{# HTML end #} +{{ report.end() }} diff --git a/roles/sudo_policy_for_unix_host/templates/sudo_policy_for_unix_host_report_common.html.j2 b/roles/sudo_policy_for_unix_host/templates/sudo_policy_for_unix_host_report_common.html.j2 new file mode 100644 index 0000000..1cf3960 --- /dev/null +++ b/roles/sudo_policy_for_unix_host/templates/sudo_policy_for_unix_host_report_common.html.j2 @@ -0,0 +1,169 @@ +{# Header #} +{% macro head(report_name) %} + + + + + {# Required meta tags for Bootstrap #} + + + + {# CSS libraries include at end of head per best practices #} + + + + + {# Ionicons preferred method of inclusion #} + + + + Safeguard Authentication Services: {{ report_name }} + +{% endmacro %} + +{# Title #} +{% macro title(report_name) %} +
+ + + {# Import base-64-encoded logo and embed in doc #} + {% import 'Logo_2020-OneIdentity_FullColor_Horizontal.txt' as logo %} + One Identity + + Privilege Manager {{ report_name }} + +
+{% endmacro %} + + +{# Table #} +{% macro table() %} + + + + + + + + +
HostnamePolicy PluginVersion
+ +{% endmacro %} + +{# Footer #} +{% macro footer(report_version, report_time) %} + +

Generated: {{ report_time }}

+

Version: {{ report_version }}

+
+{% endmacro %} + +{# JS libraries #} +{% macro libraries() %} + + + + + +{% endmacro %} + +{# Table data #} +{% macro table_data() %} + +{% endmacro %} + +{# Table detail formatter #} +{% macro table_detail_formatter() %} + +{% endmacro %} + +{# Table detail copy tooltip #} +{% macro table_detail_tooltip() %} + +{% endmacro %} + +{# Table cell style #} +{% macro table_cell_style() %} + +{% endmacro %} + +{# HTML end #} +{% macro end() %} + +{% endmacro %} diff --git a/roles/sudo_policy_for_unix_host/vars/main.yml b/roles/sudo_policy_for_unix_host/vars/main.yml new file mode 100644 index 0000000..ed97d53 --- /dev/null +++ b/roles/sudo_policy_for_unix_host/vars/main.yml @@ -0,0 +1 @@ +---