add patch report

This commit is contained in:
willtome
2022-03-23 13:50:47 -04:00
parent 7534df60c6
commit 4653d7d9ca
69 changed files with 2806 additions and 0 deletions

View File

@@ -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()

View File

@@ -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<name>.*)\s(?P<goal>\w+)\/(?P<state>\w+)(\,\sprocess\s(?P<pid>[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<service>.*?)\s+[0-9]:(?P<rl0>on|off)\s+[0-9]:(?P<rl1>on|off)\s+[0-9]:(?P<rl2>on|off)\s+'
'[0-9]:(?P<rl3>on|off)\s+[0-9]:(?P<rl4>on|off)\s+[0-9]:(?P<rl5>on|off)\s+[0-9]:(?P<rl6>on|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<service>.*?)\s+(?P<rl0>on|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()

View File

@@ -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 <http://www.gnu.org/licenses/>.
# 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;

View File

@@ -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"
},
# }
'''

View File

@@ -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 <http://www.gnu.org/licenses/>.
# 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;

View File

@@ -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"
},
# }
'''