diff --git a/collections/ansible_collections/demo/patching/plugins/modules/scan_packages.py b/collections/ansible_collections/demo/patching/plugins/modules/scan_packages.py new file mode 100644 index 0000000..039e5b2 --- /dev/null +++ b/collections/ansible_collections/demo/patching/plugins/modules/scan_packages.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python + +from ansible.module_utils.basic import * # noqa + +DOCUMENTATION = ''' +--- +module: scan_packages +short_description: Return installed packages information as fact data +description: + - Return information about installed packages as fact data +''' + +EXAMPLES = ''' +# Example fact output: +# host | success >> { +# "ansible_facts": { +# "packages": [ +# { +# "version": "1.0.6-5", +# "source": "apt", +# "arch": "amd64", +# "name": "libbz2-1.0" +# }, +# { +# "version": "2.7.1-4ubuntu1", +# "source": "apt", +# "arch": "amd64", +# "name": "patch" +# }, +# { +# "version": "4.8.2-19ubuntu1", +# "source": "apt", +# "arch": "amd64", +# "name": "gcc-4.8-base" +# } +# ] +''' + + +def rpm_package_list(): + import rpm + trans_set = rpm.TransactionSet() + installed_packages = [] + for package in trans_set.dbMatch(): + package_details = { + 'name':package[rpm.RPMTAG_NAME], + 'version':package[rpm.RPMTAG_VERSION], + 'release':package[rpm.RPMTAG_RELEASE], + 'epoch':package[rpm.RPMTAG_EPOCH], + 'arch':package[rpm.RPMTAG_ARCH], + 'source':'rpm' } + if installed_packages == []: + installed_packages = [package_details] + else: + installed_packages.append(package_details) + return installed_packages + + +def deb_package_list(): + import apt + apt_cache = apt.Cache() + installed_packages = [] + apt_installed_packages = [pk for pk in apt_cache.keys() if apt_cache[pk].is_installed] + for package in apt_installed_packages: + ac_pkg = apt_cache[package].installed + package_details = { + 'name':package, + 'version':ac_pkg.version, + 'arch':ac_pkg.architecture, + 'source':'apt'} + if installed_packages == []: + installed_packages = [package_details] + else: + installed_packages.append(package_details) + return installed_packages + + +def main(): + module = AnsibleModule( + argument_spec = dict(os_family=dict(required=True)) + ) + ans_os = module.params['os_family'] + if ans_os in ('RedHat', 'Suse', 'openSUSE Leap'): + packages = rpm_package_list() + elif ans_os == 'Debian': + packages = deb_package_list() + else: + packages = None + + if packages is not None: + results = dict(ansible_facts=dict(packages=packages)) + else: + results = dict(skipped=True, msg="Unsupported Distribution") + module.exit_json(**results) + + +main() \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/plugins/modules/scan_services.py b/collections/ansible_collections/demo/patching/plugins/modules/scan_services.py new file mode 100644 index 0000000..c4de33c --- /dev/null +++ b/collections/ansible_collections/demo/patching/plugins/modules/scan_services.py @@ -0,0 +1,186 @@ +#!/usr/bin/env python + +import re +from ansible.module_utils.basic import * # noqa + +DOCUMENTATION = ''' +--- +module: scan_services +short_description: Return service state information as fact data +description: + - Return service state information as fact data for various service management utilities +''' + +EXAMPLES = ''' +- monit: scan_services +# Example fact output: +# host | success >> { +# "ansible_facts": { +# "services": { +# "network": { +# "source": "sysv", +# "state": "running", +# "name": "network" +# }, +# "arp-ethers.service": { +# "source": "systemd", +# "state": "stopped", +# "name": "arp-ethers.service" +# } +# } +# } +''' + + +class BaseService(object): + + def __init__(self, module): + self.module = module + self.incomplete_warning = False + + +class ServiceScanService(BaseService): + + def gather_services(self): + services = {} + service_path = self.module.get_bin_path("service") + if service_path is None: + return None + initctl_path = self.module.get_bin_path("initctl") + chkconfig_path = self.module.get_bin_path("chkconfig") + + # sysvinit + if service_path is not None and chkconfig_path is None: + rc, stdout, stderr = self.module.run_command("%s --status-all 2>&1 | grep -E \"\\[ (\\+|\\-) \\]\"" % service_path, use_unsafe_shell=True) + for line in stdout.split("\n"): + line_data = line.split() + if len(line_data) < 4: + continue # Skipping because we expected more data + service_name = " ".join(line_data[3:]) + if line_data[1] == "+": + service_state = "running" + else: + service_state = "stopped" + services[service_name] = {"name": service_name, "state": service_state, "source": "sysv"} + + # Upstart + if initctl_path is not None and chkconfig_path is None: + p = re.compile('^\s?(?P.*)\s(?P\w+)\/(?P\w+)(\,\sprocess\s(?P[0-9]+))?\s*$') + rc, stdout, stderr = self.module.run_command("%s list" % initctl_path) + real_stdout = stdout.replace("\r","") + for line in real_stdout.split("\n"): + m = p.match(line) + if not m: + continue + service_name = m.group('name') + service_goal = m.group('goal') + service_state = m.group('state') + if m.group('pid'): + pid = m.group('pid') + else: + pid = None # NOQA + payload = {"name": service_name, "state": service_state, "goal": service_goal, "source": "upstart"} + services[service_name] = payload + + # RH sysvinit + elif chkconfig_path is not None: + #print '%s --status-all | grep -E "is (running|stopped)"' % service_path + p = re.compile( + '(?P.*?)\s+[0-9]:(?Pon|off)\s+[0-9]:(?Pon|off)\s+[0-9]:(?Pon|off)\s+' + '[0-9]:(?Pon|off)\s+[0-9]:(?Pon|off)\s+[0-9]:(?Pon|off)\s+[0-9]:(?Pon|off)') + rc, stdout, stderr = self.module.run_command('%s' % chkconfig_path, use_unsafe_shell=True) + # Check for special cases where stdout does not fit pattern + match_any = False + for line in stdout.split('\n'): + if p.match(line): + match_any = True + if not match_any: + p_simple = re.compile('(?P.*?)\s+(?Pon|off)') + match_any = False + for line in stdout.split('\n'): + if p_simple.match(line): + match_any = True + if match_any: + # Try extra flags " -l --allservices" needed for SLES11 + rc, stdout, stderr = self.module.run_command('%s -l --allservices' % chkconfig_path, use_unsafe_shell=True) + elif '--list' in stderr: + # Extra flag needed for RHEL5 + rc, stdout, stderr = self.module.run_command('%s --list' % chkconfig_path, use_unsafe_shell=True) + for line in stdout.split('\n'): + m = p.match(line) + if m: + service_name = m.group('service') + service_state = 'stopped' + if m.group('rl3') == 'on': + rc, stdout, stderr = self.module.run_command('%s %s status' % (service_path, service_name), use_unsafe_shell=True) + service_state = rc + if rc in (0,): + service_state = 'running' + #elif rc in (1,3): + else: + if 'root' in stderr or 'permission' in stderr.lower() or 'not in sudoers' in stderr.lower(): + self.incomplete_warning = True + continue + else: + service_state = 'stopped' + service_data = {"name": service_name, "state": service_state, "source": "sysv"} + services[service_name] = service_data + return services + + +class SystemctlScanService(BaseService): + + def systemd_enabled(self): + # Check if init is the systemd command, using comm as cmdline could be symlink + try: + f = open('/proc/1/comm', 'r') + except IOError: + # If comm doesn't exist, old kernel, no systemd + return False + for line in f: + if 'systemd' in line: + return True + return False + + def gather_services(self): + services = {} + if not self.systemd_enabled(): + return None + systemctl_path = self.module.get_bin_path("systemctl", opt_dirs=["/usr/bin", "/usr/local/bin"]) + if systemctl_path is None: + return None + rc, stdout, stderr = self.module.run_command("%s list-unit-files --type=service | tail -n +2 | head -n -2" % systemctl_path, use_unsafe_shell=True) + for line in stdout.split("\n"): + line_data = line.split() + if len(line_data) != 2: + continue + if line_data[1] == "enabled": + state_val = "running" + else: + state_val = "stopped" + services[line_data[0]] = {"name": line_data[0], "state": state_val, "source": "systemd"} + return services + + +def main(): + module = AnsibleModule(argument_spec = dict()) + service_modules = (ServiceScanService, SystemctlScanService) + all_services = {} + incomplete_warning = False + for svc_module in service_modules: + svcmod = svc_module(module) + svc = svcmod.gather_services() + if svc is not None: + all_services.update(svc) + if svcmod.incomplete_warning: + incomplete_warning = True + if len(all_services) == 0: + results = dict(skipped=True, msg="Failed to find any services. Sometimes this is due to insufficient privileges.") + else: + results = dict(ansible_facts=dict(services=all_services)) + if incomplete_warning: + results['msg'] = "WARNING: Could not find status for all services. Sometimes this is due to insufficient privileges." + module.exit_json(**results) + + +main() \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/plugins/modules/win_scan_packages.ps1 b/collections/ansible_collections/demo/patching/plugins/modules/win_scan_packages.ps1 new file mode 100644 index 0000000..0062f31 --- /dev/null +++ b/collections/ansible_collections/demo/patching/plugins/modules/win_scan_packages.ps1 @@ -0,0 +1,66 @@ +#!powershell +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +# WANT_JSON +# POWERSHELL_COMMON + +$uninstall_native_path = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" +$uninstall_wow6432_path = "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall" + +if ([System.IntPtr]::Size -eq 4) { + + # This is a 32-bit Windows system, so we only check for 32-bit programs, which will be + # at the native registry location. + + [PSObject []]$packages = Get-ChildItem -Path $uninstall_native_path | + Get-ItemProperty | + Select-Object -Property @{Name="name"; Expression={$_."DisplayName"}}, + @{Name="version"; Expression={$_."DisplayVersion"}}, + @{Name="publisher"; Expression={$_."Publisher"}}, + @{Name="arch"; Expression={ "Win32" }} | + Where-Object { $_.name } + +} else { + + # This is a 64-bit Windows system, so we check for 64-bit programs in the native + # registry location, and also for 32-bit programs under Wow6432Node. + + [PSObject []]$packages = Get-ChildItem -Path $uninstall_native_path | + Get-ItemProperty | + Select-Object -Property @{Name="name"; Expression={$_."DisplayName"}}, + @{Name="version"; Expression={$_."DisplayVersion"}}, + @{Name="publisher"; Expression={$_."Publisher"}}, + @{Name="arch"; Expression={ "Win64" }} | + Where-Object { $_.name } + + $packages += Get-ChildItem -Path $uninstall_wow6432_path | + Get-ItemProperty | + Select-Object -Property @{Name="name"; Expression={$_."DisplayName"}}, + @{Name="version"; Expression={$_."DisplayVersion"}}, + @{Name="publisher"; Expression={$_."Publisher"}}, + @{Name="arch"; Expression={ "Win32" }} | + Where-Object { $_.name } + +} + +$result = New-Object psobject @{ + ansible_facts = New-Object psobject @{ + packages = $packages + } + changed = $false +} + +Exit-Json $result; \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/plugins/modules/win_scan_packages.py b/collections/ansible_collections/demo/patching/plugins/modules/win_scan_packages.py new file mode 100644 index 0000000..3281818 --- /dev/null +++ b/collections/ansible_collections/demo/patching/plugins/modules/win_scan_packages.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +DOCUMENTATION = ''' +--- +module: win_scan_packages +short_description: Return Package state information as fact data +description: + - Return Package state information as fact data for various Packages +''' + +EXAMPLES = ''' +- monit: win_scan_packages +# Example fact output: +# host | success >> { +# "ansible_facts": { +# "packages": [ + { + "name": "Mozilla Firefox 76.0.1 (x64 en-US)", + "version": "76.0.1", + "publisher": "Mozilla", + "arch": "Win64" + }, + { + "name": "Mozilla Maintenance Service", + "version": "76.0.1", + "publisher": "Mozilla", + "arch": "Win64" + }, +# } +''' \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/plugins/modules/win_scan_services.ps1 b/collections/ansible_collections/demo/patching/plugins/modules/win_scan_services.ps1 new file mode 100644 index 0000000..4a5f840 --- /dev/null +++ b/collections/ansible_collections/demo/patching/plugins/modules/win_scan_services.ps1 @@ -0,0 +1,30 @@ +#!powershell +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +# WANT_JSON +# POWERSHELL_COMMON + +$result = New-Object psobject @{ + ansible_facts = New-Object psobject @{ + services = Get-Service | + Select-Object -Property @{Name="name"; Expression={$_."DisplayName"}}, + @{Name="win_svc_name"; Expression={$_."Name"}}, + @{Name="state"; Expression={$_."Status".ToString().ToLower()}} + } + changed = $false +} + +Exit-Json $result; \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/plugins/modules/win_scan_services.py b/collections/ansible_collections/demo/patching/plugins/modules/win_scan_services.py new file mode 100644 index 0000000..caae37d --- /dev/null +++ b/collections/ansible_collections/demo/patching/plugins/modules/win_scan_services.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +DOCUMENTATION = ''' +--- +module: win_scan_services +short_description: Return service state information as fact data +description: + - Return service state information as fact data for various service management utilities +''' + +EXAMPLES = ''' +- monit: win_scan_services +# Example fact output: +# host | success >> { +# "ansible_facts": { +# "services": [ + { + "name": "AllJoyn Router Service", + "win_svc_name": "AJRouter", + "state": "stopped" + }, + { + "name": "Application Layer Gateway Service", + "win_svc_name": "ALG", + "state": "stopped" + }, + { + "name": "Application Host Helper Service", + "win_svc_name": "AppHostSvc", + "state": "running" + }, +# } +''' \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_linux/README.md b/collections/ansible_collections/demo/patching/roles/build_report_linux/README.md new file mode 100644 index 0000000..88fa95c --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_linux/README.md @@ -0,0 +1,36 @@ +build_report_linux +======== + +Installs Apache and creates a report based on facts from Linux services and packages modules + +Requirements +------------ + +Must run on Apache server + +Role Variables / Configuration +-------------- + +N/A + +Dependencies +------------ + +N/A + +Example Playbook +---------------- + +The role can be used to create an html report on any number of Linux hosts using any number of Linux servers about their services and packages installed + + +``` +--- +- hosts: all + + tasks: + - name: Run Linux Report + import_role: + name: shadowman.reports.build_report_linux + +``` \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_linux/defaults/main.yml b/collections/ansible_collections/demo/patching/roles/build_report_linux/defaults/main.yml new file mode 100644 index 0000000..1154771 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_linux/defaults/main.yml @@ -0,0 +1,2 @@ +--- +detailedreport: True \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_linux/example_results/Ansible Linux Automation Report.png b/collections/ansible_collections/demo/patching/roles/build_report_linux/example_results/Ansible Linux Automation Report.png new file mode 100644 index 0000000..3e2287a Binary files /dev/null and b/collections/ansible_collections/demo/patching/roles/build_report_linux/example_results/Ansible Linux Automation Report.png differ diff --git a/collections/ansible_collections/demo/patching/roles/build_report_linux/files/css/new.css b/collections/ansible_collections/demo/patching/roles/build_report_linux/files/css/new.css new file mode 100644 index 0000000..f58d18f --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_linux/files/css/new.css @@ -0,0 +1,202 @@ +p.hostname { + color: #000000; + font-weight: bolder; + font-size: large; + margin: auto; + width: 50%; + } + + #subtable { + background: #ebebeb; + margin: 0px; + width: 100%; + } + + #subtable tbody tr td { + padding: 5px 5px 5px 5px; + } + + #subtable thead th { + padding: 5px; + } + + * { + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + font-family: "Open Sans", "Helvetica"; + + } + + a { + color: #ffffff; + } + + p { + color: #ffffff; + } + h1 { + text-align: center; + color: #ffffff; + } + + body { + background:#353a40; + padding: 0px; + margin: 0px; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + } + + table { + border-collapse: separate; + background:#fff; + @include border-radius(5px); + @include box-shadow(0px 0px 5px rgba(0,0,0,0.3)); + } + + .main_net_table { + margin:50px auto; + } + + thead { + @include border-radius(5px); + } + + thead th { + font-size:16px; + font-weight:400; + color:#fff; + @include text-shadow(1px 1px 0px rgba(0,0,0,0.5)); + text-align:left; + padding:20px; + border-top:1px solid #858d99; + background: #353a40; + + &:first-child { + @include border-top-left-radius(5px); + } + + &:last-child { + @include border-top-right-radius(5px); + } + } + + tbody tr td { + font-weight:400; + color:#5f6062; + font-size:13px; + padding:20px 20px 20px 20px; + border-bottom:1px solid #e0e0e0; + } + + tbody tr:nth-child(2n) { + background:#f0f3f5; + } + + tbody tr:last-child td { + border-bottom:none; + &:first-child { + @include border-bottom-left-radius(5px); + } + &:last-child { + @include border-bottom-right-radius(5px); + } + } + + td { + vertical-align: top; + } + + span.highlight { + background-color: yellow; + } + + .expandclass { + color: #5f6062; + } + + .content{ + display:none; + margin: 10px; + } + + header { + width: 100%; + position: initial; + float: initial; + padding: 0; + margin: 0; + border-radius: 0; + height: 88px; + background-color: #171717; + } + + .header-container { + margin: 0 auto; + width: 100%; + height: 100%; + max-width: 1170px; + padding: 0; + float: initial; + display: flex; + align-items: center; + } + + .header-logo { + width: 137px; + border: 0; + margin: 0; + margin-left: 15px; + } + + .header-link { + margin-left: 40px; + text-decoration: none; + cursor: pointer; + text-transform: uppercase; + font-size: 15px; + font-family: 'Red Hat Text'; + font-weight: 500; + } + + .header-link:hover { + text-shadow: 0 0 0.02px white; + text-decoration: none; + } + + table.net_info td { + padding: 5px; +} + +p.expandclass:hover { + text-decoration: underline; + color: #EE0000; + cursor: pointer; +} + +.summary_info { +} + +.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active, a.ui-button:active, .ui-button:active, .ui-button.ui-state-active:hover { + border: 1px solid #5F0000; + background: #EE0000; +} + +div#net_content { + padding: 0px; + height: auto !important; +} + +img.router_image { + vertical-align: middle; + padding: 0px 10px 10px 10px; + width: 50px; +} + +table.net_info { + width: 100%; +} + +p.internal_label { + color: #000000; +} \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_linux/files/redhat-ansible-logo.svg b/collections/ansible_collections/demo/patching/roles/build_report_linux/files/redhat-ansible-logo.svg new file mode 100644 index 0000000..2ecef98 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_linux/files/redhat-ansible-logo.svg @@ -0,0 +1,48 @@ + + + + +Logo-Red_Hat-Ansible_Automation_Platform-A-Reverse-RGB + + + + + + + + + + + diff --git a/collections/ansible_collections/demo/patching/roles/build_report_linux/files/server.png b/collections/ansible_collections/demo/patching/roles/build_report_linux/files/server.png new file mode 100644 index 0000000..9ad96fc Binary files /dev/null and b/collections/ansible_collections/demo/patching/roles/build_report_linux/files/server.png differ diff --git a/collections/ansible_collections/demo/patching/roles/build_report_linux/files/webpage_logo.png b/collections/ansible_collections/demo/patching/roles/build_report_linux/files/webpage_logo.png new file mode 100644 index 0000000..65b5836 Binary files /dev/null and b/collections/ansible_collections/demo/patching/roles/build_report_linux/files/webpage_logo.png differ diff --git a/collections/ansible_collections/demo/patching/roles/build_report_linux/tasks/main.yml b/collections/ansible_collections/demo/patching/roles/build_report_linux/tasks/main.yml new file mode 100644 index 0000000..f02fb2a --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_linux/tasks/main.yml @@ -0,0 +1,24 @@ +- name: create HTML report + ansible.builtin.template: + src: report.j2 + dest: "{{ file_path }}/linux.html" + +- name: copy CSS over + ansible.builtin.copy: + src: "css" + dest: "{{ file_path }}" + directory_mode: true + +- name: copy logos over + ansible.builtin.copy: + src: "{{ item }}" + dest: "{{ file_path }}" + directory_mode: true + loop: + - "webpage_logo.png" + - "redhat-ansible-logo.svg" + - "server.png" + +- name: display link to inventory report + ansible.builtin.debug: + msg: "Please go to http://{{ ansible_host }}/linux.html" \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_linux/templates/header.j2 b/collections/ansible_collections/demo/patching/roles/build_report_linux/templates/header.j2 new file mode 100644 index 0000000..6d504d0 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_linux/templates/header.j2 @@ -0,0 +1,15 @@ + + +
+
+
+ + + +
+
\ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_linux/templates/packages.j2 b/collections/ansible_collections/demo/patching/roles/build_report_linux/templates/packages.j2 new file mode 100644 index 0000000..86a842d --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_linux/templates/packages.j2 @@ -0,0 +1,31 @@ + +
+
+ + +
+
+ \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_linux/templates/report.j2 b/collections/ansible_collections/demo/patching/roles/build_report_linux/templates/report.j2 new file mode 100644 index 0000000..dbd7b4f --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_linux/templates/report.j2 @@ -0,0 +1,105 @@ + + + + Ansible Linux Automation Report + + + + + + + + + + + +
+ {% include 'header.j2' %} +
+
+

Ansible Linux Automation Report

+

+

+ + + + + + + + + + + +{% for linux_host in groups['tag_Insights']|sort %} + + + + + + + +{% endfor %} + +
Linux DevicePackage ManagerOperating SystemOperating System VersionOperating System Kernel Version
+
+

+ {{ hostvars[linux_host]['inventory_hostname'].split('.')[0] }}

+
+{% if detailedreport == 'True' %} +{% include 'packages.j2' %} +{% include 'services.j2' %} +{% endif %} +
{{hostvars[linux_host]['ansible_pkg_mgr']|default("none")}}{{hostvars[linux_host]['ansible_os_family']|default("none")}}{{hostvars[linux_host]['ansible_distribution_version']|default("none")}}{{hostvars[linux_host]['ansible_kernel']|default("none")}}
+

Created with


+
+
+
+ + diff --git a/collections/ansible_collections/demo/patching/roles/build_report_linux/templates/services.j2 b/collections/ansible_collections/demo/patching/roles/build_report_linux/templates/services.j2 new file mode 100644 index 0000000..b765b5e --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_linux/templates/services.j2 @@ -0,0 +1,30 @@ + +
+
+ + +
+
+ \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_linux/vars/main.yml b/collections/ansible_collections/demo/patching/roles/build_report_linux/vars/main.yml new file mode 100644 index 0000000..f09b15e --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_linux/vars/main.yml @@ -0,0 +1 @@ +file_path: /var/www/html \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_linux_patch/README.md b/collections/ansible_collections/demo/patching/roles/build_report_linux_patch/README.md new file mode 100644 index 0000000..b7e2fe2 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_linux_patch/README.md @@ -0,0 +1,36 @@ +build_report_linux_patch +======== + +Installs Apache and creates a report based on facts from Linux patching + +Requirements +------------ + +Must run on Apache server + +Role Variables / Configuration +-------------- + +N/A + +Dependencies +------------ + +N/A + +Example Playbook +---------------- + +The role can be used to create an html report on any number of Linux hosts using any number of Linux servers about their patching results(yum and dnf) + + +``` +--- +- hosts: all + + tasks: + - name: Run Windows Report + import_role: + name: shadowman.reports.build_report_linux_patch + +``` \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_linux_patch/defaults/main.yml b/collections/ansible_collections/demo/patching/roles/build_report_linux_patch/defaults/main.yml new file mode 100644 index 0000000..aaf5c3d --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_linux_patch/defaults/main.yml @@ -0,0 +1,3 @@ +EMAIL_FROM: tower@shadowman.dev +to_emails: alex@shadowman.dev,tower@shadowman.dev +EMAIL_TO: "{{ to_emails.split(',') }}" \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_linux_patch/example_results/Full_Report.png b/collections/ansible_collections/demo/patching/roles/build_report_linux_patch/example_results/Full_Report.png new file mode 100644 index 0000000..a7d66a2 Binary files /dev/null and b/collections/ansible_collections/demo/patching/roles/build_report_linux_patch/example_results/Full_Report.png differ diff --git a/collections/ansible_collections/demo/patching/roles/build_report_linux_patch/example_results/Splunk Patching Aggregated RHEL 8.png b/collections/ansible_collections/demo/patching/roles/build_report_linux_patch/example_results/Splunk Patching Aggregated RHEL 8.png new file mode 100644 index 0000000..4367264 Binary files /dev/null and b/collections/ansible_collections/demo/patching/roles/build_report_linux_patch/example_results/Splunk Patching Aggregated RHEL 8.png differ diff --git a/collections/ansible_collections/demo/patching/roles/build_report_linux_patch/files/css/main.css b/collections/ansible_collections/demo/patching/roles/build_report_linux_patch/files/css/main.css new file mode 100644 index 0000000..dfeb435 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_linux_patch/files/css/main.css @@ -0,0 +1,111 @@ +p.hostname { + color: #000000; + font-weight: bolder; + font-size: large; + } + + #subtable { + background: #ebebeb; + margin: 0px; + } + + #subtable tbody tr td { + padding: 5px 5px 5px 5px; + } + + #subtable thead th { + padding: 5px; + } + + * { + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + font-family: "Open Sans", "Helvetica"; + + } + + a { + color: #ffffff; + } + + p { + color: #ffffff; + } + h1 { + text-align: center; + color: #ffffff; + } + + body { + background:#353a40; + } + + table { + border-collapse: separate; + background:#fff; + @include border-radius(5px); + margin:50px auto; + @include box-shadow(0px 0px 5px rgba(0,0,0,0.3)); + } + + thead { + @include border-radius(5px); + } + + thead th { + font-family: 'Patua One', monospace; + font-size:16px; + font-weight:400; + color:#fff; + @include text-shadow(1px 1px 0px rgba(0,0,0,0.5)); + text-align:left; + padding:20px; + border-top:1px solid #858d99; + background: #353a40; + + &:first-child { + @include border-top-left-radius(5px); + } + + &:last-child { + @include border-top-right-radius(5px); + } + } + + tbody tr td { + font-family: 'Open Sans', sans-serif; + font-weight:400; + color:#5f6062; + font-size:13px; + padding:20px 20px 20px 20px; + border-bottom:1px solid #e0e0e0; + + } + + tbody tr:nth-child(2n) { + background:#f0f3f5; + } + + tbody tr:last-child td { + border-bottom:none; + &:first-child { + @include border-bottom-left-radius(5px); + } + &:last-child { + @include border-bottom-right-radius(5px); + } + } + + span.highlight { + background-color: yellow; + } + + .expandclass { + color: #5f6062; + } + + .content{ + display:none; + margin: 10px; + } \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_linux_patch/files/webpage_logo.png b/collections/ansible_collections/demo/patching/roles/build_report_linux_patch/files/webpage_logo.png new file mode 100644 index 0000000..3d99673 Binary files /dev/null and b/collections/ansible_collections/demo/patching/roles/build_report_linux_patch/files/webpage_logo.png differ diff --git a/collections/ansible_collections/demo/patching/roles/build_report_linux_patch/tasks/main.yml b/collections/ansible_collections/demo/patching/roles/build_report_linux_patch/tasks/main.yml new file mode 100644 index 0000000..52f096a --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_linux_patch/tasks/main.yml @@ -0,0 +1,38 @@ +- name: Create HTML report + ansible.builtin.template: + src: report.j2 + dest: "{{ file_path }}/linuxpatch.html" + check_mode: no + +- name: Copy CSS over + ansible.builtin.copy: + src: "css" + dest: "{{ file_path }}" + directory_mode: true + check_mode: no + +- name: Copy logo over + ansible.builtin.copy: + src: "webpage_logo.png" + dest: "{{ file_path }}" + directory_mode: true + check_mode: no + +- name: Display link to Linux patch report + ansible.builtin.debug: + msg: "Please go to http://{{ ansible_host }}/linuxpatch.html" + +- name: Send Report via E-mail + community.general.mail: + host: "{{ EMAIL_HOST }}" + username: "{{ EMAIL_USERNAME }}" + password: "{{ EMAIL_PASSWORD }}" + port: "{{ EMAIL_PORT }}" + subject: "Linux Patching Report" + body: "{{ lookup('template', 'report.j2') }}" + from: "{{ EMAIL_FROM }}" + to: "{{ EMAIL_TO }}" + subtype: html + delegate_to: localhost + become: false + check_mode: no \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_linux_patch/templates/report.j2 b/collections/ansible_collections/demo/patching/roles/build_report_linux_patch/templates/report.j2 new file mode 100644 index 0000000..d2886c2 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_linux_patch/templates/report.j2 @@ -0,0 +1,122 @@ + + + + Linux Patch Report + + +
+

Ansible Linux Patching Report

+ +
+ + +
+
+ + + + + + + + + + +{% for linux_host in groups['tag_RHEL']|sort %} + + + + + + +{% endfor %} + +
HostnameOperating SystemOperating System VersionRequired Updates
{{hostvars[linux_host]['inventory_hostname']}}{{hostvars[linux_host]['ansible_os_family']|default("none")}}{{hostvars[linux_host]['ansible_distribution_version']|default("none")}} +
    +{% if hostvars[linux_host].patchingresult.changed|default("false",true) == true %} +{% for packagename in hostvars[linux_host].patchingresult.changes.updated|sort %} +
  • {{ packagename[0] }} - {{ packagename[1] }}
  • +{% endfor %} +{% elif hostvars[linux_host].patchingresultdnf.changed|default("false",true) == true %} +{% for packagename in hostvars[linux_host].patchingresultdnf.results|sort %} +
  • {{ packagename }}
  • +{% endfor %} +{% elif hostvars[linux_host].patchingresultdnf.changed is undefined %} +
  • Patching Failed
  • +{% elif hostvars[linux_host].patchingresult.changed is undefined %} +
  • Patching Failed
  • +{% else %} +
  • Compliant
  • +{% endif %} +
+
+{% for host in ansible_play_hosts %} +

Created with Ansible on {{hostvars[host].ansible_date_time.iso8601}}

+{% endfor %} + + + \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_linux_patch/vars/main.yml b/collections/ansible_collections/demo/patching/roles/build_report_linux_patch/vars/main.yml new file mode 100644 index 0000000..f09b15e --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_linux_patch/vars/main.yml @@ -0,0 +1 @@ +file_path: /var/www/html \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_network/README.md b/collections/ansible_collections/demo/patching/roles/build_report_network/README.md new file mode 100644 index 0000000..a8b311a --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_network/README.md @@ -0,0 +1,36 @@ +build_report_network +======== + +Installs Apache and creates a report based on facts from network devices + +Requirements +------------ + +Must run on Apache server + +Role Variables / Configuration +-------------- + +N/A + +Dependencies +------------ + +N/A + +Example Playbook +---------------- + +The role can be used to create an html report on any number of Linux hosts using any number of network devices + + +``` +--- +- hosts: all + + tasks: + - name: Run Network Report + import_role: + name: shadowman.reports.build_report_network + +``` \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_network/example_results/Ansible Network Automation Report.png b/collections/ansible_collections/demo/patching/roles/build_report_network/example_results/Ansible Network Automation Report.png new file mode 100644 index 0000000..d766491 Binary files /dev/null and b/collections/ansible_collections/demo/patching/roles/build_report_network/example_results/Ansible Network Automation Report.png differ diff --git a/collections/ansible_collections/demo/patching/roles/build_report_network/files/css/new.css b/collections/ansible_collections/demo/patching/roles/build_report_network/files/css/new.css new file mode 100644 index 0000000..f58d18f --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_network/files/css/new.css @@ -0,0 +1,202 @@ +p.hostname { + color: #000000; + font-weight: bolder; + font-size: large; + margin: auto; + width: 50%; + } + + #subtable { + background: #ebebeb; + margin: 0px; + width: 100%; + } + + #subtable tbody tr td { + padding: 5px 5px 5px 5px; + } + + #subtable thead th { + padding: 5px; + } + + * { + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + font-family: "Open Sans", "Helvetica"; + + } + + a { + color: #ffffff; + } + + p { + color: #ffffff; + } + h1 { + text-align: center; + color: #ffffff; + } + + body { + background:#353a40; + padding: 0px; + margin: 0px; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + } + + table { + border-collapse: separate; + background:#fff; + @include border-radius(5px); + @include box-shadow(0px 0px 5px rgba(0,0,0,0.3)); + } + + .main_net_table { + margin:50px auto; + } + + thead { + @include border-radius(5px); + } + + thead th { + font-size:16px; + font-weight:400; + color:#fff; + @include text-shadow(1px 1px 0px rgba(0,0,0,0.5)); + text-align:left; + padding:20px; + border-top:1px solid #858d99; + background: #353a40; + + &:first-child { + @include border-top-left-radius(5px); + } + + &:last-child { + @include border-top-right-radius(5px); + } + } + + tbody tr td { + font-weight:400; + color:#5f6062; + font-size:13px; + padding:20px 20px 20px 20px; + border-bottom:1px solid #e0e0e0; + } + + tbody tr:nth-child(2n) { + background:#f0f3f5; + } + + tbody tr:last-child td { + border-bottom:none; + &:first-child { + @include border-bottom-left-radius(5px); + } + &:last-child { + @include border-bottom-right-radius(5px); + } + } + + td { + vertical-align: top; + } + + span.highlight { + background-color: yellow; + } + + .expandclass { + color: #5f6062; + } + + .content{ + display:none; + margin: 10px; + } + + header { + width: 100%; + position: initial; + float: initial; + padding: 0; + margin: 0; + border-radius: 0; + height: 88px; + background-color: #171717; + } + + .header-container { + margin: 0 auto; + width: 100%; + height: 100%; + max-width: 1170px; + padding: 0; + float: initial; + display: flex; + align-items: center; + } + + .header-logo { + width: 137px; + border: 0; + margin: 0; + margin-left: 15px; + } + + .header-link { + margin-left: 40px; + text-decoration: none; + cursor: pointer; + text-transform: uppercase; + font-size: 15px; + font-family: 'Red Hat Text'; + font-weight: 500; + } + + .header-link:hover { + text-shadow: 0 0 0.02px white; + text-decoration: none; + } + + table.net_info td { + padding: 5px; +} + +p.expandclass:hover { + text-decoration: underline; + color: #EE0000; + cursor: pointer; +} + +.summary_info { +} + +.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active, a.ui-button:active, .ui-button:active, .ui-button.ui-state-active:hover { + border: 1px solid #5F0000; + background: #EE0000; +} + +div#net_content { + padding: 0px; + height: auto !important; +} + +img.router_image { + vertical-align: middle; + padding: 0px 10px 10px 10px; + width: 50px; +} + +table.net_info { + width: 100%; +} + +p.internal_label { + color: #000000; +} \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_network/files/redhat-ansible-logo.svg b/collections/ansible_collections/demo/patching/roles/build_report_network/files/redhat-ansible-logo.svg new file mode 100644 index 0000000..2ecef98 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_network/files/redhat-ansible-logo.svg @@ -0,0 +1,48 @@ + + + + +Logo-Red_Hat-Ansible_Automation_Platform-A-Reverse-RGB + + + + + + + + + + + diff --git a/collections/ansible_collections/demo/patching/roles/build_report_network/files/router.png b/collections/ansible_collections/demo/patching/roles/build_report_network/files/router.png new file mode 100644 index 0000000..1fdc4f0 Binary files /dev/null and b/collections/ansible_collections/demo/patching/roles/build_report_network/files/router.png differ diff --git a/collections/ansible_collections/demo/patching/roles/build_report_network/files/webpage_logo.png b/collections/ansible_collections/demo/patching/roles/build_report_network/files/webpage_logo.png new file mode 100644 index 0000000..65b5836 Binary files /dev/null and b/collections/ansible_collections/demo/patching/roles/build_report_network/files/webpage_logo.png differ diff --git a/collections/ansible_collections/demo/patching/roles/build_report_network/tasks/main.yml b/collections/ansible_collections/demo/patching/roles/build_report_network/tasks/main.yml new file mode 100644 index 0000000..accaeba --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_network/tasks/main.yml @@ -0,0 +1,24 @@ +- name: create HTML report + ansible.builtin.template: + src: report.j2 + dest: "{{ file_path }}/network.html" + +- name: copy CSS over + ansible.builtin.copy: + src: "css" + dest: "{{ file_path }}" + directory_mode: true + +- name: copy logos over + ansible.builtin.copy: + src: "{{ item }}" + dest: "{{ file_path }}" + directory_mode: true + loop: + - "webpage_logo.png" + - "redhat-ansible-logo.svg" + - "router.png" + +- name: display link to inventory report + ansible.builtin.debug: + msg: "Please go to http://{{ ansible_host }}/network.html" \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_network/templates/bgp.j2 b/collections/ansible_collections/demo/patching/roles/build_report_network/templates/bgp.j2 new file mode 100644 index 0000000..d6b0f67 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_network/templates/bgp.j2 @@ -0,0 +1,31 @@ + +
+
+ + +
+
+ \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_network/templates/header.j2 b/collections/ansible_collections/demo/patching/roles/build_report_network/templates/header.j2 new file mode 100644 index 0000000..6d504d0 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_network/templates/header.j2 @@ -0,0 +1,15 @@ + + +
+
+
+ + + +
+
\ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_network/templates/interfaces.j2 b/collections/ansible_collections/demo/patching/roles/build_report_network/templates/interfaces.j2 new file mode 100644 index 0000000..bf13414 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_network/templates/interfaces.j2 @@ -0,0 +1,41 @@ + +
+
+ + +
+
+ \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_network/templates/l2_interfaces.j2 b/collections/ansible_collections/demo/patching/roles/build_report_network/templates/l2_interfaces.j2 new file mode 100644 index 0000000..a170b5d --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_network/templates/l2_interfaces.j2 @@ -0,0 +1,37 @@ + +
+
+ + +
+
+ \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_network/templates/l3_interfaces.j2 b/collections/ansible_collections/demo/patching/roles/build_report_network/templates/l3_interfaces.j2 new file mode 100644 index 0000000..deb217c --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_network/templates/l3_interfaces.j2 @@ -0,0 +1,58 @@ + +
+
+ + +
+
+ \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_network/templates/lacp.j2 b/collections/ansible_collections/demo/patching/roles/build_report_network/templates/lacp.j2 new file mode 100644 index 0000000..f53b2f7 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_network/templates/lacp.j2 @@ -0,0 +1,29 @@ + +
+
+ + +
+
+ \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_network/templates/lldp_interfaces.j2 b/collections/ansible_collections/demo/patching/roles/build_report_network/templates/lldp_interfaces.j2 new file mode 100644 index 0000000..3ad0852 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_network/templates/lldp_interfaces.j2 @@ -0,0 +1,33 @@ + +
+
+ + +
+
+ \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_network/templates/ospf.j2 b/collections/ansible_collections/demo/patching/roles/build_report_network/templates/ospf.j2 new file mode 100644 index 0000000..d06ff5b --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_network/templates/ospf.j2 @@ -0,0 +1,29 @@ + +
+
+ + +
+
+ \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_network/templates/report.j2 b/collections/ansible_collections/demo/patching/roles/build_report_network/templates/report.j2 new file mode 100644 index 0000000..f00eac7 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_network/templates/report.j2 @@ -0,0 +1,111 @@ + + + + Ansible Network Automation Report + + + + + + + + + + +
+ {% include 'header.j2' %} +
+
+

Ansible Network Automation Report

+

+

+ + + + + + + + + + +{% for network_switch in groups['tag_Router']|sort %} + + + + + + + +{% endfor %} + +
Network DeviceLayer 1Layer 2Layer 3
+
+

+ {{ hostvars[network_switch]['ansible_net_hostname'].split('.')[0] }}

+
+{% include 'summary.j2' %} +
+{% include 'interfaces.j2' %} + +{% include 'vlans.j2' %} +{% include 'lldp_interfaces.j2' %} +{% include 'l2_interfaces.j2' %} + +{% include 'l3_interfaces.j2' %} +{% include 'lacp.j2' %} +{% include 'bgp.j2' %} +{% include 'ospf.j2' %} +
+

Created with


+
+
+
+ + diff --git a/collections/ansible_collections/demo/patching/roles/build_report_network/templates/summary.j2 b/collections/ansible_collections/demo/patching/roles/build_report_network/templates/summary.j2 new file mode 100644 index 0000000..5f643e4 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_network/templates/summary.j2 @@ -0,0 +1,25 @@ +
+ + + + + + + + + + + + + + + + + + + + + + +
Platform{{hostvars[network_switch]['ansible_net_system']}}
Code Version{{hostvars[network_switch]['ansible_net_version']}}
Model{{hostvars[network_switch]['ansible_net_model']|default("N/A")}}
Serial Number{{hostvars[network_switch]['ansible_net_serialnum']}}
Transport{{hostvars[network_switch]['ansible_net_api']}}
+
diff --git a/collections/ansible_collections/demo/patching/roles/build_report_network/templates/vlans.j2 b/collections/ansible_collections/demo/patching/roles/build_report_network/templates/vlans.j2 new file mode 100644 index 0000000..044a334 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_network/templates/vlans.j2 @@ -0,0 +1,33 @@ + +
+
+ + +
+
+ \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_network/vars/main.yml b/collections/ansible_collections/demo/patching/roles/build_report_network/vars/main.yml new file mode 100644 index 0000000..f09b15e --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_network/vars/main.yml @@ -0,0 +1 @@ +file_path: /var/www/html \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_windows/README.md b/collections/ansible_collections/demo/patching/roles/build_report_windows/README.md new file mode 100644 index 0000000..93d6df4 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_windows/README.md @@ -0,0 +1,36 @@ +build_report_windows +======== + +Installs Apache and creates a report based on facts from Windows services and packages modules + +Requirements +------------ + +Must run on Apache server + +Role Variables / Configuration +-------------- + +N/A + +Dependencies +------------ + +N/A + +Example Playbook +---------------- + +The role can be used to create an html report on any number of Linux hosts using any number of Windows servers about their services and packages installed + + +``` +--- +- hosts: all + + tasks: + - name: Run Windows Report + import_role: + name: shadowman.reports.build_report_windows + +``` \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_windows/defaults/main.yml b/collections/ansible_collections/demo/patching/roles/build_report_windows/defaults/main.yml new file mode 100644 index 0000000..1154771 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_windows/defaults/main.yml @@ -0,0 +1,2 @@ +--- +detailedreport: True \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_windows/example_results/Ansible Windows Automation Report.png b/collections/ansible_collections/demo/patching/roles/build_report_windows/example_results/Ansible Windows Automation Report.png new file mode 100644 index 0000000..1ead477 Binary files /dev/null and b/collections/ansible_collections/demo/patching/roles/build_report_windows/example_results/Ansible Windows Automation Report.png differ diff --git a/collections/ansible_collections/demo/patching/roles/build_report_windows/files/css/new.css b/collections/ansible_collections/demo/patching/roles/build_report_windows/files/css/new.css new file mode 100644 index 0000000..f58d18f --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_windows/files/css/new.css @@ -0,0 +1,202 @@ +p.hostname { + color: #000000; + font-weight: bolder; + font-size: large; + margin: auto; + width: 50%; + } + + #subtable { + background: #ebebeb; + margin: 0px; + width: 100%; + } + + #subtable tbody tr td { + padding: 5px 5px 5px 5px; + } + + #subtable thead th { + padding: 5px; + } + + * { + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + font-family: "Open Sans", "Helvetica"; + + } + + a { + color: #ffffff; + } + + p { + color: #ffffff; + } + h1 { + text-align: center; + color: #ffffff; + } + + body { + background:#353a40; + padding: 0px; + margin: 0px; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + } + + table { + border-collapse: separate; + background:#fff; + @include border-radius(5px); + @include box-shadow(0px 0px 5px rgba(0,0,0,0.3)); + } + + .main_net_table { + margin:50px auto; + } + + thead { + @include border-radius(5px); + } + + thead th { + font-size:16px; + font-weight:400; + color:#fff; + @include text-shadow(1px 1px 0px rgba(0,0,0,0.5)); + text-align:left; + padding:20px; + border-top:1px solid #858d99; + background: #353a40; + + &:first-child { + @include border-top-left-radius(5px); + } + + &:last-child { + @include border-top-right-radius(5px); + } + } + + tbody tr td { + font-weight:400; + color:#5f6062; + font-size:13px; + padding:20px 20px 20px 20px; + border-bottom:1px solid #e0e0e0; + } + + tbody tr:nth-child(2n) { + background:#f0f3f5; + } + + tbody tr:last-child td { + border-bottom:none; + &:first-child { + @include border-bottom-left-radius(5px); + } + &:last-child { + @include border-bottom-right-radius(5px); + } + } + + td { + vertical-align: top; + } + + span.highlight { + background-color: yellow; + } + + .expandclass { + color: #5f6062; + } + + .content{ + display:none; + margin: 10px; + } + + header { + width: 100%; + position: initial; + float: initial; + padding: 0; + margin: 0; + border-radius: 0; + height: 88px; + background-color: #171717; + } + + .header-container { + margin: 0 auto; + width: 100%; + height: 100%; + max-width: 1170px; + padding: 0; + float: initial; + display: flex; + align-items: center; + } + + .header-logo { + width: 137px; + border: 0; + margin: 0; + margin-left: 15px; + } + + .header-link { + margin-left: 40px; + text-decoration: none; + cursor: pointer; + text-transform: uppercase; + font-size: 15px; + font-family: 'Red Hat Text'; + font-weight: 500; + } + + .header-link:hover { + text-shadow: 0 0 0.02px white; + text-decoration: none; + } + + table.net_info td { + padding: 5px; +} + +p.expandclass:hover { + text-decoration: underline; + color: #EE0000; + cursor: pointer; +} + +.summary_info { +} + +.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active, a.ui-button:active, .ui-button:active, .ui-button.ui-state-active:hover { + border: 1px solid #5F0000; + background: #EE0000; +} + +div#net_content { + padding: 0px; + height: auto !important; +} + +img.router_image { + vertical-align: middle; + padding: 0px 10px 10px 10px; + width: 50px; +} + +table.net_info { + width: 100%; +} + +p.internal_label { + color: #000000; +} \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_windows/files/redhat-ansible-logo.svg b/collections/ansible_collections/demo/patching/roles/build_report_windows/files/redhat-ansible-logo.svg new file mode 100644 index 0000000..2ecef98 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_windows/files/redhat-ansible-logo.svg @@ -0,0 +1,48 @@ + + + + +Logo-Red_Hat-Ansible_Automation_Platform-A-Reverse-RGB + + + + + + + + + + + diff --git a/collections/ansible_collections/demo/patching/roles/build_report_windows/files/server.png b/collections/ansible_collections/demo/patching/roles/build_report_windows/files/server.png new file mode 100644 index 0000000..9ad96fc Binary files /dev/null and b/collections/ansible_collections/demo/patching/roles/build_report_windows/files/server.png differ diff --git a/collections/ansible_collections/demo/patching/roles/build_report_windows/files/webpage_logo.png b/collections/ansible_collections/demo/patching/roles/build_report_windows/files/webpage_logo.png new file mode 100644 index 0000000..65b5836 Binary files /dev/null and b/collections/ansible_collections/demo/patching/roles/build_report_windows/files/webpage_logo.png differ diff --git a/collections/ansible_collections/demo/patching/roles/build_report_windows/tasks/main.yml b/collections/ansible_collections/demo/patching/roles/build_report_windows/tasks/main.yml new file mode 100644 index 0000000..f349f23 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_windows/tasks/main.yml @@ -0,0 +1,24 @@ +- name: create HTML report + ansible.builtin.template: + src: report.j2 + dest: "{{ file_path }}/windows.html" + +- name: copy CSS over + ansible.builtin.copy: + src: "css" + dest: "{{ file_path }}" + directory_mode: true + +- name: copy logos over + ansible.builtin.copy: + src: "{{ item }}" + dest: "{{ file_path }}" + directory_mode: true + loop: + - "webpage_logo.png" + - "redhat-ansible-logo.svg" + - "server.png" + +- name: display link to inventory report + ansible.builtin.debug: + msg: "Please go to http://{{ ansible_host }}/windows.html" \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_windows/templates/header.j2 b/collections/ansible_collections/demo/patching/roles/build_report_windows/templates/header.j2 new file mode 100644 index 0000000..6d504d0 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_windows/templates/header.j2 @@ -0,0 +1,15 @@ + + +
+
+
+ + + +
+
\ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_windows/templates/packages.j2 b/collections/ansible_collections/demo/patching/roles/build_report_windows/templates/packages.j2 new file mode 100644 index 0000000..f290897 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_windows/templates/packages.j2 @@ -0,0 +1,29 @@ + +
+
+ + +
+
+ \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_windows/templates/report.j2 b/collections/ansible_collections/demo/patching/roles/build_report_windows/templates/report.j2 new file mode 100644 index 0000000..96b5f3d --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_windows/templates/report.j2 @@ -0,0 +1,101 @@ + + + + Ansible Windows Automation Report + + + + + + + + + + + +
+ {% include 'header.j2' %} +
+
+

Ansible Windows Automation Report

+

+

+ + + + + + + + + +{% for windows_host in groups['tag_Windows']|sort %} + + + + + +{% endfor %} + +
Windows DeviceOperating SystemOperating System Kernel Version
+
+

+ {{ hostvars[windows_host]['inventory_hostname'].split('.')[0] }}

+
+{% if detailedreport == 'True' %} +{% include 'packages.j2' %} +{% include 'services.j2' %} +{% endif %} +
{{hostvars[windows_host]['ansible_os_family']|default("none")}}{{hostvars[windows_host]['ansible_distribution']|default("none")}}
+

Created with


+
+
+
+ + diff --git a/collections/ansible_collections/demo/patching/roles/build_report_windows/templates/services.j2 b/collections/ansible_collections/demo/patching/roles/build_report_windows/templates/services.j2 new file mode 100644 index 0000000..b443161 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_windows/templates/services.j2 @@ -0,0 +1,29 @@ + +
+
+ + +
+
+ \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_windows/vars/main.yml b/collections/ansible_collections/demo/patching/roles/build_report_windows/vars/main.yml new file mode 100644 index 0000000..f09b15e --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_windows/vars/main.yml @@ -0,0 +1 @@ +file_path: /var/www/html \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/README.md b/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/README.md new file mode 100644 index 0000000..dec8155 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/README.md @@ -0,0 +1,36 @@ +build_report_windows_patch +======== + +Installs Apache and creates a report based on facts from Windows update job + +Requirements +------------ + +Must run on Apache server + +Role Variables / Configuration +-------------- + +N/A + +Dependencies +------------ + +N/A + +Example Playbook +---------------- + +The role can be used to create an html patching report on any number of Linux hosts using any number of Windows servers + + +``` +--- +- hosts: all + + tasks: + - name: Run Windows Patch Report + import_role: + name: shadowman.reports.build_report_windows_patch + +``` \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/defaults/main.yml b/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/defaults/main.yml new file mode 100644 index 0000000..aaf5c3d --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/defaults/main.yml @@ -0,0 +1,3 @@ +EMAIL_FROM: tower@shadowman.dev +to_emails: alex@shadowman.dev,tower@shadowman.dev +EMAIL_TO: "{{ to_emails.split(',') }}" \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/example_results/Full_Report.png b/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/example_results/Full_Report.png new file mode 100644 index 0000000..615a021 Binary files /dev/null and b/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/example_results/Full_Report.png differ diff --git a/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/files/css/main.css b/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/files/css/main.css new file mode 100644 index 0000000..dfeb435 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/files/css/main.css @@ -0,0 +1,111 @@ +p.hostname { + color: #000000; + font-weight: bolder; + font-size: large; + } + + #subtable { + background: #ebebeb; + margin: 0px; + } + + #subtable tbody tr td { + padding: 5px 5px 5px 5px; + } + + #subtable thead th { + padding: 5px; + } + + * { + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + font-family: "Open Sans", "Helvetica"; + + } + + a { + color: #ffffff; + } + + p { + color: #ffffff; + } + h1 { + text-align: center; + color: #ffffff; + } + + body { + background:#353a40; + } + + table { + border-collapse: separate; + background:#fff; + @include border-radius(5px); + margin:50px auto; + @include box-shadow(0px 0px 5px rgba(0,0,0,0.3)); + } + + thead { + @include border-radius(5px); + } + + thead th { + font-family: 'Patua One', monospace; + font-size:16px; + font-weight:400; + color:#fff; + @include text-shadow(1px 1px 0px rgba(0,0,0,0.5)); + text-align:left; + padding:20px; + border-top:1px solid #858d99; + background: #353a40; + + &:first-child { + @include border-top-left-radius(5px); + } + + &:last-child { + @include border-top-right-radius(5px); + } + } + + tbody tr td { + font-family: 'Open Sans', sans-serif; + font-weight:400; + color:#5f6062; + font-size:13px; + padding:20px 20px 20px 20px; + border-bottom:1px solid #e0e0e0; + + } + + tbody tr:nth-child(2n) { + background:#f0f3f5; + } + + tbody tr:last-child td { + border-bottom:none; + &:first-child { + @include border-bottom-left-radius(5px); + } + &:last-child { + @include border-bottom-right-radius(5px); + } + } + + span.highlight { + background-color: yellow; + } + + .expandclass { + color: #5f6062; + } + + .content{ + display:none; + margin: 10px; + } \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/files/webpage_logo.png b/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/files/webpage_logo.png new file mode 100644 index 0000000..3d99673 Binary files /dev/null and b/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/files/webpage_logo.png differ diff --git a/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/tasks/main.yml b/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/tasks/main.yml new file mode 100644 index 0000000..12a9a74 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/tasks/main.yml @@ -0,0 +1,38 @@ +- name: Create HTML report + ansible.builtin.template: + src: report.j2 + dest: "{{ file_path }}/windowspatch.html" + check_mode: no + +- name: Copy CSS over + ansible.builtin.copy: + src: "css" + dest: "{{ file_path }}" + directory_mode: true + check_mode: no + +- name: Copy logo over + ansible.builtin.copy: + src: "webpage_logo.png" + dest: "{{ file_path }}" + directory_mode: true + check_mode: no + +- name: Display link to Patch report + ansible.builtin.debug: + msg: "Please go to http://{{ ansible_host }}/windowspatch.html" + +- name: Send Report via E-mail + community.general.mail: + host: "{{ EMAIL_HOST }}" + username: "{{ EMAIL_USERNAME }}" + password: "{{ EMAIL_PASSWORD }}" + port: "{{ EMAIL_PORT }}" + subject: "Windows Patching Report" + body: "{{ lookup('template', 'report.j2') }}" + from: "{{ EMAIL_FROM }}" + to: "{{ EMAIL_TO }}" + subtype: html + delegate_to: localhost + become: false + check_mode: no \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/templates/report.j2 b/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/templates/report.j2 new file mode 100644 index 0000000..058b0db --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/templates/report.j2 @@ -0,0 +1,115 @@ + + + + Windows Patch Report + + +
+

Ansible Windows Patching Report

+ +
+ + +
+
+ + + + + + + + + +{% for windows_host in groups['tag_Windows']|sort %} + + + + + + +{% endfor %} + +
HostnameOperating SystemRequired Updates
{{hostvars[windows_host]['inventory_hostname']}}{{hostvars[windows_host]['ansible_distribution']|default("none")}} +
    + +{% if hostvars[windows_host].patchresult.updates is defined and hostvars[windows_host].patchresult.found_update_count|int > 0 %} +{% for update in hostvars[windows_host].patchresult.updates %} +{% set updatenum = hostvars[windows_host].patchresult.updates[update] %} +
  • {{updatenum.title}}
  • +{% endfor %} +{% else %} +
  • Compliant
  • +{% endif %} +
+
+{% for host in ansible_play_hosts %} +

Created with Ansible on {{hostvars[host].ansible_date_time.iso8601}}

+{% endfor %} + + + \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/vars/main.yml b/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/vars/main.yml new file mode 100644 index 0000000..f09b15e --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/vars/main.yml @@ -0,0 +1 @@ +file_path: /var/www/html \ No newline at end of file diff --git a/linux/patching_report.yml b/linux/patching_report.yml new file mode 100644 index 0000000..a85d6c8 --- /dev/null +++ b/linux/patching_report.yml @@ -0,0 +1,13 @@ +--- +- hosts: "{{ 'reports' | default(node1) }}" + + tasks: + - yum: + name: httpd + + - service: + name: httpd + state: started + + - include_role: + name: demo.patching.build_report_linux \ No newline at end of file