[
  {
    "path": "README.md",
    "content": "![alt tag](https://raw.githubusercontent.com/lateralblast/lunar/master/lunar.png)\n\nLUNAR\n=====\n\nLockdown UNix Auditing and Reporting\n\nVersion\n-------\n\nCurrent version 15.9.1\n\nRefer to lunar.sh and changelog for more up to date version information\n\nLicense\n-------\n\nCC BY-SA: https://creativecommons.org/licenses/by-sa/4.0/\n\nFund me here: https://ko-fi.com/richardatlateralblast\n\n** NOTICE **\n------------\n\nRun this code in audit more only, e.g. with -a or --audit switch.\nRun lockdown at your own risk. As per any system change, have backups.\nI'm working on improving the recovery mode, but there may still be bugs.\n\nI've tried to clean up this script as much as possible using shellcheck,\nand I've enabled the option to use the -e (errexit) and -u (nounset) shell\nflags to help protect against errors. The -x (xtrace) shell flag can be\nenabled by using the script with the -Q or --debug flag.\n\nStatus\n------\n\nIn progress:\n\n- More flexibility in reporting format(s) e.g. CSV\n- More inline documentation and documentation output\n- Adding Azure support (current focus)\n- Adding Kubernetes support\n- Adding Apache support\n\nIntroduction\n------------\n\nThis scripts generates a scored audit report of a Unix host's security.\nIt is based on the CIS and other frameworks. Where possible there are\nreferences to the CIS and other benchmarks in the code documentation.\n\nWhy a shell script? I wanted a tool that was able to run on locked down systems\nwhere other tools may not be available. I also wanted a tool that ran on all\nversions of UNIX. Having said that there are some differences between sh and\nbash, so I've used functions only from sh.\n\nThere is no warranty implied or given with this script. My recommendation\nis to use this script in audit mode only, and address each warning individually\nvia policy, documentation and configuration management. \n\nI am by no means a coder, so there are bound to be bugs and better ways to\napproach things in this script, so a sincere thank you to the people who have \nprovided feedback, updates and patches to fix bugs/features in code.\n\nIt can also can perform a lockdown. Unlike some other scripts I have added\ncapability to backout changes. Files are backed up using cpio to a directory\nbased on the date.\n\nAlthough it can perform a lockdown, as previously stated, I'd recommend you \naddress the warnings via policy, documentation and configuration management.\nThis is how I use the tool. The AWS Services audit only supports reporting,\nit does not provide lockdown capability.\n\nSupported Operating Systems\n---------------------------\n\nThe following Operating Systems are supported:\n\n- Linux\n  - Rocky Linux\n  - RHEL\n  - Centos\n  - Scientific Linux\n  - SLES\n  - Debian\n  - Ubuntu\n  - Amazon Linux\n- Solaris\n- Mac OS X\n- FreeBSD (needs more testing)\n- AIX (needs more testing)\n- ESXi (initial support - some tests)\n\nWindows support would require the installation of additional software, so I haven't looked into it.\nHaving said that, Windows support may come in the future via bash.\n\nSupported Services\n------------------\n\nThe following services are supported:\n\n- AWS\n- Azure\n  - Entra ID (not complete)\n  - Storage (not complete)\n  - Compute (not complete)\n- Docker\n- Kubernetes (not complete)\n- Apache (not complete)\n\nThe AWS Services audit uses the AWS CLI, and as such requires a user with the\nappropriate rights. It does not currently support the lockdown capability,\nit only supports generating an audit report against the CIS benchmark.\n\nThere are a couple of the checks that can only be done or resolved via the GUI.\nAn example of this is enabling billing. Refer to the CIS Benchmark for more information.\n\nWhere possible I've put suggested fix commands in the verbose audit output.\nAgain in some cases, these can only be done by the CLI. Refer to the CIS\nBenchmark for more information.\n\nIn addition I've added a recommendations mode that checks AWS against publicly\navailable best practice from companies like Cloud Conformity.\n\nConfiguration Management\n------------------------\n\nThe following configuration management output is supported:\n\n- Ansible\n\nThis option outputs example ansible configuration management code/stanzas\nfor implementing the recommendation.\n\nRequirements\n------------\n\nFor UNIX:\n\n- Ubuntu / Debian\n  - sysv-rc-conf\n  - bc\n  - finger\n\nFor AWS:\n\n- AWS \n  - AWS CLI\n  - AWS Credentials (API Access and Secret Keys)\n  - Read rights to appropriate AWS services, e.g. \n    - CloudTrail:DescribeTrails\n    - Config:DescribeConfigurationRecorders\n    - SNS:ListSubscriptionsByTopic\n\nFor Azure:\n\n- Azure\n  - Azure CLI\n  - Extensions\n    - databricks\n    - bastion\n    - resource-graph\n    - application-insights\n\nUsage\n-----\n\n```\nUsage: ./lunar.sh -switch|--switch\n\nswitch(es):\n-----------\n-1|--list)\n  List changes/backups\n-2|--tests)\n  Print tests\n-3|--printfunct)\n  Print function\n-4|--dryrun)\n  Run in dryrun mode\n-6|--format)\n  Outpt format/type\n-7|--file)\n  Output file\n-8|--usesudo)\n  Use sudo\n-9|--shellcheck)\n  Run shellcheck against script\n-0|--force)\n  Force action\n-a|--audit)\n  Run in audit mode (for Operating Systems - no changes made to system)\n-A|--fullaudit)\n  Run in audit mode and include filesystems (for Operating Systems - no changes made to system)\n-b|--backups|--listbackups)\n  List backups\n-B|--basedir)\n  Set base directory\n-c|--codename|--distro)\n   Distro/Code name (used with docker/multipass)\n-C|--shell)\n  Run docker-compose testing suite (drops to shell in order to do more testing)\n-d|--dockeraudit)\n  Run in audit mode (for Docker - no changes made to system)\n-D|--dockertests)\n  List all Docker functions available to selective mode\n-e|--host)\n  Run in audit mode on external host (for Operating Systems - no changes made to system)\n-E|--hash|--passwordhash)\n  Password hash\n-f|--action)\n  Action (e.g delete - used with multipass)\n-F|--tempfile)\n  Temporary file to use for operations\n-g|--giturl)\n  Git URL for code to copy to container\n-G|--wheelgroup)\n  Set wheel group\n-h|--help)\n  Display help\n-H|--usage)\n  Display usage\n-i|--anacron)\n  Enable/Disable anacron\n-I|--type)\n  Audit type\n-k|--kubeaudit)\n  Run in audit mode (for Kubernetes - no changes made to system)\n-K|--function|--test)\n  Do a specific function\n-l|--lockdown)\n  Run in lockdown mode (for Operating Systems - changes made to system)\n-L|--fulllockdown|fulllock)\n  Run in lockdown mode (for Operating Systems - changes made to system)\n-m|--machine|--vm)\n  Set virtualisation type\n-M|--workdir)\n  Set work directory\n-n|--ansible)\n  Output ansible\n-N|--nocat)\n  Do output cat in score\n-o|--os|--osver)\n  Set OS version\n-O|--osinfo|--systeminfo)\n  Print OS/System information\n-p|--previous)\n  Print previous audit information\n-P|--sshsandbox|--sandbox)\n  Enable/Disabe SSH sandbox\n-q|--quiet|--nostrict)\n  Run in quiet mode\n-Q|--debug)\n  Run in debug mode\n-r|--awsregion|--region)\n  Set AWS region\n-R|--moduleinfo|--testinfo)\n  Print information about a module\n-s|--select|--check)\n  Run in selective mode (only run tests you want to)\n-S|--unixtests|--unix)\n  List UNIX tests\n-t|--tag|--name)\n  Set docker tag\n-T|--tempdir)\n  Set temp directoru\n-u|--undo)\n  Undo lockdown (for Operating Systems - changes made to system)\n-U|--dofiles)\n  Include filesystems\n-v|--verbose)\n  Run in verbose mode\n-V|--version)\n  Print version\n-w|--awsaudit)\n  Run in audit mode (for AWS - no changes made to system)\n-W|--awstests|--aws)\n  List all AWS functions available to selective mode\n-x|--awsrec)\n  Run in recommendations mode (for AWS - no changes made to system)\n-X|--strict)\n  Run shellcheck against script\n-z)\n  Run specified audit function in lockdown mode\n-Z|--changes|--listchanges)\n  List changes\n```\n\nExamples\n--------\n\nPerform full audit (without recursive file system checks):\n\n```\n./lunar.sh --audit\n```\n\nList tests:\n\n```\n./lunar.sh --tests\n```\n\nList AWS tests:\n\n```\n./lunar.sh --tests aws\n```\n\nDo a specific test:\n\n```\n./lunar.sh --audit --select remote_shell\n```\n\nCreate a Ubuntu 24.04 multipass VM for testing:\n\n```\n./lunar.sh --action create --machine multipass --osver 24.04 \n```\n\nMore Information\n----------------\n\nFor more information refer to wiki:\n\n[Wiki](https://github.com/lateralblast/lunar/wiki)\n\n[Usage](https://github.com/lateralblast/lunar/wiki/Usage)\n\n[Ansible](https://github.com/lateralblast/lunar/wiki/Ansible)\n\n[Ubuntu](https://github.com/lateralblast/lunar/wiki/Ubuntu)\n\n[Solaris 11](https://github.com/lateralblast/lunar/wiki/Solaris_11)\n\n[CentOS](https://github.com/lateralblast/lunar/wiki/CentOS)\n\n[Amazon Linux](https://github.com/lateralblast/lunar/wiki/Amazon)\n\n[AWS](https://github.com/lateralblast/lunar/wiki/AWS)\n\n[Docker](https://github.com/lateralblast/lunar/wiki/Docker)\n\nTesting\n-------\n\nAdded a simple testing framework for debugging the lunar script itself. \nThis uses docker compose to start a container, mount the lunar directory and run lunar.\n"
  },
  {
    "path": "aws/account-creation-policy.json",
    "content": "{\n  \"Version\": \"2012-10-17\",\n  \"Statement\": [\n    {\n      \"Effect\": \"Allow\",\n      \"Principal\": {\n        \"Service\": \"ec2.amazonaws.com\"\n      },\n      \"Action\": \"sts:AssumeRole\"\n    }\n  ]\n}\n"
  },
  {
    "path": "aws/iam-manager-policy.json",
    "content": "{\n\t\"Version\": \"2012-10-17\",\n  \"Statement\": [\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"iam:AddUserToGroup\",\n        \"iam:AttachGroupPolicy\",\n        \"iam:DeleteGroupPolicy\",\n        \"iam:DeleteUserPolicy\",\n        \"iam:DetachGroupPolicy\",\n        \"iam:DetachRolePolicy\",\n        \"iam:DetachUserPolicy\",\n        \"iam:PutGroupPolicy\",\n        \"iam:PutUserPolicy\",\n        \"iam:RemoveUserFromGroup\",\n        \"iam:UpdateGroup\",\n        \"iam:UpdateAssumeRolePolicy\",\n        \"iam:UpdateUser\",\n        \"iam:GetPolicy\",\n        \"iam:GetPolicyVersion\",\n        \"iam:GetRole\",\n        \"iam:GetRolePolicy\",\n        \"iam:GetUser\",\n        \"iam:GetUserPolicy\",\n        \"iam:ListEntitiesForPolicy\",\n        \"iam:ListGroupPolicies\",\n        \"iam:ListGroups\",\n        \"iam:ListGroupsForUser\",\n        \"iam:ListPolicies\",\n        \"iam:ListPoliciesGrantingServiceAccess\",\n        \"iam:ListPolicyVersions\",\n        \"iam:ListRolePolicies\",\n        \"iam:ListAttachedGroupPolicies\",\n        \"iam:ListAttachedRolePolicies\",\n        \"iam:ListAttachedUserPolicies\",\n        \"iam:ListRoles\",\n        \"iam:ListUsers\"\n      ],\n      \"Resource\": \"*\"\n    },\n    {\n      \"Effect\": \"Deny\",\n      \"Action\": [\n        \"iam:CreateGroup\",\n        \"iam:CreatePolicy\",\n        \"iam:CreatePolicyVersion\",\n        \"iam:CreateRole\",\n        \"iam:CreateUser\",\n        \"iam:DeleteGroup\",\n        \"iam:DeletePolicy\",\n        \"iam:DeletePolicyVersion\",\n        \"iam:DeleteRole\",\n        \"iam:DeleteRolePolicy\",\n        \"iam:DeleteUser\",\n        \"iam:PutRolePolicy\"\n      ],\n      \"Resource\": \"*\"\n    }\n  ]\n}\n\n"
  },
  {
    "path": "aws/iam-master-policy.json",
    "content": "{\n  \"Version\": \"2012-10-17\",\n  \"Statement\": [\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"iam:CreateGroup\",\n        \"iam:CreatePolicy\",\n        \"iam:CreatePolicyVersion\",\n        \"iam:CreateRole\",\n        \"iam:CreateUser\",\n        \"iam:DeleteGroup\",\n        \"iam:DeletePolicy\",\n        \"iam:DeletePolicyVersion\",\n        \"iam:DeleteRole\",\n        \"iam:DeleteRolePolicy\",\n        \"iam:DeleteUser\",\n        \"iam:PutRolePolicy\",\n        \"iam:GetPolicy\",\n        \"iam:GetPolicyVersion\",\n        \"iam:GetRole\",\n        \"iam:GetRolePolicy\",\n        \"iam:GetUser\",\n        \"iam:GetUserPolicy\",\n        \"iam:ListEntitiesForPolicy\",\n        \"iam:ListGroupPolicies\",\n        \"iam:ListGroups\",\n        \"iam:ListGroupsForUser\",\n        \"iam:ListPolicies\",\n        \"iam:ListPoliciesGrantingServiceAccess\",\n        \"iam:ListPolicyVersions\",\n        \"iam:ListRolePolicies\",\n        \"iam:ListAttachedGroupPolicies\",\n        \"iam:ListAttachedRolePolicies\",\n        \"iam:ListAttachedUserPolicies\",\n        \"iam:ListRoles\",\n        \"iam:ListUsers\"\n      ],\n      \"Resource\": \"*\"\n    },\n    {\n      \"Effect\": \"Deny\",\n      \"Action\": [\n        \"iam:AddUserToGroup\",\n        \"iam:AttachGroupPolicy\",\n        \"iam:DeleteGroupPolicy\",\n        \"iam:DeleteUserPolicy\",\n        \"iam:DetachGroupPolicy\",\n        \"iam:DetachRolePolicy\",\n        \"iam:DetachUserPolicy\",\n        \"iam:PutGroupPolicy\",\n        \"iam:PutUserPolicy\",\n        \"iam:RemoveUserFromGroup\",\n        \"iam:UpdateGroup\",\n        \"iam:UpdateAssumeRolePolicy\",\n        \"iam:UpdateUser\"\n      ],\n      \"Resource\": \"*\"\n    }\n  ] \n}\n"
  },
  {
    "path": "aws/server-access-logging.json",
    "content": "{\n  \"LoggingEnabled\": {\n    \"TargetBucket\": \"webapp-service-reports\",\n    \"TargetPrefix\": \"access-logs/\",\n    \"TargetGrants\": [\n      {\n        \"Grantee\": {\n            \"Type\": \"Group\",\n            \"URI\": \"http://acs.amazonaws.com/groups/s3/LogDelivery\"\n         },\n        \"Permission\": \"WRITE\"\n      },\n      {\n        \"Grantee\": {\n            \"Type\": \"Group\",\n            \"URI\": \"http://acs.amazonaws.com/groups/s3/LogDelivery\"\n         },\n        \"Permission\": \"READ_ACP\"\n      }\n    ]\n  }\n}\n"
  },
  {
    "path": "changelog",
    "content": "# Changes:\n# 0.0.0 Thursday, 25 October 2012  9:40:54 AM EST\n# Initial version\n# 0.0.1 Thursday,  1 November 2012  2:28:41 PM EST\n# Added initial audit code\n# 0.0.2 Fri  2 Nov 2012 13:24:54 EST\n# Created subroutines for updating files and parameters\n# 0.0.3 Thursday,  8 November 2012  9:35:19 PM EST\n# Added restore code\n# 0.0.4 Saturday, 10 November 2012 11:37:22 AM EST\n# Added kernel accounting\n# 1.0.0 Monday, 12 November 2012 10:45:27 AM EST\n# Initial Github Commit\n# 1.0.1 Monday, 12 November 2012  9:52:17 PM EST\n# Formating fixes\n# 1.0.2 Monday, 12 November 2012 10:03:54 PM EST\n# Additional cleanup\n# 1.0.3 Thu 15 Nov 2012 02:37:31 EST\n# Initial Solaris 11 support\n# 1.0.4 Fri 16 Nov 2012 10:57:17 EST\n# Updated Solaris 11 support, Initial re-commit to new repository\n# 1.0.5 Sat 17 Nov 2012 09:55:07 EST\n# Added echo services\n# 1.0.6 Monday, 19 November 2012  8:13:20 AM EST\n# Solaris 10 and 11 support mostly done - some minor additions could be made\n# 1.0.7 Monday, 19 November 2012 11:02:05 AM EST\n# Added initial support for Solaris versions less than 10\n# 1.0.8 Thursday, 20 December 2012  2:46:32 PM EST\n# Fixed problem with inetadm command\n# 1.0.9 Thursday, 20 December 2012  3:47:52 PM EST\n# Added -A and -L switches and moved filesystem searches to it\n# 1.1.0 Thu 20 Dec 2012 17:01:52 EST\n# Cleaned up formating\n# 1.1.1 Fri Dec 21 21:43:39 EST 2012\n# Initial Solaris 9 testing completed\n# 1.1.2 Sat Dec 22 08:13:17 EST 2012\n# Fixed bugs with parameter value checking\n# 1.1.3 Sat Dec 22 08:27:53 EST 2012\n# Fixed bug with home directory check\n# 1.1.4 Sat Dec 22 08:50:38 EST 2012\n# Fixed bug with inetd code\n# 1.1.5 Sat Dec 22 08:54:05 EST 2012\n# Fixed Solaris 9 update version detection\n# 1.1.6 Sat Dec 22 16:45:16 EST 2012\n# Updated documentation\n# 1.1.7 Thu Feb 14 20:46:31 EST 2013\n# Initial Linux support\n# 1.1.8 Fri Feb 15 18:40:48 EST 2013\n# Linux xinetd and chkconfig support added\n# 1.1.9 Sat Feb 16 12:01:05 EST 2013\n# Added sysctl audit for Linux\n# 1.2.0 Sat Feb 16 14:09:03 EST 2013\n# Added ftpd logging checking for Linux\n# 1.2.1 Sat Feb 16 14:22:58 EST 2013\n# Updated file update to support tabs\n# 1.2.2 Sat Feb 16 22:30:05 EST 2013\n# Added pam options for Linux\n# 1.2.3 Sun Feb 17 02:17:04 EST 2013\n# Added code for sendmail greeting\n# 1.2.4 Sun 17 Feb 2013 08:27:32 EST\n# Added code for vsftpd banner\n# 1.2.5 Sun Feb 17 19:55:54 EST 2013\n# Added securetty check for Linux\n# 1.2.6 Sun 17 Feb 2013 20:40:27 EST\n# Added auditd config\n# 1.2.7 Mon Feb 18 03:11:37 EST 2013\n# Added warning banners\n# 1.2.8 Mon Feb 18 04:42:08 EST 2013\n# Added X11 warning messages\n# 1.2.9 Mon Feb 18 09:41:55 EST 2013\n# Added Linux core dumps and rhosts for PAM\n# 1.3.0 Mon Feb 18 13:42:24 EST 2013\n# Added gdm.conf audit\n# 1.3.1 Mon Feb 18 14:38:04 EST 2013\n# Added Linux nodev audit\n# 1.3.2 Mon Feb 18 15:08:26 EST 2013\n# Added Linux FDI audit\n# 1.3.3 Mon Feb 18 17:53:30 EST 2013\n# Added X11 nolisten\n# 1.3.4 Mon Feb 18 20:30:30 EST 2013\n# Improved file octal derivation on Solaris\n# 1.3.5 Tue Feb 19 12:47:55 EST 2013\n# Added file verification for Linux\n# 1.3.6 Tue Feb 19 14:48:33 EST 2013\n# Added password strength testing on Linux\n# 1.3.7 Tue Feb 19 15:09:05 EST 2013\n# Added Cipher directive to SSH config\n# 1.3.8 Tue Feb 19 15:37:52 EST 2013\n# Added logrotate configuration\n# 1.3.9 Tue Feb 19 15:52:20 EST 2013\n# Added module loading and mounting to auditd\n# 1.4.0 Tue Feb 19 17:03:17 EST 2013\n# Added modprobe.conf check\n# 1.4.1 Tue Feb 19 17:25:39 EST 2013\n# Added sendmail local-only mode check\n# 1.4.2 Tue Feb 19 17:32:12 EST 2013\n# Added code to check NTP running as ntp user\n# 1.4.3 Tue Feb 19 21:01:02 EST 2013\n# Added selective function to run individual tests\n# 1.4.4 Tue Feb 19 21:34:30 EST 2013\n# Added selinux\n# 1.4.5 Tue Feb 19 21:46:55 EST 2013\n# Added yum config check\n# 1.4.6 Tue Feb 19 22:59:12 EST 2013\n# Added lockout for failed password attempts\n# 1.4.7 Wed Feb 20 10:13:46 EST 2013\n# Simplified RPM verify routine\n# 1.4.8 Wed Feb 20 10:59:28 EST 2013\n# Added root primary group audit\n# 1.4.9 Wed Feb 20 11:16:28 EST 2013\n# Added system account shell check\n# 1.5.0 Wed Feb 20 15:00:07 EST 2013\n# Added handling for [at,cron].[deny,allow]\n# 1.5.1 Wed Feb 20 16:03:18 EST 2013\n# Fixed file append function\n# 1.5.2 Thu Feb 21 14:00:42 EST 2013\n# Fixed code to update files\n# 1.5.3 Thursday, 21 February 2013  3:29:49 PM EST\n# Improved code to fix cron\n# 1.5.4 Thu Feb 21 16:49:46 EST 2013\n# Added rpm check code\n# 1.5.5 Fri 22 Feb 2013 07:23:16 EST\n# Cleaned up code for selective audit\n# 1.5.6 Fri  3 May 2013 16:25:36 EST\n# Fixed minor bug with for loop\n# 1.5.7 Fri May 24 15:46:54 EST 2013\n# Initial Debian/Ubuntu support\n# 1.5.8 Fri May 24 21:04:33 EST 2013\n# Improved Debian/Ubuntu support\n# 1.5.9 Sat May 25 11:40:50 EST 2013\n# Improved Debian/Ubuntu support\n# 1.6.0 Sat May 25 22:35:36 EST 2013\n# Improved Debian/Ubuntu support\n# 1.6.1 Sun Jun  9 09:05:44 EST 2013\n# Added some file checks\n# 1.6.2 Sun Jun  9 23:18:37 EST 2013\n# Improved documentation\n# 1.6.3 Tue Jun 11 14:25:01 EST 2013\n# Updated documentation and added verbose mode\n# 1.6.4 Wed Jun 12 10:35:31 EST 2013\n# Fixed NTP test and added audit test information\n# 1.6.5 Wed Jun 12 17:13:57 EST 2013\n# Added inital SUSE support\n# 1.6.6 Thu Jun 13 16:50:19 EST 2013\n# Added OS X support\n# 1.6.7 Thu Jun 13 19:09:55 EST 2013\n# Added Cyrus and Qpopper check\n# 1.6.8 Thu Jun 13 19:23:10 EST 2013\n# Added Postfix check\n# 1.6.9 Thu Jun 13 19:52:00 EST 2013\n# support\n# 1.7.0 Wed 21 Aug 2013 15:50:51 EST\n# Added check for root SSH keys\n# 1.7.1 Wed 21 Aug 2013 15:57:47 EST\n# Added check for SYSLOG=YES in /etc/default/login for Solaris\n# 1.7.2 Wed 21 Aug 2013 16:10:15 EST\n# Added DISABLETIME flag to /etc/default/login check for Solaris\n# 1.7.3 Wed 21 Aug 2013 16:16:45 EST\n# Added check for LOG_FROM_REMOTE=NO in /etc/default/syslogd for Solaris\n# 1.7.4 Sun 25 Aug 2013 19:35:39 EST\n# Fixed ssh key check code\n# 1.7.5 Thu 29 Aug 2013 15:12:31 EST\n# Added su wheel group check\n# 1.7.6 Thu 29 Aug 2013 15:33:13 EST\n# Added check for users that have never logged in to make sure accounts are locked\n# 1.7.7 Fri 30 Aug 2013 15:01:51 EST\n# Added default crypto check\n# 1.7.8 Fri 30 Aug 2013 15:16:08 EST\n# Added code to check wheel group users\n# 1.7.9 Fri 30 Aug 2013 15:45:06 EST\n# Added restore function to wheel checks\n# 1.8.0 Sat 31 Aug 2013 15:51:56 EST\n# Added check for PASSREQ = YES in /etc/default/login\n# 1.8.1 Tue  3 Sep 2013 13:54:12 EST\n# Added check for SYSLOG = YES in /etc/default/su\n# 1.8.2 Tue  3 Sep 2013 13:56:58 EST\n# Added check for MINDIGIT = 1 in /etc/default/passwd\n# 1.8.3 Tue  3 Sep 2013 14:55:16 EST\n# Added check for UsePrivilegeSeparation yes in /etc/ssh/sshd_config\n# 1.8.4 Tue  3 Sep 2013 14:58:27 EST\n# Added check for PrintMotd no in /etc/ssh/sshd_config\n# 1.8.5 Tue  3 Sep 2013 15:01:25 EST\n# Added check for LoginGraceTime 120 in /etc/ssh/sshd_config\n# 1.8.6 Tue  3 Sep 2013 16:06:05 EST\n# Added check to make sure shells in /etc/shells exist\n# 1.8.7 Thu 12 Sep 2013 15:51:09 EST\n# Added ability to load modules\n# 1.8.8 Mon Sep 16 05:23:51 EDT 2013\n# Bug fixes\n# 1.8.9 Mon Sep 16 19:38:17 EST 2013\n# Fixed logrotate check\n# 1.9.0 Mon 16 Sep 2013 20:03:12 EST\n# Fixed scoring on root group check\n# 1.9.1 Mon Sep 16 20:07:42 EST 2013\n# Added fix information to root SSH key check\n# 1.9.2 Mon 16 Sep 2013 20:28:54 EST\n# Fixed home directory permissions check\n# 1.9.3 Mon 16 Sep 2013 21:02:02 EST\n# Fix dot file checking\n# 1.9.4 Mon 16 Sep 2013 21:14:17 EST\n# Fixed scoring for root PATH check\n# 1.9.5 Mon 16 Sep 2013 22:23:33 EST\n# Fixed scoring for empty password field testing\n# 1.9.6 Tue 17 Sep 2013 08:46:54 EST\n# Fixed scoring in reserved UID check\n# 1.9.7 Tue 17 Sep 2013 08:54:15 EST\n# Fixed scoring for old user logins test\n# 1.9.8 Tue 17 Sep 2013 10:09:50 EST\n# Improved checking for old user logins\n# 1.9.9 Tue 17 Sep 2013 10:42:36 EST\n# Fixed scoring for System Account audit\n# 2.0.0 Tue 17 Sep 2013 10:58:53 EST\n# Numerous bug fixes\n# 2.0.1 Tue 17 Sep 2013 14:43:54 EST\n# Improved SNMP daemon check on Linux\n# 2.0.2 Wed 18 Sep 2013 13:13:23 EST\n# Added RSA SecurID PAM check\n# 2.0.3 Fri 20 Sep 2013 16:57:09 EST\n# Added better handling for *credit password parameters under Linux\n# 2.0.4 Fri 20 Sep 2013 18:21:21 EST\n# Cleaned up linux PAM audit\n# 2.0.5 Sat 21 Sep 2013 15:32:55 EST\n# Improved linux password history audit\n# 2.0.6 Wed  9 Oct 2013 09:50:53 EST\n# Moved directory check\n# 2.0.7 Wed  9 Oct 2013 09:56:16 EST\n# Fixed id check under Solaris\n# 2.0.8 Wed  9 Oct 2013 10:55:38 EST\n# Fixed call to check_inetd_service\n# 2.0.9 Wed  9 Oct 2013 10:56:44 EST\n# Fixed source on Solaris\n# 2.1.0 Wed  9 Oct 2013 11:19:38 EST\n# Fixed \"==\" evaluation\n# 2.1.1 Wed  9 Oct 2013 14:16:37 EST\n# Added check for disabled account to system account check\n# 2.1.2 Wed  9 Oct 2013 14:25:31 EST\n# Fixed grep command in audit_shells\n# 2.1.3 Wed  9 Oct 2013 14:28:33 EST\n# Fixed other grep commands\n# 2.1.4 Wed  9 Oct 2013 14:36:39 EST\n# Fixed set command on Solaris\n# 2.1.5 Wed  9 Oct 2013 14:38:56 EST\n# Fixed two SunOS checks\n# 2.1.6 Wed  9 Oct 2013 14:47:08 EST\n# Fixed message for inactive user account check\n# 2.1.7 Wed  9 Oct 2013 16:32:47 EST\n# Fixed scoring on inactive user account check\n# 2.1.8 Thu 10 Oct 2013 08:46:13 EST\n# Fixed console report on Solaris\n# 2.1.9 Thu 10 Oct 2013 09:30:40 EST\n# Fixed output for check that file ${exists}\n# 2.2.0 Thu 10 Oct 2013 09:44:36 EST\n# Fixed scoring for file permissions check\n# 2.2.1 Thu 10 Oct 2013 09:59:41 EST\n# Fixed security banner check scoring\n# 2.2.2 Wed 15 Jan 2014 09:32:48 EST\n# Fixed bug with shadow check on OS X\n# 2.2.3 Wed 15 Jan 2014 11:07:20 EST\n# Minor bug fixes\n# 2.2.4 Thu 20 Feb 2014 14:55:44 EST\n# Split code out to be more manageable\n# 2.2.5 Wed 12 Mar 2014 11:45:34 EST\n# Various typo fixes\n# 2.2.6 Thu 13 Mar 2014 15:39:00 EST\n# Fixed Login Warning for OS X\n# 2.2.7 Thu 13 Mar 2014 15:59:31 EST\n# Fixed Launchctl check for OS X\n# 2.2.8 Thu 13 Mar 2014 16:00:45 EST\n# Added Apple Remote Events code for OS X\n# 2.2.9 Fri 14 Mar 2014 09:33:14 EST\n# Added Internet Sharing code for OS X\n# 2.3.0 Fri 14 Mar 2014 15:55:55 EST\n# Added Account Lockout code for OS X\n# 2.3.1 Mon 17 Mar 2014 06:40:22 EST\n# Added Printer Sharing code for OS X\n# 2.3.2 Mon 17 Mar 2014 07:58:31 EST\n# Added hot corner check to screen lock check for OS X\n@ 2.3.3 Mon 17 Mar 2014 10:37:20 EST\n# Added SSH check for OS X\n# 2.3.4 Mon 17 Mar 2014 11:21:34 EST\n# Added DVD/CDo sharing check for OS X\n# 2.3.5 Mon 17 Mar 2014 15:28:31 EST\n# Added Wake on Lan check for OS X\n# 2.3.6 Mon 17 Mar 2014 16:00:01 EST\n# Added File Vault check for OS X\n# 2.3.7 Mon 17 Mar 2014 17:03:59 EST\n# Added Gatekeeper check for OS X\n# 2.3.8 Tue 18 Mar 2014 09:06:10 EST\n# Added Safe Downloads list check for OS X\n# 2.3.9 Tue 18 Mar 2014 09:07:23 EST\n# Updated CIS reference for firewall settings fo OS X\n# 2.4.0 Tue 18 Mar 2014 09:50:12 EST\n# Added Secure Keyboard Entry check for OS X\n# 2.4.1 Tue 18 Mar 2014 11:59:01 EST\n# Added Secure Empty Trash check for OS X\n# 2.4.2 Tue 18 Mar 2014 12:09:43 EST\n# Cleaned up some defaults checks for OS X\n# 2.4.3 Tue 18 Mar 2014 12:25:29 ES\n# Added OX Security Auditing check\n# 2.4.4 Tue 18 Mar 2014 12:38:16 EST\n# Cleaned up some code\n# 2.4.5 Tue 18 Mar 2014 15:25:02 EST\n# Added code to check system log retention on OS X\n# 2.4.6 Tue 18 Mar 2014 15:44:13 EST\n# Added code to check bonjour advertising on OS X\n# 2.4.7 Tue 18 Mar 2014 16:13:11 EST\n# Added sudo timeout check\n# 2.4.8 Tue 18 Mar 2014 16:33:21 EST\n# Added Keychain Lock time check for OS X\n# 2.4.9 Wed 19 Mar 2014 07:15:21 EST\n# Added user home directory permisions check for OS X\n# 2.5.0 Wed 19 Mar 2014 07:32:50 EST\n# Added autologin check for OS X\n# 2.5.1 Wed 19 Mar 2014 08:22:03 EST\n# Added autologout check for OS X\n# 2.5.2 Wed 19 Mar 2014 08:48:57 EST\n# Added pwpolicy function for OS X\n# 2.5.3 Wed 19 Mar 2014 09:13:10 EST\n# Added password complexity checks for OS X\n# 2.5.4 Wed 19 Mar 2014 09:18:19 EST\n# Added CIS reference to account login details check for OS X\n# 2.5.5 Wed 19 Mar 2014 09:23:03 EST\n# Added password hints check for OS X\n# 2.5.6 Wed 19 Mar 2014 09:24:56 EST\n# Added CIS reference for guest account check for OS X\n# 2.5.7 Wed 19 Mar 2014 09:27:16 EST\n# Added CIS reference for guest file sharing check for OS X\n# 2.5.8 Wed 19 Mar 2014 09:32:40 EST\n# Added file extensions check for OS X\n# 2.5.9 Wed 19 Mar 2014 11:36:56 EST\n# Added Safari Auto-run check for OS X\n# 2.6.0 Wed 19 Mar 2014 11:42:21 EST\n# Fixed bug with launchctl check\n# 2.6.1 Wed 19 Mar 2014 11:44:25 EST\n# Fixed bug with gatekeeper and wake on lan check\n# 2.6.2 Wed 19 Mar 2014 12:05:53 EST\n# Various bug fixes\n# 2.6.3 Wed 19 Mar 2014 12:20:50 EST\n# Improved ability to run script as non root user in audit only mode\n# 2.6.4 Wed 19 Mar 2014 13:24:05 EST\n# More bug fixes\n# 2.6.5 Wed 19 Mar 2014 17:10:44 EST\n# Added swap to nodev check\n# 2.6.6 Thu 20 Mar 2014 13:52:09 EST\n# Added nosuid filesystem mount check for Linux\n# 2.6.7 Thu 20 Mar 2014 14:41:40 EST\n# Fixed system log check\n# 2.6.8 Thu 20 Mar 2014 14:45:20 EST\n# Added aide check for Linux\n# 2.6.7 Thu 20 Mar 2014 16:55:35 EST\n# Moved grouped function files to full_* to better distinguish them\n# 2.6.8 Thu 20 Mar 2014 17:29:21 EST\n# Added support to old users check to use last rather than finger if finger is not available\n# 2.6.9 Thu 20 Mar 2014 22:56:31 EST\n# Updated SELinux check\n# 2.7.0 Fri 21 Mar 2014 10:29:30 EST\n# Added CIS reference to unconfined daemons test\n# 2.7.1 Fri 21 Mar 2014 10:32:24 EST\n# Added permissions check for /etc/grub to SELinux test\n# 2.7.2 Fri 21 Mar 2014 10:38:24 EST\n# Added CIS reference to single user mode test\n# 2.7.3 Fri 21 Mar 2014 10:46:47 EST\n# Added core dumps restriction to Linux and added CIS reference\n# 2.7.4 Fri 21 Mar 2014 10:56:56 EST\n# Added execshield check\n# 2.7.6 Fri 21 Mar 2014 14:02:30 EST\n# Added code to remove telnet-server package on Linux\n# 2.7.7 Fri 21 Mar 2014 14:06:58 EST\n# Added code to remove rsh-server on package Linux\n# 2.7.8 Fri 21 Mar 2014 14:10:30 EST\n# Added code to remove YP/NIS server packages on Linux\n# 2.7.9 Fri 21 Mar 2014 14:13:10 EST\n# Added code to remove tftp-server package on Linux\n# 2.8.0 Fri 21 Mar 2014 14:29:43 EST\n# Added /etc/netboot check for Solaris 11\n# 2.8.1 Fri 21 Mar 2014 14:51:23 EST\n# Added code to remove talk-server package on Linux\n# 2.8.2 Fri 21 Mar 2014 15:14:24 EST\n# Added code to remove xinetd-server package on Linux\n# 2.8.3 Fri 21 Mar 2014 15:16:44 EST\n# Added CIS references for various xinetd based services for Linux\n# 2.8.4 Fri 21 Mar 2014 15:20:21 EST\n# Added CIS reference for daemon umask check\n# 2.8.5 Fri 21 Mar 2014 15:26:05 EST\n# Added code to remove X Windows package on Linux\n# 2.8.6 Fri 21 Mar 2014 15:47:54 EST\n# Fixed bugs with OS vendor determination\n# 2.8.7 Fri 21 Mar 2014 16:01:40 EST\n# Moved Avahi server code to separate module and added CIS reference\n# 2.8.8 Fri 21 Mar 2014 16:10:05 EST\n# Added code to remove dhcp server package on Linux\n# 2.8.9 Fri 21 Mar 2014 16:11:40 EST\n# Added CIS reference for NTP\n# 2.9.0 Fri 21 Mar 2014 16:19:07 EST\n# Added code to remove openldap-servers package on Linux\n# 2.9.1 Fri 21 Mar 2014 16:20:45 EST\n# Added CIS reference for NFS check\n# 2.9.2 Sun 23 Mar 2014 12:32:36 EST\n# Minor bug fixes\n# 2.9.3 Sun 23 Mar 2014 12:38:22 EST\n# Added CIS reference to NIS server check and code to remove package on Linux\n# 2.9.4 Sun 23 Mar 2014 12:46:47 EST\n# Added package uninstall disable/enable variable\n# 2.9.5 Sun 23 Mar 2014 12:53:28 EST\n# Added CIS reference to FTP server check and code to remove package on Linux\n# 2.9.6 Sun 23 Mar 2014 12:59:18 EST\n# Added CIS reference to HTTP server check and code to remove package on Linux\n# 2.9.7 Sun 23 Mar 2014 13:04:24 EST\n# Added CIS reference for Dovecot check and code to remove package on Linux\n# 2.9.8 Sun 23 Mar 2014 13:07:47 EST\n# Added CIS reference to Samba server check and code to remove package on Linux\n# 2.9.9 Sun 23 Mar 2014 13:11:41 EST\n# Added CIS reference to Squid server check and code to remove package on Linux\n# 3.0.0 Sun 23 Mar 2014 13:18:10 EST\n# Added CIS reference to SNMP check and code to remove package on Linux\n# 3.0.1 Sun 23 Mar 2014 13:23:20 EST\n# Added CIS reference to Postfix check and code to check local-only agent mode on Linux\n# 3.0.2 Sun 23 Mar 2014 13:37:30 EST\n# Added code to install and configure rsyslog on Linux\n# 3.0.3 Sun Sun 23 Mar 2014 15:38:27 EST\n# Added CIS references to system accounting check\n# 3.0.4 Sun 23 Mar 2014 15:41:50 EST\n# Added CIS references to logrotate check\n# 3.0.5 Sun 23 Mar 2014 16:01:36 EST\n# Added CIS references to sysctl check\n# 3.0.6 Sun 23 Mar 2014 16:15:53 EST\n# Added CIS references to TCP wrappers check\n# 3.0.7 Mon 24 Mar 2014 09:20:12 EST\n# Added iptables check\n# 3.0.8 Mon 24 Mar 2014 09:22:53 EST\n# Added CIS reference to cron permissions check\n# 3.0.9 Mon 24 Mar 2014 09:35:34 EST\n# Cleaned up crow.allow test and added CIS reference\n# 3.1.0 Mon 24 Mar 2014 09:59:21 EST\n# Added CIS reference to SSH test\n# 3.1.1 Mon 24 Mar 2014 10:02:57 EST\n# Added CIS reference to password hashing algorithm test\n# 3.1.2 Mon 24 Mar 2014 10:10:33 EST\n# Added CIS reference to password policy test\n# 3.1.3 Mon 24 Mar 2014 10:26:28 EST\n# Added CIS reference for account lockout timeout test\n# 3.1.4 Mon 24 Mar 2014 17:31:53 EST\n# Added CIS reference for password reuse test\n# 3.1.5 Mon 24 Mar 2014 17:36:23 EST\n# Added CIS reference for remote console test\n# 3.1.6 Mon 24 Mar 2014 17:38:52 EST\n# Added CIS reference for pam wheel test\n# 3.1.7 Mon 24 Mar 2014 17:40:29 EST\n# Added CIS reference for password expiry test\n# 3.1.8 Mon 24 Mar 2014 17:45:45 EST\n# Added CIS reference for system account test\n# 3.1.9 Mon 24 Mar 2014 17:47:28 EST\n# Added CIS reference for default root group test\n# 3.2.0 Mon 24 Mar 2014 18:12:53 EST\n# Added CIS reference for user default umask test\n# 3.2.1 Mon 24 Mar 2014 19:36:42 EST\n# Added code to test Gnome login message on Linux\n# 3.2.2 Mon 24 Mar 2014 21:06:01 EST\n# Added CIS reference for world writable files test\n# 3.2.3 Mon 24 Mar 2014 21:09:52 EST\n# Added CIS reference for unowned file check\n# 3.2.4 Mon 24 Mar 2014 21:11:25 EST\n# Added CIS reference for suid system executables test\n# 3.2.5 Mon 24 Mar 2014 21:14:24 EST\n# Added CIS reference for password field test\n# 3.2.6 Mon 24 Mar 2014 21:16:41 EST\n# Added CIS reference for legacy NIS entries test\n# 3.2.7 Mon 24 Mar 2014 21:21:11 EST\n# Added CIS reference for reserved id test\n# 3.2.8 Mon 24 Mar 2014 21:23:46 EST\n# Added CIS reference for root path test\n# 3.2.9 Mon 24 Mar 2014 21:25:58 EST\n# Added CIS reference for user home permissions test\n# 3.3.0 Mon 24 Mar 2014 21:27:52 EST\n# Added CIS reference for user dot files test\n# 3.3.1 Mon 24 Mar 2014 21:29:32 EST\n# Added CIS reference for user .netrc test\n# 3.3.2 Mon 24 Mar 2014 21:35:03 EST\n# Added CIS reference for user .rhosts test\n# 3.3.3 Mon 24 Mar 2014 21:39:43 EST\n# Added CIS reference for group test\n# 3.3.4 Mon 24 Mar 2014 21:45:24 EST\n# Added CIS reference for duplicate ids test\n# 3.3.5 Mon 24 Mar 2014 21:47:39 EST\n# Added CIS reference for duplicate gids test\n# 3.3.6 Mon 24 Mar 2014 21:54:09 EST\n# Added CIS reference for duplicate users test\n# 3.3.7 Tue 25 Mar 2014 06:21:54 EST\n# Added CIS reference for user .forward test\n# 3.3.8 Tue 25 Mar 2014 07:33:44 EST\n# Fixed screen lock test for OS X\n# 3.3.9 Tue 25 Mar 2014 07:53:48 EST\n# Fixed CD sharing test for OS X\n# 3.4.0 Tue 25 Mar 2014 07:58:34 EST\n# Fixed printer sharing test for OS X\n# 3.4.1 Tue 25 Mar 2014 08:09:02 EST\n# Added firmware password test for OS X\n# 3.4.2 Tue 25 Mar 2014 08:29:09 EST\n# Added CIS NTP reference for OS X\n# 3.4.3 Tue 25 Mar 2014 08:42:51 EST\n# Added code to add NTP pool servers to config file\n# 3.4.4 Tue 25 Mar 2014 09:21:15 EST\n# Improved launchctl function to be able to turn off and on services\n# 3.4.5 Tue 25 Mar 2014 10:19:31 EST\n# Added samba config lockdown tests\n# 3.4.6 Tue 25 Mar 2014 10:27:55 EST\n# Added apache config lockdown tests\n# 3.4.7 Tue 25 Mar 2014 10:31:06 EST\n# Added CIS reference for SSH for OS X\n# 3.4.8 Tue 25 Mar 2014 10:51:37 EST\n# Added Xgrid check\n# 3.4.9 Tue 25 Mar 2014 10:57:18 EST\n# Added code to disable mDNS on OS X\n# 3.5.0 Tue 25 Mar 2014 13:47:00 EST\n# Initial FreeBSD support\n# 3.5.1 Tue 25 Mar 2014 13:54:21 EST\n# Added rc.conf and loader.conf support to file functions\n# 3.5.2 Tue 25 Mar 2014 14:02:58 EST\n# Added FreeBSD support and CIS reference to SSH test\n# 3.5.3 Tue 25 Mar 2014 14:14:26 EST\n# Added CIS reference for FreeBSD for TCP Wrappers and added inetd flag test for FreeBSD\n# 3.5.4 Tue 25 Mar 2014 14:29:21 EST\n# Added ipfw code and CIS reference for FreeBSD\n# 3.5.5 Tue 25 Mar 2014 14:42:04 EST\n# Added inet/init code and CIS reference for FreeBSD\n# 3.5.6 Tue 25 Mar 2014 15:32:56 EST\n# Added daemon umask test and CIS reference for FreeBSD\n# 3.5.7 Tue 25 Mar 2014 15:40:44 EST\n# Added syslog and CIS reference for FreeBSD\n# 3.5.8 Tue 25 test Mar 2014 15:59:26 EST\n# Added sendmail test and CIS reference for FreeBSD\n# 3.5.9 Tue 25 Mar 2014 16:04:18 EST\n# Added bind test and CIS reference for FreeBSD\n# 3.6.0 Tue 25 Mar 2014 16:27:15 EST\n# Added NFS test and CIS reference for FreeBSD\n# 3.6.1 Tue 25 Mar 2014 16:32:36 EST\n# Added NIS test and CIS reference for FreeBSD\n# 3.6.2 Tue 25 Mar 2014 16:39:59 EST\n# Added printing test and CIS reference for FreeBSD\n# 3.6.3 Tue 25 Mar 2014 16:50:16 EST\n# Added core dump test and CIS reference for FreeBSD\n# 3.6.4 Tue 25 Mar 2014 17:02:17 EST\n# Added kernel parameters code and CIS reference for FreeBSD\n# 3.6.5 Tue 25 Mar 2014 17:37:52 EST\n# Added syslog logging entry and CIS reference for FreeBSD while fixing bug with Syslog server code\n# 3.6.6 Tue 25 Mar 2014 17:48:07 EST\n# Added system accounting code and CIS reference for FreeBSD\n# 3.6.7 Tue 25 Mar 2014 17:52:12 EST\n# Added TCP/UDP packet logging code and CIS reference for FreeBSD\n# 3.6.8 Tue 25 Mar 2014 21:42:42 EST\n# Added newsyslog and CIS reference for FreeBSD\n# 3.6.9 Tue 25 Mar 2014 21:50:08 EST\n# Added nosuid mount test and CIS reference for FreeBSD\n# 3.7.0 Tue 25 Mar 2014 21:58:55 EST\n# Added passwd and group permissions test and CIS reference for FreeBSD\n# 3.7.1 Tue 25 Mar 2014 22:02:50 EST\n# Added sticky bit test and CIS reference for FreeBSD\n# 3.7.2 Tue 25 Mar 2014 22:05:40 EST\n# Added world writable files test and CIS reference for FreeBSD\n# 3.7.3 Tue 25 Mar 2014 22:09:34 EST\n# Added suid and sgid files test and CIS reference for FreeBSD\n# 3.7.4 Tue 25 Mar 2014 22:15:30 EST\n# Added user homde directory permissions test and CIS reference for FreeBSD\n# 3.7.5 Tue 25 Mar 2014 22:18:28 EST\n# Added unowned files test and CIS reference for FreeBSD\n# 3.7.6 Tue 25 Mar 2014 22:29:47 EST\n# Added initial PAM test and CIS reference for FreeBSD\n# 3.7.7 Tue 25 Mar 2014 22:34:36 EST\n# Added dotfiles test and CIS reference for FreeBSD\n# 3.7.8 Tue 25 Mar 2014 22:47:39 EST\n# Added cron/at test and CIS references for FreeBSD\n# 3.7.9 Tue 25 Mar 2014 22:54:48 EST\n# Added security banner test and CIS references for FreeBSD\n# 3.8.0 Wed 26 Mar 2014 05:57:25 EST\n# Added X11 listen test and CIS reference for FreeBSD\n# 3.8.1 Wed 26 Mar 2014 06:09:12 EST\n# Added system account test and CIS reference for FreeBSD\n# 3.8.2 Wed 26 Mar 2014 07:13:36 EST\n# Added toor account test and CIS reference for FreeBSD\n# 3.8.3 Wed 26 Mar 2014 07:19:10 EST\n# Added uid 0 test and CIS reference for FreeBSD\n# 3.8.4 Wed 26 Mar 2014 07:30:35 EST\n# Added umask test and CIS reference for FreeBSD\n# 3.8.5 Wed 26 Mar 2014 07:36:10 EST\n# Added mesg n test and CIS reference for FreeBSD\n# 3.8.6 Wed 26 Mar 2014 07:45:29 EST\n# Added password algorithm test and CIS reference for FreeBSD\n# 3.8.7 Wed 26 Mar 2014 08:35:24 EST\n# Added serial logins test and CIS reference for FreeBSD\n# 3.8.8 Wed 26 Mar 2014 08:54:37 EST\n# Added single user password test and CIS reference for FreeBSD\n# 3.8.9 Wed 26 Mar 2014 09:20:46 EST\n# Added X wrapper test and CIS reference for FreeBSD\n# 3.9.0 Wed 26 Mar 2014 11:21:34 EST\n# Added initial AIX support\n# 3.9.1 Wed 26 Mar 2014 13:35:49 EST\n# Added password parameter tests and CIS references for AIX\n# 3.9.2 Wed 26 Mar 2014 13:58:21 EST\n# Added login retry limit test and CIS references for AIX\n# 3.9.3 Wed 26 Mar 2014 14:06:37 EST\n# Added rlogin test and CIS reference for AIX\n# 3.9.4 Wed 26 Mar 2014 14:34:31 EST\n# Added code to drive chuser and added su group test and CIS reference for AIX\n# 3.9.5 Wed 26 Mar 2014 16:48:23 EST\n# Added system user rlogin test and CIS reference for AIX\n# 3.9.6 Wed 26 Mar 2014 17:37:12 EST\n# Added code to drive [rm,ls,ch]itab on AIX\n# 3.9.7 Wed 26 Mar 2014 17:41:27 EST\n# Added qdaemon test and CIS reference for AIX\n# 3.9.8 Wed 26 Mar 2014 17:45:23 EST\n# Added lpd and piobe test and CIS reference for AIX\n# 3.9.9 Wed 26 Mar 2014 17:50:30 EST\n# Added dt test and CIS reference for AIX\n# 4.0.0 Wed 26 Mar 2014 17:54:55 EST\n# Added rcnfs test and CIS reference for AIX\n# 4.0.1 Wed 26 Mar 2014 20:36:07 EST\n# Added world writable files test and CIS reference for AIX\n# 4.0.2 Wed 26 Mar 2014 20:45:50 EST\n# Added unowned files test and CIS reference for AIX\n# 4.0.3 Wed 26 Mar 2014 20:53:15 EST\n# Added setuid files test and CIS reference for AIX\n# 4.0.4 Thu 27 Mar 2014 07:41:22 EST\n# Added Trusted Execution handling code for AIX\n# 4.0.5 Thu 27 Mar 2014 07:57:51 EST\n# Added Trusted Execution tests and CIS reference for AIX\n# 4.0.6 Thu 27 Mar 2014 08:12:32 EST\n# Added code to check AIX package is installed\n# 4.0.7 Thu 27 Mar 2014 08:44:18 EST\n# Added root PATH check and CIS reference for AIX\n# 4.0.8 Thu 27 Mar 2014 08:48:48 EST\n# Added duplicate group test and CIS reference for AIX\n# 4.0.9 Thu 27 Mar 2014 08:52:25 EST\n# Added duplicate user test and CIS reference for AIX\n# 4.1.0 Thu 27 Mar 2014 09:01:12 EST\n# Added empty password field test and CIS reference for AIX\n# 4.1.1 Thu 27 Mar 2014 09:09:00 EST\n# Added cron/at allow tests and CIS references for AIX\n# 4.1.2 Thu 27 Mar 2014 09:14:09 EST\n# Added security motd test and CIS reference for AIX\n# 4.1.3 Thu 27 Mar 2014 10:07:11 EST\n# Added FTP banner test and CIS reference for AIX\n# 4.1.4 Thu 27 Mar 2014 10:13:14 EST\n# Added FTP daemon umask test and CIS reference for AIX\n# 4.1.5 Thu 27 Mar 2014 10:35:00 EST\n# Added FTP users test and CIS reference for AIX\n# 4.1.6 Thu 27 Mar 2014 10:55:57 EST\n# Added sar accounting test and CIS reference for AIX\n# 4.1.7 Thu 27 Mar 2014 10:58:32 EST\n# Added mesgn test and CIS reference for AIX\n# 4.1.8 Thu 27 Mar 2014 11:06:00 EST\n# Added writesrv test and CIS reference for AIX\n# 4.1.9 Thu 27 Mar 2014 11:11:56 EST\n# Added power management test and CIS reference for AIX\n# 4.2.0 Thu 27 Mar 2014 11:30:22 EST\n# Added online documentation daemon test and CIS reference for httpdlite on AIX\n# 4.2.1 Thu 27 Mar 2014 15:05:10 EST\n# Added NCS test and CIS reference for AIX\n# 4.2.2 Thu 27 Mar 2014 15:13:04 EST\n# Added i4ls test and CIS reference of AIX\n# 4.2.3 Thu 27 Mar 2014 15:45:39 EST\n# Added serial login test and CIS reference for AIX\n# 4.2.4 Thu 27 Mar 2014 16:06:59 EST\n# Added user home directory tests and CIS references for AIX\n# 4.2.5 Thu 27 Mar 2014 16:16:13 EST\n# Added /var/adm/sa ownership test and CIS reference for AIX\n# 4.2.6 Thu 27 Mar 2014 16:30:53 EST\n# Added snmp and ras permissions test and CIS reference for AIX\n# 4.2.7 Thu 27 Mar 2014 17:11:37 EST\n# Added various file/directory permissions tests and CIS references for AIX\n# 4.2.8 Thu 27 Mar 2014 17:44:09 EST\n# Added Initial TCP Wrappers test and CIS references for AIX\n# 4.2.9 Fri 28 Mar 2014 07:52:02 EST\n# Added code to drive rctcp on AIX\n# 4.3.0 Fri 28 Mar 2014 08:18:59 EST\n# Added sendmail test and CIS reference for AIX\n# 4.3.1 Fri 28 Mar 2014 08:31:37 EST\n# Added snmp test and CIS reference for AIX\n# 4.3.2 Fri 28 Mar 2014 08:37:56 EST\n# Added sendmail disable variable\n# 4.3.3 Fri 28 Mar 2014 08:46:02 EST\n# Added dhcpcd test and CIS reference for AIX\n# 4.3.4 Fri 28 Mar 2014 08:52:12 EST\n# Added dhcprd test and CIS reference for AIX\n# 4.3.5 Fri 28 Mar 2014 08:56:33 EST\n# Added dhcpsd test and CIS reference for AIX\n# 4.3.6 Fri 28 Mar 2014 09:01:46 EST\n# Added autoconf6 test and CIS reference for AIX\n# 4.3.7 Fri 28 Mar 2014 09:14:02 EST\n# Added gated test and CIS reference for AIX\n# 4.3.8 Fri 28 Mar 2014 09:56:38 EST\n# Added mrouted test and CIS reference for AIX\n# 4.3.9 Fri 28 Mar 2014 10:14:12 EST\n# Added named test and CIS reference for AIX\n# 4.3.9 Fri 28 Mar 2014 10:16:12 EST\n# Added routed test and CIS reference for AIX\n# 4.4.0 Fri 28 Mar 2014 10:21:13 EST\n# Added rwhod test and CIS reference for AIX\n# 4.4.1 Fri 28 Mar 2014 10:26:21 EST\n# Added timed test and CIS reference for AIX\n# 4.4.2 Fri 28 Mar 2014 10:29:26 EST\n# Added dpid2 test and CIS reference for AIX\n# 4.4.3 Fri 28 Mar 2014 10:31:32 EST\n# Added hostmibd test and CIS reference for AIX\n# 4.4.4 Fri 28 Mar 2014 10:32:07 EST\n# Added snmpdmibd test and CIS reference for AIX\n# 4.4.5 Fri 28 Mar 2014 10:33:56 EST\n# Added aixmibd test and CIS reference for AIX\n# 4.4.6 Fri 28 Mar 2014 10:51:38 EST\n# Added NPD tests and CIS references for AIX\n# 4.4.7 Fri 28 Mar 2014 10:57:08 EST\n# Added .netrc tests and CIS references for AIX\n# 4.4.8 Fri 28 Mar 2014 10:59:05 EST\n# Added .rhosts tests and CIS references for AIX\n# 4.4.9 Fri 28 Mar 2014 12:43:48 EST\n# Added hosts.equiv tests and CIS references for AIX\n# 4.5.0 Fri 28 Mar 2014 12:54:51 EST\n# Added code to drive no on AIX\n# 4.5.1 Fri 28 Mar 2014 13:33:07 EST\n# Added network kernel tuning parameter test and CIS references for AIX\n# 4.5.2 Fri 28 Mar 2014 14:38:14 EST\n# Added code to drive subserver on AIX\n# 4.5.3 Fri 28 Mar 2014 14:56:37 EST\n# Added legacy services tests and CIS references for AIX\n# 4.5.4 Sat 29 Mar 2014 20:45:37 EST\n# Added numerous CIS references for Solaris tests\n# 4.5.5 Sun 30 Mar 2014 09:07:50 EST\n# Added more CIS references for Solaris tests\n# 4.5.6 Sun 30 Mar 2014 15:47:53 EST\n# Added more CIS references for Linux tests and cleaned up some Linux test conditions\n# 4.5.7 Sun 30 Mar 2014 18:19:19 EST\n# Added kernel-PAE package check\n# 4.5.8 Sun 30 Mar 2014 18:46:32 EST\n# Added various client package tests for Linux\n# 4.5.9 Sun 30 Mar 2014 20:56:34 EST\n# Added code to remove talk client on Linux\n# 4.6.0 Sun 30 Mar 2014 21:03:03 EST\n# Fixed xinetd test for Linux\n# 4.6.1 Sun 30 Mar 2014 21:48:42 EST\n# Added CIS references and updated syslog configuration for Linux\n# 4.6.2 Sun 30 Mar 2014 22:00:49 EST\n# Updated syslog and rsyslog test for Linux\n# 4.6.3 Mon 31 Mar 2014 09:35:36 EST\n# Added pam_deny and pam_ccred tests for Linux\n# 4.6.4 Mon 31 Mar 2014 10:01:27 EST\n# Added inactive user test for Linux\n# 4.6.5 Mon 31 Mar 2014 10:49:09 EST\n# Added more CIS references for Linux\n# 4.6.6 Mon 31 Mar 2014 14:44:00 EST\n# Added noexec tmpfs test for Linux\n# 4.6.7 Mon 31 Mar 2014 21:05:17 EST\n# More CIS references for Linux\n# 4.6.8 Tue  1 Apr 2014 09:48:55 EST\n# Added interactive boot test\n# 4.6.9 Tue  1 Apr 2014 10:13:02 EST\n# Added kernel-pae test and CIS reference for SuSE Linux\n# 4.7.0 Tue  1 Apr 2014 13:45:14 EST\n# Added AppArmour and biosdevname test for SuSE Linux\n# 4.7.1 Tue  1 Apr 2014 14:49:16 EST\n# Added SuSEfirewall2 test\n# 4.7.2 Tue  1 Apr 2014 17:41:27 EST\n# Added shadow group member test for SuSE Linux\n# 4.7.3 Tue  1 Apr 2014 18:31:11 EST\n# Added gdm-autologin PAM check for Solaris 11\n# 4.7.4 Tue  1 Apr 2014 19:50:22 EST\n# Added EEEPROM password test for SPARC\n# 4.7.5 Wed  2 Apr 2014 12:31:55 EST\n# Fixed bugs (thanks to Mark Lane for testing)\n# 4.7.6 Wed  2 Apr 2014 15:13:36 EST\n# More bug fixes\n# 4.7.7 Thu  3 Apr 2014 15:05:09 EST\n# Updated AppArmour test for SuSE Linux\n# 4.7.8 Sat 12 Apr 2014 13:34:49 EST\n# Reference updates\n# 4.7.9 Sat 12 Apr 2014 22:20:43 EST\n# Reference updates\n# 4.8.0 Sun 13 Apr 2014 17:40:02 EST\n# Reference updates and bug fixes\n# 4.8.1 Sun 13 Apr 2014 21:21:48 EST\n# Removed duplicate auto logout module\n# 4.8.2 Fri 25 Apr 2014 12:16:09 EST\n# Fixed some bugs\n# 4.8.3 Sun 27 Apr 2014 16:07:34 EST\n# Fixed audit_system_auth_use_uid\n# 4.8.4: Tue  6 May 2014 12:42:52 EST\n# Minor fixes\n# 4.8.5: Thu  8 May 2014 09:14:24 EST\n# Fixed cron allow test for Solaris 11, Linux and FreeBSD\n# 4.8.6: Wed 14 May 2014 13:29:30 EST\n# Minor updates\n# 4.8.7: Thu 15 May 2014 12:07:13 EST\n# Deleted duplicate root group test\n# 4.8.8: Thu May 29 03:05:01 UTC 2014\n# Bug fixes and inital ESXi support (no tests)\n# 4.8.9: Thu 29 May 2014 16:28:43 EST\n# Improved scoring and added SNMP and Syslog tests for ESX\n# 4.9.0: Fri 30 May 2014 08:53:44 EST\n# Added NTP check for ESXi and made further improvements to scoring\n# 4.9.1: Fri 30 May 2014 11:37:44 EST\n# Added signed kernel module test for ESXi\n# 4.9.2: Fri 30 May 2014 15:23:01 EST\n# Added shell timeout tests for ESXi\n# 4.9.3: Fri 30 May 2014 15:40:43 EST\n# Added Syslog directory test for ESXi\n# 4.9.4: Fri 30 May 2014 16:48:29 EST\n# Added software update test for ESXi\n# 4.9.5: Fri 30 May 2014 18:48:39 EST\n# Added Managed Object Browser test for ESXi\n# 4.9.6: Fri 30 May 2014 20:44:33 EST\n# Added Dvfilter test for ESXi\n# 4.9.7: Sat 31 May 2014 06:54:25 EST\n# Added DCUI, SSH and ESXi Shell tests fo ESXi\n# 4.9.8: Sat 31 May 2014 08:15:56 EST\n# Added Lockdown check for ESXi\n# 4.9.9: Sat 31 May 2014 09:47:48 EST\n# Minor code cleanup\n# 5.0.0: Wed 11 Jun 2014 18:54:58 EST\n# Updated license\n# 5.0.1: Tue 28 Apr 2015 15:05:14 AEST\n# Removed call to audit_root_account as it was split into several audit_root_* subroutines\n# 5.0.2: Sat 14 Jan 2017 12:06:37 AEDT\n# Start adding support for Amazon Linux and added vfat to modprobe check\n# 5.0.3: Sat 14 Jan 2017 16:22:29 AEDT\n# Initial Amazon Linux support\n# 5.0.4: Sat 14 Jan 2017 17:22:34 AEDT\n# Fixed audit select function\n# 5.0.5: Sat 14 Jan 2017 19:34:40 AEDT\n# Fixed code to print module information\n# 5.0.6: Sat 14 Jan 2017 23:48:24 AEDT\n# Code cleanup\n# 5.0.7: Sun 15 Jan 2017 11:11:19 AEDT\n# Updates for Amazon Linux and Centos / RHEL 7\n# 5.0.8: Sun 15 Jan 2017 13:09:27 AEDT\n# More updates for Amazon Linux and Centos / RHEL 7\n# 5.0.9: Sun 15 Jan 2017 13:55:43 AEDT\n# More updates for Amazon Linux and Centos / RHEL 7\n# 5.1.0: Sun 15 Jan 2017 14:17:54 AEDT\n# More updated for Amazon Linux and Centos / RHEL 7\n# 5.1.1: Sun 15 Jan 2017 14:57:17 AEDT\n# Documentation cleanup\n# 5.1.2: Sun 15 Jan 2017 16:09:52 AEDT\n# More updates for Amazon Linux and Centos / RHEL 7\n# 5.1.3: Sun 15 Jan 2017 16:18:28 AEDT\n# Bug fixes\n# 5.1.4: Mon 16 Jan 2017 07:38:08 AEDT\n# Bug fixes\n# 5.1.5: Mon 16 Jan 2017 07:55:34 AEDT\n# Fix for Amazon Linux\n# 5.1.6: Mon 16 Jan 2017 08:16:55 AEDT\n# Bug fixes\n# 5.1.7: Mon 16 Jan 2017 09:18:43 AEDT\n# Cleaned up reporting\n# 5.1.8: Mon 16 Jan 2017 17:15:21 AEDT\n# Fixed code to use . rather than source on Ubuntu and Debian (sh is actually bash)\n# 5.1.9: Tue 17 Jan 2017 20:13:43 AEDT\n# Updated Linux package handling code\n# 5.2.0: Wed 18 Jan 2017 08:39:55 AEDT\n# Initial code for AWS Foundation Security audit\n# 5.2.1: Wed 18 Jan 2017 14:47:16 AEDT\n# Added AWS credentials check\n# 5.2.2: Wed 18 Jan 2017 15:49:35 AEDT\n# Added AWS credential rotation check\n# 5.2.3: Wed 18 Jan 2017 18:56:54 AEDT\n# Added AWS password policy check\n# 5.2.4: Wed 18 Jan 2017 20:33:11 AEDT\n# Added AWS root account MFA check\n# 5.2.5: Wed 18 Jan 2017 21:28:14 AEDT\n# Added AWS user policy check\n# 5.2.6: Thu 19 Jan 2017 07:34:48 AEDT\n# Added AWS support role check\n# 5.2.7: Thu 19 Jan 2017 09:05:08 AEDT\n# Added AWS access keys check\n# 5.2.8: Thu 19 Jan 2017 10:15:18 AEDT\n# Added AWS full administrative privileges check\n# 5.2.9: Thu 19 Jan 2017 10:58:16 AEDT\n# Added AWS CloudTrail MultiRegion check\n# 5.3.0: Thu 19 Jan 2017 11:14:20 AEDT\n# Added AWS CloudTrail LogFileValidation check\n# 5.3.1: Thu 19 Jan 2017 11:47:33 AEDT\n# Added AWS CloudTrail bucket permissions check\n# 5.3.2: Thu 19 Jan 2017 16:59:12 AEDT\n# Added AWS IAM Master / Manager account check\n# 5.3.3: Thu 19 Jan 2017 17:54:06 AEDT\n# Fixed various AWS bugs\n# 5.3.4: Thu 19 Jan 2017 21:40:00 AEDT\n# Added AWS CloudTrail bucket policy check\n# 5.3.5: Thu 19 Jan 2017 22:14:38 AEDT\n# Added AWS CloudTrail CloudWatch Logs integration check\n# 5.3.6: Thu 19 Jan 2017 23:02:54 AEDT\n# Added initial support for AWS Config check\n# 5.3.7: Thu 19 Jan 2017 23:13:12 AEDT\n# Added AWS CloudTrail S3 Bucket logging check\n# 5.3.8: Thu 19 Jan 2017 23:24:30 AEDT\n# Added AWS CloudTrail KMS Key check\n# 5.3.9: Fri 20 Jan 2017 08:24:56 AEDT\n# Added AWS Key check\n# 5.4.0: Fri 20 Jan 2017 10:03:02 AEDT\n# Added AWS VPC peering check\n# 5.4.1: Fri 20 Jan 2017 13:19:36 AEDT\n# Added Inbound / Outbond check for AWS Security Groups\n# 5.4.2: Fri 20 Jan 2017 14:33:57 AEDT\n# Added AWS VPC flow log check\n# 5.4.3: Fri 20 Jan 2017 16:13:34 AEDT\n# Added AWS Security Group check for open SSH / RDP ports\n# 5.4.4: Fri 20 Jan 2017 17:28:52 AEDT\n# Added initial AWS SNS checks\n# 5.4.5: Fri 20 Jan 2017 19:38:09 AEDT\n# Added initial AWS monitoring checks\n# 5.4.6: Fri 20 Jan 2017 20:14:43 AEDT\n# Added AWS alarm and subscriber checks\n# 5.4.7: Fri 20 Jan 2017 20:41:44 AEDT\n# Added AWS IAM alarm and subscriber checks\n# 5.4.8: Fri 20 Jan 2017 22:14:27 AEDT\n# Added AWS CloudTrail, Console, Key, S3, Config, NACL, Security Group, Gateway, Route and VPC alarm and subscriber checks\n# 5.4.9: Sat 21 Jan 2017 08:41:04 AEDT\n# Added fix information for AWS Access Keys\n# 5.5.0: Tue 24 Jan 2017 05:20:07 AEDT\n# Cleaned up AWS CloudTrail checks\n# 5.5.1: Tue 24 Jan 2017 16:22:48 AEDT\n# Added some fix information for VPC checks\n# 5.5.2: Tue 24 Jan 2017 16:47:11 AEDT\n# Added some fix information for SNS check\n# 5.5.3: Tue 24 Jan 2017 17:15:33 AEDT\n# Updated AWS CloudTrail Key fix information\n# 5.5.4: Tue 24 Jan 2017 17:26:25 AEDT\n# Added some fix information for S3 bucket logging\n# 5.5.5: Tue 24 Jan 2017 17:29:39 AEDT\n# Added some fix information for AWS Config\n# 5.5.6: Tue 24 Jan 2017 17:38:19 AEDT\n# Added some fix information for CloudTrail bucket permissions\n# 5.5.7: Tue 24 Jan 2017 19:58:17 AEDT\n# Added initial ability to set AWS region on command line\n# 5.5.8: Tue 24 Jan 2017 21:09:08 AEDT\n# Added additional support for setting AWS region\n# 5.5.9: Tue 24 Jan 2017 21:25:13 AEDT\n# Added initial support for AWS recommendations\n# 5.6.0: Tue 24 Jan 2017 22:35:11 AEDT\n# Added AWS IAM SSH Public Keys check\n# 5.6.1: Tue 24 Jan 2017 22:45:17 AEDT\n# Added AWS IAM empty group check\n# 5.6.2: Wed 25 Jan 2017 06:27:00 AEDT\n# Added check for expired AWS certificates\n# 5.6.3: Wed 25 Jan 2017 06:40:16 AEDT\n# Added check for inactive AWS IAM accounts\n# 5.6.4: Wed 25 Jan 2017 07:19:13 AEDT\n# Added check for AWS Route53 Domain renewals\n# 5.6.5: Wed 25 Jan 2017 07:31:24 AEDT\n# Added check for AWS Route53 Domain expiration\n# 5.6.6: Wed 25 Jan 2017 08:32:35 AEDT\n# Added check for AWS Route53 Zone SPF records\n# 5.6.7: Wed 25 Jan 2017 08:40:14 AEDT\n# Added check for AWS Route53 Domain Transfer Lock\n# 5.6.8: Wed 25 Jan 2017 12:52:00 AEDT\n# Added check for AWS instance image ID owner\n# 5.6.9: Wed 25 Jan 2017 17:47:28 AEDT\n# Added check for number of AWS EIPs consumer\n# 5.7.0: Wed 25 Jan 2017 18:21:39 AEDT\n# Added check for AWS instances using the default security group\n# 5.7.1: Wed 25 Jan 2017 18:46:14 AEDT\n# Added check for AWS EC2-Classic instances\n# 5.7.2: Wed 25 Jan 2017 19:34:59 AEDT\n# Added check against recommended Instance name\n# 5.7.3: Wed 25 Jan 2017 20:49:54 AEDT\n# Added check for AWS instance termination protection\n# 5.7.4: Wed 25 Jan 2017 21:20:52 AEDT\n# Added check to see if instances have IAM profiles\n# 5.7.5: Thu 26 Jan 2017 04:41:19 AEDT\n# Added check for publicly shared AWS AMIs\n# 5.7.6: Thu 26 Jan 2017 05:42:37 AEDT\n# Added check against recommended Security Group name\n# 5.7.7: Thu 26 Jan 2017 09:09:47 AEDT\n# Split out AWS VPC and SG checks\n# 5.7.8: Thu 26 Jan 2017 09:17:26 AEDT\n# Added check for AWS SGs with open CIFS ports\n# 5.7.9: Thu 26 Jan 2017 09:22:07 AEDT\n# Added check for AWS SGs with open DNS ports\n# 5.8.0: Thu 26 Jan 2017 09:51:13 AEDT\n# Added check for AWS SGs with open FTP ports\n# 5.8.1: Thu 26 Jan 2017 10:03:33 AEDT\n# Added check for AWS SGs with various open ports\n# 5.8.2: Thu 26 Jan 2017 11:00:34 AEDT\n# Added check for AWS SGs with open MongoDB ports\n# 5.8.3: Thu 26 Jan 2017 11:09:27 AEDT\n# Added check for AWS SGs with open RPC ports\n# 5.8.4: Thu 26 Jan 2017 11:48:10 AEDT\n# Added check for AWS SGs with open ICMP\n# 5.8.5: Thu 26 Jan 2017 11:51:56 AEDT\n# Added check for AWS SGs with open SMTP\n# 5.8.6: Thu 26 Jan 2017 11:55:15 AEDT\n# Added check for AWS SGs with open Telnet\n# 5.8.7: Thu 26 Jan 2017 12:20:11 AEDT\n# Added check for AWS users with attached policies\n# 5.8.8: Thu 26 Jan 2017 14:02:54 AEDT\n# Added check for AWS ES domains being publicly accessible\n# 5.8.9: Thu 26 Jan 2017 14:27:20 AEDT\n# Added check for AWS ES domains having IP access policy\n# 5.9.0: Thu 26 Jan 2017 14:43:32 AEDT\n# Added check for AWS ES domains having dedicated master nodes\n# 5.9.1: Thu 26 Jan 2017 14:51:13 AEDT\n# Added check for AWS ES domains using General Purpose SSD to be cost effective\n# 5.9.2: Thu 26 Jan 2017 15:25:04 AEDT\n# Added check for AWS ES domains being cross zone aware\n# 5.9.3: Thu 26 Jan 2017 16:03:54 AEDT\n# Added more tag checks for AWS EC2 instances\n# 5.9.4: Thu 26 Jan 2017 20:54:23 AEDT\n# Added check for empty DynamoDB tables to be cost effective\n# 5.9.5: Thu 26 Jan 2017 21:19:06 AEDT\n# Added check for AWS ELB logging being enabled\n# 5.9.6: Thu 26 Jan 2017 22:54:21 AEDT\n# Added check for AWS ELB connection draining being enabled\n# 5.9.7: Thu 26 Jan 2017 23:08:23 AEDT\n# Added check for AWS ELB cross zone balancing being enabled\n# 5.9.8: Fri 27 Jan 2017 07:07:37 AEDT\n# Added check for AWS ELB using deprecated ciphers\n# 5.9.9: Fri 27 Jan 2017 07:38:05 AEDT\n# Added check for AWS ELB using deprecated protocols\n# 6.0.0: Fri 27 Jan 2017 08:20:44 AEDT\n# Added check for AWS ELB using HTTP rather than HTTPS\n# 6.0.1: Fri 27 Jan 2017 08:32:32 AEDT\n# Added check for AWS ELB having at least 2 instances\n# 6.0.2: Fri 27 Jan 2017 08:48:57 AEDT\n# Added check for AWS ELB SGs being open on port 80\n# 6.0.3: Fri 27 Jan 2017 09:22:00 AEDT\n# Added check for out of service AWS ELB instances\n# 6.0.4: Fri 27 Jan 2017 09:33:32 AEDT\n# Added check for unencrypted AWS EC2 volumes\n# 6.0.5: Fri 27 Jan 2017 13:19:21 AEDT\n# Added check for AWS EC2 volume names\n# 6.0.6: Fri 27 Jan 2017 18:04:39 AEDT\n# Added check for AWS EC2 snapshots older than 30 days\n# 6.0.7: Fri 27 Jan 2017 19:13:08 AEDT\n# Added check for AWC EC2 unattached volumes to be cost effective\n# 6.0.8: Fri 27 Jan 2017 19:37:26 AEDT\n# Added check for AWC VPC exposed endpoints\n# 6.0.9: Fri 27 Jan 2017 21:42:09 AEDT\n# Added check for AWS VPC names\n# 6.1.0: Sat 28 Jan 2017 08:16:46 AEDT\n# Added check for AWS VPC / VPN redundancy\n# 6.1.1: Sat 28 Jan 2017 09:00:59 AEDT\n# Added check for AWS S3 bucket grants\n# 6.1.2: Sat 28 Jan 2017 09:05:50 AEDT\n# Added check for AWS S3 bucket logging\n# 6.1.3: Sat 28 Jan 2017 09:13:45 AEDT\n# Added check for AWS S3 bucket versioning\n# 6.1.4: Sat 28 Jan 2017 14:06:32 AEDT\n# Added check for AWS SES and DKIM\n# 6.1.5: Sat 28 Jan 2017 14:45:31 AEDT\n# Added check for AWS RDS auto minor version upgrade\n# 6.1.6: Sat 28 Jan 2017 15:15:43 AEDT\n# Added check for AWS RDS automated backups\n# 6.1.7: Sat 28 Jan 2017 16:51:40 AEDT\n# Added check for AWS RDS encryption\n# 6.1.8: Sat 28 Jan 2017 17:06:52 AEDT\n# Added check for AWS RDS having Multi-AZ enabled\n# 6.1.9: Sat 28 Jan 2017 19:32:15 AEDT\n# Added check for AWS RDS Security Groups\n# 6.2.0: Sat 28 Jan 2017 20:39:56 AEDT\n# Added check for AWS RDS using KMS key\n# 6.2.1: Sat 28 Jan 2017 21:08:09 AEDT\n# Added check for AWS RDS using General Purpose SSD to be cost effective\n# 6.2.2: Sat 28 Jan 2017 21:26:07 AEDT\n# Added check for AWS RDS instances being on a public facing subnet\n# 6.2.3: Sat 28 Jan 2017 21:45:29 AEDT\n# Added check for AWS RDS instances using default master username\n# 6.2.4: Sun 29 Jan 2017 11:40:24 AEDT\n# Added check for AWS RDS registered instances expiring\n# 6.2.5: Sun 29 Jan 2017 11:54:14 AEDT\n# Added check for AWS RDS backup retention period\n# 6.2.6: Sun 29 Jan 2017 12:44:23 AEDT\n# Added check for AWS EC2 EBS volumes having KMS keys\n# 6.2.7: Sun 29 Jan 2017 15:31:20 AEDT\n# Added check for AWS EC2 EBS volume snapshots being taken\n# 6.2.8: Sun 29 Jan 2017 17:16:24 AEDT\n# Added check for AWS CloudTrail recording global events\n# 6.2.9: Sun 29 Jan 2017 19:03:52 AEDT\n# Added check for AWS inactive KMS keys\n# 6.3.0: Sun 29 Jan 2017 19:03:52 AEDT\n# Added check for AWS SNS topic being publicly accessible\n# 6.3.1: Sun 29 Jan 2017 20:02:57 AEDT\n# Added check for AWS CloudFormation stacks using SNS\n# 6.3.2: Sun 29 Jan 2017 20:30:55 AEDT\n# Added check for AWS CloudFormation stacks having policies\n# 6.3.3: Sun 29 Jan 2017 20:49:28 AEDT\n# Added check for AWS ElastiCache having HA enabled\n# 6.3.4: Sun 29 Jan 2017 21:06:57 AEDT\n# Added check for AWS ElastiCache reserved instances expiring\n# 6.3.5: Sun 29 Jan 2017 21:23:07 AEDT\n# Added check for AWS Cloudfront WAF integration being enabled\n# 6.3.6: Sun 29 Jan 2017 21:31:31 AEDT\n# Added check for AWS Cloudfront logging being enabled\n# 6.3.7: Sun 29 Jan 2017 21:38:47 AEDT\n# Added check for AWS Cloudfront using deprecate SSL version\n# 6.3.8: Sun 29 Jan 2017 21:43:31 AEDT\n# Added check for AWS Cloudfront using HTTP only\n# 6.3.9: Sun 29 Jan 2017 22:08:20 AEDT\n# Added check for AWS CloudWatch alarm for EC2 instance changes\n# 6.4.0: Sun 29 Jan 2017 22:22:11 AEDT\n# Added check for AWS CloudWatch alarm for EC2 instance size changes\n# 6.4.1: Mon 30 Jan 2017 08:13:20 AEDT\n# Added check for AWS Redshift upgrades being enabled\n# 6.4.2: Mon 30 Jan 2017 08:36:14 AEDT\n# Added check for AWS Redshift logging being enabled\n# 6.4.3: Mon 30 Jan 2017 08:44:03 AEDT\n# Added check for AWS Redshift encryption being enabled\n# 6.4.4: Mon 30 Jan 2017 08:50:04 AEDT\n# Added check for AWS Redshift using KMS keys\n# 6.4.5: Mon 30 Jan 2017 09:12:42 AEDT\n# Added check for AWS Redshift using EC2-VPC domains rather than EC2-Classic\n# 6.4.6: Mon 30 Jan 2017 09:34:38 AEDT\n# Added check for AWS Redshift paramter groups requiring SSL\n# 6.4.7: Mon 30 Jan 2017 09:47:58 AEDT\n# Added check for AWS Redshift being publicly available\n# 6.4.8: Mon 30 Jan 2017 10:11:21 AEDT\n# Added check for AWS Redshift reserved instances about to expire\n# 6.4.9: Tue 31 Jan 2017 14:55:55 AEDT\n# Added check for AWS Inspector being used\n# 6.5.0: Tue 31 Jan 2017 16:39:08 AEDT\n# Added check for AWS Inspector assessment recommendation (CVEs)\n# 6.5.1: Tue  7 Feb 2017 14:34:39 AEDT\n# Added initial support for Docker\n# 6.5.2: Tue  7 Feb 2017 16:59:27 AEDT\n# Added additional Docker support\n# 6.5.3: Tue  7 Feb 2017 17:37:13 AEDT\n# Added Docker network bridge test\n# 6.5.4: Wed  8 Feb 2017 07:43:30 AEDT\n# Added more Docker tests and updated SSH TCP forwarding test\n# 6.5.5: Wed  8 Feb 2017 08:09:14 AEDT\n# Fixed Docker daemon test\n# 6.5.6: Wed  8 Feb 2017 08:17:15 AEDT\n# Added Docker user namespace support test\n# 6.5.7: Wed  8 Feb 2017 08:32:00 AEDT\n# Added Docker daemon storage option and authorisation plugin checks\n# 6.5.8: Wed  8 Feb 2017 08:37:12 AEDT\n# Added additional Docker logging tests\n# 6.5.9: Wed  8 Feb 2017 08:46:12 AEDT\n# Added Docker legacy registry check\n# 6.6.0: Wed  8 Feb 2017 08:48:46 AEDT\n# Added Docker liver restore check\n# 6.6.1: Wed  8 Feb 2017 08:54:36 AEDT\n# Added Docker userland proxy test\n# 6.6.2: Wed  8 Feb 2017 08:57:18 AEDT\n# Added Docker encrypted network traffic check\n# 6.6.3: Wed  8 Feb 2017 08:59:50 AEDT\n# Added Docker seccomp profile test\n# 6.6.4: Wed Feb  8 09:23:05 AEDT 2017\n# Added Docker swarm unlock key test\n# 6.6.5: Wed  8 Feb 2017 10:16:35 AEDT\n# Added Docker file permission tests\n# 6.6.6: Wed  8 Feb 2017 10:43:45 AEDT\n# Added Docker container user test\n# 6.6.7: Wed  8 Feb 2017 11:53:36 AEDT\n# Added Docker Healthcheck test\n# 6.6.8: Wed  8 Feb 2017 12:33:33 AEDT\n# Added Docker AppArmor test\n# 6.6.9: Wed  8 Feb 2017 12:46:13 AEDT\n# Added Docker SELinux test\n# 6.7.0: Wed  8 Feb 2017 14:41:52 AEDT\n# Added Docker capabilities test\n# 6.7.1: Wed  8 Feb 2017 14:48:15 AEDT\n# Added Docker privileged container check\n# 6.7.2: Wed  8 Feb 2017 15:11:17 AEDT\n# Added Docker host network namespace check\n# 6.7.3: Wed  8 Feb 2017 15:26:33 AEDT\n# Added Docker memory usage limit test\n# 6.7.4: Wed  8 Feb 2017 17:17:58 AEDT\n# Initial Docker code cleanup\n# 6.7.5: Wed  8 Feb 2017 17:50:16 AEDT\n# Additional Docker code cleanup\n# 6.7.6: Wed  8 Feb 2017 17:57:59 AEDT\n# Added Docker Memory and CpuShares tests\n# 6.7.7: Wed  8 Feb 2017 19:04:24 AEDT\n# Added Docker Ports check and cleaned up code\n# 6.7.8: Wed  8 Feb 2017 19:24:39 AEDT\n# More Docker fixes\n# 6.7.9: Wed  8 Feb 2017 19:38:44 AEDT\n# Added Docker PidMode check\n# 6.8.0: Wed  8 Feb 2017 19:41:46 AEDT\n# Added Docker IpcMode check\n# 6.8.1: Wed  8 Feb 2017 19:57:04 AEDT\n# Added Docker Devices check\n# 6.8.2: Wed  8 Feb 2017 20:02:58 AEDT\n# Added Docker Ulimits check\n# 6.8.3: Wed  8 Feb 2017 20:15:10 AEDT\n# Added Docker mount propagation check\n# 6.8.4: Wed  8 Feb 2017 20:20:25 AEDT\n# Added Docker UTSMode check\n# 6.8.5: Wed  8 Feb 2017 21:58:01 AEDT\n# Added Docker exec commands with privileged option check\n# 6.8.6: Wed  8 Feb 2017 22:45:04 AEDT\n# Cleaned up Docker tests\n# 6.8.7: Wed  8 Feb 2017 22:56:11 AEDT\n# Added Docker exec commands with user option check\n# 6.8.8: Wed  8 Feb 2017 22:59:43 AEDT\n# Added Docker CgroupParent test\n# 6.8.9: Wed  8 Feb 2017 23:09:53 AEDT\n# Added Docker SecurityOpt tests\n# 6.9.0: Wed  8 Feb 2017 23:28:37 AEDT\n# Added Docker Health test\n# 6.9.1: Wed  8 Feb 2017 23:45:46 AEDT\n# Added Docker default bridge test\n# 6.9.2: Wed  8 Feb 2017 23:49:04 AEDT\n# Added Docker UsernsMode test\n# 6.9.3: Wed  8 Feb 2017 23:59:47 AEDT\n# Added Docker socket mount test\n# 6.9.4: Thu  9 Feb 2017 00:18:07 AEDT\n# Added option to list Docker reports\n# 6.9.5: Thu  9 Feb 2017 00:36:30 AEDT\n# Updated GRUB test\n# 6.9.6: Thu Feb  9 06:53:33 AEDT 2017\n# Code cleanup and bug fixes\n# 6.9.7: Thu  9 Feb 2017 09:12:03 AEDT\n# Bug fixes and documenation updates\n# 6.9.8: Thu  9 Feb 2017 09:37:36 AEDT\n# Bug fixes and documenation updates\n# 6.9.9: Thu  9 Feb 2017 10:51:58 AEDT\n# Bug fixes and documenation updates\n# 7.0.0: Thu  9 Feb 2017 11:09:01 AEDT\n# Bug fixes and documenation updates\n# 7.0.1: Thu  9 Feb 2017 15:37:09 AEDT\n# Updated documentation\n# 7.0.2: Fri 10 Feb 2017 00:23:29 AEDT\n# Updates for OS X 10.12\n# 7.0.3: Fri 10 Feb 2017 08:25:51 AEDT\n# Bug fixes and documentation updates\n# 7.0.4: Fri 10 Feb 2017 11:52:39 AEDT\n# Code cleanup\n# 7.0.5: Fri 10 Feb 2017 12:28:13 AEDT\n# Added screen sharing test for OS X\n# 7.0.6: Fri 10 Feb 2017 12:50:59 AEDT\n# Added remote login check for OS X\n# 7.0.7: Fri 10 Feb 2017 13:44:56 AEDT\n# Added sleep check for OS X and updated documentation\n# 7.0.8: Fri 10 Feb 2017 14:05:20 AEDT\n# Code cleanup\n# 7.0.9: Sat 11 Feb 2017 07:39:17 AEDT\n# Code cleanup\n# 7.1.0: Sat 11 Feb 2017 09:52:05 AEDT\n# Updated SSH support to include sandbox for privilege separation\n# 7.1.1: Sat 11 Feb 2017 11:56:22 AEDT\n# Added Java test for OS X\n# 7.1.2: Sat 11 Feb 2017 12:21:17 AEDT\n# Added system log test for OS X\n# 7.1.3: Sat 11 Feb 2017 12:34:06 AEDT\n# Added addition system log tests for OS X and updated documentation\n# 7.1.4: Sat 11 Feb 2017 12:50:18 AEDT\n# Added addition system log tests for OS X and updated documentation\n# 7.1.5: Sat 11 Feb 2017 12:58:07 AEDT\n# Added wireless check for OS X\n# 7.1.6: Sat 11 Feb 2017 13:16:16 AEDT\n# Added NFS daemon check for OS X\n# 7.1.7: Sat 11 Feb 2017 15:44:55 AEDT\n# Added Application permission checks for OS X\n# 7.1.8: Sat 11 Feb 2017 16:33:48 AEDT\n# Updated OS X password policy test\n# 7.1.9: Sat 11 Feb 2017 17:18:07 AEDT\n# Updated OS X password policy test\n# 7.2.0: Sat 11 Feb 2017 17:39:07 AEDT\n# Updated OS X keychain check\n# 7.2.1: Sat 11 Feb 2017 17:50:45 AEDT\n# Updated OS X login policy test and documentation\n# 7.2.2: Sat 11 Feb 2017 18:18:10 AEDT\n# Added system preferences check for OS X\n# 7.2.3: Sat 11 Feb 2017 20:36:05 AEDT\n# Added System Integrity Protection test for OS X\n# 7.2.4: Sat 11 Feb 2017 21:39:02 AEDT\n# Updated documentation\n# 7.2.5: Sun Feb 12 13:26:29 AEDT 2017\n# Code cleanup\n# 7.2.6: Sat  9 Sep 2017 17:44:38 AEST\n# Cleaned up command line argument handling\n# 7.2.7: Wed 27 Dec 2017 07:55:29 AEDT\n# Fixed uname and stat on OS X\n# 7.2.8: Sat  9 Feb 2019 13:09:58 AEDT\n# Fixed a bug with chkconfig on Centos\n# 7.2.9: Sun 21 Apr 2019 11:19:00 AEST\n# Fixed Java version check and some other bugs\n# 7.3.0: Sun 21 Apr 2019 13:06:51 AEST\n# Added initial code for detecting virtual platform and fixed separate filesystems check\n# 7.3.1: Sun Apr 21 15:48:28 AEST 2019\n# Cleanup and bug fixes\n# 7.3.2: Sun 21 Apr 2019 16:25:36 AEST\n# Fixed bug with sulogin check\n# 7.3.3: Sun 21 Apr 2019 17:40:10 AEST\n# Fixed bug with file value check and check values starting in hyphens\n# 7.3.4: Sun 21 Apr 2019 18:16:35 AEST\n# Initial bug fix for X Windows System package group being installed \n# 7.3.5: Sun 21 Apr 2019 21:11:20 AEST\n# Added group package check\n# 7.3.6: Tue 23 Apr 2019 12:06:07 AEST\n# Fixed bug with module check\n# 7.3.7: Tue 23 Apr 2019 14:24:39 AEST\n# Made code more portable\n# 7.3.8: Tue 23 Apr 2019 15:14:52 AEST\n# More fixes\n# 7.3.9: Tue 23 Apr 2019 18:37:02 AEST\n# Added initial docker test matrix\n# 7.4.0: Tue 23 Apr 2019 19:16:20 AEST\n# More bug fixes\n# 7.4.1: Tue 23 Apr 2019 20:36:25 AEST\n# Improved handling for beta releases of Red Hat Linux\n# 7.4.2: Tue 23 Apr 2019 20:44:23 AEST\n# Added file check to securetty test\n# 7.4.3: Tue 23 Apr 2019 22:04:08 AEST\n# Initial Kubernetes support\n# 7.4.4: Wed 24 Apr 2019 07:24:28 AEST\n# Added support of hyphens in parameter names in file value checks\n# 7.4.5: Wed 24 Apr 2019 08:15:38 AEST\n# Added additional kubernetes checks\n# 7.4.6: Wed 24 Apr 2019 12:10:50 AEST\n# Added additional kubernetes checks\n# 7.4.7: Wed 24 Apr 2019 16:38:49 AEST\n# Minor cleanup\n# 7.4.8: Wed 24 Apr 2019 18:27:05 AEST\n# Updated check file value function\n# 7.4.9: Wed 24 Apr 2019 20:39:39 AEST\n# Added additional kubernetes checks\n# 7.5.0: Tue 11 Jun 2019 14:58:46 AEST\n# Execshield fix\n# 7.5.1: Tue 30 Jul 2019 21:54:54 AEST\n# Fixes for Debian\n# 7.5.2: Wed 31 Jul 2019 09:48:02 AEST\n# Additional fix for Debian unstable\n# 7.5.3: Wed 31 Jul 2019 20:36:53 AEST\n# Fixes for date on Linux\n# 7.5.4: Wed 22 Jan 2020 09:33:40 AEDT\n# Bug fixes and initial ansbile output\n# 7.5.5: Wed 22 Jan 2020 10:13:08 AEDT\n# Bug fixes\n# 7.5.6: Wed 22 Jan 2020 14:13:22 AEDT\n# Bug fixes and code cleanup\n# 7.5.7: Wed 22 Jan 2020 20:36:05 AEDT\n# Added more ansible stanzas\n# 7.5.8: Wed 22 Jan 2020 21:43:05 AEDT\n# Bug fixes and code cleanup\n# 7.5.9: Thu 23 Jan 2020 12:05:26 AEDT\n# Added more ansible stanzas\n# 7.6.0: Thu 23 Jan 2020 15:07:16 AEDT\n# Added more ansible stanzas\n# 7.6.1: Tue 18 Feb 2020 08:09:12 AEDT\n# Fixes and improvements as suggesting in issue 36\n# 7.6.2: Tue Feb 18 09:17:17 AEDT 2020\n# Fixes for RedHat/Centos 8.x using chrony by default as suggested in issue 35\n# 7.6.3: Sun  3 May 2020 08:48:13 AEST\n# Fixed bug with filesystem partitions check\n# 7.6.4: Sun  3 May 2020 10:53:34 AEST\n# Formating cleanup\n# 7.6.5: Sun 03 May 2020 12:19:19 AEST\n# Added in function to check_file_value to cater for multiple parameters in a line\n# 7.6.6: Sun 03 May 2020 13:13:14 AEST\n# Ansible output tweaks\n# 7.6.7: Sun 03 May 2020 14:34:48 AEST\n# More ansible output tweaks\n# 7.6.8: Mon 04 May 2020 12:01:58 AEST\n# More ansible output tweaks\n# 7.6.9: Mon 18 May 2020 19:25:17 AEST\n# More Apache support\n# 7.7.0: Wed 16 Sep 2020 09:08:19 AEST\n# Fix for filesystem searches on Linux\n# 7.7.1: Wed 16 Sep 2020 21:54:39 AEST\n# Removed elfsign\n# 7.7.2: Fri 18 Sep 2020 22:58:52 AEST\n# Fixed duplicate options\n# 7.7.3: Sat 19 Sep 2020 21:53:54 AEST\n# Fix big with AIX Retry Limit code\n# 7.7.4: Sun 20 Sep 2020 17:54:08 AEST\n# Fixed AWS password policy module\n# 7.7.5: Thu 22 Apr 2021 15:15:54 AEST\n# Cleaned up linux service check code as per issue #37\n# 7.7.6: Thu 22 Apr 2021 16:32:24 AEST\n# Added code to deal with issue #61\n# 7.7.7: Mon 31 Jan 2022 15:56:28 AEDT\n# Updated security banner based on suggestion from Mark Lane so it can be grepped out easier\n# 7.7.8: Fri 23 Sep 2022 12:19:00 AEST\n# Updated check for tally2 PAM module which has been replaced with faillock PAM module in Ubuntu 22.04\n# 7.7.9: Fri 23 Sep 2022 17:00:49 AEST\n# Added check for apport service on Ubuntu 22.04\n# 7.8.0: Fri 23 Sep 2022 17:53:12 AEST\n# Fixed AppArmor check for Ubuntu\n# 7.8.1: Sat 24 Sep 2022 19:10:14 AEST\n# Added grub check to Apparmor check\n# 7.8.2: Sun 25 Sep 2022 08:26:46 AEST\n# Added grub config/menu file check to Apparmor test\n# 7.8.3: Sun 25 Sep 2022 15:39:50 AEST\n# Added gnome defaults check for GDM3\n# 7.8.4: Sun 25 Sep 2022 17:05:31 AEST\n# Added initial code for gsettings function\n# 7.8.5: Sun 25 Sep 2022 17:11:38 AEST\n# Fixed bug with apparmor module\n# 7.8.6: Sun 25 Sep 2022 18:42:04 AEST\n# Added GDM lock check for Linux\n# 7.8.7: Sun 25 Sep 2022 21:17:32 AEST\n# Updated GDM lock check for Linux\n# 7.8.8: Mon 26 Sep 2022 13:38:37 AEST\n# Updated GDM lock check for Linux\n# 7.8.9: Mon 26 Sep 2022 14:39:14 AEST\n# Added Gnome automount check\n# 7.9.0: Mon 26 Sep 2022 14:53:17 AEST\n# Added Gnome autorun check\n# 7.9.1: Mon 26 Sep 2022 15:10:43 AEST\n# Updated Gnome autorun check and added Gnome XDMCP check\n# 7.9.2: Mon 26 Sep 2022 16:52:46 AEST\n# Fixed prelink and aide checks\n# 7.9.3: Mon 26 Sep 2022 20:18:21 AEST\n# Added PAE/NX check\n# 7.9.4: Tue 27 Sep 2022 10:48:50 AEST\n# Added exim check\n# 7.9.5: Tue 27 Sep 2022 10:59:19 AEST\n# Added wireless check for Linux\n# 7.9.6: Tue 27 Sep 2022 11:26:50 AEST\n# Added some UFW checks for Ubuntu Linux\n# 7.9.7: Tue 27 Sep 2022 11:47:58 AEST\n# Added audispd-plugins package check\n# 7.9.8: Wed 28 Sep 2022 20:20:02 AEST\n# Added grub check for audit flag\n# 7.9.9: Thu 29 Sep 2022 04:42:26 AEST\n# Added audit log size check\n# 8.0.0: Thu 29 Sep 2022 04:56:18 AEST\n# Fixed audit max log file size\n# 8.0.1: Thu 29 Sep 2022 05:11:57 AEST\n# Added faillock to auditing\n# 8.0.2: Thu 29 Sep 2022 07:23:59 AEST\n# Added additional checks to system accounting/auditing\n# 8.0.3: Thu 29 Sep 2022 13:42:08 AEST\n# Added auditd log_group check\n# 8.0.4: Thu 29 Sep 2022 14:59:40 AEST\n# Added additional aide checks\n# 8.0.5: Thu 29 Sep 2022 16:17:53 AEST\n# Various updates to system logging and auditing checks\n# 8.0.6: Sat  1 Oct 2022 14:22:20 AEST\n# Added check for audit log of running command as another user\n# 8.0.7: Sat  1 Oct 2022 14:28:36 AEST\n# Added sudo check to audit\n# 8.0.8: Sat  1 Oct 2022 14:40:46 AEST\n# Added check for auditing chchon\n# 8.0.9: Fri 27 Oct 2023 12:53:20 AEDT\n# Moved home directory check to be a part of filesystem check option\n# 8.1.0: Fri Oct 27 18:55:59 AEDT 2023\n# Bug fixes for aide check\n# 8.1.1: Fri Oct 27 19:11:38 AEDT 2023\n# Bug fix for apparmor check\n# 8.1.2: Fri Oct 27 19:15:46 AEDT 2023\n# Bug fix for OS X defaults check\n# 8.1.3: Fri Oct 27 19:18:29 AEDT 2023\n# Bug fixes for auditd check\n# 8.1.4: Fri Oct 27 19:34:00 AEDT 2023\n# Bug fixes\n# 8.1.5: Sat Oct 28 08:25:51 AEDT 2023\n# Added check for iptables\n# 8.1.6: Sat Oct 28 08:31:48 AEDT 2023\n# Added check for nmcli\n# 8.1.7: Sat Oct 28 15:59:00 AEDT 2023\n# Added non root user check for reading shadow file\n# 8.1.8: Sat Oct 28 17:16:46 AEDT 2023\n# Added more checks for when not running as root\n# 8.1.9: Sat 28 Oct 2023 22:53:06 AEDT\n# Added addition shoftware update checks for macOS Sonoma\n# 8.2.0: Sat 28 Oct 2023 22:56:29 AEDT\n# Added keychain sync test for macOS Sonoma\n# 8.2.1: Sun 29 Oct 2023 07:23:04 AEDT\n# Fixed issue with OS version/release handling\n# 8.2.2: Sun 29 Oct 2023 12:47:48 AEDT\n# Documentation cleanup\n# 8.2.3: Sun 29 Oct 2023 13:18:06 AEDT\n# Added Air Drop check\n# 8.2.4: Sun 29 Oct 2023 13:48:36 AEDT\n# Added Air Play Receiver check\n# 8.2.5: Sun 29 Oct 2023 13:52:09 AEDT\n# Documentation fixes\n# 8.2.6: Sun 29 Oct 2023 14:17:47 AEDT\n# Updates for MacOS Sonoma\n# 8.2.7: Sun 29 Oct 2023 14:29:02 AEDT\n# Documentation updates\n# 8.2.8: Sun 29 Oct 2023 15:09:04 AEDT\n# Added MacOS check for asset caching\n# 8.2.9: Sun 29 Oct 2023 20:48:01 AEDT\n# Added MacOS check for media sharing\n# 8.3.0: Sun 29 Oct 2023 21:05:10 AEDT\n# Added additional MacOS check for bluetooth sharing\n# 8.3.1: Sun 29 Oct 2023 21:31:22 AEDT\n# Added MacOS Time Machine check\n# 8.3.2: Sun 29 Oct 2023 21:52:39 AEDT\n# Added additional MacOS wireless check\n# 8.3.3: Sun 29 Oct 2023 21:59:28 AEDT\n# Added additional MacOS wireless check\n# 8.3.4: Mon 30 Oct 2023 07:16:19 AEDT\n# Added MacOS Siri checks\n# 8.3.5: Mon 30 Oct 2023 14:46:34 AEDT\n# Added MacOS Location Services check\n# 8.3.6: Mon 30 Oct 2023 16:09:37 AEDT\n# Added MacOS defaults function to handle user defaults\n# 8.3.7: Mon 30 Oct 2023 16:11:53 AEDT\n# Bug fixes\n# 8.3.8: Mon 30 Oct 2023 16:19:09 AEDT\n# Added additional location services check\n# 8.3.9: Mon 30 Oct 2023 16:59:08 AEDT\n# Added MacOS Usage data check\n# 8.4.0: Mon 30 Oct 2023 17:14:08 AEDT\n# Added MacOS Ad Tracking check and updated test feedback\n# 8.4.1: Mon 30 Oct 2023 20:35:54 AEDT\n# Updated documentation\n# 8.4.2: Mon 30 Oct 2023 20:49:28 AEDT\n# Added MacOS Lockdown check\n# 8.4.3: Mon 30 Oct 2023 21:11:38 AEDT\n# Added MacOS screen corner setting check\n# 8.4.4: Mon 30 Oct 2023 21:51:34 AEDT\n# Added MacOS universal control check\n# 8.4.5: Tue 31 Oct 2023 10:31:22 AEDT\n# Added additional MocOS sleep checks for Intel\n# 8.4.6: Tue 31 Oct 2023 10:37:41 AEDT\n# Added additional MocOS sleep checks for Apple Silicon\n# 8.4.7: Tue 31 Oct 2023 10:45:58 AEDT\n# Added filevault check to sleep checks\n# 8.4.8: Tue 31 Oct 2023 10:53:13 AEDT\n# Added powernap check to sleep checks\n# 8.4.9: Tue 31 Oct 2023 13:12:55 AEDT\n# Added screen idle time check\n# 8.5.0: Tue 31 Oct 2023 13:35:22 AEDT\n# Updated documentation\n# 8.5.1: Tue 31 Oct 2023 14:12:38 AEDT\n# Added Touch ID checks\n# 8.5.2: Tue 31 Oct 2023 14:20:28 AEDT\n# Documentation updates\n# 8.5.3: Wed  1 Nov 2023 13:57:00 AEDT\n# Added MacOS check sysadminctl function\n# 8.5.4: Wed  1 Nov 2023 16:11:13 AEDT\n# Added MacOS SMB guest sharing check\n# 8.5.5: Wed  1 Nov 2023 19:56:46 AEDT\n# Updated documentation\n# 8.5.6: Wed  1 Nov 2023 20:43:59 AEDT\n# Updated kernel accounting test for MacOS Sonoma\n# 8.5.7: Wed  1 Nov 2023 21:10:07 AEDT\n# Updated firewall logging test for MacOS Sonoma\n# 8.5.8: Wed  1 Nov 2023 21:22:02 AEDT\n# Updated bonjour advertising test for MacOS Sonoma\n# 8.5.9: Wed  1 Nov 2023 22:10:04 AEDT\n# Updated web sharing and NFS check for MacOS Sonoma\n# 8.6.0: Thu  2 Nov 2023 07:15:56 AEDT\n# Updated documentation\n# 8.6.1: Thu  2 Nov 2023 08:35:25 AEDT\n# Added Apple Mobile File Integrity check\n# 8.6.2: Thu  2 Nov 2023 08:58:41 AEDT\n# Added MacOS Sealed System Volume check\n# 8.6.3: Thu  2 Nov 2023 09:31:41 AEDT\n# Added MacOS /System permissions check\n# 8.6.4: Thu  2 Nov 2023 09:58:55 AEDT\n# Updated MacOS password policy check for Sonoma\n# 8.6.5: Thu  2 Nov 2023 14:06:09 AEDT\n# Added APFS encrypted volume checks\n# 8.6.6: Thu  2 Nov 2023 14:16:30 AEDT\n# Added Core Storage encrypted volume checks\n# 8.6.7: Thu  2 Nov 2023 14:55:46 AEDT\n# Updated sudoers timeout check\n# 8.6.8: Thu  2 Nov 2023 15:19:35 AEDT\n# Added sudoers timestamp check\n# 8.6.9: Thu  2 Nov 2023 15:39:28 AEDT\n# Updated documentation\n# 8.7.0: Thu  2 Nov 2023 15:48:28 AEDT\n# Updated documentation\n# 8.7.1: Thu  2 Nov 2023 20:11:40 AEDT\n# Added Safari history limit check\n# 8.7.2: Thu  2 Nov 2023 20:23:00 AEDT\n# Added Safari Fradulent Website Warning check\n# 8.7.3: Thu  2 Nov 2023 21:12:05 AEDT\n# Added Safari Tracking check\n# 8.7.4: Thu  2 Nov 2023 21:19:57 AEDT\n# Added Hide IP Address in Safari check\n# 8.7.5: Thu  2 Nov 2023 21:47:18 AEDT\n# Added Safari Advertising Privacy Protection check\n# 8.7.6: Fri  3 Nov 2023 08:07:58 AEDT\n# Added Safari show full URL check\n# 8.7.7: Fri  3 Nov 2023 09:22:30 AEDT\n# Added Safari auto fill check\n# 8.7.8: Fri  3 Nov 2023 09:50:02 AEDT\n# Added Safari allow popups check\n# 8.7.9: Fri  3 Nov 2023 10:09:51 AEDT\n# Added Safari Javascript check\n# 8.8.0: Fri  3 Nov 2023 10:14:10 AEDT\n# Added Safari status bar check\n# 8.8.1: Fri  3 Nov 2023 11:45:26 AEDT\n# Added MacOS Administrative login to another session check\n# 8.8.2: Fri  3 Nov 2023 19:38:55 AEDT\n# Code cleanup for MacOS defaults function\n# 8.8.3: Fri  3 Nov 2023 22:00:36 AEDT\n# Improved MacOS version handling\n# 8.8.4: Sat  4 Nov 2023 15:00:34 AEDT\n# Added check for gsettings when running gnome checks\n# 8.8.5: Sat  4 Nov 2023 16:31:08 AEDT\n# Improved tcpwrappers check\n# 8.8.6: Sat  4 Nov 2023 16:50:01 AEDT\n# Improved verbose output\n# 8.8.7: Sun 12 Nov 2023 20:41:54 AEDT\n# Fixed PAM based account lockout issue\n# 8.8.8: Sun 12 Nov 2023 20:57:03 AEDT\n# More fixes for PAM checks\n# 8.8.9: Sun  9 Jun 2024 15:02:54 AEST\n# Fixed check_file_perms.sh find depth\n# 8.9.0: Fri Jun 14 04:51:06 PM AEST 2024\n# Fixed PAE check\n# 8.9.1: Mon Jun 17 02:11:39 PM AEST 2024\n# Improved wireless test\n# 8.9.2: Mon Jun 17 02:19:52 PM AEST 2024\n# Updated motd secure message check\n# 8.9.3: Mon Jun 17 02:39:20 PM AEST 2024\n# Updated ssh config check\n# 8.9.4: Mon Jun 17 04:26:30 PM AEST 2024\n# Fixes for auditd checks\n# 8.9.5: Mon Jun 17 04:52:05 PM AEST 2024\n# Improved syslog check\n# 8.9.6: Tue Jun 18 18:23:09 AEST 2024\n# Fixed code to print module info\n# 8.9.7: Tue Jun 18 18:52:41 AEST 2024\n# Updated command line handling\n# 8.9.8: Tue 18 Jun 2024 21:30:13 AEST\n# Updated defaults\n# 8.9.9: Tue Jun 18 11:41:53 PM AEST 2024\n# Improved systemctl check\n# 9.0.0: Wed Jun 19 04:35:29 PM AEST 2024\n# Improvements to reporting output\n# 9.0.1: Wed Jun 19 08:24:22 PM AEST 2024\n# Improvements to reporting output\n# 9.0.2: Wed Jun 19 09:30:20 PM AEST 2024\n# Improvements to reporting output\n# 9.0.3: Fri 28 Jun 2024 14:28:00 AEST\n# Major cleanup of code underway\n# 9.0.4: Fri Jun 28 03:49:10 PM AEST 2024\n# Fixed bug with old users check\n# 9.0.5 Fri Jun 28 04:37:05 PM AEST 2024\n# Fixed bug with daemon unmask check\n# 9.0.6: Fri Jun 28 04:46:27 PM AEST 2024\n# Improved select function check\n# 9.0.7: Fri 28 Jun 2024 17:09:33 AEST\n# Bug fixes\n# 9.0.8: Fri Jul  5 10:27:59 AM AEST 2024\n# Formatting and bug fixes\n# 9.0.9: Fri Jul  5 01:41:18 PM AEST 2024\n# Improved avahi conf check\n# 9.1.0: Fri Jul  5 03:57:46 PM AEST 2024\n# Output format improvements\n# 9.1.1: Fri Jul  5 04:03:52 PM AEST 2024\n# Fixed bug with systemctl command\n# 9.1.2: Fri Jul  5 07:36:42 PM AEST 2024\n# Added directory check to file check \n# 9.1.3: Fri Jul  5 08:59:48 PM AEST 2024\n# Added directory check to file append\n# 9.1.4: Sat Jul  6 09:48:27 AM AEST 2024\n# Initial clean up of defaults\n# 9.1.5: Sat Jul  6 11:09:59 AM AEST 2024\n# Updated documentation\n# 9.1.6: Sat Jul  6 11:18:47 AM AEST 2024\n# Cleaned up some commands\n# 9.1.7: Sat Jul  6 11:47:47 AM AEST 2024\n# Fixed temp_file assignment\n# 9.1.8: Sat Jul  6 14:10:53 AEST 2024\n# Disable results output when running in restore mode\n# 9.1.9: Sat Jul  6 14:56:17 AEST 2024\n# Added file checks for deleting some files\n# 9.2.0: Sat Jul  6 15:07:51 AEST 2024\n# Bug fixes\n# 9.2.1: Sat Jul  6 08:35:44 PM AEST 2024\n# Fixed wheel group test\n# 9.2.2: Sat Jul  6 21:04:48 AEST 2024\n# Fixed find command in cron test\n# 9.2.3: Sat Jul  6 21:11:40 AEST 2024\n# Improved gnome automount test\n# 9.2.4: Sat Jul  6 21:20:59 AEST 2024\n# Improved gnome screen lock test\n# 9.2.5: Sat Jul  6 21:27:38 AEST 2024\n# Improved cron allow test\n# 9.2.6: Sat Jul  6 21:57:14 AEST 2024\n# Improved gsettings function\n# 9.2.7: Sun Jul  7 10:07:11 AM AEST 2024\n# Improved file backup function\n# 9.2.8: Sun Jul  7 10:12:53 AM AEST 2024\n# Made file warnings consistent when file doesn't exist\n# 9.2.9: Mon Jul  8 12:32:14 AEST 2024\n# Improved aide check\n# 9.3.0: Mon Jul  8 13:54:59 AEST 2024\n# Improved tcp_wrappers check\n# 9.3.1: Tue  9 Jul 2024 12:19:45 AEST\n# Initial clean up of options to allow other containers besides docker\n# 9.3.2: Tue Jul  9 14:47:38 AEST 2024\n# Bug fixes\n# 9.3.3: Tue Jul  9 21:23:27 AEST 2024\n# Cleaned up tests/list options, added some multipass support for testing and updated documentation\n# 9.3.4: Wed Jul 10 03:07:15 PM AEST 2024\n# Improved dialog\n# 9.3.5: Wed Jul 10 03:12:22 PM AEST 2024\n# Bug fixes\n# 9.3.6: Wed Jul 10 10:15:15 PM AEST 2024\n# Bug fixes and improvements\n# 9.3.7: Thu Jul 11 02:05:40 PM AEST 2024\n# Added strict and debug switches\n# 9.3.8: Thu Jul 11 05:07:08 PM AEST 2024\n# Fixed return code in check_systemctl_service\n# 9.3.9: Fri Jul 12 10:48:58 AM AEST 2024\n# Bug fixes and improvements\n# 9.4.0: Fri Jul 12 01:26:48 PM AEST 2024\n# Bug fixes\n# 9.4.1: Fri Jul 12 05:06:40 PM AEST 2024\n# Bug fixes\n# 9.4.2: Fri Jul 12 08:43:30 PM AEST 2024\n# Fixed iptables check\n# 9.4.3: Fri Jul 12 08:50:57 PM AEST 2024\n# Fixed apparmor check\n# 9.4.4: Fri Jul 12 09:00:09 PM AEST 2024\n# Fixed sendmail daemon check\n# 9.4.5: Fri Jul 12 09:09:28 PM AEST 2024\n# Fixed ssh root key check\n# 9.4.6: Fri Jul 12 09:43:08 PM AEST 2024\n# Fixed duplicate users check\n# 9.4.7: Sat Jul 13 09:09:54 AM AEST 2024\n# Fixed user dot files check\n# 9.4.8: Sat Jul 13 09:14:14 AM AEST 2024\n# Fixed password fields check\n# 9.4.9: Sat Jul 13 09:18:36 AM AEST 2024\n# Fixed reserved ID check\n# 9.5.0: Sat Jul 13 09:35:18 AM AEST 2024\n# Fixed daemon umask check\n# 9.5.1: Sat Jul 13 10:09:32 AM AEST 2024\n# Fixed wheel group check\n# 9.5.2: Sat Jul 13 10:14:43 AM AEST 2024\n# Added wheel group and password hashing switches\n# 9.5.3: Sat Jul 13 10:30:34 AM AEST 2024\n# Fixed file permissions check\n# 9.5.4: Sat Jul 13 10:38:11 AM AEST 2024\n# Fixed old users check\n# 9.5.5: Sat Jul 13 11:24:41 AM AEST 2024\n# Fixed cron check and added anacron switch\n# 9.5.6: Sat Jul 13 11:32:17 AM AEST 2024\n# Fixed shadow group check\n# 9.5.7: Sat Jul 13 11:39:27 AM AEST 2024\n# Fixed xlogin check\n# 9.5.8: Sat Jul 13 11:46:38 AM AEST 2024\n# Fixed gnome banner check\n# 9.5.9: Sat Jul 13 11:57:17 AM AEST 2024\n# Fixed krb5 check\n# 9.6.0: Sat Jul 13 12:03:35 PM AEST 2024\n# Fixed NIS entries check\n# 9.6.1: Sat Jul 13 12:13:35 PM AEST 2024\n# Fixed avahi daemon check\n# 9.6.2: Sat Jul 13 12:16:42 PM AEST 2024\n# Fixed mount setuid check\n# 9.6.3: Sat Jul 13 12:26:27 PM AEST 2024\n# Fixed NFS check\n# 9.6.4: Sat Jul 13 12:31:12 PM AEST 2024\n# Fixed filesystem mount check\n# 9.6.5: Sat Jul 13 12:48:49 PM AEST 2024\n# Fixed syslog server check\n# 9.6.6: Sat Jul 13 12:54:24 PM AEST 2024\n# Fixed SNMP test\n# 9.6.7: Sat Jul 13 01:03:46 PM AEST 2024\n# Fixed chrony check\n# 9.6.8: Sat Jul 13 01:07:45 PM AEST 2024\n# Fixed dhcp server test\n# 9.6.9: Sat Jul 13 01:10:26 PM AEST 2024\n# Fixed apport check\n# 9.7.0: Sat Jul 13 01:15:04 PM AEST 2024\n# Fixed SPARC hardware check\n# 9.7.1: Sat Jul 13 01:27:35 PM AEST 2024\n# Documentation updates\n# 9.7.2: Sat 13 Jul 2024 17:33:22 AEST\n# Fixed version detection on MacOS\n# 9.7.3: Sat 13 Jul 2024 17:37:35 AEST\n# Fixed dmidecode check\n# 9.7.4: Sat 13 Jul 2024 17:41:13 AEST\n# Fixed SSH sandbox check\n# 9.7.5: Sat 13 Jul 2024 17:43:01 AEST\n# Fixed password strength test\n# 9.7.6: Sat 13 Jul 2024 17:48:24 AES\n# Fixed kernel accounting check\n# 9.7.7: Sat 13 Jul 2024 17:57:16 AEST\n# Fixed ntp check\n# 9.7.8: Sat 13 Jul 2024 20:04:00 AEST\n# Fixes for MacOS\n# 9.7.9: Sat 13 Jul 2024 20:41:18 AEST\n# More fixes for MacOS\n# 9.8.0: Sat 13 Jul 2024 22:01:16 AEST\n# Fixes for MacOS defaults checks\n# 9.8.1: Sat 13 Jul 2024 22:05:46 AEST\n# Fixed file sharing check\n# 9.8.2: Sat 13 Jul 2024 22:10:29 AEST\n# Fixed firewall setting check\n# 9.8.3: Sat 13 Jul 2024 22:14:57 AEST\n# More firewall setting check fixes\n# 9.8.4: Sat 13 Jul 2024 22:24:09 AEST\n# Fixed pmset check\n# 9.8.5: Sat 13 Jul 2024 22:37:04 AEST\n# Improved MacOS defaults check\n# 9.8.6: Sat 13 Jul 2024 22:42:24 AEST\n# Fixed dscl check\n# 9.8.7: Sat 13 Jul 2024 22:50:22 AEST\n# Fixed remote management check\n# 9.8.8: Sat 13 Jul 2024 22:56:50 AEST\n# Fixed safe downloads check\n# 9.8.9: Sat 13 Jul 2024 23:06:29 AEST\n# Fixed keychain lock check\n# 9.9.0: Sat 13 Jul 2024 23:09:40 AEST\n# Fixed application permissions check\n# 9.9.1: Sat 13 Jul 2024 23:12:47 AEST\n# Fixed touch ID check\n# 9.9.2: Sat 13 Jul 2024 23:15:06 AEST\n# Fixed APFS check\n# 9.9.3: Sat 13 Jul 2024 23:17:18 AEST\n# Fixed safari history check\n# 9.9.4: Sat 13 Jul 2024 23:20:30 AEST\n# Fixed safari warning check\n# 9.9.5: Sat 13 Jul 2024 23:23:49 AEST\n# Updated documentation\n# 9.9.6: Sun 14 Jul 2024 10:45:51 AEST\n# Fixed multipass VM check\n# 9.9.7: Sun 14 Jul 2024 11:28:05 AEST\n# Added debug switch to multipass\n# 9.9.8: Sun 14 Jul 2024 11:39:07 AEST\n# Added select switch to select\n# 9.9.9: Sun 14 Jul 2024 12:03:00 AEST\n# Improved systemctl check\n# 10.0.0: Sun 14 Jul 2024 12:08:51 AEST\n# Removed may need to be run as root warning for help and version switches\n# 10.0.1: Sun 14 Jul 2024 12:21:36 AEST\n# Improved gsettings check\n# 10.0.2: Sun Jul 14 12:36:32 AEST 2024\n# More improvements to gsettings check\n# 10.0.3: Sun 14 Jul 2024 12:56:07 AEST\n# Removed check_rpm function\n# 10.0.4: Sun 14 Jul 2024 13:03:58 AEST\n# Improved select function/module handling\n# 10.0.5: Mon 15 Jul 2024 11:31:58 AEST\n# Updated output\n# 10.0.6: Mon Jul 22 14:59:00 AEST 2024\n# Bug fixes\n# 10.0.7: Mon Jul 22 15:06:52 AEST 2024\n# Fix for systemctl check\n# 10.0.8: Mon Jul 22 15:43:40 AEST 2024\n# Fix for old users check\n# 10.0.9: Fri 25 Apr 2025 13:55:04 AEST\n# Code cleanup\n# 10.1.0: Fri 25 Apr 2025 15:49:37 AEST\n# Updated help routine\n# 10.1.1: Sat 26 Apr 2025 10:54:56 AEST\n# More code cleanup\n# 10.1.2: Sat 26 Apr 2025 11:08:06 AEST\n# Updated switch processing\n# 10.1.3: Sat 26 Apr 2025 22:35:08 AEST\n# Fixes recommended by Shellcheck\n# 10.1.4: Sun 27 Apr 2025 11:35:45 AEST\n# Fixed keychain sync check\n# 10.1.5: Sun 27 Apr 2025 17:17:40 AEST\n# Documentation updates\n# 10.1.6: Sun 27 Apr 2025 18:53:29 AEST\n# Updated modprobe filesystem kernel modules check\n# 10.1.7: Sun Apr 27 07:58:25 PM AEST 2025\n# Updated filesystem checks\n# 10.1.8: Sun 27 Apr 2025 21:25:56 AEST\n# Updated AppArmor test\n# 10.1.9: Sun 27 Apr 2025 22:41:11 AEST\n# Updated documentation\n# 10.2.0: Sun 27 Apr 2025 23:10:52 AEST\n# Updated virtual memory test and added ptrace test\n# 10.2.1: Sun 27 Apr 2025 23:45:37 AEST\n# Updated documentation and gdm test\n# 10.2.2: Mon Apr 28 21:04:35 AEST 2025\n# Broke out functions from main script\n# 10.2.3: Tue Apr 29 09:28:23 AEST 2025\n# Updated audit tests and documentation\n# 10.2.4: Tue Apr 29 10:00:28 AEST 2025\n# Updated rsyslog log rotate test\n# 10.2.5: Tue Apr 29 13:07:05 AEST 2025\n# Updated journald test\n# 10.2.6: Tue Apr 29 13:27:54 AEST 2025\n# Added shell timeout check\n# 10.2.7: Tue Apr 29 15:16:39 AEST 2025\n# Updated shell check\n# 10.2.8: Tue Apr 29 15:20:43 AEST 2025\n# Updated documentation\n# 10.2.9: Tue Apr 29 18:19:12 AEST 2025\n# Added root access test\n# 10.3.0: Tue Apr 29 20:18:09 AEST 2025\n# Added non root UID 0 test\n# 10.3.1: Tue Apr 29 20:50:36 AEST 2025\n# Added non root GID 0 test\n# 10.3.2: Tue Apr 29 21:17:01 AEST 2025\n# Added password history test\n# 10.3.3: Tue Apr 29 22:10:06 AEST 2025\n# Added inactive password lock test\n# 10.3.4: Tue Apr 29 22:17:53 AEST 2025\n# Updated documentation\n# 10.3.5: Wed Apr 30 12:03:09 AEST 2025\n# Started adding addition pam checks\n# 10.3.6: Wed 30 Apr 2025 21:52:52 AEST\n# Cleaned up PAM tests and added authtok test\n# 10.3.7: Thu  1 May 2025 09:48:32 AEST\n# Updated documentation and password quality tests\n# 10.3.8: Thu  1 May 2025 11:19:34 AEST\n# Updated tests and documentation\n# 10.3.9: Thu  1 May 2025 12:00:56 AEST\n# Renamed chkconfig test to make it more generic and updated documentation\n# 10.4.0: Thu  1 May 2025 12:06:10 AEST\n# Updated java test\n# 10.4.1: Thu  1 May 2025 13:35:33 AEST\n# Updated tests and documentation and add ftp client package test\n# 10.4.2: Thu  1 May 2025 14:22:20 AEST\n# Updated tests and documentation\n# 10.4.3: Thu  1 May 2025 17:17:11 AEST\n# Updated tests and documentation\n# 10.4.4: Thu  1 May 2025 21:09:59 AEST\n# Updated password quality documentation and tests\n# 10.4.5: Thu  1 May 2025 22:20:53 AEST\n# Documentation and test updates\n# 10.4.6: Fri  2 May 2025 09:03:49 AEST\n# Added sudo authenticate test\n# 10.4.7: Fri  2 May 2025 09:22:59 AEST\n# Added sudo NOPASSWD test\n# 10.4.8: Fri  2 May 2025 10:42:57 AEST\n# Updated sudo tests\n# 10.4.9: Fri  2 May 2025 15:34:21 AEST\n# Updated SSH config tests\n# 10.5.0: Fri  2 May 2025 16:23:34 AEST\n# Added SSH permissions test\n# 10.5.1: Fri  2 May 2025 21:30:47 AEST\n# Formatting cleanup\n# 10.5.2: Sat  3 May 2025 15:57:37 AEST\n# More formatting cleanup\n# 10.5.3: Sat  3 May 2025 16:33:59 AEST\n# Moved shellcheck function to core\n# 10.5.4: Sat  3 May 2025 17:09:16 AEST\n# Shellcheck fixes\n# 10.5.5: Sun  4 May 2025 16:54:11 AEST\n# Added ansible output for some tests\n# 10.5.6: Mon  5 May 2025 10:37:12 AEST\n# Added file comment function and updated ansible in some tests\n# 10.5.7: Wed  7 May 2025 15:07:01 AEST\n# Updated touch ID test\n# 10.5.8: Wed  7 May 2025 15:41:38 AEST\n# Updated Solaris audit class check\n# 10.5.9: Thu  8 May 2025 10:50:22 AEST\n# Updated some ansible stanzas\n# 10.6.0: Fri  9 May 2025 15:49:24 AEST\n# Updated AppArmor test\n# 10.6.1: Fri  9 May 2025 15:51:10 AEST\n# Fixed dot files test\n# 10.6.2: Mon 12 May 2025 10:57:47 AEST\n# Updated lockdown and restore commands in functions\n# 10.6.3: Mon 12 May 2025 14:03:15 AEST\n# Updated lockdown and restore commands in some modules\n# 10.6.4: Mon 12 May 2025 14:30:16 AEST\n# Updated lockdown and restore commands in some modules\n# 10.6.5: Mon 12 May 2025 15:58:48 AEST\n# Updated lockdown and restore commands in some modules\n# 10.6.6: Thu 15 May 2025 18:10:29 AEST\n# Added sudo check to some tests\n# 10.6.7: Thu 15 May 2025 19:02:52 AEST\n# Cleaned up some variable names\n# 10.6.8: Thu 15 May 2025 20:42:06 AEST\n# Updated xlogin test and some other tests\n# 10.6.9: Thu 15 May 2025 22:23:07 AEST\n# Updated formating of some tests\n# 10.7.0: Sun 18 May 2025 15:52:53 AEST\n# Updated formating of some tests\n# 10.7.1: Mon May 19 00:26:10 AEST 2025\n# Added function to print module and function names\n# 10.7.2: Mon May 19 00:30:40 AEST 2025\n# Fixed typos\n# 10.7.3: Thu 29 May 2025 11:55:24 AEST\n# Improved print_audit_info routine\n# 10.7.4: Thu 29 May 2025 14:50:10 AEST\n# Added lockdown check\n# 10.7.5: Thu 29 May 2025 15:38:42 AEST\n# Added dryrun switch\n# 10.7.6: Thu 29 May 2025 15:47:11 AEST\n# Fixed lockdown check\n# 10.7.7: Thu 29 May 2025 16:32:48 AEST\n# Improved listing of backups\n# 10.7.8: Thu 29 May 2025 17:12:25 AEST\n# Added lockdown/restore counting\n# 10.7.9: Thu 29 May 2025 20:05:20 AEST\n# Output improvements\n# 10.8.0: Fri 30 May 2025 13:21:01 AEST\n# Sudo improvements\n# 10.8.1: Fri 30 May 2025 14:24:37 AEST\n# Improved restore function\n# 10.8.2: Fri 30 May 2025 14:30:04 AEST\n# More improvements\n# 10.8.3: Fri 30 May 2025 17:32:12 AEST\n# Improved report\n# 10.8.4: Fri 30 May 2025 19:42:47 AEST\n# Cleaned up some variable names\n# 10.8.5: Sat 31 May 2025 14:21:00 AEST\n# Fixed check_file_value routine logging\n# 10.8.6: Sat 31 May 2025 14:29:11 AEST\n# Stopped check_environment running multiple times\n# 10.8.7: Sat 31 May 2025 15:30:36 AEST\n# Improved check_file_value routine\n# 10.8.8: Sat May 31 15:38:14 AEST 2025\n# Fixed bug with module_name being recast\n# 10.8.9: Sat 31 May 2025 16:03:06 AEST\n# Fixes based on POSIX sh recommendations from shellcheck\n# 10.9.0: Sat 31 May 2025 16:09:06 AEST\n# More shellcheck recommendations\n# 10.9.1: Sat 31 May 2025 17:25:53 AEST\n# Updated documentation\n# 10.9.2: Thu Jan 15 11:57:32 AEDT 2026\n# Updated Ubuntu codenames\n# 10.9.3: Thu Jan 15 12:38:51 AEDT 2026\n# Fixed OS version check in aide check\n# 10.9.4: Thu Jan 15 14:16:46 AEDT 2026\n# Improved virtual check\n# 10.9.5: Thu Jan 15 14:22:12 AEDT 2026\n# Added output file and format options for future improvements\n# 10.9.6: Thu Jan 15 15:25:37 AEDT 2026\n# Added hostname and domainname to OS info\n# 10.9.7: Thu Jan 15 21:17:22 AEDT 2026\n# Added initial CSV output\n# 10.9.8: Thu Jan 15 21:26:27 AEDT 2026\n# Fixed typo\n# 10.9.9: Mon Jan 19 11:51:25 AEDT 2026\n# Added initial Azure stub\n# 11.0.0: Wed Jan 21 11:51:25 AEDT 2026\n# Added Azure Storage Accounts audit stub\n# 11.0.1: Wed Jan 21 15:52:58 AEDT 2026\n# Added Azure Storage Accounts Key Expiration check\n# 11.0.2: Thu Jan 22 14:47:19 AEDT 2026\n# Fixed Azure Storage Accounts Key Expiration check\n# 11.0.3: Thu Jan 22 17:10:30 AEDT 2026\n# Added Azure Storage Accounts Key Regeneration check\n# 11.0.4: Thu 22 Jan 2026 18:37:22 AEDT\n# Added command_message routine\n# 11.0.5: Thu 22 Jan 2026 20:44:42 AEDT\n# Added Private Endpoint check for Storage Accounts\n# 11.0.6: Thu 22 Jan 2026 21:29:00 AEDT\n# Added Public Network Access check for Storage Accounts\n# 11.0.7: Thu 22 Jan 2026 21:36:22 AEDT\n# Added fix commands for some Storage Accounts tests\n# 11.0.8: Thu 22 Jan 2026 21:41:33 AED\n# Added check to verify default network access rule for Storage Accounts\n# 11.0.9: Thu 22 Jan 2026 21:46:22 AEDT\n# Added generic check_azure_storage_account_value function\n# 11.1.0: Thu 22 Jan 2026 21:50:22 AEDT\n# Added check to verify Microsoft Entra authorization for Storage Accounts\n# 11.1.1: Thu 22 Jan 2026 21:51:33 AEDT\n# Improved check_azure_storage_account_value function\n# 11.1.2: Thu 22 Jan 2026 21:56:22 AEDT\n# Added check to verify Azure services on the trusted services list for Storage Accounts\n# 11.1.3: Thu 22 Jan 2026 22:06:22 AEDT\n# Added check to verify Secure transfer required for Storage Accounts\n# 11.1.4: Thu 22 Jan 2026 22:11:22 AEDT\n# Added check to verify Cross Tenant Replication for Storage Accounts\n# 11.1.5: Thu 22 Jan 2026 22:16:22 AEDT\n# Added check to verify Allow blob public access for Storage Accounts\n# 11.1.6: Thu 22 Jan 2026 22:21:22 AEDT\n# Added Minimum TLS version check for Storage Accounts\n# 11.1.7: Fri 23 Jan 2026 10:37:22 AEDT\n# Added check_azure_resource_manager_locks function\n# 11.1.8: Fri 23 Jan 2026 10:42:22 AEDT\n# Added Azure Resource Manager Delete locks check for Storage Accounts\n# 11.1.9: Fri 23 Jan 2026 10:46:22 AEDT\n# Added Azure Resource Manager ReadOnly locks check for Storage Accounts\n# 11.2.0: Fri 23 Jan 2026 11:12:39 AEDT\n# Added Azure Storage Accounts Redundancy check\n# 11.2.1: Fri 23 Jan 2026 11:51:22 AEDT\n# Bug fixes and improvements\n# 11.2.2: Fri 23 Jan 2026 12:06:22 AEDT\n# Added check_azure_storage_blob_value function\n# 11.2.3: Fri 23 Jan 2026 12:11:22 AEDT\n# Added check for Azure Storage Blob Soft Delete\n# 11.2.4: Fri 23 Jan 2026 12:16:22 AEDT\n# Added check for Azure Storage Blob Days Retained\n# 11.2.5: Fri 23 Jan 2026 14:12:30 AEDT\n# Added Azure auth mode\n# 11.2.6: Fri 23 Jan 2026 15:00:19 AEDT\n# Added check_azure_storage_container_value function\n# 11.2.7: Fri 23 Jan 2026 15:02:22 AEDT\n# Added check for Azure Storage Container Soft Delete\n# 11.2.8: Fri 23 Jan 2026 15:04:22 AEDT\n# Added check for Azure Storage Container Days Retained\n# 11.2.9: Fri 23 Jan 2026 15:06:22 AEDT\n# Added check for Azure Storage Container Versioning\n# 11.3.1: Fri 23 Jan 2026 20:06:22 AEDT\n# Added check of Azure File Shares \n# 11.3.2: Fri 23 Jan 2026 20:06:22 AEDT\n# Added check for Azure File Shares Soft Delete\n# 11.3.3: Fri 23 Jan 2026 20:06:22 AEDT\n# Added check for Azure File Shares Days Retained\n# 11.3.4: Fri 23 Jan 2026 20:06:22 AEDT\n# Added check for Azure File Shares SMB Protocol Version\n# 11.3.5: Fri 23 Jan 2026 20:06:22 AEDT\n# Added check for Azure File Shares SMB Channel Encryption\n# 11.3.6: Fri 23 Jan 2026 20:51:27 AEDT\n# Added Azure CLI extension checks\n# 11.3.7: Sat 24 Jan 2026 14:19:25 AEDT\n# Added Azure Databricks check routine\n# 11.3.8: Sat 24 Jan 2026 14:22:22 AEDT\n# Added Azure Monitor check routine\n# 11.3.9: Sat 24 Jan 2026 17:16:34 AEDT\n# Added Azure Databricks TBD check list\n# 11.4.0: Sat 24 Jan 2026 17:18:34 AEDT\n# Added Azure Databricks No Public IP check\n# 11.4.1: Sat 24 Jan 2026 17:19:34 AEDT\n# Added Azure Databricks Private Link check\n# 11.4.2: Sat 24 Jan 2026 17:20:34 AEDT\n# Added Azure Databricks Private Endpoints check\n# 11.4.3: Sat 24 Jan 2026 17:47:34 AEDT\n# Added Azure Compute Services check stub\n# 11.4.4: Sat 24 Jan 2026 17:48:34 AEDT\n# Added Azure Database Services check stub\n# 11.4.5: Sat 24 Jan 2026 17:58:34 AEDT\n# Added Azure Identity Services check stub\n# 11.4.6: Sat 24 Jan 2026 18:07:34 AEDT\n# Added Azure Logging and Monitoring check stub\n# 11.4.7: Sat 24 Jan 2026 18:13:34 AEDT\n# Added Azure Networking Services check stub\n# 11.4.8: Sat 24 Jan 2026 18:18:34 AEDT\n# Added Azure Security Services check stub\n# 11.4.9: Sat 24 Jan 2026 18:23:34 AEDT\n# Added Azure Storage Services check stub\n# 11.5.0: Sat 24 Jan 2026 21:32:22 AEDT\n# Added Azure Guest Users check\n# 11.5.1: Sun 25 Jan 2026 10:01:40 AEDT\n# Added Azure User Access Administrator Role check\n# 11.5.2: Sun 25 Jan 2026 11:19:03 AEDT\n# Added Azure Custom Subscription Admin Roles check\n# 11.5.3: Sun 25 Jan 2026 14:54:42 AEDT\n# Added Azure Subscription Owners check\n# 11.5.4: Sun 25 Jan 2026 17:50:12 AEDT\n# Added Azure Subscription Diagnostic Settings check\n# 11.5.5: Sun 25 Jan 2026 18:01:22 AEDT\n# Added check to ensure Diagnostic Setting captures appropriate categories\n# 11.5.6: Sun 25 Jan 2026 19:40:16 AEDT\n# Added check to ensure Diagnostic Logs are encrypted\n# 11.5.7: Sun 25 Jan 2026 21:02:32 AEDT\n# Added Azure Survey check\n# 11.5.8: Mon 26 Jan 2026 12:16:32 AEDT\n# Split out Azure Diagnostic Settings checks into multiple routines\n# 11.5.9: Mon 26 Jan 2026 18:11:56 AEDT\n# Added Azure Key Vault Logging check\n# 11.6.0: Mon 26 Jan 2026 18:21:09 AEDT\n# Added stub for Azure NSG Flow Logs check\n# 11.6.1: Mon 26 Jan 2026 18:26:22 AEDT\n# Added stub for Azure AppService HTTP logs check\n# 11.6.2: Mon 26 Jan 2026 18:27:22 AEDT\n# Documentation and formatting updates\n# 11.6.3: Mon 26 Jan 2026 18:57:48 AEDT\n# Added stub for Azure Virtual Network Flow Logs check\n# 11.6.4: Mon 26 Jan 2026 21:02:22 AEDT\n# Added stub for Azure Entra Diagnostic Settings check\n# 11.6.5: Mon 26 Jan 2026 21:11:22 AEDT\n# Added stub for Azure Graph Diagnostic Settings check\n# 11.6.6: Mon 26 Jan 2026 21:15:22 AEDT\n# Added stub for Azure Intune Logs check\n# 11.6.7: Mon 26 Jan 2026 21:34:22 AEDT\n# Added Azure Activity Log Alerts Create Policy Assignment check\n# 11.6.8: Mon 26 Jan 2026 21:41:22 AEDT\n# Added Azure Activity Log Alerts Delete Policy Assignment check\n# 11.6.9: Mon 26 Jan 2026 21:46:22 AEDT\n# Added Azure Activity Log Alerts Create or Update Network Security Group check\n# 11.7.0: Tue 27 Jan 2026 08:38:22 AEDT\n# Added Azure Activity Log Alerts Delete Network Security Group check\n# 11.7.1: Tue 27 Jan 2026 08:51:22 AEDT\n# Added Azure Activity Log Alerts Create or Update Security Solution check\n# 11.7.2: Tue 27 Jan 2026 08:54:22 AEDT\n# Added Azure Activity Log Alerts Delete Security Solution check\n# 11.7.3: Tue 27 Jan 2026 08:57:22 AEDT\n# Added Azure Activity Log Alerts Create or Update SQL Server Firewall Rule check\n# 11.7.4: Tue 27 Jan 2026 09:00:22 AEDT\n# Added Azure Activity Log Alerts Delete SQL Server Firewall Rule check\n# 11.7.5: Tue 27 Jan 2026 09:03:22 AEDT\n# Added Azure Activity Log Alerts Create or Update Public IP Address rule check\n# 11.7.6: Tue 27 Jan 2026 09:06:22 AEDT\n# Added Azure Activity Log Alerts Delete Public IP Address rule check\n# 11.7.7: Tue 27 Jan 2026 09:09:22 AEDT\n# Added Azure Activity Log Alerts Service Health check\n# 11.7.8: Tue 27 Jan 2026 09:26:22 AEDT\n# Added Azure Application Insights check\n# 11.7.9: Tue 27 Jan 2026 09:38:22 AEDT\n# Added Azure Resource Logging check\n# 11.8.0: Tue 27 Jan 2026 10:08:22 AEDT\n# Added Azure SKU Basic/Consumption check\n# 11.8.1: Tue 27 Jan 2026 11:16:00 AEDT\n# Updated documentation\n# 11.8.2: Tue 27 Jan 2026 12:18:37 AEDT\n# Added Azure Extensions check\n# 11.8.3: Tue 27 Jan 2026 13:22:22 AEDT\n# Updated documentation\n# 11.8.4: Tue 27 Jan 2026 14:10:22 AEDT\n# Added Azure Microsoft Defender check for CSPM\n# 11.8.5: Tue 27 Jan 2026 14:40:22 AEDT\n# Added Azure Microsoft Defender check for CWP\n# 11.8.6: Tue 27 Jan 2026 15:14:52 AEDT\n# Added status check to Microsoft Defender check\n# 11.8.7: Tue 27 Jan 2026 15:24:22 AEDT\n# Added Azure Microsoft Defender check for Defender for Servers\n# 11.8.8: Tue 27 Jan 2026 15:38:22 AEDT\n# Added function to check Azure security setting values\n# 11.8.9: Tue 27 Jan 2026 15:42:22 AEDT\n# Code cleanup\n# 11.9.0: Tue 27 Jan 2026 15:44:22 AEDT\n# Typo fixes\n# 11.9.1: Tue 27 Jan 2026 19:21:22 AEDT\n# Added error handling to systemctl commands\n# 11.9.2: Tue 27 Jan 2026 19:46:22 AEDT\n# Added check that enpoint protection is enabled\n# 11.9.3: Tue 27 Jan 2026 19:51:22 AEDT\n# Added check that agentless scanning is enabled\n# 11.9.4: Tue 27 Jan 2026 20:16:55 AEDT\n# Added check for Microsoft Defender for Containers\n# 11.9.5: Tue 27 Jan 2026 20:19:55 AEDT\n# Added check for Microsoft Defender for Storage\n# 11.9.6: Tue 27 Jan 2026 20:23:55 AEDT\n# Added check for Microsoft Defender for App Services\n# 11.9.7: Tue 27 Jan 2026 20:26:55 AEDT\n# Added check for Microsoft Defender for Azure Cosmos DB\n# 11.9.8: Tue 27 Jan 2026 20:31:22 AEDT\n# Added check for Microsoft Defender for Open-Source RDBMS\n# 11.9.9: Tue 27 Jan 2026 20:34:22 AEDT\n# Updated documentation\n# 12.0.0: Tue Jan 27 20:36:59 AEDT 2026\n# Added check for Microsoft Defender for SQL Server\n# 12.0.1: Tue Jan 27 20:39:35 AEDT 2026\n# Added check for Microsoft Defender for SQL Servers on Machines\n# 12.0.2: Tue Jan 27 20:43:22 AEDT 2026\n# Added check for Microsoft Defender for Azure Key Vault\n# 12.0.3: Tue Wed 28 10:16:12 AEDT 2026\n# Added check for Microsoft Defender for Resource Manager\n# 12.0.4: Tue Wed 28 12:58:38 AEDT 2026\n# Added Azure Security Contact check\n# 12.0.5: Tue Wed 28 13:26:02 AEDT 2026\n# Added Azure Security Contact check for email address\n# 12.0.6: Tue Wed 28 13:28:02 AEDT 2026\n# Added Azure Security Contact check for alert notifications\n# 12.0.7: Tue Wed 28 13:30:02 AEDT 2026\n# Updated documentation\n# 12.0.8: Tue Wed 28 13:35:02 AEDT 2026\n# Added Azure Security Contact check for alert notifications severity\n# 12.0.9: Tue Wed 28 17:08:33 AEDT 2026\n# Improved Microsoft Defender check\n# 12.1.0: Thu 29 Jan 2026 15:07:22 AEDT\n# Added Azure Key Vault check for key enabled status\n# 12.1.1: Thu 29 Jan 2026 15:10:22 AEDT\n# Added Azure Key Vault check for key expiry date\n# 12.1.2: Thu 29 Jan 2026 15:46:51 AEDT\n# Updated output for checks to be more consistent\n# 12.1.3: Thu 29 Jan 2026 15:53:49 AEDT\n# Updated checks for Azure Key Vault keys\n# 12.1.4: Thu 29 Jan 2026 17:32:22 AEDT\n# Added Azure Key Vault Purge Protection check\n# 12.1.5: Thu 29 Jan 2026 18:04:54 AEDT\n# Added Azure Key Vault RBAC check\n# 12.1.6: Thu 29 Jan 2026 19:58:18 AEDT\n# Function variable alignment for azure checks\n# 12.1.7: Thu 29 Jan 2026 21:01:10 AEDT\n# Added Azure Key Vault Public Network Access check\n# 12.1.8: Thu 29 Jan 2026 21:30:38 AEDT\n# Added Azure Key Vault Private Endpoint check\n# 12.1.9: Fri 30 Jan 2026 14:04:38 AEDT\n# Added command_message function\n# 12.2.0: Fri 30 Jan 2026 14:06:38 AEDT\n# Added key vault check for key rotation\n# 12.2.1: Fri 30 Jan 2026 14:47:22 AEDT\n# Fixed Azure Databricks check\n# 12.2.2: Fri 30 Jan 2026 15:50:22 AEDT\n# Started adding command_message function support\n# 12.2.3: Fri 30 Jan 2026 15:53:22 AEDT\n# Updated documentation\n# 12.2.4: Fri 30 Jan 2026 15:56:22 AEDT\n# Fixed Azure Application Insights check\n# 12.2.5: Fri 30 Jan 2026 15:58:22 AEDT\n# Cleaned up Azure User Access Administrator Role check\n# 12.2.6: Fri 30 Jan 2026 16:18:22 AEDT\n# Cleaned up some Azure storage checks\n# 12.2.7: Fri 30 Jan 2026 16:46:22 AEDT\n# Improved environment checking\n# 12.2.8: Fri 30 Jan 2026 17:04:10 AEDT\n# Added Azure login check\n# 12.2.9: Fri 30 Jan 2026 17:12:10 AEDT\n# Updated Azure Monitor Diagnostic Settings check\n# 12.3.0: Sat 31 Jan 2026 11:59:26 AEDT\n# Updated Azure Activity Log Alerts check\n# 12.3.1: Sat 31 Jan 2026 12:34:51 AEDT\n# Updated Azure Key Vault check\n# 12.3.2: Sat 31 Jan 2026 12:36:51 AEDT\n# Updated Azure Key Vault logging check\n# 12.3.3: Sat 31 Jan 2026 15:06:48 AEDT\n# Added command_message support to more Azure modules/functions\n# 12.3.4: Sat 31 Jan 2026 15:47:22 AEDT\n# Added command_message support to check_environment\n# 12.3.5: Sun 01 Feb 2026 11:01:22 AEDT\n# Added command_message support to modules in users directory\n# 12.3.6: Sun 01 Feb 2026 15:43:22 AEDT\n# Added command_message support to modules in wheel directory\n# 12.3.7: Sun 01 Feb 2026 15:45:22 AEDT\n# Added command_message support to modules in sudo directory\n# 12.3.8: Sun 01 Feb 2026 15:47:22 AEDT\n# Added command_message support to modules in sunos directory\n# 12.3.9: Sun 01 Feb 2026 15:49:22 AEDT\n# Added command_message support to modules in syslog directory\n# 12.4.0: Sun 01 Feb 2026 15:51:22 AEDT\n# Added command_message support to modules in talk directory\n# 12.4.1: Sun 01 Feb 2026 15:53:22 AEDT\n# Added command_message support to modules in tcp directory\n# 12.4.2: Sun 01 Feb 2026 15:55:22 AEDT\n# Added command_message support to modules in telnet directory\n# 12.4.3: Sun 01 Feb 2026 20:54:46 AEDT\n# Added command_message support to modules in ssh directory\n# 12.4.4: Sun 01 Feb 2026 20:56:46 AEDT\n# Added command_message support to modules in services directory\n# 12.4.5: Sun 01 Feb 2026 21:04:54 AEDT\n# Added command_message support to modules in remote directory\n# 12.4.6: Sun 01 Feb 2026 21:17:54 AEDT\n# Added command_message support to modules in print directory\n# 12.4.7: Sun 01 Feb 2026 21:19:16 AEDT\n# Added command_message support to modules in power directory\n# 12.4.8: Mon 02 Feb 2026 07:18:53 AEDT\n# Added command_message support to modules in password directory\n# 12.4.9: Mon 02 Feb 2026 07:32:53 AEDT\n# Added command_message support to modules in pam directory\n# 12.5.0: Mon 02 Feb 2026 07:51:53 AEDT\n# Added command_message support to modules in nis directory\n# 12.5.1: Mon 02 Feb 2026 08:00:22 AEDT\n# Added command_message support to modules in mounts directory\n# 12.5.2: Mon 02 Feb 2026 08:07:22 AEDT\n# Added command_message support to modules in mail directory\n# 12.5.3: Mon 02 Feb 2026 08:11:22 AEDT\n# Added command_message support to modules in logs directory\n# 12.5.4: Mon 02 Feb 2026 08:22:22 AEDT\n# Added command_message support to modules in login directory\n# 12.5.5: Mon 02 Feb 2026 08:24:22 AEDT\n# Added command_message support to modules in linux directory\n# 12.5.6: Mon 02 Feb 2026 08:26:22 AEDT\n# Commit some of the command_message changes\n# 12.5.7: Mon 02 Feb 2026 13:12:23 AEDT\n# Fixed typo\n# 12.5.8: Mon 02 Feb 2026 21:14:23 AEDT\n# Improved output for some checks\n# 12.5.9: Mon 02 Feb 2026 21:48:57 AEDT\n# Improved output for modules in fs directory\n# 12.6.0: Tue 03 Feb 2026 11:20:57 AEDT\n# Improved output for modules in other directories\n# 12.6.1: Tue 03 Feb 2026 11:23:43 AEDT\n# Fixed typo in audit_wireless.sh\n# 12.6.2: Tue 03 Feb 2026 12:24:54 AEDT\n# Update some more functions to use command_message\n# 12.6.3: Tue 03 Feb 2026 12:25:13 AEDT\n# Updated audit_system_accounts.sh to allow single ! in shadow field\n# 12.6.4: Tue 03 Feb 2026 15:32:34 AEDT\n# Updated more modules to use command_message\n# 12.6.5: Tue 03 Feb 2026 16:36:34 AEDT\n# Improved user account check for shells\n# 12.6.6: Tue 03 Feb 2026 17:18:22 AEDT\n# Typo fixes\n# 12.6.7: Tue 03 Feb 2026 20:13:17 AEDT\n# Updates and bug fixes\n# 12.6.8: Wed 04 Feb 2026 10:55:40 AEDT\n# Updates and bug fixes for AWS modules\n# 12.6.9: Wed 04 Feb 2026 11:01:40 AEDT\n# Added command_message support to modules in audit directory\n# 12.7.0: Wed 04 Feb 2026 13:19:29 AEDT\n# Added command_message support to modules in esxi directory\n# 12.7.1: Wed 04 Feb 2026 13:23:29 AEDT\n# Added command_message support to modules in firewall directory\n# 12.7.2: Wed 04 Feb 2026 13:26:29 AEDT\n# Added command_message support to modules in fs directory\n# 12.7.3: Wed 04 Feb 2026 13:28:29 AEDT\n# Bug fixes and improvements\n# 12.7.4: Thu 05 Feb 2026 20:45:10 AEDT\n# Added Azure NSG Security Rules check for RDP and SSH access\n# 12.7.5: Thu 05 Feb 2026 21:01:24 AEDT\n# Improved Azure NSG Security Rules check\n# 12.7.6: Thu 05 Feb 2026 21:10:24 AEDT\n# Added Azure NSG Security Rules check for UDP access\n# 12.7.7: Fri 06 Feb 2026 11:15:24 AEDT\n# Added Azure NSG Security Rules check for HTTP(S)\n# 12.7.8: Fri 06 Feb 2026 11:22:24 AEDT\n# Updated documentation for Azure NSG Security Rules check\n# 12.7.9: Fri 06 Feb 2026 11:26:24 AEDT\n# Added Azure Network Watcher check\n# 12.8.0: Fri 06 Feb 2026 13:32:24 AEDT\n# Documentation updates\n# 12.8.1: Fri 06 Feb 2026 13:35:24 AEDT\n# Added Azure Public IPs check\n# 12.8.2: Fri 06 Feb 2026 15:37:24 AEDT\n# Added Azure Network Watcher Flow Logs check\n# 12.8.3: Fri 06 Feb 2026 16:01:24 AEDT\n# Updated Azure Network Watcher Flow Logs check\n# 12.8.4: Fri 06 Feb 2026 16:07:24 AEDT\n# Added Azure Authentication Type check stub\n# 12.8.5: Fri 06 Feb 2026 17:29:24 AEDT\n# Added Azure WAF check\n# 12.8.6: Fri 06 Feb 2026 17:31:24 AEDT\n# Added Azure VNet check\n# 12.8.7: Sat 07 Feb 2026 11:35:30 AEDT\n# Added Azure WAF SSL Policy check\n# 12.8.8: Sat 07 Feb 2026 11:58:30 AEDT\n# Added Azure WAF HTTP2 check\n# 12.8.9: Sat 07 Feb 2026 18:40:30 AEDT\n# Added Azure WAF Request Body check\n# 12.9.0: Sun 08 Feb 2026 14:39:15 AEDT\n# Added Azure WAF Inspection Policy check\n# 12.9.1: Sun 08 Feb 2026 14:51:15 AEDT\n# Added Azure Network Security Perimeter module check\n# 12.9.2: Sun 08 Feb 2026 16:00:15 AEDT\n# Added Azure Network Security Perimeter check\n# 12.9.3: Tue 10 Feb 2026 16:00:15 AEDT\n# Replaced regex with case statement in several functions\n# 12.9.4: Tue 10 Feb 2026 16:45:15 AEDT\n# Added Azure Storage SAS check\n# 12.9.5: Tue 10 Feb 2026 16:50:15 AEDT\n# Added Azure Storage SAS HTTPS Only check\n# 12.9.6: Tue 10 Feb 2026 18:01:15 AEDT\n# Added Azure Storage SAS token expiration check stub\n# 12.9.7: Tue 10 Feb 2026 18:05:15 AEDT\n# Updates and improvements\n# 12.9.8: Thu 12 Feb 2026 13:13:41 AEDT\n# Updated and improvements\n# 12.9.9: Thu 12 Feb 2026 16:27:41 AEDT\n# Added Azure Elastic SAN module check\n# 13.0.0: Thu 12 Feb 2026 16:32:31 AEDT\n# Updated and improvements\n# 13.0.1: Thu 12 Feb 2026 16:55:41 AEDT\n# Added execute_command function\n# 13.0.2: Thu 12 Feb 2026 18:01:47 AEDT\n# Added Azure Elastic SAN check\n# 13.0.3: Fri 13 Feb 2026 11:01:47 AEDT\n# Added Azure Site Recovery module check\n# 13.0.4: Fri 13 Feb 2026 17:15:47 AEDT\n# Added Azure Recovery Service Vaults check\n# 13.0.5: Fri 13 Feb 2026 17:29:47 AEDT\n# Added Azure Virtual Network Access Rules check\n# 13.0.6: Fri 13 Feb 2026 17:51:47 AEDT\n# Added Azure Network Private Endpoints check\n# 13.0.7: Fri 13 Feb 2026 17:55:47 AEDT\n# Added Azure amlfs extension check\n# 13.0.8: Sat 14 Feb 2026 11:52:20 AEDT\n# Added Azure Managed Lustre check\n# 13.0.9: Sat 14 Feb 2026 11:55:20 AEDT\n# Added Azure Storage File System check\n# 13.1.0: Sat 14 Feb 2026 11:58:20 AEDT\n# Added Azure dataprotection extension check\n# 13.1.1: Sat 14 Feb 2026 03:50:57 PM AEDT\n# Added initial code for Azure Data Protection Backup Vault check\n# 13.1.2: Mon 16 Feb 2026 12:40:01 PM AEDT\n# Updates and Improvements\n# 13.1.3: Mon 16 Feb 2026 01:18:57 PM AEDT\n# Fixed check_shellcheck to use find instead of ls\n# 13.1.4: Mon 16 Feb 2026 01:37:57 PM AEDT\n# Applied shellcheck recommendation to azure functions\n# 13.1.5: Mon 16 Feb 2026 01:45:57 PM AEDT\n# Updates and improvements\n# 13.1.6: Mon 16 Feb 2026 02:02:57 PM AEDT\n# Applied shellcheck recommendations to azure modules\n# 13.1.7: Mon 16 Feb 2026 02:27:57 PM AEDT\n# Applied shellcheck recommendations to several modules\n# 13.1.8: Mon 16 Feb 2026 03:28:57 PM AEDT\n# Added Azure tenant ID support\n# 13.1.9: Mon 16 Feb 2026 04:52:57 PM AEDT\n# Added Azure allow no subscriptions support\n# 13.2.0: Mon 16 Feb 2026 05:01:57 PM AEDT\n# Added Azure Backup Vaults check\n# 13.2.1: Mon 16 Feb 2026 05:19:38 PM AEDT\n# Added additional checks to Azure Backup Vaults check\n# 13.2.2: Mon 16 Feb 2026 05:29:38 PM AEDT\n# Added additional checks to Azure Backup Vaults check\n# 13.2.3: Mon 16 Feb 2026 05:32:38 PM AEDT\n# Updates and improvements\n# 13.2.4: Mon 16 Feb 2026 05:45:38 PM AEDT\n# Added additional checks to Azure Backup Vaults check\n# 13.2.5: Mon 16 Feb 2026 06:38:57 PM AEDT\n# Added Azure Recovery Services Vault check\n# 13.2.6: Mon 16 Feb 2026 06:41:57 PM AEDT\n# Updates and improvements\n# 13.2.7: Tue 17 Feb 2026 10:45:57 AM AEDT\n# Updated Azure Recovery Services Vault check\n# 13.2.8: Tue 17 Feb 2026 12:54:28 PM AEDT\n# Added Azure File Shares check for NFS Root Squash\n# 13.2.9: Tue 17 Feb 2026 01:54:28 PM AEDT\n# Updates and improvements\n# 13.3.0: Tue 17 Feb 2026 02:17:28 PM AEDT\n# Added Azure NetApp Files check\n# 13.3.1: Tue 17 Feb 2026 02:27:28 PM AEDT\n# Updates and improvements\n# 13.3.2: Tue 17 Feb 2026 05:14:46 PM AEDT\n# Added additional Azure Elastic SAN checks\n# 13.3.3: Tue 17 Feb 2026 05:45:46 PM AEDT\n# Improved Arch Linux support\n# 13.3.4: Wed 18 Feb 2026 11:10:46 AM AEDT\n# Added Azure Databox extension check\n# 13.3.5: Wed 18 Feb 2026 12:06:14 PM AEDT\n# Added Azure Databox check\n# 13.3.6: Wed 18 Feb 2026 12:22:55 PM AEDT\n# Updates and improvements\n# 13.3.7: Wed 18 Feb 2026 01:59:55 PM AEDT\n# Updates and improvements\n# 13.3.8: Wed 18 Feb 2026 09:02:55 PM AEDT\n# Added Azure Storage Blob Policy Value check\n# 13.3.9: Wed 18 Feb 2026 09:05:55 PM AEDT\n# Updates and improvements\n# 13.4.0: Wed 18 Feb 2026 11:22:55 PM AEDT\n# Added Azure Storage Logging check for queues\n# 13.4.1: Wed 18 Feb 2026 11:40:55 PM AEDT\n# Added Azure Storage Logging check for blobs\n# 13.4.2: Thu 19 Feb 2026 06:45:51 AM AEDT\n# Added Azure Storage Logging check for tables\n# 13.4.3: Thu 19 Feb 2026 06:45:51 AM AEDT\n# Updates and improvements\n# 13.4.4: Thu 19 Feb 2026 12:45:51 PM AEDT\n# Added Azure Storage Account Delete Locks check\n# 13.4.5: Thu 19 Feb 2026 01:15:51 PM AEDT\n# Added Azure Storage Account Read-only Locks check\n# 13.4.6: Thu 19 Feb 2026 01:26:27 PM AEDT\n# Updates and improvements\n# 13.4.7: Fri 20 Feb 2026 06:24:27 AM AEDT\n# Added initial Redis Cache tests\n# 13.4.8: Fri 20 Feb 2026 06:24:27 AM AEDT\n# Updates and improvements\n# 13.4.9: Fri 20 Feb 2026 06:24:27 AM AEDT\n# Added Azure Redis Cache TLS check\n# 13.5.0: Fri 20 Feb 2026 06:24:27 AM AEDT\n# Added Azure Redis Cache Public Network Access check\n# 13.5.1: Fri 20 Feb 2026 09:23:27 AM AEDT\n# Added Azure Redis Cache Private Link check\n# 13.5.2: Fri 20 Feb 2026 09:58:27 AM AEDT\n# Added Azure redisenterprise extension check\n# 13.5.3: Fri 20 Feb 2026 10:01:27 AM AEDT\n# Added Azure Redis Enterprise function\n# 13.5.4: Fri 20 Feb 2026 10:23:27 AM AEDT\n# Added Azure Redis Enterprise Cache Customer-Managed Keys check\n# 13.5.5: Fri 20 Feb 2026 11:17:30 AM AEDT\n# Added Azure Redis Cache Access Keys Authentication check\n# 13.5.6: Fri 20 Feb 2026 11:22:30 AM AEDT\n# Added Azure Redis Cache Update Channel check\n# 13.5.7: Fri 20 Feb 2026 11:22:30 AM AEDT\n# Added Azure Cosmos DB Firewalls & Networks check\n# 13.5.8: Fri 20 Feb 2026 11:22:30 AM AEDT\n# Added Azure Cosmos DB Private Endpoints check\n# 13.5.9: Fri 20 Feb 2026 03:59:23 PM AEDT\n# Added Azure Cosmos DB Disable Local Auth check\n# 13.6.0: Fri 20 Feb 2026 04:09:23 PM AEDT\n# Updates and improvements\n# 13.6.1: Fri 20 Feb 2026 04:24:23 PM AEDT\n# Added Azure Cosmos DB Customer-Managed Keys check\n# 13.6.2: Fri 20 Feb 2026 06:09:23 PM AEDT\n# Added Azure Cosmos DB Firewalls & Networks IP Rules check\n# 13.6.3: Sat 21 Feb 2026 06:09:23 PM AEDT\n# Added Azure Cosmos DB Logging check\n# 13.6.4: Sat 21 Feb 2026 07:09:23 PM AEDT\n# Added Azure Data Factory module check\n# 13.6.5: Sat 21 Feb 2026 07:09:23 PM AEDT\n# Added Azure Data Factory Customer-Managed Keys check\n# 13.6.6: Sat 21 Feb 2026 07:09:23 PM AEDT\n# Added Azure Data Factory Managed Identities check\n# 13.6.7: Sat 21 Feb 2026 09:09:23 PM AEDT\n# Added Azure Data Factory Using Azure Key Vault check\n# 13.6.8: Sun 22 Feb 2026 09:39:23 PM AEDT\n# Added Azure Data Factory Using RBAC check\n# 13.6.9: Sun 22 Feb 2026 09:39:23 PM AEDT\n# Updates and improvements\n# 13.7.0: Sun 22 Feb 2026 02:19:13 PM AEDT\n# Added initial Azure MySQL DB module\n# 13.7.1: Sun 22 Feb 2026 02:19:13 PM AEDT\n# Added initial Azure MySQL DB function\n# 13.7.2: Sun 22 Feb 2026 03:19:13 PM AEDT\n# Added support for Azure MySQL Flexible Server\n# 13.7.3: Sun 22 Feb 2026 03:22:13 PM AEDT\n# Added support for Azure MySQL Single Server\n# 13.7.4: Sun 22 Feb 2026 03:22:13 PM AEDT\n# Added check for Azure MySQL DB Customer-Managed Keys\n# 13.7.5: Sun 22 Feb 2026 03:22:13 PM AEDT\n# Added check for Azure MySQL DB Microsoft Entra Authentication\n# 13.7.6: Sun 22 Feb 2026 03:22:13 PM AEDT\n# Updates and improvements\n# 13.7.7: Sun 22 Feb 2026 03:38:13 PM AEDT\n# Added check for Azure MySQL DB Public Network Access\n# 13.7.8: Sun 22 Feb 2026 03:43:13 PM AEDT\n# Added check for Azure MySQL DB Private Endpoints\n# 13.7.9: Sun 22 Feb 2026 03:50:37 PM AEDT\n# Added check stub for Azure MySQL DB Audit Log\n# 13.8.0: Sun 22 Feb 2026 03:51:37 PM AEDT\n# Added check stub for Azure MySQL DB Audit Log connection\n# 13.8.1: Sun 22 Feb 2026 03:55:37 PM AEDT\n# Added check stub for Azure MySQL DB Error Server Log File\n# 13.8.2: Sun 22 Feb 2026 03:55:37 PM AEDT\n# Added check stub for Azure MySQL DB Require Secure Transport\n# 13.8.3: Sun 22 Feb 2026 03:59:37 PM AEDT\n# Added check stub for Azure MySQL DB TLS Version\n# 13.8.4: Tue 24 Feb 2026 01:24:08 PM AEDT\n# Added initial Azure PostgreSQL DB module\n# 13.8.5: Tue 24 Feb 2026 01:34:08 PM AEDT\n# Added initial support for Azure PostgreSQL Flexible Server\n# 13.8.6: Tue 24 Feb 2026 01:44:08 PM AEDT\n# Added initial support for Azure PostgreSQL Single Server\n# 13.8.7: Tue 24 Feb 2026 01:54:08 PM AEDT\n# Add initial Azure PostgreSQL DB checks\n# 13.8.8: Tue 24 Feb 2026 02:04:08 PM AEDT\n# Updates and improvements\n# 13.8.9: Tue 24 Feb 2026 04:04:08 PM AEDT\n# Added initial Azure SQL DB module\n# 13.9.0: Tue 24 Feb 2026 04:04:08 PM AEDT\n# Added initial Azure SQL DB function\n# 13.9.1: Tue 24 Feb 2026 04:09:08 PM AEDT\n# Updates and improvements\n# 13.9.2: Tue 24 Feb 2026 21:33:43 PM AEDT\n# Updates and improvements\n# 13.9.3: Wed 25 Feb 2026 11:42:53 AM AEDT\n# Added initial Azure App Service App module\n# 13.9.4: Wed 25 Feb 2026 11:42:53 AM AEDT\n# Added initial Azure App Service App function\n# 13.9.5: Wed 25 Feb 2026 11:42:53 AM AEDT\n# Formating updates\n# 13.9.6: Wed 25 Feb 2026 11:52:53 AM AEDT\n# Added Azure App Service App check for Java\n# 13.9.7: Wed 25 Feb 2026 11:52:53 AM AEDT\n# Updates and improvements\n# 13.9.8: Wed 25 Feb 2026 12:52:53 PM AEDT\n# Added Azure App Service App check for Python\n# 13.9.9: Wed 25 Feb 2026 01:12:53 PM AEDT\n# Added Azure App Service App check for PHP\n# 14.0.0: Wed 25 Feb 2026 01:59:53 PM AEDT\n# Added Azure App Service App check for Basic Authentication Publishing Credentials\n# 14.0.1: Wed 25 Feb 2026 02:10:53 PM AEDT\n# Added Azure App Service App check for FTP State\n# 14.0.2: Wed 25 Feb 2026 03:07:53 PM AEDT\n# Bug fixes\n# 14.0.3: Wed 25 Feb 2026 03:20:53 PM AEDT\n# Added Azure App Service App check for HTTP Version\n# 14.0.4: Wed 25 Feb 2026 03:20:53 PM AEDT\n# Added Azure App Service App check for HTTPS Only\n# 14.0.5: Wed 25 Feb 2026 04:20:53 PM AEDT\n# Added Azure App Service App check for Minimum Inbound TLS Version\n# 14.0.6: Wed 25 Feb 2026 04:50:53 PM AEDT\n# Added Azure App Service App check for end to end TLS encryption\n# 14.0.7: Wed 25 Feb 2026 05:20:53 PM AEDT\n# Added Azure App Service App check for Remote Debugging\n# 14.0.8: Wed 25 Feb 2026 05:50:53 PM AEDT\n# Added Azure App Service App check for Client Certificates\n# 14.0.9: Wed 25 Feb 2026 06:20:53 PM AEDT\n# Added Azure App Service App check for Authentication\n# 14.1.0: Wed 25 Feb 2026 06:20:53 PM AEDT\n# Added Azure App Service App check for Managed Identities\n# 14.1.1: Wed 25 Feb 2026 06:20:53 PM AEDT\n# Added Azure App Service App check for Public Network Access\n# 14.1.2: Wed 25 Feb 2026 06:20:53 PM AEDT\n# Added Azure App Service App check for App Service Plan SKU\n# 14.1.3: Wed 25 Feb 2026 10:20:21 PM AEDT\n# Added Azure App Service App check for Private Endpoints\n# 14.1.4: Thu 26 Feb 2026 10:37:21 AM AEDT\n# Added Azure App Service App check for Private DNS Zone\n# 14.1.5: Thu 26 Feb 2026 10:47:21 AM AEDT\n# Added Azure App Service App check for Virtual Network Integration\n# 14.1.6: Thu 26 Feb 2026 11:00:21 AM AEDT\n# Added Azure App Service App check for VNet Image Pull\n# 14.1.7: Thu 26 Feb 2026 11:00:21 AM AEDT\n# Added Azure App Service App check for VNet Content Share\n# 14.1.8: Thu 26 Feb 2026 11:13:09 AM AEDT\n# Added Azure App Service App check for Cross-Origin Resource Sharing\n# 14.1.9: Thu 26 Feb 2026 12:42:49 PM AEDT\n# Added Azure App Service Deployment Slot audit module\n# 14.2.0: Thu 26 Feb 2026 12:44:59 AEDT\n# Added Azure App Service Deployment Slot function\n# 14.2.1: Thu 26 Feb 2026 12:47:19 AEDT\n# Added Azure App Service Deployment Slot Java version check\n# 14.2.2: Thu 26 Feb 2026 12:49:16 AEDT\n# Added Azure App Service Deployment Slot Python version check\n# 14.2.3: Thu 26 Feb 2026 12:50:09 AEDT\n# Added Azure App Service Deployment Slot PHP version check\n# 14.2.4: Thu 26 Feb 2026 13:08:16 AEDT\n# Added Azure App Service Deployment Slot Basic Authentication Publishing Credentials\n# 14.2.4: Thu 26 Feb 2026 13:10:25 AEDT\n# Added Azure App Service Deployment Slot FTP state check\n# 14.2.5: Thu 26 Feb 2026 13:11:07 AEDT\n# Added Azure App Service Deployment HTTP version check\n# 14.2.6: Thu 26 Feb 2026 13:13:38 AEDT\n# Added Azure App Service Deployment HTTPs check\n# 14.2.7: Thu 26 Feb 2026 13:14:36 AEDT\n# Added Azure App Service Deployment Slot TLS version check\n# 14.2.8: Thu 26 Feb 2026 13:16:53 AEDT\n# Added Azure App Service Deployment Slot end to end TLS encryptions check\n# 14.2.9: Thu 26 Feb 2026 13:20:20 AEDT\n# Added Azure App Service Deployment Slot Remote Debugging check\n# 14.2.9: Thu 26 Feb 2026 13:27:03 AEDT\n# Added Azure App Service Deployment Slot Client Certificates check\n# 14.2.9: Thu 26 Feb 2026 13:28:00 AEDT\n# Added Azure App Service Deployment Slot Managed Identities check\n# 14.3.0: Thu 26 Feb 2026 13:28:23 AEDT\n# Added Azure App Service Deployment Slot Public Network Access check\n# 14.3.1: Thu 26 Feb 2026 13:39:41 AEDT\n# Added Azure App Service Deployment Slot VNet check\n# 14.3.2: Thu 26 Feb 2026 13:40:33 AEDT\n# Added Azure App Service Deployment Slot VNet Routing check\n# 14.3.3: Thu 26 Feb 2026 13:41:45 AEDT\n# Added Azure App Service Deployment Slot Cross-Origin Resource Sharing check\n# 14.3.4: Thu 26 Feb 2026 13:44:47 AEDT\n# Updates and improvements\n# 14.3.5: Thu 26 Feb 2026 15:46:47 AEDT\n# Added Azure Function App module\n# 14.3.6: Thu 26 Feb 2026 16:47:47 AEDT\n# Added Azure Function App function\n# 14.3.7: Thu 26 Feb 2026 16:48:47 AEDT\n# Added Azure Function App check for Java version\n# 14.3.8: Thu 26 Feb 2026 16:49:47 AEDT\n# Added Azure Function App check for Python version\n# 14.3.9: Thu 26 Feb 2026 16:50:47 AEDT\n# Added Azure Function App check for PHP version\n# 14.4.0: Thu 26 Feb 2026 16:51:47 AEDT\n# Added Azure Function App check for Basic Authentication Publishing Credentials\n# 14.4.1: Thu 26 Feb 2026 16:52:47 AEDT\n# Added Azure Function App check for FTP state\n# 14.4.2: Thu 26 Feb 2026 16:53:47 AEDT\n# Added Azure Function App check for HTTP version\n# 14.4.3: Thu 26 Feb 2026 16:54:47 AEDT\n# Added Azure Function App check for HTTPS only\n# 14.4.4: Thu 26 Feb 2026 16:55:47 AEDT\n# Added Azure Function App check for Minimum Inbound TLS Version\n# 14.4.5: Thu 26 Feb 2026 16:56:47 AEDT\n# Added Azure Function App check for end to end TLS encryption\n# 14.4.6: Thu 26 Feb 2026 16:57:47 AEDT\n# Added Azure Function App check for Remote Debugging\n# 14.4.7: Thu 26 Feb 2026 16:58:47 AEDT\n# Added Azure Function App check for Client Certificates\n# 14.4.8: Thu 26 Feb 2026 16:59:47 AEDT\n# Added Azure Function App check for Authentication\n# 14.4.9: Thu 26 Feb 2026 17:00:47 AEDT\n# Added Azure Function App check for Managed Identities\n# 14.5.0: Thu 26 Feb 2026 17:01:47 AEDT\n# Added Azure Function App check for Public Network Access\n# 14.5.1: Thu 26 Feb 2026 17:02:47 AEDT\n# Added Azure Function App check for App Service Plan SKU\n# 14.5.2: Thu 26 Feb 2026 17:03:47 AEDT\n# Added Azure Function App check for Private Endpoints\n# 14.5.3: Thu 26 Feb 2026 17:04:47 AEDT\n# Added Azure Function App check for Private DNS Zone\n# 14.5.4: Thu 26 Feb 2026 17:05:47 AEDT\n# Added Azure Function App check for Virtual Network Integration\n# 14.5.5: Thu 26 Feb 2026 17:06:47 AEDT\n# Added Azure Function App check for VNet Image Pull\n# 14.5.6: Thu 26 Feb 2026 17:07:47 AEDT\n# Added Azure Function App check for VNet Content Share\n# 14.5.7: Thu 26 Feb 2026 17:08:47 AEDT\n# Added Azure Function App check for Cross-Origin Resource Sharing\n# 14.5.8: Thu 26 Feb 2026 17:21:47 AEDT\n# Updates and improvements\n# 14.5.9: Thu 26 Feb 2026 17:38:47 AEDT\n# Added Azure Function App Deployment Slot audit module\n# 14.6.0: Thu 26 Feb 2026 17:39:47 AEDT\n# Added Azure Function App Deployment Slot function\n# 14.6.1: Thu 26 Feb 2026 17:40:47 AEDT\n# Added Azure Function App Deployment Slot check for Java version\n# 14.6.2: Thu 26 Feb 2026 17:41:47 AEDT\n# Added Azure Function App Deployment Slot check for Python version\n# 14.6.3: Thu 26 Feb 2026 17:42:47 AEDT\n# Added Azure Function App Deployment Slot check for PHP version\n# 14.6.4: Thu 26 Feb 2026 17:43:47 AEDT\n# Added Azure Function App Deployment Slot check for Basic Authentication Publishing Credentials\n# 14.6.5: Thu 26 Feb 2026 17:44:47 AEDT\n# Added Azure Function App Deployment Slot check for FTP state\n# 14.6.6: Thu 26 Feb 2026 17:45:47 AEDT\n# Added Azure Function App Deployment Slot check for HTTP version\n# 14.6.7: Thu 26 Feb 2026 17:46:47 AEDT\n# Added Azure Function App Deployment Slot check for HTTPS only\n# 14.6.8: Thu 26 Feb 2026 17:47:47 AEDT\n# Added Azure Function App Deployment Slot check for Minimum Inbound TLS Version\n# 14.6.9: Thu 26 Feb 2026 17:48:47 AEDT\n# Added Azure Function App Deployment Slot check for end to end TLS encryption\n# 14.7.0: Thu 26 Feb 2026 17:49:47 AEDT\n# Added Azure Function App Deployment Slot check for Remote Debugging\n# 14.7.1: Thu 26 Feb 2026 17:50:47 AEDT\n# Added Azure Function App Deployment Slot check for Client Certificates\n# 14.7.2: Thu 26 Feb 2026 17:51:47 AEDT\n# Added Azure Function App Deployment Slot check for Authentication\n# 14.7.3: Thu 26 Feb 2026 17:52:47 AEDT\n# Added Azure Function App Deployment Slot check for Managed Identities\n# 14.7.4: Thu 26 Feb 2026 17:53:47 AEDT\n# Added Azure Function App Deployment Slot check for Public Network Access\n# 14.7.5: Thu 26 Feb 2026 17:54:47 AEDT\n# Added Azure Function App Deployment Slot check for Virtual Network Integration\n# 14.7.6: Thu 26 Feb 2026 17:55:47 AEDT\n# Added Azure Function App Deployment Slot check for VNet Image Pull\n# 14.7.7: Thu 26 Feb 2026 17:56:47 AEDT\n# Added Azure Function App Deployment Slot check for VNet Content Share\n# 14.7.8: Thu 26 Feb 2026 17:57:47 AEDT\n# Added Azure Function App Deployment Slot check for Cross-Origin Resource Sharing\n# 14.7.9: Thu 26 Feb 2026 17:58:47 AEDT\n# Updates and improvements\n# 14.8.0: Fri 27 Feb 2026 11:31:09 AEDT\n# Added Azure Key Vault Certificates audit module\n# 14.8.1: Fri 27 Feb 2026 11:32:09 AEDT\n# Added Azure Key Vault Secrets audit module\n# 14.8.2: Fri 27 Feb 2026 11:33:09 AEDT\n# Updates and improvements\n# 14.8.3: Fri 27 Feb 2026 12:41:09 AEDT\n# Added Azure App Service ASE audit module\n# 14.8.4: Fri 27 Feb 2026 12:42:09 AEDT\n# Added Azure App Service ASE function\n# 14.8.5: Fri 27 Feb 2026 12:43:09 AEDT\n# Added Azure App Service ASE check for internal load balancing mode\n# 14.8.6: Fri 27 Feb 2026 12:50:11 AEDT\n# Added Azure App Service ASE check for ASE version\n# 14.8.7: Fri 27 Feb 2026 12:51:11 AEDT\n# Added Azure App Service ASE check for internal encryption\n# 14.8.8: Fri 27 Feb 2026 12:52:11 AEDT\n# Added Azure App Service ASE check for TLS 1.0 and 1.1 disabled\n# 14.8.9: Fri 27 Feb 2026 12:53:11 AEDT\n# Added Azure App Service ASE check for TLS cipher suite ordering configured\n# 14.9.0: Fri 27 Feb 2026 15:32:11 AEDT\n# Added Azure Container Instances audit module\n# 14.9.1: Fri 27 Feb 2026 15:33:11 AEDT\n# Added Azure Container Instances function\n# 14.9.2: Fri 27 Feb 2026 15:34:11 AEDT\n# Added Azure Container Instances check for Private Virtual Networks\n# 14.9.3: Fri 27 Feb 2026 15:35:11 AEDT\n# Added Azure Container Instances check for Managed Identity\n# 14.9.4: Fri 27 Feb 2026 16:05:11 AEDT\n# Added Azure CycleCloud audit module\n# 14.9.5: Fri 27 Feb 2026 16:22:11 AEDT\n# Added Azure Batch audit module\n# 14.9.6: Fri 27 Feb 2026 16:23:11 AEDT\n# Added Azure Batch function\n# 14.9.7: Fri 27 Feb 2026 16:24:11 AEDT\n# Added Azure Batch check for customer managed keys\n# 14.9.8: Fri 27 Feb 2026 16:25:11 AEDT\n# Added Azure Batch check for pool disk encryption\n# 14.9.9: Fri 27 Feb 2026 18:06:48 AEDT\n# Added Azure Batch check for local authentication methods\n# 15.0.0: Fri 27 Feb 2026 18:07:48 AEDT\n# Added Azure Batch check for private endpoints\n# 15.0.1: Fri 27 Feb 2026 18:08:48 AEDT\n# Added Azure Batch check for public network access\n# 15.0.2: Fri 27 Feb 2026 20:10:48 AEDT\n# Updates and improvements\n# 15.0.3: Sat 28 Feb 2026 11:47:48 AEDT\n# Added Azure Virtual Machines audit module\n# 15.0.4: Sat 28 Feb 2026 11:48:48 AEDT\n# Added Azure Virtual Machines function\n# 15.0.5: Sat 28 Feb 2026 11:49:48 AEDT\n# Updates and improvements\n# 15.0.6: Sat 28 Feb 2026 21:31:31 AEDT\n# Formatting fixes\n# 15.0.7: Mon  2 Mar 2026 11:44:44 AEDT\n# Formatting fixes\n# 15.0.8: Mon  2 Mar 2026 20:45:44 AEDT\n# Formatting fixes\n# 15.0.9: Wed 04 Mar 2026 17:28:10 AEDT\n# More formatting fixes\n# 15.1.0: Tue 10 Mar 2026 14:49:52 AEDT\n# Added switch value checking\n# 15.1.1: Tue 10 Mar 2026 16:38:52 AEDT\n# Improved Azure CLI extension checking\n# 15.1.2: Wed 11 Mar 2026 15:27:06 AEDT\n# Improved module listing\n# 15.1.3: Wed 11 Mar 2026 16:35:06 AEDT\n# Formatting fixes\n# 15.1.4: Thu 12 Mar 2026 08:06:53 AEDT\n# Typo fixes\n# 15.1.5: Thu 12 Mar 2026 13:08:36 AEDT\n# Formatting fixes\n# 15.1.6: Thu 12 Mar 2026 15:50:28 AEDT\n# Shellcheck fixes\n# 15.1.7: Thu 12 Mar 2026 17:29:28 AEDT\n# Formatting fixes\n# 15.1.8: Fri 13 Mar 2026 12:45:28 AEDT\n# Split out Azure WebApps Java version check\n# 15.1.9: Fri 13 Mar 2026 12:46:28 AEDT\n# Updated Azure WebApps value check\n# 15.2.0: Fri 13 Mar 2026 13:21:28 AEDT\n# Split out Azure WebApps Python version check\n# 15.2.1: Fri 13 Mar 2026 13:26:28 AEDT\n# Split out Azure WebApps PHP version check\n# 15.2.2: Fri 13 Mar 2026 13:27:28 AEDT\n# Split out Azure WebApps FTP state check\n# 15.2.3: Fri 13 Mar 2026 15:14:28 AEDT\n# Split out Azure WebApps Basic Authentication Publishing Credentials check\n# 15.2.4: Fri 13 Mar 2026 15:15:28 AEDT\n# Fixed Azure WebApps Basic Authentication Publishing Credentials check\n# 15.2.5: Fri 13 Mar 2026 16:36:28 AEDT\n# Split out Azure WebApps HTTP values check\n# 15.2.6: Fri 13 Mar 2026 16:57:28 AEDT\n# Split out Azure WebApps TLS values check\n# 15.2.7: Fri 13 Mar 2026 17:23:28 AEDT\n# Split out Azure WebApps Remote Debugging check\n# 15.2.8: Fri 13 Mar 2026 17:36:28 AEDT\n# Split out Azure WebApps Client Certificates check\n# 15.2.9: Fri 13 Mar 2026 17:43:28 AEDT\n# Split out Azure WebApps Authentication check\n# 15.3.0: Fri 13 Mar 2026 17:46:28 AEDT\n# Split out Azure WebApps Managed Identities check\n# 15.3.1: Fri 13 Mar 2026 17:54:28 AEDT\n# Split out Azure WebApps Public Network Access check\n# 15.3.2: Fri 13 Mar 2026 17:58:28 AEDT\n# Split out Azure WebApps Private DNS Zones check\n# 15.3.3: Fri 13 Mar 2026 18:14:28 AEDT\n# Split out Azure WebApps Virtual Network Integration check\n# 15.3.4: Fri 13 Mar 2026 18:22:28 AEDT\n# Split out Azure WebApps VNet checks\n# 15.3.5: Fri 13 Mar 2026 18:43:28 AEDT\n# Split out Azure WebApps CORS check\n# 15.3.6: Fri 13 Mar 2026 18:44:28 AEDT\n# Split out Azure WebApps Private Endpoint check\n# 15.3.7: Fri 13 Mar 2026 18:45:28 AEDT\n# Fixed Azure Private Endpoint check\n# 15.3.8: Fri 13 Mar 2026 20:46:28 AEDT\n# Fixed Azure App Service Plan SKU check\n# 15.3.9: Fri 13 Mar 2026 20:47:28 AEDT\n# Split out Azure App Service Plan SKU check\n# 15.4.0: Mon 16 Mar 2026 12:38:14 AEDT\n# Split out Azure App Service Deployment Slot Java version check\n# 15.4.1: Mon 16 Mar 2026 13:47:02 AEDT\n# Split azure directories into sub directories\n# 15.4.2: Mon 16 Mar 2026 14:43:03 AEDT\n# Split out Azure App Service Deployment Slot Python version check\n# 15.4.3: Mon 16 Mar 2026 15:14:03 AEDT\n# Split out Azure App Service Deployment Slot PHP version check\n# 15.4.4: Mon 16 Mar 2026 15:15:03 AEDT\n# Split out Azure App Service Deployment Slot Basic Auth check\n# 15.4.5: Mon 16 Mar 2026 15:31:03 AEDT\n# Split out Azure App Service Deployment Slot FTP State check\n# 15.4.6: Mon 16 Mar 2026 15:52:03 AEDT\n# Split out Azure App Service Deployment Slot HTTP Version check\n# 15.4.7: Mon 16 Mar 2026 15:59:11 AEDT\n# Split out Azure App Service Deployment Slot HTTPS Only check\n# 15.4.8: Mon 16 Mar 2026 16:07:11 AEDT\n# Split out Azure App Service Deployment Slot TLS values check\n# 15.4.9: Mon 16 Mar 2026 16:51:41 AEDT\n# Split out Azure App Service Deployment Slot Remote Debugging check\n# 15.5.0: Mon 16 Mar 2026 16:56:41 AEDT\n# Split out Azure App Service Deployment Slot Client Certificates check\n# 15.5.1: Mon 16 Mar 2026 17:04:41 AEDT\n# Split out Azure App Service Deployment Slot Managed Identities check\n# 15.5.2: Mon 16 Mar 2026 17:08:41 AEDT\n# Split out Azure App Service Deployment Slot Public Network Access check\n# 15.5.3: Mon 16 Mar 2026 17:12:41 AEDT\n# Split out Azure App Service Deployment Slot Virtual Network Integration check\n# 15.5.4: Mon 16 Mar 2026 17:15:41 AEDT\n# Split out Azure App Service Deployment Slot VNet Image Pull check\n# 15.5.5: Mon 16 Mar 2026 17:16:41 AEDT\n# Split out Azure App Service Deployment Slot VNet Content Share check\n# 15.5.6: Mon 16 Mar 2026 17:22:25 AEDT\n# Split out Azure App Service Deployment Slot CORS check\n# 15.5.7: Mon 16 Mar 2026 17:27:25 AEDT\n# Split out Azure App Service Deployment Slot Private Endpoints check\n# 15.5.8: Mon 16 Mar 2026 19:31:25 AEDT\n# Split out Azure Function App Deployment Slots Java version check\n# 15.5.9: Mon 16 Mar 2026 19:55:25 AEDT\n# Split out Azure Function App Deployment Slots Python version check\n# 15.6.0: Mon 16 Mar 2026 20:09:13 AEDT\n# Split out Azure Function App Deployment Slots Basic Authentication Publishing Credentials check\n# 15.6.1: Mon 16 Mar 2026 20:15:13 AEDT\n# Split out Azure Function App Deployment Slots FTP State check\n# 15.6.2: Mon 16 Mar 2026 20:20:13 AEDT\n# Split out Azure Function App Deployment Slots HTTP Version and HTTPS Only check\n# 15.6.3: Mon 16 Mar 2026 21:43:13 AEDT\n# Split out Azure Function App Deployment Slots TLS values check\n# 15.6.4: Mon 16 Mar 2026 21:44:13 AEDT\n# Formatting fixes for Azure Function App Deployment Slots\n# 15.6.5: Mon 17 Mar 2026 22:20:13 AEDT\n# Formatting fixes for Azure App Service Deployment Slots\n# 15.6.6: Mon 17 Mar 2026 22:28:13 AEDT\n# Split out Azure Function App Deployment Slots Remote Debugging check\n# 15.6.7: Mon 17 Mar 2026 22:32:13 AEDT\n# Split out Azure Function App Deployment Slots Client Certificates check\n# 15.6.8: Mon 17 Mar 2026 22:36:13 AEDT\n# Split out Azure Function App Deployment Slots Managed Identities check\n# 15.6.9: Mon 17 Mar 2026 22:40:13 AEDT\n# Split out Azure Function App Deployment Slots Public Network Access check\n# 15.7.0: Mon 17 Mar 2026 22:44:13 AEDT\n# Split out Azure Function App Deployment Slots Virtual Network Integration and VNet check\n# 15.7.1: Mon 17 Mar 2026 22:48:13 AEDT\n# Split out Azure Function App Deployment Slots CORS check\n# 15.7.2: Mon 17 Mar 2026 22:52:13 AEDT\n# Split out Azure Function App Deployment Slots Private Endpoints check\n# 15.7.3: Mon 17 Mar 2026 22:56:13 AEDT\n# Directory structure clean up\n# 15.7.4: Tue 17 Mar 2026 11:00:33 AEDT\n# Split out Azure Function App Java versions check\n# 15.7.5: Tue 17 Mar 2026 11:02:33 AEDT\n# Split out Azure Function App Python versions check\n# 15.7.6: Tue 17 Mar 2026 13:35:33 AEDT\n# Split out Azure Function App Basic Authentication Publishing Credentials check\n# 15.7.7: Tue 17 Mar 2026 13:46:33 AEDT\n# Split out Azure Function App FTP State check\n# 15.7.8: Tue 17 Mar 2026 14:30:13 AEDT\n# Split out Azure Function App HTTP values check\n# 15.7.9: Tue 17 Mar 2026 14:37:13 AEDT\n# Split out Azure Function App TLS values check\n# 15.8.0: Wed 18 Mar 2026 15:13:13 AEDT\n# Split out Azure Function App Remote Debugging check\n# 15.8.1: Wed 18 Mar 2026 15:17:40 AEDT\n# Split out Azure Function App Client Certificates check\n# 15.8.2: Wed 18 Mar 2026 15:35:40 AEDT\n# Split out Azure Function App Service Authentication check\n# 15.8.3: Wed 18 Mar 2026 15:52:40 AEDT\n# Split out Azure Function App Managed Identities check\n# 15.8.4: Wed 18 Mar 2026 15:57:40 AEDT\n# Split out Azure Function App Public Network Access check\n# 15.8.5: Wed 18 Mar 2026 16:09:40 AEDT\n# Split out Azure Function App Virtual Network Integration and VNet checks\n# 15.8.6: Wed 18 Mar 2026 16:13:40 AEDT\n# Split out Azure Function App Cross-Origin Resource Sharing check\n# 15.8.7: Wed 18 Mar 2026 16:31:40 AEDT\n# Function name cleanup\n# 15.8.8: Thu 19 Mar 2026 14:04:02 AEDT\n# Cleaned up AWS module directory structure\n# 15.8.9: Thu 19 Mar 2026 17:34:02 AEDT\n# Added platform check to XD/NX Support check\n# 15.9.0: Thu 19 Mar 2026 18:06:02 AEDT\n# Added percentage calculation to print_info\n# 15.9.1: Thu 19 Mar 2026 21:21:45 AEDT\n# Fixed Bluetooth check\n"
  },
  {
    "path": "docker-compose.yml",
    "content": "version: '3'\nservices:\n  test-shell:\n    image: \"${OS_NAME}:${OS_VERSION}\"\n    volumes:\n      - \".:/lunar\"\n    command: \"/bin/bash\" \n  test-audit:\n    image: \"${OS_NAME}:${OS_VERSION}\"\n    volumes:\n      - \".:/lunar\"\n    command: bash -c \"/lunar/lunar.sh -a\"\n"
  },
  {
    "path": "functions/aix/check_auditctl.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_auditctl\n#\n# Check whether a executable, file or directory is being audited\n#.\n\ncheck_auditctl () {\n  check_file=\"${1}\"\n  audit_tag=\"${2}\"\n  print_function \"check_auditctl\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${audit_mode}\" != 2 ]; then\n      secure_string=\"Auditing is enabled on file \\\"${check_file}\\\"\"\n      insecure_string=\"Auditing is not enabled on file \\\"${check_file}\\\"\"\n      check_message \"${secure_string}\"\n      get_command=\"auditctl -l | grep ${check_file}\"\n      set_command=\"auditctl -w ${file} -p wa -k ${audit_tag}\"\n      if [ -e \"${check_file}\" ]; then\n        check=$( auditctl -l | grep \"${check_file}\" )\n        if [ -z \"${check}\" ]; then\n          if [ \"${ansible_mode}\" = 1 ]; then\n            ansible_counter=$((ansible_counter+1))\n            ansible_value=\"auditctl_file_check_${ansible_counter}\"\n            echo \"\"\n            echo \"- name: Checking ${secure_string}\"\n            echo \"  command: sh -c \\\"${get_command}\\\"\"\n            echo \"  register: ${ansible_value}\"\n            echo \"  failed_when: ${ansible_value} == 1\"\n            echo \"  changed_when: false\"\n            echo \"  ignore_errors: true\"\n            echo \"  when: ansible_facts['ansible_system'] == '${os_name}'\"\n            echo \"\"\n            echo \"- name: Enable Auditing for ${file}\"\n            echo \"  command: sh -c \\\"${set_command}\\\"\"\n            echo \"  when: ${ansible_value}.rc == 1 and ansible_facts['ansible_system'] == '${os_name}'\"\n            echo \"\"\n          fi\n          inc_insecure \"${insecure_string}\"\n          lock_command=\"${set_command}\"\n          lock_message=\"${secure_string}\" \n          run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n        else\n          inc_secure   \"${secure_string}\"\n        fi\n      fi\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/aix/check_chsec.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_chsec\n#\n# Function to check sec under AIX\n#.\n\ncheck_chsec() {\n  if [ \"${os_name}\" = \"AIX\" ]; then\n    sec_file=\"${1}\"\n    sec_stanza=\"${2}\"\n    parameter_name=\"${3}\"\n    correct_value=\"${4}\"\n    print_function \"check_chsec\"\n    log_file=\"${sec_file}_${sec_stanza}_${parameter_name}.log\"\n    get_command=\"lssec -f ${sec_file} -s ${sec_stanza} -a ${parameter_name} |awk '{print \\$2}' |cut -f2 -d=\"\n    set_command=\"chsec -f ${sec_file} -s ${sec_stanza} -a ${parameter_name}=${correct_value}\"\n    if [ \"${audit_mode}\" != 2 ]; then\n      string=\"Security Policy for \\\"${parameter_name}\\\" is set to \\\"${correct_value}\\\"\"\n      check_message  \"${string}\"\n      if [ \"${ansible_mode}\" = 1 ]; then\n        ansible_counter=$((ansible_counter+1))\n        ansible_value=\"check_chsec_${ansible_counter}\"\n        echo \"\"\n        echo \"- name: Checking ${string}\"\n        echo \"  command: sh -c \\\"${get_command}\\\"\"\n        echo \"  register: ${ansible_value}\"\n        echo \"  failed_when: ${ansible_value} == 1\"\n        echo \"  changed_when: false\"\n        echo \"  ignore_errors: true\"\n        echo \"  when: ansible_facts['ansible_system'] == '${os_name}'\"\n        echo \"\"\n        echo \"- name: Fixing ${string}\"\n        echo \"  command: sh -c \\\"${set_command}\\\"\"\n        echo \"  when: ${ansible_value}.rc == 1 and ansible_facts['ansible_system'] == '${os_name}'\"\n        echo \"\"\n      fi\n      actual_value=$( eval \"${get_command}\" )\n      if [ \"${actual_value}\" != \"${correct_value}\" ]; then\n        update_log   \"${log_file}\" \"chsec -f ${sec_file} -s ${sec_stanza} -a ${parameter_name}=${actual_value}\"\n        inc_insecure \"Security Policy for \\\"${parameter_name}\\\" is not set to \\\"${correct_value}\\\"\"\n        lock_command=\"chsec -f ${sec_file} -s ${sec_stanza} -a ${parameter_name}=${correct_value}\"\n        lock_message=\"Security Policy for \\\"${parameter_name}\\\" to \\\"${correct_value}\\\"\"\n        run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n      else\n        inc_secure   \"Password Policy for \\\"${parameter_name}\\\" is set to \\\"${correct_value}\\\"\"\n      fi\n    else\n      log_file=\"${restore_dir}/${log_file}\"\n      if [ -f \"${log_file}\" ]; then\n        previous_value=$( cut -f2 -d= \"${log_file}\" )\n        if [ \"${previous_value}\" != \"${actual_value}\" ]; then\n          restore_message=\"Restoring: Password Policy for \\\"${parameter_name}\\\" to \\\"${previous_value}\\\"\"\n          restore_command=\"sh < ${log_file}\"\n          execute_restore \"${restore_command}\" \"${restore_message}\" \"sudo\"\n        fi\n      fi\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/aix/check_chuser.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_chuser\n#\n# Function to check sec under AIX\n#.\n\ncheck_chuser() {\n  if [ \"${os_name}\" = \"AIX\" ]; then\n    sec_file=\"${1}\"\n    parameter_name=\"${2}\"\n    correct_value=\"${3}\"\n    group_name=\"${4}\"\n    group_value=\"${5}\"\n    user_name=\"${6}\"\n    print_function \"check_chuser\"\n    log_file=\"${sec_file}_${parameter_name}_${group_name}.log\"\n    get_command=\"lssec -f ${sec_file} -s ${sec_stanza} -a ${parameter_name} |awk '{print \\$2}' |cut -f2 -d=\"\n    set_command=\"chsec -f ${sec_file} -s ${sec_stanza} -a ${parameter_name}=${correct_value}\"\n    if [ \"${audit_mode}\" != 2 ]; then\n      string=\"Security Policy for \\\"${parameter_name}\\\" is set to \\\"${correct_value}\\\"\"\n      check_message  \"${string}\"\n      if [ \"${ansible_mode}\" = 1 ]; then\n        ansible_counter=$((ansible_counter+1))\n        ansible_value=\"check_chuser_${ansible_counter}\"\n        echo \"\"\n        echo \"- name: Checking ${string}\"\n        echo \"  command: sh -c \\\"${get_command}\\\"\"\n        echo \"  register: ${ansible_value}\"\n        echo \"  failed_when: ${ansible_value} == 1\"\n        echo \"  changed_when: false\"\n        echo \"  ignore_errors: true\"\n        echo \"  when: ansible_facts['ansible_system'] == '${os_name}'\"\n        echo \"\"\n        echo \"- name: Fixing ${string}\"\n        echo \"  command: sh -c \\\"${set_command}\\\"\"\n        echo \"  when: ${ansible_value}.rc == 1 and ansible_facts['ansible_system'] == '${os_name}'\"\n        echo \"\"\n      fi\n      actual_value=$( eval \"${get_command}\" )\n      if [ \"${actual_value}\" != \"${correct_value}\" ]; then\n        update_log   \"${log_file}\" \"chuser ${parameter_name}=${correct_value} ${group_name}=${group_value} ${user_name}\"\n        inc_insecure \"Security Policy for \\\"${parameter_name}\\\" is not set to \\\"${correct_value}\\\" for \\\"${user_name}\\\"\"\n        lock_command=\"chuser ${parameter_name}=${correct_value} ${group_name}=${group_value} ${user_name}\"\n        lock_message=\"Security Policy for \\\"${parameter_name}\\\" to \\\"${correct_value}\\\"\"\n        run_lockdown \"${lock_command}\" \"${lock_message}\"\n      else\n        inc_secure   \"Security Policy for \\\"${parameter_name}\\\" is set to \\\"${correct_value}\\\" for \\\"${user_name}\\\"\"\n      fi\n    else\n      log_file=\"${restore_dir}/${log_file}\"\n      if [ -f \"${log_file}\" ]; then\n        previous_value=$( cut -f2 -d= \"${log_file}\" )\n        if [ \"${previous_value}\" != \"${actual_value}\" ]; then\n          restore_message=\"Restoring: Password Policy for \\\"${parameter_name}\\\" to \\\"${previous_value}\\\"\"\n          restore_command=\"sh < ${log_file}\"\n          execute_restore \"${restore_command}\" \"${restore_message}\" \"sudo\"\n        fi\n      fi\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/aix/check_itab.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n# shellcheck disable=SC2086\n\n# check_itab\n#\n# Function to check inittab under AIX\n#.\n\ncheck_itab() {\n  if [ \"${os_name}\" = \"AIX\" ]; then\n    service_name=\"${1}\"\n    correct_value=\"${2}\"\n    print_function \"check_itab\"\n    log_file=\"${service_name}.log\"\n    actual_value=$( lsitab \"${service_name}\" | cut -f1 -d: )\n    if [ \"${correct_value}\" = \"off\" ]; then\n      if [ \"${actual_status}\" != \"${service_name}\" ]; then\n        actual_value=\"off\"\n      fi\n    fi\n    if [ \"${audit_mode}\" != 2 ]; then\n      string=\"Service \\\"${service_name}\\\" is not \\\"${correct_value}\\\"\"\n      check_message  \"${string}\"\n      if [ \"${ansible_mode}\" = 1 ]; then\n        echo \"\"\n        echo \"- name: Checking ${string}\"\n        echo \"  aix_inittab:\"\n        echo \"    namw: ${service_name}\"\n        echo \"    state: ${correct_value}\"\n        echo \"  when: ansible_facts['ansible_system'] == '${os_name}'\"\n        echo \"\"\n      fi\n      if [ \"${actual_value}\" != \"${correct_value}\" ]; then\n        if [ \"${audit_mode}\" = 1 ]; then\n          inc_insecure  \"Service \\\"${service_name}\\\" is \\\"${correct_value}\\\"\"\n          if [ \"${correct_value}\" = \"off\" ]; then\n            fix_message \"rmitab $( lsitab | grep \\\"^${service_name}\\\" )\"\n          else\n            fix_message \"chitab \\\"${correct_value}\\\"\"\n          fi\n        fi\n        if [ \"${audit_mode}\" = 0 ]; then\n          log_file=\"${work_dir}/${log_file}\"\n          lock_message=\"Service \\\"${service_name}\\\" to \\\"${correct_value}\\\"\"\n          if [ \"${correct_value}\" = \"off\" ]; then\n            update_log   \"${log_file}\" \"${actual_value}\"\n            lock_command=\"rmitab ${service_name}\"\n            run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n          else\n            if [ \"${actual_value}\" = \"off\" ]; then\n              update_log   \"${log_file}\" \"off\"\n              lock_command=\"mkitab ${correct_value}\"\n              run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n            else\n              update_log   \"${log_file}\" \"${actual_value}\"\n              lock_command=\"chitab ${correct_value}\"\n              run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n            fi\n          fi\n        fi\n      else\n        inc_secure \"Service \\\"${service_name}\\\" is \\\"${correct_value}\\\"\"\n      fi\n    else\n      log_file=\"${restore_dir}/${log_file}\"\n      if [ -f \"${log_file}\" ]; then\n        previous_value=$( cat \"${log_file}\" )\n        if [ \"${previous_value}\" != \"${actual_value}\" ]; then\n          restore_message=\"Service \\\"${service_name}\\\" to \\\"${previous_value}\\\"\"\n          if [ \"${previous_value}\" = \"off\" ]; then\n            restore_command=\"rmitab ${service_name}\"\n          else\n            if [ \"${actual_status}\" = \"off\" ]; then\n              restore_command=\"mkitab ${service_name} ${previous_value}\"\n            else\n              restore_command=\"chitab ${service_name} ${previous_value}\"\n            fi\n          fi\n          execute_restore \"${restore_command}\" \"${restore_message}\" \"sudo\"\n        fi\n      fi\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/aix/check_lslpp.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_lslpp\n#\n# Check if an AIX package is installed, if so install_check will be be set with\n# name of rpm, otherwise it will be empty\n#.\n\ncheck_lslpp () {\n  package_name=\"${1}\"\n  print_function \"check_lslpp\"\n  if [ \"${os_name}\" = \"AIX\" ]; then\n    lslpp_check=\"lslpp -L |grep \\\"${package_name}\\\"\"\n  fi\n}\n"
  },
  {
    "path": "functions/aix/check_no.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_no\n#\n# Function to check no under AIX\n#.\n\ncheck_no() {\n  if [ \"${os_name}\" = \"AIX\" ]; then\n    parameter_name=\"${1}\"\n    correct_value=\"${2}\"\n    print_function \"check_no\"\n    log_file=\"${parameter_name}.log\"\n    get_command=\"no -a |grep '${parameter_name} ' |cut -f2 -d= |sed 's/ //g' |grep '${correct_value}'\"\n    set_command=\"no -p -o ${parameter_name}=${correct_value}\"\n    actual_value=$( eval \"${get_command}\" )\n    if [ \"${audit_mode}\" != 2 ]; then\n      string=\"Parameter \\\"${parameter_name}\\\" is \\\"${correct_value}\\\"\"\n      check_message  \"${string}\"\n      if [ \"${ansible_mode}\" = 1 ]; then\n        ansible_counter=$((ansible_counter+1))\n        ansible_value=\"check_no_${ansible_counter}\"\n        echo \"\"\n        echo \"- name: Checking ${string}\"\n        echo \"  command: sh -c \\\"${get_command}\\\"\"\n        echo \"  register: ${ansible_value}\"\n        echo \"  failed_when: ${ansible_value} == 1\"\n        echo \"  changed_when: false\"\n        echo \"  ignore_errors: true\"\n        echo \"  when: ansible_facts['ansible_system'] == '${os_name}'\"\n        echo \"\"\n        echo \"- name: Fixing ${string}\"\n        echo \"  command: sh -c \\\"${set_command}\\\"\"\n        echo \"  when: ${ansible_value}.rc == 1 and ansible_facts['ansible_system'] == '${os_name}'\"\n        echo \"\"\n      fi\n      if [ \"${actual_value}\" != \"${correct_value}\" ]; then\n        inc_insecure \"Parameter \\\"${parameter_name}\\\" is not \\\"${correct_value}\\\"\"\n        update_log   \"${log_file}\" \"${actual_value}\"\n        lock_command=\"no -p -o ${parameter_name}=${correct_value}\"\n        lock_message=\"Parameter \\\"${parameter_name}\\\" to \\\"${correct_value}\\\"\"\n        run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n      else\n        inc_secure   \"Parameter \\\"${parameter_name}\\\" is \\\"${correct_value}\\\"\"\n      fi\n    else\n      log_file=\"${restore_dir}/${log_file}\"\n      if [ -f \"${log_file}\" ]; then\n        previous_value=$( cat \"${log_file}\" )\n        if [ \"${previous_value}\" != \"${actual_value}\" ]; then\n          restore_message=\"Parameter \\\"${parameter_name}\\\" to \\\"${previous_value}\\\"\"\n          restore_command=\"no -p -o ${parameter_name}=${previous_value}\"\n          execute_restore \"${restore_command}\" \"${restore_message}\" \"sudo\"\n        fi\n      fi\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/aix/check_pwpolicy.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_pwpolicy\n#\n# Function to check pwpolicy output under OS X\n#.\n\ncheck_pwpolicy() {\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    parameter_name=\"${1}\"\n    correct_value=\"${2}\"\n    print_function \"check_pwpolicy\"\n    log_file=\"${parameter_name}.log\"\n    if [ \"${audit_mode}\" != 2 ]; then\n      string=\"Password Policy for \\\"${parameter_name}\\\" is set to \\\"${correct_value}\\\"\"\n      check_message  \"${string}\"\n      if [ \"${os_version}\" -ge 12 ]; then\n        policy_command=\"pwpolicy -getglobalpolicy |tr ' ' '\\\\\\n' |grep ${parameter_name} |cut -f2 -d=\"\n      else\n        if [ \"${managed_node}\" = \"Error\" ]; then\n          policy_command=\"sudo pwpolicy -n /Local/Default -getglobalpolicy ${parameter_name} 2>&1 |cut -f2 -d=\"\n        else\n          policy_command=\"sudo pwpolicy -n -getglobalpolicy ${parameter_name} 2>&1 |cut -f2 -d=\"\n        fi\n      fi\n      actual_value=$( eval \"${policy_command}\" )\n      if [ \"${actual_value}\" != \"${correct_value}\" ]; then\n        lock_message=\"Password Policy for \\\"${parameter_name}\\\" to \\\"${correct_value}\\\"\"\n        inc_insecure \"Password Policy for \\\"${parameter_name}\\\" is not set to \\\"${correct_value}\\\"\"\n        if [ \"${os_version}\" -ge 12 ]; then\n          lock_command=\"sudo pwpolicy -setglobalpolicy ${parameter_name}=${correct_value}\"\n          update_log   \"${log_file}\" \"${actual_value}\"\n          run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n        else\n          if [ \"${managed_node}\" = \"Error\" ]; then\n            lock_command=\"pwpolicy -n /Local/Default -setglobalpolicy ${parameter_name}=${correct_value}\"\n            update_log   \"${log_file}\" \"${actual_value}\"\n            run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n          else\n            lock_command=\"pwpolicy -n -setglobalpolicy ${parameter_name}=${correct_value}\"\n            update_log   \"${log_file}\" \"${actual_value}\"\n            run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n          fi\n        fi\n        if [ \"${ansible_mode}\" = 1 ]; then\n          ansible_counter=$((ansible_counter+1))\n          ansible_value=\"check_pwpolicy_${ansible_counter}\"\n          echo \"\"\n          echo \"- name: Checking ${string}\"\n          echo \"  command:  sh -c \\\"${policy_command}\\\"\"\n          echo \"  register: ${ansible_value}\"\n          echo \"  failed_when: ${ansible_value} == 1\"\n          echo \"  changed_when: false\"\n          echo \"  ignore_errors: true\"\n          echo \"  when: ansible_facts['ansible_system'] == '${os_name}'\"\n          echo \"\"\n          echo \"- name: Fixing ${string}\"\n          echo \"  command: sh -c \\\"${lock_command}\\\"\"\n          echo \"  when: ${ansible_value}.rc == 1 and ansible_facts['ansible_system'] == '${os_name}'\"\n          echo \"\"\n        fi\n      else\n        if [ \"${audit_mode}\" = 1 ]; then\n          inc_secure \"Password Policy for \\\"${parameter_name}\\\" is set to \\\"${correct_value}\\\"\"\n        fi\n      fi\n    else\n      log_file=\"${restore_dir}/${log_file}\"\n      if [ -f \"${log_file}\" ]; then\n        previous_value=$( cat \"${log_file}\" )\n        restore_message=\"Password Policy for \\\"${parameter_name}\\\" to \\\"${previous_value}\\\"\"\n        if [ \"${previous_value}\" != \"${actual_value}\" ]; then\n          if [ \"${os_version}\" -ge 12 ]; then\n            restore_command=\"pwpolicy -setglobalpolicy ${parameter_name}=${previous_value}\"\n            execute_restore \"${restore_command}\" \"${restore_message}\" \"sudo\"\n          else\n            if [ \"${managed_node}\" = \"Error\" ]; then\n              restore_command=\"pwpolicy -n /Local/Default -setglobalpolicy ${parameter_name}=${previous_value}\"\n              execute_restore \"${restore_command}\" \"${restore_message}\" \"sudo\"\n            else\n              restore_command=\"pwpolicy -n -setglobalpolicy ${parameter_name}=${previous_value}\"\n              execute_restore \"${restore_command}\" \"${restore_message}\" \"sudo\"\n            fi\n          fi\n        fi\n      fi\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/aix/check_rctcp.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_rctcp\n#\n# Function to check rctcp under AIX\n#.\n\ncheck_rctcp() {\n  if [ \"${os_name}\" = \"AIX\" ]; then\n    service_name=\"${1}\"\n    correct_value=\"${2}\"\n    print_function \"check_rctcp\"\n    if [ \"${correct_value}\" = \"off\" ]; then\n      status_value=\"disabled\"\n    else\n      status_value=\"enabled\"\n    fi\n    log_file=\"${service_name}.log\"\n    actual_value=$( lssrc -a | grep \"${service_name} \" | awk '{print $4}' )\n    if [ \"${actual_value}\" = \"active\" ]; then\n      actual_value=\"off\"\n    else\n      actual_value=\"on\"\n    fi\n    if [ \"${audit_mode}\" != 2 ]; then\n      string=\"Service \\\"${service_name}\\\" is \\\"${correct_value}\\\"\"\n      check_message  \"${string}\"\n      if [ \"${ansible_mode}\" = 1 ]; then\n        echo \"\"\n        echo \"- name: Checking ${string}\"\n        echo \"  service:\"\n        echo \"    name: ${service_name}\"\n        echo \"    enabled: ${status_value}\"\n        echo \"  when: ansible_facts['ansible_system'] == '${os_name}'\"\n        echo \"\"\n      fi\n      if [ \"${actual_value}\" != \"${correct_value}\" ]; then\n        if [ \"${audit_mode}\" = 1 ]; then\n          inc_insecure \"Service \\\"${service_name}\\\" is not \\\"${correct_value}\\\"\"\n          if [ \"${correct_value}\" = \"off\" ]; then\n            fix_message \"chrctcp -d ${service_name}\"\n            fix_message \"stopsrc -s ${service_name}\"\n            fix_message \"sed \\\"/${service_name} /s/^/#/g\\\" < /etc/rc.tcpip > ${temp_file}\"\n            fix_message \"cat ${temp_file} > /etc/rc.tcpip\"\n            fix_message \"rm ${temp_file}\"\n          else\n            fix_message \"chrctcp -a ${service_name}\"\n            fix_message \"startsrc -s ${service_name}\"\n            fix_message \"sed \\\"/${service_name} /s/^#.//g\\\" < /etc/rc.tcpip > ${temp_file}\"\n            fix_message \"cat ${temp_file} > /etc/rc.tcpip\"\n            fix_message \"rm ${temp_file}\"\n          fi\n        fi\n        if [ \"${audit_mode}\" = 0 ]; then\n          log_file=\"${work_dir}/${log_file}\"\n          set_message \"Service \\\"${service_name}\\\" to \\\"${correct_value}\\\"\"\n          echo \"${actual_value}\" > \"${log_file}\"\n          if [ \"${correct_value}\" = \"off\" ]; then\n            chrctcp -d \"${service_name}\"\n            stopsrc -s \"${service_name}\"\n            sed \"/${service_name} /s/^/#/g\" < /etc/rc.tcpip > \"${temp_file}\"\n            cat \"${temp_file}\" > /etc/rc.tcpip\n            rm  \"${temp_file}\"\n          else\n            chrctcp -a  \"${service_name}\"\n            startsrc -s \"${service_name}\"\n            sed \"/${service_name} /s/^#.//g\" < /etc/rc.tcpip > \"${temp_file}\"\n            cat \"${temp_file}\" > /etc/rc.tcpip\n            rm  \"${temp_file}\"\n          fi\n        fi\n      else\n        if [ \"${audit_mode}\" = 1 ]; then\n          inc_secure \"Service \\\"${service_name}\\\" is \\\"${correct_value}\\\"\"\n        fi\n      fi\n    else\n      log_file=\"${restore_dir}/${log_file}\"\n      if [ -f \"${log_file}\" ]; then\n        previous_value=$( cat \"${log_file}\" )\n        if [ \"${previous_value}\" != \"${actual_value}\" ]; then\n          restore_message \"Service \\\"${service_name}\\\" to \\\"${previous_value}\\\"\"\n          if [ \"${previous_value}\" = \"off\" ]; then\n            chrctcp -d \"${service_name}\"\n            stopsrc -s \"${service_name}\"\n            sed \"/${service_name} /s/^/#/g\" < /etc/rc.tcpip > \"${temp_file}\"\n            cat \"${temp_file}\" > /etc/rc.tcpip\n            rm  \"${temp_file}\"\n          else\n            chrctcp -a  \"${service_name}\"\n            startsrc -s \"${service_name}\"\n            sed \"/${service_name} /s/^#.//g\" < /etc/rc.tcpip > \"${temp_file}\"\n            cat \"${temp_file}\" > /etc/rc.tcpip\n            rm  \"${temp_file}\"\n          fi\n        fi\n      fi\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/aix/check_subserver.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_subserver\n#\n# Function to check subserver under AIX\n#.\n\ncheck_subserver() {\n  if [ \"${os_name}\" = \"AIX\" ]; then\n    service_name=\"${1}\"\n    protocol_name=\"${2}\"\n    correct_value=\"${3}\"\n    print_function \"check_subserver\"\n    log_file=\"${service_name}.log\"\n    actual_value=$( grep \"${service_name} \" /etc/inetd.conf | grep \"${protocol_name} \" | grep -v \"^#\" | awk \"{print $1}\" )\n    if [ \"${actual_value}\" != \"${service_name}\" ]; then\n      actual_value=\"off\"\n    else\n      actual_value=\"on\"\n    fi\n    if [ \"${audit_mode}\" != 2 ]; then\n      string=\"Service \\\"${service_name}\\\" Protocol \\\"${protocol_name}\\\" is \\\"${correct_value}\\\"\"\n      check_message  \"${string}\"\n      if [ \"${ansible_mode}\" = 1 ]; then\n        echo \"\"\n        echo \"- name: Checking ${string}\"\n        echo \"  service:\"\n        echo \"    name: ${service_name}\"\n        echo \"    enabled: ${enabled}\"\n        echo \"  when: ansible_facts['ansible_system'] == '${os_name}'\"\n        echo \"\"\n      fi\n      if [ \"${actual_value}\" != \"${service_name}\" ]; then\n        if [ \"${audit_mode}\" = 1 ]; then\n          inc_insecure \"Service \\\"${service_name}\\\" Protocol \\\"${protocol_name}\\\" is not \\\"${correct_value}\\\"\"\n          if [ \"${correct_value}\" = \"off\" ]; then\n            fix_command=\"chsubserver -r inetd -C /etc/inetd.conf -d -v \\\"${service_name}\\\" -p \\\"${protocol_name}\\\"\"\n            fix_message \"${fix_command}\"\n          else\n            fix_command=\"chsubserver -r inetd -C /etc/inetd.conf -a -v \\\"${service_name}\\\" -p \\\"${protocol_name}\\\"\"\n            fix_message \"${fix_command}\"\n          fi\n        fi\n        if [ \"${audit_mode}\" = 0 ]; then\n          update_log   \"${log_file}\" \"${actual_value}\"\n          lock_message=\"Service \\\"${service_name}\\\" Protocol \\\"${protocol_name}\\\" to \\\"${correct_value}\\\"\"\n          if [ \"${correct_value}\" = \"off\" ]; then\n            lock_command=\"chsubserver -r inetd -C /etc/inetd.conf -d -v ${service_name} -p ${protocol_name}\"\n            run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n          else\n            lock_command=\"chsubserver -r inetd -C /etc/inetd.conf -a -v ${service_name} -p ${protocol_name}\"\n            run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n          fi\n        fi\n      else\n        inc_secure \"Service \\\"${service_name}\\\" Protocol \\\"${protocol_name}\\\" is \\\"${correct_value}\\\"\"\n      fi\n    else\n      log_file=\"${restore_dir}/${log_file}\"\n      if [ -f \"${log_file}\" ]; then\n        previous_value=$( cat \"${log_file}\" )\n        if [ \"${previous_value}\" != \"${actual_value}\" ]; then\n          restore_message=\"Service \\\"${service_name}\\\" Protocol \\\"${protocol_name}\\\" to \\\"${previous_value}\\\"\"\n          if [ \"${previous_value}\" = \"off\" ]; then\n            restore_command=\"chsubserver -r inetd -C /etc/inetd.conf -d -v ${service_name} -p ${protocol_name}\"\n            execute_restore \"${restore_command}\" \"${restore_message}\" \"sudo\"\n          else\n            restore_command=\"chsubserver -r inetd -C /etc/inetd.conf -a -v ${service_name} -p ${protocol_name}\"\n            execute_restore \"${restore_command}\" \"${restore_message}\" \"sudo\"\n          fi\n        fi\n      fi\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/aix/check_trust.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_trust\n#\n# Function to check trustchk under AIX\n#.\n\ncheck_trust() {\n  if [ \"${os_name}\" = \"AIX\" ]; then\n    parameter_name=\"${1}\"\n    correct_value=\"${2}\"\n    print_function \"check_trust\"\n    log_file=\"trustchk_${parameter_name}.log\"\n    actual_value=$( trustchk -p \"${parameter_name}\" | cut -f2 -d= )\n    policy_command=\"trustchk -p ${parameter_name} | cut -f2 -d= | grep ${correct_value}\"\n    lock_command=\"trustchk -p ${parameter_name}=${correct_value}\"\n    if [ \"${audit_mode}\" != 2 ]; then\n      string=\"Trusted Execution setting for \\\"${parameter_name}\\\" is set to \\\"${correct_value}\\\"\"\n      check_message \"${string}\"\n      if [ \"${actual_value}\" != \"${correct_value}\" ]; then\n        inc_insecure \"Trusted Execution setting for \\\"${parameter_name}\\\" is not set to \\\"${correct_value}\\\"\"\n        update_log   \"${log_file}\" \"trustchk-p ${parameter_name}=${actual_value}\"\n        lock_message=\"Trusted Execution setting for \\\"${parameter_name}\\\" to \\\"${correct_value}\\\"\"\n        run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n      else\n        inc_secure   \"Password Policy for \\\"${parameter_name}\\\" is set to \\\"${correct_value}\\\"\"\n      fi\n      if [ \"${ansible_mode}\" = 1 ]; then\n        ansible_counter=$((ansible_counter+1))\n        ansible_value=\"check_trust_${ansible_counter}\"\n        echo \"\"\n        echo \"- name: Checking ${string}\"\n        echo \"  command:  sh -c \\\"${policy_command}\\\"\"\n        echo \"  register: ${ansible_value}\"\n        echo \"  failed_when: ${ansible_value} == 1\"\n        echo \"  changed_when: false\"\n        echo \"  ignore_errors: true\"\n        echo \"  when: ansible_facts['ansible_system'] == '${os_name}'\"\n        echo \"\"\n        echo \"- name: Fixing ${string}\"\n        echo \"  command: sh -c \\\"${lock_command}\\\"\"\n        echo \"  when: ${ansible_value}.rc == 1 and ansible_facts['ansible_system'] == '${os_name}'\"\n        echo \"\"\n      fi\n    else\n      log_file=\"${restore_dir}/${log_file}\"\n      if [ -f \"${log_file}\" ]; then\n        previous_value=$( cut -f2 -d= \"${log_file}\" )\n        if [ \"${previous_value}\" != \"${actual_value}\" ]; then\n          restore_command=\"sh < ${log_file}\"\n          restore_message=\"Password Policy for \\\"${parameter_name}\\\" to \\\"${previous_value}\\\"\"\n          execute_restore \"${restore_command}\" \"${restore_message}\" \"sudo\"\n        fi\n      fi\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/aws/audit_aws.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# funct_audit_aws\n#\n# Audit AWS\n#.\n\nfunct_audit_aws () {\n  audit_mode=\"${1}\"\n  print_function \"funct_audit_aws\"\n  check_environment\n  check_aws\n  audit_aws_all\n  print_results\n}\n\n# funct_audit_aws\n#\n# Audit AWS REC\n#.\n\nfunct_audit_aws_rec () {\n  audit_mode=\"${1}\"\n  print_function \"funct_audit_aws_rec\"\n  check_environment\n  check_aws\n  audit_aws_rec_all\n  print_results\n}\n\n# audit_aws_all\n#\n# Audit AWS all\n#\n# Run various AWS audit tests\n# \n# This requires the AWS CLI to be installed and configured\n#.\n\naudit_aws_all () {\n  print_function \"audit_aws_all\"\n  audit_aws_iam\n  audit_aws_mfa\n  audit_aws_access_keys\n  audit_aws_creds\n  audit_aws_iam_policies\n  audit_aws_password_policy\n  audit_aws_support_role\n  audit_aws_monitoring\n  audit_aws_logging\n  audit_aws_keys\n  audit_aws_config\n  audit_aws_sns\n  audit_aws_vpcs\n  audit_aws_sgs\n  audit_aws_certs\n  audit_aws_dns\n  audit_aws_ec2\n  audit_aws_es\n  audit_aws_elb\n  audit_aws_s3\n  audit_aws_ses\n  audit_aws_rds\n  audit_aws_cf\n  audit_aws_ec\n  audit_aws_cdn\n  audit_aws_redshift\n  audit_aws_inspector\n}\n"
  },
  {
    "path": "functions/aws/audit_aws_rec_all.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# Audit AWS\n#\n# Run various AWS audit recommended tests\n#\n# This comes from sources like Cloud Conformity\n#\n# https://www.cloudconformity.com/conformity-rules/\n# \n# This requires the AWS CLI to be installed and configured\n#.\n\naudit_aws_rec_all () {\n  print_function \"audit_aws_rec_all\"\n  audit_aws_rec_ec2\n  audit_aws_rec_es\n  audit_aws_rec_dynamodb\n  audit_aws_rec_elb\n  audit_aws_rec_vpcs\n  audit_aws_rec_rds\n  audit_aws_rec_ec\n  audit_aws_rec_monitoring\n  audit_aws_rec_redshift\n  audit_aws_rec_inspector\n}\n\n"
  },
  {
    "path": "functions/aws/check_aws_open_port.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_aws_open_port\n#\n# Check AWS Security Groups for open ports, i.e. CIDR of 0.0.0.0/0\n#\n# This requires the AWS CLI to be installed and configured\n#.\n\ncheck_aws_open_port () {\n  sg=\"${1}\"\n  port=\"${2}\"\n  protocol=\"${3}\"\n  service=\"${4}\"\n  app=\"${5}\"\n  instance=\"${6}\"\n  print_function \"check_aws_open_port\"\n  command=\"aws ec2 describe-security-groups --region \\\"${aws_region}\\\" --group-ids \\\"${sg}\\\" --filters \\\"Name=ip-permission.to-port,Values=${port}\\\" \\\"Name=ip-permission.cidr,Values=0.0.0.0/0\\\" \\\"Name=ip-permission.protocol,Values=${protocol}\\\" --output text\"\n  command_message   \"${command}\"\n  open_port=$( eval \"${command}\" )\n  if [ \"${app}\" = \"none\" ]; then\n    string=\"Security Group \\\"${sg}\\\" does not have service \\\"${service}\\\" on port \\\"${port}\\\" open to the world\"\n  else\n    string=\"Application \\\"${app}\\\" with instance \\\"${instance}\\\" with Security Group \\\"${sg}\\\" does not have \\\"${service}\\\" on port \\\"${port}\\\" open to the world\"\n  fi\n  check_message \"${string}\"\n  if [ ! \"${open_port}\" ]; then\n    inc_secure  \"${string}\"\n  else\n    if [ \"${app}\" = \"none\" ]; then\n      string=\"Security Group \\\"${sg}\\\" has service \\\"${service}\\\" on port \\\"${port}\\\" open to the world\"\n    else\n      string=\"Application \\\"$app\\\" with instance \\\"${instance}\\\" with Security Group \\\"${sg}\\\" has \\\"${service}\\\" on port \\\"${port}\\\" open to the world\"\n    fi\n    inc_insecure \"${string}\"\n    lock_command=\"aws ec2 revoke-security-group-ingress --region ${aws_region} --group-name ${sg} --protocol ${protocol} --port ${port} --cidr 0.0.0.0/0\"\n    lock_message=\"${string}\"\n    run_lockdown \"${lock_command}\" \"${lock_message}\" \n  fi\n}\n"
  },
  {
    "path": "functions/aws/check_aws_password_policy.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_aws_password_policy\n#\n# Check AWS Password Policy\n#\n# This requires the AWS CLI to be installed and configured\n#.\n\ncheck_aws_password_policy () {\n  param=\"${1}\"\n  value=\"${2}\"\n  switch=\"${3}\"\n  print_function \"check_aws_password_policy\"\n  command=\"aws iam get-account-password-policy 2> /dev/null | grep \\\"${param}\\\"\"\n  command_message \"${command}\"\n  policy=$( eval  \"${command}\" )\n  cli_fix=\"aws iam update-account-password-policy ${switch}\"\n  command=\"grep \\\"${param}\\\" \\\"${policy}\\\" | cut -f2 -d: | sed \\\"s/ //g\\\" | sed \\\"s/,//g\\\"\"\n  command_message \"${command}\"\n  check=$( eval   \"${command}\" )\n  secure_string=\"The password policy has \\\"${param}\\\" set to \\\"${value}\\\"\"\n  insecure_string=\"The password policy does not has \\\"${param}\\\" set to \\\"${value}\\\"\"\n  verbose_message \"${secure_string}\" \"check\"\n  if [ \"${check}\" = \"${value}\" ]; then\n    inc_secure   \"${secure_string}\"\n  else\n    inc_insecure \"${insecure_string}\"\n    lock_command=\"${cli_fix}\"\n    lock_message=\"IAM Account password policy parameter \\\"${param}\\\" to \\\"${value}\\\"\"\n    run_lockdown \"${lock_command}\" \"${lock_message}\"\n  fi\n}"
  },
  {
    "path": "functions/azure/compute/batch/check_azure_batch_pool_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_batch_pool_value\n#\n# Check Azure Batch Pool value\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_batch_pool_value () {\n  description=\"${1}\"\n  pool_id=\"${2}\"\n  query_string=\"${4}\"\n  function=\"${5}\"\n  correct_value=\"${6}\"\n  set_name=\"${7}\"\n  set_value=\"${8}\"\n  print_function \"check_azure_batch_pool_value\"\n  if [ \"${set_value}\" = \"\" ]; then\n    set_value=\"${correct_value}\"\n  fi\n  check_message \"${description} for Batch Pool \\\"${pool_id}\\\" has parameter \\\"${query_string}\\\" \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n  command=\"az batch pool show --id ${pool_id} --query '${query_string}' --output tsv 2> /dev/null\"\n  command_message      \"${command}\"\n  actual_value=$( eval \"${command}\" )\n  if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n    secure_message     \"${description} for Batch Pool \\\"${pool_id}\\\" has parameter \\\"${query_string}\\\" \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n  else\n    insecure_message   \"${description} for Batch Pool \\\"${pool_id}\\\" has parameter \\\"${query_string}\\\" \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    if [ ! \"${set_name}\" = \"\" ]; then\n      fix_message \"az batch pool set --id \\\"${pool_id}\\\" ${set_name} \\\"${set_value}\\\"\"\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/azure/compute/batch/check_azure_batch_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_batch_value\n#\n# Check Azure Batch value\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_batch_value () {\n  description=\"${1}\"\n  batch_name=\"${2}\"\n  resource_group=\"${3}\"\n  query_string=\"${4}\"\n  function=\"${5}\"\n  correct_value=\"${6}\"\n  set_name=\"${7}\"\n  set_value=\"${8}\"\n  print_function \"check_azure_batch_value\"\n  if [ \"${set_value}\" = \"\" ]; then\n    set_value=\"${correct_value}\"\n  fi\n  check_message \"${description} for Batch Account \\\"${batch_name}\\\" in resource group \\\"${resource_group}\\\" has parameter \\\"${query_string}\\\" \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n  command=\"az batch account show --name ${batch_name} --resource-group ${resource_group} --query '${query_string}' --output tsv 2> /dev/null\"\n  command_message      \"${command}\"\n  actual_value=$( eval \"${command}\" )\n  if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n    secure_message     \"${description} for Batch Account \\\"${batch_name}\\\" in resource group \\\"${resource_group}\\\" has parameter \\\"${query_string}\\\" \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n  else\n    insecure_message   \"${description} for Batch Account \\\"${batch_name}\\\" in resource group \\\"${resource_group}\\\" has parameter \\\"${query_string}\\\" \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    if [ ! \"${set_name}\" = \"\" ]; then\n      fix_message \"az batch account set --name \\\"${batch_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${set_value}\\\"\"\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/azure/compute/container/check_azure_container_instance_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_container_instance_value\n#\n# Check Azure Container Instance value\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_container_instance_value () {\n  description=\"${1}\"\n  container_name=\"${2}\"\n  resource_group=\"${3}\"\n  query_string=\"${4}\"\n  function=\"${5}\"\n  correct_value=\"${6}\"\n  print_function \"check_azure_container_instance_value\"\n  check_message  \"${description} for Container Instance \\\"${container_name}\\\" in resource group \\\"${resource_group}\\\" has parameter \\\"${query_string}\\\" \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n  command=\"az container show --name ${container_name} --resource-group ${resource_group} --query '${query_string}' --output tsv 2> /dev/null\"\n  command_message      \"${command}\"\n  actual_value=$( eval \"${command}\" )\n  if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n    secure_message     \"${description} for Container Instance \\\"${container_name}\\\" in resource group \\\"${resource_group}\\\" has parameter \\\"${query_string}\\\" \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n  else\n    insecure_message   \"${description} for Container Instance \\\"${container_name}\\\" in resource group \\\"${resource_group}\\\" has parameter \\\"${query_string}\\\" \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    if [ ! \"${set_name}\" = \"\" ]; then\n      case \"${set_name}\" in\n        \"--\"*)\n          fix_message \"az container update --name \\\"${container_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${correct_value}\\\"\"\n          ;;\n        *)\n          fix_message \"az container update --name \\\"${container_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"${correct_value}\\\"\"\n          ;;\n      esac\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/azure/compute/function/check_azure_function_app_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_function_app_value\n#\n# Check Azure Function App value\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_function_app_value () {\n  description=\"${1}\"\n  app_id=\"${2}\"\n  resource_group=\"${3}\"\n  sub_function=\"${4}\"\n  resource_type=\"${5}\"\n  resource_name=\"${6}\"\n  query_string=\"${7}\"\n  function=\"${8}\"\n  correct_value=\"${9}\"\n  set_name=\"${10}\"\n  set_value=\"${11}\"\n  print_function \"check_azure_function_app_value\"\n  if [ \"${set_value}\" = \"\" ]; then\n    set_value=\"${correct_value}\"\n  fi\n  app_name=$( basename \"${app_id}\" )\n  check_message \"Azure Function App ${description} for app \\\"${app_name}\\\" with resource group \\\"${resource_group}\\\" and parameter \\\"${query_string}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n  if [ \"${sub_function}\" = \"auth\" ]; then\n    command=\"az webapp auth show --name \\\"${app_name}\\\" --resource-group \\\"${resource_group}\\\" --query \\\"${query_string}\\\" --output tsv 2> /dev/null\"\n  else\n    command=\"az functionapp show --id \\\"${app_id}\\\" --query \\\"${query_string}\\\" --output tsv 2> /dev/null\"\n  fi\n  command_message      \"${command}\"\n  actual_value=$( eval \"${command}\" )\n  if [ \"${function}\" = \"eq\" ]; then\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_secure    \"Azure Function App ${description} for app \\\"${app_name}\\\" with resource group \\\"${resource_group}\\\" and parameter \\\"${query_string}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    else\n      inc_insecure  \"Azure Function App ${description} for app \\\"${app_name}\\\" with resource group \\\"${resource_group}\\\" and parameter \\\"${query_string}\\\" is not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      if [ \"${query_string}\" = \"virtualNetworkSubnetId\" ]; then\n        fix_message \"az functionapp vnet-integration add --resource-group <resource-group-name> --name <app-name> --vnet <virtual-network-name> --subnet <subnet-name>\" \n      fi\n      if [ ! \"${set_name}\" = \"\" ]; then\n        case \"${set_name}\" in\n          \"--\"*)\n            case \"${resource_type}\" in\n              \"Microsoft.Web/sites\")\n                fix_message \"az resource update --resource-group \\\"${resource_group}\\\" --name \\\"${resource_name}\\\" --namespace \\\"${namespace_name}\\\" --resource-type \\\"${resource_type}\\\" --parent \\\"sites/${app_name}\\\" ${set_name} \\\"${set_value}\\\"\"\n                ;;\n              \"auth\")\n                fix_message \"az webapp auth update --name \\\"${app_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${set_value}\\\"\"\n                ;;\n              \"identity\")\n                fix_message \"az functionapp identity assign --name \\\"${app_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${set_value}\\\"\"\n                ;;\n              *)\n                fix_message \"az functionapp config set --name \\\"${app_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${set_value}\\\"\"\n                ;;\n            esac\n            ;;\n          *)\n            case \"${resource_type}\" in\n              \"Microsoft.Web/sites\")\n                fix_message \"az resource update --resource-group \\\"${resource_group}\\\" --name \\\"${resource_name}\\\" --namespace \\\"${namespace_name}\\\" --resource-type \\\"${resource_type}\\\" --parent \\\"sites/${app_name}\\\" --set \\\"${set_name}\\\"=\\\"${set_value}\\\"\"\n                ;;\n              \"auth\")\n                fix_message \"az webapp auth update --name \\\"${app_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"${set_value}\\\"\"\n                ;;\n              \"identity\")\n                fix_message \"az functionapp identity assign --name \\\"${app_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"${set_value}\\\"\"\n                ;;\n              *)\n                fix_message \"az functionapp config set --name \\\"${app_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"${set_value}\\\"\"\n                ;;\n            esac\n            ;;\n        esac\n      fi\n    fi\n  else\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_insecure \"Azure Function App ${description} for app \\\"${app_name}\\\" with resource group \\\"${resource_group}\\\" and parameter \\\"${query_string}\\\" is not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      if [ \"${query_string}\" = \"virtualNetworkSubnetId\" ]; then\n        fix_message \"az functionapp vnet-integration add --resource-group <resource-group-name> --name <app-name> --vnet <virtual-network-name> --subnet <subnet-name>\" \n      fi\n      if [ ! \"${set_name}\" = \"\" ]; then\n        case \"${set_name}\" in\n          \"--\"*)\n            case \"${resource_type}\" in\n              \"Microsoft.Web/sites\")\n                fix_message \"az resource update --resource-group \\\"${resource_group}\\\" --name \\\"${resource_name}\\\" --namespace \\\"${namespace_name}\\\" --resource-type \\\"${resource_type}\\\" --parent \\\"sites/${app_name}\\\" ${set_name} \\\"${set_value}\\\"\"\n                ;;\n              \"auth\")\n                fix_message \"az webapp auth update --name \\\"${app_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${set_value}\\\"\"\n                ;;\n              \"identity\")\n                fix_message \"az functionapp identity assign --name \\\"${app_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${set_value}\\\"\"\n                ;;\n              *)\n                fix_message \"az functionapp config set --name \\\"${app_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${set_value}\\\"\"\n                ;;\n            esac\n            ;;\n          *)\n            case \"${resource_type}\" in\n              \"Microsoft.Web/sites\")\n                fix_message \"az resource update --resource-group \\\"${resource_group}\\\" --name \\\"${resource_name}\\\" --namespace \\\"${namespace_name}\\\" --resource-type \\\"${resource_type}\\\" --parent \\\"sites/${app_name}\\\" --set \\\"${set_name}\\\"=\\\"${set_value}\\\"\"\n                ;;\n              \"auth\")\n                fix_message \"az webapp auth update --name \\\"${app_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"${set_value}\\\"\"\n                ;;\n              \"identity\")\n                fix_message \"az functionapp identity assign --name \\\"${app_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"${set_value}\\\"\"\n                ;;\n              *)\n                fix_message \"az functionapp config set --name \\\"${app_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"${set_value}\\\"\"\n                ;;\n            esac\n            ;;\n        esac\n      fi\n    else\n      inc_secure \"Azure App Service App ${description} for app \\\"${app_name}\\\" with resource group \\\"${resource_group}\\\" and parameter \\\"${query_string}\\\" is \\\"${function}\\\" to \\\"${set_value}\\\"\"\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/azure/compute/function/check_azure_function_deployment_slot_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_function_deployment_slot_value\n#\n# Check Azure Function Deployment Slot value\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_function_deployment_slot_value () {\n  description=\"${1}\"\n  slot_id=\"${2}\"\n  app_name=\"${3}\"\n  resource_group=\"${4}\"\n  resource_type=\"${5}\"\n  resource_name=\"${6}\"\n  namespace_name=\"${7}\"\n  query_string=\"${8}\"\n  function=\"${9}\"\n  correct_value=\"${10}\"\n  set_name=\"${11}\"\n  set_value=\"${12}\"\n  print_function \"check_azure_function_deployment_slot_value\"\n  if [ \"${set_value}\" = \"\" ]; then\n    set_value=\"${correct_value}\"\n  fi\n  slot_name=$( basename \"${slot_id}\" )\n  check_message \"Azure Function Deployment Slot ${description} for app \\\"${app_name}\\\" with resource group \\\"${resource_group}\\\" and parameter \\\"${query_string}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n  command=\"az resource show --name \\\"${resource_name}\\\" --resource-group \\\"${resource_group}\\\" --namespace \\\"${namespace_name}\\\" --resource-type \\\"${resource_type}\\\" --parent \\\"sites/${app_name}/slots/${slot_name}\\\" --query \\\"${query_string}\\\" --output tsv 2> /dev/null\"\n  command_message      \"${command}\"\n  actual_value=$( eval \"${command}\" )\n  if [ \"${function}\" = \"eq\" ]; then\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_secure    \"Azure Function Deployment Slot ${description} for app \\\"${app_name}\\\" with resource group \\\"${resource_group}\\\" and parameter \\\"${query_string}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    else\n      inc_insecure  \"Azure Function Deployment Slot ${description} for app \\\"${app_name}\\\" with resource group \\\"${resource_group}\\\" and parameter \\\"${query_string}\\\" is not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      if [ \"${query_string}\" = \"virtualNetworkSubnetId\" ]; then\n        fix_message \"az webapp vnet-integration add --resource-group <resource-group-name> --name <app-name> --vnet <virtual-network-name> --subnet <subnet-name>\" \n      fi\n      if [ ! \"${set_name}\" = \"\" ]; then\n        case \"${set_name}\" in\n          \"--\"*)\n            case \"${resource_type}\" in\n              \"Microsoft.Web/sites\")\n                fix_message \"az resource update --name \\\"${resource_name}\\\" --resource-group \\\"${resource_group}\\\" --namespace \\\"${namespace_name}\\\" --resource-type \\\"${resource_type}\\\" --parent \\\"sites/${app_name}/slots/${slot_name}\\\" ${set_name} \\\"${set_value}\\\"\"\n                ;;\n              \"auth\")\n                fix_message \"az webapp ${resource_type} update --name \\\"${app_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${set_value}\\\"\"\n                ;;\n              \"identity\")\n                fix_message \"az webapp ${resource_type} assign --name \\\"${app_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${set_value}\\\"\"\n                ;;\n              *)\n                fix_message \"az webapp update --name \\\"${app_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${set_value}\\\"\"\n                ;;\n            esac\n            ;;\n          *)\n            case \"${resource_type}\" in\n              \"Microsoft.Web/sites\")\n                fix_message \"az resource update --name \\\"${resource_name}\\\" --resource-group \\\"${resource_group}\\\" --namespace \\\"${namespace_name}\\\" --resource-type \\\"${resource_type}\\\" --parent \\\"sites/${app_name}/slots/${slot_name}\\\" --set \\\"${set_name}\\\"=\\\"${set_value}\\\"\"\n                ;;\n              \"auth\")\n                fix_message \"az webapp ${resource_type} update --name \\\"${app_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"${set_value}\\\"\"\n                ;;\n              \"identity\")\n                fix_message \"az webapp ${resource_type} assign --name \\\"${app_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"${set_value}\\\"\"\n                ;;\n              *)\n                fix_message \"az webapp update --name \\\"${app_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"${set_value}\\\"\"\n                ;;\n            esac\n            ;;\n        esac\n      fi\n    fi\n  else\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_insecure  \"Azure App Service Deployment Slot ${description} for app \\\"${app_name}\\\" with resource group \\\"${resource_group}\\\" and parameter \\\"${query_string}\\\" is not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      if [ \"${query_string}\" = \"virtualNetworkSubnetId\" ]; then\n        fix_message \"az webapp vnet-integration add --resource-group <resource-group-name> --name <app-name> --vnet <virtual-network-name> --subnet <subnet-name>\" \n      fi\n      if [ ! \"${set_name}\" = \"\" ]; then\n        case \"${set_name}\" in\n          \"--\"*)\n            case \"${resource_type}\" in\n              \"Microsoft.Web/sites\")\n                fix_message \"az resource update --name \\\"${resource_name}\\\" --resource-group \\\"${resource_group}\\\" --namespace \\\"${namespace_name}\\\" --resource-type \\\"${resource_type}\\\" --parent \\\"sites/${app_name}/slots/${slot_name}\\\" ${set_name} \\\"${set_value}\\\"\"\n                ;;\n              \"auth\")\n                fix_message \"az webapp ${resource_type} update --name \\\"${app_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${set_value}\\\"\"\n                ;;\n              \"identity\")\n                fix_message \"az webapp ${resource_type} assign --name \\\"${app_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${set_value}\\\"\"\n                ;;\n              *)\n                fix_message \"az webapp update --name \\\"${app_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${set_value}\\\"\"\n                ;;\n            esac\n            ;;\n          *)\n            case \"${resource_type}\" in\n              \"Microsoft.Web/sites\")\n                fix_message \"az resource update --name \\\"${resource_name}\\\" --resource-group \\\"${resource_group}\\\" --namespace \\\"${namespace_name}\\\" --resource-type \\\"${resource_type}\\\" --parent \\\"sites/${app_name}/slots/${slot_name}\\\" --set \\\"${set_name}\\\"=\\\"${set_value}\\\"\"\n                ;;\n              \"auth\")\n                fix_message \"az webapp ${resource_type} update --name \\\"${app_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"${set_value}\\\"\"\n                ;;\n              \"identity\")\n                fix_message \"az webapp ${resource_type} assign --name \\\"${app_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"${set_value}\\\"\"\n                ;;\n              *)\n                fix_message \"az webapp update --name \\\"${app_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"${set_value}\\\"\"\n                ;;\n            esac\n            ;;\n        esac\n      fi\n    else\n      inc_secure \"Azure App Service App ${description} for app \\\"${app_name}\\\" with resource group \\\"${resource_group}\\\" and parameter \\\"${query_string}\\\" is \\\"${function}\\\" to \\\"${set_value}\\\"\"\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/azure/compute/vm/check_azure_vm_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_vm_value\n#\n# Check Azure VM value\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_vm_value () {\n  description=\"${1}\"\n  vm_name=\"${2}\"\n  resource_group=\"${3}\"\n  parameter_name=\"${4}\"\n  function=\"${5}\"\n  correct_value=\"${6}\"\n  print_function \"check_azure_vnet_value\"\n  check_message  \"Azure VM \\\"${vm_name}\\\" in Resource Group \\\"${resource_group}\\\" has \\\"${parameter_name}\\\" ${function} to \\\"${correct_value}\\\"\"\n  command=\"az vm show --name \\\"${vm_name}\\\" --resource-group \\\"${resource_group}\\\" --query \\\"${parameter_name}\\\" --output tsv 2> /dev/null\"\n  command_message      \"${command}\"\n  actual_value=$( eval \"${command}\" )\n  if [ \"${function}\" = \"ne\" ]; then\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_insecure \"Azure VM \\\"${vm_name}\\\" in Resource Group \\\"${resource_group}\\\" does not have \\\"${parameter_name}\\\" ${function} to \\\"${correct_value}\\\"\"\n    else\n      inc_secure   \"Azure VM \\\"${vm_name}\\\" in Resource Group \\\"${resource_group}\\\" has \\\"${parameter_name}\\\" ${function} to \\\"${correct_value}\\\"\"\n    fi\n  else\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_secure   \"Azure VM \\\"${vm_name}\\\" in Resource Group \\\"${resource_group}\\\" has \\\"${parameter_name}\\\" ${function} to \\\"${correct_value}\\\"\"\n    else\n      inc_insecure \"Azure VM \\\"${vm_name}\\\" in Resource Group \\\"${resource_group}\\\" does not have \\\"${parameter_name}\\\" ${function} to \\\"${correct_value}\\\"\"\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/azure/compute/webapp/check_azure_app_service_app_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_app_service_app_value\n#\n# Check Azure App Service App value\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_app_service_app_value () {\n  description=\"${1}\"\n  app_id=\"${2}\"\n  app_name=\"${3}\"\n  resource_group=\"${4}\"\n  resource_type=\"${5}\"\n  query_string=\"${6}\"\n  function=\"${7}\"\n  correct_value=\"${8}\"\n  set_name=\"${9}\"\n  set_value=\"${10}\"\n  print_function \"check_azure_app_service_app_value\"\n  if [ \"${set_value}\" = \"\" ]; then\n    set_value=\"${correct_value}\"\n  fi\n  check_message  \"Azure App Service App ${description} for app \\\"${app_name}\\\" with resource group \\\"${resource_group}\\\" and parameter \\\"${query_string}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n  case \"${resource_type}\" in\n    \"auth|identity\")\n      command=\"az webapp ${resource_type} show --id \\\"${app_id}\\\" --query \\\"${query_string}\\\" --output tsv 2> /dev/null\"\n      ;;\n    *)\n      command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"${query_string}\\\" --output tsv 2> /dev/null\"\n      ;;\n  esac\n  command_message      \"${command}\"\n  actual_value=$( eval \"${command}\" )\n  if [ \"${actual_value}\" = \"\" ]; then\n    case \"${query_string}\" in\n      *Version)\n        inc_secure \"Azure App Service App ${description} for app \\\"${app_name}\\\" with resource group \\\"${resource_group}\\\" and parameter \\\"${query_string}\\\" is not set\"\n        return\n        ;;\n    esac\n  fi  \n  if [ \"${function}\" = \"eq\" ]; then\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_secure   \"Azure App Service App ${description} for app \\\"${app_name}\\\" with resource group \\\"${resource_group}\\\" and parameter \\\"${query_string}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    else\n      inc_insecure \"Azure App Service App ${description} for app \\\"${app_name}\\\" with resource group \\\"${resource_group}\\\" and parameter \\\"${query_string}\\\" is \\\"${actual_value}\\\" and not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      if [ \"${query_string}\" = \"virtualNetworkSubnetId\" ]; then\n        fix_message \"az webapp vnet-integration add --resource-group <resource-group-name> --name <app-name> --vnet <virtual-network-name> --subnet <subnet-name>\"\n      fi\n      if [ ! \"${set_name}\" = \"\" ]; then\n        case \"${set_name}\" in\n          \"--\"*)\n            case \"${resource_type}\" in\n              \"Microsoft.Web/sites\")\n                fix_message \"az resource update --resource-type \\\"${resource_type}\\\" --name \\\"${app_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${set_value}\\\"\"\n                ;;\n              \"auth\")\n                fix_message \"az webapp ${resource_type} update --id \\\"${app_id}\\\" ${set_name} \\\"${set_value}\\\"\"\n                ;;\n              \"identity\")\n                fix_message \"az webapp ${resource_type} assign --id \\\"${app_id}\\\" ${set_name} \\\"${set_value}\\\"\"\n                ;;\n              *)\n                fix_message \"az webapp update --name \\\"${app_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${set_value}\\\"\"\n                ;;\n            esac\n            ;;\n          *)\n            case \"${resource_type}\" in\n              \"Microsoft.Web/sites\")\n                fix_message \"az resource update --resource-type \\\"${resource_type}\\\" --name \\\"${app_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"${set_value}\\\"\"\n                ;;\n              \"auth\")\n                fix_message \"az webapp ${resource_type} update --id \\\"${app_id}\\\" --set \\\"${set_name}\\\"=\\\"${set_value}\\\"\"\n                ;;\n              \"identity\")\n                fix_message \"az webapp ${resource_type} assign --id \\\"${app_id}\\\" --set \\\"${set_name}\\\"=\\\"${set_value}\\\"\"\n                ;;\n              *)\n                fix_message \"az webapp update --name \\\"${app_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"${set_value}\\\"\"\n                ;;\n            esac\n            ;;\n        esac\n      fi\n    fi\n  else\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_insecure \"Azure App Service App ${description} for app \\\"${app_name}\\\" with resource group \\\"${resource_group}\\\" and parameter \\\"${query_string}\\\" is not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      if [ \"${query_string}\" = \"virtualNetworkSubnetId\" ]; then\n        fix_message \"az webapp vnet-integration add --resource-group <resource-group-name> --name <app-name> --vnet <virtual-network-name> --subnet <subnet-name>\"\n      fi\n      if [ ! \"${set_name}\" = \"\" ]; then\n        case \"${set_name}\" in\n          \"--\"*)\n            case \"${resource_type}\" in\n              \"Microsoft.Web/sites\")\n                fix_message \"az resource update --resource-type \\\"${resource_type}\\\" --name \\\"${app_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${set_value}\\\"\"\n                ;;\n              \"auth\")\n                fix_message \"az webapp ${resource_type} update --id \\\"${app_id}\\\" ${set_name} \\\"${set_value}\\\"\"\n                ;;\n              \"identity\")\n                fix_message \"az webapp ${resource_type} assign --id \\\"${app_id}\\\" ${set_name} \\\"${set_value}\\\"\"\n                ;;\n              *)\n                fix_message \"az webapp update --name \\\"${app_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${set_value}\\\"\"\n                ;;\n            esac\n            ;;\n          *)\n            case \"${resource_type}\" in\n              \"Microsoft.Web/sites\")\n                fix_message \"az resource update --resource-type \\\"${resource_type}\\\" --name \\\"${app_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"${set_value}\\\"\"\n                ;;\n              \"auth\")\n                fix_message \"az webapp ${resource_type} update --id \\\"${app_id}\\\" --set \\\"${set_name}\\\"=\\\"${set_value}\\\"\"\n                ;;\n              \"identity\")\n                fix_message \"az webapp ${resource_type} assign --id \\\"${app_id}\\\" --set \\\"${set_name}\\\"=\\\"${set_value}\\\"\"\n                ;;\n              *)\n                fix_message \"az webapp update --name \\\"${app_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"${set_value}\\\"\"\n                ;;\n            esac\n            ;;\n        esac\n      fi\n    else\n      inc_secure \"Azure App Service App ${description} for app \\\"${app_name}\\\" with resource group \\\"${resource_group}\\\" and parameter \\\"${query_string}\\\" is \\\"${function}\\\" to \\\"${set_value}\\\"\"\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/azure/compute/webapp/check_azure_app_service_ase_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_app_service_ase_value\n#\n# Check Azure App Service ASE value\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_app_service_ase_value () {\n  description=\"${1}\"\n  ase_name=\"${2}\"\n  sub_name=\"${3}\"\n  parameter_name=\"${4}\"\n  function=\"${5}\"\n  correct_value=\"${6}\"\n  print_function \"check_azure_app_service_ase_value\"\n  check_message  \"${description} for App Service ASE ${ase_name} parameter ${parameter_name} is ${function} to ${correct_value}\"\n  if [ -z \"${sub_name}\" ]; then\n    command=\"az appservice ase show --name ${ase_name} --query \\\"${parameter_name}\\\" --output tsv\"\n    command_message      \"${command}\"\n    actual_value=$( eval \"${command}\" 2> /dev/null )\n  else\n    if [ \"${function}\" = \"has\" ]; then\n      command=\"az appservice ase show --name ${ase_name} --query \\\"[?contains(${sub_name}.name, '${parameter_name}')]\\\" --query \\\"value\\\" --output tsv | grep \\\"${correct_value}\\\"\"\n      command_message      \"${command}\"\n      actual_value=$( eval \"${command}\" 2> /dev/null )\n      if [ -z \"${actual_value}\" ]; then\n        actual_value=\"${correct_value}\"\n      fi\n    else\n      command=\"az appservice ase show --name ${ase_name} --query \\\"[?contains(${sub_name}.name, '${parameter_name}')]\\\" --query \\\"value\\\" --output tsv\"\n      command_message      \"${command}\"\n      actual_value=$( eval \"${command}\" 2> /dev/null )\n    fi\n  fi\n  if [ \"${function}\" = \"eq\" ]; then\n    if [ \"${actual_value}\" != \"${correct_value}\" ]; then\n      insecure_message \"${description} for App Service ASE ${ase_name} parameter ${parameter_name} is not ${correct_value}\"\n    else\n      secure_message   \"${description} for App Service ASE ${ase_name} parameter ${parameter_name} is ${correct_value}\"\n    fi\n  else\n    if [ \"${function}\" = \"ne\" ]; then\n      if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n        insecure_message \"${description} for App Service ASE ${ase_name} parameter ${parameter_name} is ${correct_value}\"\n      else\n        secure_message   \"${description} for App Service ASE ${ase_name} parameter ${parameter_name} is not ${correct_value}\"\n      fi\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/azure/compute/webapp/check_azure_app_service_deployment_slot_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_app_service_app_value\n#\n# Check Azure App Service App value\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_app_service_app_value () {\n  description=\"${1}\"\n  slot_id=\"${2}\"\n  app_name=\"${3}\"\n  resource_group=\"${4}\"\n  resource_type=\"${5}\"\n  resource_name=\"${6}\"\n  namespace_name=\"${7}\"\n  query_string=\"${8}\"\n  function=\"${9}\"\n  correct_value=\"${10}\"\n  set_name=\"${11}\"\n  set_value=\"${12}\"\n  print_function \"check_azure_app_service_app_value\"\n  if [ \"${set_value}\" = \"\" ]; then\n    set_value=\"${correct_value}\"\n  fi\n  slot_name=$( basename \"${slot_id}\" )\n  check_message \"Azure App Service Deployment Slot ${description} for app \\\"${app_name}\\\" with resource group \\\"${resource_group}\\\" and parameter \\\"${query_string}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n  command=\"az resource show --name \\\"${resource_name}\\\" --resource-group \\\"${resource_group}\\\" --namespace \\\"${namespace_name}\\\" --resource-type \\\"${resource_type}\\\" --parent \\\"sites/${app_name}/slots/${slot_name}\\\" --query \\\"${query_string}\\\" --output tsv 2> /dev/null\"\n  command_message      \"${command}\"\n  actual_value=$( eval \"${command}\" )\n  if [ \"${function}\" = \"eq\" ]; then\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_secure    \"Azure App Service Deployment Slot ${description} for app \\\"${app_name}\\\" with resource group \\\"${resource_group}\\\" and parameter \\\"${query_string}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    else\n      inc_insecure  \"Azure App Service Deployment Slot ${description} for app \\\"${app_name}\\\" with resource group \\\"${resource_group}\\\" and parameter \\\"${query_string}\\\" is not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      if [ \"${query_string}\" = \"virtualNetworkSubnetId\" ]; then\n        fix_message \"az webapp vnet-integration add --resource-group <resource-group-name> --name <app-name> --vnet <virtual-network-name> --subnet <subnet-name>\"\n      fi\n      if [ ! \"${set_name}\" = \"\" ]; then\n        case \"${set_name}\" in\n          \"--\"*)\n            case \"${resource_type}\" in\n              \"Microsoft.Web/sites\")\n                fix_message \"az resource update --name \\\"${resource_name}\\\" --resource-group \\\"${resource_group}\\\" --namespace \\\"${namespace_name}\\\" --resource-type \\\"${resource_type}\\\" --parent \\\"sites/${app_name}/slots/${slot_name}\\\" ${set_name} \\\"${set_value}\\\"\"\n                ;;\n              \"auth\")\n                fix_message \"az webapp ${resource_type} update --name \\\"${app_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${set_value}\\\"\"\n                ;;\n              \"identity\")\n                fix_message \"az webapp ${resource_type} assign --name \\\"${app_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${set_value}\\\"\"\n                ;;\n              *)\n                fix_message \"az webapp update --name \\\"${app_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${set_value}\\\"\"\n                ;;\n            esac\n            ;;\n          *)\n            case \"${resource_type}\" in\n              \"Microsoft.Web/sites\")\n                fix_message \"az resource update --name \\\"${resource_name}\\\" --resource-group \\\"${resource_group}\\\" --namespace \\\"${namespace_name}\\\" --resource-type \\\"${resource_type}\\\" --parent \\\"sites/${app_name}/slots/${slot_name}\\\" --set \\\"${set_name}\\\"=\\\"${set_value}\\\"\"\n                ;;\n              \"auth\")\n                fix_message \"az webapp ${resource_type} update --name \\\"${app_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"${set_value}\\\"\"\n                ;;\n              \"identity\")\n                fix_message \"az webapp ${resource_type} assign --name \\\"${app_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"${set_value}\\\"\"\n                ;;\n              *)\n                fix_message \"az webapp update --name \\\"${app_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"${set_value}\\\"\"\n                ;;\n            esac\n            ;;\n        esac\n      fi\n    fi\n  else\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_insecure \"Azure App Service Deployment Slot ${description} for app \\\"${app_name}\\\" with resource group \\\"${resource_group}\\\" and parameter \\\"${query_string}\\\" is not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      if [ \"${query_string}\" = \"virtualNetworkSubnetId\" ]; then\n        fix_message \"az webapp vnet-integration add --resource-group <resource-group-name> --name <app-name> --vnet <virtual-network-name> --subnet <subnet-name>\"\n      fi\n      if [ ! \"${set_name}\" = \"\" ]; then\n        case \"${set_name}\" in\n          \"--\"*)\n            case \"${resource_type}\" in\n              \"Microsoft.Web/sites\")\n                fix_message \"az resource update --name \\\"${resource_name}\\\" --resource-group \\\"${resource_group}\\\" --namespace \\\"${namespace_name}\\\" --resource-type \\\"${resource_type}\\\" --parent \\\"sites/${app_name}/slots/${slot_name}\\\" ${set_name} \\\"${set_value}\\\"\"\n                ;;\n              \"auth\")\n                fix_message \"az webapp ${resource_type} update --name \\\"${app_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${set_value}\\\"\"\n                ;;\n              \"identity\")\n                fix_message \"az webapp ${resource_type} assign --name \\\"${app_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${set_value}\\\"\"\n                ;;\n              *)\n                fix_message \"az webapp update --name \\\"${app_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${set_value}\\\"\"\n                ;;\n            esac\n            ;;\n          *)\n            case \"${resource_type}\" in\n              \"Microsoft.Web/sites\")\n                fix_message \"az resource update --name \\\"${resource_name}\\\" --resource-group \\\"${resource_group}\\\" --namespace \\\"${namespace_name}\\\" --resource-type \\\"${resource_type}\\\" --parent \\\"sites/${app_name}/slots/${slot_name}\\\" --set \\\"${set_name}\\\"=\\\"${set_value}\\\"\"\n                ;;\n              \"auth\")\n                fix_message \"az webapp ${resource_type} update --name \\\"${app_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"${set_value}\\\"\"\n                ;;\n              \"identity\")\n                fix_message \"az webapp ${resource_type} assign --name \\\"${app_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"${set_value}\\\"\"\n                ;;\n              *)\n                fix_message \"az webapp update --name \\\"${app_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"${set_value}\\\"\"\n                ;;\n            esac\n            ;;\n        esac\n      fi\n    else\n      inc_secure \"Azure App Service App ${description} for app \\\"${app_name}\\\" with resource group \\\"${resource_group}\\\" and parameter \\\"${query_string}\\\" is \\\"${function}\\\" to \\\"${set_value}\\\"\"\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/azure/compute/webapp/check_azure_app_service_plan_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_app_service_plan_value\n#\n# Check Azure App Service Plan value\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_app_service_plan_value () {\n  plan_id=\"${1}\"\n  resource_group=\"${2}\"\n  query_string=\"${3}\"\n  function=\"${4}\"\n  correct_value=\"${5}\"\n  set_name=\"${7}\"\n  set_value=\"${8}\"\n  print_function \"check_azure_app_service_plan_value\"\n  if [ \"${set_value}\" = \"\" ]; then\n    set_value=\"${correct_value}\"\n  fi\n  plan_name=$( basename \"${plan_id}\" )\n  check_message  \"Azure App Service Plan \\\"${plan_name}\\\" with resource group \\\"${resource_group}\\\" and parameter \\\"${query_string}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n  command=\"az appservice plan show --id \\\"${plan_id}\\\" --query \\\"${query_string}\\\" --output tsv 2> /dev/null\" \n  command_message      \"${command}\"\n  actual_value=$( eval \"${command}\" )\n  if [ \"${function}\" = \"eq\" ]; then\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_secure   \"Azure App Service Plan \\\"${plan_name}\\\" with resource group \\\"${resource_group}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    else\n      inc_insecure \"Azure App Service Plan \\\"${plan_name}\\\" with resource group \\\"${resource_group}\\\" is \\\"${actual_value}\\\" and not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      if [ ! \"${set_name}\" = \"\" ]; then\n        case \"${set_name}\" in\n          \"--\"*)\n            fix_message \"az appservice plan update --name \\\"${plan_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${set_value}\\\"\"\n            ;;\n          *)\n            fix_message \"az appservice plan update --name \\\"${plan_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"${set_value}\\\"\"\n            ;;\n        esac\n      fi\n    fi\n  else\n    if [ \"${actual_value}\" != \"${correct_value}\" ]; then\n      inc_secure   \"Azure App Service Plan \\\"${plan_name}\\\" with resource group \\\"${resource_group}\\\" is not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    else\n      inc_insecure \"Azure App Service Plan \\\"${plan_name}\\\" with resource group \\\"${resource_group}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      if [ ! \"${set_name}\" = \"\" ]; then\n        case \"${set_name}\" in\n          \"--\"*)\n            fix_message \"az appservice plan update --name \\\"${plan_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${set_value}\\\"\"\n            ;;\n          *)\n            fix_message \"az appservice plan update --name \\\"${plan_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"${set_value}\\\"\"\n            ;;\n        esac\n      fi\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/azure/database/check_azure_cosmos_db_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_cosmos_db_value\n#\n# Check Azure Cosmos DB value\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_cosmos_db_value () {\n  description=\"${1}\"\n  cosmosdb_name=\"${2}\"\n  resource_group=\"${3}\"\n  query_string=\"${4}\"\n  function=\"${5}\"\n  correct_value=\"${6}\"\n  set_name=\"${7}\"\n  set_value=\"${8}\"\n  print_function \"check_azure_cosmos_db_value\"\n  if [ \"${set_value}\" = \"\" ]; then\n    set_value=\"${correct_value}\"\n  fi\n  check_message \"${description} for Cosmos DB \\\"${cosmosdb_name}\\\" with Resource Group \\\"${resource_group}\\\" Parameter \\\"${query_string}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n  command=\"az cosmosdb show --name \\\"${cosmosdb_name}\\\" --resource-group \\\"${resource_group}\\\" --query \\\"[].${query_string}\\\" --output tsv\"\n  command_message      \"${command}\"\n  actual_value=$( eval \"${command}\" )\n  if [ \"${function}\" = \"eq\" ]; then\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_secure   \"${description} for Cosmos DB \\\"${cosmosdb_name}\\\" with Resource Group \\\"${resource_group}\\\" Parameter \\\"${query_string}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    else\n      inc_insecure \"${description} for Cosmos DB \\\"${cosmosdb_name}\\\" with Resource Group \\\"${resource_group}\\\" Parameter \\\"${query_string}\\\" is not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      if [ ! \"${set_name}\" = \"\" ]; then\n        case \"${set_name}\" in\n          \"--\"*)\n            fix_message  \"az cosmosdb update --name \\\"${cosmosdb_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${set_value}\\\"\"\n            ;;\n          *)\n            fix_message  \"az cosmosdb update --name \\\"${cosmosdb_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"\\\"${set_value}\\\"\" \"fix\"\n            ;;\n        esac\n      fi\n    fi\n  else\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_insecure \"${description} for Cosmos DB \\\"${cosmosdb_name}\\\" with Resource Group \\\"${resource_group}\\\" Parameter \\\"${query_string}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      if [ ! \"${set_name}\" = \"\" ]; then\n        case \"${set_name}\" in\n          \"--\"*)\n            fix_message  \"az cosmosdb update --name \\\"${cosmosdb_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${set_value}\\\"\"\n            ;;\n          *)\n            fix_message  \"az cosmosdb update --name \\\"${cosmosdb_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"\\\"${set_value}\\\"\"\n            ;;\n        esac\n      fi\n    else\n      inc_secure \"${description} for Cosmos DB \\\"${cosmosdb_name}\\\" with Resource Group \\\"${resource_group}\\\" Parameter \\\"${query_string}\\\" is not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/azure/database/check_azure_mysql_db_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_mysql_db_value\n#\n# Check Azure MySQL DB value\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_mysql_db_value () {\n  description=\"${1}\"\n  server_type=\"${2}\"\n  server_name=\"${3}\"\n  resource_group=\"${4}\"\n  db_name=\"${5}\"\n  query_string=\"${6}\"\n  function=\"${7}\"\n  correct_value=\"${8}\"\n  set_name=\"${9}\"\n  set_value=\"${10}\"\n  print_function \"check_azure_mysql_db_value\"\n\n  if [ \"${set_value}\" = \"\" ]; then\n    set_value=\"${correct_value}\"\n  fi\n  if [ \"${server_type}\" = \"server\" ]; then\n    header_string=\"${description} for MySQL ${server_type} DB Server \\\"${server_name}\\\" with Resource Group \\\"${resource_group}\\\" Parameter \\\"${query_string}\\\"\"\n    check_message \"${header_string} is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    command=\"az mysql ${server_type} show --name \\\"${server_name}\\\" --resource-group \\\"${resource_group}\\\" --query \\\"[].${query_string}\\\" --output tsv\"\n    command_message \"${command}\"\n  else\n    header_string=\"${description} for MySQL ${server_type} DB \\\"${server_name}\\\" with Resource Group \\\"${resource_group}\\\" Parameter \\\"${query_string}\\\"\"\n    check_message \"${header_string} is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    command=\"az mysql ${server_type} show --server-name \\\"${server_name}\\\" --resource-group \\\"${resource_group}\\\" --database-name \\\"${db_name}\\\" --query \\\"[].${query_string}\\\" --output tsv\"\n    command_message \"${command}\"\n  fi\n  actual_value=$( eval \"${command}\" )\n  if [ \"${function}\" = \"eq\" ]; then\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_secure   \"${header_string} is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    else\n      inc_insecure \"${header_string} is not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      if [ ! \"${set_name}\" = \"\" ]; then\n        case \"${set_name}\" in\n          \"--\"*)\n            fix_message \"az mysql ${server_type} update --name \\\"${server_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${set_value}\\\"\"\n            ;;\n          *)\n            fix_message \"az mysql ${server_type} update --name \\\"${server_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"\\\"${set_value}\\\"\"\n            ;;\n        esac\n      fi\n    fi\n  else\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_insecure \"${header_string} is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      if [ ! \"${set_name}\" = \"\" ]; then\n        case \"${set_name}\" in\n          \"--\"*)\n            fix_message \"az mysql ${server_type} update --name \\\"${server_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${set_value}\\\"\"\n            ;;\n          *)\n            fix_message \"az mysql ${server_type} update --name \\\"${server_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"\\\"${set_value}\\\"\"\n            ;;\n        esac\n      fi\n    else\n      inc_secure \"${header_string} is not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/azure/database/check_azure_postgresql_db_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_postgresql_db_value\n#\n# Check Azure PostgreSQL DB value\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_postgresql_db_value () {\n  description=\"${1}\"\n  server_type=\"${2}\"\n  server_name=\"${3}\"\n  resource_group=\"${4}\"\n  db_name=\"${5}\"\n  query_string=\"${6}\"\n  function=\"${7}\"\n  correct_value=\"${8}\"\n  set_name=\"${9}\"\n  set_value=\"${10}\"\n  print_function \"check_azure_postgresql_db_value\"\n  if [ \"${set_value}\" = \"\" ]; then\n    set_value=\"${correct_value}\"\n  fi\n  if [ \"${server_type}\" = \"server\" ]; then\n    header_string=\"${description} for PostgreSQL ${server_type} DB Server \\\"${server_name}\\\" with Resource Group \\\"${resource_group}\\\" Parameter \\\"${query_string}\\\"\"\n    check_message \"${header_string} is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    command=\"az postgresql ${server_type} show --name \\\"${server_name}\\\" --resource-group \\\"${resource_group}\\\" --query \\\"[].${query_string}\\\" --output tsv\"\n    command_message \"${command}\"\n  else\n    header_string=\"${description} for PostgreSQL ${server_type} DB \\\"${server_name}\\\" with Resource Group \\\"${resource_group}\\\" Parameter \\\"${query_string}\\\"\"\n    check_message \"${header_string} is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    command=\"az postgresql ${server_type} show --server-name \\\"${server_name}\\\" --resource-group \\\"${resource_group}\\\" --database-name \\\"${db_name}\\\" --query \\\"[].${query_string}\\\" --output tsv\"\n    command_message \"${command}\"\n  fi\n  actual_value=$( eval \"${command}\" )\n  if [ \"${function}\" = \"eq\" ]; then\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_secure   \"${header_string} is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    else\n      inc_insecure \"${header_string} is not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      if [ ! \"${set_name}\" = \"\" ]; then\n        case \"${set_name}\" in\n          \"--\"*)\n            fix_message \"az postgresql ${server_type} update --name \\\"${server_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${set_value}\\\"\"\n            ;;\n          *)\n            fix_message \"az postgresql ${server_type} update --name \\\"${server_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"\\\"${set_value}\\\"\\\"\"\n            ;;\n        esac\n      fi\n    fi\n  else\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_insecure \"${header_string} is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      if [ ! \"${set_name}\" = \"\" ]; then\n        case \"${set_name}\" in\n          \"--\"*)\n            fix_message \"az postgresql ${server_type} update --name \\\"${server_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${set_value}\\\"\"\n            ;;\n          *)\n            fix_message \"az postgresql ${server_type} update --name \\\"${server_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"\\\"${set_value}\\\"\\\"\"\n            ;;\n        esac\n      fi\n    else\n      inc_secure \"${header_string} is not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/azure/database/check_azure_redis_cache_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_redis_cache_value\n#\n# Check Azure Redis Cache value\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_redis_cache_value () {\n  description=\"${1}\"\n  redis_name=\"${2}\"\n  resource_group=\"${3}\"\n  query_string=\"${4}\"\n  function=\"${5}\"\n  correct_value=\"${6}\"\n  set_name=\"${7}\"\n  print_function \"check_azure_redis_cache_value\"\n  check_message  \"${description} for Redis Cache \\\"${redis_name}\\\" with Resource Group \\\"${resource_group}\\\" Parameter \\\"${query_string}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n  command=\"az redis show --name \\\"${redis_name}\\\" --resource-group \\\"${resource_group}\\\" --query \\\"${query_string}\\\" --output tsv 2> /dev/null\"\n  command_message      \"${command}\"\n  actual_value=$( eval \"${command}\" )\n  if [ \"${function}\" = \"eq\" ]; then\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_secure   \"${description} for Redis Cache \\\"${redis_name}\\\" with Resource Group \\\"${resource_group}\\\" Parameter \\\"${query_string}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    else\n      inc_insecure \"${description} for Redis Cache \\\"${redis_name}\\\" with Resource Group \\\"${resource_group}\\\" Parameter \\\"${query_string}\\\" is not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      if [ ! \"${set_name}\" = \"\" ]; then\n        case \"${set_name}\" in\n          \"--\"*)\n            fix_message \"az redis update --name \\\"${redis_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${correct_value}\\\"\"\n            ;;\n          *)\n            fix_message \"az redis update --name \\\"${redis_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"\\\"${correct_value}\\\"\"\n            ;;\n        esac\n      fi\n    fi\n  else\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_insecure \"${description} for Redis Cache \\\"${redis_name}\\\" with Resource Group \\\"${resource_group}\\\" Parameter \\\"${query_string}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      if [ ! \"${set_name}\" = \"\" ]; then\n        case \"${set_name}\" in\n          \"--\"*)\n            fix_message \"az redis update --name \\\"${redis_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${correct_value}\\\"\"\n            ;;\n          *)\n            fix_message \"az redis update --name \\\"${redis_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"\\\"${correct_value}\\\"\"\n            ;;\n        esac\n      fi\n    else\n      inc_secure  \"${description} for Redis Cache \\\"${redis_name}\\\" with Resource Group \\\"${resource_group}\\\" Parameter \\\"${query_string}\\\" is not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/azure/database/check_azure_redis_enterprise_cache_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_redis_enterprise_cache_value\n#\n# Check Azure Redis Enterprise Cache value\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_redis_enterprise_cache_value () {\n  description=\"${1}\"\n  redis_name=\"${2}\"\n  resource_group=\"${3}\"\n  query_string=\"${4}\"\n  function=\"${5}\"\n  correct_value=\"${6}\"\n  set_name=\"${7}\"\n  print_function \"check_azure_redis_enterprise_cache_value\"\n  check_message  \"${description} for Redis Enterprise Cache \\\"${redis_name}\\\" with Resource Group \\\"${resource_group}\\\" Parameter \\\"${query_string}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n  command=\"az redisenterprise show --name \\\"${redis_name}\\\" --resource-group \\\"${resource_group}\\\" --query \\\"${query_string}\\\" --output tsv 2> /dev/null\"\n  command_message      \"${command}\"\n  actual_value=$( eval \"${command}\" )\n  if [ \"${function}\" = \"eq\" ]; then\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_secure   \"${description} for Redis Enterprise Cache \\\"${redis_name}\\\" with Resource Group \\\"${resource_group}\\\" Parameter \\\"${query_string}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    else\n      inc_insecure \"${description} for Redis Enterprise Cache \\\"${redis_name}\\\" with Resource Group \\\"${resource_group}\\\" Parameter \\\"${query_string}\\\" is not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      if [ ! \"${set_name}\" = \"\" ]; then\n        case \"${set_name}\" in\n          \"--\"*)\n            fix_message \"az redisenterprise update --name \\\"${redis_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${correct_value}\\\"\"\n            ;;\n          *)\n            fix_message \"az redisenterprise update --name \\\"${redis_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"\\\"${correct_value}\\\"\"\n            ;;\n        esac\n      fi\n    fi\n  else\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_insecure \"${description} for Redis Enterprise Cache \\\"${redis_name}\\\" with Resource Group \\\"${resource_group}\\\" Parameter \\\"${query_string}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      if [ ! \"${set_name}\" = \"\" ]; then\n        case \"${set_name}\" in\n          \"--\"*)\n            fix_message \"az redisenterprise update --name \\\"${redis_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${correct_value}\\\"\"\n            ;;\n          *)\n            fix_message \"az redisenterprise update --name \\\"${redis_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"\\\"${correct_value}\\\"\"\n            ;;\n        esac\n      fi\n    else\n      inc_secure \"${description} for Redis Enterprise Cache \\\"${redis_name}\\\" with Resource Group \\\"${resource_group}\\\" Parameter \\\"${query_string}\\\" is not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/azure/database/check_azure_sql_db_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_sql_db_value\n#\n# Check Azure SQL DB value\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_sql_db_value () {\n  description=\"${1}\"\n  server_type=\"${2}\"\n  server_name=\"${3}\"\n  resource_group=\"${4}\"\n  db_name=\"${5}\"\n  query_string=\"${6}\"\n  function=\"${7}\"\n  correct_value=\"${8}\"\n  set_name=\"${9}\"\n  set_value=\"${10}\"\n  print_function \"check_azure_sql_db_value\"\n  if [ \"${set_value}\" = \"\" ]; then\n    set_value=\"${correct_value}\"\n  fi\n  if [ \"${server_type}\" = \"server\" ]; then\n    header_string=\"${description} for SQL ${server_type} DB Server \\\"${server_name}\\\" with Resource Group \\\"${resource_group}\\\" Parameter \\\"${query_string}\\\"\"\n    check_message \"${header_string} is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    command=\"az sql ${server_type} show --name \\\"${server_name}\\\" --resource-group \\\"${resource_group}\\\" --query \\\"[].${query_string}\\\" --output tsv\"\n    command_message \"${command}\"\n  else\n    header_string=\"${description} for SQL ${server_type} DB \\\"${server_name}\\\" with Resource Group \\\"${resource_group}\\\" Parameter \\\"${query_string}\\\"\"\n    check_message \"${header_string} is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    command=\"az sql ${server_type} show --server-name \\\"${server_name}\\\" --resource-group \\\"${resource_group}\\\" --database-name \\\"${db_name}\\\" --query \\\"[].${query_string}\\\" --output tsv\"\n    command_message \"${command}\"\n  fi\n  actual_value=$( eval \"${command}\" )\n  if [ \"${function}\" = \"eq\" ]; then\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_secure   \"${header_string} is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    else\n      inc_insecure \"${header_string} is not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      if [ ! \"${set_name}\" = \"\" ]; then\n        case \"${set_name}\" in\n          \"--\"*)\n            fix_message \"az sql ${server_type} update --name \\\"${server_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${set_value}\\\"\"\n            ;;\n          *)\n            fix_message \"az sql ${server_type} update --name \\\"${server_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"\\\"${set_value}\\\"\"\n            ;;\n        esac\n      fi\n    fi\n  else\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_insecure \"${header_string} is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      if [ ! \"${set_name}\" = \"\" ]; then\n        case \"${set_name}\" in\n          \"--\"*)\n            fix_message \"az sql ${server_type} update --name \\\"${server_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${set_value}\\\"\"\n            ;;\n          *)\n            fix_message \"az sql ${server_type} update --name \\\"${server_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"\\\"${set_value}\\\"\"\n            ;;\n        esac\n      fi\n    else\n      inc_secure \"${header_string} is not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/azure/logging/check_azure_activity_log_alert_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_activity_log_alert_value\n#\n# Check Azure Activity Log Alert value\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_activity_log_alert_value () {\n  description=\"${1}\"\n  subscription_id=\"${2}\"\n  alert_check=\"${3}\"\n  print_function \"check_azure_activity_log_alert_value\"\n  query_string=\"[].{Name:name,Enabled:enabled,Condition:condition.allOf,Actions:actions}\"\n  check_message \"Azure Activity Log Alert for ${description} for subscription \\\"${subscription_id}\\\" is \\\"${alert_check}\\\"\"\n  command=\"az monitor activity-log alert list --subscription \\\"${subscription_id}\\\" --query \\\"${query_string}\\\" | grep \\\"${alert_check}\\\"\"\n  command_message      \"${command}\"\n  alert_check=$( eval  \"${command}\" )\n  if [ -n \"${alert_check}\" ]; then\n    inc_secure   \"Activity Log Alert for ${description} is enabled\"\n  else\n    inc_insecure \"Activity Log Alert for ${description} is not enabled\"\n  fi\n}\n"
  },
  {
    "path": "functions/azure/logging/check_azure_monitor_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_monitor_value\n#\n# Check Azure Monitor value\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_monitor_value () {\n  description=\"${1}\"\n  workspace_name=\"${2}\"\n  resource_id=\"${3}\"\n  monitor_property=\"${4}\"\n  parameter_name=\"${5}\"\n  function=\"${6}\"\n  correct_value=\"${7}\"\n  set_name=\"${8}\"\n  print_function \"check_azure_monitor_value\"\n  if [ \"${parameter_name}\" = \"\" ]; then\n    parameter_string=\"\"\n  else\n    parameter_string=\" and parameter \\\"${parameter_name}\\\"\"\n  fi\n  check_message  \"Azure Monitor value for workspace \\\"${workspace_name}\\\" with Resource ID \\\"${resource_id}\\\"${parameter_string} is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n  command=\"az monitor \\\"${monitor_property}\\\" show --name \\\"${workspace_name}\\\" --resource-id \\\"${resource_id}\\\" --query \\\"${parameter_name}\\\" --output tsv 2> /dev/null\"\n  command_message      \"${command}\"\n  actual_value=$( eval \"${command}\" )\n  if [ \"${function}\" = \"eq\" ]; then\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_secure    \"${description} for workspace \\\"${workspace_name}\\\" with Resource ID \\\"${resource_id}\\\"${parameter_string} is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    else\n      inc_insecure  \"${description} for workspace \\\"${workspace_name}\\\" with Resource ID \\\"${resource_id}\\\"${parameter_string} is not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      if [ ! \"${parameter_name}\" = \"\" ]; then\n        fix_message \"az monitor log-analytics workspace update --name \\\"${workspace_name}\\\" --resource-id \\\"${resource_id}\\\" --query \\\"${parameter_name}\\\" --output tsv\"\n      fi\n    fi\n  else\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_insecure  \"${description} for workspace \\\"${workspace_name}\\\" with Resource ID \\\"${resource_id}\\\"${parameter_string} is not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      if [ ! \"${parameter_name}\" = \"\" ]; then\n        fix_message \"az monitor log-analytics workspace update --name \\\"${workspace_name}\\\" --resource-id \\\"${resource_id}\\\" --query \\\"${parameter_name}\\\" --output tsv\"\n      fi\n    else\n      inc_secure    \"${description} for workspace \\\"${workspace_name}\\\" with Resource ID \\\"${resource_id}\\\"${parameter_string} is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/azure/logging/check_azure_monitoring_diagnostics_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2030\n# shellcheck disable=SC2031\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_monitoring_diagnostics_value\n#\n# Check Azure Monitoring Diagnostics value\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_monitoring_diagnostics_value () {\n  resource_id=\"${1}\"\n  print_function \"check_azure_monitoring_diagnostics_value\"\n  check_message  \"Checking Azure Monitoring Diagnostics for \\\"${resource_id}\\\"\"\n  command=\"az monitor diagnostic-settings list --resource \\\"${resource_id}\\\" --output tsv\"\n  command_message \"${command}\"\n  stderr=$( { stdout=$( az monitor diagnostic-settings list --resource \"${resource_id}\" --output tsv ); } 2>&1 )\n  if [ -n \"${stderr}\" ]; then\n    stderr=$( echo \"${stderr}\" | tr \"\\n\" \" \" | cut -f2 -d: | cut -f3-11 -d\" \" )\n    notice_message \"${stderr}\"\n  else\n    if [ -n \"${stdout}\" ]; then\n      inc_secure   \"Resource logging is enabled for ${resource_id}\"\n    else\n      inc_insecure \"Resource logging is not enabled for ${resource_id}\"\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/azure/logging/check_azure_network_watcher_flow_log_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_network_watcher_flow_log_value\n#\n# Check Azure Network Watcher Flow Log value\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_network_watcher_flow_log_value () {\n  location=\"${1}\"\n  flow_log=\"${2}\"\n  query_string=\"${3}\"\n  correct_value=\"${4}\"\n  parameter_name=\"${5}\"\n  print_function \"check_azure_network_watcher_flow_log_value\"\n  check_message  \"Azure Network Watcher Flow Log \\\"${flow_log}\\\" has \\\"${query_string}\\\" set to \\\"${correct_value}\\\"\"\n  command=\"az network watcher flow-log show --location \\\"${location}\\\" --name \\\"${flow_log}\\\" --query \\\"${query_string}\\\" --output tsv 2> /dev/null\"\n  command_message      \"${command}\"\n  actual_value=$( eval \"${command}\" )\n  if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n    inc_secure   \"Azure Network Watcher Flow Log \\\"${flow_log}\\\" has \\\"${query_string}\\\" set to \\\"${correct_value}\\\"\"\n  else\n    inc_insecure \"Azure Network Watcher Flow Log \\\"${flow_log}\\\" has \\\"${query_string}\\\" not set to \\\"${correct_value}\\\"\"\n    fix_message  \"az network watcher flow-log update --location \\\"${location}\\\" --name \\\"${flow_log}\\\" --\\\"${parameter_name}\\\" \\\"${correct_value}\\\"\"\n  fi\n}\n"
  },
  {
    "path": "functions/azure/logging/check_azure_network_watcher_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_network_watcher_value\n#\n# Check Azure Network Watcher value\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_network_watcher_value () {\n  watcher_id=\"${1}\"\n  parameter_name=\"${2}\"\n  correct_value=\"${3}\"\n  print_function \"check_azure_network_watcher_value\"\n  short_id=$( basename \"${watcher_id}\" )\n  check_message  \"Azure Network Watcher ID \\\"${short_id}\\\" has \\\"${parameter_name}\\\" set to \\\"${correct_value}\\\"\"\n  command=\"az network watcher list --query \\\"[?contains(id,'${watcher_id}')].${parameter_name}\\\" --output tsv 2> /dev/null\"\n  command_message      \"${command}\"\n  actual_value=$( eval \"${command}\" )\n  if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n    inc_secure   \"${parameter_name} is set to ${correct_value} for ${short_id}\"\n  else\n    inc_insecure \"${parameter_name} is not set to ${correct_value} for ${short_id}\"\n  fi\n}\n"
  },
  {
    "path": "functions/azure/logging/check_azure_storage_logging_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_storage_logging_value\n#\n# Check Azure Storage Logging value\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_storage_logging_value () {\n  description=\"${1}\"\n  storage_account=\"${2}\"\n  service_type=\"${3}\"\n  query_string=\"${4}\"\n  function=\"${5}\"\n  correct_value=\"${6}\"\n  log_value=\"${7}\"\n  print_function \"check_azure_storage_logging_value\"\n  short_service=$( echo \"${service_type}\" | cut -c 1 )\n  check_message  \"${description} for \\\"${file_system}\\\" for Storage Account \\\"${storage_account}\\\" has Parameter \\\"${query_string}\\\" \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n  command=\"az storage logging show --services ${short_service} --account-name \\\"${storage_account}\\\" --query \\\"${query_string}\\\" --output tsv 2> /dev/null\"\n  command_message      \"${command}\"\n  actual_value=$( eval \"${command}\" )\n  if [ \"${function}\" = \"eq\" ]; then\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_secure   \"${description} for File System \\\"${file_system}\\\" on Storage Account \\\"${storage_account}\\\" has \\\"${query_string}\\\" \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    else\n      inc_insecure \"${description} for File System \\\"${file_system}\\\" on Storage Account \\\"${storage_account}\\\" does not have \\\"${query_string}\\\" \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      if [ ! \"${log_value}\" = \"\" ]; then\n        fix_message \"az storage logging update --account-name ${storage_account} --services ${short_service} --log ${log_value} --retention ${correct_value}\"\n      fi\n    fi\n  elif [ \"${function}\" = \"ne\" ]; then\n    if [ \"${actual_value}\" != \"${correct_value}\" ]; then\n      inc_secure   \"${description} for File System \\\"${file_system}\\\" on Storage Account \\\"${storage_account}\\\" has \\\"${query_string}\\\" \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    else\n      inc_insecure \"${description} for File System \\\"${file_system}\\\" on Storage Account \\\"${storage_account}\\\" does not have \\\"${query_string}\\\" \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/azure/network/check_azure_network_private_endpoint_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_network_private_endpoint_value\n#\n# Check Azure Network Private Endpoint value\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_network_private_endpoint_value () {\n  endpoint_id=\"${1}\"\n  query_string=\"${2}\"\n  function=\"${3}\"\n  correct_value=\"${4}\"\n  endpoint_name=$( basename \"${endpoint_id}\" )\n  print_function \"check_azure_network_private_endpoint_value\"\n  check_message  \"Azure Network Private Endpoint for \\\"${endpoint_name}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n  command=\"az network private-endpoint show --id \\\"${endpoint_id}\\\" --query \\\"${query_string}\\\" --output tsv\"\n  command_message      \"${command}\"\n  actual_value=$( eval \"${command}\" 2> /dev/null )\n  if [ \"${function}\" = \"eq\" ]; then\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_secure   \"Azure Network Private Endpoint for \\\"${endpoint_name}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    else\n      inc_insecure \"Azure Network Private Endpoint for \\\"${endpoint_name}\\\" is \\\"${actual_value}\\\" and not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      fix_message  \"az network private-endpoint create --resource-group <resource-group-name> \\ \"\n      fix_message  \"--location <location> --name <private-endpoint-name> --vnet-name <virtual-network-name> \\ \"\n      fix_message  \"--subnet <subnet-name> --private-connection-resource-id <fully-qualified-app-id> \\ \"\n      fix_message  \"--connection-name <connection-name> --group-id sites\"\n    fi\n  else\n    if [ \"${function}\" = \"ne\" ]; then\n      if [ \"${actual_value}\" != \"${correct_value}\" ]; then\n        inc_secure   \"Azure Network Private Endpoint for \\\"${endpoint_name}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      else\n        inc_insecure \"Azure Network Private Endpoint for \\\"${endpoint_name}\\\" is \\\"${actual_value}\\\" and not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n        fix_message  \"az network private-endpoint create --resource-group <resource-group-name> \\ \"\n        fix_message  \"--location <location> --name <private-endpoint-name> --vnet-name <virtual-network-name> \\ \"\n        fix_message  \"--subnet <subnet-name> --private-connection-resource-id <fully-qualified-app-id> \\ \"\n        fix_message  \"--connection-name <connection-name> --group-id sites\"\n      fi\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/azure/network/check_azure_public_ip_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_public_ip_value\n#\n# Check Azure Public IP value\n#\n# 7.7   Ensure that Public IP addresses are Evaluated on a Periodic Basis (Manual)\n#\n# Refer to Section(s) 7.7 Page(s) 309-10 CIS Microsoft Azure Foundations Benchmark v5.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_public_ip_value () {\n  resource_id=\"${1}\"\n  parameter_name=\"${2}\"\n  function=\"${3}\"\n  correct_value=\"${4}\"\n  print_function \"check_azure_public_ip_value\"\n  check_message  \"Azure Public IP \\\"${parameter_name}\\\" is ${function} to \\\"${correct_value}\\\"\"\n  short_id=$( basename \"${resource_id}\" )\n  command=\"az network public-ip show --id \\\"${resource_id}\\\" --query '${parameter_name}' --output tsv\"\n  command_message      \"${command}\"\n  actual_value=$( eval \"${command}\" )\n  if [ \"${parameter_name}\" = \"ipAddress\" ]; then\n    if [ \"${correct_value}\" = \"\" ]; then\n      if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n        inc_secure   \"No Azure Public IP found for \\\"${short_id}\\\"\"\n      else\n        inc_insecure \"Azure Public IP found for \\\"${short_id}\\\": \\\"${actual_value}\\\"\"\n      fi\n    fi\n  else\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_secure   \"Azure Public IP \\\"${parameter_name}\\\" is ${function} to \\\"${correct_value}\\\"\"\n    else\n      inc_insecure \"Azure Public IP \\\"${parameter_name}\\\" is not ${function} to \\\"${correct_value}\\\"\"\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/azure/network/check_azure_vnet_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_vnet_value\n#\n# Check Azure VNet value\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_vnet_value () {\n  vnet_name=\"${1}\"\n  resource_group=\"${2}\"\n  subnet_name=\"${3}\"\n  parameter_name=\"${4}\"\n  function=\"${5}\"\n  correct_value=\"${6}\"\n  print_function \"check_azure_vnet_value\"\n  check_message  \"Azure VNet \\\"${vnet_name}\\\" in Resource Group \\\"${resource_group}\\\" Subnet \\\"${subnet_name}\\\" has \\\"${parameter_name}\\\" ${function} to \\\"${correct_value}\\\"\"\n  command=\"az network vnet subnet show --name \\\"${subnet_name}\\\" --resource-group \\\"${resource_group}\\\" --vnet-name \\\"${vnet_name}\\\" --query \\\"${parameter_name}\\\" --output tsv 2> /dev/null\"\n  command_message      \"$command\"\n  actual_value=$( eval \"$command\" )\n  if [ \"${function}\" = \"ne\" ]; then\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_insecure \"Azure VNet \\\"${vnet_name}\\\" in Resource Group \\\"${resource_group}\\\" Subnet \\\"${subnet_name}\\\" does not have \\\"${parameter_name}\\\" ${function} to \\\"${correct_value}\\\"\"\n    else\n      inc_secure   \"Azure VNet \\\"${vnet_name}\\\" in Resource Group \\\"${resource_group}\\\" Subnet \\\"${subnet_name}\\\" has \\\"${parameter_name}\\\" ${function} to \\\"${correct_value}\\\"\"\n    fi\n  else\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_secure   \"Azure VNet \\\"${vnet_name}\\\" in Resource Group \\\"${resource_group}\\\" Subnet \\\"${subnet_name}\\\" has \\\"${parameter_name}\\\" ${function} to \\\"${correct_value}\\\"\"\n    else\n      inc_insecure \"Azure VNet \\\"${vnet_name}\\\" in Resource Group \\\"${resource_group}\\\" Subnet \\\"${subnet_name}\\\" does not have \\\"${parameter_name}\\\" ${function} to \\\"${correct_value}\\\"\"\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/azure/other/audit_azure.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_all\n#\n# Audit Azure all\n#\n# Run various Azure audit tests\n# \n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_all () {\n  print_function \"audit_azure_all\"\n  audit_azure_survey\n  audit_azure_extensions\n  audit_azure_storage_services\n  audit_azure_compute_services\n  audit_azure_database_services\n  audit_azure_identity_services\n  audit_azure_logging_and_monitoring\n  audit_azure_networking_services\n  audit_azure_security_services\n}\n\n# funct_audit_azure\n#\n# Audit Azure\n#.\n\nfunct_audit_azure () {\n  audit_mode=\"${1}\"\n  print_function \"funct_audit_azure\"\n  check_environment\n  check_azure\n  audit_azure_all\n  print_results\n}\n"
  },
  {
    "path": "functions/azure/security/check_azure_basic_authentication_publishing_credential_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_basic_authentication_publishing_credential_value\n#\n# Check Azure Basic Authentication Publishing Credential value\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_basic_authentication_publishing_credential_value () {\n  app_name=\"${1}\"\n  resource_group=\"${2}\"\n  resource_name=\"${3}\"\n  resource_type=\"${4}\"\n  name_space=\"${5}\"\n  query_string=\"${6}\"\n  function=\"${7}\"\n  correct_value=\"${8}\"\n  set_name=\"${9}\"\n  set_value=\"${10}\"\n  print_function \"check_azure_basic_authentication_publishing_credential_value\"\n  if [ \"${set_value}\" = \"\" ]; then\n    set_value=\"${correct_value}\"\n  fi\n  check_message \"Azure Basic Authentication Publishing Credential for ${resource_name} for app \\\"${app_name}\\\" with resource group \\\"${resource_group}\\\" and resource \\\"${resource_name}\\\" and resource type \\\"${resource_type}\\\" and parameter \\\"${query_string}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n  command=\"az resource show --name \\\"${resource_name}\\\" --name-space \\\"${name_space}\\\" --resource-group \\\"${resource_group}\\\" --resource-type \\\"${resource_type}\\\" --parent \\\"sites/${app_name}\\\" --query \\\"${query_string}\\\" --output tsv 2> /dev/null\"\n  command_message      \"${command}\"\n  actual_value=$( eval \"${command}\" )\n  if [ \"${function}\" = \"eq\" ]; then\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_secure   \"Azure Basic Authentication Publishing Credential for ${resource_name} for app \\\"${app_name}\\\" with resource group \\\"${resource_group}\\\" and resource \\\"${resource_name}\\\" and resource type \\\"${resource_type}\\\" and parameter \\\"${query_string}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    else\n      inc_insecure \"Azure Basic Authentication Publishing Credential for ${resource_name} for app \\\"${app_name}\\\" with resource group \\\"${resource_group}\\\" and resource \\\"${resource_name}\\\" and resource type \\\"${resource_type}\\\" and parameter \\\"${query_string}\\\" is not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      if [ ! \"${set_name}\" = \"\" ]; then\n        case \"${set_name}\" in\n          \"--\"*)\n            fix_message \"az resource update --name \\\"${resource_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${set_value}\\\"\"\n            ;;\n          *)\n            fix_message \"az resource update --name \\\"${resource_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"${set_value}\\\"\"\n            ;;\n        esac\n      fi\n    fi\n  else\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_insecure \"Azure Basic Authentication Publishing Credential for ${resource_name} for app \\\"${app_name}\\\" with resource group \\\"${resource_group}\\\" and resource \\\"${resource_name}\\\" and resource type \\\"${resource_type}\\\" and parameter \\\"${query_string}\\\" is not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      if [ ! \"${set_name}\" = \"\" ]; then\n        case \"${set_name}\" in\n          \"--\"*)\n            fix_message \"az resource update --name \\\"${resource_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${set_value}\\\"\"\n            ;;\n          *)\n            fix_message \"az resource update --name \\\"${resource_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"${set_value}\\\"\"\n            ;;\n        esac\n      fi\n    else\n      inc_secure \"Azure Basic Authentication Publishing Credential for ${resource_name} for app \\\"${app_name}\\\" with resource group \\\"${resource_group}\\\" and resource \\\"${resource_name}\\\" and resource type \\\"${resource_type}\\\" and parameter \\\"${query_string}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/azure/security/check_azure_lock_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_lock_value\n#\n# Check Azure Lock value\n#\n# This requires the Azure CLI to be installed and configured\n#\n\ncheck_azure_lock_value () {\n  lock_name=\"$1\"\n  resource_group=\"$2\"\n  resource_type=\"$3\"\n  query_string=\"$4\"\n  function=\"$5\"\n  correct_value=\"$6\"\n  set_name=\"$7\"\n  print_function \"check_azure_lock_value\"\n  check_message  \"Azure Lock Value\"\n  command=\"az lock show --name \\\"${lock_name}\\\" --resource-group \\\"${resource_group}\\\" --resource-type \\\"${resource_type}\\\" --query \\\"${query_string}\\\" --output tsv\"\n  command_message      \"${command}\"\n  actual_value=$( eval \"${command}\" )\n  if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n    inc_secure   \"Lock \\\"${lock_name}\\\" in resource group \\\"${resource_group}\\\" resource type \\\"${resource_type}\\\" parameter \\\"${query_string}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n  else\n    inc_insecure \"Lock \\\"${lock_name}\\\" in resource group \\\"${resource_group}\\\" resource type \\\"${resource_type}\\\" parameter \\\"${query_string}\\\" is \\\"${function}\\\" to \\\"${actual_value}\\\" instead of \\\"${correct_value}\\\"\"\n    if [ \"${set_name}\" != \"\" ]; then\n      case \"${set_name}\" in\n        *\"--\"*)\n          fix_message \"az lock update --name \\\"${lock_name}\\\" --resource-group \\\"${resource_group}\\\" --resource-type \\\"${resource_type}\\\" --set \\\"${set_name}\\\" \\\"${correct_value}\\\"\"\n          ;;\n        *)\n          fix_message \"az lock update --name \\\"${lock_name}\\\" --resource-group \\\"${resource_group}\\\" --resource-type \\\"${resource_type}\\\" \\\"${set_name}\\\"=\\\"${correct_value}\\\"\"\n          ;;\n      esac\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/azure/security/check_azure_microsoft_defender_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_microsoft_defender_value\n#\n# Check Azure Microsoft Defender value\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_microsoft_defender_value () {\n  description=\"${1}\"\n  parameter_name=\"${2}\"\n  correct_value=\"${3}\"\n  correct_status=\"${4}\"\n  resource_type=\"${5}\"\n  print_function \"check_azure_microsoft_defender_value\"\n  if [ \"${resource_type}\" = \"\" ]; then\n    resource_check=\"ignore\"\n  else\n    resource_check=$( az resource list --resource-type \"${resource_type}\" --output tsv )\n  fi\n  if [ \"${resource_check}\" = \"\" ]; then\n    if [ \"${correct_value}\" = \"Exists\" ]; then\n      inc_insecure    \"Microsoft Defender \\\"${description}\\\" does not exist\"\n    else\n      verbose_message \"Azure Resource Type \\\"${resource_type}\\\" not found\"\n    fi\n  else\n    if [ \"${correct_value}\" = \"Exists\" ]; then\n      inc_secure    \"Microsoft Defender \\\"${description}\\\" exists\"\n    else\n      check_message \"Azure Microsoft Defender \\\"${description}\\\" parameter \\\"${parameter_name}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      command=\"az security pricing show --name \\\"${parameter_name}\\\" --query \\\"pricingTier\\\" --output tsv 2> /dev/null\"\n      command_message      \"${command}\"\n      actual_value=$( eval \"${command}\" )\n      if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n        inc_secure    \"Microsoft Defender \\\"${description}\\\" parameter \\\"${parameter_name}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      else\n        inc_insecure  \"Microsoft Defender \\\"${description}\\\" parameter \\\"${parameter_name}\\\" is not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n        if [ \"${parameter_name}\" = \"CloudPosture\" ]; then\n          fix_message \"az security pricing update --name \\\"${parameter_name}\\\" --tier \\\"${correct_value}\\\" --extensions name=ApiPosture isEnabled=true\"\n        else\n          fix_message \"az security pricing update --name \\\"${parameter_name}\\\" --tier \\\"${correct_value}\\\"\"\n        fi\n      fi\n      if [ ! \"${correct_status}\" = \"\" ]; then\n        check_message \"Azure Microsoft Defender \\\"${description}\\\" Status is \\\"${function}\\\" to \\\"${correct_status}\\\"\"\n        command=\"az security pricing show --name \\\"${parameter_name}\\\" --query \\\"[operationStatus]\\\" --output tsv 2> /dev/null\"\n        command_message       \"${command}\"\n        actual_status=$( eval \"${command}\" )\n        if [ \"${actual_status}\" = \"${correct_status}\" ]; then\n          inc_secure   \"Microsoft Defender \\\"${description}\\\" Status is \\\"${function}\\\" to \\\"${correct_status}\\\"\"\n        else\n          inc_insecure \"Microsoft Defender \\\"${description}\\\" Status is not \\\"${function}\\\" to \\\"${correct_status}\\\"\"\n        fi\n      fi\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/azure/security/check_azure_network_security_perimeter_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_network_security_perimeter_value\n#\n# Check Azure Network Security Perimeter value\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_network_security_perimeter_value () {\n  nsp_name=\"${1}\"\n  group_name=\"${2}\"\n  policy_name=\"${3}\"\n  query_string=\"${4}\"\n  function=\"${5}\"\n  correct_value=\"${6}\"\n  print_function \"check_azure_network_security_perimeter_value\"\n  if [ \"${policy_name}\" = \"association\" ]; then\n    check_message \"Azure Network Security Perimeter \\\"${nsp_name}\\\" is associated with \\\"${correct_value}\\\"\"\n    command=\"az network perimeter association list --perimeter-name \\\"${nsp_name}\\\" --resource-group \\\"${group_name}\\\" --query \\\"${query_string}\\\" --output tsv 2> /dev/null\"\n    command_message      \"${command}\"\n    actual_value=$( eval \"${command}\" )\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_secure   \"Azure Network Security Perimeter \\\"${nsp_name}\\\" is associated with \\\"${correct_value}\\\"\"\n    else\n      inc_insecure \"Azure Network Security Perimeter \\\"${nsp_name}\\\" is not associated with \\\"${correct_value}\\\"\"\n      fix_message  \"az network perimeter association create --perimeter-name <perimeter-name> --resource-group <resource-group> --association-name <association-name> --target-resource-id <target-resource-id>\"\n    fi\n  fi\n}"
  },
  {
    "path": "functions/azure/security/check_azure_nsg_security_rule_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_nsg_security_rule_value\n#\n# Check Azure NSG Security Rule value\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_nsg_security_rule_value () {\n  description=\"${1}\"\n  rule_id=\"${2}\"\n  direction=\"${3}\"\n  parameter_name=\"${4}\"\n  function=\"${5}\"\n  correct_value=\"${6}\"\n  print_function \"check_azure_nsg_security_rule_value\"\n  short_id=$( basename \"${rule_id}\" )\n  check_message  \"NSG Rule ID \\\"${short_id}\\\" is \\\"${direction}\\\"\"\n  command=\"az network nsg rule show --id ${rule_id} --query \\\"direction\\\" --output tsv 2> /dev/null\"\n  command_message      \"${command}\"\n  actual_value=$( eval \"${command}\" )\n  if [ \"${actual_value}\" = \"${direction}\" ]; then\n    check_message \"${description} rule ID \\\"${short_id}\\\" parameter \\\"${parameter_name}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    if [ \"${function}\" = \"ne\" ]; then\n      command=\"az network nsg rule show --id ${rule_id} --query \\\"${parameter_name}\\\" --output tsv 2> /dev/null\"\n      command_message      \"${command}\"\n      actual_value=$( eval \"${command}\" )\n      if [ \"${actual_value}\" = \"${correct_value}\" ] || [ \"${actual_value}\" = \"*\" ] || [ \"${actual_value}\" = \"\" ]; then\n        inc_insecure \"${description} \\\"${short_id}\\\" parameter \\\"${parameter_name}\\\" is not \\\"${function}\\\" to \\\"${correct_value}\\\" or \\\"*\\\" or \\\"\\\"\"\n      else\n        inc_secure   \"${description} \\\"${short_id}\\\" parameter \\\"${parameter_name}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      fi\n    fi\n  else\n    notice_message   \"NSG Rule ID \\\"${short_id}\\\" is not \\\"${direction}\\\"\"\n  fi\n}\n"
  },
  {
    "path": "functions/azure/security/check_azure_resource_manager_lock.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_resource_manager_lock\n#\n# Check Azure Resource Manager Lock\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_resource_manager_lock () {\n  description=\"${1}\"\n  storage_account=\"${2}\"\n  resource_group=\"${3}\"\n  parameter_name=\"${4}\"\n  function=\"${5}\"\n  correct_value=\"${6}\"\n  resource_type=\"${7}\"\n  print_function \"check_azure_resource_manager_lock\"\n  check_message  \"${description} for Storage Account \\\"${storage_account}\\\" with resource group \\\"${resource_group}\\\" and resource type \\\"${resource_type}\\\" had a \\\"${correct_value}\\\" lock applied\"\n  command=\"az resource lock list --resource-group \\\"${resource_group}\\\" --resource-type \\\"${resource_type}\\\" --resource-name \\\"${storage_account}\\\" --query \\\"${parameter_name}\\\" --output tsv 2> /dev/null\"\n  command_message      \"${command}\"\n  actual_value=$( eval \"${command}\" )\n  if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n    inc_secure   \"Storage Account \\\"${storage_account}\\\" with resource group \\\"${resource_group}\\\" and resource type \\\"${resource_type}\\\" has a \\\"${correct_value}\\\" lock applied\"\n  else\n    inc_insecure \"Storage Account \\\"${storage_account}\\\" with resource group \\\"${resource_group}\\\" and resource type \\\"${resource_type}\\\" does not have a \\\"${correct_value}\\\" lock applied\"\n    fix_message  \"az lock create --name ${correct_value} --resource-group ${resource_group} --resource-name ${storage_account} --resource-type ${resource_type} --lock-type ${correct_value}\"\n  fi\n}\n"
  },
  {
    "path": "functions/azure/security/check_azure_security_contact_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_security_contact_value \n#\n# Check Azure Security Contact value\n#\n# Refer to https://learn.microsoft.com/en-us/cli/azure/security/contact?view=azure-cli-latest\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_security_contact_value () {\n  contact_name=\"${1}\"\n  parameter_name=\"${2}\"\n  function=\"${3}\"\n  correct_value=\"${4}\"\n  print_function \"check_azure_security_contact_value\"\n  check_message  \"Azure Security Contact \\\"${contact_name}\\\" Parameter \\\"${parameter_name}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n  command=\"az security contact show --name \\\"${contact_name}\\\" --query \\\"${parameter_name}\\\" --output tsv 2> /dev/null\"\n  command_message      \"${command}\"\n  actual_value=$( eval \"${command}\" )\n  if [ \"${function}\" = \"eq\" ]; then\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_secure   \"Azure Security Contact \\\"${contact_name}\\\" Parameter \\\"${parameter_name}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    else\n      inc_insecure \"Azure Security Contact \\\"${contact_name}\\\" Parameter \\\"${parameter_name}\\\" is not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      fix_message  \"az security contact update --name ${contact_name} --email <email-address> --notifications-by-role '{\\\"state\\\":\\\"On\\\",\\\"roles\\\":[\\\"Owner\\\"]}' --alert-notifications '{\\\"state\\\":\\\"On\\\",\\\"minimalSeverity\\\":\\\"Low\\\"}'\"\n    fi\n  else\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_secure   \"Azure Security Contact \\\"${contact_name}\\\" Parameter \\\"${parameter_name}\\\" is not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    else\n      inc_insecure \"Azure Security Contact \\\"${contact_name}\\\" Parameter \\\"${parameter_name}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      fix_message  \"az security contact update --name ${contact_name} --email <email-address> --notifications-by-role '{\\\"state\\\":\\\"On\\\",\\\"roles\\\":[\\\"Owner\\\"]}' --alert-notifications '{\\\"state\\\":\\\"On\\\",\\\"minimalSeverity\\\":\\\"Low\\\"}'\"\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/azure/security/check_azure_security_setting.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_security_setting_value\n#\n# Check Azure Security Setting value\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_security_setting_value () {\n  description=\"${1}\"\n  setting_name=\"${2}\"\n  parameter_name=\"${3}\"\n  correct_value=\"${4}\"\n  print_function \"check_azure_security_setting_value\"\n  check_message  \"${description} \\\"${setting_name}\\\" parameter \\\"${parameter_name}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n  command=\"az security setting show --name \\\"${setting_name}\\\" --query \\\"${parameter_name}\\\" --output tsv 2> /dev/null\"\n  command_message      \"${command}\"\n  actual_value=$( eval \"${command}\" )\n  if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n    inc_secure   \"${description} \\\"${setting_name}\\\" parameter \\\"${parameter_name}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n  else\n    inc_insecure \"${description} \\\"${setting_name}\\\" parameter \\\"${parameter_name}\\\" is not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n  fi\n}\n"
  },
  {
    "path": "functions/azure/security/check_azure_waf_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_waf_value\n#\n# Check Azure WAF value\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_waf_value () {\n  waf_name=\"${1}\"\n  policy_name=\"${2}\"\n  resource_group=\"${3}\"\n  query_string=\"${4}\"\n  function=\"${5}\"\n  correct_value=\"${6}\"\n  parameter_name=\"${7}\"\n  parameter_value=\"${8}\"\n  waf_id=\"${waf_name}\"\n  print_function  \"check_azure_waf_value\"\n  if [ \"${policy_name}\" = \"waf-policy\" ]; then\n    check_message \"Azure WAF \\\"${waf_id}\\\" has \\\"${query_string}\\\" ${function} to \\\"${correct_value}\\\"\"\n    if [ \"${query_string}\" = \"managedRules.managedRuleSets\" ]; then\n      command=\"az network application-gateway ${policy_name} show --id \\\"${waf_id}\\\" --query \\\"${query_string}\\\" | grep \\\"${correct_value}\\\" | cut -f4 -d\\\\\\\" 2> /dev/null\"\n    else\n      command=\"az network application-gateway ${policy_name} show --id \\\"${waf_id}\\\" --query \\\"${query_string}\\\" --output tsv 2> /dev/null\"\n    fi\n    command_message      \"${command}\"\n    actual_value=$( eval \"${command}\" )\n    if [ \"${function}\" = \"ne\" ]; then\n      if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n        inc_insecure \"Azure WAF \\\"${waf_id}\\\" does not have \\\"${query_string}\\\" ${function} to \\\"${correct_value}\\\"\"\n      else\n        inc_secure   \"Azure WAF \\\"${waf_id}\\\" has \\\"${query_string}\\\" ${function} to \\\"${correct_value}\\\"\"\n      fi\n    else\n      if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n        inc_secure   \"Azure WAF \\\"${waf_id}\\\" has \\\"${query_string}\\\" ${function} to \\\"${correct_value}\\\"\"\n      else\n        inc_insecure \"Azure WAF \\\"${waf_id}\\\" does not have \\\"${query_string}\\\" ${function} to \\\"${correct_value}\\\"\"\n        if [ \"${parameter_name}\" != \"\" ]; then\n          case \"${parameter_name}\" in\n            \"--\"*)\n              fix_message \"az network application-gateway ${policy_name} update --id \\\"${waf_id}\\\" \\\"${parameter_name}\\\" \\\"${parameter_value}\\\"\"\n              ;;\n            *)\n              fix_message \"az network application-gateway ${policy_name} update --id \\\"${waf_id}\\\" --set \\\"${parameter_name}\\\"=\\\"\\\"${parameter_value}\\\"\"\n              ;;\n          esac\n        fi\n      fi\n    fi\n  else\n    if [ \"${policy_name}\" = \"\" ]; then\n      policy_string=\"\"\n      check_message \"Azure WAF \\\"${waf_name}\\\" in Resource Group \\\"${resource_group}\\\" has \\\"${query_string}\\\" ${function} to \\\"${correct_value}\\\"\"\n      command=\"az network application-gateway show --name \\\"${waf_name}\\\" --resource-group \\\"${resource_group}\\\" --query \\\"${query_string}\\\" --output tsv 2> /dev/null\"\n    else\n      policy_string=\" Policy \\\"${policy_name}\\\"\"\n      check_message \"Azure WAF Policy \\\"${policy_name}\\\" in Resource Group \\\"${resource_group}\\\" has \\\"${query_string}\\\" ${function} to \\\"${correct_value}\\\"\"\n      command=\"az network application-gateway ${policy_name} show --name \\\"${waf_name}\\\" --resource-group \\\"${resource_group}\\\" --query \\\"${query_string}\\\" --output tsv 2> /dev/null\"\n    fi\n    command_message      \"${command}\"\n    actual_value=$( eval \"${command}\" )\n    if [ \"${function}\" = \"ne\" ]; then\n      if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n        inc_insecure \"Azure WAF \\\"${waf_name}\\\"${policy_string} in Resource Group \\\"${resource_group}\\\" does not have \\\"${query_string}\\\" ${function} to \\\"${correct_value}\\\"\"\n      else\n        inc_secure   \"Azure WAF \\\"${waf_name}\\\"${policy_string} in Resource Group \\\"${resource_group}\\\" has \\\"${query_string}\\\" ${function} to \\\"${correct_value}\\\"\"\n      fi\n    else\n      if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n        inc_secure   \"Azure WAF \\\"${waf_name}\\\"${policy_string} in Resource Group \\\"${resource_group}\\\" has \\\"${query_string}\\\" ${function} to \\\"${correct_value}\\\"\"\n      else\n        inc_insecure \"Azure WAF \\\"${waf_name}\\\"${policy_string} in Resource Group \\\"${resource_group}\\\" does not have \\\"${query_string}\\\" ${function} to \\\"${correct_value}\\\"\"\n        if [ \"${parameter_name}\" != \"\" ]; then\n          case \"${parameter_name}\" in\n            \"--\"*)\n              fix_message \"az network application-gateway ${policy_name} update --name \\\"${waf_name}\\\" --resource-group \\\"${resource_group}\\\" \\\"${parameter_name}\\\" \\\"${parameter_value}\\\"\"\n              ;;\n            *)\n              fix_message \"az network application-gateway ${policy_name} update --name \\\"${waf_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${parameter_name}\\\"=\\\"${parameter_value}\\\"\"\n              ;;\n          esac\n        fi\n      fi\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/azure/storage/check_azure_backup_policy_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_backup_policy_value\n#\n# Check Azure Backup policy value\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_backup_policy_value () {\n  description=\"${1}\"\n  policy_name=\"${2}\"\n  vault_name=\"${3}\"\n  resource_group=\"${4}\"\n  query_string=\"${5}\"\n  function=\"${6}\"\n  correct_value=\"${7}\"\n  set_name=\"${8}\"\n  set_value=\"${9}\"\n  print_function \"check_azure_backup_policy_value\"\n  check_message  \"Azure Backup Policy ${description} for policy \\\"${policy_name}\\\" with vault \\\"${vault_name}\\\" with resource group \\\"${resource_group}\\\" and parameter \\\"${query_string}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n  command=\"az backup policy show --name \\\"${policy_name}\\\" --vault-name \\\"${vault_name}\\\" --resource-group \\\"${resource_group}\\\" --query \\\"${query_string}\\\" --output tsv 2> /dev/null\"\n  command_message      \"${command}\"\n  actual_value=$( eval \"${command}\" )\n  if [ \"${function}\" = \"eq\" ]; then\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_secure   \"Azure Backup Policy ${description} for policy \\\"${policy_name}\\\" with vault \\\"${vault_name}\\\" with resource group \\\"${resource_group}\\\" and parameter \\\"${query_string}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    else\n      inc_insecure \"Azure Backup Policy ${description} for policy \\\"${policy_name}\\\" with vault \\\"${vault_name}\\\" with resource group \\\"${resource_group}\\\" and parameter \\\"${query_string}\\\" is not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      if [ ! \"${set_name}\" = \"\" ]; then\n        case \"${set_name}\" in\n          \"--\"*)\n            fix_message \"az backup policy update --name \\\"${policy_name}\\\" --vault-name \\\"${vault_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${correct_value}\\\"\"\n            ;;\n          *)\n            fix_message \"az backup policy update --name \\\"${policy_name}\\\" --vault-name \\\"${vault_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"${correct_value}\\\"\"\n            ;;\n        esac\n      fi\n    fi\n  else\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_insecure \"Azure Backup Policy ${description} for policy \\\"${policy_name}\\\" with vault \\\"${vault_name}\\\" with resource group \\\"${resource_group}\\\" and parameter \\\"${query_string}\\\" is not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      if [ ! \"${set_name}\" = \"\" ]; then\n        case \"${set_name}\" in\n          \"--\"*)\n            fix_message \"az backup policy update --name \\\"${policy_name}\\\" --vault-name \\\"${vault_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${correct_value}\\\"\"\n            ;;\n          *)\n            fix_message \"az backup policy update --name \\\"${policy_name}\\\" --vault-name \\\"${vault_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"${correct_value}\\\"\"\n            ;;\n        esac\n      fi\n    else\n      inc_secure \"Azure Backup Policy ${description} for policy \\\"${policy_name}\\\" with vault \\\"${vault_name}\\\" with resource group \\\"${resource_group}\\\" and parameter \\\"${query_string}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/azure/storage/check_azure_data_factory_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_data_factory_value\n#\n# Check Azure Data Factory value\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_data_factory_value () {\n  description=\"${1}\"\n  data_factory_name=\"${2}\"\n  resource_group=\"${3}\"\n  query_string=\"${4}\"\n  function=\"${5}\"\n  correct_value=\"${6}\"\n  set_name=\"${7}\"\n  set_value=\"${8}\"\n  print_function \"check_azure_data_factory_value\"\n  if [ \"${set_value}\" = \"\" ]; then\n    set_value=\"${correct_value}\"\n  fi\n  check_message \"${description} for Data Factory \\\"${data_factory_name}\\\" with Resource Group \\\"${resource_group}\\\" Parameter \\\"${query_string}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n  command=\"az datafactory show --name \\\"${data_factory_name}\\\" --resource-group \\\"${resource_group}\\\" --query \\\"[].${query_string}\\\" --output tsv\"\n  command_message      \"${command}\"\n  actual_value=$( eval \"${command}\" )\n  if [ \"${function}\" = \"eq\" ]; then\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_secure   \"${description} for Data Factory \\\"${data_factory_name}\\\" with Resource Group \\\"${resource_group}\\\" Parameter \\\"${query_string}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    else\n      inc_insecure \"${description} for Data Factory \\\"${data_factory_name}\\\" with Resource Group \\\"${resource_group}\\\" Parameter \\\"${query_string}\\\" is not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      if [ ! \"${set_name}\" = \"\" ]; then\n        case \"${set_name}\" in\n          \"--\"*)\n            fix_message \"az datafactory update --name \\\"${data_factory_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${set_value}\\\"\"\n            ;;\n          *)\n            fix_message \"az datafactory update --name \\\"${data_factory_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"\\\"${set_value}\\\"\"\n            ;;\n        esac\n      fi\n    fi\n  else\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_insecure \"${description} for Data Factory \\\"${data_factory_name}\\\" with Resource Group \\\"${resource_group}\\\" Parameter \\\"${query_string}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      if [ ! \"${set_name}\" = \"\" ]; then\n        case \"${set_name}\" in\n          \"--\"*)\n            fix_message \"az datafactory update --name \\\"${data_factory_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${set_value}\\\"\"\n            ;;\n          *)\n            fix_message \"az datafactory update --name \\\"${data_factory_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"\\\"${set_value}\\\"\"\n            ;;\n        esac\n      fi\n    else\n      inc_secure  \"${description} for Data Factory \\\"${data_factory_name}\\\" with Resource Group \\\"${resource_group}\\\" Parameter \\\"${query_string}\\\" is not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/azure/storage/check_azure_databox_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_databox_value\n#\n# Check Azure Databox value\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_databox_value () {\n  description=\"${1}\"\n  job_name=\"${2}\"\n  resource_group=\"${3}\"\n  query_string=\"${4}\"\n  function=\"${5}\"\n  correct_value=\"${6}\"\n  set_name=\"${7}\"\n  print_function \"check_azure_databox_value\"\n  check_message  \"${description} for Databox job \\\"${job_name}\\\" in resource group \\\"${resource_group}\\\" has parameter \\\"${query_string}\\\" \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n  command=\"az databox job show --name ${job_name} --resource-group ${resource_group} --query '${query_string}' --output tsv 2> /dev/null\"\n  command_message      \"${command}\"\n  actual_value=$( eval \"${command}\" )\n  if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n    secure_message     \"${description} for Databox job \\\"${job_name}\\\" in resource group \\\"${resource_group}\\\" has parameter \\\"${query_string}\\\" \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n  else\n    insecure_message   \"${description} for Databox job \\\"${job_name}\\\" in resource group \\\"${resource_group}\\\" has parameter \\\"${query_string}\\\" \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    if [ ! \"${set_name}\" = \"\" ]; then\n      case \"${set_name}\" in\n        \"--\"*)\n          fix_message  \"az databox job update --name \\\"${job_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${correct_value}\\\"\"\n          ;;\n        *)\n          fix_message  \"az databox job update --name \\\"${job_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"${correct_value}\\\"\"\n          ;;\n      esac\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/azure/storage/check_azure_databricks_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_databricks_value\n#\n# Check Azure Databricks value\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_databricks_value () {\n  description=\"${1}\"\n  workspace_name=\"${2}\"\n  resource_group=\"${3}\"\n  query_string=\"${4}\"\n  function=\"${5}\"\n  correct_value=\"${6}\"\n  parameter_name=\"${7}\"\n  print_function \"check_azure_databricks_value\"\n  check_message  \"Azure Databricks ${description} for workspace \\\"${workspace_name}\\\" with resource group \\\"${resource_group}\\\" and parameter \\\"${query_string}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n  command=\"az databricks workspace show --name \\\"${workspace_name}\\\" --resource-group \\\"${resource_group}\\\" --query \\\"${query_string}\\\" --output tsv 2> /dev/null\"\n  command_message      \"${command}\"\n  actual_value=$( eval \"${command}\" )\n  if [ \"${function}\" = \"eq\" ]; then\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_secure   \"${description} for workspace \\\"${workspace_name}\\\" with resource group \\\"${resource_group}\\\" and parameter \\\"${query_string}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    else\n      inc_insecure \"${description} for workspace \\\"${workspace_name}\\\" with resource group \\\"${resource_group}\\\" and parameter \\\"${query_string}\\\" is not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      if [ ! \"${parameter_name}\" = \"\" ]; then\n        fix_message \"az databricks workspace update --name \\\"${workspace_name}\\\" --resource-group \\\"${resource_group}\\\" --query \\\"${parameter_name}\\\" --output tsv\"\n      fi\n    fi\n  else\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_insecure  \"${description} for workspace \\\"${workspace_name}\\\" with resource group \\\"${resource_group}\\\" and parameter \\\"${query_string}\\\" is not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      if [ ! \"${parameter_name}\" = \"\" ]; then\n        fix_message \"az databricks workspace update --name \\\"${workspace_name}\\\" --resource-group \\\"${resource_group}\\\" --query \\\"${parameter_name}\\\" --output tsv\"\n      fi\n    else\n      inc_secure    \"${description} for workspace \\\"${workspace_name}\\\" with resource group \\\"${resource_group}\\\" and parameter \\\"${query_string}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/azure/storage/check_azure_elastic_san_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_elastic_san_value\n#\n# Check Azure Elastic SAN value\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_elastic_san_value () {\n  description=\"${1}\"\n  elastic_san_id=\"${2}\"\n  elastic_san_name=\"${3}\"\n  resource_group=\"${4}\"\n  volume_group_name=\"${5}\"\n  query_string=\"${6}\"\n  function=\"${7}\"\n  correct_value=\"${8}\"\n  set_name=\"${9}\"\n  set_value=\"${10}\"\n  print_function \"check_azure_elastic_san_value\"\n  if [ \"${set_value}\" = \"\" ]; then\n    set_value=\"${correct_value}\"\n  fi\n  if [ \"${volume_group_name}\" = \"\" ]; then\n    short_name=$( basename \"${elastic_san_id}\" )\n    check_message \"${description} for Elastic SAN \\\"${short_name}\\\" has Parameter \\\"${query_string}\\\" \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    command=\"az elastic-san show --id \\\"${elastic_san_id}\\\" --query \\\"${query_string}\\\" --output tsv 2> /dev/null\"\n    command_message      \"${command}\"\n    actual_value=$( eval \"${command}\" )\n    if [ \"${function}\" = \"eq\" ]; then\n      if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n        inc_secure   \"${description} for Elastic SAN \\\"${short_name}\\\" has \\\"${query_string}\\\" \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      else\n        inc_insecure \"${description} for Elastic SAN \\\"${short_name}\\\" does not have \\\"${query_string}\\\" \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n        if [ \"${set_name}\" != \"\" ]; then\n          command=\"az elastic-san update --id \\\"${elastic_san_id}\\\" ${set_name} \\\"${set_value}\\\"\"\n          fix_message   \"${command}\"\n        fi\n      fi\n    else\n      if [ \"${function}\" = \"ne\" ]; then\n        if [ \"${actual_value}\" != \"${correct_value}\" ]; then\n          inc_secure    \"${description} for Elastic SAN \\\"${short_name}\\\" has \\\"${query_string}\\\" \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n        else\n          inc_insecure  \"${description} for Elastic SAN \\\"${short_name}\\\" does not have \\\"${query_string}\\\" \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n          if [ \"${set_name}\" != \"\" ]; then\n            command=\"az elastic-san update --id \\\"${elastic_san_id}\\\" ${set_name} \\\"${set_value}\\\"\"\n            fix_message \"${command}\"\n          fi\n        fi\n      fi\n    fi\n  else\n    command=\"az elastic-san volume-group show --resource-group \\\"${resource_group}\\\" --elastic-san \\\"${elastic_san_name}\\\" --name \\\"${volume_group_name}\\\" --query \\\"${query_string}\\\" --output tsv 2> /dev/null\"\n    command_message      \"${command}\"\n    actual_value=$( eval \"${command}\" )\n    if [ \"${function}\" = \"eq\" ]; then\n      if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n        inc_secure   \"${description} for Elastic SAN \\\"${elastic_san_name}\\\" Volume Group \\\"${volume_group_name}\\\" has Parameter \\\"${query_string}\\\" \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      else\n        inc_insecure \"${description} for Elastic SAN \\\"${elastic_san_name}\\\" Volume Group \\\"${volume_group_name}\\\" does not have \\\"${query_string}\\\" \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n        if [ \"${set_name}\" != \"\" ]; then\n          command=\"az elastic-san volume-group update --resource-group \\\"${resource_group}\\\" --elastic-san \\\"${elastic_san_name}\\\" --name \\\"${volume_group_name}\\\" ${set_name} \\\"${set_value}\\\"\"\n          fix_message \"${command}\"\n        fi\n      fi\n    else\n      if [ \"${function}\" = \"ne\" ]; then\n        if [ \"${actual_value}\" != \"${correct_value}\" ]; then\n          inc_secure   \"${description} for Elastic SAN \\\"${elastic_san_name}\\\" Volume Group \\\"${volume_group_name}\\\" has \\\"${query_string}\\\" \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n        else\n          inc_insecure \"${description} for Elastic SAN \\\"${elastic_san_name}\\\" Volume Group \\\"${volume_group_name}\\\" does not have \\\"${query_string}\\\" \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n          if [ \"${set_name}\" != \"\" ]; then\n            command=\"az elastic-san volume-group update --resource-group \\\"${resource_group}\\\" --elastic-san \\\"${elastic_san_name}\\\" --name \\\"${volume_group_name}\\\" ${set_name} \\\"${set_value}\\\"\"\n            fix_message \"${command}\"\n          fi\n        fi\n      fi\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/azure/storage/check_azure_file_share_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_file_share_value\n#\n# Check Azure File Share value\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_file_share_value () {\n  description=\"${1}\"\n  storage_account=\"${2}\"\n  resource_group=\"${3}\"\n  share_propery=\"${4}\"\n  parameter_name=\"${5}\"\n  function=\"${6}\"\n  correct_value=\"${7}\"\n  set_name=\"${8}\"\n  retention_days=\"${9}\"\n  print_function \"check_azure_file_share_value\"\n  check_message  \"${description} for Shares on Storage Account \\\"${storage_account}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n  command=\"az storage account file-${share_propery} show --account-name \\\"${storage_account}\\\" --resource-group \\\"${resource_group}\\\" --query \\\"${parameter_name}\\\" --output tsv 2> /dev/null\"\n  command_message      \"${command}\"\n  actual_value=$( eval \"${command}\" )\n  if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n    inc_secure   \"Shares for Storage Account \\\"${storage_account}\\\" has ${description} \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n  else\n    inc_insecure \"Shares for Storage Account \\\"${storage_account}\\\" does not have ${description} \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    if [ ! -z \"${set_name}\" ]; then\n      case \"${set_name}\" in\n        \"--\"*)\n          if [ \"${retention_days}\" = \"\" ]; then\n            fix_message \"az storage account file-${share_propery} update --name ${storage_account} --resource-group ${resource_group} ${set_name} ${correct_value}\"\n          else\n            fix_message \"az storage account file-${share_propery} update --name ${storage_account} --resource-group ${resource_group} ${set_name} ${correct_value} --retention-days ${retention_days}\"\n          fi\n          ;;\n        *)\n          fix_message   \"az storage account file-${share_propery} update --name ${storage_account} --resource-group ${resource_group} --set ${set_name}=${correct_value}\"\n          ;;\n      esac\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/azure/storage/check_azure_netapp_file_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_netapp_file_value\n#\n# Check Azure NetApp File value\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_netapp_file_value () {\n  description=\"${1}\"\n  storage_account=\"${2}\"\n  resource_group=\"${3}\"\n  parameter_name=\"${4}\"\n  function=\"${5}\"\n  correct_value=\"${6}\"\n  print_function \"check_azure_netapp_file_value\"\n  check_message  \"${description} for Shares on Storage Account \\\"${storage_account}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n  command=\"az netappfiles account show --account-name \\\"${storage_account}\\\" --resource-group \\\"${resource_group}\\\" --query \\\"${parameter_name}\\\" --output tsv 2> /dev/null\"\n  command_message \"${command}\"\n  actual_value=$( eval \"${command}\" )\n  if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n    inc_secure   \"Shares for Storage Account \\\"${storage_account}\\\" has ${description} \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n  else\n    inc_insecure \"Shares for Storage Account \\\"${storage_account}\\\" does not have ${description} \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    if [ \"${parameter_name}\" = \"encryptionKeySource\" ]; then\n      fix_message \"az keyvault set-policy --name <keyvault-name> --object-id <netapp-service-principal-object-id> --key-permissions get wrapKey unwrapKey\"\n      fix_message \"az netappfiles account encryption-key-source update --resource-group <resource-group> --account-name <account-name> --encryption-key-source Microsoft.KeyVault --key-vault-key-uri <key-vault-key-uri>\"\n    else  \n      if [ ! -z \"${set_name}\" ]; then\n        case \"${set_name}\" in\n          \"--\"*)\n            if [ \"${retention_days}\" = \"\" ]; then\n              fix_message \"az netappfiles account update --name ${storage_account} --resource-group ${resource_group} ${set_name} ${correct_value}\"\n            else\n              fix_message \"az netappfiles account update --name ${storage_account} --resource-group ${resource_group} ${set_name} ${correct_value} --retention-days ${retention_days}\"\n            fi\n            ;;\n          *)\n            fix_message   \"az netappfiles account update --name ${storage_account} --resource-group ${resource_group} --set ${set_name}=${correct_value}\"\n            ;;\n        esac\n      fi\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/azure/storage/check_azure_storage_account_container_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_storage_account_container_value\n#\n# Check Azure Storage Account Container value\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_storage_account_container_value () {\n  description=\"${1}\"\n  storage_account=\"${2}\"\n  resource_group=\"${3}\"\n  container_property=\"${4}\"\n  parameter_name=\"${5}\"\n  function=\"${6}\"\n  correct_value=\"${7}\"\n  set_name=\"${8}\"\n  print_function \"check_azure_storage_account_container_value\"\n  if [ \"${resource_group}\" = \"\" ]; then\n    check_message \"${description} for Storage Containers on Storage Account \\\"${storage_account}\\\" is \\\"${correct_value}\\\"\"\n    command=\"az storage account blob-${container_property} show --account-name \\\"${storage_account}\\\" --query \\\"${parameter_name}\\\" --output tsv 2> /dev/null\"\n    command_message      \"${command}\"\n    actual_value=$( eval \"${command}\" )\n  else\n    check_message \"${description} for Storage Containers on Storage Account \\\"${storage_account}\\\" Resource Group \\\"${resource_group}\\\" is \\\"${correct_value}\\\"\"\n    command=\"az storage account blob-${container_property} show --account-name \\\"${storage_account}\\\" --resource-group \\\"${resource_group}\\\" --query \\\"${parameter_name}\\\" --output tsv 2> /dev/null\"\n    command_message      \"${command}\"\n    actual_value=$( eval \"${command}\" )\n  fi\n  if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n    inc_secure   \"${description} for Storage Containers on Storage Account \\\"${storage_account}\\\" has ${description} \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n  else\n    inc_insecure \"${description} for Storage Containers on Storage Account \\\"${storage_account}\\\" does not have ${description} \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    if [ ! -z \"${set_name}\" ]; then\n      if [ \"${resource_group}\" = \"\" ]; then\n        case \"${set_name}\" in\n          \"--\"*)\n            fix_message \"az storage account blob-${container_property} update --account-name ${storage_account} ${set_name} ${correct_value}\"\n            ;;\n          *)\n            fix_message \"az storage account blob-${container_property} update --account-name ${storage_account} --set ${set_name}=${correct_value}\"\n            ;;\n        esac\n      else\n        case \"${set_name}\" in\n          \"--\"*)\n            fix_message \"az storage account blob-${container_property} update --account-name ${storage_account} --resource-group ${resource_group} ${set_name} ${correct_value}\"\n            ;;\n          *)\n            fix_message \"az storage account blob-${container_property} update --account-name ${storage_account} --resource-group ${resource_group} --set ${set_name}=${correct_value}\"\n            ;;\n        esac\n      fi\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/azure/storage/check_azure_storage_account_keys_rotation.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2086\n# shellcheck disable=SC2154\n\n# check_azure_storage_account_keys_rotation\n#\n# Check Azure Storage Account Keys Rotation\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_storage_account_keys_rotation () {\n  storage_account=\"${1}\"\n  resource_id=\"${2}\"\n  correct_value=\"${3}\"\n  print_function \"check_azure_storage_account_keys_rotation\"\n  check_message  \"Storage Account \\\"${storage_account}\\\" has access keys regenerated in the last \\\"${correct_value}\\\" days\"\n  command=\"az monitor activity-log list --namespace Microsoft.Storage --offset ${correct_value}d --query \\\"[?contains(authorization.action, 'regenerateKey')]\\\" --resource-id \\\"${resource_id}\\\" 2> /dev/null |grep \\\"Succeeded\\\"\"\n  command_message      \"${command}\"\n  status_check=$( eval \"${command}\" )\n  if [ -n \"${status_check}\" ]; then\n    inc_secure \"Storage Account \\\"${storage_account}\\\" has access keys regenerated in the last \\\"${correct_value}\\\" days\"\n  else\n    creation_date=$( az storage account show --name \"${storage_account}\" --query \"creationTime\" --output tsv | cut -d T -f 1 )\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      creation_secs=$( date -d \"${creation_date}\" +%s )\n      current_secs=$(  date +%s )\n    else \n      if [ \"${os_name}\" = \"Darwin\" ]; then\n        creation_secs=$( date -j -f \"%Y-%m-%d\" \"${creation_date}\" +%s )\n        current_secs=$(  date +%s )\n      fi\n    fi\n    diff_secs=$(( current_secs - creation_secs ))\n    diff_days=$(( diff_secs / 86400 ))\n    if [ ${diff_days} -le ${correct_value}  ]; then\n      inc_secure   \"Storage Account \\\"${storage_account}\\\" has access keys generated in the last \\\"${correct_value}\\\" days\"\n    else\n      inc_insecure \"Storage Account \\\"${storage_account}\\\" does not have access keys regenerated in the last \\\"${correct_value}\\\" days\"\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/azure/storage/check_azure_storage_account_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_storage_account_value\n#\n# Check Azure Storage Account value\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_storage_account_value () {\n  description=\"${1}\"\n  storage_account=\"${2}\"\n  resource_group=\"${3}\"\n  parameter_name=\"${4}\"\n  function=\"${5}\"\n  correct_value=\"${6}\"\n  set_name=\"${7}\"\n  print_function \"check_azure_storage_account_value\"\n  if [ \"${resource_group}\" = \"\" ]; then\n    check_message \"${description} for Storage Account \\\"${storage_account}\\\" is \\\"${correct_value}\\\"\"\n    command=\"az storage account show --name \\\"${storage_account}\\\" --query \\\"${parameter_name}\\\" --output tsv 2> /dev/null\"\n    command_message      \"${command}\"\n    actual_value=$( eval \"${command}\" )\n    if [ \"${function}\" = \"eq\" ]; then\n      if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n        inc_secure   \"Storage Account \\\"${storage_account}\\\" has ${description} \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      else\n        inc_insecure \"Storage Account \\\"${storage_account}\\\" does not have ${description} \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n        if [ ! -z \"${set_name}\" ]; then\n          case \"${set_name}\" in\n            \"--\"*)\n              fix_message \"az storage account update --name ${storage_account} ${set_name} ${correct_value}\"\n              ;;\n            *)\n              fix_message \"az storage account update --name ${storage_account} --set ${set_name}=${correct_value}\"\n              ;;\n          esac\n        fi\n      fi\n    else\n      if [ \"${function}\" = \"ne\" ]; then\n        if [ \"${actual_value}\" != \"${correct_value}\" ]; then\n          inc_secure   \"Storage Account \\\"${storage_account}\\\" does not have ${description} \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n        else\n          inc_insecure \"Storage Account \\\"${storage_account}\\\" has ${description} \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n          if [ ! -z \"${set_name}\" ]; then\n            case \"${set_name}\" in\n              \"--\"*)\n                fix_message \"az storage account update --name ${storage_account} ${set_name} ${correct_value}\"\n                ;;\n              *)\n                fix_message \"az storage account update --name ${storage_account} --set ${set_name}=${correct_value}\"\n                ;;\n            esac\n          fi\n        fi\n      fi\n    fi\n  else\n    command=\"az storage account show --name \\\"${storage_account}\\\" --query \\\"resourceGroup\\\" --output tsv 2> /dev/null\"\n    command_message      \"${command}\"\n    resource_group=$( eval \"${command}\" )\n    check_message \"${description} for Storage Account \\\"${storage_account}\\\" Resource Group \\\"${resource_group}\\\" is \\\"${correct_value}\\\"\"\n    command=\"az storage account show --name \\\"${storage_account}\\\" --resource-group \\\"${resource_group}\\\" --query \\\"${parameter_name}\\\" --output tsv 2> /dev/null\"\n    command_message      \"${command}\"\n    actual_value=$( eval \"${command}\" )\n    if [ \"${function}\" = \"eq\" ]; then\n      if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n        inc_secure   \"Storage Account \\\"${storage_account}\\\" has ${description} \\\"${function}\\\" to \\\"${correct_value}\\\" for resource group \\\"${resource_group}\\\"\"\n      else\n        inc_insecure \"Storage Account \\\"${storage_account}\\\" does not have ${description} \\\"${function}\\\" to \\\"${correct_value}\\\" for resource group \\\"${resource_group}\\\"\"\n        if [ ! -z \"${set_name}\" ]; then\n          case \"${set_name}\" in\n            \"--\"*)\n              fix_message \"az storage account update --name ${storage_account} --resource-group ${resource_group} ${set_name} ${correct_value}\"\n              ;;\n            *)\n              fix_message \"az storage account update --name ${storage_account} --resource-group ${resource_group} --set ${set_name}=${correct_value}\"\n              ;;\n          esac\n        fi\n      fi\n    else\n      if [ \"${function}\" = \"ne\" ]; then\n        if [ \"${actual_value}\" != \"${correct_value}\" ]; then\n          inc_secure   \"Storage Account \\\"${storage_account}\\\" does not have ${description} \\\"${function}\\\" to \\\"${correct_value}\\\" for resource group \\\"${resource_group}\\\"\"\n        else\n          inc_insecure \"Storage Account \\\"${storage_account}\\\" has ${description} \\\"${function}\\\" to \\\"${correct_value}\\\" for resource group \\\"${resource_group}\\\"\"\n          if [ ! -z \"${set_name}\" ]; then\n            case \"${set_name}\" in\n              \"--\"*)\n                fix_message \"az storage account update --name ${storage_account} --resource-group ${resource_group} ${set_name} ${correct_value}\"\n                ;;\n              *)\n                fix_message \"az storage account update --name ${storage_account} --resource-group ${resource_group} --set ${set_name}=${correct_value}\"\n                ;;\n            esac\n          fi\n        fi\n      fi\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/azure/storage/check_azure_storage_blob_policy_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_storage_blob_policy_value\n#\n# Check Azure Storage Blob Policy value\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_storage_blob_policy_value () {\n  description=\"${1}\"\n  storage_account=\"${2}\"\n  blob_property=\"${5}\"\n  blob_policy=\"${6}\"\n  parameter_name=\"${5}\"\n  function=\"${6}\"\n  correct_value=\"${7}\"\n  set_name=\"${8}\"\n  print_function \"check_azure_storage_blob_policy_value\"\n  check_message  \"${description} for Storage Blobs Property \\\"${blob_property}\\\" Policy \\\"${blob_policy}\\\" on account \\\"${storage_account}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n  if [ \"${azure_auth_mode}\" = \"login\" ]; then\n    command=\"az storage blob ${blob_property} ${blob_policy} show --account-name \\\"${storage_account}\\\" --query \\\"${parameter_name}\\\" --output tsv --auth-mode \\\"${azure_auth_mode}\\\" 2> /dev/null\"\n    command_message      \"${command}\"\n    actual_value=$( eval \"${command}\" )\n  else\n    command=\"az storage blob ${blob_property} ${blob_policy} show --account-name \\\"${storage_account}\\\" --query \\\"${parameter_name}\\\" --output tsv 2> /dev/null\"\n    command_message      \"${command}\"\n    actual_value=$( eval \"${command}\" )\n  fi\n  if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n    inc_secure   \"${description} for Storage Blobs Property \\\"${blob_property}\\\" Policy \\\"${blob_policy}\\\" on account \\\"${storage_account}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n  else\n    inc_insecure \"${description} for Storage Blobs Property \\\"${blob_property}\\\" Policy \\\"${blob_policy}\\\" on account \\\"${storage_account}\\\" is not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    if [ ! -z \"${set_name}\" ]; then\n      case \"${set_name}\" in\n        \"--\"*)\n          fix_message \"az storage blob ${blob_property} ${blob_policy} update --name ${storage_account} ${set_name} ${correct_value}\"\n          ;;\n        *)\n          fix_message \"az storage blob ${blob_property} ${blob_policy} update --name ${storage_account} --set ${set_name}=${correct_value}\"\n          ;;\n      esac\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/azure/storage/check_azure_storage_blob_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_storage_blob_value\n#\n# Check Azure Storage Blob value\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_storage_blob_value () {\n  description=\"${1}\"\n  storage_account=\"${2}\"\n  container_name=\"${3}\"\n  blob_name=\"${4}\"\n  parameter_name=\"${5}\"\n  function=\"${6}\"\n  correct_value=\"${7}\"\n  set_name=\"${8}\"\n  print_function \"check_azure_storage_account_value\"\n  check_message  \"${description} for Storage Blob \\\"${blob_name}\\\" on account \\\"${storage_account}\\\" in container \\\"${container_name}\\\" is \\\"${function} to \\\"${correct_value}\\\"\"\n  if [ \"${azure_auth_mode}\" = \"login\" ]; then\n    command=\"az storage blob ${blob_property} ${blob_policy} show --account-name \\\"${storage_account}\\\" --query \\\"${parameter_name}\\\" --output tsv --auth-mode \\\"${azure_auth_mode}\\\" 2> /dev/null\"\n    command_message      \"${command}\"\n    actual_value=$( eval \"${command}\" )\n  else\n    command=\"az storage blob ${blob_property} ${blob_policy} show --account-name \\\"${storage_account}\\\" --query \\\"${parameter_name}\\\" --output tsv 2> /dev/null\"\n    command_message      \"${command}\"\n    actual_value=$( eval \"${command}\" )\n  fi\n  if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n    inc_secure   \"${description} for Storage Blob \\\"${blob_name}\\\" on account \\\"${storage_account}\\\" in container \\\"${container_name}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n  else\n    inc_insecure \"${description} for Storage Blob \\\"${blob_name}\\\" on account \\\"${storage_account}\\\" in container \\\"${container_name}\\\" is not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    if [ ! -z \"${set_name}\" ]; then\n      case \"${set_name}\" in\n        \"--\"*)\n          fix_message \"az storage blob ${blob_property} ${blob_policy} update --name ${storage_account} ${set_name} ${correct_value}\"\n          ;;\n        *)\n          fix_message \"az storage blob ${blob_property} ${blob_policy} update --name ${storage_account} --set ${set_name}=${correct_value}\"\n          ;;\n      esac\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/azure/storage/check_azure_storage_container_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_storage_container_value\n#\n# Check Azure Storage Container value\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_storage_container_value () {\n  description=\"${1}\"\n  storage_account=\"${2}\"\n  container_name=\"${3}\"\n  query_string=\"${4}\"\n  function=\"${5}\"\n  correct_value=\"${6}\"\n  print_function \"check_azure_storage_container_value\"\n  check_message  \"${description} for Storage Container \\\"${container_name}\\\" for Storage Account \\\"${storage_account}\\\" has Parameter \\\"${query_string}\\\" \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n  command=\"az storage container show --account-name \\\"${storage_account}\\\" --name \\\"${container_name}\\\" --query \\\"${query_string}\\\" --auth-mode \\\"${azure_auth_mode}\\\" --output tsv 2> /dev/null\"\n  command_message      \"${command}\"\n  actual_value=$( eval \"${command}\" )\n  if [ \"${function}\" = \"eq\" ]; then\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_secure   \"${description} for Storage Container \\\"${container_name}\\\" on Storage Account \\\"${storage_account}\\\" has \\\"${query_string}\\\" \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    else\n      inc_insecure \"${description} for Storage Container \\\"${container_name}\\\" on Storage Account \\\"${storage_account}\\\" does not have \\\"${query_string}\\\" \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    fi\n  elif [ \"${function}\" = \"ne\" ]; then\n    if [ \"${actual_value}\" != \"${correct_value}\" ]; then\n      inc_secure   \"${description} for Storage Container \\\"${container_name}\\\" on Storage Account \\\"${storage_account}\\\" has \\\"${query_string}\\\" \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    else\n      inc_insecure \"${description} for Storage Container \\\"${container_name}\\\" on Storage Account \\\"${storage_account}\\\" does not have \\\"${query_string}\\\" \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/azure/storage/check_azure_storage_fs_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_storage_fs_value\n#\n# Check Azure Storage File System value\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_storage_fs_value () {\n  description=\"${1}\"\n  storage_account=\"${2}\"\n  file_system=\"${3}\"\n  query_string=\"${4}\"\n  function=\"${5}\"\n  correct_value=\"${6}\"  \n  print_function \"check_azure_storage_fs_value\"\n  check_message  \"${description} for File System \\\"${file_system}\\\" for Storage Account \\\"${storage_account}\\\" has Parameter \\\"${query_string}\\\" \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n  command=\"az storage fs show --account-name \\\"${storage_account}\\\" --name \\\"${file_system}\\\" --query \\\"${query_string}\\\" --auth-mode \\\"${azure_auth_mode}\\\" --output tsv 2> /dev/null\"\n  command_message      \"${command}\"\n  actual_value=$( eval \"${command}\" )\n  if [ \"${function}\" = \"eq\" ]; then\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_secure   \"${description} for File System \\\"${file_system}\\\" on Storage Account \\\"${storage_account}\\\" has \\\"${query_string}\\\" \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    else\n      inc_insecure \"${description} for File System \\\"${file_system}\\\" on Storage Account \\\"${storage_account}\\\" does not have \\\"${query_string}\\\" \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    fi\n  elif [ \"${function}\" = \"ne\" ]; then\n    if [ \"${actual_value}\" != \"${correct_value}\" ]; then\n      inc_secure   \"${description} for File System \\\"${file_system}\\\" on Storage Account \\\"${storage_account}\\\" has \\\"${query_string}\\\" \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    else\n      inc_insecure \"${description} for File System \\\"${file_system}\\\" on Storage Account \\\"${storage_account}\\\" does not have \\\"${query_string}\\\" \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    fi\n  fi\n}"
  },
  {
    "path": "functions/azure/vaults/check_azure_backup_vault_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_backup_vault_value\n#\n# Check Azure Backup value\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_backup_vault_value () {\n  description=\"${1}\"\n  vault_name=\"${2}\"\n  resource_group=\"${3}\"\n  query_string=\"${4}\"\n  function=\"${5}\"\n  correct_value=\"${6}\"\n  set_name=\"${7}\"\n  print_function \"check_azure_backup_vault_value\"\n  check_message  \"Azure Backup Vault ${description} for vault \\\"${vault_name}\\\" with resource group \\\"${resource_group}\\\" and parameter \\\"${query_string}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n  command=\"az dataprotection backup-vault show --name \\\"${vault_name}\\\" --resource-group \\\"${resource_group}\\\" --query \\\"${query_string}\\\" --output tsv 2> /dev/null\"\n  command_message      \"${command}\"\n  actual_value=$( eval \"${command}\" )\n  if [ \"${function}\" = \"eq\" ]; then\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_secure    \"Azure Backup Vault ${description} for vault \\\"${vault_name}\\\" with resource group \\\"${resource_group}\\\" and parameter \\\"${query_string}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    else\n      inc_insecure  \"Azure Backup Vault ${description} for vault \\\"${vault_name}\\\" with resource group \\\"${resource_group}\\\" and parameter \\\"${query_string}\\\" is not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      if [ \"${query_string}\" = \"properties.encryption.keyUri\" ]; then\n        fix_message \"az keyvault set-policy --name <keyvault-name> --object-id <vault-managed-identity-object-id> --key-permissions get wrapKey unwrapKey\"\n        fix_message \"az backup vault encryption enable --resource-group <resource-group> --vault-name <vault-name> --key-uri <key-vault-key-uri>\"\n      else\n        if [ ! \"${set_name}\" = \"\" ]; then\n          case \"${set_name}\" in\n            \"--\"*)\n              fix_message \"az backup vault update --name \\\"${vault_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${correct_value}\\\"\"\n              ;;\n            *)\n              fix_message \"az backup vault update --name \\\"${vault_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"${correct_value}\\\"\"\n              ;;\n          esac\n        fi\n      fi\n    fi\n  else\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_insecure \"Azure Backup Vault ${description} for vault \\\"${vault_name}\\\" with resource group \\\"${resource_group}\\\" and parameter \\\"${query_string}\\\" is not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      if [ \"${query_string}\" = \"properties.encryption.keyUri\" ]; then\n        fix_message \"az keyvault set-policy --name <keyvault-name> --object-id <vault-managed-identity-object-id> --key-permissions get wrapKey unwrapKey\"\n        fix_message \"az backup vault encryption enable --resource-group <resource-group> --vault-name <vault-name> --key-uri <key-vault-key-uri>\"\n      else\n        if [ ! \"${set_name}\" = \"\" ]; then\n          case \"${set_name}\" in\n            \"--\"*)\n              fix_message \"az backup vault update --name \\\"${vault_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${correct_value}\\\"\"\n              ;;\n            *)\n              fix_message \"az backup vault update --name \\\"${vault_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"${correct_value}\\\"\"\n              ;;\n          esac\n        fi\n      fi\n    else\n      inc_secure \"Azure Backup Vault ${description} for vault \\\"${vault_name}\\\" with resource group \\\"${resource_group}\\\" and parameter \\\"${query_string}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/azure/vaults/check_azure_key_vault_key_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_key_vault_key_value\n#\n# Check Azure Key Vault key value\n#\n# This requires the Azure CLI to be installed and configured\n# Audit account needs to have the 'Key Vault Reader' role\n# To do any changes to the key vaults, the 'Key Vault Administrator' role is required\n#.\n\ncheck_azure_key_vault_key_value () {\n  key_vault=\"${1}\"\n  key_name=\"${2}\"\n  parameter_name=\"${3}\"\n  function=\"${4}\"\n  correct_value=\"${5}\"\n  policy_name=\"${6}\"\n  action_value=\"${7}\"\n  print_function \"check_azure_key_vault_key_value\"\n  check_message  \"Key \\\"${key_name}\\\" in key vault \\\"${key_vault}\\\" with parameter \\\"${parameter_name}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n  if [ \"${policy_name}\" = \"\" ]; then\n    command=\"az keyvault key show --vault-name \\\"${key_vault}\\\" --name \\\"${key_name}\\\" --query \\\"${parameter_name}\\\" --output tsv 2> /dev/null\"\n    command_message      \"${command}\"\n    actual_value=$( eval \"${command}\" )\n  else\n    if [ \"${parameter_name}\" = \"\" ]; then\n      query_string=\"lifetimeActions[?contains(action, '${action_value}')]\"\n    else\n      query_string=\"lifetimeActions[?contains(action, '${action_value}')].${parameter_name}\"\n    fi\n    command=\"az keyvault key ${policy_name} show --vault-name \\\"${key_vault}\\\" --name \\\"${key_name}\\\" --query \\\"${query_string}\\\" --output tsv 2> /dev/null\"\n    command_message      \"${command}\"\n    actual_value=$( eval \"${command}\" )\n  fi\n  if [ \"${function}\" = \"eq\" ]; then\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_secure   \"Key \\\"${key_name}\\\" in key vault \\\"${key_vault}\\\" with parameter \\\"${parameter_name}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    else\n      inc_insecure \"Key \\\"${key_name}\\\" in key vault \\\"${key_vault}\\\" with parameter \\\"${parameter_name}\\\" is not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    fi\n  else\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_insecure \"Key \\\"${key_name}\\\" in key vault \\\"${key_vault}\\\" with parameter \\\"${parameter_name}\\\" is not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    else\n      inc_secure   \"Key \\\"${key_name}\\\" in key vault \\\"${key_vault}\\\" with parameter \\\"${parameter_name}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/azure/vaults/check_azure_key_vault_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_key_vault_value\n#\n# Check Azure Key Vault value\n#\n# This requires the Azure CLI to be installed and configured\n# Audit account needs to have the 'Key Vault Reader' role\n# To do any changes to the key vaults, the 'Key Vault Administrator' role is required\n#.\n\ncheck_azure_key_vault_value () {\n  resource_name=\"${1}\"\n  resource_group=\"${2}\"\n  parameter_name=\"${3}\"\n  function=\"${4}\"\n  correct_value=\"${5}\"\n  set_name=\"${6}\"\n  print_function \"check_azure_key_vault_value\"\n  check_message  \"Key vault with resource name \\\"${resource_name}\\\" in resource group \\\"${resource_group}\\\" with parameter \\\"${parameter_name}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n  command=\"az keyvault show --resource-group \\\"${resource_group}\\\" --name \\\"${resource_name}\\\" --query \\\"${parameter_name}\\\" --output tsv 2> /dev/null\"\n  command_message      \"${command}\"\n  actual_value=$( eval \"${command}\" )\n  if [ \"${function}\" = \"eq\" ]; then\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_secure    \"Key vault with resource name \\\"${resource_name}\\\" in resource group \\\"${resource_group}\\\" with parameter \\\"${parameter_name}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    else\n      inc_insecure  \"Key vault with resource name \\\"${resource_name}\\\" in resource group \\\"${resource_group}\\\" with parameter \\\"${parameter_name}\\\" is not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      if [ ! \"${set_name}\" = \"\" ]; then\n        fix_message \"az keyvault update --resource-group ${resource_group} --name ${resource_name} ${set_name} ${correct_value}\"\n      fi\n    fi\n  else\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_insecure    \"Key vault with resource name \\\"${resource_name}\\\" in resource group \\\"${resource_group}\\\" with parameter \\\"${parameter_name}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      if [ ! \"${set_name}\" = \"\" ]; then\n        fix_message   \"az keyvault update --resource-group ${resource_group} --name ${resource_name} ${set_name} ${correct_value}\"\n      else\n        if [ \"${parameter_name}\" = \"properties.privateEndpointConnections\" ]; then\n          fix_message \"1. To create an endpoint, run the following command:\"\n          fix_message \"az network private-endpoint create --resource-group <resourceGroup> --vnet-name <vnetName> --subnet <subnetName> --name <PrivateEndpointName> \\ \"\n          fix_message \"--private-connection-resource-id \\\"/subscriptions/<AZURE SUBSCRIPTION ID>/resourceGroups/<resourceGroup>/providers/Microsoft.KeyVault/vaults/<keyVaultName>\\\" \\ \"\n          fix_message \"--group-ids vault --connection-name <privateLinkConnectionName> --location <azureRegion> --manual-request\"\n          fix_message \"2. To manually approve the endpoint request, run the following command:\"\n          fix_message \"az keyvault private-endpoint-connection approve --resource-group <resourceGroup> --vault-name <keyVaultName> –name <privateLinkName>\"\n          fix_message \"3. Determine the Private Endpoint's IP address to connect the Key Vault to the Private DNS you have previously created:\"\n          fix_message \"4. Look for the property networkInterfaces then id; the value must be placed in the variable <privateEndpointNIC> within step 7.\"\n          fix_message \"az network private-endpoint show -g <resourceGroupName> -n <privateEndpointName>\"\n          fix_message \"5. Look for the property networkInterfaces then id; the value must be placed on <privateEndpointNIC> in step 7.\"\n          fix_message \"az network nic show --ids <privateEndpointName>\"\n          fix_message \"6. Create a Private DNS record within the DNS Zone you created for the Private Endpoint:\"\n          fix_message \"az network private-dns record-set a add-record -g <resourcecGroupName> -z \\\"privatelink.vaultcore.azure.net\\\" -n <keyVaultName> -a <privateEndpointNIC>\"\n          fix_message \"7. nslookup the private endpoint to determine if the DNS record is correct:\"\n          fix_message \"nslookup <keyVaultName>.vault.azure.net\"\n          fix_message \"nslookup <keyVaultName>.privatelink.vaultcore.azure.net\"\n        fi\n      fi\n    else\n      inc_secure \"Key vault with resource name \\\"${resource_name}\\\" in resource group \\\"${resource_group}\\\" with parameter \\\"${parameter_name}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/azure/vaults/check_azure_recovery_services_vault_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_azure_recovery_services_vault_value\n#\n# Check Azure Recovery Services Vault value\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\ncheck_azure_recovery_services_vault_value () {\n  description=\"${1}\"\n  vault_name=\"${2}\"\n  resource_group=\"${3}\"\n  query_string=\"${4}\"\n  function=\"${5}\"\n  correct_value=\"${6}\"\n  set_name=\"${7}\"\n  print_function \"check_azure_recovery_services_vault_value\"\n  check_message  \"Azure Recovery Services Vault ${description} for vault \\\"${vault_name}\\\" with resource group \\\"${resource_group}\\\" and parameter \\\"${query_string}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n  command=\"az dataprotection backup-vault show --name \\\"${vault_name}\\\" --resource-group \\\"${resource_group}\\\" --query \\\"${query_string}\\\" --output tsv 2> /dev/null\"\n  command_message      \"${command}\"\n  actual_value=$( eval \"${command}\" )\n  if [ \"${function}\" = \"eq\" ]; then\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_secure    \"Azure Recovery Services Vault ${description} for vault \\\"${vault_name}\\\" with resource group \\\"${resource_group}\\\" and parameter \\\"${query_string}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    else\n      inc_insecure  \"Azure Recovery Services Vault ${description} for vault \\\"${vault_name}\\\" with resource group \\\"${resource_group}\\\" and parameter \\\"${query_string}\\\" is not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      if [ \"${query_string}\" = \"properties.encryption.keyUri\" ]; then\n        fix_message \"az keyvault set-policy --name <keyvault-name> --object-id <vault-managed-identity-object-id> --key-permissions get wrapKey unwrapKey\"\n        fix_message \"az dataprotection backup-vault encryption enable --resource-group <resource-group> --vault-name <vault-name> --key-uri <key-vault-key-uri>\"\n      else\n        if [ ! \"${set_name}\" = \"\" ]; then\n          case \"${set_name}\" in\n            \"--\"*)\n              fix_message \"az dataprotection backup-vault update --name \\\"${vault_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${correct_value}\\\"\"\n              ;;\n            *)\n              fix_message \"az dataprotection backup-vault update --name \\\"${vault_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"${correct_value}\\\"\"\n              ;;\n          esac\n        fi\n      fi\n    fi\n  else\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_insecure \"Azure Recovery Services Vault ${description} for vault \\\"${vault_name}\\\" with resource group \\\"${resource_group}\\\" and parameter \\\"${query_string}\\\" is not \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n      if [ \"${query_string}\" = \"properties.encryption.keyUri\" ]; then\n        fix_message \"az keyvault set-policy --name <keyvault-name> --object-id <vault-managed-identity-object-id> --key-permissions get wrapKey unwrapKey\"\n        fix_message \"az dataprotection backup-vault encryption enable --resource-group <resource-group> --vault-name <vault-name> --key-uri <key-vault-key-uri>\"\n      else\n        if [ ! \"${set_name}\" = \"\" ]; then\n          case \"${set_name}\" in\n            \"--\"*)\n              fix_message \"az dataprotection backup-vault update --name \\\"${vault_name}\\\" --resource-group \\\"${resource_group}\\\" ${set_name} \\\"${correct_value}\\\"\"\n              ;;\n            *)\n              fix_message \"az dataprotection backup-vault update --name \\\"${vault_name}\\\" --resource-group \\\"${resource_group}\\\" --set \\\"${set_name}\\\"=\\\"${correct_value}\\\"\"\n              ;;\n          esac\n        fi\n      fi\n    else\n      inc_secure \"Azure Recovery Services Vault ${description} for vault \\\"${vault_name}\\\" with resource group \\\"${resource_group}\\\" and parameter \\\"${query_string}\\\" is \\\"${function}\\\" to \\\"${correct_value}\\\"\"\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/command/check_command_output.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_command_output\n#\n# Code to test command output\n#.\n\ncheck_command_output () {\n  print_function \"check_command_output\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    command_name=\"${1}\"\n    if [ \"${command_name}\" = \"getcond\" ]; then\n      get_command=\"auditconfig -getcond |cut -f2 -d'=' |sed 's/ //g'\"\n    fi\n    if [ \"${command_name}\" = \"getpolicy\" ]; then\n      get_command=\"auditconfig -getpolicy |head -1 |cut -f2 -d'=' |sed 's/ //g'\"\n      correct_value=\"argv,cnt,zonename\"\n      audit_command=\"auditconfig -setpolicy\"\n    fi\n    if [ \"${command_name}\" = \"getnaflages\" ]; then\n      get_command=\"auditconfig -getpolicy |head -1 |cut -f2 -d'=' |sed 's/ //g' |cut -f1 -d'('\"\n      correct_value=\"lo\"\n      audit_command=\"auditconfig -setnaflags\"\n    fi\n    if [ \"${command_name}\" = \"getflages\" ]; then\n      get_command=\"auditconfig -getflags |head -1 |cut -f2 -d'=' |sed 's/ //g' |cut -f1 -d'('\"\n      correct_value=\"lck,ex,aa,ua,as,ss,lo,ft\"\n      audit_command=\"auditconfig -setflags\"\n    fi\n    if [ \"${command_name}\" = \"getplugin\" ]; then\n      get_command=\"auditconfig -getplugin audit_binfile |tail-1 |cut -f3 -d';'\"\n      correct_value=\"p_minfree=1\"\n      audit_command=\"auditconfig -setplugin audit_binfile active\"\n    fi\n    if [ \"${command_name}\" = \"userattr\" ]; then\n      get_command=\"userattr audit_flags root\"\n      correct_value=\"lo,ad,ft,ex,lck:no\"\n      audit_command=\"auditconfig -setplugin audit_binfile active\"\n    fi\n    if [ \"${command_name}\" = \"getcond\" ]; then\n      set_command=\"auditconfig -conf\"\n    else\n      if [ \"${command_name}\" = \"getflags\" ]; then\n        set_command=\"${audit_command} lo,ad,ft,ex,lck\"\n      else\n        set_command=\"${audit_command} ${correct_value}\"\n      fi\n    fi\n    log_file=\"${command_name}.log\"\n    check_value=$( ${get_command} )\n    if [ \"${audit_mode}\" != 2 ]; then\n      string=\"Command \\\"${command_name}\\\" returns \\\"${correct_value}\\\"\"\n      check_message  \"${string}\"\n       if [ \"${ansible_mode}\" = 1 ]; then\n        ansible_counter=$((ansible_counter+1))\n        ansible_value=\"check_command_output_${command_name}_${ansible_counter}\"\n        echo \"\"\n        echo \"- name: Checking ${string}\"\n        echo \"  command: sh -c \\\"${get_command} |grep '${correct_value}'\\\"\"\n        echo \"  register: ${ansible_value}\"\n        echo \"  failed_when: ${ansible_value} == 1\"\n        echo \"  changed_when: false\"\n        echo \"  ignore_errors: true\"\n        echo \"  when: ansible_facts['ansible_system'] == '${os_name}'\"\n        echo \"\"\n        echo \"- name: Fixing ${string}\"\n        echo \"  command: sh -c \\\"${set_command}\\\"\"\n        echo \"  when: ${ansible_value}.rc == 1 and ansible_facts['ansible_system'] == '${os_name}'\"\n        echo \"\"\n      fi\n      if [ \"${check_value}\" != \"${correct_value}\" ]; then\n        inc_insecure \"Command \\\"${command_name}\\\" does not return correct value\"\n      else\n        inc_secure   \"Command \\\"${command_name}\\\" returns correct value\"\n      fi\n      update_log  \"${log_file}\" \"${audit_command}\"\n      lock_message=\"Command \\\"${command_name}\\\" to correct value\"\n      lock_command=\"${set_command}\"\n      run_lockdown    \"${lock_command}\" \"${lock_message}\" \"sudo\"\n    fi\n    if [ \"${audit_mode}\" = 2 ]; then\n      restore_file=\"${restore_dir}/${log_file}\"\n      if [ -f \"${restore_file}\" ]; then\n        restore_message=\"Restoring: Previous value for \\\"${command_name}\\\"\"\n        if [ \"${command_name}\" = \"getcond\" ]; then\n          restore_command=\"${audit_command}\"\n          execute_restore \"${restore_command}\" \"${restore_message}\" \"sudo\"\n        else\n          restore_string=$( cat \"${restore_file}\" )\n          restore_command=\"${audit_command} ${restore_string}\"\n          execute_restore \"${restore_command}\" \"${restore_message}\" \"sudo\"\n        fi\n      fi\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/command/check_command_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_command_value\n#\n# Audit command output values\n#\n# Depending on the command_name send an appropriate check_command and set_command are set\n# If the current_value is not the correct_value then it is fixed if run in lockdown mode\n# A copy of the value is stored in a log file, which can be restored\n#.\n\ncheck_command_value () {\n  command_name=\"${1}\"\n  parameter_name=\"${2}\"\n  correct_value=\"${3}\"\n  service_name=\"${4}\"\n  print_function \"check_command_value\"\n  if [ \"${audit_mode}\" = 2 ]; then\n    restore_file=\"${restore_dir}/${command_name}.log\"\n    if [ -f \"${restore_file}\" ]; then\n      parameter_name=$( grep \"${parameter_name}\" \"${restore_file}\" | cut -f1 -d',' )\n      correct_value=$(  grep \"${parameter_name}\" \"${restore_file}\" | cut -f2 -d',' )\n      package_test=$(   echo \"${parameter_name}\" | grep \"[A-z]\" )\n      if [ -n \"${package_test}\" ]; then\n        verbose_message \"Returning \\\"${parameter_name}\\\" to \\\"${correct_value}\\\"\"\n        if [ \"${command_name}\" = \"routeadm\" ]; then\n          if [ \"${correct_value}\" = \"disabled\" ]; then\n            set_command=\"routeadm -d\"\n          else\n            set_command=\"routeadm -e\"\n          fi\n          eval \"${set_command} ${parameter_name}\"\n        else\n          eval \"${set_command} ${parameter_name}=${correct_value}\"\n          package_test=$( echo \"${parameter_name}\" | grep \"tcp_trace\" )\n          if [ -n \"${package_test}\" ]; then\n            svcadm refresh svc:/network/inetd\n          fi\n        fi\n      fi\n    fi\n  else\n    if [ \"${parameter_name}\" = \"tcp_wrappers\" ]; then\n      string=\"Service \\\"${service_name}\\\" has \\\"${parameter_name}\\\" set to \\\"${correct_value}\\\"\"\n    else\n      string=\"Output of command \\\"${command_name}\\\" parameter \\\"${parameter_name}\\\" is \\\"${correct_value}\\\"\"\n    fi\n   check_message  \"${string}\"\n  fi\n  if [ \"${command_name}\" = \"inetadm\" ]; then\n    check_command=\"inetadm -l ${service_name}\"\n    set_command=\"inetadm -m ${service_name}\"\n    current_value=$( $check_command | grep \"${parameter_name}\" | awk '{print $2}' | cut -f2 -d'=' )\n  fi\n  if [ \"${command_name}\" = \"routeadm\" ]; then\n    check_command=\"routeadm -p ${parameter_name}\"\n    current_value=$( $check_command | awk '{print $3}' | cut -f2 -d'=' )\n    if [ \"${correct_value}\" = \"disabled\" ]; then\n      set_command=\"routeadm -d\"\n    else\n      set_command=\"routeadm -e\"\n    fi\n    lock_command=\"${set_command} ${parameter_name}\"\n  else\n    lock_command=\"${set_command} ${parameter_name}=${correct_value}\"\n  fi\n  if [ \"${ansible_mode}\" = 1 ]; then\n    ansible_counter=$((ansible_counter+1))\n    ansible_value=\"check_command_value_${command_name}_${ansible_counter}\"\n    echo \"\"\n    echo \"- name: Checking ${string}\"\n    echo \"  command: sh -c \\\"$check_command\\\"\"\n    echo \"  register: ${ansible_value}\"\n    echo \"  failed_when: ${ansible_value} == 1\"\n    echo \"  changed_when: false\"\n    echo \"  ignore_errors: true\"\n    echo \"  when: ansible_facts['ansible_system'] == '${os_name}'\"\n    echo \"\"\n    echo \"- name: Fixing ${string}\"\n    echo \"  command: sh -c \\\"${lock_command}\\\"\"\n    echo \"  when: ${ansible_value}.rc == 1 and ansible_facts['ansible_system'] == '${os_name}'\"\n    echo \"\"\n  fi\n  log_file=\"${command_name}.log\"\n  if [ \"${current_value}\" != \"${correct_value}\" ]; then\n    if [ \"${audit_mode}\" = 1 ]; then\n      inc_insecure \"Parameter \\\"${parameter_name}\\\" not set to \\\"${correct_value}\\\"\"\n      if [ \"${command_name}\" = \"routeadm\" ]; then\n        if [ \"${correct_value}\" = \"disabled\" ]; then\n          set_command=\"routeadm -d\"\n        else\n          set_command=\"routeadm -e\"\n        fi\n        lock_command=\"${set_command} ${parameter_name}\"\n        fix_message  \"${lock_command}\"\n      else\n        lock_command=\"${set_command} ${parameter_name}=${correct_value}\"\n        fix_message  \"${lock_command}\"\n      fi\n    else\n      if [ \"${audit_mode}\" = 0 ]; then\n        update_log  \"${log_file}\" \"${parameter_name},${current_value}\"\n        lock_message=\"Parameter ${parameter_name} to ${correct_value}\"\n        if [ \"${command_name}\" = \"routeadm\" ]; then\n          if [ \"${correct_value}\" = \"disabled\" ]; then\n            set_command=\"routeadm -d\"\n          else\n            set_command=\"routeadm -e\"\n          fi\n          lock_command=\"${set_command} ${parameter_name}\"\n          run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n        else\n          lock_command=\"${set_command} ${parameter_name}=${correct_value}\"\n          run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n        fi \n      fi\n    fi\n  else\n    if [ \"${audit_mode}\" != 2 ]; then\n      if [ \"${audit_mode}\" = 1 ]; then\n        if [ \"${parameter_name}\" = \"tcp_wrappers\" ]; then\n          inc_secure \"Service \\\"${service_name}\\\" already has \\\"${parameter_name}\\\" set to \\\"${correct_value}\\\"\"\n        else\n          inc_secure \"Output for command \\\"${command_name}\\\" parameter \\\"${parameter_name}\\\" already set to \\\"${correct_value}\\\"\"\n        fi\n      fi\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/darwin/check_dscl.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_dscl\n#\n# Function to check dscl output under OS X\n#.\n\ncheck_dscl () {\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    file=\"${1}\"\n    param=\"${2}\"\n    value=\"${3}\"\n    print_function \"check_dscl\"\n    dir=\"/var/db/dslocal/nodes/Default\"\n    if [ \"${audit_mode}\" != 2 ]; then\n      string=\"Parameter \\\"${param}\\\" is set to \\\"${value}\\\" in \\\"${file}\\\"\"\n      check_message  \"${string}\"\n      if [ \"${ansible_mode}\" = 1 ]; then\n        ansible_counter=$((ansible_counter+1))\n        ansible_value=\"check_dscl_${ansible_counter}\"\n        echo \"\"\n        echo \"- name: Checking ${string}\"\n        echo \"  command: sh -c \\\"sudo dscl . -read ${file} ${param} 2> /dev/null\\\"\"\n        echo \"  register: ${ansible_value}\"\n        echo \"  failed_when: ${ansible_value} == 1\"\n        echo \"  changed_when: false\"\n        echo \"  ignore_errors: true\"\n        echo \"  when: ansible_facts['ansible_system'] == '${os_name}'\"\n        echo \"\"\n        echo \"- name: Fixing ${string}\"\n        echo \"  command: sh -c \\\"sudo dscl . -create ${file} ${param} '${value}'\\\"\"\n        echo \"  when: ${ansible_value}.rc == 1 and ansible_facts['ansible_system'] == '${os_name}'\"\n        echo \"\"\n      fi\n      command=\"sudo dscl . -read \\\"${file}\\\" \\\"${param}\\\" 2> /dev/null | wc -l | sed \\\"s/ //g\\\"\"\n      command_message \"${command}\"\n      d_check=$( eval \"${command}\" )\n      if [ \"${d_check}\" = \"0\" ]; then\n        check=\"not-found\"\n      else\n        command=\"sudo dscl . -read \\\"${file}\\\" \\\"${param}\\\" 2> /dev/null\"\n        command_message \"${command}\"\n        check=$( eval   \"${command}\" )\n      fi\n      if [ \"${check}\" != \"${value}\" ]; then\n        inc_insecure \"Parameter \\\"${param}\\\" not set to \\\"${value}\\\" in \\\"${file}\\\"\"\n        fix_message  \"sudo dscl . -create ${file} ${param} \\\"${value}\\\"\"\n        if [ \"${audit_mode}\" = 0 ]; then\n          backup_file  \"${dir}/${file}\"\n          lock_message=\"Parameter \\\"${param}\\\" to \\\"${value}\\\" in ${file}\"\n          lock_command=\"dscl . -create ${file} ${param} ${value}\"\n          run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n        fi\n      else\n        if [ \"${audit_mode}\" = 1 ]; then\n          inc_secure \"Parameter \\\"${param}\\\" is set to \\\"${value}\\\" in \\\"${file}\\\"\"\n        fi\n      fi\n    else\n      restore_file   \"${dir}/${file}\" \"${restore_dir}\"\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/darwin/check_launchctl_service.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_launchctl_service\n#\n# Function to check launchctl output under OS X\n#.\n\ncheck_launchctl_service () {\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    launchctl_service=\"${1}\"\n    required_status=\"${2}\"\n    print_function  \"check_launchctl_service\"\n    log_file=\"${launchctl_service}.log\"\n    if [ \"${required_status}\" = \"on\" ] || [ \"${required_status}\" = \"enable\" ]; then\n      required_status=\"enabled\"\n      change_status=\"load\"\n    else\n      required_status=\"disabled\"\n      change_status=\"unload\"\n    fi\n    get_command=\"launchctl list |grep ${launchctl_service} |awk '{print \\$3}'\"\n    set_command=\"sudo launchctl ${change_status} -w ${launchctl_service}.plist\"\n    check_value=$( eval \"${get_command}\" )\n    if [ \"${check_value}\" = \"${launchctl_service}\" ]; then\n      actual_status=\"enabled\"\n    else\n      actual_status=\"disabled\"\n    fi\n    if [ \"${audit_mode}\" != 2 ]; then\n      string=\"Service \\\"${launchctl_service}\\\" is \\\"${required_status}\\\"\"\n      check_message  \"${string}\"\n      if [ \"${ansible_mode}\" = 1 ]; then\n        ansible_counter=$((ansible_counter+1))\n        ansible_value=\"check_launchctl_service_${ansible_counter}\"\n        echo \"\"\n        echo \"- name: Checking ${string}\"\n        echo \"  command: sh -c \\\"${get_command}\\\"\"\n        echo \"  register: ${ansible_value}\"\n        echo \"  failed_when: ${ansible_value} == 1\"\n        echo \"  changed_when: false\"\n        echo \"  ignore_errors: true\"\n        echo \"  when: ansible_facts['ansible_system'] == '${os_name}'\"\n        echo \"\"\n        echo \"- name: Fixing ${string}\"\n        echo \"  command: sh -c \\\"${set_command}\\\"\"\n        echo \"  when: ${ansible_value}.rc == 1 and ansible_facts['ansible_system'] == '${os_name}'\"\n        echo \"\"\n      fi\n      if [ \"${actual_status}\" != \"${required_status}\" ]; then\n        inc_insecure \"Service \\\"${launchctl_service}\\\" is \\\"${actual_status}\\\"\"\n        lock_command=\"sudo launchctl ${change_status} -w ${launchctl_service}.plist\"\n        lock_message=\"Service ${launchctl_service} to ${required_status}\"\n        update_log   \"${log_file}\" \"${actual_status}\"\n        run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n      else\n        inc_secure   \"Service \\\"${launchctl_service}\\\" is \\\"${required_status}\\\"\"\n      fi\n    else\n      log_file=\"${restore_dir}/${log_file}\"\n      if [ -f \"${log_file}\" ]; then\n        restore_status=$( cat \"${log_file}\" )\n        if [ \"${restore_status}\" = \"enabled\" ]; then\n          change_status=\"load\"\n        else\n          change_status=\"unload\"\n        fi\n        if [ \"${restore_status}\" != \"${actual_status}\" ]; then\n          restore_message=\"Restoring ${launchctl_service} to ${change_status}\"\n          restore_command=\"launchctl ${change_status} -w ${launchctl_service}.plist\"\n          execute_restore \"${restore_command}\" \"${restore_message}\" \"sudo\"\n        fi\n      fi\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/darwin/check_osx_defaults.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_osx_defaults\n#\n# Function to check defaults under OS X\n#.\n\ncheck_osx_defaults () {\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    defaults_file=\"${1}\"\n    defaults_parameter=\"${2}\"\n    defaults_value=\"${3}\"\n    defaults_type=\"${4}\"\n    if [ \"${defaults_type}\" = \"dict\" ]; then\n      defaults_second_value=\"${5}\"\n      defaults_second_type=\"${6}\"\n      defaults_user=\"${7}\"\n    else\n      defaults_host=\"${5}\"\n      defaults_user=\"${6}\"\n    fi\n    print_function \"check_osx_defaults\"\n    defaults_read=\"read\"\n    defaults_write=\"write\"\n    backup_file=${defaults_file}\n    if [ ! \"${defaults_host}\" = \"currentHost\" ]; then\n      defaults_user=\"${defaults_host}\"\n      defaults_host=\"\"\n    fi\n    if [ \"${defaults_user}\" = \"\" ]; then\n      defaults_command=\"sudo defaults\"\n    else\n      defaults_command=\"sudo -u ${defaults_user} defaults\"\n    fi\n    if [ \"${audit_mode}\" != 2 ]; then\n      if [ \"${defaults_user}\" = \"\" ]; then\n        string=\"Parameter \\\"${defaults_parameter}\\\" is set to \\\"${defaults_value}\\\" in \\\"${defaults_file}\\\"\"\n      else\n        string=\"Parameter \\\"${defaults_parameter}\\\" is set to \\\"${defaults_value}\\\" in \\\"${defaults_file}\\\" for user \\\"${defaults_user}\\\"\"\n      fi\n      check_message  \"${string}\"\n      if [ \"${defaults_host}\" = \"currentHost\" ]; then\n        defaults_read=\"-currentHost ${defaults_read}\"\n        defaults_write=\"-currentHost ${defaults_write}\"\n        backup_file=\"$HOME/Library/Preferences/ByHost/${defaults_file}*\"\n        defaults_command=\"defaults\"\n      fi\n      command=\"${defaults_command} ${defaults_read} ${defaults_file} ${defaults_parameter} 2> /dev/null | wc -l |sed 's/ //g'\"\n      command_message    \"${command}\"\n      null_check=$( eval \"${command}\" )\n      if [ \"$null_check\" = \"0\" ]; then\n        check_value=\"not-found\"\n      else\n        command=\"${defaults_command} ${defaults_read} ${defaults_file} ${defaults_parameter} 2> /dev/null | sed 's/^ //g' |grep '0' |wc -l |sed 's/ //g'\"\n        command_message    \"${command}\"\n        zero_check=$( eval \"${command}\" )\n        if [ \"${zero_check}\" = \"1\" ]; then\n          check_value=\"0\"\n        else\n          command=\"${defaults_command} ${defaults_read} ${defaults_file} ${defaults_parameter} 2> /dev/null | sed 's/^ //g'\"\n          command_message     \"${command}\"\n          check_value=$( eval \"${command}\" )\n        fi\n      fi\n      temp_value=\"${defaults_value}\"\n      if [ \"${defaults_type}\" = \"bool\" ]; then\n        if [ \"${defaults_value}\" = \"no\" ]; then\n          temp_value=0\n        fi\n        if [ \"${defaults_value}\" = \"yes\" ]; then\n          temp_value=1\n        fi\n      fi\n      if [ \"${check_value}\" != \"${temp_value}\" ]; then\n        if [ \"${defaults_user}\" = \"\" ]; then\n          inc_insecure \"Parameter \\\"${defaults_parameter}\\\" not set to \\\"${defaults_value}\\\" in \\\"${defaults_file}\\\"\"\n        else\n          inc_insecure \"Parameter \\\"${defaults_parameter}\\\" not set to \\\"${defaults_value}\\\" in \\\"${defaults_file}\\\" for user \\\"${defaults_user}\\\"\"\n        fi\n        if [ \"${defaults_value}\" = \"\" ]; then\n          fix_message \"${defaults_command} delete ${defaults_file} ${defaults_parameter}\"\n          set_command=\"${defaults_command} delete ${defaults_file} ${defaults_parameter}\"\n        else\n          if [ \"${defaults_type}\" = \"bool\" ]; then\n            fix_message \"${defaults_command} write ${defaults_file} ${defaults_parameter} -bool \\\"${defaults_value}\\\"\"\n            set_command=\"${defaults_command} write ${defaults_file} ${defaults_parameter} -bool \\\"${defaults_value}\\\"\"\n          else\n            if [ \"${defaults_type}\" = \"int\" ]; then\n              fix_message \"${defaults_command} write ${defaults_file} ${defaults_parameter} -int ${defaults_value}\"\n              set_command=\"${defaults_command} write ${defaults_file} ${defaults_parameter} -int ${defaults_value}\"\n            else\n              if [ \"${defaults_type}\" = \"dict\" ]; then\n                if [ \"${defaults_second_type}\" = \"bool\" ]; then\n                  fix_message \"${defaults_command} write ${defaults_file} ${defaults_parameter} -dict ${defaults_value} -bool ${defaults_second_value}\"\n                  set_command=\"${defaults_command} write ${defaults_file} ${defaults_parameter} -dict ${defaults_value} -bool ${defaults_second_value}\"\n                else\n                  if [ \"${defaults_second_type}\" = \"int\" ]; then\n                    fix_message \"${defaults_command} write ${defaults_file} ${defaults_parameter} -dict ${defaults_value} -int ${defaults_second_value}\"\n                    set_command=\"${defaults_command} write ${defaults_file} ${defaults_parameter} -dict ${defaults_value} -int ${defaults_second_value}\"\n                  fi\n                fi\n              else\n                fix_message \"${defaults_command} write ${defaults_file} ${defaults_parameter} \\\"${defaults_value}\\\"\"\n                set_command=\"${defaults_command} write ${defaults_file} ${defaults_parameter} \\\"${defaults_value}\\\"\"\n              fi\n            fi\n          fi\n        fi\n        if [ \"${audit_mode}\" = 0 ]; then\n          backup_file \"${backup_file}\"\n          string=\"Parameter ${defaults_parameter} to ${defaults_value} in ${defaults_file}\"\n          lock_message=\"${string}\"\n          if [ \"${defaults_value}\" = \"\" ]; then\n            lock_command=\"${defaults_command} delete ${defaults_file} ${defaults_parameter}\"\n            run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n          else\n            if [ \"${defaults_type}\" = \"bool\" ]; then\n              lock_command=\"${defaults_command} write ${defaults_file} ${defaults_parameter} -bool ${defaults_value}\"\n              run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n            else\n              if [ \"${defaults_type}\" = \"int\" ]; then\n                lock_command=\"${defaults_command} write ${defaults_file} ${defaults_parameter} -int ${defaults_value}\"\n                run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n                if [ \"${defaults_file}\" = \"/Library/Preferences/com.apple.Bluetooth\" ]; then\n                  killall -HUP blued\n                fi\n              else\n                if [ \"${defaults_type}\" = \"dict\" ]; then\n                  if [ \"${defaults_second_type}\" = \"bool\" ]; then\n                    lock_command=\"${defaults_command} write ${defaults_file} ${defaults_parameter} -dict ${defaults_value} -bool ${defaults_second_value}\"\n                    run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n                  else\n                    if [ \"${defaults_second_type}\" = \"int\" ]; then\n                      lock_command=\"${defaults_command} write ${defaults_file} ${defaults_parameter} -dict ${defaults_value} -int ${defaults_second_value}\"\n                      run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n                    fi\n                  fi\n                else\n                  lock_command=\"${defaults_command} write ${defaults_file} ${defaults_parameter} \\\"${defaults_value}\\\"\"\n                  run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n                fi\n              fi\n            fi\n          fi\n        fi\n        get_command=\"${defaults_command} ${defaults_read} ${defaults_file} ${defaults_parameter} 2>&1 |grep ${defaults_value}\"\n        if [ \"${ansible_mode}\" = 1 ]; then\n          ansible_counter=$((ansible_counter+1))\n          ansible_value=\"check_osx_defaults_${ansible_counter}\"\n          echo \"\"\n          echo \"- name: Checking ${string}\"\n          echo \"  command: sh -c \\\"${get_command}\\\"\"\n          echo \"  register: ${ansible_value}\"\n          echo \"  failed_when: ${ansible_value} == 1\"\n          echo \"  changed_when: false\"\n          echo \"  ignore_errors: true\"\n          echo \"  when: ansible_facts['ansible_system'] == '${os_name}'\"\n          echo \"\"\n          echo \"- name: Fixing ${string}\"\n          echo \"  command: sh -c \\\"${set_command}\\\"\"\n          echo \"  when: ${ansible_value}.rc == 1 and ansible_facts['ansible_system'] == '${os_name}'\"\n          echo \"\"\n        fi\n      else\n        if [ \"${defaults_user}\" = \"\" ]; then\n          inc_secure \"Parameter \\\"${defaults_parameter}\\\" is set to \\\"${defaults_value}\\\" in \\\"${defaults_file}\\\"\"\n        else\n          inc_secure \"Parameter \\\"${defaults_parameter}\\\" is set to \\\"${defaults_value}\\\" in \\\"${defaults_file}\\\" for user \\\"${defaults_user}\\\"\"\n        fi\n      fi\n    else\n      restore_file \"${backup_file}\" \"${restore_dir}\"\n    fi\n  fi\n}\n\ncheck_osx_defaults_dict () {\n  check_osx_defaults \"${1}\" \"${2}\" \"${3}\" \"${4}\" \"${5}\" \"${6}\" \"\" \"\"\n}\n\ncheck_osx_defaults_int () {\n  check_osx_defaults \"${1}\" \"${2}\" \"${3}\" \"int\" \"\" \"\" \"\" \"\"\n}\n\ncheck_osx_defaults_bool () {\n  check_osx_defaults \"${1}\" \"${2}\" \"${3}\" \"bool\" \"\" \"\" \"\" \"\"\n}\n\ncheck_osx_defaults_string () {\n  check_osx_defaults \"${1}\" \"${2}\" \"${3}\" \"string\" \"\" \"\" \"\" \"\"\n}\n\ncheck_osx_defaults_user () {\n  check_osx_defaults \"${1}\" \"${2}\" \"${3}\" \"${4}\" \"${5}\" \"\" \"\" \"\"\n}\n\ncheck_osx_defaults_host () {\n  check_osx_defaults \"${1}\" \"${2}\" \"${3}\" \"${4}\" \"currentHost\" \"\" \"\" \"\"\n}\n\ncheck_osx_defaults_value () {\n  check_osx_defaults \"${1}\" \"${2}\" \"${3}\" \"\" \"\" \"\" \"\" \"\"\n}\n"
  },
  {
    "path": "functions/darwin/check_osx_systemsetup.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_osx_systemsetup\n#\n# Function to systemsetup output under OS X\n#.\n\ncheck_osx_systemsetup () {\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${os_version}\" -ge 12 ]; then\n      param=\"${1}\"\n      value=\"${2}\"\n      print_function \"check_osx_systemsetup\"\n      log_file=\"systemsetup_${param}.log\"\n      if [ \"${audit_mode}\" != 2 ]; then\n        string=\"Parameter \\\"${param}\\\" is set to \\\"${value}\\\"\"\n        check_message  \"${string}\"\n        if [ \"${ansible_mode}\" = 1 ]; then\n          ansible_counter=$((ansible_counter+1))\n          ansible_value=\"check_osx_systemsetup_${ansible_counter}\"\n          echo \"\"\n          echo \"- name: Checking ${string}\"\n          echo \"  command: sh -c \\\"sudo systemsetup -${param} |cut -f2 -d: |sed 's/ //g' |tr '[:upper:]' '[:lower:]'\\\"\"\n          echo \"  register: ${ansible_value}\"\n          echo \"  failed_when: ${ansible_value} == 1\"\n          echo \"  changed_when: false\"\n          echo \"  ignore_errors: true\"\n          echo \"  when: ansible_facts['ansible_system'] == '${os_name}'\"\n          echo \"\"\n          echo \"- name: Fixing ${string}\"\n          echo \"  command: sudo systemsetup -${param} ${value}\"\n          echo \"  when: ${ansible_value}.rc == 0 and ansible_facts['ansible_system'] == '${os_name}'\"\n          echo \"\"\n        fi\n        command=\"sudo systemsetup -${param} | cut -f2 -d: | sed 's/ //g' | tr '[:upper:]' '[:lower:]'\"\n        command_message \"${command}\"\n        check=$( eval   \"${command}\" )\n        if [ \"${check}\" != \"${value}\" ]; then\n          inc_insecure \"Parameter \\\"${param}\\\" not set to \\\"${value}\\\"\"\n          update_log   \"${log_file}\" \"${check_file}\"\n          lock_command=\"systemsetup -${param} ${value}\"\n          lock_message=\"Parameter \\\"${param}\\\" to \\\"${value}\\\"\"\n          run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n        else\n          inc_secure   \"Parameter \\\"${param}\\\" is set to \\\"${value}\\\"\"\n        fi\n      else\n        restore_file=\"${restore_dir}/${log_file}\"\n        if [ -f \"${restore_file}\" ]; then\n          command=\"sudo systemsetup -${param} | cut -f2 -d: | sed 's/ //g' | tr '[:upper:]' '[:lower:]'\"\n          command_message \"${command}\"\n          now=$( eval     \"${command}\" )\n          old=$( cat \"${restore_file}\" )\n          if [ \"${now}\" != \"${old}\" ]; then\n            restore_command=\"systemsetup -${param} ${old}\"\n            restore_message=\"Parameter \\\"${param}\\\" back to \\\"${old}\\\"\"\n            execute_restore \"${restore_command}\" \"${restore_message}\" \"sudo\"\n          fi\n        fi\n      fi\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/darwin/check_pmset.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_pmset\n#\n# Check Apple Power Management settings\n#.\n\ncheck_pmset() {\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    service=\"${1}\"\n    value=\"${2}\"\n    print_function \"check_pmset\"\n    state=\"${value}\"\n    if [ \"${value}\" = \"off\" ]; then\n      value=\"0\"\n    fi\n    if [ \"${value}\" = \"on\" ]; then\n      value=\"1\"\n    fi\n    if [ \"${value}\" = \"0\" ]; then\n      state=\"off\"\n    fi\n    if [ \"${value}\" = \"1\" ]; then\n      state=\"on\"\n    fi\n    log_file=\"pmset_${service}.log\"\n    command=\"pmset -g | grep \\\"${service}\\\" | awk '{print \\$2}' | grep -c \\\"${value}\\\" | sed \\\"s/ //g\\\"\"\n    command_message     \"${command}\"\n    actual_test=$( eval \"${command}\" )\n    if [ \"$actual_test\" = \"0\" ]; then\n      actual_value=\"not-found\"\n    else\n      command=\"pmset -g | grep \\\"${service}\\\" | awk '{print \\$2}' | grep \\\"${value}\\\"\"\n      command_message      \"${command}\"\n      actual_value=$( eval \"${command}\" )\n    fi\n    if [ \"${audit_mode}\" != 2 ]; then\n      string=\"Sleep is disabled when powered\"\n      check_message  \"${string}\"\n      if [ \"${ansible_mode}\" = 1 ]; then\n        ansible_counter=$((ansible_counter+1))\n        ansible_value=\"check_pmset_${ansible_counter}\"\n        echo \"\"\n        echo \"- name: Checking ${string}\"\n        echo \"  command: sh -c \\\"pmset -g | grep ${service} |awk '{print \\$2}' |grep ${value}\\\"\"\n        echo \"  register: ${ansible_value}\"\n        echo \"  failed_when: ${ansible_value} == 1\"\n        echo \"  changed_when: false\"\n        echo \"  ignore_errors: true\"\n        echo \"  when: ansible_facts['ansible_system'] == '${os_name}'\"\n        echo \"\"\n        echo \"- name: Fixing ${string}\"\n        echo \"  command: sh -c \\\"pmset -c ${service} ${value}\\\"\"\n        echo \"  when: ${ansible_value}.rc == 1 and ansible_facts['ansible_system'] == '${os_name}'\"\n        echo \"\"\n      fi\n      if [ ! \"${actual_value}\" = \"${value}\" ]; then\n        inc_insecure \"Service \\\"${service}\\\" is not \\\"${state}\\\"\"\n        lock_command=\"echo \\\"${state}\\\" > ${work_dir}/${log_file} ; pmset -c ${service} ${value}\"\n        lock_message=\"Service \\\"${service}\\\" to \\\"${state}\\\"\"\n        run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n      else\n        inc_secure   \"Service \\\"${service}\\\" is \\\"${state}\\\"\"\n      fi\n    else\n      restore_file=$retore_dir/${log_file}\n      if [ -f \"${restore_file}\" ]; then\n        restore_value=$( cat \"${restore_file}\" )\n        if [ \"${restore_value}\" != \"${actual_value}\" ]; then\n          restore_message=\"Wake on lan to enabled\"\n          restore_command=\"pmset -c ${service} ${restore_value}\"\n          execute_restore \"${restore_command}\" \"${restore_message}\" \"sudo\"\n        fi\n      fi\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/darwin/check_sysadminctl.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_sysadminctl\n#\n# Function to check sysadminctl output under OS X\n#.\n\ncheck_sysadminctl () {\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    param=\"${1}\"\n    value=\"${2}\"\n    print_function \"check_sysadminctl\"\n    log_file=\"sysadminctl.log\"\n    if [ \"${value}\" = \"off\" ]; then\n      search_value=\"disabled\"\n      other_value=\"on\"\n    fi\n    if [ \"${value}\" = \"on\" ]; then\n      search_value=\"enabled\"\n      other_value=\"off\"\n    fi\n    if [ \"${audit_mode}\" != 2 ]; then\n      string=\"Parameter \\\"${param}\\\" is set to \\\"${value}\\\"\"\n      check_message  \"${string}\"\n      get_command=\"sudo sysadminctl -${param} status > /dev/null 2>&1 |grep ${search_value}\"\n      set_command=\"sudo sysadminctl -${param} ${value}\"\n      if [ \"${ansible_mode}\" = 1 ]; then\n        ansible_counter=$((ansible_counter+1))\n        ansible_value=\"check_sysadminctl_${ansible_counter}\"\n        echo \"\"\n        echo \"- name: Checking ${string}\"\n        echo \"  command: sh -c \\\"${get_command}\\\"\"\n        echo \"  register: ${ansible_value}\"\n        echo \"  failed_when: \\\"${search_value}\\\" not in ${ansible_value}\"\n        echo \"  changed_when: false\"\n        echo \"  ignore_errors: true\"\n        echo \"  when: ansible_facts['ansible_system'] == '${os_name}'\"\n        echo \"\"\n        echo \"- name: Fixing ${string}\"\n        echo \"  command: sh -c \\\"${set_command}\\\"\"\n        echo \"  when: ${ansible_value}.rc == 1 and ansible_facts['ansible_system'] == '${os_name}'\"\n        echo \"\"\n      fi\n      command=\"sudo sysadminctl -${param} status > /dev/null 2>&1 | grep ${search_value} | wc -l | sed 's/ //g'\"\n      command_message \"${command}\"\n      check=$( eval   \"${command}\" )\n      if [ \"${check}\" != \"1\" ]; then\n        inc_insecure  \"Parameter \\\"${param}\\\" not set to \\\"${value}\\\"\"\n        fix_message   \"sudo sysadminctl -${param} ${value}\"\n        if [ \"${audit_mode}\" = 0 ]; then\n          update_log   \"${log_file}\" \"${param},${other_value}\"\n          lock_message=\"Parameter \\\"${param}\\\" to \\\"${value}\\\"\"\n          lock_command=\"${set_command}\"\n          run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n        fi\n      else\n        if [ \"${audit_mode}\" = 1 ]; then\n          inc_secure   \"Parameter \\\"${param}\\\" is set to \\\"${value}\\\"\"\n        fi\n      fi\n    else\n      restore_file=\"${restore_dir}/${log_file}\"\n      restore_value=$( grep \"^${param}\" \"${restore_file}\" |cut -f2 -d, )\n      restore_message=\"Parameter \\\"${param}\\\" to \\\"${restore_value}\\\"\"\n      restore_command=\"sudo sysadminctl -${param} ${restore_value}\"\n      execute_restore \"${restore_command}\" \"${restore_message}\\\"\" \"sudo\"\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/docker/audit_docker.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_docker_all\n#\n# Audit Docker\n#\n# All the Docker specific tests\n#.\n\naudit_docker_all () {\n  print_function \"audit_docker_all\"\n  audit_auditd\n  audit_docker_users\n  audit_docker_daemon\n  audit_docker_network\n  audit_docker_logging\n  audit_docker_monitoring\n  audit_docker_security\n}\n\n# funct_audit_docker\n#\n# Audit Docker \n#.\n\nfunct_audit_docker () {\n  audit_mode=\"${1}\"\n  print_function \"funct_audit_docker\"\n  audit_docker_all\n  print_results\n}\n"
  },
  {
    "path": "functions/docker/check_dockerd.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n# shellcheck disable=SC2009\n# shellcheck disable=SC2016\n\n# check_dockerd\n#\n# Check dockerd parameter value\n#.\n\ncheck_dockerd () {\n  used=\"${1}\"\n  type=\"${2}\"\n  param=\"${3}\"\n  value=\"${4}\"\n  if [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${audit_mode}\" != 2 ]; then\n      print_function \"check_dockerd\"\n      if [ \"${type}\" = \"config\" ]; then\n        if [ \"${value}\" ]; then\n         check_message \"Docker \\\"${type}\\\" parameter \\\"${param}\\\" has value \\\"${value}\\\"\"\n        else\n         check_message \"Docker \\\"${type}\\\" parameter \\\"${param}\\\" has no value\"\n        fi\n      else\n        if [ \"${value}\" ]; then\n         check_message \"Docker \\\"${type}\\\" parameter \\\"${param}\\\" is \\\"${used}\\\" and has value \\\"${value}\\\"\"\n        else\n         check_message \"Docker \\\"${type}\\\" parameter \\\"${param}\\\" is \\\"${used}\\\"\"\n        fi\n      fi\n      case \"${type}\" in\n        \"daemon\")\n          command=\"ps -ef | grep dockerd | grep \\\"${param}\\\"\"\n          command_message \"${command}\"\n          check=$( eval   \"${command}\" )\n          if [ \"${check}\" ] && [ \"${value}\" ] && [ \"${used}\" = \"unused\" ]; then\n            command=\"ps -ef | grep dockerd | grep \\\"${param}\\\" | grep \\\"${value}\\\"\"\n            command_message \"${command}\"\n            check=$( eval   \"${command}\" )\n            if [ ! \"${check}\" ]; then\n              inc_insecure  \"Docker parameter \\\"${param}\\\" is not set to \\\"${value}\\\"\"\n            else\n              inc_secure    \"Docker parameter \\\"${param}\\\" is set to \\\"${value}\\\"\"\n            fi\n          else\n            if [ \"${used}\" = \"used\" ] && [ ! \"${check}\" ]; then\n              \n              inc_insecure  \"Docker parameter \\\"${param}\\\" is not used\"\n            else\n              \n              inc_secure    \"Docker parameter \\\"${param}\\\" is \\\"${used}\\\"\"\n            fi\n          fi\n          ;;\n        \"info\")\n          command=\"docker info 2> /dev/null |grep \\\"${param}\\\"\"\n          command_message \"${command}\"\n          check=$( eval \"${command}\" )\n          if [ \"${check}\" ] && [ \"${value}\" ] && [ \"${used}\" = \"unused\" ]; then\n            command=\"docker info 2> /dev/null | grep \\\"${param}\\\" | grep \\\"${value}\\\"\"\n            command_message \"${command}\"\n            check=$( eval \"${command}\" )\n            if [ ! \"${check}\" ]; then\n              inc_insecure \"Docker parameter \\\"${param}\\\" is not set to \\\"${value}\\\"\"\n            else\n              inc_secure   \"Docker parameter \\\"${param}\\\" is set to \\\"${value}\\\"\"\n            fi\n          else\n            inc_secure \"Docker parameter \\\"${param}\\\" is \\\"${used}\\\"\"\n          fi\n          ;;\n        \"kernel\")\n          OFS=$IFS\n          IFS=$(printf '\\n+'); IFS=${IFS%?}\n          command=\"docker ps --quiet --all | xargs docker inspect --format '{{ .Id }}: CapAdd={{ .HostConfig.CapAdd }}' 2> /dev/null\"\n          command_message     \"${command}\"\n          docker_info=$( eval \"${command}\" )\n          if [ ! \"${docker_info}\" ]; then\n            verbose_message   \"No Docker instances\" notice\n          fi\n          for info in ${docker_info}; do\n            command=\"echo \\\"${info}\\\" | cut -f1 -d:\"\n            command_message   \"${command}\"\n            docker_id=$( eval \"${command}\" )\n            command=\"echo \\\"${info}\\\" | cut -f2 -d: | cut -f2 -d= | grep \\\"${param}\\\"\"\n            command_message   \"${command}\"\n            check=$( eval     \"${command}\" )\n            if [ \"${used}\" = \"used\" ]; then\n              if [ \"${profile}\" ]; then\n                inc_secure    \"Docker instance \\\"${docker_id}\\\" has capability \\\"${param}\\\"\"\n              else\n                inc_insecure  \"Docker instance \\\"${docker_id}\\\" does not have capability \\\"${param}\\\"\"\n              fi\n            else\n              if [ \"${profile}\" ]; then\n                inc_secure    \"Docker instance \\\"${docker_id}\\\" does not have capability \\\"${param}\\\"\"\n              else\n                inc_insecure  \"Docker instance \\\"${docker_id}\\\" has capability \\\"${param}\\\"\"\n              fi\n              command=\"docker inspect --format '{{ .Id }}: CapAdd={{ .HostConfig.CapDrop }}' \\\"${docker_id}\\\" | cut -f2 -d= | grep \\\"${param}\\\"\"\n              command_message \"${command}\"\n              check=$( eval   \"${command}\" )\n              if [ \"${check}\" ]; then\n                inc_secure    \"Docker instance \\\"${docker_id}\\\" forcibly drops capability \\\"${param}\\\"\"\n              else\n                inc_insecure  \"Docker instance \\\"${docker_id}\\\" does not forcibly capability \\\"${param}\\\"\"\n              fi\n            fi\n          done\n          IFS=$OFS\n          ;;\n        \"config\")\n          OFS=$IFS\n          IFS=$(printf '\\n+'); IFS=${IFS%?}\n          case ${param} in\n            \"AppArmorProfile\")\n              command=\"docker ps --quiet --all | xargs docker inspect --format \\\"{{ .Id }}: ${param}={{ .${param} }}\\\" 2> /dev/null\"\n              command_message     \"${command}\"\n              docker_info=$( eval \"${command}\" )\n              ;;\n            \"User\")\n              command=\"docker ps --quiet --all | xargs docker inspect --format \\\"{{ .Id }}: ${param}={{ .Config.${param} }}\\\" 2> /dev/null\"\n              command_message     \"${command}\"\n              docker_info=$( eval \"${command}\" )\n              ;;\n            \"Ports\")\n              command=\"docker ps --quiet --all | xargs docker inspect --format \\\"{{ .Id }}: ${param}={{ .NetworkSettings.${param} }}\\\" 2> /dev/null\"\n              command_message     \"${command}\"\n              docker_info=$( eval \"${command}\" )\n              ;;\n            \"Propagation\")\n              command=\"docker ps --quiet --all | xargs docker inspect --format '{{ .Id }}: Propagation={{range $mnt := .Mounts}} {{json $mnt.Propagation}} {{end}}' 2> /dev/null\"\n              command_message     \"${command}\"\n              docker_info=$( eval \"${command}\" )\n              ;;\n            \"Health\")\n              command=\"docker ps --quiet | xargs docker inspect --format '{{ .Id }}: Health={{ .State.Health.Status }}' 2> /dev/null\"\n              command_message     \"${command}\"\n              docker_info=$( eval \"${command}\" )\n              ;;\n            *)\n              command=\"docker ps --quiet --all | xargs docker inspect --format \\\"{{ .Id }}: ${param}={{ .HostConfig.${param} }}\\\" 2> /dev/null\"\n              command_message     \"${command}\"\n              docker_info=$( eval \"${command}\" )\n              ;;\n          esac\n          if [ ! \"${docker_info}\" ]; then\n            verbose_message \"No Docker instances with \\\"${param}\\\" set\" notice\n          fi\n          for info in ${docker_info}; do\n            command=\"echo \\\"${info}\\\" | cut -f1 -d:\"\n            command_message   \"${command}\"\n            docker_id=$( eval \"${command}\" )\n            case ${used} in\n              \"notequal\")\n                command=\"echo \\\"${info}\\\" | cut -f2 -d: | cut -f2 -d= | grep -v \\\"\\\\[\\\\]\\\"\"\n                command_message  \"${command}\"\n                profile=$( eval  \"${command}\" )\n                if [ ! \"${value}\" ]; then\n                  if [ \"${profile}\" ]; then\n                    inc_secure   \"Docker instance \\\"${docker_id}\\\" does not have parameter \\\"${param}\\\"\"\n                  else\n                    inc_insecure \"Docker instance \\\"${docker_id}\\\" has parameter \\\"${param}\\\"\"\n                  fi\n                else\n                  if [ ! \"${profile}\" = \"${value}\" ]; then\n                    inc_secure   \"Docker instance \\\"${docker_id}\\\" does not have parameter \\\"${param}\\\" set to \\\"${value}\\\"\"\n                  else\n                    inc_insecure \"Docker instance \\\"${docker_id}\\\" has parameter \\\"${param}\\\" set to \\\"${value}\\\"\"\n                  fi\n                fi\n                ;;\n              \"equal\")\n                command=\"echo \\\"${info}\\\" | cut -f2 -d: | cut -f2 -d= | grep -v \\\"\\[\\]\\\"\"\n                command_message  \"${command}\"\n                profile=$( eval  \"${command}\" )\n                if [ ! \"${value}\" ]; then\n                  if [ ! \"${profile}\" ]; then\n                    inc_secure   \"Docker instance \\\"${docker_id}\\\" does not have parameter \\\"${param}\\\"\"\n                  else\n                    inc_insecure \"Docker instance \\\"${docker_id}\\\" has parameter \\\"${param}\\\"\"\n                  fi\n                else\n                  if [ \"${profile}\" = \"${value}\" ]; then\n                    inc_secure   \"Docker instance \\\"${docker_id}\\\" does not have parameter \\\"${param}\\\" set to \\\"${value}\\\"\"\n                  else\n                    inc_insecure \"Docker instance \\\"${docker_id}\\\" does not have parameter \\\"${param}\\\" set to \\\"${value}\\\"\"\n                  fi\n                fi\n                ;;\n              \"notinclude\")\n                command=\"echo \\\"${info}\\\" | cut -f2 -d: | cut -f2 -d= | grep \\\"${param}\\\"\"\n                command_message \"${command}\"\n                profile=$( eval \"${command}\" )\n                if [ ! \"${profile}\" ]; then\n                  inc_secure    \"Docker instance \\\"${docker_id}\\\" parameter \\\"${param}\\\" does not include \\\"${value}\\\"\"\n                else\n                  inc_insecure  \"Docker instance \\\"${docker_id}\\\" parameter \\\"${param}\\\" includes \\\"${value}\\\"\"\n                fi\n                ;; \n              \"include\")\n                command=\"echo \\\"${info}\\\" | cut -f2 -d: | cut -f2 -d= | grep \\\"${param}\\\"\"\n                command_message \"${command}\"\n                profile=$( eval \"${command}\" )\n                if [ \"${profile}\" ]; then\n                  inc_secure    \"Docker instance \\\"${docker_id}\\\" parameter \\\"${param}\\\" includes \\\"${value}\\\"\"\n                else\n                  inc_insecure  \"Docker instance \\\"${docker_id}\\\" parameter \\\"${param}\\\" does not include \\\"${value}\\\"\"\n                fi\n                ;; \n            esac \n          done\n          IFS=$OFS\n          ;;\n      esac\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/file/audit_search_fs.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_search_fs\n#\n# Audit Filesystem\n#\n# Run various filesystem audits, add support for NetBackup\n#.\n\naudit_search_fs () {\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    print_function  \"audit_search_fs\"\n    verbose_message \"Filesystem Search\"\n    command=\"pkginfo -l | grep SYMCnbclt | grep PKG | awk '{print \\$2}'\"\n    command_message \"${command}\"\n    check=$( eval   \"${command}\" )\n    if [ \"${check}\" != \"SYMCnbclt\" ]; then\n      audit_bpcd\n      audit_vnetd\n      audit_vopied\n      audit_bpjava_msvc\n    else\n      funct_file_value \"/etc/hosts.allow\" \"bpcd\"  \"colon\"       \" ALL\" \"hash\"\n      funct_file_value \"/etc/hosts.allow\" \"vnetd\" \"colon\"       \" ALL\" \"hash\"\n      funct_file_value \"/etc/hosts.allow\" \"bpcd\"  \"vopied\"      \" ALL\" \"hash\"\n      funct_file_value \"/etc/hosts.allow\" \"bpcd\"  \"bpjava-msvc\" \" ALL\" \"hash\"\n    fi\n    audit_extended_attributes\n  fi\n  audit_writable_files\n  audit_suid_files\n  audit_file_perms\n  audit_sticky_bit\n}\n"
  },
  {
    "path": "functions/file/audit_select.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# funct_audit_select\n#\n# Selective Audit\n#.\n\nfunct_audit_select () {\n  audit_mode=\"${1}\"\n  module_name=\"${2}\"\n  print_function \"funct_audit_select\"\n  module_test=$( echo \"${module_name}\" | grep -c aws )\n  if [ \"$module_test\" = \"1\" ]; then\n    check_aws\n  fi\n  suffix_test=$( echo \"${module_name}\" | grep -c \"\\\\.sh\" )\n  if [ \"${suffix_test}\" = \"1\" ]; then\n    module_name=$( echo \"${module_name}\" | cut -f1 -d. )\n  fi\n  module_test=$( echo \"${module_name}\" | grep -c \"full\" )\n  if [ \"$module_test\" = \"0\" ]; then  \n    function_test=$( echo \"${module_name}\" | grep -c \"audit_\" )\n    if [ \"${function_test}\" = \"0\" ]; then\n      module_name=\"audit_${module_name}\"\n    fi\n  fi\n  module_test=$( echo \"${module_name}\" | grep \"audit\" )\n  if [ -n \"$module_test\" ]; then\n    command=\"find \\\"${modules_dir}\\\" -name \\\"${module_name}.sh\\\"\"\n    command_message   \"${command}\"\n    file_name=$( eval \"${command}\" )\n    if [ -f \"${file_name}\" ]; then\n      print_audit_info \"${module_name}\"\n      eval \"${module_name}\"\n    else\n      warn_message    \"Audit function \\\"${module_name}\\\" does not exist\"\n      verbose_message \"\" \"\"\n      exit\n    fi \n    print_results\n  else\n    warn_message    \"Audit function \\\"${module_name}\\\" does not exist\"\n    verbose_message \"\" \"\"\n  fi\n}\n"
  },
  {
    "path": "functions/file/audit_test_subset.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_test_subset\n#\n# Audit Subset for testing\n#.\n\naudit_test_subset () {\n  print_function \"audit_test_subset\"\n  audit_legacy\n}\n"
  },
  {
    "path": "functions/file/backup_file.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC2034\n# shellcheck disable=SC1090\n# shellcheck disable=SC2154\n\n# backup_file\n#\n# Backup file\n#.\n\nbackup_file () {\n  check_file=\"${1}\"\n  print_function \"backup_file\"\n  if [ -f \"${check_file}\" ]; then\n    if [ \"${audit_mode}\" = 0 ]; then\n      backup_file=\"${work_dir}${check_file}\"\n      if [ ! -f \"${backup_file}\" ]; then\n        verbose_message \"File \\\"${check_file}\\\" to \\\"${backup_file}\\\"\" \"backup\"\n        command=\"find \\\"${check_file}\\\" | cpio -pdm \\\"${work_dir}\\\" 2> /dev/null\"\n        command_message \"${command}\"\n        eval \"${command}\"\n        if [ \"${check_file}\" = \"/etc/system\" ]; then\n          reboot_required=1\n        \tverbose_message \"Notice:    Reboot required\"\n        fi\n        check_base=$( basename \"${check_file}\" )\n        if [ \"${check_base}\" = \"sshd_config\" ]; then\n          verbose_message \"Notice:    Service restart required for SSH\"\n        fi\n        if [ \"${ansible_mode}\" = 1 ]; then\n          echo \"\"\n          echo \"- name: Restart ssh service\"\n          echo \"  service:\"\n          echo \"    name:  ssh\"\n          echo \"    state: restarted\"\n          echo \"\"\n        fi\n      fi\n    fi\n  else\n    warn_message \"File \\\"${check_file}\\\" does not exist\"\n  fi\n}\n"
  },
  {
    "path": "functions/file/check_append_file.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_append_file\n#\n# Code to append a file with a line\n#\n# check_file      = The name of the original file\n# parameter       = The parameter/line to add to a file\n# comment_value   = The character used in the file to distinguish a line as a comment\n#.\n\ncheck_append_file () {\n  check_file=\"${1}\"\n  parameter=\"${2}\"\n  comment_value=\"${3}\"\n  print_function \"check_append_file\"\n  dir_name=$( dirname \"${check_file}\" )\n  if [ ! -f \"${check_file}\" ]; then\n    warn_message \"File \\\"${check_file}\\\" does not exist\"\n  fi\n  if [ ! -d \"${dir_name}\" ]; then\n    warn_message \"Directory \\\"${dir_name}\\\" does not exist\"\n  else\n    if [ \"${comment_value}\" = \"star\" ]; then\n      comment_value=\"*\"\n    else\n      comment_value=\"#\"\n    fi\n    if [ \"${audit_mode}\" = 2 ]; then\n      restore_file=\"${restore_dir}${check_file}\"\n      restore_file \"${check_file}\" \"${restore_dir}\"\n    else\n      secure_string=\"Parameter \\\"${parameter}\\\" is set in \\\"${check_file}\\\"\"\n      insecure_string=\"Parameter \\\"${parameter}\\\" is not set in \\\"${check_file}\\\"\"\n      check_message \"${secure_string}\"\n      if [ ! -f \"${check_file}\" ]; then\n        inc_insecure \"Parameter \\\"${parameter}\\\" does not exist in \\\"${check_file}\\\"\"\n        lock_command=\"echo \\\"${parameter}\\\" >> ${check_file}\"\n        lock_message=\"Parameter \\\"${parameter}\\\" in \\\"${check_file}\\\"\"\n        run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n        if [ \"${parameter}\" ]; then\n          if [ \"${ansible_mode}\" = 1 ]; then\n            echo \"\"\n            echo \"- name: Checking ${secure_string}\"\n            echo \"  lineinfile:\"\n            echo \"    path: ${check_file}\"\n            echo \"    line: '${parameter}'\"\n            echo \"    create: yes\"\n            echo \"\"\n          fi\n        fi\n      else\n        if [ \"${parameter}\" ]; then\n          if [ \"${ansible_mode}\" = 1 ]; then\n            echo \"\"\n            echo \"- name: Checking ${secure_string}\"\n            echo \"  lineinfile:\"\n            echo \"    path: ${check_file}\"\n            echo \"    line: '${parameter}'\"\n            echo \"\"\n          fi\n          command=\"grep -v \\\"^${comment_value}\\\" \\\"${check_file}\\\" | grep -- \\\"${parameter}\\\" | uniq | wc -l | sed \\\"s/ //g\\\"\"\n          command_message     \"${command}\"\n          check_value=$( eval \"${command}\" )\n          if [ \"${check_value}\" != \"1\" ]; then\n            inc_insecure \"${insecure_string}\"\n            backup_file  \"${check_file}\"\n            lock_command=\"echo \\\"${parameter}\\\" >> ${check_file}\"\n            lock_message=\"Parameter \\\"${parameter}\\\" in \\\"${check_file}\\\"\"\n            run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n          else\n            inc_secure   \"${secure_string}\"\n          fi\n        fi\n      fi\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/file/check_file_comment.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2012\n# shellcheck disable=SC2028\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_file_comment\n#\n# Check if a file contains a value and comment it out\n#\n#.\n\ncheck_file_comment () {\n  file=\"${1}\"\n  search=\"${2}\"\n  comment=\"${3}\"\n  print_function \"check_file_comment\"\n  line=\"^(\\s*${search}.*)\"\n  if [ \"${comment}\" = \"hash\" ]; then\n    comment=\"#\"\n  fi\n  string=\"File ${file} with line containing ${search} is commented out\"\n  check_message  \"${string}\"\n  if [ \"${audit_mode}\" != 2 ]; then\n    if [ -f \"${file}\" ]; then\n      check=$( grep \"${search}\" < \"${file}\" | grep -cv \"^${comment}\" )\n      if [ ! \"${check}\" = \"0\" ]; then\n        if [ \"${ansible_mode}\" = 1 ]; then\n          echo \"\"\n          echo \"- name: Checking ${string}\"\n          echo \"  lineinfile:\"\n          echo \"    path: ${check_file}\"\n          echo \"    line: '${line}'\"\n          echo \"    replace: '#\\1'\"\n          echo \"    create: yes\"\n          echo \"\"\n        else\n          command=\"sed 's/${line}/${comment}\\1/g' < ${check_file} > ${temp_file} ; cat ${temp_file} > ${check_file}\"\n          run_lockdown \"${command}\"\n        fi\n        if [ \"${audit_mode}\" = 0 ]; then\n          backup_file  \"${check_file}\"\n          update_log   \"${log_file}\" \"${check_file},sed\"\n          lock_message=\"File \\\"${check_file}\\\"\"\n          lock_command=\"sed  \\\"s/${line}/${comment}\\1/g\\\" < ${check_file} > ${temp_file} ; cat  ${temp_file} > ${check_file}\"\n          run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n        fi\n      fi\n    fi\n  fi\n  if [ \"${audit_mode}\" = 2 ]; then\n    restore_file \"${check_file}\" \"${restore_dir}\"\n  fi\n}\n"
  },
  {
    "path": "functions/file/check_file_exists.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_file_exists\n#\n# Check to see a file ${exists} and create it or delete it\n#\n# check_file    = File to check fo\n# check_${exists}  = If equal to no and file ${exists}, delete it\n#                 If equal to yes and file doesn't exist, create it\n#.\n\ncheck_file_exists () {\n  check_file=\"${1}\"\n  check_exists=\"${2}\"\n  print_function \"check_file_exists\"\n  log_file=\"file.log\"\n  if [ \"${check_exists}\" = \"no\" ]; then\n    if [ \"${audit_mode}\" != 2 ]; then\n      string=\"File \\\"${check_file}\\\" does not exist\"\n      check_message  \"${string}\"\n      if [ \"${ansible_mode}\" = 1 ]; then\n        ansible_counter=$((ansible_counter+1))\n        ansible_value=\"check_file_exists_${ansible_counter}\"\n        echo \"\"\n        echo \"- name: Checking ${string}\"\n        echo \"  stat:\"\n        echo \"    path ${check_file}\"\n        echo \"  register: ${ansible_value}\"\n        echo \"\"\n        echo \"- name: Fixing ${string}\"\n        echo \"  file:\"\n        echo \"    path: ${check_file}\"\n        echo \"    state: absent\"\n        echo \"  when: ${ansible_value}.${exists} == True\"\n        echo \"\"\n      fi\n    fi\n    if [ -f \"${check_file}\" ]; then\n      if [ \"${audit_mode}\" = 1 ]; then\n        inc_insecure \"File \\\"${check_file}\\\" ${exists}\"\n      fi\n      if [ \"${audit_mode}\" = 0 ]; then\n        backup_file  \"${check_file}\"\n        update_log   \"${log_file}\" \"${check_file},rm\"\n        lock_message=\"File \\\"${check_file}\\\"\"\n        lock_command=\"rm ${check_file}\"\n        run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n      fi\n    else\n      if [ \"${audit_mode}\" = 1 ]; then\n        inc_secure \"File \\\"${check_file}\\\" does not exist\"\n      fi\n    fi\n  else\n    if [ \"${audit_mode}\" != 2 ]; then\n      string=\"File \\\"${check_file}\\\" ${exists}\"\n      check_message  \"${string}\"\n      if [ \"${ansible_mode}\" = 1 ]; then\n        ansible_counter=$((ansible_counter+1))\n        ansible_value=\"check_file_exists_${ansible_counter}\"\n        echo \"\"\n        echo \"- name: Checking ${string}\"\n        echo \"  stat:\"\n        echo \"    path ${check_file}\"\n        echo \"  register: stat_result\"\n        echo \"\"\n        echo \"- name: Fixing ${string}\"\n        echo \"  file:\"\n        echo \"    path: ${check_file}\"\n        echo \"    state: touch\"\n        echo \"  when: stat_result.${exists} == False\"\n        echo \"\"\n      fi\n    fi\n    if [ ! -f \"${check_file}\" ]; then\n      if [ \"${audit_mode}\" = 1 ]; then\n        inc_insecure \"File \\\"${check_file}\\\" does not exist\"\n      fi\n      if [ \"${audit_mode}\" = 0 ]; then\n        update_log   \"${log_file}\" \"${check_file},touch\"\n        lock_message=\"File \\\"${check_file}\\\"\"\n        lock_command=\"touch ${check_file}\"\n        run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n      fi\n    else\n      if [ \"${audit_mode}\" = 1 ]; then\n        inc_secure \"File \\\"${check_file}\\\" ${exists}\"\n      fi\n    fi\n  fi\n  if [ \"${audit_mode}\" = 2 ]; then\n    restore_file \"${check_file}\" \"${restore_dir}\"\n  fi\n}\n"
  },
  {
    "path": "functions/file/check_file_perms.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n# shellcheck disable=SC2012\n\n# check_file_perms\n#\n# Code to check permissions on a file\n# If running in audit mode it will check permissions and report\n# If running in lockdown mode it will fix permissions if they\n# don't match those passed to routine\n# Takes:\n# check_file:   Name of file\n# check_perms:  Octal of file permissions, eg 755\n# check_owner:  Owner of file\n# check_group:  Group ownership of file\n#.\n\ncheck_file_perms () {\n  check_file=\"${1}\"\n  check_perms=\"${2}\"\n  check_owner=\"${3}\"\n  check_group=\"${4}\"\n  print_function \"check_file_perms\"\n  if [ \"${id_check}\" = \"0\" ]; then\n    find_command=\"find\"\n  else\n    find_command=\"sudo find\"\n  fi\n  if [ \"${audit_mode}\" != 2 ]; then\n    string=\"File permissions on \\\"${check_file}\\\"\"\n    check_message  \"${string}\"\n    if [ \"${ansible_mode}\" = 1 ]; then\n      echo \"\"\n      echo \"- name: Checking ${string}\"\n      echo \"  file:\"\n      echo \"    path: ${check_file}\"\n      if [ ! \"${check_owner}\" = \"\" ]; then\n        echo \"    owner: ${check_owner}\"\n      fi\n      if [ ! \"${check_group}\" = \"\" ]; then\n        echo \"    group: ${check_group}\"\n      fi\n      echo \"    mode: ${check_perms}\"\n      echo \"\"\n    fi\n  fi\n  if [ ! -e \"${check_file}\" ]; then\n    if [ \"${audit_mode}\" != 2 ]; then\n      warn_message \"File \\\"${check_file}\\\" does not exist\"\n    fi\n    return\n  fi\n  if [ \"${check_owner}\" != \"\" ]; then\n    command=\"find \\\"${check_file}\\\" -maxdepth 0 -perm \\\"${check_perms}\\\" -user \\\"${check_owner}\\\" -group \\\"${check_group}\\\" 2> /dev/null | wc -l | sed \\\"s/ //g\\\"\"\n    command_message      \"${command}\"\n    check_result=$( eval \"${command}\" )\n  else\n    command=\"find \\\"${check_file}\\\" -maxdepth 0 -perm \\\"${check_perms}\\\" 2> /dev/null | wc -l | sed \\\"s/ //g\\\"\"\n    command_message      \"${command}\"\n    check_result=$( eval \"${command}\" )\n  fi\n  log_file=\"fileperms.log\"\n  if [ \"${check_result}\" != \"1\" ]; then\n    if [ \"${audit_mode}\" = 1 ] && [ -n \"${check_result}\" ]; then\n      inc_insecure \"File \\\"${check_file}\\\" has incorrect permissions\"\n      fix_message  \"chmod ${check_perms} ${check_file}\"\n      if [ \"${check_owner}\" != \"\" ]; then\n        if [ \"${check_result}\" != \"1\" ]; then\n          fix_message \"chown ${check_owner}:${check_group} ${check_file}\"\n        fi\n      fi\n    fi\n    if [ \"${audit_mode}\" = 0 ]; then\n      log_file=\"${work_dir}/${log_file}\"\n      if [ \"${os_name}\" = \"SunOS\" ]; then\n        command=\"truss -vstat -tstat ls -ld \\\"${check_file}\\\" 2>&1 | grep 'm=' | tail -1 | awk '{print $3}' | cut -f2 -d'=' | cut -c4-7\"\n        command_message    \"${command}\"\n        file_perms=$( eval \"${command}\" )\n      else\n        if [ \"${os_name}\" = \"Darwin\" ]; then\n          command=\"stat -f %p \\\"${check_file}\\\" | tail -c 4\"\n          command_message    \"${command}\"\n          file_perms=$( eval \"${command}\" )\n        else\n          command=\"stat -c %a \\\"${check_file}\\\"\"\n          command_message    \"${command}\"\n          file_perms=$( eval \"${command}\" )\n        fi\n      fi\n      if [ \"${os_name}\" = \"Linux\" ]; then\n        command=\"stat -c \\\"%U,%G\\\" \\\"${check_file}\\\"\"\n        command_message    \"${command}\"\n        file_owner=$( eval \"${command}\" )\n      else\n        command=\"ls -ld \\\"${check_file}\\\" | awk '{print \\\"\\$3\\\",\\\"\\$4\\\"}'\"\n        command_message    \"${command}\"\n        file_owner=$( eval \"${command}\" )\n      fi\n      update_log \"${log_file}\" \"${check_file},${file_perms},${file_owner}\"\n      lock_message=\"File \\\"${check_file}\\\" to have correct permissions\"\n      lock_command=\"chmod ${check_perms} ${check_file}\"\n      run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n      if [ \"${check_owner}\" != \"\" ]; then\n        if [ \"${check_result}\" != \"${check_file}\" ]; then\n          lock_message=\"File \\\"${check_file}\\\" to have correct owner\"\n          lock_command=\"chown ${check_owner}:${check_group} ${check_file}\"\n          run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n        fi\n      fi\n    fi\n  else\n    if [ \"${audit_mode}\" = 1 ]; then\n      inc_secure \"File \\\"${check_file}\\\" has correct permissions\"\n    fi\n  fi\n  if [ \"${audit_mode}\" = 2 ]; then\n    restore_file=\"${restore_dir}/${log_file}\"\n    if [ -f \"${restore_file}\" ]; then\n      command=\"grep \\\"${check_file}\\\" \\\"${restore_file}\\\" | cut -f1 -d,\"\n      command_message       \"${command}\"\n      restore_check=$( eval \"${command}\" )\n      if [ \"${restore_check}\" = \"${check_file}\" ]; then\n        restore_info=$(  grep \"${check_file}\" \"${restore_file}\" )\n        restore_perms=$( echo \"${restore_info}\" | cut -f2 -d, )\n        restore_owner=$( echo \"${restore_info}\" | cut -f3 -d, )\n        restore_group=$( echo \"${restore_info}\" | cut -f4 -d, )\n        restore_message=\"File \\\"${check_file}\\\" to previous permissions\"\n        restore_command=\"chmod ${restore_perms} ${check_file}\"\n        execute_restore \"${restore_command}\" \"${restore_message}\" \"sudo\"\n        if [ \"${check_owner}\" != \"\" ]; then\n          if [ \"${check_result}\" != \"${check_file}\" ]; then\n            restore_message=\"File \\\"${check_file}\\\" to previous owner\"\n            restore_command=\"chown ${restore_owner}:${restore_group} ${check_file}\"\n            execute_restore \"${restore_command}\" \"${restore_message}\" \"sudo\"\n          fi\n        fi\n      fi\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/file/check_file_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2046\n# shellcheck disable=SC2086\n# shellcheck disable=SC2154\n\n# check_file_value\n#\n# Audit file values\n#\n# This routine takes the following values\n#\n# check_file      = The name of the file to check\n# parameter_name  = The parameter to be checked\n# seperator       = Character used to seperate parameter name from it's value (eg =)\n# correct_value   = The value we expect to be returned\n# comment_value   = Character used as a comment (can be #, *, etc)\n#                   Needs to be passed as word, e.g. hash, star, bang, semicolon, eq, space, colon\n# position        = E.g. after\n# search_value    = Additional search term to help locate parameter / value\n#\n# If the current_value is not the correct_value then it is fixed if run in lockdown mode\n# A copy of the value is stored in a log file, which can be restored\n#.\n\ncheck_file_value_with_position () {\n  operator=\"${1}\"\n  check_file=\"${2}\"\n  parameter_name=\"${3}\"\n  separator=\"${4}\"\n  correct_value=\"${5}\"\n  comment_value=\"${6}\"\n  position=\"${7}\"\n  search_value=\"${8}\"\n  print_function \"check_file_value_with_position\"\n  temp_file=$( basename ${check_file} )\n  temp_file=\"${temp_dir}/${temp_file}\"\n  dir_name=$(  dirname \"${check_file}\" )\n  sshd_test=$( echo \"${check_file}\" | grep -c \"sshd_config\" | sed \"s/ //g\" )\n  if [ ! -f \"${check_file}\" ]; then\n    warn_message \"File \\\"${check_file}\\\" does not exist\"\n  fi\n  if [ ! -d \"${dir_name}\" ]; then\n    warn_message \"Directory \\\"${dir_name}\\\" does not exist\"\n  else\n    if [ \"${operator}\" = \"set\" ]; then\n      correct_value=\"[A-Z,a-z,0-9]\"\n      operator=\"is\"\n    fi\n    if [ \"${comment_value}\" = \"star\" ]; then\n      comment_value=\"*\"\n    else\n      if [ \"${comment_value}\" = \"bang\" ]; then\n        comment_value=\"!\"\n      else\n        if [ \"${comment_value}\" = \"semicolon\" ]; then\n          comment_value=\";\"\n        else\n          comment_value=\"#\"\n        fi\n      fi\n    fi\n    sep_test=$( expr \"${separator}\" : \"eq\" )\n    if [ \"${sep_test}\" = 2 ]; then\n      separator=\"=\"\n      spacer=\"\\=\"\n    else\n      sep_test=$( expr \"${separator}\" : \"space\" )\n      if [ \"${sep_test}\" = 5 ]; then\n        separator=\" \"\n        spacer=\" \"\n      else\n        sep_test=$( expr \"${separator}\" : \"colon\" )\n        if [ \"${sep_test}\" = 5 ]; then\n          separator=\":\"\n          space=\":\"\n        fi\n      fi\n    fi\n    if [ \"${operator}\" = \"is\" ] || [ \"${operator}\" = \"in\" ]; then\n      negative=\"not\"\n    else\n      negative=\"is\"\n    fi\n    if [ \"${id_check}\" = \"0\" ] || [ \"${os_name}\" = \"VMkernel\" ]; then\n      cat_command=\"cat\"\n      sed_command=\"sed\"\n      echo_command=\"echo\"\n    else\n      cat_command=\"sudo cat\"\n      sed_command=\"sudo sed\"\n      echo_command=\"sudo echo\"\n    fi\n    if [ \"${check_file}\" = \"/etc/audit/auditd.conf\" ] || [ \"${check_file}\" = \"/etc/security/faillock.conf\" ] || [ \"${check_file}\" = \"/etc/security/pwquality.conf\" ]; then\n      spacer=\" ${spacer} \"\n    fi\n    if [ \"${audit_mode}\" = 2 ]; then\n      restore_file \"${check_file}\" \"${restore_dir}\"\n    else\n      string=\"Value of \\\"${parameter_name}\\\" ${operator} set to \\\"${correct_value}\\\" in \\\"${check_file}\\\"\"\n      check_message  \"${string}\"\n      string=\"Parameter ${parameter_name} to ${correct_value} in ${check_file}\"\n      lock_message=\"Value of \\\"${parameter_name}\\\" to \\\"${correct_value}\\\" in \\\"${check_file}\\\"\"\n      if [ ! -f \"${check_file}\" ]; then\n        if [ \"${check_file}\" = \"/etc/default/sendmail\" ] || [ \"${check_file}\" = \"/etc/sysconfig/mail\" ] || [ \"${check_file}\" = \"/etc/rc.conf\" ] || [ \"${check_file}\" = \"/boot/loader.conf\" ] || [ \"${check_file}\" = \"/etc/sysconfig/boot\" ] || [ \"${check_file}\" = \"/etc/sudoers\" ]; then\n          line=\"${parameter_name}${separator}\\\"${correct_value}\\\"\"\n        else\n          line=\"${parameter_name}${separator}${correct_value}\"\n        fi\n        lock_command=\"echo '${line}' >> ${check_file}\"\n        if [ \"${audit_mode}\" = 1 ]; then\n          inc_insecure \"Parameter \\\"${parameter_name}\\\" ${negative} set to \\\"${correct_value}\\\" in \\\"${check_file}\\\"\"\n          fix_message  \"${lock_command}\"\n        else\n          if [ \"${audit_mode}\" = 0 ]; then\n            log_file=\"${restore_dir}/fileops.log\"\n            update_log  \"${log_file}\" \"rm,${check_file}\"\n            backup_file \"${check_file}\"\n            if [ \"${check_file}\" = \"/etc/system\" ]; then\n              reboot_required=1\n              notice_message \"Reboot required\"\n            fi\n            if [ \"$sshd_test\" =  \"1\" ]; then\n              notice_message \"Service restart required for SSH\"\n            fi\n            run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n          fi\n          if [ \"${ansible_mode}\" = 1 ]; then\n            echo \"\"\n            echo \"- name: Checking ${string}\"\n            echo \"  lineinfile:\"\n            echo \"    path: ${check_file}\"\n            echo \"    line: '${line}'\"\n            echo \"    create: yes\"\n            echo \"\"\n          fi\n        fi\n      else\n        correct_hyphen=$( echo \"${correct_value}\" | grep -c \"^[\\-]\" | sed \"s/ //g\" )\n        if [ \"${correct_hyphen}\" = \"1\" ]; then\n          correct_value=\"\\\\${correct_value}\"\n        fi\n        param_hyphen=$( echo \"${parameter_name}\" | grep -c \"^[\\-]\" | sed \"s/ //g\" )\n        if [ \"${param_hyphen}\" = \"1\" ]; then\n          parameter_name=\"\\\\${parameter_name}\"\n        fi\n        if [ \"${separator}\" = \"tab\" ]; then\n          check_value=$( ${cat_command} \"${check_file}\" | grep -v \"^${comment_value}\" | grep \"${parameter_name}\" | awk '{print $2}' | sed 's/\"//g' | uniq | grep -cE \"${correct_value}\" | sed \"s/ //g\" )\n        else\n          if [ \"$sshd_test\" = \"1\" ]; then\n            check_value=$( ${cat_command} \"${check_file}\" | grep -v \"^${comment_value}\" | grep \"${parameter_name}\" | cut -f2 -d\"${separator}\" | sed 's/\"//g' | sed 's/ //g' | uniq | grep -cE \"${correct_value}\" | sed \"s/ //g\" )\n            if [ ! \"${check_value}\" ]; then\n              check_value=$( ${cat_command} \"${check_file}\" | grep \"${parameter_name}\" | cut -f2 -d\"${separator}\" | sed 's/\"//g' | sed 's/ //g' | uniq | grep -cE \"${correct_value}\" | sed \"s/ //g\" )\n            fi\n          else\n            if [ \"${search_value}\" ]; then\n              if [ \"${operator}\" = \"is\" ]; then\n                check_value=$( ${cat_command} \"${check_file}\" | grep -v \"^${comment_value}\" | grep \"${parameter_name}\" | cut -f2 -d\"${separator}\" | sed 's/\"//g' | sed 's/ //g' | uniq | grep -cE \"${search_value}\" | sed \"s/ //g\" )\n              else\n                check_value=$( ${cat_command} \"${check_file}\" | grep -v \"^${comment_value}\" | grep \"${parameter_name}\" | grep \"${separator}\" | uniq | grep -cE \"${search_value}\" | sed \"s/ //g\" )\n              fi\n            else\n              if [ \"${operator}\" = \"is\" ]; then\n                check_value=$( ${cat_command} \"${check_file}\" | grep -v \"^${comment_value}\" | grep \"${parameter_name}\" | cut -f2 -d\"${separator}\" | sed 's/\"//g' | sed 's/ //g' | uniq | grep -cE \"${correct_value}\" | sed \"s/ //g\" )\n              else\n                check_value=$( ${cat_command} \"${check_file}\" | grep -v \"^${comment_value}\" | grep \"${parameter_name}\" | grep \"${separator}\" | uniq | grep -cE \"${correct_value}\" | sed \"s/ //g\" )\n              fi\n            fi\n          fi\n        fi\n        if [ \"${operator}\" = \"is\" ] || [ \"${operator}\" = \"in\" ]; then\n          if [ \"${check_value}\"  = \"1\" ]; then\n            test_value=1\n          else\n            test_value=0\n          fi\n        else\n          if [ \"${check_value}\" = \"\" ]; then\n            test_value=0\n          else\n            test_value=1\n          fi\n        fi\n        if [ \"${ansible_mode}\" = 1 ]; then\n          if [ \"${negative}\" = \"not\" ]; then\n            line=\"${parameter_name}${separator}${correct_value}\"\n          else\n            line=\"${comment_value}${parameter_name}${separator}${correct_value}\"\n          fi\n          echo \"\"\n          echo \"- name: ${string}\"\n          echo \"  lineinfile:\"\n          echo \"    path: ${check_file}\"\n          echo \" .  regex: '^${parameter_name}'\"\n          echo \"    line: '${line}'\"\n          echo \"\"\n        fi\n        if [ \"${separator}\" = \"tab\" ]; then\n          check_parameter=$( ${cat_command} \"${check_file}\" | grep -v \"^${comment_value}\" | grep \"${parameter_name}\" | awk '{print $1}' )\n        else\n          check_parameter=$( ${cat_command} \"${check_file}\" | grep -v \"^${comment_value}\" | grep \"${parameter_name}\" | cut -f1 -d\"${separator}\" | sed 's/ //g' | uniq )\n        fi\n        if [ \"$test_value\" = 0 ]; then\n          correct_hyphen=$(  echo \"${correct_value}\" | grep -c \"^[\\\\]\" | sed \"s/ //g\" )\n          if [ \"${correct_hyphen}\" = \"1\" ]; then\n            correct_value=$( echo \"${correct_value}\" | sed \"s/^[\\\\]//g\" )\n          fi\n          param_hyphen=$( echo \"${parameter_name}\" | grep -c \"^[\\\\]\" | sed \"s/ //g\" )\n          if [ \"${param_hyphen}\" = \"1\" ]; then\n            parameter_name=$( echo \"${parameter_name}\" | sed \"s/^[\\\\]//g\" )\n          fi\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_insecure \"Parameter \\\"${parameter_name}\\\" ${negative} set to \\\"${correct_value}\\\" in \\\"${check_file}\\\"\"\n            if [ \"${check_parameter}\" != \"${parameter_name}\" ]; then\n              if [ \"${separator}\" = \"tab\" ]; then\n                fix_message \"echo -e \\\"${parameter_name}\\t${correct_value}\\\" >> ${check_file}\"\n              else\n                if [ \"${position}\" = \"after\" ]; then\n                  fix_message \"${cat_command} ${check_file} | sed \\\"s,${search_value},&\\\\\\n${parameter_name}${separator}${correct_value},\\\" > ${temp_file}\"\n                  fix_message \"${cat_command} ${temp_file} > ${check_file}\"\n                else\n                  fix_message \"echo \\\"${parameter_name}${separator}${correct_value}\\\" >> ${check_file}\"\n                fi\n              fi\n            else\n              if [ \"${check_file}\" = \"/etc/default/sendmail\" ] || [ \"${check_file}\" = \"/etc/sysconfig/mail\" ] || [ \"${check_file}\" = \"/etc/rc.conf\" ] || [ \"${check_file}\" = \"/boot/loader.conf\" ] || [ \"${check_file}\" = \"/etc/sysconfig/boot\" ] || [ \"${check_file}\" = \"/etc/sudoers\" ]; then\n                fix_message \"${sed_command} \\\"s/^${parameter_name}.*/${parameter_name}${spacer}\\\"${correct_value}\\\"/\\\" ${check_file} > ${temp_file} ; cat ${temp_file} > ${check_file} ; rm ${temp_file}\"\n              else\n                fix_message \"${sed_command} \\\"s/^${parameter_name}.*/${parameter_name}${spacer}${correct_value}/\\\" ${check_file} > ${temp_file} ; cat ${temp_file} > ${check_file} ; rm ${temp_file}\"\n              fi\n            fi\n          else\n            if [ \"${audit_mode}\" = 0 ]; then\n              set_message \"Parameter \\\"${parameter_name}\\\" to \\\"${correct_value}\\\" in \\\"${check_file}\\\"\"\n              if [ \"${check_file}\" = \"/etc/system\" ]; then\n                reboot_required=1\n                notice_message \"Reboot required\"\n              fi\n              if [ \"${check_file}\" = \"/etc/ssh/sshd_config\" ] || [ \"${check_file}\" = \"/etc/sshd_config\" ]; then\n                notice_message \"Service restart required for SSH\"\n              fi\n              backup_file \"${check_file}\"\n              if [ \"${check_parameter}\" != \"${parameter_name}\" ]; then\n                if [ \"${separator_value}\" = \"tab\" ]; then\n                  lock_command=\"${echo_command} -e \\\"${parameter_name}\\t${correct_value}\\\" >> ${check_file}\"\n                else\n                  if [ \"${position}\" = \"after\" ]; then\n                    lock_command=\"${cat_command} ${check_file} | sed \\\"s,${search_value},&\\\\\\n${parameter_name}${separator}${correct_value},\\\" > ${temp_file} ; ${cat_command} ${temp_file} > ${check_file} ; rm ${temp_file}\"\n                  else\n                    lock_command=\"${echo_command} \\\"${parameter_name}${separator}${correct_value}\\\" >> ${check_file}\"\n                  fi\n                fi\n                run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n              else\n                if [ \"${check_file}\" = \"/etc/default/sendmail\" ] || [ \"${check_file}\" = \"/etc/sysconfig/mail\" ] || [ \"${check_file}\" = \"/etc/rc.conf\" ] || [ \"${check_file}\" = \"/boot/loader.conf\" ] || [ \"${check_file}\" = \"/etc/sysconfig/boot\" ] || [ \"${check_file}\" = \"/etc/sudoers\" ]; then\n                  lock_command=\"${sed_command} \\\"s/^${parameter_name}.*/${parameter_name}${spacer}\\\\\"${correct_value}\\\\\"/\\\" ${check_file} > ${temp_file} ; cat ${temp_file} > ${check_file} ; rm ${temp_file}\"\n                else\n                  lock_command=\"${sed_command} \\\"s/^${parameter_name}.*/${parameter_name}${spacer}${correct_value}/\\\" ${check_file} > ${temp_file} ; cat ${temp_file} > ${check_file} ; rm ${temp_file}\"\n                fi\n                run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n                if [ \"${os_name}\" = \"SunOS\" ]; then\n                  if [ \"${os_version}\" != \"11\" ]; then\n                    pkgchk -f -n -p \"${check_file}\" 2> /dev/null\n                  else\n                    pkg fix $( pkg search \"${check_file}\" | grep pkg | awk '{print $4}' )\n                  fi\n                fi\n              fi\n            fi\n          fi\n        else\n          inc_secure \"Parameter \\\"${parameter_name}\\\" ${operator} set to \\\"${correct_value}\\\" in \\\"${check_file}\\\"\"\n        fi\n      fi\n    fi\n  fi\n}\n\ncheck_file_value () {\n  if [ -n \"${7}\" ]; then\n    check_file_value_with_position  \"${1}\" \"${2}\" \"${3}\" \"${4}\" \"${5}\" \"${6}\" \"${7}\" \"\"\n  else\n    if [ -n \"${8}\" ]; then\n      check_file_value_with_position  \"${1}\" \"${2}\" \"${3}\" \"${4}\" \"${5}\" \"${6}\" \"${7}\" \"${8}\"\n    else\n      check_file_value_with_position  \"${1}\" \"${2}\" \"${3}\" \"${4}\" \"${5}\" \"${6}\" \"\" \"\"\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/file/disable_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# disable_value\n#\n# Code to comment out a line\n#\n# This routine takes 3 values\n# check_file      = Name of file to check\n# parameter_name  = Line to comment out\n# comment_value   = The character to use as a comment, eg # (passed as hash)\n#.\n\ndisable_value () {\n  check_file=\"${1}\"\n  parameter_name=\"${2}\"\n  comment_value=\"${3}\"\n  print_function \"disable_value\"\n  if [ -f \"${check_file}\" ]; then\n    if [ \"${comment_value}\" = \"star\" ]; then\n      comment_value=\"*\"\n    else\n      if [ \"${comment_value}\" = \"bang\" ]; then\n        comment_value=\"!\"\n      else\n        comment_value=\"#\"\n      fi\n    fi\n    if [ \"${audit_mode}\" = 2 ]; then\n      restore_file \"${check_file}\" \"${restore_dir}\"\n    else\n      check_message \"Parameter \\\"${parameter_name}\\\" in \\\"${check_file}\\\" is disabled\"\n      if [ \"${separator}\" = \"tab\" ]; then\n        param_hyphen=$( echo \"${parameter_name}\" | grep \"^[\\-]\" )\n        if [ \"${param_hyphen}\" ]; then\n          parameter_name=\"\\\\${parameter_name}\"\n        fi\n        check_value=$(  grep -v \"^${comment_value}\" \"${check_file}\" | grep \"${parameter_name}\" | uniq )\n        param_hyphen=$( echo \"${parameter_name}\" | grep \"^[\\\\]\" )\n        if [ \"${param_hyphen}\" ]; then\n          parameter_name=$( echo \"${parameter_name}\" | sed \"s/^[\\\\]//g\" )\n        fi\n        if [ \"${check_value}\" != \"${parameter_name}\" ]; then\n          inc_insecure \"Parameter \\\"${parameter_name}\\\" not set to \\\"${correct_value}\\\" in ${check_file}\"\n          if [ \"${audit_mode}\" = 0 ]; then\n            set_message \"Parameter \\\"${parameter_name}\\\" to \\\"${correct_value}\\\" in ${check_file}\"\n            if [ \"${check_file}\" = \"/etc/system\" ]; then\n              reboot_required=1\n              notice_message \"Reboot required\"\n            fi\n            if [ \"${check_file}\" = \"/etc/ssh/sshd_config\" ] || [ \"${check_file}\" = \"/etc/sshd_config\" ]; then\n              notice_message \"Service restart required SSH\"\n            fi\n            backup_file \"${check_file}\"\n            sed \"s/${parameter_name}/${comment_value}&\" < \"${check_file}\" > \"${temp_file}\"\n            cat \"${temp_file}\" > \"${check_file}\"\n            if [ \"${os_name}\" = \"SunOS\" ]; then\n              if [ \"${os_version}\" != \"11\" ]; then\n                pkgchk -f -n -p \"${check_file}\" 2> /dev/null\n              else\n                pkg_info=$( pkg search \"${check_file}\" | grep pkg | awk '{print $4}' )\n                pkg fix \"${pkg_info}\"\n              fi\n            fi\n            rm \"${temp_file}\"\n          fi\n        fi\n      else\n        inc_secure \"Parameter \\\"${parameter_name}\\\" already set to \\\"${correct_value}\\\" in ${check_file}\"\n      fi\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/file/replace_file_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# replace_file_value\n#\n# Replace a value in a file with the correct value\n#\n# As there is no interactive sed on Solaris, ie sed -i\n# pipe through sed to a temporary file, then replace original file\n# Some handling is added to replace / when searching so sed works\n#\n# check_file    = File to replace value in\n# check_value   = Value to check for\n# correct_value = What the value should be\n# position      = Position of value in the line\n#.\n\nreplace_file_value () {\n  check_file=\"${1}\"\n  check_value=\"${2}\"\n  new_check_value=\"${check_value}\"\n  correct_value=\"${3}\"\n  new_correct_value=\"${correct_value}\"\n  position=\"${4}\"\n  print_function \"replace_file_value\"\n  if [ \"${position}\" = \"start\" ]; then\n    position=\"^\"\n  else\n    position=\"\"\n  fi\n  string_check=$( expr \"${check_value}\" : \"\\/\" )\n  if [ \"${string_check}\" = 1 ]; then\n    new_check_value=$(  echo \"${check_value}\" | sed 's,/,\\\\\\/,g' )\n  fi\n  string_check=$( expr \"${correct_value}\" : \"\\/\" )\n  if [ \"${string_check}\" = 1 ]; then\n    new_correct_value=$( echo \"${correct_value}\" | sed 's,/,\\\\\\/,g' )\n  fi\n  new_check_value=\"${position}${new_check_value}\"\n  if [ \"${audit_mode}\" != 2 ]; then\n    string=\"File \\\"${check_file}\\\" contains \\\"${correct_value}\\\" rather than \\\"${check_value}\\\"\"\n    check_message  \"${string}\"\n  fi\n  if [ -f \"${check_file}\" ]; then\n    check_dfs=$( grep -c \"${new_check_value}\" < \"${check_file}\" | sed \"s/ //g\" )\n  fi\n  if [ \"${check_dfs}\" != 0 ]; then\n    if [ \"${audit_mode}\" != 2 ]; then\n      if [ \"${ansible_mode}\" = 1 ]; then\n        echo \"\"\n        echo \"- name: Checking ${string}\"\n        echo \"  lineinfile:\"\n        echo \"    path: ${check_file}\"\n        echo \"    regexp: '${new_check_value}\"\n        echo \"    replace: '${new_correct_value}\"\n        echo \"\"\n      fi\n      inc_insecure \"File \\\"${check_file}\\\" contains \\\"${check_value}\\\" rather than \\\"${correct_value}\\\"\"\n      backup_file  \"${check_file}\"\n      lock_command=\"sed -e \\\"s/${new_check_value}/${new_correct_value}/\\\" < ${check_file} > ${temp_file} ; cat ${temp_file} > ${check_file} ; rm ${temp_file}\"\n      run_lockdown \"${lock_command}\" \"Share entries in ${check_file} to be secure\" \"sudo\"\n      if [ \"${os_version}\" != \"11\" ]; then\n        pkgchk -f -n -p \"${check_file}\" 2> /dev/null\n      else\n        pkg_info=$( pkg search \"${check_file}\" | grep pkg | awk '{print $4}' )\n        pkg fix \"${pkg_info}\"\n      fi\n    else\n      restore_file \"${check_file}\" \"${restore_dir}\"\n    fi\n  else\n    inc_secure \"File ${check_file} contains \\\"${correct_value}\\\" rather than \\\"${check_value}\\\"\"\n  fi\n}\n"
  },
  {
    "path": "functions/file/restore_file.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# restore_file\n#\n# Restore file\n#\n# This routine restores a file from the backup directory to its original\n# As par of the restore it also restores the original permissions\n#\n# check_file      = The name of the original file\n# restore_dir     = The directory to restore from\n#.\n\nrestore_file () {\n  check_file=\"${1}\"\n  check_dir=\"${2}\"\n  print_function \"restore_file\"\n  if [ ! \"${check_dir}\" ]; then\n    restore_file=\"${restore_dir}${check_file}\"\n  else\n    restore_file=\"${check_dir}${check_file}\"\n  fi\n  log_file=\"${restore_dir}/fileops.log\"\n  if [ \"${audit_mode}\" = 2 ]; then\n    if [ -f \"${restore_file}\" ]; then\n      if [ -f \"${log_file}\" ]; then\n        operation=$( grep \"${check_file}\" < \"${log_file}\" | cut -f1 -d, )\n        if [ -n \"${operation}\" ]; then\n          restore_command=\"${operation} \\\"${check_file}\\\"\"\n          restore_message=\"${restore_command}\"\n          execute_restore \"${restore_message}\" \"${restore_command}\" \"sudo\"\n        fi\n      else\n        sum_check_file=$( cksum \"${check_file}\" | awk '{print $1}' )\n        sum_restore_file=$( cksum \"${restore_file}\" | awk '{print $1}' )\n        if [ \"$sum_check_file\" != \"$sum_restore_file\" ]; then\n          restore_message=\"File \\\"${restore_file}\\\" to \\\"${check_file}\\\"\"\n          restore_command=\"cp -p \\\"${restore_file}\\\" \\\"${check_file}\\\"\"\n          execute_restore \"${restore_message}\" \"${restore_command}\" \"sudo\"\n          if [ \"${os_name}\" = \"SunOS\" ]; then\n            if [ \"${os_version}\" != \"11\" ]; then\n              pkgchk -f -n -p \"${check_file}\" 2> /dev/null\n            else\n              pkg_info=$( pkg search \"${check_file}\" | grep pkg | awk '{print $4}' )\n              pkg fix \"${pkg_info}\"\n            fi\n          fi\n        fi\n      fi \n      if [ \"${check_file}\" = \"/etc/system\" ]; then\n        reboot_required=1\n        verbose_message \"Reboot required\" \"notice\"\n      fi\n      check_base=$( basename \"${check_file}\" )\n      if [ \"${check_base}\" = \"sshd_config\" ]; then\n        verbose_message \"Notice:    Service restart required for SSH\"\n      fi\n      if [ \"${ansible_mode}\" = 1 ]; then\n        echo \"\"\n        echo \"- name: Restart ssh service\"\n        echo \"  service:\"\n        echo \"    name:  ssh\"\n        echo \"    state: restarted\"\n        echo \"\"\n      fi\n    else\n      if [ -f \"${log_file}\" ]; then\n        operation=$( grep \"${check_file}\" < \"${log_file}\" | cut -f1 -d, )\n        if [ -n \"${operation}\" ]; then\n          restore_command=\"${operation} \\\"${check_file}\\\"\"\n          restore_message=\"${restore_command}\"\n          execute_restore \"${restore_message}\" \"${restore_command}\" \"sudo\"\n        fi\n      fi\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/file/update_log_file.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# update_log\n#\n# Update log file\n#\n# log_file      = The name of the original file\n# log_vale      = The directory to restore from\n#.\n\nupdate_log () {\n  log_file=\"${1}\"\n  log_value=\"${2}\"\n  print_function \"update_log\"\n  log_dir=$( dirname \"${log_file}\" )\n  if [ \"${log_dir}\" = \".\" ]; then\n    log_file=\"${restore_dir}/${log_file}\"\n  fi\n  if [ \"${audit_mode}\" = \"0\" ]; then\n    echo \"${log_value}\" >> \"${log_file}\"\n  fi\n}\n"
  },
  {
    "path": "functions/kubernetes/audit_kubernetes.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_kubernetes_all\n#\n# Audit Kubernetes \n#\n# All the Kubernetes specific tests\n#.\n\naudit_kubernetes_all () {\n  print_function \"audit_kubernetes_all\"\n  audit_kubernetes_apiserver\n  audit_kubernetes_scheduler\n  audit_kubernetes_controller\n  audit_kubernetes_etcd\n  audit_kubernetes_kubelet\n}\n\n# funct_audit_kubernetes\n#\n# Audit Kubernetes\n#.\n\nfunct_audit_kubernetes () {\n  audit_mode=\"${1}\"\n  print_function \"funct_audit_kubernetes\"\n  audit_kubernetes_all\n  print_results\n}\n"
  },
  {
    "path": "functions/linux/check_ausearch.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_ausearch\n#\n# Check what the auditing entries are for a specific command\n#.\n\ncheck_ausearch () {\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${audit_mode}\" != 2 ]; then\n      funct=\"${1}\"\n      bin=\"${2}\"\n      command=\"${3}\"\n      mode=\"${4}\"\n      value=\"${5}\" \n      print_function \"check_ausearch\"\n      exists=$( command -v \"${bin}\" )\n      if [ \"${exists}\" ]; then\n        if [ \"${value}\" ]; then\n          check=$( ausearch -k \"${bin}\" 2> /dev/null | grep \"${command}\" | grep \"${mode}\" | grep \"${value}\" )\n          secure_string=\"Binary \\\"${bin}\\\" has commands \\\"${command}\\\" with option \\\"${mode}\\\" is set to \\\"${value}\\\"\"\n          insecure_string=\"Binary \\\"${bin}\\\" has commands \\\"${command}\\\" with option \\\"${mode}\\\" is not set to \\\"${value}\\\"\"\n        else\n          check=$( ausearch -k \"${bin}\" 2> /dev/null | grep \"${command}\" | grep \"${mode}\" )\n          secure_string=\"Binary \\\"${bin}\\\" has commands \\\"${command}\\\" with option \\\"${mode}\\\" is set\"\n          insecure_string=\"Binary \\\"${bin}\\\" has commands \\\"${command}\\\" with option \\\"${mode}\\\" is unset\"\n        fi\n        check_message \"${secure_string}\"\n        if [ \"${ansible_mode}\" = 1 ]; then\n          echo \"\"\n          echo \"- name: Checking ${secure_string}\"\n          echo \"  file:\"\n          echo \"    path: ${check_file}\"\n          echo \"    mode: ${check_perms}\"\n          echo \"\"\n        fi\n        if [ \"$funct\" = \"equal\" ]; then\n          if [ \"${value}\" ]; then\n            if [ -z \"${check}\" ]; then\n              inc_insecure \"${insecure_string}\"\n            else\n              inc_secure   \"${secure_string}\"\n            fi\n          else\n            if [ \"${check}\" ]; then\n              inc_insecure \"${insecure_string}\"\n            else\n              inc_secure   \"${secure_string}\"\n            fi\n          fi\n        else\n          if [ \"${value}\" ]; then\n            if [ \"${check}\" ]; then\n              inc_insecure \"${insecure_string}\"\n            else\n              inc_secure   \"${secure_string}\"\n            fi\n          else\n            if [ -z \"${check}\" ]; then\n              inc_insecure \"${insecure_string}\"\n            else\n              inc_secure   \"${secure_string}\"\n            fi\n          fi\n        fi\n      fi\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/linux/check_chkconfig_service.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_chkconfig_service\n#\n# Code to audit a service managed by chkconfig, and enable, or disbale\n#\n# service_name    = Name of service\n# service_level   = Level service runs at\n# correct_status  = What the status of the service should be, ie enabled/disabled\n#.\n\ncheck_chkconfig_service () {\n  if [ \"${os_name}\" = \"VMkernel\" ]; then\n    service_name=\"${1}\"\n    service_level=\"${2}\"\n    correct_status=\"${3}\"\n    print_function \"check_chkconfig_service\"\n    chk_config=\"/bin/chkconfig\"\n    log_file=\"chkconfig.log\"\n    actual_status=$( ${chk_config} --list \"${service_name}\" | awk '{print $2}' )\n    if [ \"${audit_mode}\" = 2 ]; then\n      restore_file=\"${restore_dir}/${log_file}\"\n      if [ -f \"${restore_file}\" ]; then\n        check_status=$( grep \"${service_name}\" \"${restore_file}\" | cut -f2 -d, )\n        if [ \"${check_status}\" = \"on\" ] || [ \"${check_status}\" = \"off\" ]; then\n          if [ \"${check_status}\" != \"${actual_status}\" ]; then\n            restore_command=\"${chk_config} --level ${service_level} ${service_name} ${check_status}\"\n            restore_message=\"Restoring: Service \\\"${service_name}\\\" at run level \\\"${service_level}\\\" to \\\"${check_status}\\\"\"\n            execute_restore \"${restore_command}\" \"${restore_message}\" \"sudo\"\n          fi\n        fi\n      fi\n    else\n      if [ \"${actual_status}\" = \"on\" ] || [ \"${actual_status}\" = \"off\" ]; then\n       string=\"Service \\\"${service_name}\\\" is \\\"${correct_status}\\\"\"\n       check_message  \"${string}\"\n        if [ \"${actual_status}\" != \"${correct_status}\" ]; then\n          inc_insecure \"Service \\\"${service_name}\\\" is not \\\"${correct_status}\\\"\"\n          update_log   \"${log_file}\" \"${service_name},${actual_status}\"\n          lock_command=\"${chk_config} ${service_name} ${correct_status}\"\n          lock_message=\"Service \\\"${service_name}\\\" to \\\"${correct_status}\\\"\"\n          run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n        else\n          inc_secure \"${string}\"\n        fi\n      fi\n    fi\n  fi\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    service_name=\"${1}\"\n    service_level=\"${2}\"\n    correct_status=\"${3}\"\n    secure_string=\"Sevice \\\"${service_name}\\\" at run level \\\"${service_level}\\\" at rune level \\\"${service_level}\\\" is \\\"${correct_status}\\\"\"\n    insecure_string=\"Service \\\"${service_name}\\\" at run level \\\"${service_level}\\\" at rune level \\\"${service_level}\\\" is \\\"${correct_status}\\\"\"\n    check_message   \"${secure_string}\"\n    if [ \"${correct_status}\" = \"on\" ]; then\n      enabled=\"yes\"\n    else\n      enabled=\"no\"\n    fi\n    if [ \"${linux_dist}\" = \"debian\" ]; then\n      chk_config=\"/usr/sbin/sysv-rc-conf\"\n    else\n      chk_config=\"/usr/sbin/chkconfig\"\n      if [ ! -f \"${chk_config}\" ]; then\n        chk_config=\"/sbin/chkconfig\"\n      fi\n    fi\n    log_file=\"chkconfig.log\"\n    if [ \"${service_level}\" = \"3\" ]; then\n      actual_status=$( ${chk_config} --list \"${service_name}\" 2> /dev/null | awk '{print $5}' | cut -f2 -d':' | awk '{print $1}' )\n    fi\n    if [ \"${service_level}\" = \"5\" ]; then\n      actual_status=$( ${chk_config} --list \"${service_name}\" 2> /dev/null | awk '{print $7}' | cut -f2 -d':' | awk '{print $1}' )\n    fi\n    if [ \"${audit_mode}\" = 2 ]; then\n      restore_file=\"${restore_dir}/${log_file}\"\n      if [ -f \"${restore_file}\" ]; then\n        check_status=$( grep \"${service_name}\" \"${restore_file}\" | grep \",${service_level},\" | cut -f3 -d, )\n        if [ \"${check_status}\" = \"on\" ] || [ \"${check_status}\" = \"off\" ]; then\n          if [ \"${check_status}\" != \"${actual_status}\" ]; then\n            restore_command=\"${chk_config} --level ${service_level} ${service_name} ${check_status}\"\n            restore_message=\"Restoring: Service \\\"${service_name}\\\" at run level \\\"${service_level}\\\" to \\\"${check_status}\\\"\"\n            execute_restore \"${restore_command}\" \"${restore_message}\"\n          fi\n        fi\n      fi\n    else\n      if [ \"${actual_status}\" = \"on\" ] || [ \"${actual_status}\" = \"off\" ]; then\n        if [ \"${ansible_mode}\" = 1 ]; then\n          echo \"\"\n          echo \"- name: Checking ${string}\"\n          echo \"  service:\"\n          echo \"    name: ${service_name}\"\n          echo \"    enabled: ${enabled}\"\n          echo \"\"\n        fi\n        if [ \"${actual_status}\" != \"${correct_status}\" ]; then\n          inc_insecure \"${insecure_string}\"\n          update_log   \"${log_file}\" \"${service_name},${service_level},${actual_status}\"\n          lock_command=\"${chk_config} --level ${service_level} ${service_name} ${correct_status}\"\n          lock_message=\"Service ${service_name} at run level ${service_level} to ${correct_status}\"\n          run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n        else\n          inc_secure \"${secure_string}\"\n        fi\n      fi\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/linux/check_debian_package.sh",
    "content": "#!/bin/sh\n\n# -> Needs checking for install_check\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_debian_package\n#\n# Check if a deb is installed, if so install_check will be be set with name of dep,\n# otherwise it will be empty\n#.\n\ncheck_debian_package () {\n  package_name=\"${1}\"\n  print_function \"check_debian_package\"\n  check_message  \"Debian package \\\"${package_name}\\\"\"\n  install_check=$( dpkg -l \"${package_name}\" 2>&1 | grep \"${package_name}\" | awk '{print $2}' | grep \"^${package_name}$\" )\n}\n"
  },
  {
    "path": "functions/linux/check_gsettings_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_gsettings_value\n#\n# Audit gsettings values\n#\n# This routine takes the followinf values\n#\n# parameter_root  = The parameter root to be checked\n# parameter_name  = The parameter name to be checked\n# correct_value   = The value we expect to be returned\n#\n# If the current_value is not the correct_value then it is fixed if run in lockdown mode\n# A copy of the value is stored in a log file, which can be restored\n#.\n\ncheck_gsettings_value () {\n  parameter_root=\"${1}\"\n  parameter_name=\"${2}\" \n  correct_value=\"${3}\"\n  print_function \"check_gsettings_value\"\n  command_name=\"gsettings\"\n  log_file=\"${command_name}.log\"\n  check=$( command -v gsettings 2> /dev/null | wc -l | sed \"s/ //g\" )\n  if [ \"${check}\" = \"1\" ]; then\n    string=\"Parameter \\\"${parameter_name}\\\" to \\\"${correct_value}\\\"\"\n    check_message  \"${string}\"\n    set_command=\"gsettings set\"\n    get_command=\"gsettings get\"\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      if [ \"${audit_mode}\" = 2 ]; then\n        restore_file=\"${restore_dir}/${log_file}\"\n        if [ -f \"${restore_file}\" ]; then\n          parameter_root=$( grep \"${parameter_name}\" \"${restore_file}\" | cut -f1 -d',' )\n          parameter_name=$( grep \"${parameter_name}\" \"${restore_file}\" | cut -f2 -d',' )\n          correct_value=$(  grep \"${parameter_name}\" \"${restore_file}\" | cut -f3 -d',' )\n          package_test=$(   echo \"${parameter_name}\" | grep \"[A-z]\" )\n          if [ -n \"${package_test}\" ]; then\n            restore_message=\"Parameter \\\"${parameter_name}\\\" to \\\"${correct_value}\\\"\"\n            restore_command=\"${set_command} ${parameter_root} ${parameter_name} ${correct_value}\"\n            execute_restore \"${restore_command}\" \"${restore_message}\" \"sudo\"\n          fi\n        fi\n      else\n        value_check=$( gsettings get \"${parameter_root}\" \"${parameter_name}\" 2>  /dev/null | grep -c \"${correct_value}\" | sed \"s/ //g\" )\n        if [ \"${value_check}\" = \"0\" ]; then\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_insecure \"Parameter \\\"${parameter_name}\\\" is not set to \\\"${correct_value}\\\" in ${parameter_root}\"\n            string=\"Parameter \\\"${parameter_root}.${parameter_name}\\\" to \\\"${correct_value}\\\"\"\n            if [ \"${ansible_mode}\" = 1 ]; then\n              echo \"\"\n              echo \"- name: Setting ${string}\"\n              echo \"  gsetting:\"\n              echo \"    ${parameter_root}.${parameter_name}: ${correct_value}\"\n              echo \"\"\n            fi\n            fix_message \"${set_command} ${parameter_root} ${parameter_name} \\\"${correct_value}\\\"\"\n          else\n            current_value=$( gsettings get \"${parameter_root}\" \"${parameter_name}\" 2> /dev/null )\n            if [ \"${audit_mode}\" = 0 ]; then\n              update_log   \"${log_file}\" \"${parameter_root},${parameter_name},${current_value}\"\n              lock_message=\"Parameter \\\"${parameter_name}\\\" to \\\"${correct_value}\\\"\"\n              lock_command=\"${set_command} ${parameter_root} ${parameter_name} ${correct_value}\"\n              run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n            fi\n          fi\n        else\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_secure \"Parameter \\\"${parameter_name}\\\" is set to \\\"${correct_value}\\\" in ${parameter_root}\"\n          fi\n        fi\n      fi \n    fi\n  fi\n}"
  },
  {
    "path": "functions/linux/check_linux_package.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_linux_package\n#\n# Check package\n# Takes the following variables:\n# package_mode:   Mode, eg check install uninstall restore\n# package_check:  Package to check for\n#.\n\ncheck_linux_package_with_group () {\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    package_mode=\"${1}\"\n    package_check=\"${2}\"\n    group_check=\"${3}\"\n    print_function \"check_linux_package_with_group\"\n    package_type=\"Package\"\n    if [ \"${package_mode}\" = \"install\" ]; then\n      package_status=\"installed\"\n      package_state=\"present\"\n    else\n      package_status=\"uninstalled\"\n      package_state=\"absent\"\n    fi\n    log_file=\"package_log\"\n    if [ \"${audit_mode}\" != \"2\" ]; then\n      string=\"${package_type} \\\"${package_check}\\\" is \\\"${package_status}\\\"\"\n      check_message \"${string}\"\n      if [ \"${ansible_mode}\" = 1 ]; then\n        echo \"\"\n        echo \"- name: ${string}\"\n        echo \"  package:\"\n        echo \"    name: ${package_check}\"\n        echo \"    state: $package_state\"\n        echo \"\"\n      fi\n      if [ \"${linux_dist}\" = \"debian\" ]; then\n        package_name=$( dpkg -l \"${package_check}\" 2>&1 | grep \"${package_check}\" | awk '{print $2}' )\n      else\n        if [ \"${linux_dist}\" = \"arch\" ]; then\n          package_name=$( pacman -Qi \"${package_check}\" 2>&1 | grep '^Name' | awk '{print $3}' )\n        else\n          if [ ! \"${group_check}\" = \"\" ]; then\n            package_type=\"Group\"\n            package_name=$( yum grouplist 2>&1 | grep \"${package_check}\" | sed \"s/^   //g\" )\n          else\n            package_name=$( rpm -qi \"${package_check}\" | grep '^Name' | awk '{print $3}' )\n          fi\n        fi\n      fi\n      if [ \"${package_mode}\" = \"install\" ] && [ \"${package_name}\" = \"${package_check}\" ]; then\n        inc_secure \"${package_type} \\\"${package_check}\\\" is \\\"${package_status}\\\"\"\n      else\n        if [ \"${package_mode}\" = \"uninstall\" ] && [ \"${package_name}\" != \"${package_check}\" ] || [ \"${package_name}\" = \"\" ]; then\n          inc_secure   \"${package_type} \\\"${package_check}\\\" is \\\"${package_status}\\\"\"\n        else\n          inc_insecure \"${package_type} \\\"${package_check}\\\" is not \\\"${package_status}\\\"\"\n        fi\n      fi\n      if [ \"${package_mode}\" = \"install\" ]; then\n        if [ \"${linux_dist}\" = \"redhat\" ]; then\n          if [ \"${group_check}\" ]; then\n            package_command=\"yum -y groupinstall ${package_check}\"\n          else\n            package_command=\"yum -y install ${package_check}\"\n          fi\n        fi\n        if [ \"${linux_dist}\" = \"suse\" ]; then\n          package_command=\"zypper install ${package_check}\"\n        fi\n        if [ \"${linux_dist}\" = \"debian\" ]; then\n          package_command=\"apt-get install ${package_check}\"\n        fi\n        if [ \"${linux_dist}\" = \"arch\" ]; then\n          package_command=\"pacman -S ${package_check}\"\n        fi\n        if [ \"${package_check}\" = \"aide\" ]; then\n          if [ -f \"/usr/sbin/aide\" ]; then\n            if [ ! -f \"/var/lib/aide/aide.db.gz\" ]; then\n              /usr/sbin/aide --init -B \"database_out=file:/var/lib/aide/aide.db.gz\"\n            fi\n          fi\n        fi\n      fi\n      if [ \"${package_mode}\" = \"uninstall\" ]; then\n        if [ \"${linux_dist}\" = \"redhat\" ]; then\n          if [ \"${group_check}\" ]; then\n            package_command=\"yum -y groupremove ${package_check}\"\n          else\n            package_command=\"rpm -e ${package_check}\"\n          fi\n        fi\n        if [ \"${linux_dist}\" = \"suse\" ]; then\n          package_command=\"zypper remove ${package_check}\"\n        fi\n        if [ \"${linux_dist}\" = \"debian\" ]; then\n          package_command=\"apt-get purge ${package_check}\"\n        fi\n        if [ \"${linux_dist}\" = \"arch\" ]; then\n          package_command=\"pacman -R ${package_check}\"\n        fi\n      fi\n      lock_message=\"${package_type} \\\"${package_check}\\\" to \\\"${package_status}\\\"\"\n      if [ \"${audit_mode}\" = \"0\" ] && [ \"${package_mode}\" != \"check\" ]; then\n        if [ \"$package_uninstall\" = \"yes\" ]; then\n          update_log   \"${log_file}\" \"${package_check},${package_mode}\"\n          lock_command=\"${package_command}\"\n          run_lockdown \"${lock_command}\" \"${lock_message}\"\n        else\n          inc_insecure \"Not uninstalling package as package uninstall has been set to no\"\n          fix_message  \"${package_command}\"\n        fi\n      else\n        fix_message    \"${package_command}\"\n      fi\n    else\n      restore_file=\"${restore_dir}/${log_file}\"\n      if [ -f \"${restore_file}\" ]; then\n        restore_check=$( grep \"${package_check}\" \"${restore_file}\" | awk '{print $2}' )\n        if [ \"$restore_check\" = \"${package_check}\" ]; then\n          package_action=$( grep \"${package_check}\" \"${restore_file}\" | awk '{print $1}' )\n          restore_message=\"Package \\\"${package_check}\\\" to\\\" ${package_action}\\\"\"\n          if [ \"${package_action}\" = \"install\" ]; then\n            if [ \"${linux_dist}\" = \"redhat\" ]; then\n              if [ \"${group_check}\" ]; then\n                restore_command=\"yum groupremove ${package_check}\"\n              else\n                restore_command=\"rpm -e ${package_check}\"\n              fi\n            fi\n            if [ \"${linux_dist}\" = \"debian\" ]; then\n              restore_command=\"apt-get purge ${package_check}\"\n            fi\n            if [ \"${linux_dist}\" = \"suse\" ]; then\n              restore_command=\"zypper remove ${package_check}\"\n            fi\n            if [ \"${linux_dist}\" = \"arch\" ]; then\n              restore_command=\"pacman -R ${package_check}\"\n            fi\n          else\n            if [ \"${linux_dist}\" = \"redhat\" ]; then\n              if [ \"${group_check}\" ]; then\n                restore_command=\"yum groupinstall ${package_check}\"\n              else\n                restore_command=\"yum -y install ${package_check}\"\n              fi\n            fi\n            if [ \"${linux_dist}\" = \"debian\" ]; then\n              restore_command=\"apt-get install ${package_check}\"\n            fi\n            if [ \"${linux_dist}\" = \"suse\" ]; then\n              restore_command=\"zypper install ${package_check}\"\n            fi\n            if [ \"${linux_dist}\" = \"arch\" ]; then\n              restore_command=\"pacman -S ${package_check}\"\n            fi\n          fi\n          execute_restore \"${restore_command}\" \"${restore_message}\" \"sudo\"\n        fi\n      fi\n    fi\n  fi\n}\n\ncheck_linux_package () {\n  check_linux_package_with_group \"${1}\" \"${2}\" \"\"\n}\n"
  },
  {
    "path": "functions/linux/check_linux_service.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_linux_service\n#\n# Code to audit a linux service managed by chkconfig, and enable, or disable\n#\n# service_name    = Name of service\n# correct_status  = What the status of the service should be, ie enabled/disabled\n#.\n\ncheck_linux_service () {\n  service_name=\"${1}\"\n  correct_status=\"${2}\" \n  print_function \"check_linux_service\"\n  if [ \"${os_name}\" = \"VMkernel\" ] || [ \"${os_name}\" = \"Linux\" ]; then\n    if [ -f \"/usr/bin/systemctl\" ]; then\n      if [ \"${correct_status}\" = \"on\" ] || [ \"${correct_status}\" = \"enable\" ]; then\n        correct_status=\"enable\"\n      else\n        correct_status=\"disable\"\n      fi\n      check_systemctl_service \"${correct_status}\"   \"${service_name}\"\n    else\n      check_chkconfig_service \"${service_name}\" \"3\" \"${correct_status}\"\n      check_chkconfig_service \"${service_name}\" \"5\" \"${correct_status}\"\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/linux/check_systemctl_service.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_systemctl_service\n#\n# Code to audit a service managed by systemctl, and enable, or disable\n#\n# service_name    = Name of service\n# service_level   = Level service runs at\n# correct_status  = What the status of the service should be, ie enabled/disabled\n#.\n\ncheck_systemctl_service () {\n  temp_status=\"${1}\"\n  temp_name=\"${2}\"\n  print_function \"check_systemctl_service\"\n  use_systemctl=\"no\"\n  if [ \"${temp_name}\" = \"on\" ] || [ \"${temp_name}\" = \"off\" ]; then\n    correct_status=\"${temp_name}\" \n    service_name=\"${temp_status}\"\n  else\n    correct_status=\"${temp_status}\"\n    service_name=\"${temp_name}\"\n  fi\n  if [ \"${correct_status}\" = \"enable\" ] || [ \"${correct_status}\" = \"enabled\" ] || [ \"${correct_status}\" = \"on\" ]; then\n    service_switch=\"enable\"\n    correct_status=\"enabled\"\n  else\n    service_switch=\"disable\"\n    correct_status=\"disabled\"\n  fi\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${os_vendor}\" = \"Ubuntu\" ] && [ \"${os_version}\" -ge 16 ]; then\n      use_systemctl=\"yes\"\n    fi\n    if [ \"${os_vendor}\" = \"Centos\" ] || [ \"${os_vendor}\" = \"Red\" ] && [ \"${os_version}\" -ge 7 ]; then\n      use_systemctl=\"yes\"\n    fi\n  fi\n  if [ \"${correct_status}\" = \"disabled\" ]; then\n    search_string=\"disabled\"\n  else\n    search_string=\"enabled\"\n  fi\n  if [ \"${use_systemctl}\" = \"yes\" ]; then\n    log_file=\"systemctl.log\"\n    alias_check=$( systemctl is-enabled \"${service_name}\" 2> /dev/null | grep -c \"alias\" | sed \"s/ //g\" )\n    if [ \"$alias_check\" = \"1\" ]; then\n      service_name=$( systemctl status \"${service_name}\" 2> /dev/null | head -1 | awk '{print $2}' )\n    fi\n    nf_status=$( systemctl is-enabled \"${service_name}\" 2> /dev/null | grep -c \"not-found\" | sed \"s/ //g\" )\n    if [ \"$nf_status\" = \"1\" ]; then\n      actual_status=\"not-found\"\n    else\n      en_status=$( systemctl is-enabled \"${service_name}\" 2> /dev/null | grep -cE \"enabled|static\" | sed \"s/ //g\" )\n      if [ \"$en_status\" = \"1\" ]; then\n        actual_status=\"enabled\"\n      else\n        en_status=$( systemctl is-enabled \"${service_name}\" 2> /dev/null | grep -cE \"disabled\" | sed \"s/ //g\" )\n        if [ \"$en_status\" = \"1\" ]; then\n          actual_status=\"disabled\"\n        fi\n      fi\n    fi\n    if [ \"${audit_mode}\" = 2 ]; then\n      restore_file=\"${restore_dir}/${log_file}\"\n      if [ -f \"${restore_file}\" ]; then\n        check_status=$( grep \"${service_name}\" \"${restore_file}\" | cut -f2 -d, )\n        if [ \"${check_status}\" = \"enabled\" ] || [ \"${check_status}\" = \"disabled\" ]; then\n          if [ \"${check_status}\" != \"${actual_status}\" ]; then\n            verbose_message \"Restoring: Service ${service_name} at run level ${service_level} to ${check_status}\"\n            if [ \"${check_status}\" = \"enable\" ] || [ \"${check_status}\" = \"enabled\" ]; then\n              service_switch=\"enable\"\n            else\n              service_switch=\"disable\"\n            fi\n            eval \"systemctl ${service_switch} ${service_name} 2> /dev/null\"\n          fi\n        fi\n      fi\n    else\n      string=\"Service \\\"${service_name}\\\" is \\\"${correct_status}\\\"\"\n      check_message \"${string}\"\n      if [ \"${audit_mode}\" != 2 ]; then\n        if [ \"${ansible_mode}\" = 1 ]; then\n          echo \"\"\n          echo \"- name: Checking ${string}\"\n          echo \"  service:\"\n          echo \"    name: ${service_name}\"\n          echo \"    enabled: ${enabled}\"\n          echo \"  when: ansible_facts['ansible_system'] == '${os_name}'\"\n          echo \"\"\n        fi\n      fi\n      if [ \"${actual_status}\" = \"is-enabled\" ] || [ \"${actual_status}\" = \"disabled\" ] || [ \"${actual_status}\" = \"not-found\" ] || [ \"${actual_status}\" = \"enabled\" ]; then\n        if [ \"${correct_status}\" = \"enabled\" ] && [ \"${actual_status}\" = \"not-found\" ]; then\n          inc_insecure \"Service \\\"${service_name}\\\" is \\\"${actual_status}\\\"\"\n        else\n          if [ \"${actual_status}\" != \"${correct_status}\" ] && [ ! \"${actual_status}\" = \"not-found\" ]; then\n            inc_insecure \"Service \\\"${service_name}\\\" is not \\\"${correct_status}\\\"\"\n            update_log   \"${log_file}\" \"${service_name},${actual_status}\"\n            lock_command=\"systemctl ${service_switch} ${service_name} 2> /dev/null\"\n            lock_message=\"Service \\\"${service_name}\\\" to \\\"${correct_status}\\\"\"\n            run_lockdown \"${lock_command}\"  \"${lock_message}\" \"sudo\"\n          else\n            if [ \"${actual_status}\" = \"not-found\" ]; then\n              inc_secure \"Service \\\"${service_name}\\\" is \\\"${actual_status}\\\"\"\n            else\n              inc_secure \"Service \\\"${service_name}\\\" is \\\"${correct_status}\\\"\"\n            fi\n          fi\n        fi\n      fi\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/linux/check_xinetd_service.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_xinetd_service\n#\n# Code to audit an xinetd service, and enable, or disable\n#\n# service_name    = Name of service\n# correct_status  = What the status of the service should be, ie enabled/disabled\n#.\n\naudit_xinetd_service () {\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    service_name=\"${1}\"\n    parameter_name=\"${2}\"\n    correct_status=\"${3}\"\n    print_function \"audit_xinetd_service\"\n    check_file=\"/etc/xinetd.d/${service_name}\"\n    log_file=\"${work_dir}/${service_name}.log\"\n    if [ -f \"${check_file}\" ]; then\n      actual_status=$( grep \"${parameter_name}\" \"${check_file}\" | awk '{print $3}' )\n      if [ \"${audit_mode}\" != 2 ]; then\n        string=\"If xinetd service \\\"${service_name}\\\" has \\\"${parameter_name}\\\" set to \\\"${correct_status}\\\"\"\n        check_message  \"${string}\"\n        if [ \"${actual_status}\" != \"${correct_status}\" ]; then\n          if [ \"${linux_dist}\" = \"debian\" ]; then\n            command=\"update-rc.d ${service_name} ${correct_status}\"\n          else\n            command=\"chkconfig ${service_name} ${correct_status}\"\n          fi\n          inc_insecure \"Service \\\"${service_name}\\\" does not have \\\"${parameter_name}\\\" set to \\\"${correct_status}\\\"\"\n          lock_command=\"${check_file} |sed 's/${parameter_name}.*/${parameter_name} = ${correct_status}/g' > ${temp_file} ; cat ${temp_file} > ${check_file} ; ${command}\"\n          backup_file  \"${check_file}\"\n          update_log   \"${log_file}\" \"${parameter_name},${actual_status}\"\n          run_lockdown \"${lock_command}\" \"Service to ${parameter_name}\" \"sudo\"\n        else\n          inc_secure   \"Service \\\"${service_name}\\\" has \\\"${parameter_name}\\\" set to \\\"${correct_status}\\\"\"\n        fi\n        if [ \"${ansible_mode}\" = 1 ]; then\n          ansible_counter=$((ansible_counter+1))\n          ansible_value=\"audit_xinetd_service_${ansible_counter}\"\n          echo \"\"\n          echo \"- name: Checking ${string}\"\n          echo \"  command:  sh -c \\\"cat ${check_file} |grep ${parameter_name} |awk '{print \\$3}'\\\"\"\n          echo \"  register: ${ansible_value}\"\n          echo \"  failed_when: ${ansible_value} == 1\"\n          echo \"  changed_when: false\"\n          echo \"  ignore_errors: true\"\n          echo \"  when: ansible_facts['ansible_system'] == '${os_name}'\"\n          echo \"\"\n          echo \"- name: Fixing ${string}\"\n          echo \"  command: sh -c \\\"${lock_command}\\\"\"\n          echo \"  when: ${ansible_value}.rc == 1 and ansible_facts['ansible_system'] == '${os_name}'\"\n          echo \"\"\n        fi\n      else\n        restore_file=\"${restore_dir}/${log_file}\"\n        if [ -f \"${restore_file}\" ]; then\n          check_name=$( grep \"${service_name}\" \"${restore_file}\" | cut -f1 -d, )\n          if [ \"$check_name\" = \"${service_name}\" ]; then\n            check_status=$( grep \"${service_name}\" \"${restore_file}\" | cut -f2 -d, )\n            if [ \"${actual_status}\" != \"${check_status}\" ]; then\n              restore_file \"${check_file}\" \"${restore_dir}\"\n            fi\n          fi\n        fi\n      fi\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/packages/check_package.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_package\n#\n# Check Package\n#.\n\ncheck_package () {\n  package_name=\"${1}\"\n  print_function \"check_package\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n  \tcheck_linux_package   \"${package_name}\"\n  fi\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n  \tcheck_solaris_package \"${package_name}\"\n  fi\n}"
  },
  {
    "path": "functions/services/check_inetd_service.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n# shellcheck disable=SC2028\n\n# check_inetd_service\n#\n# Change status of an inetd (/etc/inetd.conf) services\n#\n#.\n\ncheck_inetd_service () {\n  if [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"SunOS\" ]; then\n    service_name=\"${1}\"\n    correct_status=\"${2}\"\n    print_function \"check_inetd_service\"\n    check_file=\"/etc/inetd.conf\"\n    log_file=\"${service_name}.log\"\n    if [ -f \"${check_file}\" ]; then\n      if [ \"${correct_status}\" = \"disabled\" ]; then\n        actual_status=$( grep \"^${service_name}\" \"${check_file}\" | grep -v '^#' | awk '{print $1}' )\n      else\n        actual_status=$( grep \"^${service_name}\" \"${check_file}\" | awk '{print $1}' )\n      fi\n      if [ \"${audit_mode}\" != 2 ]; then\n        string=\"If inetd service \\\"${service_name}\\\" is set to \\\"${correct_status}\\\"\"\n        check_message \"${string}\"\n        if [ \"${ansible_mode}\" = 1 ]; then\n          echo \"\"\n          echo \"- name: Checking ${string}\"\n          echo \"  lineinfile:\"\n          echo \"    path: ${check_file}\"\n          echo \"    regexp: ''(.*${service_name}.*)'\"\n          echo \"    replace: '#\\1'\"\n          echo \"  when: ansible_facts['ansible_system'] == '${os_name}' or ansible_facts['ansible_system'] == '${os_name}'\"\n          echo \"\"\n        fi\n        if [ \"${actual_status}\" != \"\" ]; then\n          inc_insecure \"Service \\\"${service_name}\\\" does not have \\\"${parameter_name}\\\" set to \\\"${correct_status}\\\"\"\n          backup_file  \"${check_file}\"\n          if [ \"${correct_status}\" = \"disable\" ]; then\n            disable_value \"${check_file}\" \"${service_name}\" \"hash\"\n          else\n            :\n          fi\n        else\n          inc_secure \"Service \\\"${service_name}\\\" is set to \\\"${correct_status}\\\"\"\n        fi\n      else\n        restore_file \"${check_file}\" \"${restore_dir}\"\n      fi\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/sunos/audit_system.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# funct_audit_system\n#\n# Audit System\n#.\n\nfunct_audit_system () {\n  audit_mode=\"${1}\"\n  print_function \"funct_audit_system\"\n  if [ \"${audit_mode}\" = 0 ]; then\n    if [ ! -d \"${work_dir}\" ]; then\n      mkdir -p \"${work_dir}\"\n      if [ \"${os_name}\" = \"SunOS\" ]; then\n        echo \"Creating:  Alternate Boot Environment ${date_suffix}\"\n        if [ \"${os_version}\" = \"11\" ]; then\n          beadm create \"audit_${date_suffix}\"\n        fi\n        if [ \"${os_version}\" = \"8\" ] || [ \"${os_version}\" = \"9\" ] || [ \"${os_version}\" = \"10\" ]; then\n          if [ \"${os_platform}\" != \"i386\" ]; then\n            lucreate -n \"audit_${date_suffix}\"\n          fi\n        fi\n      else\n        :\n        # Add code to do LVM snapshot\n      fi\n    fi\n  fi\n  if [ \"${audit_mode}\" = 2 ]; then\n    restore_dir=\"${base_dir}/${restore_date}\"\n    if [ ! -d \"${restore_dir}\" ]; then\n      echo \"Restore directory \\\"${restore_dir}\\\" does not exit\"\n      exit\n    else\n      set_message \"Restore directory to \\\"${restore_dir}\\\"\"\n    fi\n  fi\n  audit_system_all\n  if [ \"${do_fs}\" = 1 ]; then\n    audit_search_fs\n  fi\n  #audit_test_subset\n  sparc_test=$( echo \"${os_platform}\" | grep -c \"sparc\" | sed \"s/ //g\" )\n  if [ \"${sparc_test}\" = \"0\" ]; then\n    audit_system_x86\n  else\n    audit_system_sparc\n  fi\n  print_results\n}\n\n# audit_system_all\n#\n# Audit All System\n#.\n\naudit_system_all () {\n  print_function \"audit_system_all\"\n  full_audit_shell_services\n  full_audit_accounting_services\n  full_audit_firewall_services\n  full_audit_password_services\n  full_audit_kernel_services\n  full_audit_mail_services\n  full_audit_user_services\n  full_audit_disk_services\n  full_audit_hardware_services\n  full_audit_power_services\n  full_audit_virtualisation_services\n  full_audit_x11_services\n  full_audit_naming_services\n  full_audit_file_services\n  full_audit_web_services\n  full_audit_print_services\n  full_audit_routing_services\n  full_audit_windows_services\n  full_audit_other_daemons\n  full_audit_log_services\n  full_audit_network_services\n  full_audit_other_services\n  full_audit_update_services\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    full_audit_osx_services\n  fi\n}\n"
  },
  {
    "path": "functions/sunos/audit_system_sparc.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_system_sparc\n#\n# Audit SPARC\n#.\n\naudit_system_sparc () {\n  print_function \"audit_system_sparc\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    audit_eeprom_security\n  fi\n}\n"
  },
  {
    "path": "functions/sunos/audit_system_x86.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_system_x86\n#\n# Audit x86\n#.\n\naudit_system_x86 () {\n  print_function \"audit_system_x86\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    audit_grub_security\n    audit_kdm_config\n  fi\n}\n"
  },
  {
    "path": "functions/sunos/check_initd_service.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2010\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_initd_service\n#\n# Code to audit an init.d service, and enable, or disable service\n#\n# service_name    = Name of service\n# correct_status  = What the status of the service should be, ie enabled/disabled\n#.\n\ncheck_initd_service () {\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    service_name=\"${1}\"\n    correct_status=\"${2}\"\n    print_function \"check_initd_service\"\n    log_file=\"initd.log\"\n    service_check=$( ls /etc/init.d | grep \"^${service_name}$\" | sed 's/ //g' )\n    if [ -n \"${service_check}\" ]; then\n      if [ \"${correct_status}\" = \"disabled\" ]; then\n        check_file=\"/etc/init.d/_${service_name}\"\n        if [ -f \"${check_file}\" ]; then\n          actual_status=\"disabled\"\n        else\n          actual_status=\"enabled\"\n        fi\n      else\n        check_file=\"/etc/init.d/${service_name}\"\n        if [ -f \"${check_file}\" ]; then\n          actual_status=\"enabled\"\n        else\n          actual_status=\"disabled\"\n        fi\n      fi\n      if [ \"${audit_mode}\" != 2 ]; then\n        string=\"If init.d service \\\"${service_name}\\\" is \\\"${correct_status}\\\"\"\n        verbose_message \" ${string}\" \"check\"\n        if [ \"${ansible_mode}\" = 1 ]; then\n          echo \"\"\n          echo \"- name: Checking ${string}\"\n          echo \"  service:\"\n          echo \"    name: ${service_name}\"\n          echo \"    enabled: ${actual_status}\"\n          echo \"  when: ansible_facts['ansible_system'] == '${os_name}'\"\n          echo \"\"\n        fi\n      fi\n      if [ \"${actual_status}\" != \"${correct_status}\" ]; then\n        inc_insecure \"Service \\\"${service_name}\\\" is not \\\"${correct_status}\\\"\"\n        update_log   \"${log_file}\" \"${service_name},${actual_status}\"\n        lock_message=\"Service ${service_name} to ${correct_status}\"\n        if [ \"${correct_status}\" = \"disabled\" ]; then\n          lock_command=\"/etc/init.d/${service_name} stop ; mv /etc/init.d/${service_name} /etc/init.d/_${service_name}\"\n          run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n        else\n          lock_command=\"mv /etc/init.d/_${service_name} /etc/init.d/${service_name} ; /etc/init.d/${service_name} start\"\n          run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n        fi\n      else\n        if [ \"${audit_mode}\" = 2 ]; then\n          restore_file=\"${restore_dir}/${log_file}\"\n          if [ -f \"${restore_file}\" ]; then\n            check_name=$( grep \"${service_name}\" \"${restore_file}\" | cut -f1 -d, )\n            if [ \"$check_name\" = \"${service_name}\" ]; then\n              check_status=$( grep \"${service_name}\" \"${restore_file}\" | cut -f2 -d, )\n              restore_message=\"Service ${service_name} to ${check_status}\"\n              if [ \"${check_status}\" = \"disabled\" ]; then\n                restore_command=\"/etc/init.d/${service_name} stop ; mv /etc/init.d/${service_name} /etc/init.d/_${service_name}\"\n                execute_restore \"${restore_command}\" \"${restore_message}\"\n              else\n                restore_command=\"mv /etc/init.d/_${service_name} /etc/init.d/${service_name} ; /etc/init.d/${service_name} start\"\n                execute_restore \"${restore_command}\" \"${restore_message}\"\n              fi\n            fi\n          fi\n        else\n          inc_secure \"Service \\\"${service_name}\\\" is \\\"${correct_status}\\\"\"\n        fi\n      fi\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/sunos/check_service.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_service\n#\n# Service audit routine wrapper, sends to appropriate function based on service type\n#\n# service_name    = Name of service\n# correct_status  = What the status of the service should be, ie enable/disabled\n#.\n\ncheck_service () {\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    service_name=\"${1}\"\n    correct_status=\"${2}\"\n    print_function \"check_service\"\n    service_test=$( echo \"${service_name}\" | grep \"svc:\" )\n    if [ -n \"${service_test}\" ]; then\n      check_svcadm_service \"${service_name}\" \"${correct_status}\"\n    else\n      check_initd_service  \"${service_name}\" \"${correct_status}\"\n      check_inetd_service  \"${service_name}\" \"${correct_status}\"\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/sunos/check_solaris_package.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# funct_check_pkg\n#\n# Check is a package is installed\n#\n# Install package if it's not installed and in the pkg dir under the base dir\n# Needs some more work\n#.\n\nfunct_check_pkg () {\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    package_name=\"${1}\"\n    print_function \"funct_check_pkg\"\n    package_check=$( pkginfo \"${1}\" )\n    log_file=\"${work_dir}/pkg.log\"\n    if [ \"${audit_mode}\" = 2 ]; then\n      restore_file=\"${restore_dir}/pkg.log\"\n      if [ -f \"${restore_file}\" ]; then\n        restore_check=$( grep \"^${package_name}$\" < \"${restore_file}\" | head -1 )\n        if [ \"$restore_check\" = \"${package_name}\" ]; then\n          if [ \"${os_version}\" = \"11\" ]; then\n            execute_restore \"pkg uninstall ${package_name}\" \"Package \\\"${package_name}\\\"\" \"sudo\"\n          else\n            execute_restore \"pkgrm ${package_name}\" \"Package \\\"${package_name}\\\"\" \"sudo\"\n          fi\n        fi\n      fi\n    else\n      string=\"Package \\\"${package_name}\\\" is installed\"\n      check_message \"${string}\"\n      if [ \"${ansible_mode}\" = 1 ]; then\n        echo \"\"\n        echo \"- name: Checking ${string}\"\n        echo \"  package:\"\n        echo \"    name: ${package_name}\"\n        echo \"    state: present\"\n        echo \"  when: ansible_facts['ansible_system'] == '${os_name}'\"\n        echo \"\"\n      fi\n      package_test=$( echo \"${package_check}\" | grep \"ERROR\" )\n      if [ -z \"${package_test}\" ]; then\n        inc_secure \"Package \\\"${package_name}\\\" is already installed\"\n      else\n        if [ \"${audit_mode}\" = 1 ]; then\n          inc_insecure \"Package \\\"${package_name}\\\" is not installed\"\n          pkg_dir=\"${base_dir}/pkg/${package_name}\"\n          if [ -d \"$pkg_dir\" ]; then\n            install_message \"Package \\\"${package_name}\\\"\"\n            if [ \"${os_version}\" = \"11\" ]; then\n              pkgadd \"${package_name}\"\n            else\n              pkgadd -d \"${base_dir}/pkg\" \"${package_name}\"\n              package_check=$( pkginfo \"${1}\" )\n            fi\n            package_test=$( echo \"${package_check}\" | grep \"ERROR\" )\n            if [ -z \"${package_check}\" ]; then\n              fix_message \"${package_name}\" >> \"${log_file}\"\n            fi\n          fi\n        fi\n      fi\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/sunos/check_sunos_service.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_sunos_service\n#\n# Service audit routine wrapper, sends to appropriate function based on service type\n#\n# service_name    = Name of service\n# correct_status  = What the status of the service should be, ie enable/disabled\n#.\n\ncheck_sunos_service () {\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    temp_name=\"${1}\"\n    temp_status=\"${2}\"\n    print_function \"check_sunos_service\"\n    if [ \"${temp_name}\" = \"disable\" ] || [ \"${temp_name}\" = \"enable\" ]; then\n      service_name=${temp_status}\n      if [ \"${temp_name}\" = \"disable\" ]; then\n        correct_status=\"disabled\"\n      else\n        correct_status=\"enabled\"\n      fi\n    else\n      service_name=\"${temp_name}\"\n      correct_status=\"${temp_status}\"\n    fi\n    service_test=$( echo \"${service_name}\" | grep \"svc:\" )\n    if [ -n \"${service_test}\" ]; then\n      check_svcadm_service \"${service_name}\" \"${correct_status}\"\n    else\n      check_initd_service  \"${service_name}\" \"${correct_status}\"\n      check_inetd_service  \"${service_name}\" \"${correct_status}\"\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/sunos/check_svcadm_service.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_svcadm_service\n#\n# Function to audit a svcadm service and enable or disable\n#\n# service_name    = Name of service\n# correct_status  = What the status of the service should be, ie enabled/disabled\n#.\n\ncheck_svcadm_service () {\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    service_name=\"${1}\"\n    correct_status=\"${2}\"\n    print_function \"check_svcadm_service\"\n    file_header=\"svcadm\"\n    service_exists=$( svcs -a | grep \"${service_name}\" | awk '{print $3}' )\n    if [ \"${audit_mode}\" = 2 ]; then\n      restore_file=\"${restore_dir}/${file_header}.log\"\n      if [ -f \"${restore_file}\" ]; then\n        restore_status=$( grep \"^${service_name}\" \"${restore_file}\" | cut -f2 -d, )\n        restore_test=$(   echo \"${restore_status}\" | grep \"[A-z]\" )\n        if [ -n \"${restore_test}\" ]; then\n          if [ \"${restore_status}\" != \"${service_status}\" ]; then\n            restore_status=$( echo \"${restore_status}\" | sed \"s/online/enable/g\" | sed \"s/offline/disable/g\" )\n            restore_message=\"Service \\\"${service_name}\\\" to \\\"${restore_status}\\\"\"\n            restore_command=\"svcadm ${restore_status} ${service_name} ; svcadm refresh ${service_name}\"\n            execute_restore \"${restore_command}\" \"${restore_message}\" \"sudo\"\n          fi\n        fi\n      fi\n    else\n      if [ \"${service_exists}\" = \"${service_name}\" ]; then\n        service_status=$( svcs -Ho state \"${service_name}\" )\n        log_file=\"${file_header}.log\"\n        string=\"Service ${service_name} is ${correct_status}\"\n        check_message  \"${string}\"\n        if [ \"${ansible_mode}\" = 1 ]; then\n          echo \"\"\n          echo \"- name: Checking ${string}\"\n          echo \"  service:\"\n          echo \"    name: ${service_name}\"\n          echo \"    enabled: ${service_status}\"\n          echo \"  when: ansible_facts['ansible_system'] == '${os_name}'\"\n          echo \"\"\n        fi\n        if [ \"${service_status}\" != \"${correct_status}\" ]; then\n          inc_insecure \"Service \\\"${service_name}\\\" is \\\"enabled\\\"\"\n          update_log   \"${log_file}\" \"${service_name},${service_status}\"\n          lock_message=\"Service \\\"${service_name}\\\" to \\\"${correct_status}\\\"\"\n          lock_command=\"inetadm -d ${service_name} ; svcadm refresh ${service_name}\"\n          run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n        else\n          inc_secure   \"Service \\\"${service_name}\\\" is already \\\"disabled\\\"\"\n        fi\n      fi\n    fi\n  fi\n}\n"
  },
  {
    "path": "functions/sunos/create_ndd_script.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n# shellcheck disable=SC2129\n\n# create_nddscript\n#\n# Creates an ndd boot script for Solaris\n#\n#.\n\ncreate_nddscript () {\n  print_function \"create_nddscript\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" != \"11\" ]; then\n      check_message \"Kernel ndd Parameters\"\n      check_file=\"/etc/init.d/ndd-netconfig\"\n      rcd_file=\"/etc/rc2.d/S99ndd-netconfig\"\n      if [ \"${audit_mode}\" = 0 ]; then\n        if [ ! -f \"${check_file}\" ]; then\n          echo \"Creating:  Init script \\\"${check_file}\\\"\"\n          printf \"#!/sbin/sh\"       > \"${check_file}\"\n          printf \"case \\\"\\$1\\\" in\"  >> \"${check_file}\"\n          printf \"start)\"           >> \"${check_file}\"\n          printf \"\\t/usr/sbin/ndd -set /dev/ip ip_forward_src_routed 0\"                 >> \"${check_file}\"\n          printf \"\\t/usr/sbin/ndd -set /dev/ip ip_forwarding 0\"                         >> \"${check_file}\"\n          if [ \"${os_version}\" = \"8\" ] || [ \"${os_version}\" = \"9\" ] || [ \"${os_version}\" = \"10\" ]; then\n            printf \"\\t/usr/sbin/ndd -set /dev/ip ip6_forward_src_routed 0\"              >> \"${check_file}\"\n            printf \"\\t/usr/sbin/ndd -set /dev/tcp tcp_rev_src_routes 0\"                 >> \"${check_file}\"\n            printf \"\\t/usr/sbin/ndd -set /dev/ip ip6_forwarding 0\"                      >> \"${check_file}\"\n          fi\n          printf \"\\t/usr/sbin/ndd -set /dev/ip ip_forward_directed_broadcasts 0\"        >> \"${check_file}\"\n          printf \"\\t/usr/sbin/ndd -set /dev/tcp tcp_conn_req_max_q0 4096\"               >> \"${check_file}\"\n          printf \"\\t/usr/sbin/ndd -set /dev/tcp tcp_conn_req_max_q 1024\"                >> \"${check_file}\"\n          printf \"\\t/usr/sbin/ndd -set /dev/ip ip_respond_to_timestamp 0\"               >> \"${check_file}\"\n          printf \"\\t/usr/sbin/ndd -set /dev/ip ip_respond_to_timestamp_broadcast 0\"     >> \"${check_file}\"\n          printf \"\\t/usr/sbin/ndd -set /dev/ip ip_respond_to_address_mask_broadcast 0\"  >> \"${check_file}\"\n          printf \"\\t/usr/sbin/ndd -set /dev/ip ip_respond_to_echo_multicast 0\"          >> \"${check_file}\"\n          if [ \"${os_version}\" = \"8\" ] || [ \"${os_version}\" = \"9\" ] || [ \"${os_version}\" = \"10\" ]; then\n            printf \"\\t/usr/sbin/ndd -set /dev/ip ip6_respond_to_echo_multicast 0\"       >> \"${check_file}\"\n          fi\n          printf \"\\t/usr/sbin/ndd -set /dev/ip ip_respond_to_echo_broadcast 0\"          >> \"${check_file}\"\n          printf \"\\t/usr/sbin/ndd -set /dev/arp arp_cleanup_interval 60000\"             >> \"${check_file}\"\n          printf \"\\t/usr/sbin/ndd -set /dev/ip ip_ire_arp_interval 60000\"               >> \"${check_file}\"\n          printf \"\\t/usr/sbin/ndd -set /dev/ip ip_ignore_redirect 1\"                    >> \"${check_file}\"\n          if [ \"${os_version}\" = \"8\" ] || [ \"${os_version}\" = \"9\" ] || [ \"${os_version}\" = \"10\" ]; then\n            printf \"\\t/usr/sbin/ndd -set /dev/ip ip6_ignore_redirect 1\"                 >> \"${check_file}\"\n          fi\n          printf \"\\t/usr/sbin/ndd -set /dev/tcp tcp_extra_priv_ports_add 6112\"          >> \"${check_file}\"\n          printf \"\\t/usr/sbin/ndd -set /dev/ip ip_strict_dst_multihoming 1\"             >> \"${check_file}\"\n          if [ \"${os_version}\" = \"8\" ] || [ \"${os_version}\" = \"9\" ] || [ \"${os_version}\" = \"10\" ]; then\n            printf \"\\t/usr/sbin/ndd -set /dev/ip ip6_strict_dst_multihoming 1\"          >> ${check_file}\n          fi\n          printf \"\\t/usr/sbin/ndd -set /dev/ip ip_send_redirects 0\"                     >> \"${check_file}\"\n          if [ \"${os_version}\" = \"8\" ] || [ \"${os_version}\" = \"9\" ] || [ \"${os_version}\" = \"10\" ]; then\n            printf \"\\t/usr/sbin/ndd -set /dev/ip ip6_send_redirects 0\"                  >> \"${check_file}\"\n          fi\n          printf \"esac\"   >> ${check_file}\n          printf \"exit 0\" >> ${check_file}\n          chmod 750 ${check_file}\n          if [ ! -f \"${rcd_file}\" ]; then\n            ln -s \"${check_file}\" \"${rcd_file}\"\n          fi\n        fi\n      else\n        if [ \"${audit_mode}\" = 1 ]; then\n          fix_message \"\"\n          if [ ! -f \"${check_file}\" ]; then\n            fix_message   \"Create an init script ${check_file} containing the following:\"\n            fix_message   \"#!/sbin/sh\"\n            fix_message   \"case \\\"\\$1\\\" in\"\n            fix_message   \"start)\"\n            fix_message   \"\\t/usr/sbin/ndd -set /dev/ip ip_forward_src_routed 0\"\n            fix_message   \"\\t/usr/sbin/ndd -set /dev/ip ip_forwarding 0\"\n            if [ \"${os_version}\" = \"8\" ] || [ \"${os_version}\" = \"9\" ] || [ \"${os_version}\" = \"10\" ]; then\n              fix_message \"\\t/usr/sbin/ndd -set /dev/ip ip6_forward_src_routed 0\"\n              fix_message \"\\t/usr/sbin/ndd -set /dev/tcp tcp_rev_src_routes 0\"\n              fix_message \"\\t/usr/sbin/ndd -set /dev/ip ip6_forwarding 0\"\n            fi\n            fix_message   \"\\t/usr/sbin/ndd -set /dev/ip ip_forward_directed_broadcasts 0\"\n            fix_message   \"\\t/usr/sbin/ndd -set /dev/tcp tcp_conn_req_max_q0 4096\"\n            fix_message   \"\\t/usr/sbin/ndd -set /dev/tcp tcp_conn_req_max_q 1024\"\n            fix_message   \"\\t/usr/sbin/ndd -set /dev/ip ip_respond_to_timestamp 0\"\n            fix_message   \"\\t/usr/sbin/ndd -set /dev/ip ip_respond_to_timestamp_broadcast 0\"\n            fix_message   \"\\t/usr/sbin/ndd -set /dev/ip ip_respond_to_address_mask_broadcast 0\"\n            fix_message   \"\\t/usr/sbin/ndd -set /dev/ip ip_respond_to_echo_multicast 0\"\n            if [ \"${os_version}\" = \"8\" ] || [ \"${os_version}\" = \"9\" ] || [ \"${os_version}\" = \"10\" ]; then\n              fix_message \"\\t/usr/sbin/ndd -set /dev/ip ip6_respond_to_echo_multicast 0\"\n            fi\n            fix_message   \"\\t/usr/sbin/ndd -set /dev/ip ip_respond_to_echo_broadcast 0\"\n            fix_message   \"\\t/usr/sbin/ndd -set /dev/arp arp_cleanup_interval 60000\"\n            fix_message   \"\\t/usr/sbin/ndd -set /dev/ip ip_ire_arp_interval 60000\"\n            fix_message   \"\\t/usr/sbin/ndd -set /dev/ip ip_ignore_redirect 1\"\n            if [ \"${os_version}\" = \"8\" ] || [ \"${os_version}\" = \"9\" ] || [ \"${os_version}\" = \"10\" ]; then\n              fix_message \"\\t/usr/sbin/ndd -set /dev/ip ip6_ignore_redirect 1\"\n            fi\n            fix_message   \"\\t/usr/sbin/ndd -set /dev/tcp tcp_extra_priv_ports_add 6112\"\n            fix_message   \"\\t/usr/sbin/ndd -set /dev/ip ip_strict_dst_multihoming 1\"\n            if [ \"${os_version}\" = \"8\" ] || [ \"${os_version}\" = \"9\" ] || [ \"${os_version}\" = \"10\" ]; then\n              fix_message \"\\t/usr/sbin/ndd -set /dev/ip ip6_strict_dst_multihoming 1\"\n            fi\n            fix_message   \"\\t/usr/sbin/ndd -set /dev/ip ip_send_redirects 0\"\n            if [ \"${os_version}\" = \"8\" ] || [ \"${os_version}\" = \"9\" ] || [ \"${os_version}\" = \"10\" ]; then\n              fix_message \"\\t/usr/sbin/ndd -set /dev/ip ip6_send_redirects 0\"\n            fi\n            fix_message   \"esac\"\n            fix_message   \"exit 0\"\n            fix_message   \"\"\n            fix_message   \"Then run the following command(s)\"\n            fix_message   \"chmod 750 ${check_file}\"\n            if [ ! -f \"${rcd_file}\" ]; then\n              fix_message \"ln -s ${check_file} ${rcd_file}\"\n            fi\n          fi\n        fi\n      fi\n    fi\n  fi\n}\n"
  },
  {
    "path": "lunar.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2029\n# shellcheck disable=SC2034\n# shellcheck disable=SC2124\n# shellcheck disable=SC2317\n# shellcheck disable=SC2329\n# shellcheck disable=SC3046\n\n# Name:         lunar (Lockdown UNix Auditing and Reporting)\n# Version:      15.9.1\n# License:      CC-BA (Creative Commons By Attribution)\n#               http://creativecommons.org/licenses/by/4.0/legalcode\n# Group:        System\n# Source:       N/A\n# URL:          http://lateralblast.com.au/\n# Distribution: Solaris, Red Hat Linux, SuSE Linux, Debian Linux,\n#               Ubuntu Linux, Mac OS X, AIX, FreeBSD, ESXi\n# Vendor:       UNIX\n# Packager:     Richard Spindler <richard@lateralblast.com.au>\n# Description:  Audit script based on various benchmarks\n#               Addition improvements added\n#               Written in bourne shell so it can be run on different releases\n\n# No warranty is implied or given with this script\n# It is based on numerous security guidelines\n# As with any system changes, the script should be vetted and\n# changed to suit the environment in which it is being used\n\n# Unless your organization is specifically using the service, disable it.\n# The best defense against a service being exploited is to disable it.\n\n# Even if a service is set to off the script will audit the configuration\n# file so that if a service is re-enabled the configuration is secure\n# Where possible checks are made to make sure the package is installed\n# if the package is not installed the checks will not be run\n\n# To do:\n#\n# - nosuid,noexec for Linux\n# - Disable user mounted removable filesystems for Linux\n# - Disable USB devices for Linux\n# - Grub password\n# - Restrict NFS client requests to privileged ports Linux\n\n# Solaris Release Information\n#  1/06 U1\n#  6/06 U2\n# 11/06 U3\n#  8/07 U4\n#  5/08 U5\n# 10/08 U6\n#  5/09 U7\n# 10/09 U8\n#  9/10 U9\n#  8/11 U10\n#  1/13 U11\n\n# audit_mode = 1 : Audit Mode\n# audit_mode = 0 : Lockdown Mode\n# audit_mode = 2 : Restore Mode\n\n# Azure\ncheck_azure=0\nazure_auth_mode=\"login\"\nazure_tenant_id=\"\"\nazure_allow_no_subscriptions=\"no\"\nazure_python_version=\"3.8\"\nazure_java_version=\"11\"\nazure_ftp_state=\"Disabled\"\nazure_managed_identity=\"SystemAssigned\"\nazure_sku_tier=\"Basic\"\nazure_ase_version=\"ASEV3\"\n#azure_ftp_state=\"FtpsOnly\"\n\n# Defaults for AWS\n\ncheck_aws=0\naws_iam_master_role=\"iam-master\"\naws_iam_manager_role=\"iam-manager\"\naws_cloud_trail_name=\"aws-audit-log\"\nsns_protocol=\"email\"\nsns_endpoint=\"alerts@company.com\"\nvalid_tag_string=\"(ue1|uw1|uw2|ew1|ec1|an1|an2|as1|as2|se1)-(d|t|s|p)-([a-z0-9\\-]+)$\"\nstrict_valid_names=\"y\"\ncheck_volattach=\"y\"\ncheck_voltype=\"y\"\ncheck_snapage=\"y\"\naws_region=\"\"\naws_rds_min_retention=\"7\"\naws_ec2_min_retention=\"7\"\naws_ec2_max_retention=\"30\"\naws_days_to_key_deletion=\"7\"\n\n# Defaults for MacOS\n\nkeychain_sync=\"1\"\ndisable_airdrop=\"1\"\nasset_cache=\"false\"\nwifi_status=\"2\"\ntouchid_timeout=\"86400\"\n\n# Defaults for SSH\n\nssh_protocol=\"2\"\nssh_key_size=\"4096\"\nssh_allowusers=\"\"\nssh_allowgroups=\"\"\nssh_denyusers=\"\"\nssh_denygroups=\"\"\n\n# Set up some counters\n\nsecure_count=0\ninsecure_count=0\nlockdown_count=0\nrestore_count=0\ntotal_count=0\n\n# Set up some global variables/defaults\n\nos_hostname=$( hostname -f )\napp_dir=$( dirname \"$0\" )\nargs=\"$@\"\nuse_sudo=0\nsyslog_server=\"\"\nsyslog_logdir=\"\"\npkg_suffix=\"lunar\"\nbase_dir=\"/var/log/${pkg_suffix}\"\ntemp_dir=\"${base_dir}/tmp\"\ndate_suffix=$( date +%d_%m_%Y_%H_%M_%S )\ntemp_file=\"${temp_dir}/${pkg_suffix}.tmp\"\nwork_dir=\"${base_dir}/${date_suffix}\"\ncsv_dir=\"${base_dir}/csv\"\nwheel_group=\"wheel\"\ndocker_group=\"docker\"\nreboot_required=0\nverbose_mode=0\ncommand_mode=0\ndryrun_mode=0\nansible_mode=0\nansible_counter=0\nmain_dir=\"${app_dir}/main\"\nfunctions_dir=\"${app_dir}/functions\"\nmodules_dir=\"${app_dir}/modules\"\nprivate_dir=\"${app_dir}/private\"\npackage_uninstall=\"no\"\ncountry_suffix=\"au\"\nlanguage_suffix=\"en_US\"\nosx_mdns_enable=\"yes\"\nmax_super_user_id=\"100\"\nuse_expr=\"no\"\nuse_finger=\"yes\"\ntest_os=\"none\"\ntest_tag=\"none\"\naction=\"none\"\ndo_compose=0\ndo_multipass=0\ndo_shell=0\ndo_remote=0\nmy_id=$(id -u)\ntcpd_allow=\"sshd\"\ndo_audit=0\ndo_fs=0\naudit_mode=1\naudit_type=\"local\"\ngit_url=\"https://github.com/lateralblast/lunar.git\"\npassword_hashing=\"sha512\"\nanacron_enable=\"no\"\nssh_sandbox=\"yes\"\ndo_debug=0\ndo_select=0\nmodule_name=\"\"\nno_cat=1\nubuntu_codename=\"\"\noutput_type=\"cli\"\noutput_file=\"\"\noutput_csv=\"Module,Check,Status,Fix\"\n\n# Disable daemons\n\nnfsd_disable=\"yes\"\nsnmpd_disable=\"yes\"\ndhcpcd_disable=\"yes\"\ndhcprd_disable=\"yes\"\ndhcpsd_disable=\"yes\"\nsendmail_disable=\"yes\"\nipv6_disable=\"yes\"\nrouted_disable=\"yes\"\nnamed_disable=\"yes\"\n\n# verbose_message\n#\n# Print a message if verbose mode enabled\n#.\n\nverbose_message () {\n  text=\"${1}\"\n  style=\"${2}\"\n  if [ \"${verbose_mode}\" = 1 ] && [ \"${style}\" = \"fix\" ]; then\n    if [ \"${text}\" = \"\" ]; then\n      echo \"\"\n    else\n      echo \"[ Fix ]     ${text}\"\n      output_csv=\"${output_csv},${text}\"\n      if [ ! \"${output_file}\" = \"\" ]; then\n        case \"${output_csv}\" in *\"check_\"*) echo \"${output_csv}\" >> \"${output_file}\";; esac\n      fi\n    fi\n  else\n    case $style in\n      audit*)\n        echo \"Auditing:   ${text}\"\n        ;;\n      backup)\n        echo \"Backup:     ${text}\"\n        ;;\n      check*)\n        echo \"Checking:   ${text}\"\n        output_csv=\"${output_csv},${text}\"\n        ;;\n      creat*)\n        echo \"Creating:   ${text}\"\n        ;;\n      delet*)\n        echo \"Deleting:   ${text}\"\n        ;;\n      exec*)\n        if [ \"${dryrun_mode}\" = 0 ]; then\n          echo \"Executing:  ${text}\"\n        else\n          echo \"Command:    ${text}\"\n        fi\n        ;;\n      install*)\n        echo \"Installing: ${text}\"\n        ;;\n      load*)\n        echo \"Loading:    ${text}\"\n        ;;\n      module)\n        echo \"Module:     ${text}\"\n        if [ ! \"${output_file}\" = \"\" ]; then\n          case \"${output_csv}\" in *\"check_\"*) echo \"${output_csv}\" >> \"${output_file}\";; esac\n        fi\n        output_csv=\"${text}\"\n        ;;\n      notice)\n        echo \"Notice:     ${text}\"\n        ;;\n      remov*)\n        echo \"Removing:   ${text}\"\n        ;;\n      run*)\n        echo \"Running:    ${text}\"\n        ;;\n      sav*)\n        echo \"Saving:     ${text}\"\n        ;;\n      set*)\n        echo \"Setting:    ${text}\"\n        ;;\n      secur*)\n        echo \"Secure:     ${text}\"\n        ;;\n      updat*)\n        echo \"Updating:   ${text}\"\n        ;;\n      warn*)\n        echo \"Warning:    ${text}\"\n        ;;\n      na)\n        echo \"Notice:     ${text} is not applicable on this system\"\n        ;;\n      *)\n        if [ \"${verbose_mode}\" = 1 ]; then\n          echo \"${text}\"\n        fi\n        ;;\n    esac\n  fi\n}\n\n# warn_message\n#\n# Warning message\n#.\n\nwarn_message () {\n  verbose_message \"${1}\" \"warn\"\n}\n\n# info_message\n#\n# Information message\n#.\n\ninfo_message () {\n  verbose_message \"${1}\" \"info\"\n}\n\n# lockdown_warning\n#\n# Check whether to proceed\n#.\n\nlockdown_warning () {\n  if [ \"${dryrun_mode}\" = 0 ]; then\n    if [ \"${force}\" != 1 ]; then\n      warning_message \"This will alter the system\"\n      printf \"%s\" \"Do you want to continue? (yes/no): \"\n      while read -r reply\n      do\n        case \"${reply}\" in\n          yes)\n            return\n            ;;\n          *)\n            exit\n            ;;\n        esac\n      done\n    fi\n  fi\n}\n\n# Get our ID\n\nos_name=$( uname )\nif [ \"${os_name}\" != \"VMkernel\" ]; then\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    id_check=$( id | cut -c5 )\n  else\n    id_check=$( id -u )\n  fi\n  arg_test=$(echo \"$@\" | grep -cE \"\\-h|-V|--help|--version|info\" )\nfi\n\n# Reset base dirs if not running as root\nif [ ! \"${id_check}\" = 0 ]; then\n  base_dir=\"$HOME/.${pkg_suffix}\"\n  temp_dir=\"${base_dir}/tmp\"\n  temp_file=\"${temp_dir}/${pkg_suffix}.tmp\"\n  work_dir=\"${base_dir}/${date_suffix}\"\n  csv_dir=\"${base_dir}/csv\"\nfi\n\n# Load main functions from main directory\nif [ -d \"${main_dir}\" ]; then\n  if [ \"${verbose_mode}\" = \"1\" ]; then\n    echo \"\"\n    echo \"Loading main functions\"\n    echo \"\"\n  fi\n  file_list=$( ls \"${main_dir}\"/*.sh )\n  for file_name in ${file_list}; do\n    . \"${file_name}\"\n    if [ \"${verbose_mode}\" = \"1\" ]; then\n      verbose_message \"\\\"${file_name}\\\"\" \"load\"\n    fi\n  done\nfi\n\n# Install packages\n\ninstall_rsyslog=\"no\"\n\n# This is the company name that will go into the security message\n# Change it as required\n\ncompany_name=\"Insert Company Name Here\"\n\n# check_virtual_platform\n#\n# Check if we are running on a virtual platform\n#.\n\ncheck_virtual_platform () {\n  virtual=\"Unknown\"\n  if [ -f \"/.dockerenv\" ]; then\n    virtual=\"Docker\"\n  else \n    dmi_check=$( command -v dmidecode | grep dmidecode | grep -cv no )\n    if [ \"$dmi_check\" = \"1\" ] && [ \"${my_id}\" = \"0\" ]; then\n      virtual=$( dmidecode | grep Manufacturer |head -1 | awk '{print $2}' | sed \"s/,//g\" )\n    else\n      virtual=$( uname -p )\n      if [ \"${virtual}\" = \"unknown\" ]; then\n        virtual=$( uname -m )\n      fi\n    fi\n  fi\n  echo \"Platform:   ${virtual}\"\n}\n\n# execute_command\n#\n# Execute a command\n#.\n\nexecute_command () {\n  command=\"${1}\"\n  verbose_message \"${command}\" \"execute\"\n  if [ \"${dryrun_mode}\" = 0 ]; then\n    result=$( eval \"${command}\" )\n    echo \"${result}\"\n  fi\n}\n\n# run_lockdown\n#\n# Run a lockdown command\n# Check that we are in lockdown mode\n# If not in lockdown mode output a verbose message\n#.\n\nrun_lockdown () {\n  command=\"${1}\"\n  message=\"${2}\"\n  privilege=\"${3}\"\n  if [ \"${audit_mode}\" = 0 ]; then\n    total_count=$((total_count+1))\n    if [ \"${message}\" ]; then\n      verbose_message \"${message}\" \"set\"\n    fi\n    verbose_message \"${command}\" \"execute\"\n    if [ \"${privilege}\" = \"\" ]; then\n      if [ \"${dryrun_mode}\" = 0 ]; then\n        lockdown_count=$((lockdown_count+1))\n        sh -c \"${command}\"\n      fi\n    else\n      if [ \"$my_id\" = \"0\" ]; then\n        if [ \"${dryrun_mode}\" = 0 ]; then\n          lockdown_count=$((lockdown_count+1))\n          sh -c \"${command}\"\n        fi\n      else\n        if [ \"${use_sudo}\" = \"1\" ]; then\n          if [ \"${dryrun_mode}\" = 0 ]; then\n            lockdown_count=$((lockdown_count+1))\n            sudo sh -c \"${command}\"\n          fi\n        fi\n      fi\n    fi\n  else\n    verbose_message \"${command}\" \"fix\"\n  fi\n}\n\n# execute_restore\n#\n# Run restore command\n# Check we are running in restore mode run a command\n#.\n\nexecute_restore () {\n  command=\"${1}\"\n  message=\"${2}\"\n  privilege=\"${3}\"\n  if [ \"${audit_mode}\" = 2 ]; then\n    total_count=$((total_count+1))\n    if [ \"${message}\" ]; then\n      verbose_message \"${message}\" \"restore\"\n    fi\n    verbose_message \"${command}\" \"execute\"\n    if [ \"${privilege}\" = \"\" ]; then\n      if [ \"${dryrun_mode}\" = 0 ]; then\n        restore_count=$((restore_count+1))\n        sh -c \"${command}\"\n      fi\n    else\n      if [ \"$my_id\" = \"0\" ]; then\n        if [ \"${dryrun_mode}\" = 0 ]; then\n          restore_count=$((restore_count+1))\n          sh -c \"${command}\"\n        fi\n      else\n        if [ \"${use_sudo}\" = \"1\" ]; then\n          if [ \"${dryrun_mode}\" = 0 ]; then\n            restore_count=$((restore_count+1))\n            sudo sh -c \"${command}\"\n          fi\n        fi\n      fi\n    fi\n  else\n    verbose_message \"${command}\" \"fix\"\n  fi\n}\n\n#\n# backup_state\n#\n# Backup state to a log file for later restoration\n#.\n\nbackup_state () {\n  if [ \"${audit_mode}\" = 0 ]; then\n    backup_name=\"${1}\"\n    backup_value=\"${1}\"\n    backup_file=\"${work_dir}/${backup_name}.log\"\n    echo \"$backup_value\" > \"${backup_file}\"\n  fi\n}\n\n#\n# restore_state\n#\n# Restore state from a log file\n#.\n\nrestore_state () {\n  if [ \"${audit_mode}\" = 2 ]; then\n    restore_name=\"${1}\"\n    current_value=\"${2}\"\n    restore_command=\"${3}\"\n    restore_file=\"${restore_dir}/${restore_name}\"\n    if [ -f \"${restore_file}\" ]; then\n      restore_value=$( cat \"${restore_file}\" )\n      if [ \"${current_value}\" != \"${restore_value}\" ]; then\n        echo \"Executing: ${command}\"\n        eval \"${restore_command}\"\n      fi\n    fi\n  fi\n}\n\n# inc_secure\n#\n# Increment secure count\n#.\n\ninc_secure () {\n  if [ \"${audit_mode}\" != 2 ]; then\n    message=\"${1}\"\n    total_count=$((total_count+1))\n    secure_count=$((secure_count+1))\n    if [ \"${secure_count}\" = 1 ]; then\n      echo \"Secure:     ${message} [${secure_count} Pass]\"\n    else\n      echo \"Secure:     ${message} [${secure_count} Passes]\"\n    fi\n    output_csv=\"${output_csv},PASS:${message}\"\n  fi\n}\n\n# inc_insecure\n#\n# Increment insecure count\n#.\n\ninc_insecure () {\n  if [ \"${audit_mode}\" != 2 ]; then\n    message=\"${1}\"\n    total_count=$((total_count+1))\n    insecure_count=$((insecure_count+1))\n    if [ \"${insecure_count}\" = 1 ]; then\n      verbose_message \"${message} [${insecure_count} Warning]\" \"warn\"\n    else\n      verbose_message \"${message} [${insecure_count} Warnings]\" \"warn\"\n    fi\n    output_csv=\"${output_csv},FAIL:${message}\"\n  fi\n  insecure_temp=\"${insecure_count}\"\n}\n\n# Get the path the script starts from\n\nstart_path=$( pwd )\n\n# Get the version of the script from the script itself\n\nscript_version=$( cd \"${start_path}\" || exit ; grep '^# Version' < \"$0\"| awk '{print $3}' )\n\n# secure_baseline\n#\n# Establish a Secure Baseline\n# This uses the Solaris 10 svcadm baseline\n# Don't really need this so haven't coded anything for it yet\n#.\n\nsecure_baseline () {\n  :\n}\n\n\n# Handle command line arguments\n\naudit_mode=3\ndo_fs=0\naudit_select=0\nverbose_mode=0\nforce=0\ndo_select=0\ndo_aws=0\ndo_aws_rec=0\ndo_docker=0\nprint_funct=0\n\n# If given no command line arguments print usage information\n\nif [ \"$*\" = \"\" ]; then\n  print_help\n  exit\nfi\n\n# Check environment for cloud providers\n\ncase \"$*\" in\n  *azure*)\n    case \"$*\" in\n      *--checkenv*)\n        ;;\n      *)\n        check_azure_environment\n        ;;\n    esac\n    ;;\n  *aws*) \n    case \"$*\" in\n      *--checkenv*) \n        ;;\n      *)\n        check_aws_environment\n        ;;\n    esac\n    ;;\n  *)\n    if [ \"${arg_test}\" != \"1\" ]; then\n      if [ \"${id_check}\" != \"0\" ]; then\n        verbose_message \"$0 may need root\" \"warn\"\n      fi\n    fi\n    ;;\nesac\n\n# check_switch_value\n#\n# Check if a value is a switch or empty\n#.\n\ncheck_switch_value () {\n  param=\"${1}\"\n  value=\"${2}\"\n  if [ \"${value}\" = \"\" ]; then\n    warn_message \"No value provided for ${param}\"\n    exit\n  fi\n  case \"${value}\" in\n    -*)\n      warn_message \"Value provided for ${param} appears to be a switch [${value}]\"\n      exit\n      ;;\n  esac\n}\n\n# Parse arguments\n\nwhile test $# -gt 0\ndo\n  case $1 in\n    -1|--list)                      # switch - List changes/backups\n      check_switch_value \"${1}\" \"${2}\" \n      list=\"${2}\"\n      if [ -z \"${list}\" ]; then\n        print_changes\n        print_backups\n        shift\n        exit\n      else\n        case ${list} in\n          changes)\n            print_changes\n            ;;\n          backups)\n            print_backups \n            ;;\n          tests)\n            print_tests \"All\"\n            ;;\n        esac\n        shift 2\n      fi\n      exit\n      ;;\n    -2|--tests)                     # switch - Print tests\n      check_switch_value \"${1}\" \"${2}\" \n      tests=\"${2}\" \n      if [ -z \"${tests}\" ]; then\n        print_tests \"All\"\n      else\n        if [ \"${tests}\" = \"--verbose\" ]; then\n          verbose_mode=1\n          print_tests \"All\"\n        else\n          print_tests \"${tests}\"\n          shift 2\n        fi\n      fi\n      exit\n      ;;\n    -3|--printfunct)                # switch - Print function\n      print_funct=1\n      shift\n      ;;\n    -4|--dryrun)                    # switch - Run in dryrun mode\n      dryrun_mode=1\n      shift\n      ;;\n    -5|--commands)                  # switch - Display command that would be run\n      command_mode=1\n      shift\n      ;;\n    -6|--format)                    # switch - Outpt format/type\n      check_switch_value \"${1}\" \"${2}\" \n      output_type=\"${2}\"\n      shift 2\n      ;;\n    -7|--file)                      # switch - Output file\n      check_switch_value \"${1}\" \"${2}\" \n      output_file=\"${2}\"\n      shift 2\n      ;;\n    -8|--usesudo)                   # switch - Use sudo\n      use_sudo=1\n      shift\n      ;;\n    -9|--checkenv)                  # switch - Run environment check\n      check_switch_value \"${1}\" \"${2}\" \n      check=\"${2}\"\n      do_check=1\n      shift 2\n      ;;\n    -0|--force|--install)           # switch - Force action or install requirements\n      force=1\n      shift\n      ;;\n    -a|--audit)                     # switch - Run in audit mode (for Operating Systems - no changes made to system)\n      audit_mode=1\n      do_fs=0\n      shift\n      ;;\n    -A|--fullaudit)                 # switch - Run in audit mode and include filesystems (for Operating Systems - no changes made to system)\n      audit_mode=1\n      do_fs=1\n      shift\n      ;;\n    -b|--backups|--listbackups)     # switch - List backups\n      print_backups\n      shift\n      exit\n      ;;\n    -B|--basedir)                   # switch - Set base directory\n      check_switch_value \"${1}\" \"${2}\" \n      base_dir=\"${2}\"\n      shift 2\n      ;;\n    -c|--codename|--distro)         # switch -  Distro/Code name (used with docker/multipass)\n      check_switch_value \"${1}\" \"${2}\" \n      test_distro=\"${2}\"\n      shift 2\n      ;;\n    -C|--shell)                     # switch - Run docker-compose testing suite (drops to shell in order to do more testing)\n      do_compose=1\n      do_shell=1\n      shift\n      ;;\n    -d|--dockeraudit)               # switch - Run in audit mode (for Docker - no changes made to system)\n      check_switch_value \"${1}\" \"${2}\" \n      audit_mode=1\n      do_docker=1\n      module_name=\"${2}\"\n      shift 2\n      ;;\n    -D|--dockertests)               # switch - List all Docker functions available to selective mode\n      print_tests \"Docker\"\n      shift\n      exit\n      ;;  \n    -e|--host)                      # switch - Run in audit mode on external host (for Operating Systems - no changes made to system)\n      check_switch_value \"${1}\" \"${2}\" \n      do_remote=1\n      ext_host=\"${2}\"\n      shift 2\n      ;;\n    -E|--hash|--passwordhash)       # switch - Password hash\n      check_switch_value \"${1}\" \"${2}\" \n      password_hashing=\"${2}\"\n      shift 2\n      ;;\n    -f|--action)                    # switch - Action (e.g delete - used with multipass)\n      check_switch_value \"${1}\" \"${2}\" \n      action=\"${2}\"\n      case $action in\n        audit)\n          audit_mode=1\n          do_fs=0\n          ;;\n        fullaudit)\n          audit_mode=1\n          do_fs=1\n          ;;\n        lockdown)\n          audit_mode=0\n          do_fs=0\n          ;;\n        undo|restore)\n          audit_mode=2\n          ;;\n        osinfo|systeminfo)\n          check_os_release\n          exit\n          ;;\n      esac\n      shift 2\n      ;; \n    -F|--tempfile)                  # switch - Temporary file to use for operations\n      check_switch_value \"${1}\" \"${2}\" \n      temp_file=\"${2}\"\n      shift 2\n      ;;\n    -g|--giturl)                    # switch - Git URL for code to copy to container\n      check_switch_value \"${1}\" \"${2}\" \n      git_url=\"${2}\"\n      shift 2\n      ;;\n    -G|--wheelgroup)                # switch - Set wheel group\n      check_switch_value \"${1}\" \"${2}\" \n      wheel_group=\"${2}\"\n      shift 2\n      ;;\n    -h|--help)                      # switch - Display help\n      print_help\n      if [ \"${verbose_mode}\" = 1 ]; then\n       print_usage\n      fi \n      shift\n      exit 0\n      ;;\n    -H|--usage)                     # switch - Display usage\n      print_usage\n      shift\n      exit\n      ;;\n    -i|--anacron)                   # switch - Enable/Disable anacron\n      check_switch_value \"${1}\" \"${2}\" \n      anacron_enable=\"${2}\"\n      shift 2\n      ;;\n    -I|--type)                      # switch - Audit type\n      check_switch_value \"${1}\" \"${2}\" \n      audit_type=\"${2}\"\n      shift 2\n      ;;\n    -k|--kubeaudit)                 # switch - Run in audit mode (for Kubernetes - no changes made to system)\n      check_switch_value \"${1}\" \"${2}\" \n      audit_mode=1\n      do_kubernetes=1\n      module_name=\"${2}\"\n      shift 2\n      ;;\n    -K|--function|--test)           # switch - Do a specific function\n      check_switch_value \"${1}\" \"${2}\" \n      module_name=\"${2}\"\n      shift 2\n      ;;\n    -l|--lockdown)                  # switch - Run in lockdown mode (for Operating Systems - changes made to system)\n      audit_mode=0\n      do_fs=0\n      shift\n      ;;\n    -L|--fulllockdown|fulllock)     # switch - Run in lockdown mode (for Operating Systems - changes made to system)\n      audit_mode=0\n      do_fs=1\n      shift\n      ;;\n    -m|--machine|--vm)              # switch - Set virtualisation type\n      check_switch_value \"${1}\" \"${2}\" \n      vm_type=\"${2}\"\n      case $vm_type in\n        docker)\n          do_compose=1\n          do_shell=0\n          ;;\n        multipass)\n          do_multipass=1\n          do_shell=0\n          ;;\n      esac\n      shift 2\n      ;;\n    -M|--workdir)                   # switch - Set work directory\n      check_switch_value \"${1}\" \"${2}\" \n      work_dir=\"${2}\"\n      shift 2\n      ;;\n    -n|--ansible)                   # switch - Output ansible\n      ansible_mode=1\n      shift\n      ;;\n    -N|--nocat)                     # switch - Do output cat in score\n      no_cat=1\n      shift\n      ;;\n    -o|--os|--osver)                # switch - Set OS version\n      check_switch_value \"${1}\" \"${2}\" \n      test_os=\"${2}\"\n      shift 2\n      ;;\n    -O|--osinfo|--systeminfo)       # switch - Print OS/System information\n      check_os_release\n      shift\n      exit\n      ;;\n    -p|--previous)                  # switch - Print previous audit information\n      print_previous\n      shift\n      exit\n      ;;\n    -P|--sshsandbox|--sandbox)      # switch - Enable/Disabe SSH sandbox\n      check_switch_value \"${1}\" \"${2}\" \n      ssh_sandbox=\"${2}\"\n      shift 2\n      ;;\n    -q|--quiet|--nostrict)          # switch - Run in quiet mode\n      unset eu\n      shift\n      ;;\n    -Q|--debug)                     # switch - Run in debug mode\n      do_debug=1\n      set -ux\n      shift\n      ;;\n    -r|--awsregion|--region)        # switch - Set AWS region\n      check_switch_value \"${1}\" \"${2}\" \n      aws_region=\"${2}\"\n      shift 2\n      ;;\n    -R|--moduleinfo|--testinfo)     # switch - Print information about a module\n      check_switch_value \"${1}\" \"${2}\" \n      module=\"${2}\"\n      print_audit_info \"${module}\"\n      shift 2\n      exit\n      ;;\n    -s|--select|--check)            # switch - Run in selective mode (only run tests you want to)\n      check_switch_value \"${1}\" \"${2}\" \n      audit_mode=1\n      do_select=1\n      module_name=\"${2}\"\n      shift 2\n      ;;\n    -S|--unixtests|--unix)          # switch - List UNIX tests\n      print_tests \"UNIX\"\n      shift\n      exit\n      ;;\n    -t|--tag|--name)                # switch - Set docker tag\n      check_switch_value \"${1}\" \"${2}\" \n      test_tag=\"${2}\"\n      shift 2\n      ;;\n    -T|--tempdir)                   # switch - Set temp directoru\n      check_switch_value \"${1}\" \"${2}\" \n      temp_dir=\"${2}\"\n      shift 2\n      ;;\n    -u|--undo)                      # switch - Undo lockdown (for Operating Systems - changes made to system)\n      check_switch_value \"${1}\" \"${2}\" \n      audit_mode=2\n      restore_date=\"${2}\"\n      shift 2\n      ;;\n    -U|--dofiles)                   # switch - Include filesystems\n      do_fs=1\n      shift\n      ;;\n    -v|--verbose)                   # switch - Run in verbose mode\n      verbose_mode=1\n      shift\n      ;;\n    -V|--version)                   # switch - Print version\n      print_version\n      shift\n      exit\n      ;;\n    -w|--awsaudit)                  # switch - Run in audit mode (for AWS - no changes made to system)\n      check_switch_value \"${1}\" \"${2}\" \n      audit_mode=1\n      do_aws=1\n      module_name=\"${2}\"\n      shift 2\n      ;;\n    -W|--awstests|--aws)            # switch - List all AWS functions available to selective mode\n      print_tests \"AWS\"\n      shift\n      exit\n      ;;\n    -x|--awsrec)                    # switch - Run in recommendations mode (for AWS - no changes made to system)\n      check_switch_value \"${1}\" \"${2}\" \n      audit_mode=1\n      do_aws_rec=1\n      module_name=\"${2}\"\n      shift 2\n      ;;\n    -X|--strict)                    # switch - Run shellcheck against script\n      unset eu\n      shift\n      exit\n      ;;\n    -z)                             # switch - Run specified audit function in lockdown mode\n      check_switch_value \"${1}\" \"${2}\" \n      audit_mode=0\n      do_fs=0\n      do_select=1\n      module_name=\"${2}\"\n      shift 2\n      ;;\n    -Z|--changes|--listchanges)     # switch - List changes\n      print_changes\n      shift\n      exit\n      ;;\n    --tenant*)                      # switch - Azure tenant ID\n      check_switch_value \"${1}\" \"${2}\" \n      azure_tenant_id=\"${2}\"\n      shift 2\n      ;;\n    --allow-no-subscriptions)       # switch - Azure login allow no subscriptions\n      azure_allow_no_subscriptions=\"yes\"\n      shift\n      ;;\n    *)\n      print_help >&2\n      exit 1\n      ;;\n  esac\ndone\n\n# Run check if specified\n\nif [ \"${do_check}\" = 1 ]; then\n  case \"${check}\" in\n    *shell*)\n      check_shellcheck\n      ;;\n    *azure*)\n      check_azure_environment\n      ;;\n    *aws*)\n      check_aws_environment\n      ;;\n    *docker*)\n      check_docker\n      ;;\n    *multipass*)\n      check_multipass\n      ;;\n    *env*)\n      check_environment\n      ;;\n    *all*)\n      check_all\n      ;;\n    *)\n      verbose_message \"Unknown check: ${check}\" \"error\"\n      exit\n      ;;\n  esac\n  exit\nfi\n\n# Set Restore Directory if not set\n\nif [ \"${audit_mode}\" = 2 ]; then\n  restore_dir=\"${base_dir}/${restore_date}\"\nelse\n  if [ \"${restore_dir}\" = \"\" ]; then\n    restore_dir=\"${work_dir}\"\n  fi\nfi\n\n# If running in dry run mode say so\n\nif [ \"${dryrun_mode}\" = 1 ]; then\n  verbose_message \"Running in dryrun mode\" \"notice\"\nfi\n\n# If we are in lockdown mode do a check whether we are in force mode and whether to proceed\n\nif [ \"${audit_mode}\" = 0 ]; then\n  lockdown_warning\nfi\n\n# Get function name\n\nmodule_name=$(echo \"${module_name}\" | tr '[:upper:]' '[:lower:]' | sed \"s/ /_/g\" )\n\n# check arguments\n\nif [ \"${do_audit}\" = 1 ]; then\n  if [ \"${audit_type}\" = \"\" ]; then\n    audit_type=\"local\"\n  fi\nfi\n\n# Run script remotely \n\nif [ \"${do_remote}\" = 1 ]; then\n  echo \"Copying ${app_dir} to ${ext_host}:/tmp\"\n  scp -r \"${app_dir}\" \"${ext_host}\":/tmp\n  echo \"Executing lunar in audit mode (no changes will be made) on ${ext_host}\"\n  ssh \"${ext_host}\" \"sudo sh -c \\\"${temp_dir}/lunar.sh -a\\\"\"\n  exit\nfi\n\n# Check environment\n\ncheck_environment\n\n# Setup output file and directory\n\noutput_dir=$(dirname \"${output_file}\")\nif [ ! -d \"${output_dir}\" ]; then\n  mkdir -p \"${output_dir}\"\nfi\nif [ \"${output_type}\" = \"csv\" ] && [ \"${output_file}\" = \"\" ]; then\n  output_file=\"${csv_dir}/lunar_${os_hostname}_${date_suffix}.csv\"\nfi\nif [ \"${output_type}\" = \"csv\" ]; then\n  verbose_message \"${output_file}\" \"create\"\n  echo \"${output_csv}\" > \"${output_file}\"\nfi\n\n# Run in docker or multipass\n\nif [ \"${do_compose}\" = 1 ] || [ \"${do_multipass}\" = 1 ]; then\n  if [ \"${do_multipass}\" = 1 ]; then\n    get_ubuntu_codename \"${test_os}\"\n    test_os=\"${ubuntu_codename}\"\n    if [ \"${test_tag}\" = \"none\" ]; then\n      if [ ! \"${test_os}\" = \"none\" ]; then\n        test_tag=\"${pkg_suffix}-${test_os}\"\n      fi\n    fi\n  fi\n  if [ ! \"${test_os}\" = \"none\" ] && [ ! \"${test_tag}\" = \"none\" ]; then\n    if [ \"${do_compose}\" = 1 ]; then\n      d_test=$(command -v docker-compose )\n      if [ -n \"$d_test\" ]; then\n        if [ \"$do_shell\" = 0 ]; then\n          cd \"${app_dir}\" || exit ; export OS_NAME=\"${test_os}\" ; export OS_VERSION=\"${test_tag}\" ; docker-compose run test-audit\n        else\n          cd \"${app_dir}\" || exit ; export OS_NAME=\"${test_os}\" ; export OS_VERSION=\"${test_tag}\" ; docker-compose run test-shell\n        fi\n      else\n        verbose_message \"Command docker-compose not found\" \"warn\"\n        exit\n      fi\n    else\n      mpackage_test=$(command -v multipass | wc -l | sed \"s/ //g\" )\n      if [ \"${mpackage_test}\" = \"1\" ]; then\n        vm_test=$(multipass list | awk '{print $1}' | grep -c \"${test_tag}\" )\n        if [ \"${vm_test}\" = \"1\" ]; then\n          if [ \"${action}\" = \"delete\" ]; then\n            verbose_message \"Multipass VM \\\"${test_tag}\\\" with release \\\"${test_os}\\\"\" \"delete\"\n            multipass delete \"${test_tag}\"\n            multipass purge\n          else\n            if [ \"${do_shell}\" = 1 ] || [ \"${action}\" = \"shell\" ]; then\n              multipass shell \"${test_tag}\"\n            else\n              if [ \"${action}\" = \"refresh\" ]; then\n                multipass exec \"${test_tag}\" -- bash -c \"rm -rf lunar\"\n                multipass exec \"${test_tag}\" -- bash -c \"git clone ${git_url}\"\n              else\n                mp_command=\"sudo lunar/lunar.sh --action ${action}\"\n                if [ \"${do_debug}\" = \"1\" ]; then  \n                  mp_command=\"${mp_command} --debug\"\n                fi\n                if [ \"${do_select}\" = \"1\" ]; then  \n                  mp_command=\"${mp_command} --select ${module_name}\"\n                fi\n                multipass exec \"${test_tag}\" -- bash -c \"${mp_command}\"\n              fi\n            fi\n          fi\n        else \n          if [ \"${action}\" = \"delete\" ]; then\n            verbose_message \"Multipass VM \\\"${test_tag}\\\" does not exist\"\n            exit\n          else\n            if [ \"${action}\" = \"create\" ]; then\n              verbose_message \"Multipass VM \\\"${test_tag}\\\" with release \\\"${test_os}\\\"\" \"create\"\n              multipass launch \"${test_os}\" --name \"${test_tag}\"\n              multipass exec \"${test_tag}\" -- bash -c \"git clone ${git_url}\"\n              exit\n            fi\n          fi\n        fi\n      else\n        verbose_message \"Command multipass not found\" \"warn\"\n        exit\n      fi\n    fi\n  else\n    echo \"OS name or version not given\"\n    exit\n  fi\n  exit\nfi \n\nif [ \"${audit_mode}\" != 3 ]; then\n  echo \"\"\n  if [ \"${audit_mode}\" = 2 ]; then\n    verbose_message \"In Restore mode (changes will be made to system)\" \"run\"\n    verbose_message \"Restore date ${restore_date}\" \"set\"\n  fi\n  if [ \"${audit_mode}\" = 1 ]; then\n    verbose_message \"In audit mode (no changes will be made to system)\" \"run\"\n  fi\n  if [ \"${audit_mode}\" = 0 ]; then\n    verbose_message \"In lockdown mode (changes will be made to system)\" \"run\"\n  fi\n  if [ \"${do_fs}\" = 1 ]; then\n    verbose_message \"Filesystem checks will be done\" \"info\"\n  fi\n  echo \"\"\n  if [ \"${do_select}\" = 1 ]; then\n    verbose_message    \"Selecting ${module_name}\" \"audit\"\n    funct_audit_select \"${audit_mode}\" \"${module_name}\"\n  else\n    case \"${audit_type}\" in\n      Kubernetes)\n        verbose_message        \"Kubernetes\" \"audit\"\n        funct_audit_kubernetes \"${audit_mode}\"\n        exit\n        ;;\n      docker)\n        verbose_message    \"Docker\" \"audit\"\n        funct_audit_docker \"${audit_mode}\"\n        exit\n        ;;\n      awsrecommended)\n        verbose_message     \"AWS - Recommended Tests\" \"audit\"\n        funct_audit_aws_rec \"${audit_mode}\"\n        exit\n        ;;\n      aws)\n        verbose_message \"AWS\" \"audit\"\n        funct_audit_aws \"${audit_mode}\"\n        exit\n        ;;\n      local|system|os)\n        verbose_message    \"Operating System\" \"audit\"\n        funct_audit_system \"${audit_mode}\"\n        exit\n        ;;\n    esac\n  fi\n  exit\nfi\n"
  },
  {
    "path": "main/check_environment.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n# shellcheck disable=SC3046\n\n# check_aws_environment\n#\n# Check AWS CLI etc is installed\n#.\n\ncheck_aws_environment () {\n  print_function \"check_aws_environment\"\n  aws_bin=$( command -v aws 2> /dev/null )\n  if [ -f \"$aws_bin\" ]; then\n    aws_creds=\"$HOME/.aws/credentials\"\n    if [ -f \"${aws_creds}\" ]; then\n      if [ \"${os_name}\" = \"Darwin\" ]; then\n        base64_d=\"base64 -D\"\n      else\n        base64_d=\"base64 -d\"\n      fi\n    else\n      echo \"AWS credentials file does not exit\"\n      exit\n    fi\n  else\n    echo \"AWS CLI is not installed\"\n    exit\n  fi\n  if [ ! \"${aws_region}\" ]; then\n    aws_region=$( aws configure get region )\n  fi\n}\n\n# check_azure_environment\n#\n# Check Azure CLI etc is installed\n#.\n\ncheck_azure_environment () {\n  print_function \"check_azure_environment\"\n  azure_bin=$( command -v az 2> /dev/null )\n  if [ -f \"$azure_bin\" ]; then\n    for cli_ext in databricks bastion resource-graph application-insights nsp \\\n      elastic-san site-recovery amlfs dataprotection databox redisenterprise \\\n      datafactory; do\n      info_message \"Checking for Azure CLI extension \\\"${cli_ext}\\\"\"\n      command=\"az extension list --query \\\"[].name\\\" --output tsv | grep \\\"^${cli_ext}$\\\"\"\n      command_message  \"${command}\"\n      ext_test=$( eval \"${command}\" )\n      if [ -z \"${ext_test}\" ]; then\n        if [ \"${force}\" = \"1\" ]; then\n          info_message \"Installing Azure CLI extension \\\"${cli_ext}\\\"\"\n          command=\"az extension add --name \\\"${cli_ext}\\\" 2> /dev/null\"\n          command_message \"${command}\"\n          eval \"${command}\"\n        else\n          warn_message \"Azure \\\"${cli_ext}\\\" extension is not installed\"\n          exit\n        fi\n      fi\n    done\n  else\n    if [ \"${force}\" = \"1\" ]; then\n      if [ \"${os_name}\" = \"Darwin\" ]; then\n        brew_bin=$( command -v brew 2> /dev/null )\n        if [ -f \"$brew_bin\" ]; then\n          command=\"brew install azure-cli\"\n        else\n          command=\"pip install azure-cli\"\n        fi\n        command_message \"${command}\"\n        eval \"${command}\"\n      else\n        echo \"Azure CLI is not installed\"\n        exit\n      fi\n    else\n      echo \"Azure CLI is not installed\"\n      exit\n    fi\n  fi\n  command=\"az ad signed-in-user show --query displayName -o tsv\"\n  command_message \"${command}\"\n  azure_display_name=$( eval \"${command}\" )\n  if [ -z \"${azure_display_name}\" ]; then\n    if [ \"${azure_allow_no_subscriptions}\" = \"yes\" ]; then\n      az login --allow-no-subscriptions\n    else\n      if [ -n \"${azure_tenant_id}\" ]; then\n        az login --tenant \"${azure_tenant_id}\"\n      else\n        az login\n      fi\n    fi\n  else\n    verbose_message \"Logged in as ${azure_display_name}\" \"notice\"\n  fi\n}\n\n# check_environment\n#\n# Do some environment checks\n# Create base and temporary directory\n#.\n\ncheck_environment () {\n  print_function \"check_environment\"\n  check_os_release\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    verbose_message \"\" \"\"\n    info_message    \"Checking if node is managed\"\n    command=\"sudo pwpolicy -n -getglobalpolicy 2>&1 |cut -f1 -d:\"\n    command_message      \"${command}\"\n    managed_node=$( eval \"${command}\" )\n    if [ \"${managed_node}\" = \"Error\" ]; then\n      notice_message \"Node is not managed\"\n    else\n      notice_message \"Node is managed\"\n    fi\n    verbose_message  \"\" \"\"\n  fi\n  # Load functions from functions directory\n  if [ -d \"${functions_dir}\" ]; then\n    if [ \"${verbose_mode}\" = \"1\" ]; then\n      echo \"\"\n      echo \"Loading Functions\"\n      echo \"\"\n    fi\n    file_list=$( find \"${functions_dir}\" -name \"*.sh\" )\n    for file_name in ${file_list}; do\n      if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"AIX\" ] ||  [ \"${os_vendor}\" = \"Debian\" ] || [ \"${os_vendor}\" = \"Ubuntu\" ]; then\n        . \"${file_name}\"\n      else\n        source \"${file_name}\"\n      fi\n      if [ \"${verbose_mode}\" = \"1\" ]; then\n        verbose_message \"\\\"${file_name}\\\"\" \"load\"\n      fi\n    done\n  fi\n  # Load modules for modules directory\n  if [ -d \"${modules_dir}\" ]; then\n    if [ \"${verbose_mode}\" = \"1\" ]; then\n      echo \"\"\n      echo \"Loading Modules\"\n      echo \"\"\n    fi\n    file_list=$( find \"${modules_dir}\" -name \"*.sh\" )\n    for file_name in ${file_list}; do\n      if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"AIX\" ] || [ \"${os_vendor}\" = \"Debian\" ] || [ \"${os_vendor}\" = \"Ubuntu\" ]; then\n        . \"${file_name}\"\n      else\n        if [ \"${file_name}\" = \"modules/audit_ftp_users.sh\" ]; then\n          if [ \"${os_name}\" != \"VMkernel\" ]; then\n             source \"${file_name}\"\n          fi\n        else\n          source \"${file_name}\"\n        fi\n      fi\n      if [ \"${verbose_mode}\" = \"1\" ]; then\n        verbose_message \"\\\"${file_name}\\\"\" \"load\"\n      fi\n    done\n  fi\n  # Private modules for customers\n  if [ -d \"${private_dir}\" ]; then\n      echo \"\"\n      echo \"Loading Customised Modules\"\n      echo \"\"\n    if [ \"${verbose_mode}\" = \"1\" ]; then\n      echo \"\"\n    fi\n    file_list=$( find \"${private_dir}\" -name \"*.sh\" )\n    for file_name in ${file_list}; do\n      if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"AIX\" ] ||  [ \"${os_vendor}\" = \"Debian\" ] || [ \"${os_vendor}\" = \"Ubuntu\" ]; then\n        . \"${file_name}\"\n      else\n        source \"${file_name}\"\n      fi\n    done\n    if [ \"${verbose_mode}\" = \"1\" ]; then\n      echo \"Loading:   ${file_name}\"\n    fi\n  fi\n  if [ ! -d \"${base_dir}\" ]; then\n    mkdir -p  \"${base_dir}\"\n    chmod 700 \"${base_dir}\"\n  fi\n  if [ ! -d \"${temp_dir}\" ]; then\n    mkdir -p \"${temp_dir}\"\n  fi\n  if [ \"${audit_mode}\" = 0 ]; then\n    if [ ! -d \"${work_dir}\" ]; then\n      mkdir -p \"${work_dir}\"\n    fi\n  fi\n}\n"
  },
  {
    "path": "main/check_os_release.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# get_ubuntu_codename\n#\n# Get Ubuntu Codename \n#.\n\nget_ubuntu_codename () {\n  print_function \"get_ubuntu_codename\"\n  case \"${1}\" in\n    \"4.10\")  ubuntu_codename=\"warty\"    ;;\n    \"5.04\")  ubuntu_codename=\"hoary\"    ;;\n    \"5.10\")  ubuntu_codename=\"breezy\"   ;;\n    \"6.04\")  ubuntu_codename=\"dapper\"   ;;\n    \"6.10\")  ubuntu_codename=\"edgy\"     ;;\n    \"7.04\")  ubuntu_codename=\"feisty\"   ;;\n    \"7.10\")  ubuntu_codename=\"gutsy\"    ;;\n    \"8.04\")  ubuntu_codename=\"hardy\"    ;;\n    \"8.10\")  ubuntu_codename=\"intrepid\" ;;\n    \"9.04\")  ubuntu_codename=\"jaunty\"   ;;\n    \"9.10\")  ubuntu_codename=\"karmic\"   ;;\n    \"10.04\") ubuntu_codename=\"lucid\"    ;;\n    \"10.10\") ubuntu_codename=\"maverick\" ;;\n    \"11.04\") ubuntu_codename=\"natty\"    ;;\n    \"11.10\") ubuntu_codename=\"oneieric\" ;;\n    \"12.04\") ubuntu_codename=\"precise\"  ;;\n    \"12.10\") ubuntu_codename=\"quantal\"  ;;\n    \"13.04\") ubuntu_codename=\"raring\"   ;;\n    \"13.10\") ubuntu_codename=\"saucy\"    ;;\n    \"14.04\") ubuntu_codename=\"trusty\"   ;;\n    \"16.04\") ubuntu_codename=\"xenial\"   ;;\n    \"18.04\") ubuntu_codename=\"bionic\"   ;;\n    \"20.04\") ubuntu_codename=\"focal\"    ;;\n    \"22.04\") ubuntu_codename=\"jammy\"    ;;\n    \"24.04\") ubuntu_codename=\"noble\"    ;;\n    \"24.10\") ubuntu_codename=\"oracular\" ;;\n    \"25.04\") ubuntu_codename=\"plucky\"   ;;\n    \"25.10\") ubuntu_codename=\"questing\" ;;\n    \"26.04\") ubuntu_codename=\"resolute\" ;;\n    *)       ubuntu_codename=\"unknown\"  ;;\n  esac\n}\n\n# check_os_release\n#\n# Get OS release information\n#.\n\ncheck_os_release () {\n  print_function \"check_os_release\"\n  echo \"\"\n  echo \"# Local System Information:\"\n  echo \"\"\n  os_codename=\"\"\n  os_minorrev=\"\"\n  os_domain=\"unknown\"\n  os_platform=\"unknown\"\n  os_processor=\"unknown\"\n  os_vendor=\"unknown\"\n  os_release=\"unknown\"\n  os_version=\"unknown\"\n  os_update=\"unknown\"\n  os_codename=\"unknown\"\n  os_name=$( uname )\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    os_release=$( sw_vers |grep ProductVersion |awk '{print $2}' )\n    os_version=$( echo \"${os_release}\" |cut -f1 -d. )\n    os_update=$(  echo \"${os_release}\" |cut -f2 -d. )\n    os_vendor=\"Apple\"\n    if [ \"${os_update}\" = \"\" ]; then\n      os_update=$( sw_vers |grep ^BuildVersion |awk '{print $2}' )\n    fi\n  fi\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    linux_dist=$( lsb_release -i -s | tr '[:upper:]' '[:lower:]' )\n    os_release=$( lsb_release -r 2> /dev/null |awk '{print $2}' )\n    if [ -f \"/etc/redhat-release\" ]; then\n      os_version=$( awk '{print $3}' < /etc/redhat-release | cut -f1 -d. )\n      if [ \"${os_version}\" = \"Enterprise\" ]; then\n        os_version=$( awk '{print $7}' < /etc/redhat-release | cut -f1 -d. )\n        if [ \"${os_version}\" = \"Beta\" ]; then\n          os_version=$( awk '{print $6}' < /etc/redhat-release | cut -f1 -d. )\n          os_update=$(  awk '{print $6}' < /etc/redhat-release | cut -f2 -d. )\n        else\n          os_update=$(  awk '{print $7}' < /etc/redhat-release | cut -f2 -d. )\n        fi\n      else\n        if [ \"${os_version}\" = \"release\" ]; then\n          os_version=$( awk '{print $4}' < /etc/redhat-release | cut -f1 -d. )\n          os_update=$(  awk '{print $4}' < /etc/redhat-release | cut -f2 -d. )\n        else\n          os_update=$(  awk '{print $3}' < /etc/redhat-release | cut -f2 -d. )\n        fi\n      fi\n      os_vendor=$( awk '{print $1}' < /etc/redhat-release )\n      linux_dist=\"redhat\"\n    else\n      if [ -f \"/etc/debian_version\" ]; then\n        if [ -f \"/etc/lsb-release\" ]; then\n          os_version=$(  grep \"DISTRIB_RELEASE\" /etc/lsb-release | cut -f2 -d= | cut -f1 -d. )\n          os_update=$(   grep \"DISTRIB_RELEASE\" /etc/lsb-release | cut -f2 -d= | cut -f2 -d. )\n          os_vendor=$(   grep \"DISTRIB_ID\" /etc/lsb-release | cut -f2 -d= )\n          os_codename=$( grep \"DISTRIB_CODENAME\" /etc/lsb-release | cut -f2 -d= )\n          os_minorrev=$( lsb_release -d |awk '{print $3}' |cut -f3 -d. )\n        else\n          if [ -f \"/etc/debian_version\" ]; then\n            os_version=$( cut -f1 -d. /etc/debian_version )\n            os_update=$(  cut -f2 -d. /etc/debian_version )\n            os_vendor=\"Debian\"\n          else\n            os_version=$( lsb_release -r | awk '{print $2}' | cut -f1 -d. )\n            os_update=$(  lsb_release -r | awk '{print $2}' | cut -f2 -d. )\n            os_vendor=$(  lsb_release -i | awk '{print $3}' )\n          fi\n        fi\n        linux_dist=\"debian\"\n        os_test=$( echo \"${os_version}\" | grep \"[0-9]\" )\n        if [ -n \"$os_test\" ]; then \n          if [ ! -f \"/usr/sbin/sysv-rc-conf\" ] && [ \"${os_version}\" -lt 16 ]; then\n            echo \"Notice:    The sysv-rc-conf package may be required by this script but is not present\"\n          fi\n        fi\n        if [ ! -f \"/usr/bin/bc\" ]; then\n          use_expr=\"yes\"\n        fi\n        if [ ! -f \"/usr/bin/finger\" ]; then\n          use_finger=\"no\"\n        fi\n      else\n        if [ -f \"/etc/SuSE-release\" ]; then\n          os_version=$( grep '^VERSION' /etc/SuSe-release | awk '{print $3}' | cut -f1 -d. )\n          os_update=$(  grep '^VERSION' /etc/SuSe-release | awk '{print $3}' | cut -f2 -d. )\n          os_vendor=\"SuSE\"\n          linux_dist=\"suse\"\n        else\n          if [ -f \"/etc/arch-release\" ]; then\n            os_vendor=\"Arch\"\n            linux_dist=\"arch\"\n          else\n            if [ -f \"/etc/os-release\" ]; then\n              os_vendor=\"Amazon\"\n              os_version=$( grep 'CPE_NAME' /etc/os-release | cut -f2 -d: | cut -f1 -d. )\n              os_update=$(  grep 'CPE_NAME' /etc/os-release | cut -f2 -d: | cut -f2 -d. )\n            fi\n          fi\n        fi\n      fi\n    fi\n  fi\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    os_vendor=\"Oracle Solaris\"\n    os_version=$( uname -r |cut -f2 -d. )\n    if [ \"${os_version}\" = \"11\" ]; then\n      os_update=$( grep Solaris /etc/release | awk '{print $3}' | cut -f2 -d. )\n    fi\n    if [ \"${os_version}\" = \"10\" ]; then\n      os_update=$( grep Solaris /etc/release | awk '{print $5}' | cut -f2 -d_ | sed 's/[A-z]//g' )\n    fi\n    if [ \"${os_version}\" = \"9\" ]; then\n      os_update=$( grep Solaris /etc/release | awk '{print $4}' | cut -f2 -d_ | sed 's/[A-z]//g' )\n    fi\n  fi\n  if [ \"${os_name}\" = \"FreeBSD\" ]; then\n    os_version=$( uname -r | cut -f1 -d. )\n    os_update=$(  uname -r | cut -f2 -d. )\n    os_vendor=${os_name}\n  fi\n  if [ \"${os_name}\" = \"AIX\" ]; then\n    os_vendor=\"IBM\"\n    os_version=$( oslevel | cut -f1 -d. )\n    os_update=$(  oslevel | cut -f2 -d. )\n  fi\n  if [ \"${os_name}\" = \"VMkernel\" ]; then\n    os_version=$( uname -r )\n    os_update=$(  uname -v | awk '{print $4}' )\n    os_vendor=\"VMware\"\n  fi\n  if [ \"${os_name}\" != \"Linux\" ] && [ \"${os_name}\" != \"SunOS\" ] && [ \"${os_name}\" != \"Darwin\" ] && [ \"${os_name}\" != \"FreeBSD\" ] && [ \"${os_name}\" != \"AIX\" ] && [ \"${os_name}\" != \"VMkernel\" ]; then\n    echo \"OS not supported\"\n    exit\n  fi\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    os_platform=$( grep model < /proc/cpuinfo |tail -1 |cut -f2 -d: |sed \"s/^ //g\" )\n  else\n    if [ \"${os_name}\" = \"Darwin\" ]; then\n      os_platform=$( system_profiler SPHardwareDataType |grep Chip |cut -f2 -d: |sed \"s/^ //g\" )\n    else\n      os_platform=$( uname -p )\n    fi\n  fi\n  echo \"Hostname:   ${os_hostname}\"\n  os_domain=$( hostname -d )\n  if [ \"${os_domain}\" = \"\" ]; then\n    os_domain=$( hostname -f | cut -f2- -d. )\n  fi\n  if [ \"${os_domain}\" = \"\" ]; then\n    if [ -f \"/etc/domainname\" ]; then\n      os_domain=$( cat /etc/domainname )\n    fi\n  fi\n  if [ \"${os_domain}\" = \"\" ]; then\n    os_domain=\"unknown\"\n  fi\n  if [ \"${os_domain}\" = \"(none)\" ]; then\n    os_domain=\"none\"\n  fi\n  echo \"Domain:     ${os_domain}\"\n  os_machine=$( uname -m )\n  check_virtual_platform\n  if [ \"${os_platform}\" = \"\" ]; then\n    os_platform=$( uname -p )\n  fi\n  echo \"Processor:  ${os_platform}\"\n  echo \"Machine:    ${os_machine}\"\n  echo \"Vendor:     ${os_vendor}\"\n  echo \"Name:       ${os_name}\"\n  if [ ! \"${os_release}\" = \"\" ]; then\n    echo \"Release:    ${os_release}\"\n  fi\n  echo \"Version:    ${os_version}\"\n  echo \"Update:     ${os_update}\"\n  if [ ! \"${os_minorrev}\" = \"\" ]; then\n    echo \"Minor Rev:  ${os_minorrev}\"\n  fi\n  echo \"Codename:   ${os_codename}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${os_update}\" -lt 10 ]; then\n      long_update=\"0${os_update}\"\n    else\n      long_update=\"${os_update}\"\n    fi\n    long_os_version=\"${os_version}${long_update}\"\n    #echo \"XRelease:  ${long_os_version}\"\n  fi\n}\n"
  },
  {
    "path": "main/check_shellcheck.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# check_shellcheck\n# \n# Run shellcheck against script\n#.\n\ncheck_shellcheck () {\n  print_function \"check_shellcheck\"\n  bin_test=$( command -v shellcheck | grep -c shellcheck )\n  if [ ! \"$bin_test\" = \"0\" ]; then\n    echo \"Checking $0\"\n    shellcheck \"$0\"\n  fi\n  for dir_name in \"${functions_dir}\" \"${modules_dir}\"; do\n    if [ -d \"${dir_name}\" ]; then\n      file_list=$( find \"${dir_name}\" -name \"*.sh\" -type f -print )\n      for file_name in ${file_list}; do\n        if [ \"${verbose_mode}\" = \"1\" ]; then\n          verbose_message \"\\\"${file_name}\\\"\" \"load\"\n        fi\n        echo \"Checking ${file_name}\"\n        shellcheck \"${file_name}\"\n      done\n    fi\n  done\n}"
  },
  {
    "path": "main/get_info.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# get_service_name_from_port_no\n#\n# Get the service name from the port number\n#\n# Arguments:\n#   ${1} - Port number\n#\n# Returns:\n#   Service name\n\nget_service_name_from_port_no () {\n  port_no=\"${1}\"\n  print_function \"get_service_name_from_port_no\"\n  case \"${port_no}\" in\n    22)   echo \"SSH\"     ;;\n    53)   echo \"DNS\"     ;;\n    80)   echo \"HTTP\"    ;;\n    123)  echo \"NTP\"     ;;\n    161)  echo \"SNMP\"    ;;\n    389)  echo \"LDAP\"    ;;\n    443)  echo \"HTTPS\"   ;;\n    1900) echo \"SSDP\"    ;;\n    3389) echo \"RDP\"     ;;\n    *)    echo \"Unknown\" ;;\n  esac\n}\n\n\n# cidr_to_mask\n#\n# Convert CIDR to netmask\n#.\n\ncidr_to_mask () {\n  print_function \"cidr_to_mask\"\n  set -- $(( 5 - ($1 / 8) )) 255 255 255 255 $(( (255 << (8 - ($1 % 8))) & 255 )) 0 0 0\n  if [ \"${1}\" -gt 1 ]; then\n    shift \"${1}\" \n  else\n    shift\n  fi\n  echo \"${1-0}\".\"${2-0}\".\"${3-0}\".\"${4-0}\"\n}\n\n# mask_to_cidr\n#\n# Convert netmask to CIDR\n#.\n\nmask_to_cidr () {\n  print_function \"mask_to_cidr\"\n  x=\"${1##*255.}\"\n  set -- 0^^^128^192^224^240^248^252^254^ $(( (${#1} - ${#x})*2 )) \"${x%%.*}\"\n  x=${1%%\"${3}\"*}\n  echo $(( $2 + (${#x}/4) ))\n}\n"
  },
  {
    "path": "main/print_info.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# print_version\n#\n# Print version information\n#.\n\nprint_version () {\n  print_function \"print_version\"\n  echo \"${script_version}\"\n}\n\n# print_info\n#\n# Routing to parse script to print information like switch usage\n#.\n\nprint_info () {\n  info=\"${1}\"\n  print_function \"print_info\"\n  echo \"\"\n  echo \"Usage: $0 -${info}|--${info}\"\n  echo \"\"\n  if [ \"${info}\" = \"switch\" ]; then\n    echo \"${info}(es):\"\n    echo \"-----------\"\n  else\n    echo \"${info}(s):\"\n    echo \"----------\"\n  fi\n  while read -r line; do\n    test=$( echo \"${line}\" | grep \"# ${info}\" )\n    if [ \"${test}\" ]; then\n      switch=$( echo \"$line\" |cut -f1 -d# )\n      desc=$(   echo \"$line\" |cut -f2 -d# |sed \"s/ ${info} - //g\")\n      echo \"${switch}\"\n      echo \"  ${desc}\"\n    fi\n  done < \"$0\"\n  echo \"\"\n}\n\n# print_help\n#\n# If given a -h or no valid switch print usage information\n#.\n\nprint_help () {\n  print_function \"print_help\"\n  print_info     \"switch\"\n}\n\n# print_usage\n#\n# Print usage information\n# If given -H print some examples\n#.\n\nprint_usage () {\n  print_function \"print_usage\"\n  echo \"\"\n  echo \"Examples:\"\n  echo \"\"\n  echo \"Run AWS CLI audit\"\n  echo \"\"\n  echo \"$0 -w\"\n  echo \"\"\n  echo \"Run Docker audit\"\n  echo \"\"\n  echo \"$0 -d\"\n  echo \"\"\n  echo \"Run in Audit Mode (for Operating Systems)\"\n  echo \"\"\n  echo \"$0 -a\"\n  echo \"\"\n  echo \"Run in Audit Mode and provide more information (for Operating Systems)\"\n  echo \"\"\n  echo \"$0 -a -v\"\n  echo \"\"\n  echo \"Display Previous Backups:\"\n  echo \"\"\n  echo \"$0 -b\"\n  echo \"Previous Backups:\"\n  echo \"21_12_2012_19_45_05  21_12_2012_20_35_54  21_12_2012_21_57_25\"\n  echo \"\"\n  echo \"Restore from Previous Backup:\"\n  echo \"\"\n  echo \"$0 -u 21_12_2012_19_45_05\"\n  echo \"\"\n  echo \"List tests:\"\n  echo \"\"\n  echo \"$0 -S\"\n  echo \"\"\n  echo \"Only run shell based tests:\"\n  echo \"\"\n  echo \"$0 -s audit_shell_services\"\n  echo \"\"\n}\n\n# print_backups\n#\n# Print backups\n#.\n\nprint_backups () {\n  print_function \"print_backups\"\n  echo \"\"\n  echo \"Previous backups:\"\n  echo \"\"\n  if [ -d \"${base_dir}\" ]; then\n    find \"${base_dir}\" -maxdepth 1 -name \"[0-9]*\" -type d\n  fi\n}\n\n# print_tests\n#\n# Print Tests\n#. \n\nprint_tests () {\n  test_string=\"${1}\"\n  print_function \"print_tests\"\n  echo \"\"\n  if [ \"${test_string}\" = \"UNIX\" ]; then\n    grep_string=\"-v aws\"\n  else\n    grep_string=\"${test_string}\"\n  fi\n  echo \"${test_string} Security Tests:\"\n  echo \"\"\n  dir_list=$( find \"${modules_dir}\" -type f | grep -v \"full_\" | sed \"s/\\.sh//g\" ) \n  for dir_entry in ${dir_list} ; do\n    case ${test_string} in\n      AWS|aws)\n        module_name=$( echo \"${dir_entry}\" | grep \"aws\" )\n        ;;\n      *ocker*)\n        module_name=$( echo \"${dir_entry}\" | grep \"docker\" )\n        ;;\n      *ubernetes*|k8s)\n        module_name=$( echo \"${dir_entry}\" | grep \"kubernetes\" )\n        ;;\n      All|all)\n        module_name=\"${dir_entry}\"\n        ;;\n      *zure*)\n        module_name=$( basename \"${dir_entry}\" | grep \"azure_\" )\n        ;;\n      *)\n        module_name=$( echo \"${dir_entry}\" | grep \"${test_string}\" )\n        ;;\n    esac\n    if [ -n \"${module_name}\" ]; then\n      if [ \"${verbose_mode}\" -eq 1 ]; then\n        print_audit_info \"${module_name}\"\n      else\n        echo \"${module_name}\"\n      fi\n    fi\n  done\n  echo \"\"\n}\n\n# print_function\n#\n# Print fuction name\n#.\n\nprint_function() {\n  funct_name=\"${1}\"\n  if [ \"${verbose_mode}\" -eq 1 ]; then\n    echo \"Function:   ${funct_name}\"\n  fi\n}\n\n# print_changes\n#\n# Do a diff between previous file (saved) and existing file\n#.\n\nprint_changes () {\n  print_function \"print_changes\"\n  if [ -f \"${base_dir}\" ]; then\n    echo \"\"\n    echo \"Printing changes:\"\n    echo \"\"\n    file_list=$( find \"${base_dir}\" -type f -print )\n    for saved_file in ${file_list}; do\n      check_file=$( echo \"${saved_file}\" | cut -f 5- -d/ )\n      top_dir=$(    echo \"${saved_file}\" | cut -f 1-4 -d/ )\n      echo \"Directory: \\\"${top_dir}\\\"\"\n      log_test=$(   echo \"${check_file}\" |grep \"log$\" )\n      if [ -n \"${log_test}\" ]; then\n        echo \"Original system parameters:\"\n        sed  \"s/,/ /g\" < \"${saved_file}\"\n      else\n        echo \"Changes to \\\"/${check_file}\\\":\"\n        diff \"${saved_file}\" \"/${check_file}\"\n      fi\n    done\n  else\n    echo \"No changes made recently\"\n  fi\n}\n\n# print_previous\n#\n# Print previous changes\n#.\n\nprint_previous () {\n  print_function \"print_previous\"\n  if [ -d \"${base_dir}\" ]; then\n    echo \"\"\n    echo \"Printing previous settings:\"\n    echo \"\"\n    if [ -d \"${base_dir}\" ]; then\n      find \"${base_dir}\" -type f -print -exec cat -n {} \\;\n    fi\n  fi\n}\n\n# handle_output\n#\n# Handle output\n#.\n\nhandle_output () {\n  text=\"${1}\"\n  echo \"${1}\"\n}\n\n# checking_message\n#\n# Checking message\n#.\n\nchecking_message () {\n  verbose_message \"${1}\" \"check\"\n}\n\ncheck_message () {\n  verbose_message \"${1}\" \"check\"\n}   \n\n# setting_message\n#\n# Setting message\n#.\n\nsetting_message () {\n  verbose_message \"${1}\" \"set\"\n}\n\nset_message () {\n  verbose_message \"${1}\" \"set\"\n}\n\n# command_message\n#\n# Command message\n#.\n\ncommand_message () {\n  if [ \"${command_mode}\" = 1 ]; then\n    verbose_message \"${1}\" \"exec\"\n  fi\n}\n\n# na_message\n#\n# Not Applicable message\n#.\n\nna_message () {\n  if [ \"${command_mode}\" = 1 ]; then\n    verbose_message \"${1}\" \"na\"\n  fi\n}\n\n# notice_message\n#\n# Notice message\n#.\n\nnotice_message () {\n  if [ \"${command_mode}\" = 1 ]; then\n    verbose_message \"${1}\" \"notice\"\n  fi\n}\n\n# fix_message\n#\n# Fix message\n#.\n\nfix_message () {\n  verbose_message \"${1}\" \"fix\"\n}\n\n# restore_message\n#\n# Restore message\n#.\n\nrestore_message () {\n  verbose_message \"${1}\" \"restore\"\n}\n\n# insecure_message\n#\n# Insecure message\n#.\n\ninsecure_message () {\n  verbose_message \"${1}\" \"fix\"\n}\n\n# backup_message\n#\n# Backup message\n#.\n\nbackup_message () {\n  verbose_message \"${1}\" \"backup\"\n}\n\n# install_message\n#\n# Install message\n#.\n\ninstall_message () {\n  verbose_message \"${1}\" \"install\"\n}\n\n# remove_message\n#\n# Remove message\n#.\n\nremove_message () {\n  verbose_message \"${1}\" \"remove\"\n}\n\n# save_message\n#\n# Save message\n#.\n\nsave_message () {\n  verbose_message \"${1}\" \"save\"\n}\n\n# print_audit_info\n#\n# This function searches the script for the information associated\n# with a function.\n# It finds the line starting with # function_name\n# then reads until it finds a #.\n#.\n\nprint_audit_info () {\n  module=\"${1}\"\n  print_function \"print_audit_info\"\n  comment_text=\"0\"\n  dir_name=$( pwd )\n  check=$( echo \"${module}\" | grep \"audit\" )\n  if [ -z \"${check}\" ]; then\n    module=\"audit_${module}\" \n  fi\n  file_name=\"${dir_name}/modules/${module}.sh\"\n  if [ -f \"${file_name}\" ] ; then\n    verbose_message \"# Module: ${module}\"\n    while read -r line ; do\n      if [ \"${line}\" = \"# ${module}\" ]; then\n        comment_text=1\n      else\n        if [ \"${comment_text}\" = 1 ]; then\n          if [ \"${line}\" = \"#.\" ]; then\n            verbose_message \"\"\n            comment_text=0\n          fi\n          if [ \"${comment_text}\" = 1 ]; then\n            verbose_message \"${line}\"\n          fi\n        fi\n      fi\n    done < \"${file_name}\"\n  fi\n}\n\n# print_results\n#\n# Print Results\n#.\n\nprint_results () {\n  print_function \"print_results\"\n  echo \"\"\n  if [ \"${reboot_required}\" = 1 ]; then\n    reboot_required=\"Required\"\n  else\n    reboot_required=\"Not Required\"\n  fi\n  percent=$( awk \"BEGIN { pc=100*${secure_count}/${total_count}; i=int(pc); print (pc-i<0.5)?i:i+1 }\" )\n  if [ \"${no_cat}\" = \"1\" ]; then\n    echo \"Tests:      ${total_count}\"\n    case \"${audit_mode}\" in\n      2)\n        echo \"Restores:   ${restore_count}\"\n        ;;\n      0)\n        echo \"Lockdowns:  ${lockdown_count}\"\n        ;;\n      *)\n        echo \"Passes:     ${secure_count}\"\n        echo \"Warnings:   ${insecure_count}\"\n        echo \"Score:      ${percent}%\"\n        ;;\n    esac\n    echo \"Reboot:     ${reboot_required}\"\n  else\n    echo \" \\    /\\    Tests:      ${total_count}\"\n    case \"${audit_mode}\" in\n      2)\n        echo \"  )  ( ')   Restores:   ${restore_count}\"\n        echo \" (  /  )    \"\n        ;;\n      0)\n        echo \"  )  ( ')   Lockdowns:  ${lockdown_count}\"\n        echo \" (  /  )    \"\n        ;;\n      *)\n        echo \"  )  ( ')   Passes:     ${secure_count}\"\n        echo \" (  /  )    Warnings:   ${insecure_count}\"\n        echo \"  \\(__)|    Score:      ${percent}%\"\n        ;;\n    esac\n    echo \"            Reboot:     ${reboot_required}\"\n  fi\n  if [ \"${audit_mode}\" = 0 ]; then\n    echo \"\"\n    echo \"Backup:     ${work_dir}\"\n    if [ ! \"${module_name}\" = \"\" ]; then\n      echo \"Restore:    $0 -s ${module_name} -u ${date_suffix} -8\"\n    else\n      echo \"Restore:    $0 -u ${date_suffix} -8\"\n    fi\n  fi\n  if [ \"${output_type}\" = \"csv\" ]; then\n    echo \"\"\n    echo \"CSV File:   ${output_file}\"\n  fi\n  echo \"\"\n}\n"
  },
  {
    "path": "modules/accounting/audit_filesystem_partitions.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_filesystem_partitions\n#\n# Check filesystems are on separate partitions\n#\n# Refer to Section(s) 1.1.1,5,7,8,9   Page(s) 14-21           CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 1.1.1,5,7,8,9   Page(s) 15-22           CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 1.1.1,5,7,8,9   Page(s) 18-26           CIS RHEL 6 Benchmark v1.0.0\n# Refer to Section(s) 1.1.2,6-7       Page(s) 26-7,31-2       CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 1.1.2.6-7       Page(s) 27-8,32-3       CIS Ubuntu LTS 16.04 Benchmark v1.0.0\n# Refer to Section(s) 1.1.2.[1-7].1   Page(s) 76-8,87-8,96-8,\n#                                             104-6,112-3,\n#                                             121-2,130-1     CIS Ubuntu LTS 24.04 Benchmark v1.0.0\n# Refer to Section(s) 2.1,5,7,8,9     Page(s) 14-21           CIS SLES 11 Benchmark v1.2.0\n# Refer to Section(s) 2.1,5,7,8,9     Page(s) 14-21           CIS SLES 11 Benchmark v1.2.0\n# Refer to Section(s) 1.1.2,6-7,11-13 Page(s) 24-6,35-7       CIS Amazon Linux Benchmark v2.0.0\n#.\n\naudit_filesystem_partitions () {\n  print_function \"audit_filesystem_partitions\"\n  string=\"Filesystem Partitions\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    for filesystem in /tmp /var /var/log /var/log/audit /home /dev/shm /var/tmp; do\n      mount_test=$( df | awk '{print $6}' | grep -c \"^${filesystem}$\" | sed \"s/ //g\" )\n      if [ ! \"${mount_test}\" = \"0\" ]; then\n        inc_secure   \"Filesystem \\\"${filesystem}\\\" is a separate filesystem\"\n\t    else\n        inc_insecure \"Filesystem \\\"${filesystem}\\\" is not a separate filesystem\"\n      fi\n    done\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/accounting/audit_kernel_accounting.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_kernel_accounting\n#\n# Check Kernel Accounting\n#\n# Refer to Section(s) 3.3     Page(s) 38-39           CIS Apple OS X 10.8  Benchmark v1.0.0\n# Refer to Section(s) 3.3     Page(s) 92              CIS Apple OS X 10.12 Benchmark v1.0.0\n# Refer to Section(s) 4.9     Page(s) 73-5            CIS Solaris 10 Benchmark v5.1.0\n# Refer to Section(s) 3.2,4-5 Page(s) 274-5,8-9,280-3 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_kernel_accounting () {\n  print_function \"audit_kernel_accounting\"\n  string=\"Kernel and Process Accounting\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Darwin\" ]; then\n    check_file=\"/etc/system\"\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      if [ \"${os_version}\" = \"10\" ]; then\n        if [ -f \"${check_file}\" ]; then\n          check_message \"Kernel and Process Accounting\"\n          command=\"grep -v \\\"^\\\\*\\\" \\\"${check_file}\\\" | grep \\\"c2audit:audit_load\\\"\"\n          command_message   \"${command}\"\n          check_acc=$( eval \"${command}\" )\n          if [ -z \"${check_acc}\" ]; then\n            check_file_value  \"is\" \"${check_file}\" \"c2audit\"  \"colon\" \"audit_load\"  \"star\"\n            if [ \"${audit_mode}\" = 0 ]; then\n              log_file=\"${work_dir}/bsmconv.log\"\n              echo \"y\" >> \"${log_file}\"\n              echo \"y\" | /etc/security/bsmconv\n            fi\n          fi\n          if [ \"${audit_mode}\" = 2 ]; then\n            restore_file=\"${restore_dir}/bsmconv.log\"\n            if [ -f \"${restore_file}\" ]; then\n              echo \"y\" | /etc/security/bsmunconv\n            fi\n          fi\n          check_file_value \"is\" \"/etc/security/audit_control\" \"flags\"         \"colon\" \"lo,ad,cc\" \"hash\"\n          check_file_value \"is\" \"/etc/security/audit_control\" \"naflags\"       \"colon\" \"lo,ad,ex\" \"hash\"\n          check_file_value \"is\" \"/etc/security/audit_control\" \"minfree\"       \"colon\"  \"20\"      \"hash\"\n          check_file_value \"is\" \"/etc/security/audit_user\"    \"root\"          \"colon\" \"lo,ad:no\" \"hash\"\n        fi\n      fi\n    else\n      check_file_perms \"/etc/security/audit_control\"          \"0750\"  \"root\"  \"${wheel_group}\"\n      check_file_perms \"/var/audit\"                           \"0750\"  \"root\"  \"${wheel_group}\"\n      check_file_value \"is\" \"/etc/security/audit_control\"     \"flags\" \"colon\" \"lo,ad,fd,fm,-all\"  \"hash\"\n      if [ \"${os_version}\" -ge 14 ]; then\n        check_file_value \"is\" \"/etc/security/audit_control\"   \"expire-after\"  \"colon\" \"60d\"       \"hash\"\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/accounting/audit_process_accounting.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_process_accounting\n#\n# Refer to Section(s) 10.1 Page(s) 137-8 CIS Solaris 10 Benchmark v1.1.0\n#.\n\naudit_process_accounting () {\n  print_function \"audit_process_accounting\"\n  string=\"Process Accounting\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    check_file=\"/etc/rc3.d/S99acct\"\n    init_file=\"/etc/init.d/acct\"\n    log_file=\"${work_dir}/acct.log\"\n    if [ ! -f \"${check_file}\" ]; then\n      if [ \"${audit_mode}\" = 1 ]; then\n        inc_insecure \"Process accounting not enabled\"\n      fi\n      if [ \"${audit_mode}\" = 0 ]; then\n        set_message  \"Process accounting to enabled\"\n        echo  \"disabled\" > \"${log_file}\"\n        ln -s \"${init_file}\" \"${check_file}\"\n        notice_message \"Starting Process accounting\"\n        eval  \"${init_file} start > /dev/null 2>&1\"\n      fi\n    else\n      if [ \"${audit_mode}\" = 1 ]; then\n        inc_secure \"Process accounting not enabled\"\n      fi\n      if [ \"${audit_mode}\" = 2 ]; then\n        log_file=\"${restore_dir}/acct.log\"\n        if [ -f \"${log_file}\" ]; then\n          if [ -f \"${check_file}\" ]; then\n            rm \"${check_file}\"\n          fi\n          restore_message \"Process accounting to disabled\"\n          notice_message  \"Stoping Process accounting\"\n          eval \"${init_file} stop > /dev/null 2>&1\"\n        fi\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/accounting/audit_sar_accounting.sh",
    "content": "#!/bin/sh -\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_sar_accounting\n#\n# Check system accounting\n#\n# Refer to Section(s) 2.12.8 Page(s) 212-3 CIS AIX Benchmark v1.1.0\n# Refer to Section(s) 4.8    Page(s) 71-72 CIS Oracle Solaris 10 Benchmark v5.1.0\n#.\n\naudit_sar_accounting () {\n  print_function \"audit_sar_accounting\"\n  string=\"SAR Accounting\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"AIX\" ]; then\n    if [ \"${my_id}\" != \"0\" ] && [ \"${use_sudo}\" = \"0\" ]; then\n      notice_message      \"Requires sudo to check\"\n      return\n    fi\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      check_append_file   \"/var/spool/cron/crontabs/adm\" \"0,20,40 * * * * /usr/lib/sa/sa1\"                         \"hash\"\n      check_append_file   \"/var/spool/cron/crontabs/adm\" \"45 23 * * * /usr/lib/sa/sa2 -s 0:00 -e 23:59 -i 1200 -A\" \"hash\"\n    fi\n    if [ \"${os_name}\" = \"AIX\" ]; then\n      package_name=\"bos.acct\"\n      check_lslpp ${package_name}\n      if [ \"${lslpp_check}\" = \"${package_name}\" ]; then\n        check_append_file \"/var/spool/cron/crontabs/adm\" \"#=================================================================\" \"hash\"\n        check_append_file \"/var/spool/cron/crontabs/adm\" \"#      SYSTEM ACTIVITY REPORTS\"                                     \"hash\"\n        check_append_file \"/var/spool/cron/crontabs/adm\" \"# 8am-5pm activity reports every 20 mins during weekdays.\"          \"hash\"\n        check_append_file \"/var/spool/cron/crontabs/adm\" \"# activity reports every an hour on Saturday and Sunday.\"           \"hash\"\n        check_append_file \"/var/spool/cron/crontabs/adm\" \"# 6pm-7am activity reports every an hour during weekdays.\"          \"hash\"\n        check_append_file \"/var/spool/cron/crontabs/adm\" \"# Daily summary prepared at 18:05.\"                                 \"hash\"\n        check_append_file \"/var/spool/cron/crontabs/adm\" \"#=================================================================\" \"hash\"\n        check_append_file \"/var/spool/cron/crontabs/adm\" \"0 8-17 * * 1-5 /usr/lib/sa/sa1 1200 3 &\"                            \"hash\"\n        check_append_file \"/var/spool/cron/crontabs/adm\" \"0 * * * 0,6 /usr/lib/sa/sa1 &\"                                      \"hash\"\n        check_append_file \"/var/spool/cron/crontabs/adm\" \"0 18-7 * * 1-5 /usr/lib/sa/sa1 &\"                                   \"hash\"\n        check_append_file \"/var/spool/cron/crontabs/adm\" \"5 18 * * 1-5 /usr/lib/sa/sa2 -s 8:00 -e 18:01 -i 3600 -ubcwyaqvm &\" \"hash\"\n      else\n        fix_message       \"Sar accounting requires \\\"${package_name}\\\" to be installed\"\n      fi\n    fi\n    check_dir=\"/var/adm/sa\"\n    if [ ! -d \"${check_dir}\" ]; then\n      mkdir -p \"${check_dir}\"\n    fi\n    check_file_perms \"${check_dir}\" \"0750\" \"adm\" \"adm\"\n  else\n    na_message \"${string}\"\n  fi\n}\n\n"
  },
  {
    "path": "modules/accounting/audit_system_accounting.sh",
    "content": "#!/bin/sh\n\n# -> Needs fixing\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2046\n# shellcheck disable=SC2154\n\n# audit_system_accounting\n#\n# Check system accounting\n#\n# Refer to Section(s) 4.2.1.1-18            Page(s) 77-96         CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 5.3.1.1-21            Page(s) 113-136       CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 5.2.1.1-18            Page(s) 86-9,100-120  CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 4.1.1.1-3,4.2.1-18    Page(s) 164-191       CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 8.1.1.1-18            Page(s) 86-106        CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 5.2                   Page(s) 18            CIS FreeBSD Benchmark v1.0.5\n# Refer to Section(s) 2.11.4-5,17           Page(s) 194-5,202     CIS AIX Benchmark v1.1.0\n# Refer to Section(s) 4.8                   Page(s) 71-2          CIS Solaris 10 Benchmark v5.1.0\n# Refer to Section(s) 4.1.1.1-3,4.2.1-18    Page(s) 148-75        CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 4.1.1.1-3,4.1.2-18    Page(s) 159-86        CIS Ubuntu 16.04 Benchmark v1.0.0\n# Refer to Section(s) 4.1.2.1-3-4.1.3.29    Page(s) 440-527       CIS Ubuntu 22.04 Benchmark v1.0.0\n# Refer to Section(s) 4.1.2.1-3-4.1.3.29    Page(s) 440-527       CIS Ubuntu 22.04 Benchmark v1.0.0\n# Refer to Section(s) 6.2.2.1-4,6.2.3.1-21  Page(s) 807-97        CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_system_accounting () {\n  print_function \"audit_system_accounting\"\n  string=\"System Accounting\"\n  check_message  \"${string}\"\n  max_log_file=\"8\"\n  max_log_file_action=\"keep_logs\"\n  disk_full_action=\"single\"\n  disk_error_action=\"single\"\n  space_left_action=\"single\"\n  admin_space_left_action=\"single\"\n  if [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"FreeBSD\" ] || [ \"${os_name}\" = \"AIX\" ]; then\n    if [ \"${os_name}\" = \"AIX\" ]; then\n      check_file_perms  \"/var/adm/sa\"         \"0755\" \"adm\"  \"adm\"\n      check_file_perms  \"/etc/security/audit\" \"0750\" \"root\" \"audit\"\n      check_file_perms  \"/audit\"              \"0750\" \"root\" \"audit\"\n    fi\n    if [ \"${os_name}\" = \"FreeBSD\" ]; then\n      check_file_exists \"/var/account/acct\" \"yes\"\n      check_file_value  \"is\" \"/etc/rc.conf\" \"accounting_enable\" \"eq\" \"YES\" \"hash\"\n    fi\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      check_append_file   \"/etc/audit/audit.rules\" \"-w /var/log/sudo.log -p wa -k actions\" \"hash\"\n      check_linux_package \"install\" \"sysstat\"\n      log_file=\"sysstat.log\"\n      if [ \"${os_vendor}\" = \"Debian\" ] || [ \"${os_vendor}\" = \"Ubuntu\" ]; then\n        check_file_value \"is\" \"/etc/default/sysstat\" \"ENABLED\" \"eq\" \"true\" \"hash\"\n      fi\n      if [ \"${package_name}\" != \"sysstat\" ]; then\n        if [ \"${audit_mode}\" = 1 ]; then\n          inc_insecure \"System accounting not enabled\"\n          if [ \"${os_vendor}\" = \"Red\" ] || [ \"${os_vendor}\" = \"CentOS\" ]; then\n            fix_message \"yum -y install ${package_check}\"\n          fi\n          if [ \"${os_vendor}\" = \"SuSE\" ]; then\n            fix_message \"zypper install ${package_check}\"\n          fi\n          if [ \"${os_vendor}\" = \"Debian\" ] || [ \"${os_vendor}\" = \"Ubuntu\" ]; then\n            fix_message \"apt-get install ${package_check}\"\n          fi\n        fi\n        if [ \"${audit_mode}\" = 0 ]; then\n          set_message \"System Accounting to enabled\"\n          log_file=\"${work_dir}/${log_file}\"\n          echo \"Installed sysstat\" >> \"${log_file}\"\n          check_linux_package \"install\" \"sysstat\"\n        fi\n      else\n        if [ \"${audit_mode}\" = 1 ]; then\n          \n          inc_secure \"System accounting enabled\"\n        fi\n        if [ \"${audit_mode}\" = 2 ]; then\n          restore_file=\"${restore_dir}/${log_file}\"\n          check_linux_package \"restore\" \"sysstat\" \"${restore_file}\"\n        fi\n      fi\n      check_file=\"/etc/audit/rules.d/audit.rules\"\n      # Set failure mode to syslog notice\n      check_append_file   \"${check_file}\" \"-f 1\" \"hash\"\n      # Things that could affect time\n      check_append_file   \"${check_file}\" \"\"     \"hash\"\n      # Things that modify time\n      check_append_file   \"${check_file}\" \"-a always,exit -F arch=b32 -S adjtimex,settimeofday,clock_settime,stime -k time-change\" \"hash\"\n      if [ \"${os_platform}\" = \"x86_64\" ]; then\n        check_append_file \"${check_file}\" \"-a always,exit -F arch=b64 -S adjtimex,settimeofday,clock_settime -k time-change\"       \"hash\"\n      fi\n      check_append_file   \"${check_file}\" \"-w /etc/localtime -p wa -k time-change\"                                   \"hash\"\n      # Things that affect identity\n      check_append_file   \"${check_file}\" \"-w /etc/group -p wa -k identity\"                                          \"hash\"\n      check_append_file   \"${check_file}\" \"-w /etc/passwd -p wa -k identity\"                                         \"hash\"\n      check_append_file   \"${check_file}\" \"-w /etc/gshadow -p wa -k identity\"                                        \"hash\"\n      check_append_file   \"${check_file}\" \"-w /etc/shadow -p wa -k identity\"                                         \"hash\"\n      check_append_file   \"${check_file}\" \"-w /etc/security/opasswd -p wa -k identity\"                               \"hash\"\n      # Things that could affect system locale\n      check_append_file   \"${check_file}\" \"-a exit,always -F arch=b32 -S sethostname,setdomainname -k system-locale\" \"hash\"\n      if [ \"${os_platform}\" = \"x86_64\" ]; then\n        check_append_file \"${check_file}\" \"-a exit,always -F arch=b64 -S sethostname,setdomainname -k system-locale\" \"hash\"\n      fi\n      check_append_file   \"${check_file}\" \"-w /etc/issue -p wa -k system-locale\"                                     \"hash\"\n      check_append_file   \"${check_file}\" \"-w /etc/issue.net -p wa -k system-locale\"                                 \"hash\"\n      check_append_file   \"${check_file}\" \"-w /etc/hosts -p wa -k system-locale\"                                     \"hash\"\n      check_append_file   \"${check_file}\" \"-w /etc/sysconfig/network -p wa -k system-locale\"                         \"hash\"\n      # Things that could affect MAC policy\n      check_append_file   \"${check_file}\" \"-w /etc/selinux/ -p wa -k MAC-policy\"                                     \"hash\"\n      # Things that could affect apparmor\n      check_append_file   \"${check_file}\" \"-w /etc/apparmor/ -p wa -k MAC-policy\"                                    \"hash\"\n      check_append_file   \"${check_file}\" \"-w /etc/apparmor.d/ -p wa -k MAC-policy\"                                  \"hash\"\n      # Things that could affect logins\n      check_append_file   \"${check_file}\" \"-w /var/log/faillog -p wa -k logins\"                                      \"hash\"\n      check_append_file   \"${check_file}\" \"-w /var/log/lastlog -p wa -k logins\"                                      \"hash\"\n      if [ \"${os_vendor}\" = \"Ubuntu\" ] && [ \"${os_version}\" -ge 16 ]; then\n        check_append_file \"${check_file}\" \"-w /var/run/faillock -p wa -k logins\"                                     \"hash\"\n      fi\n      # Process and session initiation (unsuccessful and successful)\n      check_append_file   \"${check_file}\" \"-w /var/run/utmp -p wa -k session\"                                        \"hash\"\n      check_append_file   \"${check_file}\" \"-w /var/log/btmp -p wa -k session\"                                        \"hash\"\n      check_append_file   \"${check_file}\" \"-w /var/log/wtmp -p wa -k session\"                                        \"hash\"\n      # Record chchon command usage\n      check_append_file   \"${check_file}\" \"-a always,exit -F path=/usr/bin/chcon -F perm=x -F auid>=1000 -F auid!=unset -k perm_chng\"                         \"hash\"\n      # Discretionary access control permission modification (unsuccessful and successful use of chown/chmod)\n      check_append_file   \"${check_file}\" \"-a always,exit -S all -F path=/usr/bin/chcon -F perm=x -F auid>=1000 -F auid!=-1 -F key=perm_chng\"                 \"hash\"\n      check_append_file   \"${check_file}\" \"-a always,exit -F path=/usr/bin/setfacl -F perm=x -F auid>=1000 -F auid!=unset -k perm_chng\"                       \"hash\"\n      check_append_file   \"${check_file}\" \"-a always,exit -F arch=b32 -C euid!=uid -F auid!=unset -S execve -k user_emulation\"                                \"hash\"\n      if [ \"${os_platform}\" = \"x86_64\" ]; then\n        check_append_file \"${check_file}\" \"-a always,exit -F arch=b64 -C euid!=uid -F auid!=unset -S execve -k user_emulation\"                                \"hash\"\n      fi\n      check_append_file   \"${check_file}\" \"-a always,exit -F arch=b32 -S chmod -S fchmod -S fchmodat -F auid>=500 -F auid!=4294967295 -k perm_mod\"            \"hash\"\n      if [ \"${os_platform}\" = \"x86_64\" ]; then\n        check_append_file \"${check_file}\" \"-a always,exit -F arch=b64 -S chmod -S fchmod -S fchmodat -F auid>=500 -F auid!=4294967295 -k perm_mod\"            \"hash\"\n      fi\n      check_append_file   \"${check_file}\" \"-a always,exit -F arch=b32 -S chown -S fchown -S fchownat -S lchown -F auid>=500 - F auid!=4294967295 -k perm_mod\" \"hash\"\n      if [ \"${os_platform}\" = \"x86_64\" ]; then\n        check_append_file \"${check_file}\" \"-a always,exit -F arch=b64 -S chown -S fchown -S fchownat -S lchown -F auid>=500 - F auid!=4294967295 -k perm_mod\" \"hash\"\n      fi\n      check_append_file   \"${check_file}\" \"-a always,exit -F arch=b32 -S setxattr -S lsetxattr -S fsetxattr -S removexattr -S lremovexattr -S fremovexattr -F auid>=500 -F auid!=4294967295 -k perm_mod\" \"hash\"\n      if [ \"${os_platform}\" = \"x86_64\" ]; then\n        check_append_file \"${check_file}\" \"-a always,exit -F arch=b64 -S setxattr -S lsetxattr -S fsetxattr -S removexattr -S lremovexattr -S fremovexattr -F auid>=500 -F auid!=4294967295 -k perm_mod\" \"hash\"\n      fi\n      #- Unauthorized access attempts to files (unsuccessful)\n      check_append_file   \"${check_file}\" \"-a always,exit -F arch=b32 -S creat -S open -S openat -S truncate -S ftruncate -F exit=-EACCES -F auid>=500 -F auid!=4294967295 -k access\"                    \"hash\"\n      check_append_file   \"${check_file}\" \"-a always,exit -F arch=b32 -S creat -S open -S openat -S truncate -S ftruncate -F exit=-EPERM -F auid>=500 -F auid!=4294967295 -k access\"                     \"hash\"\n      if [ \"${os_platform}\" = \"x86_64\" ]; then\n        check_append_file \"${check_file}\" \"-a always,exit -F arch=b64 -S creat -S open -S openat -S truncate -S ftruncate -F exit=-EACCES -F auid>=500 -F auid!=4294967295 -k access\"                    \"hash\"\n        check_append_file \"${check_file}\" \"-a always,exit -F arch=b64 -S creat -S open -S openat -S truncate -S ftruncate -F exit=-EPERM -F auid>=500 -F auid!=4294967295 -k access\"                     \"hash\"\n      fi\n      #- Use of privileged commands (unsuccessful and successful)\n      #check_append_file \"${check_file}\" \"-a always,exit -F path=/bin/ping -F perm=x -F auid>=500 -F auid!=4294967295 -k privileged\"   \"hash\"\n      check_append_file   \"${check_file}\" \"-a always,exit -F path=/usr/bin/chacl -F perm=x -F auid>=1000 -F auid!=unset -k priv_cmd\"   \"hash\"\n      check_append_file   \"${check_file}\" \"-a always,exit -F arch=b32 -S mount -F auid>=500 -F auid!=4294967295 -k export\"             \"hash\"\n      if [ \"${os_platform}\" = \"x86_64\" ]; then\n        check_append_file \"${check_file}\" \"-a always,exit -F arch=b64 -S mount -F auid>=500 -F auid!=4294967295 -k export\"             \"hash\"\n      fi\n      #- Files and programs deleted by the user (successful and unsuccessful)\n      check_append_file   \"${check_file}\" \"-a always,exit -F path=/usr/sbin/usermod -F perm=x -F auid>=1000 -F auid!=unset -k usermod\" \"hash\"\n      check_append_file   \"${check_file}\" \"-a always,exit -F arch=b32 -S unlink -S unlinkat -S rename -S renameat -F auid>=500 -F auid!=4294967295 -k delete\" \"hash\"\n      if [ \"${os_platform}\" = \"x86_64\" ]; then\n        check_append_file \"${check_file}\" \"-a always,exit -F arch=b64 -S unlink -S unlinkat -S rename -S renameat -F auid>=500 -F auid!=4294967295 -k delete\" \"hash\"\n      fi\n      #- All system administration actions\n      check_append_file   \"${check_file}\" \"-w /etc/sudoers -p wa -k scope\"              \"hash\"\n      check_append_file   \"${check_file}\" \"-w /etc/sudoers.d -p wa -k scope\"            \"hash\"\n      check_append_file   \"${check_file}\" \"-w /etc/sudoers -p wa -k actions\"            \"hash\"\n      check_append_file   \"${check_file}\" \"-w /var/log/sudo.log -p wa -k sudo_log_file\" \"hash\"\n      #- Make sue kernel module loading and unloading is recorded\n      check_append_file   \"${check_file}\" \"-w /sbin/insmod -p x -k modules\"             \"hash\"\n      check_append_file   \"${check_file}\" \"-w /sbin/rmmod -p x -k modules\"              \"hash\"\n      check_append_file   \"${check_file}\" \"-w /sbin/modprobe -p x -k modules\"           \"hash\"\n      if [ \"${os_platform}\" = \"x86_64\" ]; then\n        check_append_file \"${check_file}\" \"-a always,exit -F arch=b64 -S init_module,finit_module,delete_module,create_module,query_module -F auid>=1000 -F auid!=unset -k kernel_modules\" \"hash\"\n      fi\n      check_append_file   \"${check_file}\" \"-a always,exit -F path=/usr/bin/kmod -F perm=x -F auid>=1000 -F auid!=unset - k kernel_modules\" \"hash\"\n      check_append_file   \"${check_file}\" \"-a always,exit -S init_module -S delete_module -k modules\"                                      \"hash\"\n      #- Tracks successful and unsuccessful mount commands\n      if [ \"${os_platform}\" = \"x86_64\" ]; then\n        check_append_file \"${check_file}\" \"-a always,exit -F arch=b64 -S mount -F auid>=500 -F auid!=4294967295 -k mounts\" \"hash\"\n      fi\n      check_append_file   \"${check_file}\" \"-a always,exit -F arch=b32 -S mount -F auid>=500 -F auid!=4294967295 -k mounts\" \"hash\"\n      #check_append_file \"${check_file}\" \"\" \"hash\"\n      #- Manage and retain logs\n      check_append_file   \"${check_file}\" \"space_left_action = ${space_left_action}\"             \"hash\"\n      check_append_file   \"${check_file}\" \"action_mail_acct = email\"                             \"hash\"\n      check_append_file   \"${check_file}\" \"admin_space_left_action = ${admin_space_left_action}\" \"hash\"\n      check_append_file   \"${check_file}\" \"disk_full_action = ${disk_full_action}\"               \"hash\"\n      check_append_file   \"${check_file}\" \"disk_error_action= ${disk_error_action}\"              \"hash\"\n      check_append_file   \"${check_file}\" \"max_log_file = ${max_log_file}\"                       \"hash\"\n      check_append_file   \"${check_file}\" \"max_log_file_action = ${max_log_file_action}\"         \"hash\"\n      #- Make file immutable - MUST BE LAST!\n      check_append_file   \"${check_file}\" \"-e 2\"                                                 \"hash\"\n      for service_name in sysstat auditd; do\n        check_linux_service \"${service_name}\" \"on\"\n      done\n    fi\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      if [ \"${os_version}\" = \"10\" ]; then\n        check_file=\"/var/spool/cron/crontabs/sys\"\n        check_append_file \"${check_file}\" \"\" \"\"\n        if [ -f \"${check_file}\" ]; then\n          command=\"grep -v \\\"^\\\\*\\\" \\\"${check_file}\\\" | grep \\\"sa2\\\"\"\n          command_message \"${command}\"\n          sar_check=$( eval \"${command}\" )\n        fi\n        if [ $( expr \"${sar_check}\" : \"[A-z]\" ) != 1 ]; then\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_insecure \"System Accounting is not enabled\"\n            fix_message  \"echo \\\"0,20,40 * * * * /usr/lib/sa/sa1\\\" >> ${check_file}\"\n            fix_message  \"echo \\\"45 23 * * * /usr/lib/sa/sa2 -s 0:00 -e 23:59 -i 1200 -A\\\" >> ${check_file}\"\n            fix_message  \"chown sys:sys /var/adm/sa/*\"\n            fix_message  \"chmod go-wx /var/adm/sa/*\"\n          fi\n          if [ \"${audit_mode}\" = 0 ]; then\n            set_message \"System Accounting to enabled\"\n            if [ ! -f \"${log_file}\" ]; then\n              echo \"Saving:    File ${check_file} to ${work_dir}${check_file}\"\n              find \"${check_file}\" | cpio -pdm \"${work_dir}\" 2> /dev/null\n            fi\n            command=\"echo \\\"0,20,40 * * * * /usr/lib/sa/sa1\\\" >> \\\"${check_file}\\\"\"\n            command_message \"${command}\"\n            eval \"${command}\"\n            command=\"echo \\\"45 23 * * * /usr/lib/sa/sa2 -s 0:00 -e 23:59 -i 1200 -A\\\" >> \\\"${check_file}\\\"\"\n            command_message \"${command}\"\n            eval \"${command}\"\n            command=\"chown sys:sys /var/adm/sa/*\"\n            command_message \"${command}\"\n            eval \"${command}\"\n            command=\"chmod go-wx /var/adm/sa/*\"\n            command_message \"${command}\"\n            eval \"${command}\"\n            if [ \"${os_version}\" = \"10\" ]; then\n              command=\"pkgchk -f -n -p \\\"${check_file}\\\" 2> /dev/null\"\n              command_message \"${command}\"\n              eval \"${command}\"\n            else\n              command=\"pkg fix $( pkg search \\\"${check_file}\\\" | grep pkg | awk '{print $4}' )\"\n              command_message \"${command}\"\n              eval \"${command}\"\n            fi\n          fi\n        else\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_secure \"System Accounting is already enabled\"\n          fi\n          if [ \"${audit_mode}\" = 2 ]; then\n            restore_file \"${check_file}\" \"${restore_dir}\"\n          fi\n        fi\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/accounting/audit_system_accounts.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC2034\n# shellcheck disable=SC1090\n# shellcheck disable=SC2154\n\n# audit_system_accounts\n#\n# Check system accounts\n#\n# Refer to Section(s) 7.2     Page(s) 146-147 CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 7.2     Page(s) 169     CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 7.2     Page(s) 149-150 CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 5.4.2   Page(s) 252     CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 10.2    Page(s) 138-9   CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 8.1     Page(s) 27      CIS FreeBSD Benchmark v1.0.5\n# Refer to Section(s) 9.3     Page(s) 73-4    CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 7.1     Page(s) 100-1   CIS Solaris 10 Benchmark v5.1.0\n# Refer to Section(s) 5.4.2   Page(s) 231     CIS Amazon Linux v2.0.0\n# Refer to Section(s) 5.4.2   Page(s) 244     CIS Ubuntu 16.04 v2.0.0`\n# Refer to Section(s) 5.4.2.7 Page(s) 708-10  CIS Ubuntu 24.04 v1.0.0`\n#.\n\naudit_system_accounts () {\n  print_function \"audit_system_accounts\"\n  string=\"System Accounts that do not have a shell\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"FreeBSD\" ]; then\n    if [ \"${my_id}\" != \"0\" ] && [ \"${use_sudo}\" = \"0\" ]; then\n      notice_message \"Requires sudo to check\"\n      return\n    fi\n    password_file=\"/etc/passwd\"\n    shadow_file=\"/etc/shadow\"\n    if test -r \"$shadow_file\"; then\n      if [ \"${audit_mode}\" != 2 ]; then\n        command=\"awk -F: '(\\$1!=\\\"root\\\" && \\$1!=\\\"sync\\\" && \\$1!=\\\"shutdown\\\" && \\$1!=\\\"halt\\\" && \\$3<500 && \\$7!=\\\"/sbin/nologin\\\" && \\$7!=\\\"/bin/false\\\" && \\$7!=\\\"/usr/sbin/nologin\\\") {print \\$1}' < \\\"${password_file}\\\"\"\n        command_message   \"${command}\"\n        user_list=$( eval \"${command}\" )\n        for user_name in ${user_list}; do\n          command=\"grep \\\"${user_name}:\\\" \\\"${password_file}\\\" | cut -f7 -d:\"\n          command_message     \"${command}\"\n          shell_field=$( eval \"${command}\" )\n          if [ ! -f \"${shell_field}\" ] || [ \"${shell_field}\" = \"\" ]; then\n            if [ \"${audit_mode}\" = 1 ]; then\n              inc_insecure \"System account \\\"${user_name}\\\" has an invalid shell\"\n              if [ \"${os_name}\" = \"FreeBSD\" ]; then\n                lock_command=\"pw moduser ${user_name} -s /sbin/nologin\"\n                fix_message  \"${lock_command}\"\n              else\n                lock_command=\"usermod -s /sbin/nologin ${user_name}\"\n                fix_message  \"${lock_command}\"\n              fi\n            fi\n            if [ \"${audit_mode}\" = 0 ]; then\n              lock_message=\"System account \\\"${user_name}\\\" to have shell /sbin/nologin\"\n              backup_file  \"${password_file}\"\n              run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n            fi\n          fi\n        done\n      else\n        restore_file \"${password_file}\" \"${restore_dir}\"\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/accounting/audit_system_auth.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_system_auth\n#\n# Check system auth settings\n#\n# Refer to Section(s) 6.3.1         Page(s) 160-1   CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 6.3.5-6       Page(s) 163-5   CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 5.3.1-2       Page(s) 238-41  CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 5.3.1-2       Page(s) 220-1   CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 5.3.1-4       Page(s) 232-6   CIS Ubuntu 16.04 Benchmark v1.0.0\n# Refer to Section(s) 5.3.1.1.1-3.1 Page(s) 598-656 CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_system_auth () {\n  print_function \"audit_system_auth\"\n  string=\"Check system auth settings\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    check_file=\"/etc/security/pwquality.conf\"\n    check=0\n    if [ \"${os_vendor}\" = \"Amazon\" ] && [ \"${os_version}\" = \"2016\" ]; then\n      check=1\n    fi\n    if [ \"${os_vendor}\" = \"Ubuntu\" ] && [ \"${os_version}\" -ge 16 ]; then\n      check_linux_package \"install\" \"libpam-runtime\"\n      check_linux_package \"install\" \"libpam-modules\"\n      check=1\n    fi\n    if [ \"${check}\" -eq 1 ]; then\n      check_file_value \"is\" \"${check_file}\"   \"minlen\"   \"eq\" \"8\"      \"hash\" \n      check_file_value \"is\" \"${check_file}\"   \"dcredit\"  \"eq\" \"-1\"     \"hash\" \n      check_file_value \"is\" \"${check_file}\"   \"ocredit\"  \"eq\" \"-1\"     \"hash\" \n      check_file_value \"is\" \"${check_file}\"   \"ucredit\"  \"eq\" \"-1\"     \"hash\" \n      check_file_value \"is\" \"${check_file}\"   \"lcredit\"  \"eq\" \"-1\"     \"hash\" \n      audit_system_auth_nullok\n      audit_system_auth_unlock_time           \"auth\"     \"unlock_time\" \"900\"\n      audit_system_auth_password_history      \"account\"  \"remember\"    \"5\"\n      audit_system_auth_password_hashing      \"password\" \"${password_hashing}\"\n    else\n      if [ \"${os_vendor}\" = \"Red\" ] || [ \"${os_vendor}\" = \"CentOS\" ] && [ \"${os_version}\" = \"7\" ]; then\n        check_file_value \"is\" \"${check_file}\" \"minlen\"   \"eq\" \"8\"      \"hash\"  \n        check_file_value \"is\" \"${check_file}\" \"dcredit\"  \"eq\" \"-1\"     \"hash\"  \n        check_file_value \"is\" \"${check_file}\" \"ocredit\"  \"eq\" \"-1\"     \"hash\"  \n        check_file_value \"is\" \"${check_file}\" \"ucredit\"  \"eq\" \"-1\"     \"hash\"  \n        check_file_value \"is\" \"${check_file}\" \"lcredit\"  \"eq\" \"-1\"     \"hash\"  \n        audit_system_auth_nullok\n        audit_system_auth_unlock_time         \"auth\"     \"unlock_time\" \"900\"\n        audit_system_auth_password_history    \"account\"  \"remember\"    \"5\"\n        audit_system_auth_password_hashing    \"password\" \"${password_hashing}\"\n      else\n        if [ \"${audit_mode}\" != 2 ]; then\n          audit_system_auth_nullok\n          audit_system_auth_password_history  \"account\"  \"remember\"    \"10\"\n          audit_system_auth_password_policy   \"password\" \"minlen\"      \"8\"\n          audit_system_auth_password_policy   \"password\" \"dcredit\"     \"-1\"\n          audit_system_auth_password_policy   \"password\" \"lcredit\"     \"-1\"\n          audit_system_auth_password_policy   \"password\" \"ocredit\"     \"-1\"\n          audit_system_auth_password_policy   \"password\" \"ucredit\"     \"-1\"\n          audit_system_auth_unlock_time       \"auth\"     \"unlock_time\" \"900\"\n          audit_system_auth_account_reset     \"account\"  \"reset\"\n          audit_system_auth_password_strength \"password\" \"16,12,8\"\n          audit_system_auth_no_magic_root     \"auth\"     \"no_magic_root\"\n        fi\n      fi\n    fi\n    if [ \"${os_vendor}\" = \"Ubuntu\" ] && [ \"${os_version}\" -ge 24 ]; then\n      check_linux_package \"install\" \"libpam-pwquality\"\n      check_file=\"/etc/security/pwquality.conf\"\n      check_file_value  \"is\"  \"${check_file}\" \"maxsequence\"      \"eq\"   \"3\"   \"hash\" \n      check_file_value  \"is\"  \"${check_file}\" \"difok\"            \"eq\"   \"2\"   \"hash\" \n      check_file_value  \"is\"  \"${check_file}\" \"dictcheck\"        \"eq\"   \"0\"   \"hash\" \n      check_file_value  \"is\"  \"${check_file}\" \"lcredit\"          \"eq\"   \"0\"   \"hash\"  \n      check_file_value  \"not\" \"${check_file}\" \"enforcing\"        \"eq\"   \"0\"   \"hash\"  \n      check_append_file       \"${check_file}\" \"enforce_for_root\" \"hash\"\n      check_file=\"/etc/security/faillock.conf\"\n      check_append_file       \"${check_file}\" \"even_deny_root\"   \"hash\"\n      check_file_value  \"is\"  \"${check_file}\" \"root_unlock_time\" \"eq\"   \"60\"  \"hash\"  \n      check_file_value  \"is\"  \"${check_file}\" \"unlock_time\"      \"eq\"   \"900\" \"hash\"  \n      check_file_value  \"is\"  \"${check_file}\" \"deny\"             \"eq\"   \"5\"   \"hash\"  \n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/accounting/audit_system_auth_account_reset.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_system_auth_account_reset\n#\n# Check account reset settingd\n#\n# Refer to Section(s) 6.3.2 Page(s) 161-2 CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 9.3.2 Page(s) 133-4 CIS SLES 11 Benchmark v1.0.0\n#.\n\naudit_system_auth_account_reset () {\n  auth_string=\"${1}\"\n  search_string=\"${2}\"\n  print_function \"audit_system_auth_account_reset\"\n  string=\"Account Reset Settings\"\n  check_message  \"${string}\"\n  temp_file=\"${temp_dir}/audit_system_auth_account_reset\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${audit_mode}\" != 2 ]; then\n      for check_file in /etc/pam.d/common-auth /etc/pam.d/system-auth; do \n        if [ -f \"${check_file}\" ]; then\n          check_value=$( grep \"^${auth_string}\" ${check_file} | grep \"${search_string}$\" | awk '{print $6}' )\n          if [ \"${check_value}\" != \"${search_string}\" ]; then\n            if [ \"${os_vendor}\" = \"Ubuntu\" ] && [ \"${os_version}\" -ge 22 ]; then\n              lock_command=\"awk '( \\$1 == \\\"account\\\" && \\$2 == \\\"required\\\" && \\$3 == \\\"pam_failback.so\\\" ) { print \\\"auth\\trequired\\tpam_faillock.so onerr=fail no_magic_root reset\\\"; print $0; next };' < ${check_file} > ${temp_file} ; cat ${temp_file} > ${check_file} ; rm ${temp_file}\"\n              if [ \"${audit_mode}\" = \"1\" ]; then\n                inc_insecure \"Account reset entry not enabled in \\\"${check_file}\\\"\"\n                fix_message  \"rm ${lock_command}\"\n              fi\n              if [ \"${audit_mode}\" = 0 ]; then\n                backup_file  \"${check_file}\"\n                lock_message=\"Account reset entry in \\\"${check_file}\\\"\"\n\n              fi\n            else\n              lock_command=\"awk '( \\$1 == \\\"account\\\" && \\$2 == \\\"required\\\" && \\$3 == \\\"pam_tally2.so\\\" ) { print \\\"auth\\trequired\\tpam_tally2.so onerr=fail no_magic_root reset\\\"; print $0; next };' < ${check_file} > ${temp_file} ; cat ${temp_file} > ${check_file} ; rm ${temp_file}\"\n              if [ \"${audit_mode}\" = \"1\" ]; then\n                inc_insecure \"Account reset entry not enabled in \\\"${check_file}\\\"\"\n                fix_message  \"rm ${lock_command}\"\n              fi\n              if [ \"${audit_mode}\" = 0 ]; then\n                backup_file  \"${check_file}\"\n                lock_message=\"Account reset entry in \\\"${check_file}\\\"\"\n                run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n              fi\n            fi \n          else\n            if [ \"${audit_mode}\" = \"1\" ]; then\n              inc_secure \"Account entry enabled in \\\"${check_file}\\\"\"\n            fi\n          fi\n        fi\n      done\n    else\n      for check_file in /etc/pam.d/common-auth /etc/pam.d/system-auth; do \n        restore_file \"${check_file}\" \"${restore_dir}\"\n      done \n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/accounting/audit_system_auth_no_magic_root.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_system_auth_no_magic_root\n#\n# Make sure root account isn't locked as part of account locking\n#.\n\naudit_system_auth_no_magic_root () {\n  auth_string=\"${1}\"\n  search_string=\"${2}\"\n  string=\"Make sure root account isn't locked as part of account locking\"\n  check_message  \"${string}\"\n  print_function \"audit_system_auth_no_magic_root\"\n  temp_file=\"${temp_dir}/audit_system_auth_no_magic_root\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${audit_mode}\" != 2 ]; then\n      for check_file in /etc/pam.d/common-auth /etc/pam.d/system-auth; do \n        if [ -f \"${check_file}\" ]; then\n          check_value=$( grep \"^${auth_string}\" \"${check_file}\" | grep \"${search_string}$\" | awk '{print $5}' )\n          if [ \"${check_value}\" != \"${search_string}\" ]; then\n            if [ \"${os_vendor}\" = \"Ubuntu\" ] && [ \"${os_version}\" -ge 22 ]; then\n              lock_command=\"cat ${temp_file} |awk '( \\$1 == \\\"auth\\\" && \\$2 == \\\"required\\\" && \\$3 == \\\"pam_deny.so\\\" ) { print \\\"auth\\trequired\\tpam_faillock.so onerr=fail no_magic_root\\\"; print $0; next };' < ${check_file}> ${temp_file} ; cat ${temp} > ${check_file} ; rm ${temp_file}\"\n            else\n              lock_command=\"cat ${temp_file} |awk '( \\$1 == \\\"auth\\\" && \\$2 == \\\"required\\\" && \\$3 == \\\"pam_deny.so\\\" ) { print \\\"auth\\trequired\\tpam_tally2.so onerr=fail no_magic_root\\\"; print $0; next };' < ${check_file} > ${temp_file} ; cat ${temp} > ${check_file} ; rm ${temp_file}\"\n            fi\n            if [ \"${audit_mode}\" = \"1\" ]; then\n              inc_insecure \"Auth entry not enabled in \\\"${check_file}\\\"\"\n              fix_message  \"rm ${lock_command}\"\n            fi\n            if [ \"${audit_mode}\" = 0 ]; then\n              backup_file  \"${check_file}\"\n              lock_message=\"Setting:   Auth entry in \\\"${check_file}\\\"\"\n              run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n            fi\n          else\n            if [ \"${audit_mode}\" = \"1\" ]; then\n              inc_secure   \"Auth entry enabled in \\\"${check_file}\\\"\"\n            fi\n          fi\n        fi\n      done\n    else\n      for restore_file in /etc/pam.d/common-auth /etc/pam.d/system-auth; do \n        restore_file \"${restore_file}\" \"${restore_dir}\"\n      done \n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/accounting/audit_system_auth_nullok.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_system_auth_nullok\n#\n# Ensure null passwords are not accepted\n#\n# Refer to Section(s) 5.3.3.4.1 Page(s) 664-6  CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_system_auth_nullok () {\n  print_function \"audit_system_auth_nullok\"\n  string=\"Ensure null passwords are not accepted\"\n  check_message  \"${string}\"\n  temp_file=\"${temp_dir}/audit_system_auth_nullok\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${audit_mode}\" != 2 ]; then\n      for check_file in /etc/pam.d/common-auth /etc/pam.d/system-auth; do\n        if [ -f \"${check_file}\" ]; then\n          check_value=0\n          command=\"grep -v '^#' \\\"${check_file}\\\" | grep \\\"nullok\\\" | head -1 | wc -l | sed \\\"s/ //g\\\"\"\n          command_message     \"${command}\"\n          check_value=$( eval \"${command}\" )\n          lock_command=\"sed 's/ nullok//' < ${check_file} > ${temp_file} ; cat ${temp_file} > ${check_file} ; rm ${temp_file}\"\n          if [ \"${check_value}\" = 1 ]; then\n            if [ \"${audit_mode}\" = \"1\" ]; then\n              inc_insecure \"Found nullok \\\"entry\\\" in \\\"${check_file}\\\"\"\n              fix_message  \"${lock_command}\"\n            fi\n            if [ \"${audit_mode}\" = 0 ]; then\n              backup_file  \"${check_file}\"\n              lock_message=\"Removing \\\"nullok\\\" entries from \\\"${check_file}\\\"\"\n              run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n            fi\n          else\n            if [ \"${audit_mode}\" = \"1\" ]; then\n              inc_secure   \"No \\\"nullok\\\" entries in \\\"${check_file}\\\"\"\n            fi\n          fi\n        fi\n      done\n    else\n      for check_file in /etc/pam.d/common-auth /etc/pam.d/system-auth; do\n        restore_file \"${check_file}\" \"${restore_dir}\"\n      done \n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/accounting/audit_system_auth_unlock_time.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_system_auth_unlock_time\n#\n# Check lockout time for failed password attempts enabled\n#\n# Refer to Section(s) 6.3.3 Page(s) 139-140 CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 6.3.3 Page(s) 143-4   CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 5.3.2 Page(s) 234     CIS Ubuntu 16.04 Benchmark v1.0.0\n#.\n\naudit_system_auth_unlock_time () {\n  auth_string=\"${1}\"\n  search_string=\"${2}\"\n  search_value=\"${3}\"\n  print_function \"audit_system_auth_unlock_time\"\n  string=\"Check lockout time for failed password attempts enabled\"\n  check_message  \"${string}\"\n  temp_file=\"${temp_dir}/audit_system_auth_unlock_time\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    os_check=0\n    if [ \"${os_vendor}\" = \"Amazon\" ]; then\n      os_check=1\n    fi\n    if [ \"${os_vendor}\" = \"Ubuntu\" ] && [ \"${os_version}\" -ge 16 ]; then\n      if [ \"${os_version}\" -ge 22 ]; then\n        os_check=0\n      else\n        os_check=1\n      fi\n    fi\n    for check_file in /etc/pam.d/system-auth /etc/pam.d/common-auth; do\n      if [ -f \"${check_file}\" ]; then\n        if [ \"${audit_mode}\" != 2 ]; then\n          check_value=$( grep \"^${auth_string}\" \"${check_file}\" | grep \"${search_string}$\" | awk -F '${search_string}=' '{print $2}' | awk '{print $1}' )\n          if [ \"${check_value}\" != \"${search_string}\" ]; then\n            if [ \"${os_check}\" -eq 0 ]; then\n              lock_command=\"sed 's/^auth.*pam_env.so$/&\\nauth\\t\\trequired\\t\\t\\tpam_faillock.so preauth audit silent deny=5 unlock_time=900\\nauth\\t\\t[success=1 default=bad]\\t\\t\\tpam_unix.so\\nauth\\t\\t[default=die]\\t\\t\\tpam_faillock.so authfail audit deny=5 unlock_time=900\\nauth\\t\\tsufficient\\t\\t\\tpam_faillock.so authsucc audit deny=5 ${search_string}=${search_value}\\n/' < ${check_file} > ${temp_file} ; cat ${temp_file} > ${check_file} ; rm ${temp_file}\"\n            else\n              lock_command=\"awk '( \\$1 == \\\"auth\\\" && \\$2 == \\\"required\\\" && \\$3 == \\\"pam_tally2.so\\\" ) { print \\\"auth\\trequired\\tpam_tally2.so onerr=fail audit silent deny=5 unlock_time=900\\\"; print \\$0; next };' < ${check_file} > ${temp_file} ; cat ${temp_file} > ${check_file} ; rm ${temp_file}\"\n            fi\n            if [ \"${audit_mode}\" = 1 ]; then\n              inc_insecure \"Lockout time for failed password attempts not enabled in \\\"${check_file}\\\"\"\n              fix_message  \"${lock_command}\"\n            fi\n            if [ \"${audit_mode}\" = 0 ]; then\n              backup_file  \"${check_file}\"\n              lock_message=\"Lockout time for failed password attempts in \\\"${check_file}\\\"\"\n              run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n            fi\n          else\n            if [ \"${audit_mode}\" = \"1\" ]; then\n              inc_secure   \"Lockout time for failed password attempts enabled in \\\"${check_file}\\\"\"\n            fi\n          fi\n        else\n          for restore_file in /etc/pam.d/system-auth /etc/pam.d/common-auth; do\n            restore_file   \"${restore_file}\" \"${restore_dir}\"\n          done\n        fi\n      fi\n    done\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/accounting/audit_system_auth_use_uid.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_system_auth_use_uid\n#\n# Check the use of su is restricted by sudo\n#\n# Refer to Section(s) 6.5 Page(s) 165-6 CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 6.5 Page(s) 145-6 CIS RHEL 6 Benchmark v1.2.0\n#.\n\naudit_system_auth_use_uid () {\n  print_function \"audit_system_auth_use_uid\"\n  string=\"Check the use of su is restricted by sudo\"\n  check_message  \"${string}\"\n  auth_string=\"auth\"\n  search_string=\"use_uid\"\n  check_file=\"/etc/pam.d/su\"\n  temp_file=\"${temp_dir}/audit_system_auth_use_uid\"\n  if [ -f \"${check_file}\" ]; then\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      if [ \"${audit_mode}\" != 2 ]; then\n        lock_command=\"sed 's/^auth.*use_uid$/&\\nauth\\t\\trequired\\t\\t\\tpam_wheel.so use_uid\\n/' < ${check_file} > ${temp_file} ; cat ${temp_file} > ${check_file}\"\n        command=\"grep \\\"^${auth_string}\\\" ${check_file} | grep \\\"${search_string}$\\\" | awk '{print \\\"\\$8\\\"}'\"\n        command_message \"${command}\"\n        check_value=$( eval \"${command}\" )\n        if [ \"${check_value}\" != \"${search_string}\" ]; then\n          if [ \"${audit_mode}\" = \"1\" ]; then\n            inc_insecure \"The use of su is not restricted by sudo in ${check_file}\"\n            fix_message  \"${lock_command}\"\n          fi\n          if [ \"${audit_mode}\" = 0 ]; then\n            backup_file  \"${check_file}\"\n            lock_message=\"The use of su to be restricted by sudo in ${check_file}\"\n            run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n          fi\n        else\n          if [ \"${audit_mode}\" = \"1\" ]; then\n            inc_secure   \"The use of su is restricted by sudo in \\\"${check_file}\\\"\"\n          fi\n        fi\n      else\n        restore_file \"${check_file}\" \"${restore_dir}\"\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/accounting/audit_system_integrity.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_system_integrity\n#\n# Check System Integrity Protection is enabled\n#\n# Refer to Section(s) 5.18    Page(s) 148-9     CIS Apple OS X 10.12 Benchmark v1.0.0\n# Refer to Section(s) 5.1.2,4 Page(s) 300-3,5-6 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_system_integrity () {\n  print_function \"audit_system_integrity\"\n  string=\"Check System Integrity Protection is enabled\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${audit_mode}\" != 2 ]; then\n      command=\"/usr/bin/csrutil status | grep enabled\"\n      command_message \"${command}\"\n      check=$( eval \"${command}\" )\n      if [ ! \"${check}\" ]; then\n        inc_insecure \"System Integrity Protection is not enabled\"\n      else\n        inc_secure   \"System Integrity Protection is enabled\"\n      fi\n      if [ \"${os_version}\" -ge 11 ]; then\n        command=\"/usr/bin/csrutil authenticated-root status | grep enabled\"\n        command_message \"${command}\"\n        check=$( eval   \"${command}\" )\n        if [ -z \"${check}\" ]; then\n          inc_insecure \"Sealed System Volume is not enabled\"\n        else\n          inc_secure   \"Sealed System Volume is enabled\"\n        fi\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/aix/audit_i4ls.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_i4ls\n#\n# Check License Manager\n#\n# Refer to Section(s) 2.12.2 Page(s) 207 CIS AIX Benchmark v1.1.0\n#.\n\naudit_i4ls () {\n  print_function \"audit_i4ls\"\n  string=\"License Manager\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"AIX\" ]; then\n    check_itab \"i4ls\" \"off\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/aix/audit_writesrv.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_writesrv\n#\n# Refer to Section(s) 2.12.6 Page(s) 210-1 CIS AIX Benchmark v1.1.0\n#.\n\naudit_writesrv () {\n  print_function \"audit_writesrv\"\n  string=\"Writesrv\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"AIX\" ]; then\n    check_itab \"writesrv\" \"off\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/apache/audit_apache.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_apache\n#\n# Check Apache\n#\n# Refer to Section(s) 3.11,14       Page(s) 66-9        CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 2.2.10        Page(s) 110         CIS Ubuntu Linux 16.04 Benchmark v1.0.0\n# Refer to Section(s) 2.1.17-8      Page(s) 273-9       CIS Ubuntu Linux 24.04 Benchmark v1.0.0\n# Refer to Section(s) 3.11,14       Page(s) 79-81       CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 3.11,14       Page(s) 69-71       CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 2.2.10,13     Page(s) 110,113     CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 6.10,13       Page(s) 59,61       CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 2.4.14.7      Page(s) 56-7        CIS OS X 10.5 Benchmark v1.1.0\n# Refer to Section(s) 2.10          Page(s) 21-2        CIS Solaris 11.1 v1.0.0\n# Refer to Section(s) 2.2.11        Page(s) 21-2        CIS Solaris 10 v5.1.0\n# Refer to Section(s) 2.2.10,13     Page(s) 102,105     CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 2.2.10,13     Page(s) 110,113     CIS Ubuntu 16.04 Benchmark v2.0.0\n# Refer to Section(s) 2-11          Page(s) 16-186      CIS Apache 2.2 Benchmark v3.6.0\n# Refer to Section(s) 2-11          Page(s) 16-186      CIS Apache 2.4 Benchmark v1.5.0\n#.\n\naudit_apache () {\n  print_function \"audit_apache\"\n  string=\"Apache and web based services\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      if [ \"${os_version}\" = \"10\" ]; then\n        check_sunos_service \"svc:/network/http:apache2\" \"disabled\"\n      fi\n      if [ \"${os_version}\" = \"11\" ]; then\n        check_sunos_service \"svc:/network/http:apache2\" \"disabled\"\n      fi\n      if [ \"${os_version}\" = \"10\" ]; then\n        check_sunos_service \"apache\" \"disabled\"\n      fi\n    fi\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      for service_name in httpd apache apache2 tomcat5 squid prixovy nginx; do\n        check_linux_service \"${service_name}\" \"off\"\n        check_linux_package \"uninstall\"       \"${service_name}\" \n      done\n    fi\n    check_file_perms /var/log/httpd 0640 root apache\n    for check_dir in /etc /etc/sfw /etc/apache /etc/apache2 /etc/apache2.2 /etc/apache/2.4 /usr/local/etc /usr/sfw/etc /opt/sfw/etc; do\n      for check_file in \"${check_dir}/httpd.conf\" \"${check_dir}/apache2.conf\"; do\n        if [ -f \"${check_file}\" ]; then\n          check_file_value \"is\"  \"${check_file}\" \"SSLHonorCipherOrder\"              \"space\" \"On\"                                             \"hash\"\n          check_file_value \"is\"  \"${check_file}\" \"SSLCipherSuite\"                   \"space\" \"EECDH:EDH:!NULL:!SSLv2:!RC4:!aNULL:!3DES:!IDEA\" \"hash\"\n          check_file_value \"is\"  \"${check_file}\" \"ServerTokens\"                     \"space\" \"Prod\"                                           \"hash\"\n          check_file_value \"is\"  \"${check_file}\" \"ServerSignature\"                  \"space\" \"Off\"                                            \"hash\"\n          check_file_value \"is\"  \"${check_file}\" \"SSLProtocol\"                      \"space\" \"TLSv1.2 TLSv1.3\"                                \"hash\"\n          check_file_value \"is\"  \"${check_file}\" \"SSLInsecureRenegotiation\"         \"space\" \"Off\"                                            \"hash\"\n          check_file_value \"is\"  \"${check_file}\" \"UserDir\"                          \"space\" \"Off\"                                            \"hash\"\n          check_file_value \"is\"  \"${check_file}\" \"TraceEnable\"                      \"space\" \"Off\"                                            \"hash\"\n          check_file_value \"is\"  \"${check_file}\" \"AllowOverride\"                    \"space\" \"None\"                                           \"hash\"\n          check_file_value \"is\"  \"${check_file}\" \"Options\"                          \"space\" \"None\"                                           \"hash\"\n          check_file_value \"is\"  \"${check_file}\" \"FileETag\"                         \"space\" \"None\"                                           \"hash\"\n          check_file_value \"is\"  \"${check_file}\" \"User\"                             \"space\" \"apache\"                                         \"hash\"\n          check_file_value \"is\"  \"${check_file}\" \"Group\"                            \"space\" \"apache\"                                         \"hash\"\n          check_file_value \"is\"  \"${check_file}\" \"KeepAlive\"                        \"space\" \"On\"                                             \"hash\"\n          check_file_value \"is\"  \"${check_file}\" \"MaxKeepAliveRequests\"             \"space\" \"100\"                                            \"hash\"\n          check_file_value \"is\"  \"${check_file}\" \"KeepAliveTimeout\"                 \"space\" \"15\"                                             \"hash\"\n          check_file_value \"is\"  \"${check_file}\" \"TraceEnable\"                      \"space\" \"Off\"                                            \"hash\"\n          check_file_value \"is\"  \"${check_file}\" \"RewriteEngine\"                    \"space\" \"On\"                                             \"hash\"\n          check_file_value \"is\"  \"${check_file}\" \"RewriteOptions\"                   \"space\" \"Inherit\"                                        \"hash\"\n          check_file_value \"is\"  \"${check_file}\" \"LimitRequestLine\"                 \"space\" \"512\"                                            \"hash\"\n          check_file_value \"is\"  \"${check_file}\" \"LimitRequestFields\"               \"space\" \"100\"                                            \"hash\"\n          check_file_value \"is\"  \"${check_file}\" \"LimitRequestFieldsize\"            \"space\" \"1024\"                                           \"hash\"\n          check_file_value \"is\"  \"${check_file}\" \"LimitRequestBody\"                 \"space\" \"102400\"                                         \"hash\"\n          check_file_value \"is\"  \"${check_file}\" \"Header\"                           \"space\" \"always append X-Frame-Options SAMEORIGIN\"       \"hash\"\n          check_file_value \"is\"  \"${check_file}\" \"RewriteCond\"                      \"space\" \"%{THE_REQUEST} !HTTP/1\\.1$\"                     \"hash\"\n          check_file_value \"is\"  \"${check_file}\" \"RewriteCond\"                      \"space\" \"%{HTTP_HOST} !^www\\.example\\.com [NC]\"          \"hash\"\n          check_file_value \"is\"  \"${check_file}\" \"RewriteCond\"                      \"space\" \"%{REQUEST_URI} !^/error [NC]\"                   \"hash\"\n          check_file_value \"is\"  \"${check_file}\" \"RewriteRule\"                      \"space\" \".* - [F]\"                                       \"hash\"\n          check_file_value \"is\"  \"${check_file}\" \"RequestReadTimeout\"               \"space\" \"header=20-40,MinRate=500 body=20,MinRate=500\"   \"hash\"\n          check_file_value \"is\"  \"${check_file}\" \"LimitRequestBody\"                 \"space\" \"102400\"                                         \"hash\"\n          check_file_value \"not\" \"${check_file}\" \"LoadModule dav_module\"            \"space\" \"modules/mod_dav.so\"                             \"hash\"\n          check_file_value \"not\" \"${check_file}\" \"LoadModule dav_fs_module\"         \"space\" \"modules/mod_dav_fs.so\"                          \"hash\"\n          check_file_value \"not\" \"${check_file}\" \"LoadModule status_module\"         \"space\" \"modules/mod_status.so\"                          \"hash\"\n          check_file_value \"not\" \"${check_file}\" \"LoadModule autoindex_module\"      \"space\" \"autoindex_module\"                               \"hash\"\n          check_file_value \"not\" \"${check_file}\" \"LoadModule proxy_module\"          \"space\" \"modules/mod_proxy.so\"                           \"hash\"\n          check_file_value \"not\" \"${check_file}\" \"LoadModule proxy_balancer_module\" \"space\" \"modules/mod_proxy_balancer.so\"                  \"hash\"\n          check_file_value \"not\" \"${check_file}\" \"LoadModule proxy_ftp_module\"      \"space\" \"modules/mod_proxy_ftp.so\"                       \"hash\"\n          check_file_value \"not\" \"${check_file}\" \"LoadModule proxy_http_module\"     \"space\" \"modules/mod_proxy_http.so\"                      \"hash\"\n          check_file_value \"not\" \"${check_file}\" \"LoadModule proxy_connect_module\"  \"space\" \"modules/mod_proxy_connect.so\"                   \"hash\"\n          check_file_value \"not\" \"${check_file}\" \"LoadModule proxy_ajp_module\"      \"space\" \"modules/mod_proxy_ajp.so\"                       \"hash\"\n          check_file_value \"not\" \"${check_file}\" \"LoadModule proxy_fcgi_module\"     \"space\" \"modules/mod_proxy_fcgi.so\"                      \"hash\"\n          check_file_value \"not\" \"${check_file}\" \"LoadModule proxy_scgi_module\"     \"space\" \"modules/mod_proxy_scgi.so\"                      \"hash\"\n          check_file_value \"not\" \"${check_file}\" \"LoadModule proxy_express_module\"  \"space\" \"modules/proxy_express_module.so\"                \"hash\"\n          check_file_value \"not\" \"${check_file}\" \"LoadModule proxy_wstunnel_module\" \"space\" \"modules/proxy_wstunnel_module.so\"               \"hash\"\n          check_file_value \"not\" \"${check_file}\" \"LoadModule proxy_fdpass_module\"   \"space\" \"modules/proxy_fdpass_module.so\"                 \"hash\"\n          check_file_value \"not\" \"${check_file}\" \"LoadModule userdir_module\"        \"space\" \"modules/mod_userdir.so\"                         \"hash\"\n          check_file_value \"not\" \"${check_file}\" \"LoadModule info_module\"           \"space\" \"modules/mod_info.so\"                            \"hash\"\n          check_file_value \"not\" \"${check_file}\" \"LoadModule mod_auth_basic\"        \"space\" \"modules/mod_auth_basic.so\"                      \"hash\"\n          check_file_value \"not\" \"${check_file}\" \"LoadModule mod_auth_digest\"       \"space\" \"modules/mod_auth_digest.so\"                     \"hash\"\n          check_file_value \"is\"  \"${check_file}\" \"LoadModule log_config_module\"     \"space\" \"modules/mod_log_config.so\"                      \"hash\"\n          check_file_value \"is\"  \"${check_file}\" \"LoadModule rewrite_module\"        \"space\" \"modules/mod_rewrite.so\"                         \"hash\"\n          check_file_value \"is\"  \"${check_file}\" \"LoadModule security2_module\"      \"space\" \"modules/mod_security2.so\"                       \"hash\"\n          check_file_value \"is\"  \"${check_file}\" \"LoadModule reqtimeout_module\"     \"space\" \"modules/mod_reqtimeout.so\"                      \"hash\"\n        fi\n      done\n    done\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/audit/audit_auditd.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_auditd\n#\n# Check auditd is installed - Required for various other tests like docker\n#\n# Refer to Section(s) 4.1         Page(s) 157-8       CIS Ubuntu 16.04 Benchmark v1.0.0\n# Refer to Section(s) 4.1.1.1-4   Page(s) 278-83      CIS Ubuntu 16.04 Benchmark v1.0.0\n# Refer to Section(s) 4.1.4.3,8   Page(s) 535-6,47-8  CIS Ubuntu 22.04 Benchmark v1.0.0\n# Refer to Section(s) 6.2.4.1-10, Page(s) 799-806     CIS Ubuntu 24.04 Benchmark v1.0.0\n#                     6.2.1.1-4           899-922     \n# Refer to Section(s) 3.2         Page(s) 91          CIS Apple OS X 10.12 Benchmark v1.0.0\n# Refer to Section(s) 3.1         Page(s) 272-3       CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_auditd () {\n  print_function \"audit_auditd\"\n  string=\"Audit Daemon\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      check_linux_package \"install\" \"auditd\"\n      check_linux_package \"install\" \"audispd-plugins\" \n      check_file=\"/etc/default/grub\"\n      app_name=\"Audit\"\n      package_name=\"audit\"\n      if [ \"${audit_mode}\" = 2 ]; then\n        restore_file \"${check_file}\" \"${restore_dir}\"\n      else\n        if [ -f \"${check_file}\" ]; then\n          package_disable_test=$( grep \"${package_name}=0\" \"${check_file}\" )\n          package_enabled_test=$( grep \"${package_name}=1\" \"${check_file}\" )\n        else\n          package_disabled_test=0\n          package_enabled_test=0\n        fi\n        if [ -n \"${package_disabled_test}\" ]; then\n          temp_file=\"${temp_dir}/${package_name}\"\n          inc_insecure \"Application \\\"${app_name}\\\" is disabled in \\\"${check_file}\\\"\"\n          backup_file  \"${check_file}\"\n          run_lockdown \"cat ${check_file} |sed 's/${package_name}=0//g' > ${temp_file} ; cat ${temp_file} > ${check_file} ; update-grub\" \"Application \\\"${app_name}\\\" in \\\"${check_file}\\\" to disabled\"\n        else\n          inc_secure   \"Application \\\"${app_name}\\\" is not disabled in \\\"${check_file}\\\"\"\n        fi\n        if [ -n \"${package_enabled_test}\" ]; then\n          inc_secure   \"Application \\\"${app_name}\\\" is enabled \\\"${check_file}\\\"\"\n        else\n          temp_file=\"${temp_dir}/${package_name}\"\n          inc_insecure \"Application \\\"${app_name}\\\" is not enabled in \\\"${check_file}\\\"\"\n          backup_file  \"${check_file}\"\n          line_check=$( grep \"^GRUB_CMDLINE_LINUX\" \"${check_file}\" )\n          if [ -n \"${line_check}\" ]; then\n            existing_value=$( grep \"^GRUB_CMDLINE_LINUX\" \"${check_file}\" | cut -f2 -d= |sed \"s/\\\"//g\" )\n            new_value=\"GRUB_CMDLINE_LINUX=\\\"audit=1 ${existing_value}\\\"\"\n            run_lockdown \"cat ${check_file} |sed 's/^GRUB_CMDLINE_LINUX/GRUB_CMDLINE_LINUX=\\\"${new_value}\\\"/g' > ${temp_file} ; cat ${temp_file} > ${check_file} ; update-grub\" \"Application \\\"${app_name}\\\" to enabled\"\n          else\n            run_lockdown \"echo 'GRUB_CMDLINE_LINUX=\\\"audit=1\\\"' >> ${check_file} ; update-grub\" \"Application \\\"${app_name}\\\" to enabled\"\n          fi\n        fi\n      fi\n      package_name=\"audit_backlog_limit\"\n      package_value=\"8192\"\n      if [ \"${audit_mode}\" = 2 ]; then\n        restore_file \"${check_file}\" \"${restore_dir}\"\n      else\n        if [ -f \"${check_file}\" ]; then\n          package_disable_test=$( grep \"${package_name}=0\" \"${check_file}\" )\n          package_enabled_test=$( grep  \"${package_name}=${package_value}\" \"${check_file}\" )\n        else\n          package_disabled_test=0\n          package_enabled_test=0\n        fi\n        if [ -n \"${package_disabled_test}\" ]; then\n          temp_file=\"${temp_dir}/${package_name}\"\n          inc_insecure \"${app_name} is disabled in ${check_file}\"\n          backup_file  \"${check_file}\"\n          lock_command=\"cat ${check_file} |sed 's/${package_name}=0//g' > ${temp_file} ; cat ${temp_file} > ${check_file} ; update-grub\"\n          lock_message=\"Application/Feature \\\"${app_name} \\\" in \\\"${check_file}\\\" to enabled\"\n          run_lockdown    \"${lock_command}\" \"${lock_message}\" \"sudo\"\n          existing_value=$( grep \"^GRUB_CMDLINE_LINUX\" \"${check_file}\" |cut -f2 -d= | sed \"s/\\\"//g\" )\n          new_value=\"GRUB_CMDLINE_LINUX=\\\"${package_name}=${package_value} ${existing_value}\\\"\"\n          lock_command=\"cat ${check_file} |sed 's/^GRUB_CMDLINE_LINUX/GRUB_CMDLINE_LINUX=\\\"${new_value}\\\"/g' > ${temp_file} ; cat ${temp_file} > ${check_file} ; update-grub\"\n          lock_message=\"Application/Feature \\\"${app_name}\\\" to enabled\"\n          run_lockdown    \"${lock_command}\" \"${lock_message}\" \"sudo\"\n        else\n          inc_secure       \"${app_name} is not disabled in ${check_file}\"\n        fi\n        if [ -n \"${package_enabled_test}\" ]; then\n          inc_secure   \"${app_name} is enabled ${check_file}\"\n        else\n          inc_insecure \"${app_name} is not enabled in ${check_file}\"\n          temp_file=\"${temp_dir}/${package_name}\"\n          backup_file \"${check_file}\"\n          line_check=$( grep \"^GRUB_CMDLINE_LINUX\" ${check_file} )\n          if [ -n \"${line_check}\" ]; then\n            existing_value=$( grep \"^GRUB_CMDLINE_LINUX\" \"${check_file}\" | cut -f2 -d= |sed \"s/\\\"//g\" )\n            new_value=\"GRUB_CMDLINE_LINUX=\\\"${package_name}=${package_value} ${existing_value}\\\"\"\n            lock_command=\"cat ${check_file} |sed 's/^GRUB_CMDLINE_LINUX/GRUB_CMDLINE_LINUX=\\\"${new_value}\\\"/g' > ${temp_file} ; cat ${temp_file} > ${check_file} ; update-grub\"\n            lock_message=\"Application/Feature \\\"${app_name}\\\" to enabled\"\n            run_lockdown    \"${lock_command}\" \"${lock_message}\" \"sudo\"\n          else\n            lock_command=\"echo 'GRUB_CMDLINE_LINUX=\\\"${package_name}=${package_value}\\\"' >> ${check_file} ; update-grub\"\n            lock_message=\"Application/Feature \\\"${app_name}\\\" to enabled\"\n            run_lockdown    \"${lock_command}\" \"${lock_message}\" \"sudo\"\n          fi\n        fi\n      fi\n    fi\n    if [ \"${os_name}\" = \"Darwin\" ]; then\n      check_launchctl_service \"com.apple.auditd\" \"on\"\n    fi\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      check_linux_service     \"auditd\"           \"on\"\n    fi\n    check_file=\"/etc/audit/auditd.conf\"\n    check_file_value \"is\" \"${check_file}\" \"log_group\" \"eq\" \"adm\" \"hash\"\n    for check_file in /sbin/auditctl /sbin/aureport /sbin/ausearch /sbin/autrace /sbin/auditd /sbin/augenrules; do\n      if [ -f \"${check_file}\" ]; then\n        check_file_perms   \"${check_file}\" \"0750\" \"root\" \"root\"\n      fi\n    done\n    if [ -d \"/etc/audit\" ]; then\n      command=\"find /etc/audit/ -type f \\( -name '*.conf' -o -name '*.rules' \\)\"\n      command_message    \"${command}\"\n      file_list=$( eval  \"${command}\" )\n      for check_file in ${file_list}; do\n        check_file_perms \"${check_file}\" \"0640\" \"root\" \"root\"\n      done\n    fi\n    check_file=\"/var/log/audit/audit.log\"\n    if [ -f \"${check_file}\" ]; then\n      check_file_perms   \"${check_file}\" \"0640\" \"root\" \"root\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/aws/compute/audit_aws_ec2.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_aws_ec2\n#\n# Check AWS EC2\n#\n# Refer to https://www.cloudconformity.com/conformity-rules/EC2/default-securitygroups-in-use.html\n# Refer to https://www.cloudconformity.com/conformity-rules/EC2/ec2-instance-using-iam-roles.html\n# Refer to https://www.cloudconformity.com/conformity-rules/EC2/publicly-shared-ami.html\n# Refer to https://www.cloudconformity.com/conformity-rules/EBS/ebs-encrypted.html\n# Refer to https://www.cloudconformity.com/conformity-rules/EBS/ebs-encrypted-with-kms-customer-master-keys.html\n#.\n\naudit_aws_ec2 () {\n  print_function    \"audit_aws_ec2\"\n  check_message     \"EC2\"\n  command=\"aws ec2 describe-instances --region \\\"${aws_region}\\\" --query 'Reservations[].Instances[].InstanceId' --filters \\\"Name=instance.group-name,Values=default\\\" --output text\"\n  command_message   \"${command}\"\n  instances=$( eval \"${command}\" )\n  if [ -z \"${instances}\" ]; then\n    inc_secure \"There are no instances using the default security group\"\n  else\n    for instance in ${instances}; do\n      inc_insecure \"The instance \\\"${instance}\\\" is using the default security group\"\n    done\n  fi\n  command=\"aws ec2 describe-instances --region \\\"${aws_region}\\\" --query \\\"Reservations[].Instances[].InstanceId\\\" --output text\"\n  command_message   \"${command}\"\n  instances=$( eval \"${command}\" )\n  for instance in ${instances}; do\n    command=\"aws ec2 describe-instances --region \\\"${aws_region}\\\" --instance-ids \\\"${instance}\\\" --query \\\"Reservations[*].Instances[*].IamInstanceProfile\\\" --output text\"\n    command_message \"${command}\"\n    profile=$( eval \"${command}\" )\n    if [ -n \"${profile}\" ]; then\n      inc_secure    \"Instances \\\"${instance}\\\" uses an IAM profile\"\n    else\n      inc_insecure  \"Warning:   Instance \\\"${instance}\\\" does not use an IAM profile\"\n    fi\n  done\n  command=\"aws ec2 describe-images --region \\\"${aws_region}\\\" --owners self --query \\\"Images[].ImageId\\\" --output text\"\n  command_message \"${command}\"\n  images=$( eval  \"${command}\" )\n  for image in ${images}; do\n    command=\"aws ec2 describe-images --owners self --region \\\"${aws_region}\\\" --image-ids \\\"${image}\\\" --query \\\"Images[].Public\\\" | grep true\"\n    command_message \"${command}\"\n    public=$( eval  \"${command}\" )\n    if [ -z \"${public}\" ]; then\n      inc_secure      \"Image \\\"${image}\\\" is not publicly shared\"\n    else\n      inc_insecure    \"Image \\\"${image}\\\" is publicly shared\"\n      verbose_message \"aws ec2 modify-image-attribute --region ${aws_region} --image-id ${image} --launch-permission '{\\\"Remove\\\":[{\\\"Group\\\":\\\"all\\\"}]}'\" \"fix\"\n    fi\n  done\n  command=\"aws ec2 describe-volumes --query \\\"Volumes[].VolumeId\\\" --output text\"\n  command_message \"${command}\"\n  volumes=$( eval \"${command}\" )\n  for volume in ${volumes}; do\n    command=\"aws ec2 describe-volumes --volume-id \\\"${volume}\\\" --query \\\"Volumes[].Encrypted\\\" | grep true\"\n    command_message \"${command}\"\n    check=$( eval   \"${command}\" )\n    if [ -n \"${check}\" ]; then\n      inc_secure   \"EBS Volume \\\"${volume}\\\" is encrypted\"\n    else\n      inc_insecure \"EBS Volume \\\"${volume}\\\" is not encrypted\"\n    fi\n    # Check if KMS is being used\n    command=\"aws ec2 describe-volumes --region \\\"${aws_region}\\\" --volume-ids \\\"${volume}\\\" --query 'Volumes[].KmsKeyId' --output text | cut -f2 -d/\"\n    command_message \"${command}\"\n    key_id=$( eval  \"${command}\" )\n    if [ -n \"${key_id}\" ]; then\n      inc_secure    \"EBS Volume \\\"${volume}\\\" is encrypted with a KMS key\"\n    else\n      inc_insecure  \"EBS Volume \\\"${volume}\\\" is encrypted not with a KMS key\"\n    fi\n  done\n}\n\n"
  },
  {
    "path": "modules/aws/compute/audit_aws_elb.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_aws_elb\n#\n# Check AWS ELB \n#\n# Refer to http://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-security-policy-table.html\n# Refer to https://www.cloudconformity.com/conformity-rules/ELB/elb-access-log.html\n# Refer to https://www.cloudconformity.com/conformity-rules/ELB/elb-insecure-ssl-ciphers.html\n# Refer to https://www.cloudconformity.com/conformity-rules/ELB/elb-insecure-ssl-protocols.html\n# Refer to https://www.cloudconformity.com/conformity-rules/ELB/elb-listener-security.html\n# Refer to https://www.cloudconformity.com/conformity-rules/ELB/elb-security-group.html\n#.\n\naudit_aws_elb () {\n  # Ensure ELBs have logging enabled\n  print_function  \"audit_aws_elb\"\n  check_message   \"ELB\"\n  command=\"aws elb describe-load-balancers --region \\\"${aws_region}\\\" --query \\\"LoadBalancerDescriptions[].LoadBalancerName\\\" --output text\"\n  command_message \"${command}\"\n  elbs=$( eval    \"${command}\" )\n  for elb in ${elbs}; do\n    command=\"aws elb describe-load-balancers --region \\\"${aws_region}\\\" --load-balancer-name \\\"${elb}\\\"  --query \\\"LoadBalancerDescriptions[].AccessLog\\\" | grep true\"\n    command_message  \"${command}\"\n    check=$( eval    \"${command}\" )\n    if [ -z \"${check}\" ]; then\n      inc_insecure    \"ELB \\\"${elb}\\\" does not have access logging enabled\"\n      verbose_message \"aws elb modify-load-balancer-attributes --region ${aws_region} --load-balancer-name ${elb} --load-balancer-attributes \\\"{\\\\\\\"AccessLog\\\\\\\":{\\\\\\\"Enabled\\\\\\\":true,\\\\\\\"EmitInterval\\\\\\\":60,\\\\\\\"S3BucketName\\\\\\\":\\\\\\\"elb-logging-bucket\\\\\\\"}}\\\"\" fix\n    else\n      inc_secure      \"ELB \\\"${elb}\\\" has access logging enabled\"\n    fi\n    # Ensure ELBs are not using HTTP\n    command=\"aws elb describe-load-balancers --region \\\"${aws_region}\\\" --load-balancer-name \\\"${elb}\\\"  --query \\\"LoadBalancerDescriptions[].ListenerDescriptions[].Listener[].Protcol\\\" --output text\"\n    command_message  \"${command}\"\n    protocol=$( eval \"${command}\" )\n    if [ \"${protocol}\" = \"HTTP\" ]; then\n      inc_insecure   \"ELB \\\"${elb}\\\" is using HTTP\"\n    else\n      inc_secure     \"ELB \\\"${elb}\\\" is not using HTTP\"\n    fi\n    # Ensure ELB SGs do not have port 80 open to the world\n    command=\"aws elb describe-load-balancers --region \\\"${aws_region}\\\" --load-balancer-name \\\"${elb}\\\"  --query \\\"LoadBalancerDescriptions[].SecurityGroups\\\" --output text\"\n    command_message  \"${command}\"\n    sgs=$( eval      \"${command}\" )\n    for sg in ${sgs}; do\n      check_aws_open_port \"${sg}\" \"80\" \"tcp\" \"HTTP\" \"ELB\" \"${elb}\"\n    done\n    # Ensure no deprecated ciphers of protocols are being used\n    command=\"aws elb describe-load-balancer-policies --region \\\"${aws_region}\\\" --load-balancer-name \\\"${elb}\\\" --output text\"\n    command_message  \"${command}\"\n    list=$( eval     \"${command}\" )\n    for cipher in SSLv2 RC2-CBC-MD5 PSK-AES256-CBC-SHA PSK-3DES-EDE-CBC-SHA KRB5-DES-CBC3-SHA KRB5-DES-CBC3-MD5 \\\n                  PSK-AES128-CBC-SHA PSK-RC4-SHA KRB5-RC4-SHA KRB5-RC4-MD5 KRB5-DES-CBC-SHA KRB5-DES-CBC-MD5 \\\n                  EXP-EDH-RSA-DES-CBC-SHA EXP-EDH-DSS-DES-CBC-SHA EXP-ADH-DES-CBC-SHA EXP-DES-CBC-SHA \\\n                  SSLv3 EXP-RC2-CBC-MD5 EXP-KRB5-RC2-CBC-SHA EXP-KRB5-DES-CBC-SHA EXP-KRB5-RC2-CBC-MD5 \\\n                  EXP-KRB5-DES-CBC-MD5 EXP-ADH-RC4-MD5 EXP-RC4-MD5 EXP-KRB5-RC4-SHA EXP-KRB5-RC4-MD5; do\n      check=$( echo \"${list}\" | grep ${cipher} | grep true )\n      if [ -n \"${check}\" ]; then\n        inc_insecure \"ELB \\\"${elb}\\\" is using deprecated cipher \\\"${cipher}\\\"\"\n      else\n        inc_secure   \"ELB \\\"${elb}\\\" is not using deprecated cipher \\\"${cipher}\\\"\"\n      fi\n    done\n  done\n}\n"
  },
  {
    "path": "modules/aws/compute/audit_aws_es.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_aws_es\n#\n# Check AWS Elasticsearch\n#\n# Refer to https://www.cloudconformity.com/conformity-rules/Elasticsearch/elasticsearch-domain-exposed.html\n# Refer to https://www.cloudconformity.com/conformity-rules/Elasticsearch/elasticsearch-accessible-only-from-whitelisted-ip-addresses.html\n#.\n\naudit_aws_es () {\n  print_function  \"audit_aws_es\"\n  check_message   \"Elasticsearch\"\n  command=\"aws es list-domain-names --region \\\"${aws_region}\\\" --query \\\"DomainNames[].DomainName\\\" --output text\"\n  command_message \"${command}\"\n  domains=$( eval \"${command}\" )\n  for domain in ${domains}; do\n    command=\"aws es describe-elasticsearch-domain --domain-name \\\"${domain}\\\" --query 'DomainStatus.AccessPolicies' --output text | grep Principle | grep \\\"{\\\\\\\"AWS\\\\\\\":\\\\\\\"\\\\*\\\\\\\"}\\\"\"\n    command_message \"${command}\"\n    check=$( eval   \"${command}\" )\n    if [ -z \"${check}\" ]; then\n      inc_secure    \"Elasticsearch domain \\\"${domain}\\\" is not publicly accessible\"\n    else\n      inc_insecure  \"Elasticsearch domain \\\"${domain}\\\" is publicly accessible\"\n    fi\n    command=\"aws es describe-elasticsearch-domain --domain-name \\\"${domain}\\\" --query 'DomainStatus.AccessPolicies' --output text | grep \\\"aws:SourceIp\\\" | grep \\\"[0-9]\\.\\\"\"\n    command_message \"${command}\"\n    check=$( eval   \"${command}\" )\n    if [ -n \"${check}\" ]; then\n      inc_secure    \"Elasticsearch doamin \\\"${domain}\\\" has an IP based access policy\"\n    else\n      inc_insecure  \"Elasticsearch domain \\\"${domain}\\\" does not have and IP based access policy\"\n    fi\n  done\n}\n\n"
  },
  {
    "path": "modules/aws/compute/audit_aws_rec_ec2.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_aws_rec_ec2\n#\n# Check EC2 Recommendations\n#\n# Refer to https://www.cloudconformity.com/conformity-rules/EC2/ami-naming-conventions.html\n# Refer to https://www.cloudconformity.com/conformity-rules/EC2/approved-golden-amis.html\n# Refer to https://www.cloudconformity.com/conformity-rules/EC2/ec2-instance-naming-conventions.html\n# Refer to https://www.cloudconformity.com/conformity-rules/EC2/ec2-instance-termination-protection.html\n# Refer to https://www.cloudconformity.com/conformity-rules/EC2/security-group-naming-conventions.html\n# Refer to https://www.cloudconformity.com/conformity-rules/EBS/ebs-naming-conventions.html\n# Refer to https://www.cloudconformity.com/conformity-rules/EBS/general-purpose-ssd-volume.html\n# Refer to https://www.cloudconformity.com/conformity-rules/EBS/ebs-volumes-too-old-snapshots.html\n# Refer to https://www.cloudconformity.com/conformity-rules/EBS/unused-ebs-volumes.html\n# Refer to https://www.cloudconformity.com/conformity-rules/EBS/ebs-volumes-recent-snapshots.html\n#.\n\naudit_aws_rec_ec2 () {\n  print_function  \"audit_aws_rec_ec2\"\n  check_message   \"EC2 Recommendations\"\n  command=\"aws ec2 describe-volumes --region \\\"${aws_region}\\\" --query 'Volumes[].VolumeId' --output text\"\n  command_message \"${command}\"\n  volumes=$( eval \"${command}\" )\n  for volume in ${volumes}; do\n    if [ \"${check_volattach}\" = \"y\" ]; then\n      # Check for EC2 volumes that are unattached\n      command=\"aws ec2 describe-volumes --region \\\"${aws_region}\\\" --volume-id \\\"${volume}\\\" --query 'Volumes[].State' --output text\"\n      command_message \"${command}\"\n      check=$( eval   \"${command}\" )\n      if [ ! \"${check}\" = \"available\" ]; then\n        inc_secure    \"EC2 volume \\\"${volume}\\\" is attached to an instance\"\n      else\n        inc_insecure  \"EC2 volume \\\"${volume}\\\" is not attached to an instance\"\n      fi\n    fi\n    if [ \"${check_volattach}\" = \"y\" ]; then\n      # Check that EC2 volumes are using cost effective storage\n      command=\"aws ec2 describe-volumes --region \\\"${aws_region}\\\" --volume-id \\\"${volume}\\\" --query 'Volumes[].VolumeType' | grep \\\"gp2\\\"\"\n      command_message \"${command}\"\n      check=$( eval   \"${command}\" )\n      if [ -n \"${check}\" ]; then\n        inc_secure    \"EC2 volume \\\"${volume}\\\" is using General Purpose SSD\"\n      else\n        inc_insecure  \"EC2 volume \\\"${volume}\\\" is not using General Purpose SSD\"\n      fi\n    fi\n  done\n  # Check date of snapshots\n  if [ \"${check_snapage}\" = \"y\" ]; then\n    command=\"aws iam get-user --query \\\"User.Arn\\\" --output text | cut -f5 -d:\"\n    command_message   \"${command}\"\n    arn=$( eval       \"${command}\" )\n    command=\"aws ec2 describe-snapshots --region \\\"${aws_region}\\\" --owner-ids \\\"${arn}\\\" --filters ansible_value=status,Values=completed --query \\\"Snapshots[].SnapshotId\\\" --output text\"\n    command_message   \"${command}\"\n    snapshots=$( eval \"${command}\" )\n    counter=0\n    for snapshot in ${snapshot}s; do\n      command=\"aws ec2 describe-snapshots --region \\\"${aws_region}\\\" --snapshot-id \\\"${snapshot}\\\" --query \\\"Snapshots[].StartTime\\\" --output text --output text | cut -f1 -d.\"\n      command_message   \"${command}\"\n      snap_date=$( eval \"${command}\" )\n      if [ \"${os_name}\" = \"Linux\" ]; then\n        command=\"date -d \\\"${snap_date}\\\" \\\"+%s\\\"\"\n        command_message   \"${command}\"\n        snap_secs=$( eval \"${command}\" )\n      else\n        command=\"date -j -f \\\"%Y-%m-%dT%H:%M:%SS\\\" \\\"${snap_date}\\\" \\\"+%s\\\"\"\n        command_message   \"${command}\"\n        snap_secs=$( eval \"${command}\" )\n      fi\n      command=\"date \\\"+%s\\\"\"\n      command_message   \"${command}\"\n      curr_secs=$( eval \"${command}\" )\n      command=\"echo \\\"(${curr_secs} - ${snap_secs})/84600\\\" | bc\"\n      command_message   \"${command}\"\n      diff_days=$( eval \"${command}\" )\n      if [ \"${diff_days}\" -gt \"${aws_ec2_max_retention}\" ]; then\n        inc_insecure \"EC2 snapshot \\\"${snapshot}\\\" is more than \\\"${aws_ec2_max_retention}\\\" days old\"\n      else\n        inc_secure   \"EC2 snapshot \\\"${snapshot}\\\" is less than \\\"${aws_ec2_max_retention}\\\" days old\"\n      fi\n      if [ \"${diff_days}\" -gt \"${aws_ec2_min_retention}\" ]; then\n        counter=$((counter+1))\n      fi\n    done\n    if [ \"${counter}\" -gt 0 ]; then\n      inc_secure   \"There are EC2 snapshots more than \\\"${aws_ec2_min_retention}\\\" days old\"\n    else\n      inc_insecure \"There are no EC2 snapshots more than \\\"${aws_ec2_min_retention}\\\" days old\"\n    fi\n  fi\n  # Check Security Groups have Name tags\n  command=\"aws ec2 describe-security-groups --region \\\"${aws_region}\\\" --query 'SecurityGroups[].GroupId' --output text\"\n  command_message \"${command}\"\n  sgs=$( eval \"${command}\" )\n  for sg in ${sgs}; do\n    if [ ! \"${sg}\" = \"default\" ]; then\n      command=\"aws ec2 describe-security-groups --region \\\"${aws_region}\\\" --group-id \\\"${sg}\\\" --query \\\"SecurityGroups[].Tags[?Key==\\\\\\`Name\\\\\\`].Value\\\" 2> /dev/null --output text\"\n      command_message       \"${command}\"\n      ansible_value=$( eval \"${command}\" )\n      if [ -z \"${ansible_value}\" ]; then\n        inc_insecure    \"AWS Security Group \\\"${sg}\\\" does not have a Name tag\"\n        verbose_message \"aws ec2 create-tags --region \\\"${aws_region}\\\" --resources \\\"${image}\\\" --tags Key=Name,Value=<valid_name_tag>\" \"fix\"\n      else\n        if [ \"${strict_valid_names}\" = \"y\" ]; then\n          command=\"echo \\\"${ansible_value}\\\" |grep \\\"^sg-${valid_tag_string}\\\"\"\n          command_message \"${command}\"\n          check=$( eval   \"${command}\" )\n          if [ -n \"${check}\" ]; then\n            inc_secure    \"AWS Security Group \\\"${sg}\\\" has a valid Name tag\"\n          else\n            inc_insecure  \"AWS Security Group \\\"${sg}\\\" does not have a valid Name tag\"\n          fi\n        fi\n      fi\n    fi\n  done\n  # Check Volumes have Name tags\n  command=\"aws ec2 describe-volumes --region \\\"${aws_region}\\\" --query \\\"Volumes[].VolumeId\\\" --output text\"\n  command_message \"${command}\"\n  volumes=$( eval \"${command}\" )\n  for volume in ${volumes}; do\n    command=\"aws ec2 describe-volumes --region \\\"${aws_region}\\\" --volume-id \\\"${volume}\\\" --query \\\"Volumes[].Tags[?Key==\\\\\\`Name\\\\\\`].Value\\\" --output text\"\n    command_message       \"${command}\"\n    ansible_value=$( eval \"${command}\" )\n    if [ -z \"${ansible_value}\" ]; then\n      inc_insecure \"AWS EC2 volume \\\"${volume}\\\" does not have a Name tag\"\n      verbose_message    \"aws ec2 create-tags --region \\\"${aws_region}\\\" --resources \\\"${volume}\\\" --tags Key=Name,Value=<valid_name_tag>\" \"fix\"\n    else\n      if [ \"${strict_valid_names}\" = \"y\" ]; then\n        command=\"echo \\\"${ansible_value}\\\" |grep \\\"^ami-${valid_tag_string}\\\"\"\n        command_message \"${command}\"\n        check=$( eval \"${command}\" )\n        if [ -n \"${check}\" ]; then\n          inc_secure   \"AWS EC2 volume \\\"${volume}\\\" has a valid Name tag\"\n        else\n          inc_insecure \"AWS EC2 volume \\\"${volume}\\\" does not have a valid Name tag\"\n        fi\n      fi\n    fi\n  done\n  # Check AMIs have Name tags\n  command=\"aws ec2 describe-images --region \\\"${aws_region}\\\" --owners self --query \\\"Images[].ImageId\\\" --output text\"\n  command_message \"${command}\"\n  images=$( eval  \"${command}\" )\n  for image in ${images}; do\n\t  command=\"aws ec2 describe-images --region \\\"${aws_region}\\\" --owners self --image-id \\\"${image}\\\" --query \\\"Images[].Tags[?Key==\\\\\\`Name\\\\\\`].Value\\\" --output text\"\n    command_message       \"${command}\"\n    ansible_value=$( eval \"${command}\" )\n    if [ -z \"${ansible_value}\" ]; then\n      inc_insecure \"AWS AMI \\\"${image}\\\" does not have a Name tag\"\n      verbose_message    \"aws ec2 create-tags --region \\\"${aws_region}\\\" --resources \\\"${image}\\\" --tags Key=Name,Value=<valid_name_tag>\" \"fix\"\n    else\n      if [ \"${strict_valid_names}\" = \"y\" ]; then\n        command=\"echo \\\"${ansible_value}\\\" |grep \\\"^ami-${valid_tag_string}\\\"\"\n        command_message \"${command}\"\n        check=$( eval   \"${command}\" )\n        if [ -n \"${check}\" ]; then\n          inc_secure    \"AWS AMI \\\"${image}\\\" has a valid Name tag\"\n        else\n          inc_insecure  \"AWS AMI \\\"${image}\\\" does not have a valid Name tag\"\n        fi\n      fi\n    fi\n  done\n  # Check Instances have Name tags\n  command=\"aws ec2 describe-instances --region \\\"${aws_region}\\\" --query \\\"Reservations[].Instances[].InstanceId\\\" --output text\"\n  command_message   \"${command}\"\n  instances=$( eval \"${command}\" )\n  for instance in ${instances}; do\n    for tag in Name Role Environment Owner; do\n      command=\"aws ec2 describe-instances --region \\\"${aws_region}\\\" --instance-id \\\"${instance}\\\" --query \\\"Reservations[].Instances[].Tags[?Key==\\\\\\`${tag}\\\\\\`].Value\\\" --output text\"\n      command_message \"${command}\"\n      check=$( eval   \"${command}\" )\n      if [ -z \"${check}\" ]; then\n        inc_insecure    \"AWS Instance \\\"${instance}\\\" does not have a \\\"${tag}\\\" tag\"\n        verbose_message \"aws ec2 create-tags --region \\\"${aws_region}\\\" --resources \\\"${instance}\\\" --tags Key=${tag},Value=<valid_name_tag>\" \"fix\"\n      else\n        if [ \"${strict_valid_names}\" = \"y\" ]; then\n          command=\"echo \\\"${ansible_value}\\\" |grep \\\"^ec2-${valid_tag_string}\\\"\"\n          command_message \"${command}\"\n          check=$( eval   \"${command}\" )\n          if [ -n \"${check}\" ]; then\n            inc_secure    \"AWS Instance \\\"${instance}\\\" has a valid \\\"${tag}\\\" tag\"\n          else\n            inc_insecure  \"AWS Instance \\\"${instance}\\\" does not have a valid \\\"${tag}\\\" tag\"\n          fi\n        fi\n      fi\n    done\n    command=\"aws ec2 describe-instance-attribute --region \\\"${aws_region}\\\" --instance-id \\\"${instance}\\\" --attribute disableApiTermination --query \\\"DisableApiTermination\\\" | grep -i true\"\n    command_message    \"${command}\"\n    term_check=$( eval \"${command}\" )\n    command=\"aws autoscaling describe-auto-scaling-instances --region \\\"${aws_region}\\\" --query 'AutoScalingInstances[].InstanceId' | grep \\\"${instance}\\\"\"\n    command_message    \"${command}\"\n    asg_check=$( eval  \"${command}\" )\n    if [ -n \"${term_check}\" ] && [ -z \"${asg_check}\" ]; then\n      inc_secure   \"Termination Protection is enabled for instance \\\"${instance}\\\"\"\n    else\n      inc_insecure \"Termination Protection is not enabled for instance \\\"${instance}\\\"\"\n    fi\n  done\n  # Check Instances are from self produced images\n  command=\"aws ec2 describe-instances --region \\\"${aws_region}\\\" --query 'Reservations[].Instances[].ImageId' --output text\"\n  command_message \"${command}\"\n  images=$( eval  \"${command}\" )\n  for image in ${images}; do\n    command=\"aws ec2 describe-images --region \\\"${aws_region}\\\" --image-ids \\\"${image}\\\" --query 'Images[].ImageOwnerAlias' --output text\"\n    command_message \"${command}\"\n    owner=$( eval   \"${command}\" )\n    if [ \"${owner}\" = \"self\" ] || [ -z \"${owner}\" ]; then\n      inc_secure   \"AWS AMI \\\"${image}\\\" is a self produced image\"\n    else\n      \n      inc_insecure \"AWS AMI \\\"${image}\\\" is not have a valid Name tag\"\n    fi\n  done\n  # Check number of Elastic IPs that are being used\n  command=\"aws ec2 describe-account-attributes --region \\\"${aws_region}\\\" --attribute-names max-elastic-ips --query \\\"AccountAttributes[].AttributeValues[].AttributeValue\\\" --output text\"\n  command_message \"${command}\"\n  max_ips=$( eval \"${command}\" )\n  command=\"aws ec2 describe-addresses --region \\\"${aws_region}\\\" --query 'Addresses[].PublicIp' --filters \\\"Name=domain,Values=standard\\\" --output text | wc -l | sed \\\"s/ //g\\\"\"\n  command_message \"${command}\"\n  no_ips=$( eval  \"${command}\" )\n  if [ \"${max_ips}\" -ne \"${no_ips}\" ]; then\n    inc_secure    \"Number of Elastic IPs consumed is less than limit of \\\"${max_ips}\\\"\"\n  else\n    inc_insecure  \"Number of Elastic IPs consumed has reached limit of \\\"${max_ips}\\\"\"\n  fi\n  # Check Instances are using EC2-VPC and not EC2-Classic\n  command=\"aws ec2 describe-instances --region \\\"${aws_region}\\\" --query 'Reservations[*].Instances[*].InstanceId' --output text\"\n  command_message   \"${command}\"\n  instances=$( eval \"${command}\" )\n  for instance in ${instances}; do\n    command=\"aws ec2 describe-instances --region \\\"${aws_region}\\\" --instance-ids \\\"${instance}\\\" --query 'Reservations[*].Instances[*].VpcId' --output text\"\n    command_message \"${command}\"\n    vpc=$( eval     \"${command}\" )\n    if [ -n \"${vpc}\" ]; then\n      inc_secure    \"Instance \\\"${instance}\\\" is an EC2-VPC platform\"\n    else\n      inc_insecure  \"Instance \\\"${instance}\\\" is an EC2-Classic platform\"\n    fi \n  done\n}\n\n"
  },
  {
    "path": "modules/aws/compute/audit_aws_rec_elb.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_aws_rec_elb\n#\n# Check ELB Recommendations\n# \n# Refer to https://www.cloudconformity.com/conformity-rules/ELB/elb-connection-draining-enabled.html\n# Refer to https://www.cloudconformity.com/conformity-rules/ELB/elb-cross-zone-load-balancing-enabled.html\n# Refer to https://www.cloudconformity.com/conformity-rules/ELB/elb-minimum-number-of-ec2-instances.html\n# Refer to https://www.cloudconformity.com/conformity-rules/ELB/unused-elastic-load-balancers.html\n#.\n\naudit_aws_rec_elb () {\n  print_function  \"audit_aws_rec_elb\"\n  check_message   \"ELB Recommendations\"\n  command=\"aws elb describe-load-balancers --region \\\"${aws_region}\\\" --query \\\"LoadBalancerDescriptions[].LoadBalancerName\\\" --output text\"\n  command_message \"${command}\"\n\telbs=$( eval    \"${command}\" )\n  for elb in ${elbs}; do\n    command=\"aws elb describe-load-balancer-attributes --region \\\"${aws_region}\\\" --load-balancer-name \\\"${elb}\\\" --query \\\"LoadBalancerAttributes.ConnectionDraining\\\" | grep Enabled | grep true\"\n    command_message \"${command}\"\n    check=$( eval   \"${command}\" )\n    if [ ! \"${check}\" ]; then\n      inc_insecure    \"ELB \\\"${elb}\\\" does not have connection draining enabled\"\n      verbose_message \"aws elb modify-load-balancer-attributes --region \\\"${aws_region}\\\" --load-balancer-name \\\"${elb}\\\" --load-balancer-attributes \\\"{\\\\\\\"ConnectionDraining\\\\\\\":{\\\\\\\"Enabled\\\\\\\":true, \\\\\\\"Timeout\\\\\\\":300}}\\\"\" \"fix\"\n    else\n      inc_secure      \"ELB \\\"${elb}\\\" has connection draining\"\n    fi\n    command=\"aws elb describe-load-balancer-attributes --region \\\"${aws_region}\\\" --load-balancer-name \\\"${elb}\\\"  --query \\\"LoadBalancerAttributes.CrossZoneLoadBalancing\\\" | grep Enabled | grep true\"\n    command_message \"${command}\"\n    check=$( eval   \"${command}\" )\n    if [ ! \"${check}\" ]; then\n      inc_insecure  \"ELB \\\"${elb}\\\" does not have cross zone balancing enabled\"\n    else\n      inc_secure    \"ELB \\\"${elb}\\\" has cross zone balancing enabled\"\n    fi\n    command=\"aws elb describe-instance-health --region \\\"${aws_region}\\\" --load-balancer-name \\\"${elb}\\\"  --query \\\"InstanceStates[].State\\\" | grep -c InService\"\n    command_message \"${command}\"\n    number=$( eval  \"${command}\" )\n    if [ \"${number}\" -lt 2 ]; then\n      inc_insecure  \"ELB \\\"${elb}\\\" does not have at least 2 instances in service\"\n    else\n      inc_secure    \"ELB \\\"${elb}\\\" has at least two instances in service\"\n    fi\n    command=\"aws elb describe-instance-health --region \\\"${aws_region}\\\" --load-balancer-name \\\"${elb}\\\"  --query \\\"InstanceStates[].InstanceState\\\" --filter ansible_value=state,Values='OutOfService' --output text\"\n    command_message   \"${command}\"\n    instances=$( eval \"${command}\" )\n    for instance in ${instances}; do\n      inc_insecure  \"ELB \\\"${elb}\\\" instance \\\"${instance}\\\" is out of service \"\n    done\n  done\n}\n\n"
  },
  {
    "path": "modules/aws/compute/audit_aws_rec_es.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_aws_rec_es\n#\n# Check Elasticsearch Recommendations\n#\n# Refer to https://www.cloudconformity.com/conformity-rules/Elasticsearch/elasticsearch-dedicated-master-enabled.html\n# Refer to https://www.cloudconformity.com/conformity-rules/Elasticsearch/general-purpose-ssd-volume.html\n#.\n\naudit_aws_rec_es () {\n  print_function  \"audit_aws_rec_es\"\n  check_message   \"Elasticsearch Recommendations\"\n  command=\"aws es list-domain-names --region \\\"${aws_region}\\\" --query \\\"DomainNames[].DomainName\\\" --output text\"\n  command_message \"${command}\"\n  domains=$( eval \"${command}\" )\n  for domain in ${domains}; do\n    # Check that ES domains have dedicated masters\n    command=\"aws es describe-elasticsearch-domain --domain-name \\\"${domain}\\\" --query \\\"DomainStatus.ElasticsearchClusterConfig.DedicatedMasterEnabled\\\" | grep true\"\n    command_message \"${command}\"\n    check=$( eval   \"${command}\" )\n    if [ -n \"${check}\" ]; then\n      inc_secure    \"Elasticsearch doamin \\\"${domain}\\\" has dedicated master nodes\"\n    else\n      inc_insecure  \"Elasticsearch domain \\\"${domain}\\\" does not have dedicated master nodes\"\n    fi\n    # Check that ES domains are using cost effective storage\n    command=\"aws es describe-elasticsearch-domain --domain-name \\\"${domain}\\\" --query \\\"DomainStatus.EBSOptions.VolumeType\\\" | grep \\\"gp2\\\"\"\n    command_message \"${command}\"\n    check=$( eval   \"${command}\" )\n    if [ -n \"${check}\" ]; then\n      inc_secure    \"Elasticsearch doamin \\\"${domain}\\\" is using General Purpose SSD\"\n    else\n      inc_insecure  \"Elasticsearch domain \\\"${domain}\\\" is not using General Purpose SSD\"\n      command=\"aws es describe-elasticsearch-domain --domain-name \\\"${domain}\\\" --query \\\"DomainStatus.EBSOptions.VolumeSize\\\" --output text\"\n      command_message  \"${command}\"\n      vol_size=$( eval \"${command}\" )\n      verbose_message  \"aws es update-elasticsearch-domain-config --region \\\"${aws_region}\\\" --domain-name \\\"${domain}\\\" --ebs-options EBSEnabled=true,VolumeType=\\\"gp2\\\",VolumeSize=$vol_size\" \"fix\"\n    fi\n    # Check that ES domains have cross zone awareness\n    command=\"aws es describe-elasticsearch-domain --domain-name \\\"${domain}\\\" --query \\\"DomainStatus.ElasticsearchClusterConfig.ZoneAwarenessEnabled\\\" | grep true\"\n    command_message \"${command}\"\n    check=$( eval   \"${command}\" )\n    if [ -n \"${check}\" ]; then\n      inc_secure    \"Elasticsearch doamin \\\"${domain}\\\" has cross zone awareness\"\n    else\n      inc_insecure  \"Elasticsearch domain \\\"${domain}\\\" does not have cross zone awareness\"\n    fi\n  done\n}\n\n"
  },
  {
    "path": "modules/aws/compute/audit_aws_ses.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_aws_ses\n#\n# Check AWS SES\n#\n# Refer to https://www.cloudconformity.com/conformity-rules/SES/dkim-enabled.html\n#.\n\naudit_aws_ses () {\n  print_function  \"audit_aws_ses\"\n  check_message   \"SES\"\n  # determine if your AWS Simple Email Service (SES) identities (domains and email addresses) are configured to use DKIM signatures\n  command=\"aws ses list-identities --region \\\"${aws_region}\\\" --query Identities --output text 2> /dev/null\"\n  command_message \"${command}\"\n  domains=$( eval \"${command}\" )\n  for domain in ${domains}; do\n    command=\"aws ses get-identity-dkim-attributes --region \\\"${aws_region}\\\" --identities \\\"${domain}\\\" | grep DkimEnabled | grep true\"\n    command_message   \"${command}\"\n    check=$( eval     \"${command}\" )\n    if [ -n \"${check}\" ]; then\n      inc_secure      \"Domain \\\"${domain}\\\" has DKIM enabled\" \n    else\n      inc_insecure    \"Domain \\\"${domain}\\\" does not have DKIM enabled\"\n      verbose_message \"aws ses set-identity-dkim-enabled --region \\\"${aws_region}\\\" --identity \\\"${domain}\\\" --dkim-enabled\" \"fix\"\n    fi\n  done\n}\n\n"
  },
  {
    "path": "modules/aws/config/audit_aws_cf.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_aws_cf\n#\n# Check AWS CloudFormation\n#\n# Refer to https://www.cloudconformity.com/conformity-rules/CloudFormation/cloudformation-stack-notification.html\n# Refer to https://www.cloudconformity.com/conformity-rules/CloudFormation/cloudformation-stack-policy.html\n#.\n\naudit_aws_cf () {\n  # Check Cloud Formation stacks are using SNS\n  print_function  \"audit_aws_cf\"\n  check_message   \"CloudFormation\"\n  command=\"aws cloudformation list-stacks --region \\\"${aws_region}\\\" --query 'StackSummaries[].StackId' --output text\"\n  command_message \"${command}\"\n  stacks=$( eval  \"${command}\" )\n  for stack in ${stacks}; do \n    command=\"aws cloudformation describe-stacks --region \\\"${aws_region}\\\" --stack-name \\\"${stack}\\\" --query 'Stack[].NotificationARNs' --output text\"\n    command_message \"${command}\"\n    check=$( eval   \"${command}\" )\n    stack=$( echo   \"${stack}\" | cut -f2 -d/ )\n    if [ \"${check}\" ]; then\n      inc_secure    \"SNS topic ${exists} for CloudFormation stack \\\"${stack}\\\"\"\n    else\n      inc_insecure  \"SNS topic does not exist for CloudFormation stack \\\"${stack}\\\"\"\n    fi\n  done\n  # Check stacks have a policy\n  command=\"aws cloudformation list-stacks --region \\\"${aws_region}\\\" --query 'StackSummaries[].StackName' --output text\"\n  command_message \"${command}\"\n  stacks=$( eval  \"${command}\" )\n  for stack in ${stacks}; do \n    command=\"aws cloudformation get-stack-policy --region \\\"${aws_region}\\\" --stack-name \\\"${stack}\\\" --query 'StackPolicyBody' --output text 2> /dev/null\"\n    command_message \"${command}\"\n    check=$( eval   \"${command}\" )\n    if [ \"${check}\" ]; then\n      inc_secure    \"CloudFormation stack \\\"${stack}\\\" has a policy\"\n    else\n      inc_insecure  \"CloudFormation stack \\\"${stack}\\\" does not have a policy\"\n    fi\n  done\n}\n\n"
  },
  {
    "path": "modules/aws/config/audit_aws_config.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_aws_config\n#\n# Check AWS Config\n#\n# Refer to https://www.cloudconformity.com/conformity-rules/Config/aws-config-enabled.html\n#.\n\naudit_aws_config () {\n  print_function  \"audit_aws_config\"\n  check_message   \"Config\"\n\tcommand=\"aws configservice describe-configuration-recorders --region \\\"${aws_region}\\\"\"\n  command_message \"${command}\"\n  check=$( eval   \"${command}\" )\n  if [ ! \"${check}\" ]; then\n    inc_insecure  \"AWS Configuration Recorder not enabled\"\n    run_lockdown  \"aws configservice start-configuration-recorder\" \"Configuration Recorder Service to enabled\"\n  else\n    inc_secure    \"AWS Configuration Recorder enabled\"\n  fi\n  command=\"aws configservice --region \\\"${aws_region}\\\" get-status | grep FAILED\"\n  command_message \"${command}\"\n  check=$( eval   \"${command}\" )\n  if [ \"${check}\" ]; then\n    inc_insecure  \"AWS Config not enabled\"\n  else\n    inc_secure    \"AWS Config enabled\"\n  fi\n}\n\n"
  },
  {
    "path": "modules/aws/config/audit_aws_support_role.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_aws_support_role\n#\n# Check AWS Support Role\n#\n# Refer to Section(s) 1.22 Page(s) 64-5 CIS AWS Foundations Benchmark v1.1.0\n#.\n\naudit_aws_support_role () {\n  print_function  \"audit_aws_support_role\"\n  check_message   \"Support\"\n  command=\"aws iam list-policies --query 'Policies[?PolicyName == \\\"AWSSupportAccess\\\"]' | grep Arn | awk -F': ' '{print \\$2}' | sed \\\"s/ //g\\\" | sed \\\"s/,//g\\\" | sed \\\"s/\\\\\\\"//g\\\"\"\n  command_message \"${command}\"\n  arn=$( eval     \"${command}\" )\n  command=\"aws iam list-entities-for-policy --policy-arn \\\"${arn}\\\" | grep PolicyRoles | cut -f2 -d:\"\n  command_message \"${command}\"\n  roles=$( eval   \"${command}\" )\n  command=\"aws iam list-entities-for-policy --policy-arn \\\"${arn}\\\" | grep PolicyGroups | cut -f2 -d:\"\n  command_message \"${command}\"\n  groups=$( eval  \"${command}\" )\n  command=\"aws iam list-entities-for-policy --policy-arn \\\"${arn}\\\" | grep PolicyUsers | cut -f2 -d:\"\n  command_message \"${command}\"\n  users=$( eval   \"${command}\" )\n  if [ -z \"${roles}\" ] && [ -z \"${users}\" ] && [ -z \"${groups}\" ]; then\n    inc_secure    \"A support role has been created to manage incidents\"\n  else\n    inc_insecure  \"There is no support role to manage incidents\"\n  fi\n}\n"
  },
  {
    "path": "modules/aws/database/audit_aws_ec.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_aws_ec\n#\n# Check AWS ElastiCache\n#\n# Refer to https://www.cloudconformity.com/conformity-rules/ElastiCache/elasticache-multi-az.html\n#.\n\naudit_aws_ec () {\n  print_function  \"audit_aws_ec\"\n  check_message   \"ElastiCache\"\n  command=\"aws elasticache describe-replication-groups --region \\\"${aws_region}\\\" --query 'ReplicationGroups[].ReplicationGroupId' --output text\"\n  command_message \"${command}\"\n  caches=$( eval  \"${command}\" )\n  for cache in ${caches}; do \n    command=\"aws elasticache describe-replication-groups --region \\\"${aws_region}\\\" --replication-group-id \\\"${cache}\\\" --query 'ReplicationGroups[].AutomaticFailover' | grep enabled\"\n    command_message \"${command}\"\n    check=$( eval   \"${command}\" )\n    if [ -n \"${check}\" ]; then\n      inc_secure   \"ElastiCache \\\"${cache}\\\" is Multi-AZ enabled\"\n    else\n      inc_insecure \"ElastiCache \\\"${cache}\\\" is not Multi-AZ enabled\"\n      lock_command=\"aws elasticache modify-replication-group --region ${aws_region} --replication-group-id ${cache} --automatic-failover-enabled --apply-immediately\"\n      lock_message=\"ElastiCache \\\"${cache}\\\" Multi-AZ to enabled\"\n      run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n    fi\n  done\n}\n\n"
  },
  {
    "path": "modules/aws/database/audit_aws_rds.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_aws_rds\n#\n# Check RDS Recommendations\n#\n# Refer to https://www.cloudconformity.com/conformity-rules/RDS/rds-auto-minor-version-upgrade.html\n# Refer to https://www.cloudconformity.com/conformity-rules/RDS/rds-automated-backups-enabled.html\n# Refer to https://www.cloudconformity.com/conformity-rules/RDS/rds-encryption-enabled.html\n# Refer to https://www.cloudconformity.com/conformity-rules/RDS/rds-publicly-accessible.html\n# Refer to https://www.cloudconformity.com/conformity-rules/RDS/rds-encrypted-with-kms-customer-master-keys.html\n# Refer to https://www.cloudconformity.com/conformity-rules/RDS/instance-not-in-public-subnet.html\n# Refer to https://www.cloudconformity.com/conformity-rules/RDS/rds-master-username.html\n#.\n\naudit_aws_rds () {\n  print_function  \"audit_aws_rds\"\n  check_message   \"RDS\"\n  command=\"aws rds describe-db-instances --region \\\"${aws_region}\\\" --query 'DBInstances[].DBInstanceIdentifier' --output text\"\n  command_message \"${command}\"\n  dbs=$( eval     \"${command}\" )\n  for db in ${dbs}; do\n    # Check if auto minor version upgrades are enabled\n    command=\"aws rds describe-db-instances --region \\\"${aws_region}\\\" --db-instance-identifier \\\"${db}\\\" --query 'DBInstances[].AutoMinorVersionUpgrade' | grep true\"\n    command_message \"${command}\"\n    check=$( eval   \"${command}\" )\n    if [ \"${check}\" ]; then\n      inc_secure    \"RDS instance \\\"${db}\\\" has auto minor version upgrades enabled\"\n    else\n      inc_insecure  \"RDS instance \\\"${db}\\\" does not have auto minor version upgrades enabled\"\n      fix_message   \"aws rds modify-db-instance --region \\\"${aws_region}\\\" --db-instance-identifier \\\"${db}\\\" --auto-minor-version-upgrade --apply-immediately\"\n    fi\n    # Check if automated backups are enabled\n    command=\"aws rds describe-db-instances --region \\\"${aws_region}\\\" --db-instance-identifier \\\"${db}\\\" --query 'DBInstances[].BackupRetentionPeriod' --output text\"\n    command_message \"${command}\"\n    check=$( eval   \"${command}\" )\n    if [ ! \"${check}\" -eq \"0\" ]; then\n      inc_secure    \"RDS instance \\\"${db}\\\" has automated backups enabled\"\n    else\n      inc_insecure  \"RDS instance \\\"${db}\\\" does not have automated backups enabled\"\n      fix_message   \"aws rds modify-db-instance --region \\\"${aws_region}\\\" --db-instance-identifier \\\"${db}\\\" --backup-retention-period \\\"${aws_rds_min_retention}\\\" --apply-immediately\"\n    fi\n    # Check if RDS instance is encrypted\n    command=\"aws rds describe-db-instances --region \\\"${aws_region}\\\" --db-instance-identifier \\\"${db}\\\" --query 'DBInstances[].StorageEncrypted' | grep true\"\n    command_message \"${command}\"\n    check=$( eval   \"${command}\" )\n    if [ -n \"${check}\" ]; then\n      inc_secure    \"RDS instance \\\"${db}\\\" is encrypted\"\n    else\n      inc_insecure  \"RDS instance \\\"${db}\\\" is not encrypted\"\n    fi\n    # Check if KMS is being used\n    command=\"aws rds describe-db-instances --region \\\"${aws_region}\\\" --db-instance-identifier \\\"${db}\\\" --query 'DBInstances[].KmsKeyId' --output text | cut -f2 -d/\"\n    command_message \"${command}\"\n    key_id=$( eval  \"${command}\" )\n    if [ -n \"${key_id}\" ]; then\n      inc_secure    \"RDS instance \\\"${db}\\\" is encrypted with a KMS key\"\n    else\n      inc_insecure  \"RDS instance \\\"${db}\\\" is not encrypted with a KMS key\"\n    fi\n    # Check if RDS instance is publicly accessible\n    command=\"aws rds describe-db-instances --region \\\"${aws_region}\\\" --db-instance-identifier \\\"${db}\\\" --query 'DBInstances[].PubliclyAccessible' | grep true\"\n    command_message \"${command}\"\n    check=$( eval   \"${command}\" )\n    if [ -z \"${check}\" ]; then\n      inc_secure    \"RDS instance \\\"${db}\\\" is not publicly accessible\"\n    else\n      inc_insecure  \"RDS instance \\\"${db}\\\" is publicly accessible\"\n    fi\n    # Check if RDS instance VPC is publicly accessible\n    command=\"aws rds describe-db-instances --region \\\"${aws_region}\\\" --db-instance-identifier \\\"${db}\\\" --query 'DBInstances[*].VpcSecurityGroups[].VpcSecurityGroupId' --output text\"\n    command_message \"${command}\"\n    sgs=$( eval \"${command}\" )\n    for sg in ${sgs}; do\n      check_aws_open_port  \"${sg}\" \"3306\" \"tcp\" \"MySQL\" \"RDS\" \"${db}\"\n    done\n    # Check RDS instance is not on a public subnet\n    command=\"aws rds describe-db-instances --region \\\"${aws_region}\\\" --db-instance-identifier \\\"${db}\\\" --query 'DBInstances[].DBSubnetGroup.Subnets[].SubnetIdentifier' --output text\"\n    command_message \"${command}\"\n    subnets=$( eval \"${command}\" )\n    for subnet in ${subnets}; do\n      command=\"aws ec2 describe-route-tables --region \\\"${aws_region}\\\" --filters \\\"Name=association.subnet-id,Values=$subnet\\\" --query 'RouteTables[].Routes[].DestinationCidrBlock' | grep \\\"0.0.0.0/0\\\"\"\n      command_message \"${command}\"\n      check=$( eval   \"${command}\" )\n      if [ -z \"${check}\" ]; then\n        inc_secure    \"RDS instance \\\"${db}\\\" is not on a public facing subnet\"\n      else\n        inc_insecure  \"RDS instance \\\"${db}\\\" is on a public facing subnet\"\n      fi\n    done\n    # Check that your Amazon RDS production databases are not using 'awsuser' as master \n    command=\"aws rds describe-db-instances --region \\\"${aws_region}\\\" --db-instance-identifier \\\"${db}\\\" --query 'DBInstances[].MasterUsername' | grep \\\"awsuser\\\"\"\n    command_message \"${command}\"\n    check=$( eval   \"${command}\" )\n    if [ -z \"${check}\" ]; then\n      inc_secure    \"RDS instance \\\"${db}\\\" is not using awsuser as master username\"\n    else\n      inc_insecure  \"RDS instance \\\"${db}\\\" is using awsuser as master username\"\n    fi\n  done\n}\n"
  },
  {
    "path": "modules/aws/database/audit_aws_rec_dynamodb.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_aws_rec_dynamodb\n#\n# Check DynamoDB Recommendations\n# \n# Refer to https://www.cloudconformity.com/conformity-rules/DynamoDB/unused-dynamodb-tables.html\n#.\n\naudit_aws_rec_dynamodb () {\n  # Check for zero length tables\n  print_function  \"audit_aws_rec_dynamodb\"\n  check_message   \"DynamoDB\"\n  command=\"aws dynamodb list-tables --region \\\"${aws_region}\\\" --query 'TableNames' --output text\"\n  command_message \"${command}\"\n  tables=$( eval  \"${command}\" )\n  for table in ${table}s; do\n    command=\"aws dynamodb describe-table --region \\\"${aws_region}\\\" --table-name \\\"${table}\\\" --query 'Table.ItemCount' --output text\"\n    command_message \"${command}\"\n    size=$( eval    \"${command}\" )\n    if [ ! \"${size}\" -eq 0 ]; then\n      inc_secure    \"DynamoDB table \\\"${table}\\\" is not empty\"\n    else\n      inc_insecure  \"DynamoDB table \\\"${table}\\\" is empty\"\n    fi\n  done\n}\n\n"
  },
  {
    "path": "modules/aws/database/audit_aws_rec_ec.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_aws_rec_ec\n#\n# Check ElastiCache Recommendation\n#\n# Refer to https://www.cloudconformity.com/conformity-rules/ElastiCache/reserved-cache-nodes-expiration.html\n#.\n\naudit_aws_rec_ec () {\n  print_function  \"audit_aws_rec_ec\"\n  check_message   \"ElastiCache Recommendation\"\n  # Ensure that your AWS ElastiCache Reserved Instances (RIs) are renewed before expiration\n  command=\"aws elasticache describe-reserved-cache-nodes --region \\\"${aws_region}\\\" --query 'ReservedCacheNodes[].ReservedCacheNodeId' --output text\"\n  command_message \"${command}\"\n  caches=$( eval  \"${command}\" )\n  for cache in ${caches}; do\n    command=\"aws elasticache describe-reserved-cache-nodes --region \\\"${aws_region}\\\" --reserved-cache-node-id \\\"${cache}\\\" --query 'ReservedDBInstances[].ReservedCacheNodes' --output text | cut -f1 -d.\"\n    command_message   \"${command}\"\n    start_date=$( eval \"${command}\" )\n    command=\"aws elasticache describe-reserved-cache-nodes --region \\\"${aws_region}\\\" --reserved-cache-node-id \\\"${cache}\\\" --query 'ReservedDBInstances[].Duration' --output text\"\n    command_message  \"${command}\"\n    dur_secs=$( eval \"${command}\" )\n    curr_secs=$( date \"+%s\" )\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      command=\"date -d \\\"${start_date}\\\" \\\"+%s\\\"\"\n      command_message    \"${command}\"\n      start_secs=$( eval \"${command}\" )\n    else\n      command=\"date -j -f \\\"%Y-%m-%dT%H:%M:%SS\\\" \\\"${start_date}\\\" \\\"+%s\\\"\"\n      command_message    \"${command}\"\n      start_secs=$( eval \"${command}\" )\n    fi\n    command=\"echo \\\"(${start_secs} + ${dur_secs})\\\" | bc\"\n    command_message   \"${command}\"\n    exp_secs=$( eval  \"${command}\" )\n    command=\"echo \\\"(7 * 84600)\\\" |bc\"\n    command_message   \"${command}\"\n    test_secs=$( eval \"${command}\" )\n    command=\"echo \\\"(${exp_secs} - ${curr_secs})\\\" | bc\"\n    command_message   \"${command}\"\n    left_secs=$( eval \"${command}\" )\n    if [ \"${left_secs}\" -lt \"${test_secs}\" ]; then\n      inc_secure   \"Reserved ElastiCache instance \\\"${cache}\\\" has more than 7 days remaining\"\n    else\n      inc_insecure \"Reserved ElastiCache instance \\\"${cache}\\\" has less than 7 days remaining\"\n    fi\n  done\n}"
  },
  {
    "path": "modules/aws/database/audit_aws_rec_rds.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_aws_rec_rds\n#\n# Check RDS recommendations\n#\n# Refer to https://www.cloudconformity.com/conformity-rules/RDS/rds-multi-az.html\n# Refer to https://www.cloudconformity.com/conformity-rules/RDS/general-purpose-ssd-storage-type.html\n# Refer to https://www.cloudconformity.com/conformity-rules/RDS/reserved-instance-expiration.html\n# Refer to https://www.cloudconformity.com/conformity-rules/RDS/rds-sufficient-backup-retention-period.html\n#.\n\naudit_aws_rec_rds () {\n  print_function  \"audit_aws_rec_rds\"\n  check_message   \"RDS Recommendations\"\n  command=\"aws rds describe-db-instances --region \\\"${aws_region}\\\" --query 'DBInstances[].DBInstanceIdentifier' --output text\"\n  command_message \"${command}\"\n  dbs=$( eval     \"${command}\" )\n  for db in ${dbs}; do\n    # Check if database is Multi-AZ\n    command=\"aws rds describe-db-instances --region \\\"${aws_region}\\\" --db-instance-identifier \\\"${db}\\\" --query 'DBInstances[].MultiAZ' | grep true\"\n    command_message \"${command}\"\n    check=$( eval   \"${command}\" )\n    if [ -n \"${check}\" ]; then\n      inc_secure      \"RDS instance \\\"${db}\\\" is Multi-AZ enabled\"\n    else\n      inc_insecure    \"RDS instance \\\"${db}\\\" is not Multi-AZ enabled\"\n      verbose_message \"aws rds modify-db-instance --region ${aws_region} --db-instance-identifier ${db} --multi-az --apply-immediately\" \"fix\"\n    fi\n    # Check that EC2 volumes are using cost effective storage\n    command=\"aws rds describe-db-instances --region \\\"${aws_region}\\\" --db-instance-identifier \\\"${db}\\\" --query 'DBInstances[].StorageType' |grep \\\"gp2\\\"\"\n    command_message \"${command}\"\n    check=$( eval   \"${command}\" )\n    if [ \"${check}\" = \"available\" ]; then\n      inc_secure    \"RDS instance \\\"${db}\\\" is using General Purpose SSD\"\n    else\n      inc_insecure  \"RDS instance \\\"${db}\\\" is not using General Purpose SSD\"\n    fi\n    # Check backup retention period is at least 7 days\n    command=\"aws rds describe-db-instances --region \\\"${aws_region}\\\" --db-instance-identifier \\\"${db}\\\" --query 'DBInstances[].BackupRetentionPeriod' --output text\"\n    command_message \"${command}\"\n    check=$( eval   \"${command}\" )\n    if [ ! \"${check}\" -lt \"$aws_rds_min_retention\" ]; then\n      inc_secure    \"RDS instance \\\"${db}\\\" has a retention period greater than \\\"$aws_rds_min_retention\\\"\"\n    else\n      inc_insecure  \"RDS instance \\\"${db}\\\" has a retention period less than \\\"$aws_rds_min_retention\\\"\"\n    fi\n  done\n  # Ensure that your AWS RDS Reserved Instances (RIs) are renewed before expiration\n  command=\"aws rds describe-reserved-db-instances --region \\\"${aws_region}\\\" --query 'ReservedDBInstances[].ReservedDBInstanceId' --output text\"\n  command_message \"${command}\"\n  dbs=$( eval     \"${command}\" )\n  for db in ${dbs}; do\n    command=\"aws rds describe-reserved-db-instances --region \\\"${aws_region}\\\" --reserved-db-instance-id \\\"${db}\\\" --query 'ReservedDBInstances[].StartTime' --output text |cut -f1 -d. \"\n    command_message    \"${command}\"\n    start_date=$( eval \"${command}\" )\n    command=\"aws rds describe-reserved-db-instances --region \\\"${aws_region}\\\" --reserved-db-instance-id \\\"${db}\\\" --query 'ReservedDBInstances[].Duration' --output text\"\n    command_message    \"${command}\"\n    dur_secs=$( eval   \"${command}\" )\n    command=\"date \\\"+%s\\\"\"\n    command_message    \"${command}\"\n    curr_secs=$( eval  \"${command}\" )\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      command=\"date -d \\\"${start_date}\\\" \\\"+%s\\\"\"\n      command_message    \"${command}\"\n      start_secs=$( eval \"${command}\" )\n    else\n      command=\"date -j -f \\\"%Y-%m-%dT%H:%M:%SS\\\" \\\"${start_date}\\\" \\\"+%s\\\"\"\n      command_message    \"${command}\"\n      start_secs=$( eval \"${command}\" )\n    fi\n    command=\"echo \\\"(${start_secs} + ${dur_secs})\\\" | bc\"\n    command_message   \"${command}\"\n    exp_secs=$( eval  \"${command}\" )\n    command=\"echo \\\"(7 * 84600)\\\" | bc\"\n    command_message   \"${command}\"\n    test_secs=$( eval \"${command}\" )\n    command=\"echo \\\"(${exp_secs} - ${curr_secs})\\\" | bc\"\n    command_message   \"${command}\"\n    left_secs=$( eval \"${command}\" )\n    if [ \"${left_secs}\" -lt \"${test_secs}\" ]; then\n      inc_secure   \"Reserved RDS instance \\\"${db}\\\" has more than 7 days remaining\"\n    else\n      inc_insecure \"Reserved RDS instance \\\"${db}\\\" has less than 7 days remaining\"\n    fi\n  done\n}\n"
  },
  {
    "path": "modules/aws/database/audit_aws_rec_redshift.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_aws_rec_redshift\n#\n# Check AWS Redshift recommendations\n#\n# Refer to https://www.cloudconformity.com/conformity-rules/Redshift/reserved-nodes-expiration.html\n#.\n\naudit_aws_rec_redshift () {\n  print_function  \"audit_aws_rec_redshift\"\n  check_message   \"Redshift Recommendations\"\n  command=\"aws redshift describe-reserved-nodes --region \\\"${aws_region}\\\" --query 'ReservedNodes[].ReservedNodeId' --output text\"\n  command_message \"${command}\"\n  dbs=$( eval     \"${command}\" )\n  for db in ${dbs}; do\n    command=\"aws redshift describe-reserved-nodes --region \\\"${aws_region}\\\" --reserved-node-id \\\"${dir_name}\\\" --query 'ReservedNodes[].StartTime' --output text | cut -f1 -d. \"\n    command_message    \"${command}\"\n    start_date=$( eval \"${command}\" )\n    command=\"aws redshift describe-reserved-nodes --region \\\"${aws_region}\\\" --reserved-node-id \\\"${db}\\\" --query 'ReservedNodes[].Duration' --output text\"\n    command_message    \"${command}\"\n    dur_secs=$( eval   \"${command}\" )\n    command=\"date \\\"+%s\\\"\"\n    command_message    \"${command}\"\n    curr_secs=$( eval  \"${command}\" )\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      command=\"date -d \\\"${start_date}\\\" \\\"+%s\\\"\"\n      command_message    \"${command}\"\n      start_secs=$( eval \"${command}\" )\n    else\n      command=\"date -j -f \\\"%Y-%m-%dT%H:%M:%SS\\\" \\\"${start_date}\\\" \\\"+%s\\\"\"\n      command_message    \"${command}\"\n      start_secs=$( eval \"${command}\" )\n    fi\n    command=\"echo \\\"(${start_secs} + ${dur_secs})\\\" | bc\"\n    command_message   \"${command}\"\n    exp_secs=$( eval  \"${command}\" )\n    command=\"echo \\\"(7 * 84600)\\\" | bc\"\n    command_message   \"${command}\"\n    test_secs=$( eval \"${command}\" )\n    command=\"echo \\\"(${exp_secs} - ${curr_secs})\\\" | bc\"\n    command_message   \"${command}\"\n    left_secs=$( eval \"${command}\" )\n    if [ \"${left_secs}\" -lt \"${test_secs}\" ]; then\n      inc_secure   \"Reserved Redshift instance \\\"${db}\\\" has more than 7 days remaining\"\n    else\n      inc_insecure \"Reserved Redshift instance \\\"${db}\\\" has less than 7 days remaining\"\n    fi\n  done\n}\n"
  },
  {
    "path": "modules/aws/database/audit_aws_redshift.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_aws_redshift\n#\n# Check AWS Redshift\n#\n# Refer to https://www.cloudconformity.com/conformity-rules/Redshift/cluster-allow-version-upgrade.html\n# Refer to https://www.cloudconformity.com/conformity-rules/Redshift/redshift-cluster-audit-logging-enabled.html\n# Refer to https://www.cloudconformity.com/conformity-rules/Redshift/redshift-cluster-encrypted.html\n# Refer to https://www.cloudconformity.com/conformity-rules/Redshift/redshift-cluster-encrypted-with-kms-customer-master-keys.html\n# Refer to https://www.cloudconformity.com/conformity-rules/Redshift/redshift-cluster-in-vpc.html\n# Refer to https://www.cloudconformity.com/conformity-rules/Redshift/redshift-parameter-groups-require-ssl.html\n# Refer to https://www.cloudconformity.com/conformity-rules/Redshift/redshift-cluster-publicly-accessible.html\n#.\n\naudit_aws_redshift () {\n  print_function  \"audit_aws_redshift\"\n  check_message   \"Redshift\"\n  command=\"aws redshift describe-clusters --region \\\"${aws_region}\\\" --query 'Clusters[].ClusterIdentifier' --output text\"\n  command_message \"${command}\"\n  dbs=$( eval     \"${command}\" )\n  for db in ${dbs}; do\n    # Check if version upgrades are enabled\n    command=\"aws redshift describe-clusters --region \\\"${aws_region}\\\" --cluster-identifier \\\"${db}\\\" --query 'Clusters[].AllowVersionUpgrade' | grep true\"\n    command_message   \"${command}\"\n    check=$( eval     \"${command}\" )\n    if [ -n \"${check}\" ]; then\n      inc_secure      \"Redshift instance \\\"${db}\\\" has version upgrades enabled\"\n    else\n      inc_insecure    \"Redshift instance \\\"${db}\\\" does not have version upgrades enabled\"\n      verbose_message \"aws redshift modify-cluster --region \\\"${aws_region}\\\" --cluster-identifier \\\"${db}\\\" --allow-version-upgrade\" \"fix\"\n    fi\n    # Check if audit logging is enabled\n    command=\"aws redshift describe-logging-status --region \\\"${aws_region}\\\" --cluster-identifier \\\"${db}\\\" | grep true\"\n    command_message   \"${command}\"\n    check=$( eval     \"${command}\" )\n    if [ -n \"${check}\" ]; then\n      inc_secure      \"Redshift instance \\\"${db}\\\" has logging enabled\"\n    else\n      inc_insecure    \"Redshift instance \\\"${db}\\\" does not have logging enabled\"\n      verbose_message \"aws redshift enable-logging --region \\\"${aws_region}\\\" --cluster-identifier \\\"${db}\\\" --bucket-name <aws-redshift-audit-logs>\" \"fix\"\n    fi\n    # Check if encryption is enabled\n    command=\"aws redshift describe-logging-status --region \\\"${aws_region}\\\" --cluster-identifier \\\"${db}\\\" --query 'Clusters[].Encrypted' | grep true\"\n    command_message \"${command}\"\n    check=$( eval   \"${command}\" )\n    if [ -n \"${check}\" ]; then\n      inc_secure    \"Redshift instance \\\"${db}\\\" has encryption enabled\"\n    else\n      inc_insecure  \"Redshift instance \\\"${db}\\\" does not have encryption enabled\"\n    fi\n    # Check if KMS keys are being used\n    command=\"aws redshift describe-logging-status --region \\\"${aws_region}\\\" --cluster-identifier \\\"${db}\\\" --query 'Clusters[].[Encrypted,KmsKeyId]' | grep true\"\n    command_message \"${command}\"\n    check=$( eval   \"${command}\" )\n    if [ -n \"${check}\" ]; then\n      inc_secure    \"Redshift instance \\\"${db}\\\" is using KMS keys\"\n    else\n      inc_insecure  \"Redshift instance \\\"${db}\\\" is not using KMS keys\"\n    fi\n    # Check if EC2-VPC platform is being used rather than EC2-Classic\n    command=\"aws redshift describe-logging-status --region \\\"${aws_region}\\\" --cluster-identifier \\\"${db}\\\" --query 'Clusters[].VpcId' --output text\"\n    command_message \"${command}\"\n    check=$( eval   \"${command}\" )\n    if [ -n \"${check}\" ]; then\n      inc_secure    \"Redshift instance \\\"${db}\\\" is using the EC2-VPC platform\"\n    else\n      inc_insecure  \"Redshift instance \\\"${db}\\\" may be using the EC2-Classic platform\"\n    fi\n    # Check that parameter groups require SSL\n    command=\"aws redshift describe-logging-status --region \\\"${aws_region}\\\" --cluster-identifier \\\"${db}\\\" --query 'Clusters[].ClusterParameterGroups[].ParameterGroupName[]' --output text\"\n    command_message \"${command}\"\n    groups=$( eval  \"${command}\" )\n    for group in ${groups}; do\n      command=\"aws redshift describe-cluster-parameters --region \\\"${aws_region}\\\" --parameter-group-name \\\"${group}\\\" --query 'Parameters[].Description' | grep -i ssl\"\n      command_message \"${command}\"\n      check=$( eval   \"${command}\" )\n      if [ -n \"${check}\" ]; then\n        inc_secure    \"Redshift instance \\\"${db}\\\" parameter group \\\"$group\\\" is using SSL\"\n      else\n        inc_insecure  \"Redshift instance \\\"${db}\\\" parameter group \\\"$group\\\" is not using SSL\"\n      fi\n    done\n    # Check if Redshift is publicly available\n    command=\"aws redshift describe-clusters --region \\\"${aws_region}\\\" --cluster-identifier \\\"${db}\\\" --query 'Clusters[].PubliclyAccessible' | grep true\"\n    command_message \"${command}\"\n    check=$( eval   \"${command}\" )\n    if [ -z \"${check}\" ]; then\n      inc_secure    \"Redshift instance \\\"${db}\\\" is not publicly available\"\n    else\n      inc_insecure  \"Redshift instance \\\"${db}\\\" is publicly available\"\n    fi\n  done\n}\n"
  },
  {
    "path": "modules/aws/logging/audit_aws_inspector.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_aws_inspector\n#\n# Check AWS Inspector\n#\n# Refer to https://docs.aws.amazon.com/inspector/latest/userguide/inspector_introduction.html\n#.\n\naudit_aws_inspector () {\n  # check for templates\n  print_function \"audit_aws_inspector\"\n  check_message  \"Inspector\"\n  command=\"aws inspector list-assessment-templates 2> /dev/null --output text\"\n  command_message   \"${command}\"\n  templates=$( eval \"${command}\" )\n  if [ -n \"${templates}\" ]; then\n    # check for subscriptions to templates\n    command=\"aws inspector list-event-subscriptions --region \\\"${aws_region}\\\" --query subscriptions --output text\"\n    command_message \"${command}\"\n    check=$( eval   \"${command}\" )\n    if [ \"${check}\" ]; then\n      inc_secure   \"Inspectors have subscriptions\"\n    else\n      inc_insecure \"Inspectors do not have subscriptions\"\n    fi\n    for template in ${templates}; do\n      command=\"aws inspector describe-assessment-templates --region \\\"${aws_region}\\\" --assessment-template-arns \\\"${template}\\\" --query 'assessmentTemplates[].name' --output text\"\n      command_message \"${command}\"\n      names=$( eval   \"${command}\" )\n      for name in ${ansible_value}s; do\n        command=\"aws ec2 describe-instances --region \\\"${aws_region}\\\" --query 'Reservations[].Instances[].InstanceId' --output text\"\n        command_message   \"${command}\"\n        instances=$( eval \"${command}\" )\n        for instance in ${instances}; do\n          command=\"aws ec2 describe-instances --region \\\"${aws_region}\\\" --instance-id \\\"${instance}\\\" --query 'Reservations[].Instances[].Tags' | grep \\\"${ansible_value}\\\"\"\n          command_message \"${command}\"\n          check=$( eval   \"${command}\" )\n          if [ -n \"${check}\" ]; then\n            inc_secure   \"Instance \\\"${instance}\\\" has an inspector tag\"\n          else\n            inc_insecure \"Instance \\\"${instance}\\\" does not have an inspector tag\"\n          fi\n        done\n      done\n    done\n  else\n    inc_insecure \"No inspector templates exist\"\n  fi\n}\n\n"
  },
  {
    "path": "modules/aws/logging/audit_aws_logging.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_aws_logging\n#\n# Check AWS Logging\n#\n# Refer to Section(s) 2.1 Page(s) 70-1 CIS AWS Foundations Benchmark v1.1.0\n# Refer to Section(s) 2.2 Page(s) 72-3 CIS AWS Foundations Benchmark v1.1.0\n# Refer to Section(s) 2.3 Page(s) 74-5 CIS AWS Foundations Benchmark v1.1.0\n# Refer to Section(s) 2.4 Page(s) 76-7 CIS AWS Foundations Benchmark v1.1.0\n# Refer to Section(s) 2.6 Page(s) 81-2 CIS AWS Foundations Benchmark v1.1.0\n# Refer to Section(s) 2.7 Page(s) 83-4 CIS AWS Foundations Benchmark v1.1.0\n#\n# Refer to https://www.cloudconformity.com/conformity-rules/CloudTrail/cloudtrail-s3-bucket-logging-enabled.html\n# Refer to https://www.cloudconformity.com/conformity-rules/CloudTrail/cloudtrail-bucket-mfa-delete-enabled.html\n# Refer to https://www.cloudconformity.com/conformity-rules/CloudTrail/cloudtrail-bucket-publicly-accessible.html\n# Refer to https://www.cloudconformity.com/conformity-rules/CloudTrail/cloudtrail-enabled.html\n# Refer to https://www.cloudconformity.com/conformity-rules/CloudTrail/cloudtrail-global-services-enabled.html\n# Refer to https://www.cloudconformity.com/conformity-rules/CloudTrail/cloudtrail-integrated-with-cloudwatch.html\n# Refer to https://www.cloudconformity.com/conformity-rules/CloudTrail/cloudtrail-log-file-integrity-validation.html\n# Refer to https://www.cloudconformity.com/conformity-rules/CloudTrail/cloudtrail-bucket-publicly-accessible.html\n# Refer to https://www.cloudconformity.com/conformity-rules/CloudTrail/cloudtrail-s3-bucket-logging-enabled.html\n# Refer to https://www.cloudconformity.com/conformity-rules/CloudTrail/cloudtrail-global-services-logging-duplicated.html\n#.\n\naudit_aws_logging () {\n  print_function  \"audit_aws_logging\"\n  check_message   \"CloudTrail\"\n  command=\"aws cloudtrail describe-trails --region \\\"${aws_region}\\\" --query \\\"trailList[].Name\\\" --output text\"\n  command_message \"${command}\"\n  trails=$( eval  \"${command}\" )\n  if [ \"${trails}\" ]; then\n    for trail in ${trails}; do\n      # Check CloudTrail has MultiRegion enabled\n      command=\"aws cloudtrail describe-trails --region \\\"${aws_region}\\\" --trail-name-list \\\"${trail}\\\" --query \\\"trailList[].IsMultiRegionTrail\\\" | grep true\"\n      command_message \"${command}\"\n      check=$( eval   \"${command}\" )\n      if [ -n \"${check}\" ]; then\n        inc_secure      \"CloudTrail \\\"${trail}\\\" is enabled in all regions\"\n    \telse\n        inc_insecure    \"CloudTrail \\\"${trail}\\\" is not enabled in all regions\"\n        verbose_message \"aws cloudtrail update-trail --name ${trail} --is-multi-region-trail\" fix\n      fi\n      # Check CloudTrail is recording global events\n      command=\"aws cloudtrail describe-trails --region \\\"${aws_region}\\\" --trail-name-list \\\"${trail}\\\" --query \\\"trailList[].IncludeGlobalServiceEvents\\\" | grep true\"\n      command_message \"${command}\"\n      check=$( eval   \"${command}\" )\n      if [ -n \"${check}\" ]; then\n        inc_secure      \"CloudTrail \\\"${trail}\\\" is recording global events\"\n      else\n        inc_insecure    \"CloudTrail \\\"${trail}\\\" is not recording global events\"\n        verbose_message \"aws cloudtrail update-trail --name ${trail} --include-global-service-events\" fix\n      fi\n      # Check log file validation is enabled\n      command=\"aws cloudtrail describe-trails --region \\\"${aws_region}\\\" --trail-name-list \\\"${trail}\\\" --query \\\"trailList[].LogFileValidationEnabled\\\" | grep true\"\n      command_message \"${command}\"\n      check=$( eval   \"${command}\" )\n      if [ -n \"${check}\" ]; then\n        inc_secure      \"CloudTrail \\\"${trail}\\\" log file validation is enabled\"\n      else\n        inc_insecure    \"CloudTrail \\\"${trail}\\\" log file validation is not enabled\"\n        verbose_message \"aws cloudtrail update-trail --region ${aws_region} --name ${trail} --enable-log-file-validation\" fix\n      fi\n      # \n    done\n    command=\"aws cloudtrail describe-trails --region \\\"${aws_region}\\\" --query 'trailList[*].S3BucketName' --output text\"\n    command_message \"${command}\"\n    buckets=$( eval \"${command}\" )\n    # Check that CloudTrail buckets don't grant access to users it shouldn't\n    # Check that CloudTrail bucket versioning is enable\n    for bucket in ${buckets}; do\n      command=\"aws s3api get-bucket-acl --region \\\"${aws_region}\\\" --bucket \\\"${bucket}\\\" | grep URI | grep AllUsers\"\n      command_message \"${command}\"\n      grants=$( eval   \"${command}\" )\n      if [ -n \"${grants}\" ]; then\n        inc_insecure \"CloudTrail log file bucket \\\"${bucket}\\\" grants access to Principal AllUsers\"\n      else\n        inc_secure   \"CloudTrail log file bucket \\\"${bucket}\\\" does not grant access to Principal AllUsers\"\n      fi\n      command=\"aws s3api get-bucket-acl --region \\\"${aws_region}\\\" --bucket \\\"${bucket}\\\" | grep URI | grep AuthenticatedUsers\"\n      command_message \"${command}\"\n      grants=$( eval  \"${command}\" )\n      if [ -n \"${grants}\" ]; then\n        inc_insecure    \"CloudTrail log file bucket ${bucket} grants access to Principal AuthenticatedUsers\"\n        verbose_message \"aws s3api put-bucket-acl --region ${aws_region} --region ${aws_region}--bucket ${bucket} --acl private\" fix\n      else\n        inc_secure      \"CloudTrail log file bucket ${bucket} does not grant access to Principal AuthenticatedUsers\"\n      fi\n      \n      command=\"aws s3api get-bucket-policy --region \\\"${aws_region}\\\" --bucket \\\"${bucket}\\\" --query Policy | tr \\\"}\\\" \\\"\\\\\\n\\\" | grep Allow | grep \\\"\\*\\\"\"\n      command_message \"${command}\"\n      grants=$( eval   \"${command}\" )\n      if [ -n \"${grants}\" ]; then\n        inc_insecure \"CloudTrail log file bucket \\\"${bucket}\\\" grants access to Principal *\"\n      else\n        inc_secure   \"CloudTrail log file bucket \\\"${bucket}\\\" does not grant access to Principal *\"\n      fi\n      command=\"aws s3api get-bucket-logging --region \\\"${aws_region}\\\" --bucket \\\"${bucket}\\\"\"\n      command_message \"${command}\"\n      logging=$( eval \"${command}\" )\n      if [ -z \"$logging\" ]; then\n        inc_insecure    \"CloudTrail log file bucket ${bucket} does not have access logging enabled\"\n        verbose_message \"aws s3api put-bucket-acl --region ${aws_region} --bucket ${bucket} --grant-write URI=http://acs.amazonaws.com/groups/s3/LogDelivery --grant-read-acp URI=http://acs.amazonaws.com/groups/s3/LogDelivery\" fix\n        verbose_message \"cd aws ; aws s3api put-bucket-logging --region ${aws_region} --bucket ${bucket} --bucket-logging-status file://server-access-logging.json\"\n      else\n        inc_secure      \"CloudTrail log file bucket ${bucket} has access logging enabled\"\n      fi\n      command=\"aws s3api get-bucket-versioning --bucket \\\"${bucket}\\\" | grep Enabled\"\n      command_message \"${command}\"\n      check=$( eval   \"${command}\" )\n      if [ -n \"${check}\" ]; then\n        inc_secure    \"CloudTrail log bucket \\\"${bucket}\\\" has versioning enabled\"\n      else\n        inc_insecure  \"CloudTrail bucket \\\"${bucket}\\\" does not have versioning enabled\"\n      fi\n    done\n    command=\"aws cloudtrail describe-trails --region \\\"${aws_region}\\\" --query trailList[].Name --output text\"\n    command_message   \"${command}\"\n    trails=$( eval    \"${command}\" )\n    for trail in ${trails}; do\n      # Check CloudTrail has a CloudWatch Logs group enabled\n      command=\"aws cloudtrail describe-trails --region \\\"${aws_region}\\\" --trail-name-list \\\"${trail}\\\" |grep CloudWatchLogsLogGroupArn\"\n      command_message \"${command}\"\n      check=$( eval   \"${command}\" )\n      if [ -z \"${check}\" ]; then\n        inc_insecure  \"CloudTrail ${trail} does not have a CloudWatch Logs group enabled\"\n      else\n        inc_secure    \"CloudTrail ${trail} has a CloudWatch Logs group enabled\"\n      fi\n      # Check CloudTrail bucket is receiving logs\n      command=\"aws cloudtrail get-trail-status --region \\\"${aws_region}\\\" --name \\\"${bucket}\\\" --query \\\"LatestCloudWatchLogsDeliveryTime\\\" --output text\"\n      command_message \"${command}\"\n      check=$( eval   \"${command}\" )\n      if [ -z \"${check}\" ]; then\n        inc_insecure  \"CloudTrail \\\"${trail}\\\" does not have a Last log file delivered timestamp\"\n      else\n        inc_secure    \"CloudTrail \\\"${trail}\\\" has a last log file delivered timestamp\"\n      fi\n      # Check CloudTrail has key enabled for bucket\n      command=\"aws cloudtrail get-trail-status --region \\\"${aws_region}\\\" --name \\\"${bucket}\\\" | grep KmsKeyId\"\n      command_message \"${command}\"\n      check=$( eval   \"${command}\" )\n      if [ -z \"${check}\" ]; then\n        inc_insecure  \"CloudTrail \\\"${trail}\\\" does not have a KMS Key ID\"\n      else\n        inc_secure    \"CloudTrail \\\"${trail}\\\" has a KMS Key ID\"\n      fi\n    done\n  else\n    inc_insecure \"CloudTrail is not enabled\"\n  fi\n}\n\n"
  },
  {
    "path": "modules/aws/logging/audit_aws_monitoring.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_aws_monitoring\n#\n# Check AWS monitoring\n#\n# Refer to Section(s) 3.1  Page(s) 87-9   CIS AWS Foundations Benchmark v1.1.0\n# Refer to Section(s) 3.2  Page(s) 90-2   CIS AWS Foundations Benchmark v1.1.0\n# Refer to Section(s) 3.3  Page(s) 93-6   CIS AWS Foundations Benchmark v1.1.0\n# Refer to Section(s) 3.4  Page(s) 97-9   CIS AWS Foundations Benchmark v1.1.0 \n# Refer to Section(s) 3.5  Page(s) 100-2  CIS AWS Foundations Benchmark v1.1.0 \n# Refer to Section(s) 3.6  Page(s) 103-5  CIS AWS Foundations Benchmark v1.1.0 \n# Refer to Section(s) 3.7  Page(s) 106-7  CIS AWS Foundations Benchmark v1.1.0 \n# Refer to Section(s) 3.8  Page(s) 108-10 CIS AWS Foundations Benchmark v1.1.0 \n# Refer to Section(s) 3.9  Page(s) 111-3  CIS AWS Foundations Benchmark v1.1.0 \n# Refer to Section(s) 3.10 Page(s) 114-6  CIS AWS Foundations Benchmark v1.1.0 \n# Refer to Section(s) 3.11 Page(s) 117-9  CIS AWS Foundations Benchmark v1.1.0 \n# Refer to Section(s) 3.12 Page(s) 120-2  CIS AWS Foundations Benchmark v1.1.0 \n# Refer to Section(s) 3.13 Page(s) 123-5  CIS AWS Foundations Benchmark v1.1.0 \n# Refer to Section(s) 3.14 Page(s) 126-8  CIS AWS Foundations Benchmark v1.1.0\n# Refer to https://www.cloudconformity.com/conformity-rules/CloudWatchLogs/aws-config-changes-alarm.html\n# Refer to https://www.cloudconformity.com/conformity-rules/CloudWatchLogs/authorization-failures-alarm.html\n# Refer to https://www.cloudconformity.com/conformity-rules/CloudWatchLogs/cmk-disabled-or-scheduled-for-deletion-alarm.html\n# Refer to https://www.cloudconformity.com/conformity-rules/CloudWatchLogs/cloudtrail-changes-alarm.html\n# Refer to https://www.cloudconformity.com/conformity-rules/CloudWatchLogs/console-sign-in-failures-alarm.html\n# Refer to https://www.cloudconformity.com/conformity-rules/CloudWatchLogs/ec2-instance-changes-alarm.html\n# Refer to https://www.cloudconformity.com/conformity-rules/CloudWatchLogs/iam-policy-changes-alarm.html\n# Refer to https://www.cloudconformity.com/conformity-rules/CloudWatchLogs/internet-gateway-changes-alarm.html\n# Refer to https://www.cloudconformity.com/conformity-rules/CloudWatchLogs/network-acl-changes-alarm.html\n# Refer to https://www.cloudconformity.com/conformity-rules/CloudWatchLogs/root-account-usage-alarm.html\n# Refer to https://www.cloudconformity.com/conformity-rules/CloudWatchLogs/route-table-changes-alarm.html\n# Refer to https://www.cloudconformity.com/conformity-rules/CloudWatchLogs/s3-bucket-changes-alarm.html\n# Refer to https://www.cloudconformity.com/conformity-rules/CloudWatchLogs/securitygroup-changes-alarm.html\n# Refer to https://www.cloudconformity.com/conformity-rules/CloudWatchLogs/vpc-changes-alarm.html\n#.\n\naudit_aws_monitoring () {\n  print_function  \"audit_aws_monitoring\"\n  check_message   \"CloudWatch\"\n  command=\"aws cloudtrail describe-trails --region \\\"${aws_region}\\\" --query \\\"trailList[].CloudWatchLogsLogGroupArn\\\" --output text | awk -F':' '{print \\$7}'\"\n  command_message \"${command}\"\n  trails=$( eval  \"${command}\" )\n  if [ \"${trails}\" ]; then\n    inc_secure \"CloudWatch log groups exits for CloudTrail\"\n    for trail in ${trails}; do\n      command=\"aws logs describe-metric-filters --region \\\"${aws_region}\\\" --log-group-name \\\"${trail}\\\" --query \\\"metricFilters[].filterPattern\\\" --output text\"\n      command_message \"${command}\"\n      metrics=$( eval \"${command}\" )\n      if [ ! \"${metric}\" ]; then\n        inc_insecure     \"CloudWatch log group ${trail} has no metrics\"\n        verbose_message  \"aws logs put-metric-filter --region ${aws_region} --log-group-name ${trail} --filter-name unauthorized-api-calls-metric --metric-transformations metricName=unauthorized-api-calls-metric,metricNamespace='Audit',metricValue=1 --filter-pattern '{ ($.errorCode = \\\"*UnauthorizedOperation\\\") || ($.errorCode = \\\"AccessDenied*\\\") }'\"     \"fix\"\n        verbose_message  \"aws logs put-metric-filter --region ${aws_region} --log-group-name ${trail} --filter-name no_mfa_console_signin_metric --metric-transformations metricName=no_mfa_console_signin_metric,metricNamespace='Audit',metricValue=1 --filter-pattern '{ ($.eventName = \\\"ConsoleLogin\\\") && ($.additionalEventData.MFAUsed != \\\"Yes\\\") }'\"        \"fix\"\n        verbose_message  \"aws logs put-metric-filter --region ${aws_region} --log-group-name ${trail} --filter-name root_usage_metric --metric-transformations metricName=root_usage_metric,metricNamespace='Audit',metricValue=1 --filter-pattern '{ $.userIdentity.type = \\\"Root\\\" && $.userIdentity.invokedBy NOT ${exists} && $.eventType != \\\"AwsServiceEvent\\\" }'\" \"fix\"\n        verbose_message  \"aws logs put-metric-filter --region ${aws_region} --log-group-name ${trail} --filter-name iam_changes_metric --metric-transformations metricName=iam_changes_metric,metricNamespace='Audit',metricValue=1 --filter-pattern '{($.eventName=DeleteGroupPolicy)||($.eventName=DeleteRolePolicy)||($.eventName=DeleteUserPolicy)||($.eventName=PutGroupPolicy)||($.eventName=PutRolePolicy)||($.eventName=PutUserPolicy)||($.eventName=CreatePolicy)||($.eventName=DeletePolicy)||($.eventName=CreatePolicyVersion)||($.eventName=DeletePolicyVersion)||($.eventName=AttachRolePolicy)||($.eventName=DetachRolePolicy)||($.eventName=AttachUserPolicy)||($.eventName=DetachUserPolicy)||($.eventName=AttachGroupPolicy)||($.eventName=DetachGroupPolicy)}'\" \"fix\"\n        verbose_message  \"aws logs put-metric-filter --region ${aws_region} --log-group-name ${trail} --filter-name cloudtrail_config_changes_metric --metric-transformations metricName=cloudtrail_cfg_changes_metric,metricNamespace='Audit',metricValue=1 --filter-pattern '{ ($.eventName = CreateTrail) || ($.eventName = UpdateTrail) ||($.eventName = DeleteTrail) || ($.eventName = StartLogging) || ($.eventName = StopLogging) }'\" \"fix\"\n        verbose_message  \"aws logs put-metric-filter --region ${aws_region} --log-group-name ${trail} --filter-name console_signin_failure_metric --metric-transformations metricName=console_signin_failure_metric,metricNamespace='Audit',metricValue=1 --filter-pattern '{ ($.eventName = ConsoleLogin) && ($.errorMessage = \\\"Failedauthentication\\\") }'\" \"fix\"\n        verbose_message  \"aws logs put-metric-filter --region ${aws_region} --log-group-name ${trail} --filter-name disable_or_delete_cmk_metric --metric-transformations metricName=disable_or_delete_cmk_metric,metricNamespace='Audit',metricValue=1 --filter-pattern '{($.eventSource = kms.amazonaws.com) && (($.eventName=DisableKey)||($.eventName=ScheduleKeyDeletion))}'\" \"fix\"\n        verbose_message  \"aws logs put-metric-filter --region ${aws_region} --log-group-name ${trail} --filter-name s3_bucket_policy_changes_metric --metric-transformations metricName=s3_bucket_policy_changes_metric,metricNamespace='Audit',metricValue=1 --filter-pattern '{ ($.eventSource = s3.amazonaws.com) && (($.eventName = PutBucketAcl) || ($.eventName = PutBucketPolicy) || ($.eventName = PutBucketCors) || ($.eventName = PutBucketLifecycle) || ($.eventName = PutBucketReplication) || ($.eventName = DeleteBucketPolicy) || ($.eventName = DeleteBucketCors) || ($.eventName = DeleteBucketLifecycle) || ($.eventName = DeleteBucketReplication)) }'\" \"fix\"\n        verbose_message  \"aws logs put-metric-filter --region ${aws_region} --log-group-name ${trail} --filter-name aws_config_changes_metric --metric-transformations metricName=aws_config_changes_metric,metricNamespace='Audit',metricValue=1 --filter-pattern '{($.eventSource = config.amazonaws.com) && (($.eventName=StopConfigurationRecorder)||($.eventName=DeleteDeliveryChannel)||($.eventName=PutDeliveryChannel)||($.eventName=PutConfigurationRecorder))}'\" \"fix\"\n        verbose_message  \"aws logs put-metric-filter --region ${aws_region} --log-group-name ${trail} --filter-name nacl_changes_metric --metric-transformations metricName=nacl_changes_metric,metricNamespace='Audit',metricValue=1 --filter-pattern '{ ($.eventName = CreateNetworkAcl) || ($.eventName = CreateNetworkAclEntry) || ($.eventName = DeleteNetworkAcl) || ($.eventName = DeleteNetworkAclEntry) || ($.eventName = ReplaceNetworkAclEntry) || ($.eventName = ReplaceNetworkAclAssociation) }'\" \"fix\"\n        verbose_message  \"aws logs put-metric-filter --region ${aws_region} --log-group-name ${trail} --filter-name security_group_changes_metric --metric-transformations metricName=security_group_changes_metric,metricNamespace='Audit',metricValue=1 --filter-pattern '{ ($.eventName = AuthorizeSecurityGroupIngress) || ($.eventName = AuthorizeSecurityGroupEgress) || ($.event Name = RevokeSecurityGroupIngress) || ($.eventName = RevokeSecurityGroupEgress) || ($.eventName = CreateSecurityGroup) || ($.eventName = DeleteSecurityGroup)}'\" \"fix\"\n        verbose_message  \"aws logs put-metric-filter --region ${aws_region} --log-group-name ${trail} --filter-name network_gateway_changes_metric --metric-transformations metricName=network_gw_changes_metric,metricNamespace='Audit',metricValue=1 --filter-pattern '{ ($.eventName = CreateCustomerGateway) || ($.eventName = DeleteCustomerGateway) || ($.eventName = AttachInternetGateway) || ($.eventName = CreateInternetGateway) || ($.eventName = DeleteInternetGateway) || ($.eventName = DetachInternetGateway) }'\" \"fix\"\n        verbose_message  \"aws logs put-metric-filter --region ${aws_region} --log-group-name ${trail} --filter-name route_table_changes_metric --metric-transformations metricName=route_table_changes_metric,metricNamespace='Audit',metricValue=1 --filter-pattern '{ ($.eventName = CreateRoute) || ($.eventName = CreateRouteTable) || ($.eventName = ReplaceRoute) || ($.eventName = ReplaceRouteTableAssociation) || ($.eventName = DeleteRouteTable) || ($.eventName = DeleteRoute) || ($.eventName = DisassociateRouteTable) }'\" \"fix\"\n        verbose_message  \"aws logs put-metric-filter --region ${aws_region} --log-group-name ${trail} --filter-name vpc_changes_metric --metric-transformations metricName=vpc_changes_metric,metricNamespace='Audit',metricValue=1 --filter-pattern '{ ($.eventName = CreateVpc) || ($.eventName = DeleteVpc) || ($.eventName = ModifyVpcAttribute) || ($.eventName = AcceptVpcPeeringConnection) || ($.eventName = CreateVpcPeeringConnection) || ($.eventName = DeleteVpcPeeringConnection) || ($.eventName = RejectVpcPeeringConnection) || ($.eventName = AttachClassicLinkVpc) || ($.eventName = DetachClassicLinkVpc) || ($.eventName = DisableVpcClassicLink) || ($.eventName = EnableVpcClassicLink) }'\" \"fix\"\n        verbose_message  \"aws logs put-metric-filter --region ${aws_region} --log-group-name ${trail} --filter-name ec2_changes_metric --metric-transformations metricName=ec2_changes_metric,metricNamespace='Audit',metricValue=1 --filter-pattern '{ ($.eventName = RunInstances) || ($.eventName = RebootInstances) || ($.eventName = StartInstances) || ($.eventName = StopInstances) || ($.eventName = TerminateInstances) }'\" \"fix\"\n        for sns_topic in unauthorized-api-calls no_mfa_console_signin root_usage iam_changes cloudtrail_config_changes console_signin_failure disable_or_delete_cmk \\\n                         s3_bucket_policy_changes aws_config_changes nacl_changes security_group network_gateway route_table_changes vpc_changes ec2_changes; do\n           verbose_message  \"aws sns create-topic --region ${aws_region} --name ${sns_topic}\" \"fix\"\n           verbose_message  \"aws sns subscribe --region ${aws_region} --topic-arn ${sns_topic} --protocol $sns_protocol notification-endpoint $sns_endpoints\" \"fix\" \n        done\n      else\n        for metric in UnauthorizedOperation AccessDenied ConsoleLogin additionalEventData.MFAUsed userIdentity.invokedBy AwsServiceEvent \\\n                      DeleteGroupPolicy DeleteRolePolicy DeleteUserPolicy PutGroupPolicy PutRolePolicy PutUserPolicy CreatePolicy \\\n                      DeletePolicy CreatePolicyVersion DeletePolicyVersion AttachRolePolicy DetachRolePolicy AttachUserPolicy \\\n                      DetachUserPolicy AttachGroupPolicy DetachGroupPolicy CreateTrail UpdateTrail DeleteTrail StartLogging StopLogging \\\n                      Failedauthentication DisableKey ScheduleKeyDeletion PutBucketAcl PutBucketPolicy PutBucketCors PutBucketLifecycle \\\n                      PutBucketReplication DeleteBucketPolicy DeleteBucketCors DeleteBucketLifecycle DeleteBucketReplication \\\n                      StopConfigurationRecorder DeleteDeliveryChannel PutDeliveryChannel PutConfigurationRecorder AuthorizeSecurityGroupIngress \\\n                      AuthorizeSecurityGroupEgress RevokeSecurityGroupIngress RevokeSecurityGroupEgress CreateSecurityGroup DeleteSecurityGroup \\\n                      CreateNetworkAcl CreateNetworkAclEntry DeleteNetworkAcl DeleteNetworkAclEntry ReplaceNetworkAclEntry ReplaceNetworkAclAssociation \\\n                      CreateCustomerGateway DeleteCustomerGateway AttachInternetGateway CreateInternetGateway DeleteInternetGateway DetachInternetGateway \\\n                      CreateRoute CreateRouteTable ReplaceRoute ReplaceRouteTableAssociation DeleteRouteTable DeleteRoute DisassociateRouteTable \\\n                      CreateVpc DeleteVpc ModifyVpcAttribute AcceptVpcPeeringConnection CreateVpcPeeringConnection DeleteVpcPeeringConnection \\\n                      RejectVpcPeeringConnection AttachClassicLinkVpc DetachClassicLinkVpc DisableVpcClassicLink EnableVpcClassicLink \\\n                      TerminateInstances StopInstances StartInstances RebootInstances RunInstances; do\n          command=\"aws logs describe-metric-filters --region \\\"${aws_region}\\\" --log-group-name \\\"${trail}\\\" --query \\\"metricFilters[].filterPattern\\\" --output text |grep \\\"${metric}\\\"\"\n          command_message \"${command}\"\n          check=$( eval   \"${command}\" )\n          if [ -n \"${check}\" ]; then\n            inc_secure   \"CloudWatch log group \\\"${trail}\\\" metrics include \\\"${metric}\\\"\"\n          else\n            inc_insecure \"CloudWatch log groups \\\"${trail}\\\" metrics do not include \\\"${metric}\\\"\"\n          fi\n        done\n      fi\n    done\n  else\n    inc_insecure \"No CloudWatch log groups exist for CloudTrail\"\n  fi\n  command=\"aws cloudwatch describe-alarms --region \\\"${aws_region}\\\" --query \\\"MetricAlarms[].AlarmActions\\\" --output text\"\n  command_message \"${command}\"\n  alarms=$( eval  \"${command}\" )\n  if [ \"${alarms}\" ]; then\n    inc_secure \"CloudWatch alarms exits for CloudTrail\"\n    for alarm in ${alarms}; do\n      command=\"aws sns list-subscriptions-by-topic --region \\\"${aws_region}\\\" --topic-arn \\\"${alarm}\\\" --output text\"\n      command_message     \"${command}\"\n      subscribers=$( eval \"${command}\" )\n      if [ \"${subscribers}\" ]; then\n        inc_secure   \"CloudWatch alarm \\\"${alarm}\\\" has subscribers\"\n      else\n        inc_insecure \"CloudWatch alarm \\\"${alarm}\\\" does not have subscribers\"\n      fi \n    done\n  else\n    inc_insecure \"No CloudWatch alarms exist for CloudTrail\"\n  fi\n}\n\n"
  },
  {
    "path": "modules/aws/logging/audit_aws_rec_inspector.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_aws_rec_inspector\n#\n# Check Inspector Recommendations\n#\n# Refer to https://docs.aws.amazon.com/inspector/latest/userguide/inspector_introduction.html\n#.\n\naudit_aws_rec_inspector () {\n  print_function    \"audit_aws_rec_inspector\"\n  check_message     \"Inspector Recommendations\"\n  # check for templates\n  command=\"aws inspector list-assessment-templates 2> /dev/null --output text\"\n  command_message   \"${command}\"\n  templates=$( eval \"${command}\" )\n  if [ -n \"${templates}\" ]; then\n    # Check for CVEs in assessments\n    command=\"aws inspector list-assessment-runs --region \\\"${aws_region}\\\" --output text\"\n    command_message     \"${command}\"\n    assessments=$( eval \"${command}\" )\n    if [ \"${assessments}\" ]; then\n      command=\"aws inspector list-findings --query nextToken --output text | grep -v None\"\n      command_message  \"${command}\"\n      token=$( eval    \"${command}\" )\n      command=\"aws inspector list-findings --query findingArns --output text | grep -v None\"\n      command_message  \"${command}\"\n      findings=$( eval \"${command}\" )\n      for finding in ${findings}; do\n        command=\"aws inspector describe-findings --finding-arns \\\"${finding}\\\" --query findings[].attributes[?key==\\\\\\`INSTANCE_ID\\\\\\`].value --output text\"\n        command_message  \"${command}\"\n        instance=$( eval \"${command}\" )\n        command=\"aws inspector describe-findings --finding-arns \\\"${finding}\\\" --query findings[].attributes[?key==\\\\\\`CVE_ID\\\\\\`].value --output text\"\n        command_message  \"${command}\"\n        cve_id=$( eval   \"${command}\" )\n        if [ \"${cve_id}\" ]; then\n          inc_insecure \"Instance \\\"${instance}\\\" is vulnerable to \\\"${cve_id}\\\"\"\n        fi\n      done\n      if [ -n \"${token}\" ]; then\n        while [ \"${token}\" ] ; do\n          command=\"aws inspector list-findings --next-token \\\"${token}\\\" --query findingArns --output text |grep -v None\"\n          command_message  \"${command}\"\n          findings=$( eval \"${command}\" )\n          for finding in ${findings}; do\n            command=\"aws inspector describe-findings --finding-arns \\\"${finding}\\\" --query findings[].attributes[?key==\\\\\\`INSTANCE_ID\\\\\\`].value --output text\"\n            command_message  \"${command}\"\n            instance=$( eval \"${command}\" )\n            command=\"aws inspector describe-findings --finding-arns \\\"${finding}\\\" --query findings[].attributes[?key==\\\\\\`CVE_ID\\\\\\`].value --output text\"\n            command_message  \"${command}\"\n            cve_id=$( eval   \"${command}\" )\n            if [ \"${cve_id}\" ]; then\n              inc_insecure \"Instance \\\"${instance}\\\" is vulnerable to \\\"${cve_id}\\\"\"\n            fi\n          done\n          command=\"aws inspector list-findings --next-token \\\"${token}\\\" --query nextToken --output text |grep -v None\"\n          command_message \"${command}\"\n          token=$( eval   \"${command}\" )\n        done\n      fi\n    fi\n  else\n    inc_insecure \"No inspector templates exist\"\n  fi\n}\n"
  },
  {
    "path": "modules/aws/logging/audit_aws_rec_monitoring.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_aws_rec_monitoring\n#\n# Check CloudWatch Recommendations\n#\n# Refer to https://www.cloudconformity.com/conformity-rules/CloudWatchLogs/ec2-large-instance-changes-alarm.html\n#.\n\naudit_aws_rec_monitoring () {\n  print_function    \"audit_aws_rec_monitoring\"\n  check_message     \"CloudWatch Recommendations\"\n  command=\"aws cloudtrail describe-trails --region \\\"${aws_region}\\\" --query \\\"trailList[].CloudWatchLogsLogGroupArn\\\" --output text |awk -F':' '{print \\$7}'\"\n  command_message   \"${command}\"\n  trails=$( eval    \"${command}\" )\n  if [ \"${trails}\" ]; then\n    inc_secure \"CloudWatch log groups exits for CloudTrail\"\n    for trail in ${trails}; do\n      command=\"aws logs describe-metric-filters --region \\\"${aws_region}\\\" --log-group-name \\\"${trail}\\\" --query \\\"metricFilters[].filterPattern\\\" --output text\"\n      command_message \"${command}\"\n      metrics=$( eval \"${command}\" )\n      if [ -z \"${metrics}\" ]; then\n        inc_insecure    \"CloudWatch log group \\\"${trail}\\\" has no metrics\"\n        verbose_message \"aws logs put-metric-filter --region ${aws_region} --log-group-name ${trail} --filter-name ec2_size_changes_metric --metric-transformations metricName=ec2_size_changes_metric,metricNamespace='Audit',metricValue=1 --filter-pattern '{ ($.eventName = RunInstances) && (($.requestParameters.instanceType = *.8xlarge) || ($.requestParameters.instanceType = *.4xlarge)) }'\" \"fix\"\n#        for sns_topic in ec2_size_changes; do\n#           verbose_message \"aws sns create-topic --region ${aws_region} --name ${sns_topic}\" fix\n#           verbose_message \"aws sns subscribe --region ${aws_region} --topic-arn ${sns_topic} --protocol $sns_protocol notification-endpoint $sns_endpoints\" fix \n#        done\n      else\n        for metric in RunInstances instanceType ; do\n          command=\"aws logs describe-metric-filters --region \\\"${aws_region}\\\" --log-group-name \\\"${trail}\\\" --query \\\"metricFilters[].filterPattern\\\" --output text | grep \\\"${metric}\\\"\"\n          command_message \"${command}\"\n          check=$( eval   \"${command}\" )\n          if [ -n \"${check}\" ]; then\n            inc_secure    \"CloudWatch log group \\\"${trail}\\\" metrics include \\\"${metric}\\\"\"\n          else\n            inc_insecure  \"CloudWatch log groups \\\"${trail}\\\" metrics do not include \\\"${metric}\\\"\"\n          fi\n        done\n      fi\n    done\n  else\n    inc_insecure \"No CloudWatch log groups exist for CloudTrail\"\n  fi\n}\n\n"
  },
  {
    "path": "modules/aws/logging/audit_aws_sns.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_aws_sns\n#\n# Check AWS SNS\n# \n# Refer to Section(s) 3.15 Page(s) 129-30 CIS AWS Foundations Benchmark v1.1.0\n#\n# Refer to https://www.cloudconformity.com/conformity-rules/SNS/sns-topic-exposed.html\n#.\n\naudit_aws_sns () {\n  print_function  \"audit_aws_sns\"\n  check_message   \"SNS\"\n  command=\"aws sns list-topics --region \\\"${aws_region}\\\" --query 'Topics[].TopicArn' --output text\"\n  command_message    \"${command}\"\n  topic_list=$( eval \"${command}\" )\n  for topic in ${topic_list}; do\n    # Check SNS topics have subscribers\n    command=\"aws sns list-subscriptions-by-topic --region \\\"${aws_region}\\\" --topic-arn \\\"${topic}\\\" --output text\"\n    command_message     \"${command}\"\n    subscribers=$( eval \"${command}\" )\n    if [ -z \"${subscribers}\" ]; then\n      inc_insecure \"SNS topic \\\"${topic}\\\" has no subscribers\"\n    else\n      inc_secure   \"SNS topic has subscribers, review subscribers\"\n    fi\n    #check SNS topics are not publicly accessible\n    command=\"aws sns get-topic-attributes --region \\\"${aws_region}\\\" --topic-arn \\\"${topic}\\\" --query 'Attributes.Policy'  |grep -E \\\"\\*|{\\\\\\\"AWS\\\\\\\":\\\\\\\"\\*\\\\\\\"}\\\"\"\n    command_message   \"${command}\"\n    sns_check=$( eval \"${command}\" )\n    if [ -n \"${sns_check}\" ]; then\n      inc_insecure \"SNS topic \\\"${topic}\\\" is publicly accessible\"\n    else\n      inc_secure   \"SNS topic is not publicly accessible\"\n    fi\n  done\n}\n\n"
  },
  {
    "path": "modules/aws/network/audit_aws_dns.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_aws_dns\n#\n# Check AWS DNS\n# \n# Refer to https://www.cloudconformity.com/conformity-rules/Route53/route-53-domain-auto-renew.html\n# Refer to https://www.cloudconformity.com/conformity-rules/Route53/route-53-domain-expired.html\n# Refer to https://www.cloudconformity.com/conformity-rules/Route53/sender-policy-framework-record-present.html\n# Refer to https://www.cloudconformity.com/conformity-rules/Route53/route-53-domain-transfer-lock.html\n#.\n\naudit_aws_dns () {\n  print_function  \"audit_aws_dns\"\n  check_message   \"Route53\"\n  command=\"aws route53domains list-domains --query 'Domains[].DomainName' --output text 2> /dev/null\"\n  command_message \"${command}\"\n  domains=$( eval \"${command}\" )\n  for domain in ${domains}; do\n    command=\"aws route53domains get-domain-detail --domain-name \\\"${domain}\\\" | grep true\"\n    command_message \"${command}\"\n    check=$( eval   \"${command}\" )\n    if [ -z \"${check}\" ]; then\n      inc_insecure \"Domain ${domain} does not auto renew\"\n      lock_command=\"aws route53domains enable-domain-auto-renew --domain-name ${domain}\"\n      lock_message=\"Auto-Renew on Domain \\\"${domain}\\\" to enabled\"\n      run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n    else\n      inc_secure   \"Domain \\\"${domain}\\\" auto renews\"\n    fi\n    command=\"date \\\"+%s\\\"\"\n    command_message  \"${command}\"\n    cur_secs=$( eval \"${command}\" )\n    command=\"aws route53domains get-domain-detail --domain-name \\\"${domain}\\\" --query \\\"ExpirationDate\\\" --output text 2> /dev/null\"\n    command_message  \"${command}\"\n    exp_secs=$( eval \"${command}\" )\n    if [ \"${exp_secs}\" -lt \"${cur_secs}\" ]; then\n      inc_insecure   \"Warning:   Domain \\\"${domain}\\\" registration has expired\" \n    else\n      inc_secure     \"Domain \\\"${domain}\\\" registration has not expired\"\n    fi\n    command=\"aws route53domains get-domain-detail --domain-name \\\"${domain}\\\" --query \\\"Status\\\" --output text 2> /dev/null | grep clientTransferProhibited\"\n    command_message  \"${command}\"\n    check=$( eval    \"${command}\" )\n    if [ -n \"${check}\" ]; then\n      inc_secure     \"Domain \\\"${domain}\\\" has Domain Transfer Lock enabled\"\n    else\n      inc_insecure   \"Domain \\\"${domain}\\\" does not have Domain Transfer Lock enabled\" \n    fi\n  done\n  command=\"aws route53 list-hosted-zones --query \\\"HostedZones[].Id\\\" --output text 2> /dev/null | cut -f3 -d'/'\"\n  command_message    \"${command}\"\n  zones=$( eval      \"${command}\" )\n  for zone in ${zones}; do\n    command=\"aws route53 list-resource-record-sets --hosted-zone-id \\\"${zone}\\\" --query \\\"ResourceRecordSets[?Type == 'SPF']\\\" --output text\"\n    command_message  \"${command}\"\n    spf=$( eval      \"${command}\" )\n    if [ -n \"${spf}\" ]; then\n      inc_secure     \"Zone \\\"${zone}\\\" has SPF records\"\n    else\n      inc_insecure   \"Zone \\\"${zone}\\\" does not have SPF records\" \n    fi\n  done\n}\n\n"
  },
  {
    "path": "modules/aws/network/audit_aws_rec_vpcs.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_aws_rec_vpcs\n#\n# Check AWS VPC recommendations\n#\n# Refer to https://www.cloudconformity.com/conformity-rules/VPC/vpc-naming-conventions.html\n# Refer to https://www.cloudconformity.com/conformity-rules/VPC/vpn-tunnel-redundancy.html\n#.\n\naudit_aws_rec_vpcs () {\n  print_function  \"audit_aws_rec_vpcs\"\n  check_message   \"VPC Recommendations\"\n  # Check Security Groups have Name tags\n  command=\"aws ec2 describe-vpcs --region \\\"${aws_region}\\\" --query 'Vpcs[].VpcId' --output text\"\n  command_message \"${command}\"\n  vpcs=$( eval    \"${command}\" )\n  for vpc in ${vpcs}; do\n    if [ ! \"${vpc}\" = \"default\" ]; then\n      command=\"aws ec2 describe-vpcs --region \\\"${aws_region}\\\" --vpc-ids \\\"${vpcs}\\\" --query \\\"Vpcs[].Tags[?Key==\\\\\\`Name\\\\\\`].Value\\\" 2> /dev/null --output text\"\n      command_message       \"${command}\"\n      ansible_value=$( eval \"${command}\" )\n      if [ -z \"${ansible_value}\" ]; then\n        inc_insecure    \"AWS VPC ${vpc} does not have a Name tag\"\n        verbose_message \"aws ec2 create-tags --region ${aws_region} --resources ${image} --tags Key=Name,Value=<valid_name_tag>\" \"fix\"\n      else\n        if [ \"${strict_valid_names}\" = \"y\" ]; then\n          command=\"echo \\\"${ansible_value}\\\" |grep \\\"^vpc-$valid_tag_string\\\"\"\n          command_message \"${command}\"\n          check=$( eval   \"${command}\" )\n          if [ \"${check}\" ]; then\n            inc_secure    \"AWS VPC \\\"${vpc}\\\" has a valid Name tag\"\n          else\n            inc_insecure  \"AWS VPC \\\"${vpc}\\\" does not have a valid Name tag\"\n          fi\n        fi\n      fi\n    fi\n  done\n  # Check VPN tunnel redundancy \n  command=\"aws ec2 describe-vpn-connections --region \\\"${aws_region}\\\" --query \\\"VpnConnections[].VpnConnectionId\\\" --output text\"\n  command_message \"${command}\"\n  tunnels=$( eval \"${command}\" )\n  for tunnel in ${tunnels}; do\n    command=\"aws ec2 describe-vpn-connections --region \\\"${aws_region}\\\" --vpc-connection-ids \\\"${tunnel}\\\" --query \\\"VpnConnections[].VgwTelemetry[].Status\\\" |grep \\\"DOWN\\\"\"\n    command_message \"${command}\"\n    check=$( eval   \"${command}\" )\n    if [ -n \"${check}\" ]; then\n      inc_insecure  \"AWS VPC \\\"${vpc}\\\" does not have VPN tunnel redundancy\"\n    else\n      inc_secure    \"AWS VPC \\\"${vpc}\\\" has VPN tunnel redundancy\"\n    fi\n  done\n}\n\n"
  },
  {
    "path": "modules/aws/network/audit_aws_vpcs.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_aws_vpcs\n#\n# Check VPCs\n#\n# Refer to Section(s) 4.2 Page(s) 133-4  CIS AWS Foundations Benchmark v1.1.0\n# Refer to Section(s) 4.3 Page(s) 135-7  CIS AWS Foundations Benchmark v1.1.0\n# Refer to Section(s) 4.4 Page(s) 138-40 CIS AWS Foundations Benchmark v1.1.0\n# Refer to Section(s) 4.5 Page(s) 141-2  CIS AWS Foundations Benchmark v1.1.0\n#\n# Refer http://docs.aws.amazon.com/AmazonCloudWatch/latest/DeveloperGuide/SettingLogRetention.html\n# Refer to https://www.cloudconformity.com/conformity-rules/VPC/endpoint-exposed.html\n#.\n\naudit_aws_vpcs () {\n  print_function  \"audit_aws_vpcs\"\n  check_message   \"VPCs\"\n  # Check for exposed VPC endpoints\n  command=\"aws ec2 describe-vpc-endpoints --region \\\"${aws_region}\\\" --query 'VpcEndpoints[*].VpcEndpointId' --output text\"\n  command_message       \"${command}\"\n  endpoint_list=$( eval \"${command}\" )\n  for endpoint in ${endpoint_list}; do\n    command=\"aws ec2 describe-vpc-endpoints --region \\\"${aws_region}\\\" --vpc-endpoint-ids \\\"$endpoint\\\" --query 'VpcEndpoints[].PolicyDocument' |grep Principal |grep -E \\\"\\*|{\\\\\\\"AWS\\\\\\\":\\\\\\\"\\*\\\\\\\"}\\\"\"\n\t\tcommand_message \"${command}\"\n\t\tvpc=$( eval     \"${command}\" )\n    if [ -n \"${vpc}\" ]; then\n      inc_insecure  \"VPC \\\"${vpc}\\\" has en exposed enpoint\"\n    else\n      inc_secure    \"VPC \\\"${vpc}\\\" does not have an exposed endpoint\"\n    fi\n  done\n  # Check for VPC peering\n\tcommand=\"aws ec2 describe-vpc-peering-connections --region \\\"${aws_region}\\\" --query VpcPeeringConnections --output text\"\n\tcommand_message   \"${command}\"\n\tvpc_peers=$( eval \"${command}\" )\n  if [ -z \"${vpc_peers}\" ]; then\n    inc_secure \"VPC peering is not being used\"\n  else\n    command=\"aws ec2 describe-vpcs --query Vpcs[].VpcId --output text\"\n\t\tcommand_message \"${command}\"\n\t\tvpcs=$( eval    \"${command}\" )\n    for vpc in ${vpcs}; do\n      command=\"aws ec2 describe-route-tables --region \\\"${aws_region}\\\" --filter \\\"Name=vpc-id,Values=${vpc}\\\" --query \\\"RouteTables[*].{RouteTableId:RouteTableId, VpcId:VpcId, Routes:Routes,AssociatedSubnets:Associations[*].SubnetId}\\\" | grep GatewayID | grep pcx-\"\n\t\t\tcommand_message  \"${command}\"\n\t\t\tcheck=$( eval    \"${command}\" )\n      if [ -z \"${check}\" ]; then\n        inc_secure      \"VPC \\\"${vpc}\\\" does not have a peer as it's gateway\"\n      else\n        inc_insecure    \"VPC peering is being used review VPC: \\\"${vpc}\\\"\"\n        verbose_message \"aws ec2 delete-route --region \\\"${aws_region}\\\" --route-table-id <route_table_id> --destination-cidr-block <non_compliant_destination_CIDR>\" \"fix\"\n        verbose_message \"aws ec2 create-route --region \\\"${aws_region}\\\" --route-table-id <route_table_id> --destination-cidr-block <compliant_destination_CIDR> --vpc-peering-connection-id <peering_connection_id>\" \"fix\"\n      fi\n    done\n  fi\n  # Check for VPC flow logging\n\tcommand=\"aws ec2 describe-flow-logs --region \\\"${aws_region}\\\" --query FlowLogs[].FlowLogId --output text\"\n\tcommand_message \"${command}\"\n\tlogs=$( eval    \"${command}\" )\n  if [ -n \"${logs}\" ]; then\n    command=\"aws ec2 describe-vpcs --region \\\"${aws_region}\\\" --query Vpcs[].VpcId --output text\"\n\t\tcommand_message \"${command}\"\n\t\tvpcs=$( eval    \"${command}\" )\n    for vpc in ${vpcs}; do\n      command=\"aws ec2 describe-flow-logs --region \\\"${aws_region}\\\" --query FlowLogs[].ResourceId --output text\"\n\t\t\tcommand_message   \"${command}\"\n\t\t\tvpc_check=$( eval \"${command}\" )\n      if [ \"${vpc_check}\" ]; then\n        command=\"aws ec2 describe-flow-logs --region \\\"${aws_region}\\\" --filter \\\"Name=resource-id,Values=${vpc}\\\" | grep FlowLogStatus | grep ACTIVE\"\n\t\t\t\tcommand_message      \"${command}\"\n\t\t\t\tactive_check=$( eval \"${command}\" )\n        if [ -n \"${active_check}\" ]; then\n          inc_secure   \"VPC \\\"${vpc}\\\" has active flow logs\"\n        else\n          inc_insecure \"VPC \\\"${vpc}\\\" has flow logs but they are not active\"\n        fi\n      else\n        inc_insecure   \"VPC \\\"${vpc}\\\" does not have flow logs\"\n      fi\n    done\n  else\n    inc_insecure \"There are no VPC flow logs\"\n  fi\n}\n\n"
  },
  {
    "path": "modules/aws/security/audit_aws_access_keys.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_aws_access_keys\n# \n# Check AWS Access Keys\n#\n# Refer to Section(s) 1.23 Page(s) 66-7 CIS AWS Foundations Benchmark v1.1.0\n#.\n\naudit_aws_access_keys () {\n  print_function  \"audit_aws_access_keys\"\n  check_message   \"Access Keys\"\n  command=\"aws iam generate-credential-report > /dev/null 2>&1\"\n  command_message \"${command}\"\n  eval \"${command}\"\n  command=\"aws iam get-credential-report --query 'Content' --output text | \\\"${base64_d}\\\" | cut -d, -f1,4,9,11,14,16 | sed '1 d' | grep -v '<root_account>' | awk -F '\\\\\\n' '{print \\$1}'\"\n  command_message \"${command}\"\n  eval \"${command}\"\n  for entry in ${entries}; do\n    aws_user=$(  echo \"${entry}\" | cut -d, -f1 )\n    key1_use=$(  echo \"${entry}\" | cut -d, -f3 )\n    key1_last=$( echo \"${entry}\" | cut -d, -f4 )\n    key2_use=$(  echo \"${entry}\" | cut -d, -f5 )\n    key2_last=$( echo \"${entry}\" | cut -d, -f6 )\n    if [ \"${key1_use}\" = \"true\" ] && [ \"${key1_last}\" = \"N/A\" ]; then\n      inc_insecure \"Account \\\"${aws_user}\\\" has key access enabled but has not used their AWS API credentials consider removing keys\"\n      command=\"aws iam list-access-keys --user-name \\\"${aws_user}\\\" --query \\\"AccessKeyMetadata[].{AccessKeyId:AccessKeyId, Status:Status}\\\" --output text | grep Active | awk '{print \\$1}'\"\n      command_message \"${command}\"\n      key_ids=$( eval \"${command}\" )\n      for key_id in ${key_ids}; do\n        lock_command=\"aws iam delete-access-key --access-key \\\"${key_id}\\\" --user-name \\\"${aws_user}\\\"\"\n        lock_message=\"Key \\\"${key_id}\\\" for user \\\"${aws_user}\\\" to disabled\"\n        run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n      done\n    else\n      inc_secure   \"Account \\\"${aws_user}\\\" has key access enabled and has used their AWS API credentials\"\n    fi\n    if [ \"${key2_use}\" = \"true\" ] && [ \"${key2_last}\" = \"N/A\" ]; then\n      inc_insecure \"Account \\\"${aws_user}\\\" has key access enabled but has not used their AWS API credentials consider removing keys\"\n    else\n      inc_secure   \"Account \\\"${aws_user}\\\" has key access enabled and has used their AWS API credentials\"\n    fi\n  done\n}"
  },
  {
    "path": "modules/aws/security/audit_aws_certs.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_aws_certs\n#\n# Check AWS Certificates\n#\n# Refer to https://www.cloudconformity.com/conformity-rules/IAM/expired-ssl-tls-certificate.html\n#.\n\naudit_aws_certs () {\n  print_function   \"audit_aws_certs\"\n  check_message    \"Certificates\"\n  command=\"aws iam list-server-certificates --region \\\"${aws_region}\\\" --query \\\"ServerCertificateMetadataList[].ServerCertificateName\\\" --output text\"\n  command_message  \"${command}\"\n  certs=$( eval    \"${command}\" )\n  command=\"date \\\"+%Y-%m-%dT%H:%M:%SS\\\"\"\n  command_message  \"${command}\"\n  cur_date=$( eval \"${command}\" )\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    command=\"date -d \\\"${cur_date}\\\" \\\"+%s\\\"\"\n    command_message  \"${command}\"\n    cur_secs=$( eval \"${command}\" )\n  else\n    command=\"date -j -f \\\"%Y-%m-%dT%H:%M:%SS\\\" \\\"${cur_date}\\\" \\\"+%s\\\"\"\n    command_message  \"${command}\"\n    cur_secs=$( eval \"${command}\" )\n  fi\n  for cert in ${certs}; do\n    command=\"aws iam get-server-certificate --server-certificate-name \\\"${cert}\\\" --query \\\"ServerCertificate.ServerCertificateMetadata.Expiration\\\" --output text\"\n    command_message  \"${command}\"\n    exp_date=$( eval \"${command}\" )\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      command=\"date -d \\\"${exp_date}\\\" \\\"+%s\\\"\"\n      command_message  \"${command}\"\n      exp_secs=$( eval \"${command}\" )\n    else\n      command=\"date -j -f \\\"%Y-%m-%dT%H:%M:%SZ\\\" \\\"${exp_date}\\\" \\\"+%s\\\"\"\n      command_message  \"${command}\"\n      exp_secs=$( eval \"${command}\" )\n    fi\n    if [ \"${exp_secs}\" -lt \"${cur_secs}\" ]; then\n      inc_insecure \"Certificate \\\"${cert}\\\" has expired\"\n    else\n      inc_secure   \"Certificate \\\"${cert}\\\" has not expired\"\n    fi\n  done\n}\n"
  },
  {
    "path": "modules/aws/security/audit_aws_creds.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_aws_creds\n#\n# Check AWS Credentials\n#\n# Refer to Section(s) 1.3  Page(s) 15-6 CIS AWS Foundations Benchmark v1.1.0\n# Refer to Section(s) 1.4  Page(s) 17-8 CIS AWS Foundations Benchmark v1.1.0\n# Refer to Section(s) 1.12 Page(s) 33-4 CIS AWS Foundations Benchmark v1.1.0\n#.\n\naudit_aws_creds () {\n  print_function  \"audit_aws_creds\"\n  check_message   \"Credentials\"\n  command=\"aws iam generate-credential-report > /dev/null 2>&1\"\n  command_message \"${command}\"\n  eval \"${command}\"\n  command=\"aws iam get-credential-report --query 'Content' --output text | \\\"${base64_d}\\\" | cut -d, -f1,4,5,6,9,10,11,14,15,16 | sed '1 d' | awk -F '\\\\\\n' '{print \\$1}'\"\n  command_message \"${command}\"\n  entries=$( eval \"${command}\" )\n  for entry in ${entries}; do\n    aws_user=$(  echo \"${entry}\" | cut -d, -f1 )\n    aws_pass=$(  echo \"${entry}\" | cut -d, -f2 )\n    aws_last=$(  echo \"${entry}\" | cut -d, -f3 )\n    aws_rot=$(   echo \"${entry}\" | cut -d, -f4 )\n    key1_use=$(  echo \"${entry}\" | cut -d, -f5 )\n    key1_rot=$(  echo \"${entry}\" | cut -d, -f6 )\n    key1_last=$( echo \"${entry}\" | cut -d, -f7 )\n    key2_use=$(  echo \"${entry}\" | cut -d, -f8 )\n    key2_rot=$(  echo \"${entry}\" | cut -d, -f9 )\n    key2_last=$( echo \"${entry}\" | cut -d, -f10 )\n    cur_sec=$(   date \"+%s\" )\n    if [ \"${aws_user}\" = \"<root_account>\" ]; then\n      if [ \"${key1_use}\" = \"true\" ] || [ \"${key2_use}\" = \"true\" ]; then\n        inc_insecure \"Account \\\"${aws_user}\\\" is using access keys\"\n      else\n        inc_secure   \"Account \\\"${aws_user}\\\" isn't using access keys\"\n      fi\n    else\n      if [ \"${aws_pass}\" = \"false\" ] && [ \"${key1_use}\" = \"false\" ] && [ \"${key2_use}\" = \"false\" ]; then\n          inc_insecure  \"Account \\\"${aws_user}\\\" does not use any AWS credentials consider removing account\"\n      else\n        if [ \"${aws_pass}\" = \"true\" ]; then \n          a_test=$( echo \"${aws_last}\" |grep \"[0-9]\" )\n          if [ -n \"$a_test\" ]; then\n            if [ \"${os_name}\" = \"Linux\" ]; then\n              command=\"date -d \\\"${aws_last}\\\" \\\"+%s\\\"\"\n              command_message \"${command}\"\n              aws_sec=$( eval \"${command}\" )\n            else\n              command=\"date -j -f \\\"%Y-%m-%dT%H:%M:%S+00:00\\\" \\\"${aws_last}\\\" \\\"+%s\\\"\"\n              command_message \"${command}\"\n              aws_sec=$( eval \"${command}\" )\n            fi\n            aws_days=$( echo \"(${cur_sec} - ${aws_sec})/84600\" | bc )\n            if [ \"$aws_days\" -gt 90 ]; then\n              inc_insecure    \"Account ${aws_user} has not used AWS Console credentials in over 90 days consider locking access\"\n            else\n              inc_secure      \"Account ${aws_user} has used AWS Console credentials in the past 90 days\"\n            fi\n          fi\n          a_test=$( echo \"${aws_rot}\" |grep \"[0-9]\" )\n          if [ -n \"$a_test\" ]; then\n            if [ \"${os_name}\" = \"Linux\" ]; then\n              command=\"date -d \\\"${aws_last}\\\" \\\"+%s\\\"\"\n              command_message \"${command}\"\n              rot_sec=$( eval \"${command}\" )\n            else\n              command=\"date -j -f \\\"%Y-%m-%dT%H:%M:%S+00:00\\\" \\\"${aws_last}\\\" \\\"+%s\\\"\"\n              command_message \"${command}\"\n              rot_sec=$( eval \"${command}\" )\n            fi\n            rot_days=$(  echo \"(${rot_sec} - ${cur_sec})/84600\" | bc )\n            if [ \"${rot_days}\" -gt 90 ]; then\n              inc_insecure \"Account \\\"${aws_user}\\\" will not rotate their AWS Console password in the next 90 days consider locking access\"\n            else\n              inc_secure   \"Account \\\"${aws_user}\\\" will rotate their AWS Console password in the past 90 days\"\n            fi\n          else\n            inc_insecure   \"Account \\\"${aws_user}\\\" will not rotate their AWS Console password in the next 90 days consider locking access\"\n          fi\n        fi\n        if [ \"${key1_use}\" = \"true\" ]; then\n          if [ \"${os_name}\" = \"Linux\" ]; then\n            command=\"date -d \\\"${key1_last}\\\" \\\"+%s\\\"\"\n            command_message  \"${command}\"\n            key1_sec=$( eval \"${command}\" )\n          else\n            command=\"date -j -f \\\"%Y-%m-%dT%H:%M:%S+00:00\\\" \\\"${key1_last}\\\" \\\"+%s\\\"\"\n            command_message  \"${command}\"\n            key1_sec=$( eval \"${command}\" )\n          fi\n          key1_days=$( echo \"(${cur_sec} - ${key1_sec})/84600\" | bc )\n          if [ \"${key1_days}\" -gt 90 ]; then\n            inc_insecure \"Account \\\"${aws_user}\\\" has not used AWS API credentials in over 90 days consider removing keys\"\n          else\n            inc_secure   \"Account \\\"${aws_user}\\\" has used AWS API credentials in the past 90 days\"\n          fi\n          k_test=$( echo \"${key1_rot}\" |grep \"[0-9]\" )\n          if [ -n \"${k_test}\" ]; then\n            if [ \"${os_name}\" = \"Linux\" ]; then\n              command=\"date -d \\\"${key1_rot}\\\" \\\"+%s\\\"\"\n              command_message \"${command}\"\n              rot_sec=$( eval \"${command}\" )\n            else\n              command=\"date -j -f \\\"%Y-%m-%dT%H:%M:%S+00:00\\\" \\\"${key1_rot}\\\" \\\"+%s\\\"\"\n              command_message \"${command}\"\n              rot_sec=$( eval \"${command}\" )\n            fi\n            rot_days=$( echo \"(${cur_sec} - ${rot_sec})/84600\" | bc )\n            if [ \"${rot_days}\" -gt 90 ]; then\n              inc_insecure \"Account \\\"${aws_user}\\\" will not rotate their AWS API credentials in the next 90 days\"\n            else\n              inc_secure   \"Account \\\"${aws_user}\\\" has rotated their AWS API credentials in the last 90 days\"\n            fi\n          else\n            inc_insecure   \"Account \\\"${aws_user}\\\" will not rotate their AWS API credentials in the next 90 days\"\n          fi\n        fi\n        if [ \"${key2_use}\" = \"true\" ]; then\n          if [ \"${os_name}\" = \"Linux\" ]; then\n            command=\"date -d \\\"${key2_last}\\\" \\\"+%s\\\"\"\n            command_message  \"${command}\"\n            key2_sec=$( eval \"${command}\" )\n          else\n            command=\"date -j -f \\\"%Y-%m-%dT%H:%M:%S+00:00\\\" \\\"${key2_last}\\\" \\\"+%s\\\"\"\n            command_message  \"${command}\"\n            key2_sec=$( eval \"${command}\" )\n          fi\n          key2_days=$(  echo \"(${cur_sec} - ${key2_sec})/84600\" | bc )\n          if [ \"${key2_days}\" -gt 90 ]; then\n            inc_insecure \"Account \\\"${aws_user}\\\" has not used AWS SOA credentials in over 90 days consider removing keys\"\n          else\n            inc_secure   \"Account \\\"${aws_user}\\\" has used AWS SOA credentials in the past 90 days\"\n          fi\n          k_test=$( echo \"${key2_rot}\" |grep \"[0-9]\" )\n          if [ -n \"${k_test}\" ]; then\n            if [ \"${os_name}\" = \"Linux\" ]; then\n              command=\"date -d \\\"${key2_rot}\\\" \\\"+%s\\\"\"\n              command_message \"${command}\"\n              rot_sec=$( eval \"${command}\" )\n            else\n              command=\"date -j -f \\\"%Y-%m-%dT%H:%M:%S+00:00\\\" \\\"${key2_rot}\\\" \\\"+%s\\\"\"\n              command_message \"${command}\"\n              rot_sec=$( eval \"${command}\" )\n            fi\n            rot_days=$( echo \"(${cur_sec} - ${rot_sec})/84600\" | bc )\n            if [ \"${rot_days}\" -gt 90 ]; then\n              inc_insecure \"Account \\\"${aws_user}\\\" will not rotate their AWS SOA credentials in the next 90 days\"\n            else\n              inc_secure   \"Account \\\"${aws_user}\\\" has rotated their AWS SOA credentials in the last 90 days\"\n            fi\n          else\n            inc_insecure   \"Account \\\"${aws_user}\\\" will not rotate their AWS SOA credentials in the next 90 days\"\n          fi\n        fi\n      fi\n    fi\n  done\n}\n\n"
  },
  {
    "path": "modules/aws/security/audit_aws_iam.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_aws_iam\n#\n# Check AWS IAM\n#\n# Refer to Section(s) 1.1  Page(s) 10-1  CIS AWS Foundations Benchmark v1.1.0\n# Refer to Section(s) 1.18 Page(s) 46-57 CIS AWS Foundations Benchmark v1.1.0\n#\n# Refer to http://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html\n# Refer to https://www.cloudconformity.com/conformity-rules/IAM/unused-iam-group.html\n# Refer to https://www.cloudconformity.com/conformity-rules/IAM/unused-iam-user.html\n# Refer to https://www.cloudconformity.com/conformity-rules/IAM/iam-user-policies.html\n#.\n\naudit_aws_iam () {\n  # Root account should only be used sparingly, admin functions and responsibilities should be delegated\n  print_function  \"audit_aws_iam\"\n  check_message   \"IAM\"\n  command=\"aws iam generate-credential-report > /dev/null 2>&1\"\n  command_message \"${command}\"\n  eval \"${command}\"\n  command=\"date +%Y-%m\"\n  command_message    \"${command}\"\n  date_test=$( eval  \"${command}\" )\n  command=\"aws iam get-credential-report --query 'Content' --output text | \\\"${base64_d}\\\" | cut -d, -f1,5,11,16 | grep -B1 '<root_account>' | cut -f2 -d, | cut -f1,2 -d- | grep '[0-9]'\"\n  command_message    \"${command}\"\n  last_login=$( eval \"${command}\" )\n  if [ \"${date_test}\" = \"${last_login}\" ]; then\n    inc_insecure \"Root account appears to be being used regularly\"\n  else\n    inc_secure   \"Root account does not appear to be being used frequently\"\n  fi\n  # Check to see if there is an IAM master role\n  command=\"aws iam get-role --role-name \\\"${aws_iam_master_role}\\\" 2> /dev/null\"\n  command_message  \"${command}\"\n  check=$( eval    \"${command}\" )\n  if [ -n \"${check}\" ]; then \n    inc_secure     \"IAM Master role \\\"${aws_iam_master_role}\\\" ${exists}\"\n  else\n    inc_insecure    \"IAM Master role \\\"${aws_iam_master_role}\\\" does not exist\"\n    verbose_message \"cd aws\" \"fix\"\n    verbose_message \"aws iam create-role --role-name ${aws_iam_master_role} --assume-role-policy-document file://account-creation-policy.json\" \"fix\"\n    verbose_message \"aws iam put-role-policy --role-name ${aws_iam_master_role} --policy-name ${aws_iam_master_role} --policy-document file://iam-master-policy.json\" \"fix\"\n  fi\n  # Check there is an IAM manager role\n  command=\"aws iam get-role --role-name \\\"${aws_iam_manager_role}\\\" 2> /dev/null\"\n  command_message   \"${command}\"\n  check=$( eval     \"${command}\" )\n  if [ -n \"${check}\" ]; then \n    inc_secure      \"IAM Manager role \\\"${aws_iam_manager_role}\\\" ${exists}\"\n  else\n    inc_insecure    \"IAM Manager role \\\"${aws_iam_manager_role}\\\" does not exist\"\n    verbose_message \"cd aws\" \"fix\"\n    verbose_message \"aws iam create-role --role-name ${aws_iam_master_role} --assume-role-policy-document file://account-creation-policy.json\" \"fix\"\n    verbose_message \"aws iam put-role-policy --role-name ${aws_iam_manager_role} --policy-name ${aws_iam_manager_role} --policy-document file://iam-manager-policy.json\" \"fix\"\n  fi\n  # Check groups have members\n  command=\"aws iam list-groups --query 'Groups[].GroupName' --output text\"\n  command_message   \"${command}\"\n  groups=$( eval    \"${command}\" )\n  for group in ${groups}; do\n    command=\"aws iam get-group --group-name \\\"${group}\\\" --query \\\"Users\\\" --output text\"\n    command_message \"${command}\"\n    users=$( eval   \"${command}\" )\n    if [ -n \"${users}\" ]; then\n      inc_secure    \"IAM group \\\"${group}\\\" is not empty\"\n    else\n      inc_insecure  \"IAM group \\\"${group}\\\" is empty\"\n    fi\n  done\n  command=\"aws iam list-users --query 'Users[].UserName' --output text\"\n  command_message   \"${command}\"\n  users=$( eval     \"${command}\" )\n  for user in ${users}; do\n    # Check for inactive users\n    command=\"aws iam list-access-keys --user-name \\\"${user}\\\" --query \\\"AccessKeyMetadata\\\" --output text\"\n    command_message \"${command}\"\n    check=$( eval   \"${command}\" )\n    if [ -n \"${check}\" ]; then\n      inc_secure      \"IAM user \\\"${user}\\\" is active\"\n    else\n      inc_insecure    \"IAM user \\\"${user}\\\" is not active\"\n      verbose_message \"aws iam delete-user --user-name ${user}\" \"fix\"\n    fi\n    # Check users do not have attached policies, they should be members of groups which have those policies\n    command=\"aws iam list-attached-user-policies --user-name \\\"${user}\\\" --query \\\"AttachedPolicies[].PolicyArn\\\" --output text\"\n    command_message   \"${command}\"\n    policies=$( eval  \"${command}\" )\n    if [ -n \"${policies}\" ]; then\n      for policy in ${policies}; do\n        inc_insecure    \"IAM user \\\"${user}\\\" has attached policy \\\"${policy}\\\"\"\n        verbose_message \"aws iam detach-user-policy --user-name ${user} --policy-arn ${policy}\" \"fix\"\n      done\n    else\n      inc_secure \"IAM user \\\"${user}\\\" does not have attached policies\"\n    fi\n  done\n}\n\n"
  },
  {
    "path": "modules/aws/security/audit_aws_keys.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_aws_keys\n#\n# Check AWS KMS Keyd\n#\n# Refer to Section(s) 2.8 Page(s) 85-6 CIS AWS Foundations Benchmark v1.1.0\n#\n# Refer to https://www.cloudconformity.com/conformity-rules/IAM/unnecessary-ssh-public-keys.html\n# Refer to https://www.cloudconformity.com/conformity-rules/KMS/key-rotation-enabled.html\n# Refer to https://www.cloudconformity.com/conformity-rules/KMS/unused-customer-master-key.html\n#.\n\naudit_aws_keys () {\n  print_function  \"audit_aws_keys\"\n  check_message   \"KMS Keys\"\n  command=\"aws kms list-keys --query Keys --output text\"\n  command_message \"${command}\"\n  keys=$( eval    \"${command}\" )\n  if [ \"${keys}\" ]; then\n    for key in ${keys}; do\n      # Check key is enabled\n      command=\"aws kms get-key-rotation-status --key-id \\\"${key}\\\" --query 'KeyMetadata' | grep Enabled | grep true\"\n      command_message \"${command}\"\n      check=$( eval   \"${command}\" )\n      if [ ! \"${check}\" ]; then\n        inc_insecure    \"Key \\\"${key}\\\" is not enabled\"\n        verbose_message \"aws kms schedule-key-deletion --key-id ${key} --pending-window-in-days $aws_days_to_key_deletion\" \"fix\"\n      else\n        inc_secure      \"Key \\\"${key}\\\" is enabled\"\n      fi\n      # Check that key rotation is enabled\n      command=\"aws kms get-key-rotation-status --key-id \\\"${key}\\\" |grep KeyRotationEnabled | grep true\"\n      command_message \"${command}\"\n      check=$( eval   \"${command}\" )\n      if [ ! \"${check}\" ]; then\n        inc_insecure    \"Key \\\"${key}\\\" does not have key rotation enabled\"\n        verbose_message \"aws cloudtrail update-trail --name <trail_name> --kms-id <cloudtrail_kms_key> aws kms put-key-policy --key-id <cloudtrail_kms_key> --policy <cloudtrail_kms_key_policy>\" \"fix\"\n        verbose_message \"aws kms enable-key-rotation --key-id <cloudtrail_kms_key>\" \"fix\"\n      else\n        inc_secure      \"Key \\\"${key}\\\" has rotation enabled\"\n      fi\n    done\n  else\n    inc_insecure \"No Keys are being used\"\n  fi\n  # Check for SSH keys\n  command=\"aws iam list-users --query 'Users[].UserName' --output text\"\n  command_message \"${command}\"\n  users=$( eval   \"${command}\" )\n  for user in ${users}; do\n    command=\"aws iam list-ssh-public-keys --region \\\"${aws_region}\\\" --user-name \\\"${user}\\\" | grep -c Active\"\n    command_message \"${command}\"\n    check=$( eval   \"${command}\" )\n    if [ \"${check}\" -gt 1 ]; then\n      inc_insecure  \"User \\\"${user}\\\" does has more than one active SSH key\"\n    else\n      if [ \"${check}\" -eq 0 ]; then\n        inc_secure  \"User \\\"${user}\\\" does not have any active SSH key\"\n      else\n        inc_secure  \"User \\\"${user}\\\" does not have more than one active SSH key\"\n      fi\n    fi \n  done\n}\n\n"
  },
  {
    "path": "modules/aws/security/audit_aws_mfa.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_aws_mfa\n#\n# Check AWS MFA\n#\n# Refer to Section(s) 1.2  Page(s) 12-4 CIS AWS Foundations Benchmark v1.1.0\n# Refer to Section(s) 1.13 Page(s) 35-6 CIS AWS Foundations Benchmark v1.1.0\n# Refer to Section(s) 1.14 Page(s) 37-8 CIS AWS Foundations Benchmark v1.1.0\n#\n# Refer to http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_mfa.html\n# Refer to http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_mfa_enable_virtual.html\n# Refer to http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_mfa_enable_physical.html#enable-hw-mfa-for-root\n#.\n\naudit_aws_mfa () {\n  print_function \"audit_aws_mfa\"\n  check_message  \"MFA\"\n  command=\"aws iam get-credential-report --query 'Content' --output text | \\\"${base64_d}\\\" | cut -d, -f1,4,8 | sed '1 d' | awk -F '\\\\\\n' '{print \\$1}'\"\n  command_message \"${command}\"\n  entries=$( eval \"${command}\" )\n  for entry in ${entries}; do\n    user=$( echo \"${entry}\" | cut -d, -f1 )\n    pass=$( echo \"${entry}\" | cut -d, -f2 )\n    mfa=$(  echo \"${entry}\" | cut -d, -f3 )\n    if [ \"${user}\" = \"<root_account>\" ]; then\n      if [ \"${mfa}\" = \"false\" ]; then\n        inc_insecure \"Account \\\"${user}\\\" does not have MFA enabled\"\n      else\n        inc_secure   \"Account \\\"${user}\\\" has MFA enabled\"\n      fi\n    else\n      if [ \"${pass}\" != \"false\" ]; then\n        if [ \"${mfa}\" = \"false\" ]; then\n          inc_insecure \"Account \\\"${user}\\\" does not have MFA enabled\"\n        else\n          inc_secure   \"Account \\\"${user}\\\" has MFA enabled\"\n        fi\n      else\n        inc_secure   \"Account \\\"${user}\\\" does not log into console\"\n      fi\n    fi\n  done\n  command=\"aws iam get-account-summary | grep \\\"AccountMFAEnabled\\\" | cut -f1 -d: | sed \\\"s/ //g\\\" | sed \\\"s/,//g\\\"\"\n  command_message \"${command}\"\n  check=$( eval   \"${command}\" )\n  if [ \"${check}\" = \"1\" ]; then\n    inc_secure \"The root account has MFA enabled\"\n    command=\"iaws iam list-virtual-mfa-devices | grep \\\"SerialNumber\\\" | grep -c \\\"root_account\\\"\"\n    command_message \"${command}\"\n    check=$( eval   \"${command}\" )\n    if [ \"${check}\" = \"0\" ]; then\n      inc_secure    \"The root account does not have a virtual MFA\"\n    else\n      inc_insecure  \"The root account does not have a hardware MFA\"\n    fi\n  else\n    inc_insecure    \"The root account does not have MFA enabled\"\n    inc_insecure    \"The root account does not a hardware MFA\"\n  fi\n}"
  },
  {
    "path": "modules/aws/security/audit_aws_password_policy.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_aws_password_policy\n#\n# Check AWS Password Policy\n#\n# Refer to Section(s) 1.5 Page(s)  19-20 CIS AWS Foundations Benchmark v1.1.0\n# Refer to Section(s) 1.6 Page(s)  21-22 CIS AWS Foundations Benchmark v1.1.0\n# Refer to Section(s) 1.7 Page(s)  23-24 CIS AWS Foundations Benchmark v1.1.0\n# Refer to Section(s) 1.8 Page(s)  25-26 CIS AWS Foundations Benchmark v1.1.0\n# Refer to Section(s) 1.9 Page(s)  27-28 CIS AWS Foundations Benchmark v1.1.0\n# Refer to Section(s) 1.10 Page(s) 29-30 CIS AWS Foundations Benchmark v1.1.0\n# Refer to Section(s) 1.11 Page(s) 31-32 CIS AWS Foundations Benchmark v1.1.0\n#.\n\naudit_aws_password_policy () {\n  print_function  \"audit_aws_password_policy\"\n  check_message   \"Password Policy\"\n  command=\"aws iam get-account-password-policy 2> /dev/null\"\n  command_message \"${command}\"\n  policy=$( eval  \"${command}\" )\n  command=\"echo \\\"${policy}\\\" | wc -l | sed \\\"s/ //g\\\"\"\n  command_message \"${command}\"\n  length=$( eval  \"${command}\" )\n  if [ \"${length}\" = \"0\" ]; then\n    inc_insecure \"No password policy ${exists}\"\n    fix_message  \"aws iam update-account-password-policy --require-uppercase-characters\"\n    fix_message  \"aws iam update-account-password-policy --require-lowercase-characters\"\n    fix_message  \"aws iam update-account-password-policy --require-symbols\"\n    fix_message  \"aws iam update-account-password-policy --require-numbers\"\n    fix_message  \"aws iam update-account-password-policy --minimum-password-length 14\"\n    fix_message  \"aws iam update-account-password-policy --password-reuse-prevention 24\"\n    fix_message  \"aws iam update-account-password-policy --max-password-age 90\"\n  else\n    check_aws_password_policy \"RequireUppercaseCharacters\" \"true\" \"--require-uppercase-characters\"\n    check_aws_password_policy \"RequireLowercaseCharacters\" \"true\" \"--require-lowercase-characters\"\n    check_aws_password_policy \"RequireSymbols\"             \"true\" \"--require-symbols\"\n    check_aws_password_policy \"RequireNumbers\"             \"true\" \"--require-numbers\"\n    check_aws_password_policy \"MinimumPasswordLength\"      \"14\"   \"--minimum-password-length 14\"\n    check_aws_password_policy \"PasswordReusePrevention\"    \"24\"   \"--password-reuse-prevention 24\"\n    check_aws_password_policy \"MaxPasswordAge\"             \"90\"   \"--max-password-age 90\"\n  fi\n}\n\n"
  },
  {
    "path": "modules/aws/security/audit_aws_sgs.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_aws_sgs\n#\n# Check AWS Security Groups\n#\n# Refer to https://www.cloudconformity.com/conformity-rules/EC2/security-group-ingress-any.html\n# Refer to https://www.cloudconformity.com/conformity-rules/EC2/unrestricted-ssh-access.html\n# Refer to https://www.cloudconformity.com/conformity-rules/EC2/unrestricted-rdp-access.html\n# Refer to https://www.cloudconformity.com/conformity-rules/EC2/unrestricted-cifs-access.html\n# Refer to https://www.cloudconformity.com/conformity-rules/EC2/unrestricted-dns-access.html\n# Refer to https://www.cloudconformity.com/conformity-rules/EC2/unrestricted-ftp-access.html\n# Refer to https://www.cloudconformity.com/conformity-rules/EC2/unrestricted-mongodb-access.html\n# Refer to https://www.cloudconformity.com/conformity-rules/EC2/unrestricted-netbios-access.html\n# Refer to https://www.cloudconformity.com/conformity-rules/EC2/unrestricted-rpc-access.html\n# Refer to https://www.cloudconformity.com/conformity-rules/EC2/unrestricted-icmp-access.html\n# Refer to https://www.cloudconformity.com/conformity-rules/EC2/unrestricted-smtp-access.html\n# Refer to https://www.cloudconformity.com/conformity-rules/EC2/unrestricted-telnet-access.html\n#.\n\naudit_aws_sgs () {\n  print_function  \"audit_aws_sgs\"\n  check_message   \"Security Groups\"\n  command=\"aws ec2 describe-security-groups --region \\\"${aws_region}\\\" --query SecurityGroups[].GroupId --output text\"\n  command_message \"${command}\"\n  sgs=$( eval     \"${command}\" )\n  for sg in ${sgs}; do\n    command=\"aws ec2 describe-security-groups --region \\\"${aws_region}\\\" --group-ids \\\"${sg}\\\" --filters ansible_value=group-name,Values='default' --query 'SecurityGroups[*].{IpPermissions:IpPermissions,GroupId:GroupId}' | grep \\\"0.0.0.0/0\\\"\"\n    command_message  \"${command}\"\n    in_check=$( eval \"${command}\" )\n    if [ -z \"${in_check}\" ]; then\n      inc_secure     \"Security Group \\\"${sg}\\\" does not have a open inbound rule\"\n    else\n      check_aws_open_port \"${sg}\" \"-1\"          \"icmp\" \"ICMP\"       \"none\" \"none\"\n      check_aws_open_port \"${sg}\" \"20,21\"       \"tcp\"  \"FTP\"        \"none\" \"none\"\n      check_aws_open_port \"${sg}\" \"22\"          \"tcp\"  \"SSH\"        \"none\" \"none\"\n      check_aws_open_port \"${sg}\" \"23\"          \"tcp\"  \"Telnet\"     \"none\" \"none\"\n      check_aws_open_port \"${sg}\" \"25\"          \"tcp\"  \"SMTP\"       \"none\" \"none\"\n      check_aws_open_port \"${sg}\" \"53\"          \"tcp\"  \"DNS\"        \"none\" \"none\"\n      check_aws_open_port \"${sg}\" \"80\"          \"tcp\"  \"HTTP\"       \"none\" \"none\"\n      check_aws_open_port \"${sg}\" \"135\"         \"tcp\"  \"RPC\"        \"none\" \"none\"\n      check_aws_open_port \"${sg}\" \"137,138,139\" \"tcp\"  \"SMB\"        \"none\" \"none\"\n      check_aws_open_port \"${sg}\" \"443\"         \"tcp\"  \"HTTPS\"      \"none\" \"none\"\n      check_aws_open_port \"${sg}\" \"445\"         \"tcp\"  \"CIFS\"       \"none\" \"none\"\n      check_aws_open_port \"${sg}\" \"1433\"        \"tcp\"  \"MSSQL\"      \"none\" \"none\"\n      check_aws_open_port \"${sg}\" \"1521\"        \"tcp\"  \"Oracle\"     \"none\" \"none\"\n      check_aws_open_port \"${sg}\" \"3306\"        \"tcp\"  \"MySQL\"      \"none\" \"none\"\n      check_aws_open_port \"${sg}\" \"3389\"        \"tcp\"  \"RDP\"        \"none\" \"none\"\n      check_aws_open_port \"${sg}\" \"5432\"        \"tcp\"  \"PostgreSQL\" \"none\" \"none\"\n      check_aws_open_port \"${sg}\" \"27017\"       \"tcp\"  \"MongoDB\"    \"none\" \"none\"\n    fi\n    command=\"aws ec2 describe-security-groups --region \\\"${aws_region}\\\" --group-ids \\\"${sg}\\\" --filters ansible_value=group-name,Values='default' --query 'SecurityGroups[*].{IpPermissionsEgress:IpPermissionsEgress,GroupId:GroupId}' | grep \\\"0.0.0.0/0\\\"\"\n    command_message   \"${command}\"\n    out_check=$( eval \"${command}\" )\n    if [ -z \"${out_check}\" ]; then\n      inc_secure      \"Security Group \\\"${sg}\\\" does not have a open outbound rule\"\n    else\n      inc_insecure    \"Security Group \\\"${sg}\\\" has an open outbound rule\"\n      verbose_message \"aws ec2 revoke-security-group-egress --region \\\"${aws_region}\\\" --group-name \\\"${sg}\\\" --protocol tcp --cidr 0.0.0.0/0\" \"fix\"\n    fi\n  done\n}\n"
  },
  {
    "path": "modules/aws/storage/audit_aws_cdn.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_aws_cdn\n#\n# Check AWS Cloudfront\n#\n# Refer to https://www.cloudconformity.com/conformity-rules/CloudFront/cloudfront-integrated-with-waf.html\n# Refer to https://www.cloudconformity.com/conformity-rules/CloudFront/cloudfront-logging-enabled.html\n# Refer to https://www.cloudconformity.com/conformity-rules/CloudFront/cloudfront-insecure-origin-ssl-protocols.html\n# Refer to https://www.cloudconformity.com/conformity-rules/CloudFront/cloudfront-traffic-to-origin-unencrypted.html\n#.\n\naudit_aws_cdn () {\n  print_function  \"audit_aws_cdn\"\n  check_message   \"Cloudfront\"\n  aws configure set preview.cloudfront true\n  command=\"aws cloudfront list-distributions --query 'DistributionList.Items[].Id' --output text | grep -v null\"\n  command_message \"${command}\"\n  cdns=$( eval    \"${command}\" )\n  for cdn in ${cdns}; do \n    # Check Cloudfront is using WAF\n    command=\"aws cloudfront get-distribution --id \\\"${cdn}\\\" --query 'Distribution.DistributionConfig.WebACLId' --output text\"\n    command_message \"${command}\"\n    check=$( eval   \"${command}\" )\n    if [ \"${check}\" ]; then\n      inc_secure    \"Cloudfront CDN \\\"${cdn}\\\" is WAF integration enabled\"\n    else\n      inc_insecure  \"Cloudfront CDN \\\"${cdn}\\\" is not WAF integration enabled\"\n    fi\n    # Check logging is enabled\n    command=\"aws cloudfront get-distribution --id \\\"${cdn}\\\" --query 'Distribution.DistributionConfig.Logging.Enabled' | grep true\"\n    command_message \"${command}\"\n    check=$( eval   \"${command}\" )\n    if [ \"${check}\" ]; then\n      inc_secure    \"Cloudfront CDN \\\"${cdn}\\\" has logging enabled\"\n    else\n      inc_insecure  \"Cloudfront CDN \\\"${cdn}\\\" does not have logging enabled\"\n    fi\n    # check SSL protocol versions being used against deprecated ones\n    command=\"aws cloudfront get-distribution --id \\\"${cdn}\\\" --query 'Distribution.DistributionConfig.Origins.Items[].CustomOriginConfig.OriginSslProtocols.Items' | grep -E \\\"SSLv3|SSLv2\\\"\"\n    command_message \"${command}\"\n    check=$( eval   \"${command}\" )\n    if [ ! \"${check}\" ]; then\n      inc_secure    \"Cloudfront CDN \\\"${cdn}\\\" is not using a deprecated version of SSL\"\n    else\n      inc_insecure  \"Cloudfront CDN \\\"${cdn}\\\" is using a deprecated verions of SSL\"\n    fi\n    # check if HTTP only being used \n    command=\"aws cloudfront get-distribution --id \\\"${cdn}\\\" --query 'Distribution.DistributionConfig.Origins.Items[].CustomOriginConfig.OriginProtocolPolicy' | grep -E \\\"http-only\\\"\"\n    command_message \"${command}\"\n    check=$( eval   \"${command}\" )\n    if [ ! \"${check}\" ]; then\n      inc_secure    \"Cloudfront CDN \\\"${cdn}\\\" is not using HTTP only\"\n    else\n      inc_insecure  \"Cloudfront CDN \\\"${cdn}\\\" is using HTTP only\"\n    fi\n  done\n}\n\n"
  },
  {
    "path": "modules/aws/storage/audit_aws_s3.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_aws_s3\n#\n# Check AWS S3\n#\n# Refer to https://www.cloudconformity.com/conformity-rules/S3/s3-bucket-authenticated-users-full-control-access.html\n# Refer to https://www.cloudconformity.com/conformity-rules/S3/s3-bucket-logging-enabled.html\n# Refer to https://www.cloudconformity.com/conformity-rules/S3/s3-bucket-public-full-control-access.html\n#.\n\naudit_aws_s3 () {\n  print_function  \"audit_aws_s3\"\n  check_message   \"S3\"\n  command=\"aws s3api list-buckets --region \\\"${aws_region}\\\" --query 'Buckets[*].Name' --output text\"\n  command_message \"${command}\"\n  buckets=$( eval \"${command}\" )\n  for bucket in ${buckets}; do\n    for user in http://acs.amazonaws.com/groups/global/AllUsers http://acs.amazonaws.com/groups/global/AuthenticatedUsers; do\n      command=\"aws s3api get-bucket-acl --region \\\"${aws_region}\\\" --bucket \\\"${bucket}\\\" | grep URI | grep \\\"${user}\\\"\"\n      command_message \"${command}\"\n      grants=$( eval  \"${command}\" )\n      if [ -n \"${grants}\" ]; then\n        inc_insecure  \"Bucket \\\"${bucket}\\\" grants access to Principal \\\"${user}\\\"\"\n      else\n        inc_secure    \"Bucket \\\"${bucket}\\\" does not grant access to Principal \\\"${user}\\\"\"\n      fi\n    done\n    command=\"aws s3api get-bucket-logging --region \\\"${aws_region}\\\" --bucket \\\"${bucket}\\\"\"\n    command_message   \"${command}\"\n    check=$( eval     \"${command}\" )\n    if [ -z \"${check}\" ]; then\n      inc_insecure    \"Bucket ${bucket} does not have access logging enabled\"\n      verbose_message \"aws s3api put-bucket-acl --region \\\"${aws_region}\\\" --bucket \\\"${bucket}\\\" --grant-write URI=http://acs.amazonaws.com/groups/s3/LogDelivery --grant-read-acp URI=http://acs.amazonaws.com/groups/s3/LogDelivery\" \"fix\"\n      verbose_message \"cd aws ; aws s3api put-bucket-logging --region \\\"${aws_region}\\\" --bucket \\\"${bucket}\\\" --bucket-logging-status file://server-access-logging.json\"\n    else\n      inc_secure      \"Bucket \\\"${bucket}\\\" has access logging enabled\"\n    fi\n    command=\"aws s3api get-bucket-versioning --bucket \\\"${bucket}\\\" | grep Enabled\"\n    command_message   \"${command}\"\n    check=$( eval     \"${command}\" )\n    if [ -n \"${check}\" ]; then\n      inc_secure      \"Bucket \\\"${bucket}\\\" has versioning enabled\"\n    else\n      inc_insecure    \"Bucket \\\"${bucket}\\\" does not have versioning enabled\"\n    fi\n  done\n}\n\n"
  },
  {
    "path": "modules/azure/compute/batch/audit_azure_batch.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_batch\n#\n# Check Azure Batch\n#\n# 15.1 Ensure Batch account is set to use customer-managed keys to encrypt data - TBD\n# 15.2 Ensure Batch pools disk encryption is set enabled - TBD\n# 15.3 Ensure local authentication methods for accounts are disabled - TBD\n# 15.4 Ensure Private endpoints are considered for Batch accounts - TBD\n# 15.5 Ensure public network access is disabled for Batch accounts - TBD\n# 15.6 Ensure private DNS zones for private endpoints that connect to Batch accounts are configured - TBD\n# 15.7 Ensure Diagnostics settings logs for Batch accounts are enabled - TBD\n# \n# Refer to Section(s) 15- Page(s) 277- CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_batch () {\n  print_function \"audit_azure_batch\"\n  check_message  \"Azure Batch\"\n  command=\"az batch account list --query \\\"[].name\\\" --output tsv\"\n  command_message    \"${command}\"\n  batch_list=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${batch_list}\" ]; then\n    info_message \"No Batch accounts found\"\n  fi\n  for batch_name in ${batch_list}; do\n    command=\"az batch account show --name \\\"${batch_name}\\\" --query \\\"[].resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    # 15.1 Ensure Batch account is set to use customer-managed keys to encrypt data - TBD\n    check_azure_batch_value \"Customer Managed Keys\"        \"${batch_name}\" \"${res_group}\" \"keyVaultReference\"          \"ne\" \"\"         \"--encryption-key-identifier\" \"https://<keyvault_name>.vault.azure.net/keys/<key_name>/<Version>\"\n    # 15.3 Ensure local authentication methods for accounts are disabled - TBD\n    check_azure_batch_value \"Local Authentication Methods\" \"${batch_name}\" \"${res_group}\" \"allowedAuthenticationModes\" \"eq\" \"AAD\"      \"\"                            \"\"\n    # 15.5 Ensure public network access is disabled for Batch accounts - TBD\n    check_azure_batch_value \"Public Network Access\"        \"${batch_name}\" \"${res_group}\" \"publicNetworkAccess\"        \"eq\" \"Disabled\" \"\"                            \"\"\n    # 15.2 Ensure Batch pools disk encryption is set enabled - TBD\n    command=\"az batch pool list --account-name \\\"${batch_name}\\\" --query \\\"[].id\\\" --output tsv\"\n    command_message  \"${command}\"\n    pool_ids=$( eval \"${command}\" )\n    for pool_id in ${pool_ids}; do\n      for disk_name in OsDisk TemporaryDisk; do\n        check_azure_batch_pool_value \"Batch pools disk encryption\" \"${pool_id}\" \"deploymentConfiguration.virtualMachineConfiguration.diskEncryption.Configuration.encryption.targets\" \"has\" \"${disk_name}\"\n      done\n    done\n    # 15.4 Ensure Private endpoints are considered for Batch accounts - TBD\n    check_azure_network_private_endpoint_value \"${res_group}\" \"[?privateLinkServiceConnections[?contains(properties.privateLinkServiceId, 'Microsoft.Batch/batchAccounts/${batch_name}')]]\" \"ne\" \"\"\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/container/audit_azure_container_instances.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_container_instances\n#\n# Check Azure Container Instances\n#\n# 3.1  Ensure Private Virtual Networks are used for Container Instances - TBD\n# 3.2  Ensure a Managed Identity is used for interactions with other Azure services - TBD\n# 3.3  Ensure the principle of least privilege is used when assigning roles to a Managed Identity - TBD\n#\n# Refer to Section(s) 3.1- Page(s) 255- CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_container_instances () {\n  print_function  \"audit_azure_container_instances\"\n  check_message   \"Azure Container Instances\"\n  command=\"az container list --query \\\"[].name\\\" --output tsv\"\n  command_message \"${command}\"\n  c_list=$( eval  \"${command}\" 2> /dev/null )\n  if [ -z \"${c_list}\" ]; then\n    info_message  \"No Container Instances found\"\n  fi\n  for c_name in ${c_list}; do\n    command=\"az container show --name \\\"${c_name}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    check_azure_container_instance_value \"Private Virtual Networks\" \"${c_name}\" \"${res_group}\" \"ipAddress.type\" \"eq\" \"Private\"\n    check_azure_container_instance_value \"Managed Identity\"         \"${c_name}\" \"${res_group}\" \"identity.type\"  \"eq\" \"${azure_managed_identity}\"\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/cycle/audit_azure_cycle_cloud.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_cycle_cloud\n#\n# Check Azure CycleCloud\n#\n# Refer to Section(s) 2- Page(s) 22- CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_cycle_cloud () {\n  print_function \"audit_azure_cycle_cloud\"\n  check_message  \"Azure CycleCloud\"\n}\n"
  },
  {
    "path": "modules/azure/compute/function/apps/audit_azure_function_app_basic_authentication_publishing_credentials.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_function_app_basic_authentication_publishing_credentials\n#\n# 2.3.3   Ensure 'Basic Authentication Publishing Credentials' are 'Disabled' - TBD\n#\n# Refer to Section(s) 2.3.3 Page(s) 149-51 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_function_app_basic_authentication_publishing_credentials () {\n  print_function \"audit_azure_function_app_basic_authentication_publishing_credentials\"\n  check_message  \"Azure Function Apps Basic Authentication Publishing Credentials\"\n  command=\"az functionapp list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No Function Apps found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az functionapp show --id \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    check_azure_function_app_value \"Basic Authentication Publishing Credentials\" \"${app_id}\" \"${res_group}\" \"basicPublishingCredentialsPolicies\" \"ftp\" \"Microsoft.Web\" \"properties.allow\" \"eq\" \"false\" \"\" \"\"\n    check_azure_function_app_value \"Basic Authentication Publishing Credentials\" \"${app_id}\" \"${res_group}\" \"basicPublishingCredentialsPolicies\" \"scm\" \"Microsoft.Web\" \"properties.allow\" \"eq\" \"false\" \"\" \"\"\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/function/apps/audit_azure_function_app_client_certificates.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_function_app_client_certificates\n#\n# 2.3.10  Ensure incoming client certificates are enabled and required (if in use) - TBD\n#\n# Refer to Section(s) 2.3.10 Page(s) 169-71 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_function_app_client_certificates () {\n  print_function \"audit_azure_function_app_client_certificates\"\n  check_message  \"Azure Function Apps Client Certificates\"\n  command=\"az functionapp list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No Function Apps found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az functionapp show --id \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    check_azure_function_app_value \"Client Certificates\" \"${app_id}\" \"${res_group}\" \"config\" \"web\" \"Microsoft.Web/sites\" \"clientCertEnabled\" \"eq\" \"true\" \"clientCertEnabled\" \"\"\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/function/apps/audit_azure_function_app_cross_origin_resource_sharing.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_function_app_cross_origin_resource_sharing\n#\n# 2.3.17  Ensure cross-origin resource sharing does not allow all origins - TBD\n#\n# Refer to Section(s) 2.3.17 Page(s) 143-5 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_function_app_cross_origin_resource_sharing () {\n  print_function \"audit_azure_function_app_cross_origin_resource_sharing\"\n  check_message  \"Azure Function Apps Cross-Origin Resource Sharing\"\n  command=\"az functionapp list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No Function Apps found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az functionapp show --id \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    check_azure_function_app_value \"Cross-Origin Resource Sharing\" \"${app_id}\" \"${res_group}\" \"config\" \"web\" \"cors\" \"siteConfig.cors.allowedOrigins\" \"ne\" \"*\" \"properties.cors.allowedOrigins\" \"\"\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/function/apps/audit_azure_function_app_ftp_states.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_function_app_ftp_states\n#\n# 2.3.4   Ensure 'FTP State' is set to 'FTPS only' or 'Disabled' - TBD\n#\n# Refer to Section(s) 2.3.4 Page(s) 152-4 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_function_app_java_versions () {\n  print_function \"audit_azure_function_app_java_versions\"\n  check_message  \"Azure Function Apps Java Versions\"\n  command=\"az functionapp list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No Function Apps found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az functionapp show --id \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    check_azure_function_app_value \"FTP State\" \"${app_id}\" \"${res_group}\" \"config\" \"ftp\" \"\" \"ftpState\" \"eq\" \"${azure_ftp_state}\" \"--ftp-state\" \"\"\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/function/apps/audit_azure_function_app_http_values.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_function_app_http_values\n#\n# 2.3.5   Ensure 'HTTP version' is set to '2.0' (if in use) - TBD\n# 2.3.6   Ensure 'HTTPS Only' is set to 'On' - TBD\n#\n# Refer to Section(s) 2.3.5-6 Page(s) 155-60 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_function_app_http_values () {\n  print_function \"audit_azure_function_app_http_values\"\n  check_message  \"Azure Function Apps HTTP Values\"\n  command=\"az functionapp list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No Function Apps found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az functionapp show --id \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    check_azure_function_app_value \"HTTP Version\" \"${app_id}\" \"${res_group}\" \"config\" \"web\" \"\" \"http20Enabled\" \"eq\" \"true\" \"--http20-enabled\" \"\"\n    check_azure_function_app_value \"HTTPS Only\"   \"${app_id}\" \"${res_group}\" \"config\" \"web\" \"\" \"httpsOnly\"     \"eq\" \"true\" \"httpsOnly\"        \"\"\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/function/apps/audit_azure_function_app_java_versions.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_function_app_java_versions\n#\n# 2.3.1   Ensure 'Java version' is currently supported (if in use) - TBD\n#\n# Refer to Section(s) 2.3.1 Page(s) 143-5 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_function_app_java_versions () {\n  print_function \"audit_azure_function_app_java_versions\"\n  check_message  \"Azure Function Apps Java Versions\"\n  command=\"az functionapp list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No Function Apps found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az functionapp show --id \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    check_azure_function_app_value \"Java Version\"           \"${app_id}\" \"${res_group}\" \"config\" \"web\" \"\" \"javaVersion\"          \"eq\" \"${azure_java_version}\" \"--java-version\"           \"\"\n    check_azure_function_app_value \"Java Container Version\" \"${app_id}\" \"${res_group}\" \"config\" \"web\" \"\" \"javaContainerVersion\" \"eq\" \"${azure_java_version}\" \"--java-container-version\" \"\"\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/function/apps/audit_azure_function_app_managed_identities.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_function_app_managed_identities\n#\n# 2.3.12  Ensure managed identities are configured - TBD\n#\n# Refer to Section(s) 2.3.12 Page(s) 175-7 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_function_app_managed_identities () {\n  print_function \"audit_azure_function_app_managed_identities\"\n  check_message  \"Azure Function Apps Managed Identities\"\n  command=\"az functionapp list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No Function Apps found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az functionapp show --id \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    check_azure_function_app_value \"Managed Identities\" \"${app_id}\" \"${res_group}\" \"config\" \"web\" \"identity\" \"type\" \"eq\" \"${azure_managed_identity}\" \"\" \"\"\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/function/apps/audit_azure_function_app_public_network_access.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_function_app_public_network_access\n#\n# 2.3.13  Ensure public network access is disabled - TBD\n#\n# Refer to Section(s) 2.3.13 Page(s) 178-80 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_function_app_public_network_access () {\n  print_function \"audit_azure_function_app_public_network_access\"\n  check_message  \"Azure Function Apps Public Network Access\"\n  command=\"az functionapp list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No Function Apps found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az functionapp show --id \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    check_azure_function_app_value \"Public Network Access\" \"${app_id}\" \"${res_group}\" \"config\" \"web\" \"Microsoft.Web/sites\" \"publicNetworkAccess\" \"eq\" \"Disabled\" \"properties.publicNetworkAccess\" \"\"\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/function/apps/audit_azure_function_app_python_versions.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_function_apps\n#\n# 2.3.2   Ensure 'Python version' is currently supported (if in use) - TBD\n#\n# Refer to Section(s) 2.3.2 Page(s) 146-8 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_function_apps () {\n  print_function \"audit_azure_functions_apps\"\n  check_message  \"Azure Function Apps\"\n  command=\"az functionapp list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No Function Apps found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az functionapp show --id \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    check_azure_function_app_value \"Python Version\" \"${app_id}\" \"${res_group}\" \"config\" \"web\" \"\" \"pythonVersion\" \"eq\" \"${azure_python_version}\" \"--python-version\" \"\"\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/function/apps/audit_azure_function_app_remote_debugging.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_function_app_remote_debugging\n#\n# 2.3.9   Ensure 'Remote debugging' is set to 'Off' - TBD\n#\n# Refer to Section(s) 2.3.9 Page(s) 167-8 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_function_app_remote_debugging () {\n  print_function \"audit_azure_function_app_remote_debugging\"\n  check_message  \"Azure Function Apps Remote Debugging\"\n  command=\"az functionapp list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No Function Apps found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az functionapp show --id \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    check_azure_function_app_value \"Remote Debugging\" \"${app_id}\" \"${res_group}\" \"config\" \"web\" \"\" \"remoteDebuggingEnabled\" \"eq\" \"false\" \"--remote-debugging-enabled\" \"\"\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/function/apps/audit_azure_function_app_service_authentication.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_function_app_service_authentication\n#\n# 2.3.11 Ensure 'App Service authentication' is set to 'Enabled' - TBD\n#\n# Refer to Section(s) 2.3.11 Page(s) 172-4 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_function_app_service_authentication () {\n  print_function \"audit_azure_function_app_service_authentication\"\n  check_message  \"Azure Function Apps Service Authentication\"\n  command=\"az functionapp list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No Function Apps found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az functionapp show --id \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    check_azure_function_app_value \"App Service Authentication\" \"${app_id}\" \"${res_group}\" \"auth\" \"web\" \"Microsoft.Web/sites\" \"authSettings.enabled\" \"eq\" \"true\" \"properties.authSettings.enabled\" \"\"\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/function/apps/audit_azure_function_app_tls_values.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_function_app_tls_values\n#\n# 2.3.7   Ensure 'Minimum Inbound TLS Version' is set to '1.2' or higher - TBD\n# 2.3.8   Ensure end-to-end TLS encryption is enabled - TBD\n#\n# Refer to Section(s) 2.3.7-8 Page(s) 155-156 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_function_app_tls_values () {\n  print_function \"audit_azure_function_app_tls_values\"\n  check_message  \"Azure Function Apps TLS Values\"\n  command=\"az functionapp list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No Function Apps found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az functionapp show --id \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    check_azure_function_app_value \"Minimum Inbound TLS Version\" \"${app_id}\" \"${res_group}\" \"config\" \"web\" \"\"                    \"minTlsVersion\"             \"eq\" \"1.2\"                           \"--min-tls-version\"                              \"\"\n    check_azure_function_app_value \"End-to-End TLS Encryption\"   \"${app_id}\" \"${res_group}\" \"config\" \"web\" \"Microsoft.Web/sites\" \"endToEndEncryptionEnabled\" \"eq\" \"true\"                          \"properties.endToEndEncryptionEnabled\"           \"\"\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/function/apps/audit_azure_function_app_virtual_network_integration.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_function_app_virtual_network_integration\n#\n# 2.3.14  Ensure app is integrated with a virtual network - TBD\n# 2.3.15  Ensure configuration is routed through the virtual network integration - TBD\n# 2.3.16  Ensure all traffic is routed through the virtual network - TBD\n#\n# Refer to Section(s) 2.3.14, 2.3.15, 2.3.16 Page(s) 181- CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_function_app_virtual_network_integration () {\n  print_function \"audit_azure_function_app_virtual_network_integration\"\n  check_message  \"Azure Function Apps Virtual Network Integration\"\n  command=\"az functionapp list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No Function Apps found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az functionapp show --id \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    check_azure_function_app_value \"Virtual Network Integration\" \"${app_id}\" \"${res_group}\" \"config\" \"web\" \"\"                    \"virtualNetworkSubnetId\"  \"ne\" \"\"     \"\"                                   \"\"\n    check_azure_function_app_value \"VNet Image Pull\"             \"${app_id}\" \"${res_group}\" \"config\" \"web\" \"Microsoft.Web/sites\" \"vnetImagePullEnabled\"    \"eq\" \"true\" \"properties.vnetRouteAllEnabled\"     \"\"\n    check_azure_function_app_value \"VNet Content Share\"          \"${app_id}\" \"${res_group}\" \"config\" \"web\" \"Microsoft.Web/sites\" \"vnetContentShareEnabled\" \"eq\" \"true\" \"properties.vnetContentShareEnabled\" \"\"\n    check_azure_function_app_value \"VNet Route All\"              \"${app_id}\" \"${res_group}\" \"config\" \"web\" \"Microsoft.Web/sites\" \"vnetRouteAllEnabled\"     \"eq\" \"true\" \"properties.vnetRouteAllEnabled\"     \"\"\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/function/apps/audit_azure_function_apps.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_function_apps\n#\n# Function Apps\n# 2.3.1   Ensure 'Java version' is currently supported (if in use) - TBD\n# 2.3.2   Ensure 'Python version' is currently supported (if in use) - TBD\n# 2.3.3   Ensure 'Basic Authentication Publishing Credentials' are 'Disabled' - TBD\n# 2.3.5   Ensure 'HTTP version' is set to '2.0' (if in use) - TBD\n# 2.3.6   Ensure 'HTTPS Only' is set to 'On' - TBD\n# 2.3.7   Ensure 'Minimum Inbound TLS Version' is set to '1.2' or higher - TBD\n# 2.3.8   Ensure end-to-end TLS encryption is enabled - TBD\n# 2.3.9   Ensure 'Remote debugging' is set to 'Off' - TBD\n# 2.3.10  Ensure incoming client certificates are enabled and required (if in use) - TBD\n# 2.3.11  Ensure 'App Service authentication' is set to 'Enabled' - TBD\n# 2.3.12  Ensure managed identities are configured - TBD\n# 2.3.13  Ensure public network access is disabled - TBD\n# 2.3.14  Ensure function app is integrated with a virtual network - TBD\n# 2.3.15  Ensure configuration is routed through the virtual network integration - TBD\n# 2.3.16  Ensure all traffic is routed through the virtual network - TBD\n# 2.3.17  Ensure cross-origin resource sharing does not allow all origins - TBD\n#\n# Refer to Section(s) 2.3.1-17 Page(s) 142- CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_function_apps () {\n  print_function \"audit_azure_functions_apps\"\n  check_message  \"Azure Function Apps\"\n  command=\"az functionapp list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No Function Apps found\"\n    return\n  fi\n  # 2.3.1   Ensure 'Java version' is currently supported (if in use) - TBD\n  audit_azure_function_app_java_versions\n  # 2.3.2   Ensure 'Python version' is currently supported (if in use) - TBD\n  audit_azure_function_app_python_versions\n  # 2.3.3   Ensure 'Basic Authentication Publishing Credentials' are 'Disabled' - TBD\n  audit_azure_function_app_basic_authentication_publishing_credentials\n  # 2.3.4   Ensure 'FTP State' is set to 'FTPS only' or 'Disabled' - TBD\n  audit_azure_function_app_ftp_states\n  # 2.3.5   Ensure 'HTTP version' is set to '2.0' (if in use) - TBD\n  # 2.3.6   Ensure 'HTTPS Only' is set to 'On' - TBD\n  audit_azure_function_app_http_values\n  # 2.3.7   Ensure 'Minimum Inbound TLS Version' is set to '1.2' or higher - TBD\n  # 2.3.8   Ensure end-to-end TLS encryption is enabled - TBD\n  audit_azure_function_app_tls_values\n  # 2.3.9   Ensure 'Remote debugging' is set to 'Off' - TBD\n  audit_azure_function_app_remote_debugging\n  # 2.3.10  Ensure incoming client certificates are enabled and required (if in use) - TBD\n  audit_azure_function_app_client_certificates\n  # 2.3.11 Ensure 'App Service authentication' is set to 'Enabled' - TBD\n  audit_azure_function_app_service_authentication\n  # 2.3.12  Ensure managed identities are configured - TBD\n  audit_azure_function_app_managed_identities\n  # 2.3.13  Ensure public network access is disabled - TBD\n  audit_azure_function_app_public_network_access\n  # 2.3.14  Ensure app is integrated with a virtual network - TBD\n  # 2.3.15  Ensure configuration is routed through the virtual network integration - TBD\n  # 2.3.16  Ensure all traffic is routed through the virtual network - TBD\n  audit_azure_function_app_virtual_network_integration\n  # 2.3.17  Ensure cross-origin resource sharing does not allow all origins - TBD\n  audit_azure_function_app_cross_origin_resource_sharing\n}\n"
  },
  {
    "path": "modules/azure/compute/function/slots/audit_azure_function_deployment_slots.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_function_deployment_slots\n#\n# Functions Deployment Slots\n# 2.4.1   Ensure 'Java version' is currently supported (if in use) - TBD\n# 2.4.2   Ensure 'Python version' is currently supported (if in use) - TBD\n# 2.4.3   Ensure 'Basic Authentication Publishing Credentials' are 'Disabled' - TBD\n# 2.4.4   Ensure 'FTP state' is set to 'FTPS only' or 'Disabled' - TBD\n# 2.4.5   Ensure 'HTTP version' is set to '2.0' (if in use) - TBD\n# 2.4.6   Ensure 'HTTPS Only' is set to 'On' - TBD\n# 2.4.7   Ensure 'Minimum Inbound TLS Version' is set to '1.2' or higher - TBD\n# 2.4.8   Ensure end-to-end TLS encryption is enabled - TBD\n# 2.4.9   Ensure 'Remote debugging' is set to 'Off' - TBD\n# 2.4.10  Ensure incoming client certificates are enabled and required (if in use) - TBD\n# 2.4.11  Ensure managed identities are configured - TBD\n# 2.4.12  Ensure public network access is disabled - TBD\n# 2.4.13  Ensure deployment slot is integrated with a virtual network - TBD\n# 2.4.14  Ensure configuration is routed through the virtual network integration - TBD\n# 2.4.15  Ensure all traffic is routed through the virtual network - TBD\n# 2.4.16  Ensure cross-origin resource sharing does not allow all origins - TBD\n#\n# Refer to Section(s) 2.4.1-16 Page(s) 192-237 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_function_deployment_slots () {\n  print_function \"audit_azure_function_deployment_slots\"\n  check_message  \"Azure Function App Deployment Slots\"\n  command=\"az functionapp list --query \\\"[].name\\\" --output tsv\"\n  command_message   \"${command}\"\n  app_names=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_names}\" ]; then\n    info_message \"No Function App Apps found\"\n    return\n  fi\n  for app_name in ${app_names}; do\n    command=\"az functionapp show --name \\\"${app_name}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message    \"${command}\"\n    res_group=$( eval  \"${command}\" )\n    command=\"az functionapp deployment slot list --name \\\"${app_name}\\\" --resource-group \\\"${res_group}\\\" --query \\\"[].name\\\" --output tsv\"\n    command_message    \"${command}\"\n    slot_names=$( eval \"${command}\" 2> /dev/null )\n    if [ -z \"${slot_names}\" ]; then\n      info_message \"No Function App Deployment Slots found\"\n      return\n    fi\n    # 2.4.1   Ensure 'Java version' is currently supported (if in use) - TBD\n    audit_azure_function_deployment_slots_java_versions\n    # 2.4.2   Ensure 'Python version' is currently supported (if in use) - TBD\n    audit_azure_function_deployment_slots_python_versions\n    # 2.4.3   Ensure 'Basic Authentication Publishing Credentials' are 'Disabled' - TBD\n    audit_azure_function_deployment_slots_basic_authentication_publishing_credentials\n    # 2.4.4   Ensure 'FTP State' is set to 'FTPS only' or 'Disabled' - TBD\n    audit_azure_function_deployment_slots_ftp_states\n    # 2.4.5   Ensure 'HTTP version' is set to '2.0' (if in use) - TBD\n    # 2.4.6   Ensure 'HTTPS Only' is set to 'On' - TBD\n    audit_azure_function_deployment_slots_http_values\n    # 2.4.7   Ensure 'Minimum Inbound TLS Version' is set to '1.2' or higher - TBD\n    # 2.4.8   Ensure end-to-end TLS encryption is enabled - TBD\n    audit_azure_function_deployment_slots_tls_values\n    # 2.4.9   Ensure 'Remote debugging' is set to 'Off' - TBD\n    audit_azure_function_deployment_slots_remote_debugging\n    # 2.4.10  Ensure incoming client certificates are enabled and required (if in use) - TBD\n    audit_azure_function_deployment_slots_client_certificates\n    # 2.4.11  Ensure managed identities are configured - TBD\n    audit_azure_function_deployment_slots_managed_identities\n    # 2.4.12  Ensure public network access is disabled - TBD\n    audit_azure_function_deployment_slots_public_network_access\n    # 2.4.13  Ensure app is integrated with a virtual network - TBD\n    # 2.4.14  Ensure configuration is routed through the virtual network integration - TBD\n    audit_azure_function_deployment_slots_virtual_network_integration\n    # 2.4.15  Ensure cross-origin resource sharing does not allow all origins - TBD\n    audit_azure_function_deployment_slots_cross_origin_resource_sharing\n    # 2.4.16  Ensure private endpoints are used to access App Service apps - TBD\n    audit_azure_app_service_deployment_slots_private_endpoints\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/function/slots/audit_azure_function_deployment_slots_basic_authentication_publishing_credentials.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_function_deployment_slots_basic_authentication_publishing_credentials\n#\n# 2.4.3   Ensure 'Basic Authentication Publishing Credentials' are 'Disabled' - TBD\n#\n# Refer to Section(s) 2.4.3 Page(s) 199-201 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_function_deployment_slots_basic_authentication_publishing_credentials () {\n  print_function \"audit_azure_function_deployment_slots_basic_authentication_publishing_credentials\"\n  check_message  \"Azure Function App Deployment Slots Basic Authentication Publishing Credentials\"\n  command=\"az functionapp list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No Function App Apps found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az functionapp show --name \\\"${app_id}\\\" --query \\\"name\\\" --output tsv\"\n    command_message   \"${command}\"\n    app_name=$( eval  \"${command}\" )\n    command=\"az functionapp show --name \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    command=\"az functionapp deployment slot list --name \\\"${app_id}\\\" --query \\\"[].id\\\" --output tsv\"\n    command_message   \"${command}\"\n    slot_ids=$( eval  \"${command}\" 2> /dev/null )\n    if [ -z \"${slot_ids}\" ]; then\n      info_message \"No Function App Deployment Slots found\"\n      return\n    fi\n    for slot_id in ${slot_ids}; do\n      check_azure_function_deployment_slot_value \"Basic Authentication Publishing Credentials\" \"${slot_id}\" \"${app_name}\" \"${res_group}\" \"basicPublishingCredentialsPolicies\" \"ftp\" \"Microsoft.Web/sites\" \"properties.allow\"                  \"eq\" \"false\"                         \"\"                                      \"\"\n      check_azure_function_deployment_slot_value \"Basic Authentication Publishing Credentials\" \"${slot_id}\" \"${app_name}\" \"${res_group}\" \"basicPublishingCredentialsPolicies\" \"scm\" \"Microsoft.Web/sites\" \"properties.allow\"                  \"eq\" \"false\"                         \"\"                                      \"\"\n    done\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/function/slots/audit_azure_function_deployment_slots_client_certificates.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_function_deployment_slots_client_certificates\n#\n# 2.4.10  Ensure incoming client certificates are enabled and required (if in use) - TBD\n#\n# Refer to Section(s) 2.4.10 Page(s) 219-21 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_function_deployment_slots_client_certificates () {\n  print_function \"audit_azure_function_deployment_slots_client_certificates\"\n  check_message  \"Azure Function App Deployment Slots Client Certificates\"\n  command=\"az functionapp list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No Function App Apps found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az functionapp show --name \\\"${app_id}\\\" --query \\\"name\\\" --output tsv\"\n    command_message   \"${command}\"\n    app_name=$( eval  \"${command}\" )\n    command=\"az functionapp show --name \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    command=\"az functionapp deployment slot list --name \\\"${app_id}\\\" --query \\\"[].id\\\" --output tsv\"\n    command_message   \"${command}\"\n    slot_ids=$( eval  \"${command}\" 2> /dev/null )\n    if [ -z \"${slot_ids}\" ]; then\n      info_message \"No Function App Deployment Slots found\"\n      return\n    fi\n    for slot_id in ${slot_ids}; do\n      check_azure_function_deployment_slot_value \"Client Certificates\" \"${slot_id}\" \"${app_name}\" \"${res_group}\" \"config\" \"web\" \"Microsoft.Web/sites\" \"clientCertEnabled\" \"eq\" \"true\" \"clientCertEnabled\" \"\"\n    done\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/function/slots/audit_azure_function_deployment_slots_cross_origin_resource_sharing.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_function_deployment_slots_cross_origin_resource_sharing\n#\n# 2.4.15  Ensure cross-origin resource sharing does not allow all origins - TBD\n#\n# Refer to Section(s) 2.4.15 Page(s) 232-4 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_function_deployment_slots_cross_origin_resource_sharing () {\n  print_function \"audit_azure_function_deployment_slots_cross_origin_resource_sharing\"\n  check_message  \"Azure Function App Deployment Slots Cross-Origin Resource Sharing\"\n  command=\"az functionapp list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No Function App Apps found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az functionapp show --name \\\"${app_id}\\\" --query \\\"name\\\" --output tsv\"\n    command_message   \"${command}\"\n    app_name=$( eval  \"${command}\" )\n    command=\"az functionapp show --name \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    command=\"az functionapp deployment slot list --name \\\"${app_id}\\\" --query \\\"[].id\\\" --output tsv\"\n    command_message   \"${command}\"\n    slot_ids=$( eval  \"${command}\" 2> /dev/null )\n    if [ -z \"${slot_ids}\" ]; then\n      info_message \"No Function App Deployment Slots found\"\n      return\n    fi\n    for slot_id in ${slot_ids}; do\n      check_azure_function_deployment_slot_value \"Cross-Origin Resource Sharing\" \"${slot_id}\" \"${app_name}\" \"${res_group}\" \"config\" \"web\" \"cors\" \"siteConfig.cors.allowedOrigins\" \"ne\" \"*\" \"properties.cors.allowedOrigins\" \"\"\n    done\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/function/slots/audit_azure_function_deployment_slots_ftp_states.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_function_deployment_slots_ftp_states\n#\n# 2.4.4   Ensure 'FTP State' is set to 'FTPS only' or 'Disabled' - TBD\n#\n# Refer to Section(s) 2.4.4 Page(s) 203-4 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_function_deployment_slots_ftp_states () {\n  print_function \"audit_azure_function_deployment_slots_ftp_states\"\n  check_message  \"Azure Function App Deployment Slots FTP States\"\n  command=\"az functionapp list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No Function App Apps found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az functionapp show --name \\\"${app_id}\\\" --query \\\"name\\\" --output tsv\"\n    command_message   \"${command}\"\n    app_name=$( eval  \"${command}\" )\n    command=\"az functionapp show --name \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    command=\"az functionapp deployment slot list --name \\\"${app_id}\\\" --query \\\"[].id\\\" --output tsv\"\n    command_message   \"${command}\"\n    slot_ids=$( eval  \"${command}\" 2> /dev/null )\n    if [ -z \"${slot_ids}\" ]; then\n      info_message \"No Function App Deployment Slots found\"\n      return\n    fi\n    for slot_id in ${slot_ids}; do\n      check_azure_function_deployment_slot_value \"FTP State\" \"${slot_id}\" \"${app_name}\" \"${res_group}\" \"config\" \"ftp\" \"Microsoft.Web/sites\" \"ftpState\" \"eq\" \"${azure_ftp_state}\" \"--ftp-state\" \"\"\n    done\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/function/slots/audit_azure_function_deployment_slots_http_values.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_function_deployment_slots_http_values\n#\n# 2.4.5   Ensure 'HTTP version' is set to '2.0' (if in use) - TBD\n# 2.4.6   Ensure 'HTTPS Only' is set to 'On' - TBD\n#\n# Refer to Section(s) 2.4.5-6 Page(s) 205-10 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_function_deployment_slots_http_values () {\n  print_function \"audit_azure_function_deployment_slots_http_values\"\n  check_message  \"Azure Function App Deployment Slots HTTP Values\"\n  command=\"az functionapp list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No Function App Apps found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az functionapp show --name \\\"${app_id}\\\" --query \\\"name\\\" --output tsv\"\n    command_message   \"${command}\"\n    app_name=$( eval  \"${command}\" )\n    command=\"az functionapp show --name \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    command=\"az functionapp deployment slot list --name \\\"${app_id}\\\" --query \\\"[].id\\\" --output tsv\"\n    command_message   \"${command}\"\n    slot_ids=$( eval  \"${command}\" 2> /dev/null )\n    if [ -z \"${slot_ids}\" ]; then\n      info_message \"No Function App Deployment Slots found\"\n      return\n    fi\n    for slot_id in ${slot_ids}; do\n      check_azure_function_deployment_slot_value \"HTTP Version\" \"${slot_id}\" \"${app_name}\" \"${res_group}\" \"config\" \"web\" \"Microsoft.Web/sites\" \"http20Enabled\" \"eq\" \"true\" \"--http20-enabled\" \"\"\n      check_azure_function_deployment_slot_value \"HTTPS Only\"   \"${slot_id}\" \"${app_name}\" \"${res_group}\" \"config\" \"web\" \"Microsoft.Web/sites\" \"httpsOnly\"     \"eq\" \"true\" \"httpsOnly\"        \"\"\n    done\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/function/slots/audit_azure_function_deployment_slots_java_versions.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_function_deployment_slots_java_versions\n#\n# 2.4.1   Ensure 'Java version' is currently supported (if in use) - TBD\n#\n# Refer to Section(s) 2.4.1 Page(s) 193-5 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_function_deployment_slots_java_versions () {\n  print_function \"audit_azure_function_deployment_slots_java_versions\"\n  check_message  \"Azure Function App Deployment Slots Java Versions\"\n  command=\"az functionapp list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No Function App Apps found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az functionapp show --name \\\"${app_id}\\\" --query \\\"name\\\" --output tsv\"\n    command_message   \"${command}\"\n    app_name=$( eval  \"${command}\" )\n    command=\"az functionapp show --name \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    command=\"az functionapp deployment slot list --name \\\"${app_id}\\\" --query \\\"[].id\\\" --output tsv\"\n    command_message   \"${command}\"\n    slot_ids=$( eval  \"${command}\" 2> /dev/null )\n    if [ -z \"${slot_ids}\" ]; then\n      info_message \"No Function App Deployment Slots found\"\n      return\n    fi\n    for slot_id in ${slot_ids}; do\n      check_azure_function_deployment_slot_value \"Java Version\"           \"${slot_id}\" \"${app_name}\" \"${res_group}\" \"config\" \"web\" \"Microsoft.Web/sites\" \"javaVersion\"          \"eq\" \"${azure_java_version}\" \"--java-version\"           \"\"\n      check_azure_function_deployment_slot_value \"Java Container Version\" \"${slot_id}\" \"${app_name}\" \"${res_group}\" \"config\" \"web\" \"Microsoft.Web/sites\" \"javaContainerVersion\" \"eq\" \"${azure_java_version}\" \"--java-container-version\" \"\"\n    done\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/function/slots/audit_azure_function_deployment_slots_managed_identities.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_function_deployment_slots_managed_identities\n#\n# 2.4.11  Ensure managed identities are configured - TBD\n#\n# Refer to Section(s) 2.4.11 Page(s) 222-4 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_function_deployment_slots_managed_identities () {\n  print_function \"audit_azure_function_deployment_slots_managed_identities\"\n  check_message  \"Azure Function App Deployment Slots Managed Identities\"\n  command=\"az functionapp list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No Function App Apps found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az functionapp show --name \\\"${app_id}\\\" --query \\\"name\\\" --output tsv\"\n    command_message   \"${command}\"\n    app_name=$( eval  \"${command}\" )\n    command=\"az functionapp show --name \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    command=\"az functionapp deployment slot list --name \\\"${app_id}\\\" --query \\\"[].id\\\" --output tsv\"\n    command_message   \"${command}\"\n    slot_ids=$( eval  \"${command}\" 2> /dev/null )\n    if [ -z \"${slot_ids}\" ]; then\n      info_message \"No Function App Deployment Slots found\"\n      return\n    fi\n    for slot_id in ${slot_ids}; do\n      check_azure_function_deployment_slot_value \"Managed Identities\" \"${slot_id}\" \"${app_name}\" \"${res_group}\" \"config\" \"web\" \"identity\" \"type\" \"eq\" \"${azure_managed_identity}\" \"\" \"\"\n    done\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/function/slots/audit_azure_function_deployment_slots_private_endpoints.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_function_deployment_slots_private_endpoints\n#\n# 2.4.16  Ensure private endpoints are used to access App Service apps - TBD\n#\n# Refer to Section(s) 2.4.16 Page(s) 235-7 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_function_deployment_slots_private_endpoints () {\n  print_function \"audit_azure_function_deployment_slots_private_endpoints\"\n  check_message  \"Azure Function App Deployment Slots Private Endpoints\"\n  command=\"az functionapp list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No Function App Apps found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az functionapp show --name \\\"${app_id}\\\" --query \\\"name\\\" --output tsv\"\n    command_message   \"${command}\"\n    app_name=$( eval  \"${command}\" )\n    command=\"az functionapp show --name \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    command=\"az functionapp deployment slot list --name \\\"${app_id}\\\" --query \\\"[].id\\\" --output tsv\"\n    command_message   \"${command}\"\n    slot_ids=$( eval  \"${command}\" 2> /dev/null )\n    if [ -z \"${slot_ids}\" ]; then\n      info_message \"No Function App Deployment Slots found\"\n      return\n    fi\n    for slot_id in ${slot_ids}; do\n      check_azure_network_private_endpoint_value \"${app_id}\" \"[*].privateLinkServiceConnections[*].[privateLinkServiceId,privateLinkServiceConnectionState.status]\"   \"eq\" \"Approved\"\n    done\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/function/slots/audit_azure_function_deployment_slots_public_network_access.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_function_deployment_slots_public_network_access\n#\n# 2.4.12  Ensure public network access is disabled - TBD\n#\n# Refer to Section(s) 2.4.12 Page(s) 225-7 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_function_deployment_slots_public_network_access () {\n  print_function \"audit_azure_function_deployment_slots_public_network_access\"\n  check_message  \"Azure Function App Deployment Slots Public Network Access\"\n  command=\"az functionapp list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No Function App Apps found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az functionapp show --name \\\"${app_id}\\\" --query \\\"name\\\" --output tsv\"\n    command_message   \"${command}\"\n    app_name=$( eval  \"${command}\" )\n    command=\"az functionapp show --name \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    command=\"az functionapp deployment slot list --name \\\"${app_id}\\\" --query \\\"[].id\\\" --output tsv\"\n    command_message   \"${command}\"\n    slot_ids=$( eval  \"${command}\" 2> /dev/null )\n    if [ -z \"${slot_ids}\" ]; then\n      info_message \"No Function App Deployment Slots found\"\n      return\n    fi\n    for slot_id in ${slot_ids}; do\n      check_azure_function_deployment_slot_value \"Public Network Access\" \"${slot_id}\" \"${app_name}\" \"${res_group}\" \"config\" \"web\" \"Microsoft.Web/sites\" \"publicNetworkAccess\" \"eq\" \"Disabled\" \"properties.publicNetworkAccess\" \"\"\n    done\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/function/slots/audit_azure_function_deployment_slots_python_versions.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_function_deployment_slots_python_versions\n#\n# 2.4.2   Ensure 'Python version' is currently supported (if in use) - TBD\n#\n# Refer to Section(s) 2.4.2 Page(s) 196-8 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_function_deployment_slots_python_versions () {\n  print_function \"audit_azure_function_deployment_slots_python_versions\"\n  check_message  \"Azure Function App Deployment Slots Python Versions\"\n  command=\"az functionapp list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message  \"No App Service Deployment Slots found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"name\\\" --output tsv\"\n    command_message   \"${command}\"\n    app_name=$( eval  \"${command}\" )\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    command=\"az webapp deployment slot list --id \\\"${app_id}\\\" --query \\\"[].id\\\" --output tsv\"\n    command_message   \"${command}\"\n    slot_ids=$( eval  \"${command}\" 2> /dev/null )\n    if [ -z \"${slot_ids}\" ]; then\n      info_message \"No Function App Deployment Slots found\"\n      return\n    fi\n    for slot_id in ${slot_ids}; do\n      check_azure_function_deployment_slot_value \"Python Version\" \"${slot_id}\" \"${app_name}\" \"${res_group}\" \"config\" \"web\" \"Microsoft.Web/sites\" \"pythonVersion\" \"eq\" \"${azure_python_version}\" \"--python-version\" \"\"\n    done\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/function/slots/audit_azure_function_deployment_slots_remote_debugging.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_function_deployment_slots_remote_debugging\n#\n# 2.4.9   Ensure 'Remote debugging' is set to 'Off' - TBD\n#\n# Refer to Section(s) 2.4.9 Page(s) 216-8 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_function_deployment_slots_remote_debugging () {\n  print_function \"audit_azure_function_deployment_slots_remote_debugging\"\n  check_message  \"Azure Function App Deployment Slots Remote Debugging\"\n  command=\"az functionapp list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No Function App Apps found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az functionapp show --name \\\"${app_id}\\\" --query \\\"name\\\" --output tsv\"\n    command_message   \"${command}\"\n    app_name=$( eval  \"${command}\" )\n    command=\"az functionapp show --name \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    command=\"az functionapp deployment slot list --name \\\"${app_id}\\\" --query \\\"[].id\\\" --output tsv\"\n    command_message   \"${command}\"\n    slot_ids=$( eval  \"${command}\" 2> /dev/null )\n    if [ -z \"${slot_ids}\" ]; then\n      info_message \"No Function App Deployment Slots found\"\n      return\n    fi\n    for slot_id in ${slot_ids}; do\n      check_azure_function_deployment_slot_value \"Remote Debugging\" \"${slot_id}\" \"${app_name}\" \"${res_group}\" \"config\" \"web\" \"Microsoft.Web/sites\" \"remoteDebuggingEnabled\" \"eq\" \"false\" \"--remote-debugging-enabled\" \"\"\n    done\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/function/slots/audit_azure_function_deployment_slots_tls_values.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_function_deployment_slots_tls_values\n#\n# 2.4.7   Ensure 'Minimum Inbound TLS Version' is set to '1.2' or higher - TBD\n# 2.4.8   Ensure end-to-end TLS encryption is enabled - TBD\n#\n# Refer to Section(s) 2.4.7-8 Page(s) 211-5 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_function_deployment_slots_tls_values () {\n  print_function \"audit_azure_function_deployment_slots_tls_values\"\n  check_message  \"Azure Function App Deployment Slots TLS Values\"\n  command=\"az functionapp list --query \\\"[].name\\\" --output tsv\"\n  command_message   \"${command}\"\n  app_names=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_names}\" ]; then\n    info_message \"No Function App Apps found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az functionapp show --name \\\"${app_id}\\\" --query \\\"name\\\" --output tsv\"\n    command_message   \"${command}\"\n    app_name=$( eval  \"${command}\" )\n    command=\"az functionapp show --name \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    command=\"az functionapp deployment slot list --name \\\"${app_id}\\\" --query \\\"[].id\\\" --output tsv\"\n    command_message   \"${command}\"\n    slot_ids=$( eval  \"${command}\" 2> /dev/null )\n    if [ -z \"${slot_ids}\" ]; then\n      info_message \"No Function App Deployment Slots found\"\n      return\n    fi\n    for slot_id in ${slot_ids}; do\n      check_azure_function_deployment_slot_value \"Minimum Inbound TLS Version\" \"${slot_id}\" \"${app_name}\" \"${res_group}\" \"config\" \"web\" \"Microsoft.Web/sites\" \"minTlsVersion\"             \"eq\" \"1.2\"  \"--min-tls-version\"                    \"\"\n      check_azure_function_deployment_slot_value \"End-to-End TLS Encryption\"   \"${slot_id}\" \"${app_name}\" \"${res_group}\" \"config\" \"web\" \"Microsoft.Web/sites\" \"endToEndEncryptionEnabled\" \"eq\" \"true\" \"properties.endToEndEncryptionEnabled\" \"\"\n    done\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/function/slots/audit_azure_function_deployment_slots_virtual_network_integration.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_function_deployment_slots_virtual_network_integration\n#\n# 2.4.13  Ensure app is integrated with a virtual network - TBD\n# 2.4.14  Ensure configuration is routed through the virtual network integration - TBD\n#\n# Refer to Section(s) 2.4.13-4 Page(s) 228-31 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_function_deployment_slots_virtual_network_integration () {\n  print_function \"audit_azure_function_deployment_slots_virtual_network_integration\"\n  check_message  \"Azure Function App Deployment Slots Virtual Network Integration\"\n  command=\"az functionapp list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No Function App Apps found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az functionapp show --name \\\"${app_id}\\\" --query \\\"name\\\" --output tsv\"\n    command_message   \"${command}\"\n    app_name=$( eval  \"${command}\" )\n    command=\"az functionapp show --name \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    command=\"az functionapp deployment slot list --name \\\"${app_id}\\\" --query \\\"[].id\\\" --output tsv\"\n    command_message   \"${command}\"\n    slot_ids=$( eval  \"${command}\" 2> /dev/null )\n    if [ -z \"${slot_ids}\" ]; then\n      info_message \"No Function App Deployment Slots found\"\n      return\n    fi\n    for slot_id in ${slot_ids}; do\n      check_azure_function_deployment_slot_value \"Virtual Network Integration\" \"${slot_id}\" \"${app_name}\" \"${res_group}\" \"config\" \"web\" \"Microsoft.Web/sites\" \"virtualNetworkSubnetId\"  \"ne\" \"\"     \"\"                                   \"\"\n      check_azure_function_deployment_slot_value \"VNet Image Pull\"             \"${slot_id}\" \"${app_name}\" \"${res_group}\" \"config\" \"web\" \"Microsoft.Web/sites\" \"vnetRouteAllEnabled\"     \"eq\" \"true\" \"properties.vnetRouteAllEnabled\"     \"\"\n      check_azure_function_deployment_slot_value \"VNet Content Share\"          \"${slot_id}\" \"${app_name}\" \"${res_group}\" \"config\" \"web\" \"Microsoft.Web/sites\" \"vnetContentShareEnabled\" \"eq\" \"true\" \"properties.vnetContentShareEnabled\" \"\"\n    done\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/main/audit_azure_compute_services.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_compute_services\n#\n# Check Azure Compute Services\n#\n# Refer to Section(s) 3 Page(s) 63-8 CIS Microsoft Azure Foundations Benchmark v5.0.0\n# Refer to CIS Microsoft Azure Compute Services Benchmark\n#\n# 2.1     App Service Apps\n# 2.1.1   Ensure 'Java version' is currently supported (if in use) - TBD\n# 2.1.2   Ensure 'Python version' is currently supported (if in use) - TBD\n# 2.1.3   Ensure 'PHP version' is currently supported (if in use) - TBD\n# 2.1.4   Ensure 'Basic Authentication Publishing Credentials' are 'Disabled' - TBD\n# 2.1.5   Ensure 'FTP State' is set to 'FTPS only' or 'Disabled' - TBD\n# 2.1.6   Ensure 'HTTP version' is set to '2.0' (if in use) - TBD\n# 2.1.7   Ensure 'HTTPS Only' is set to 'On' - TBD\n# 2.1.8   Ensure 'Minimum Inbound TLS Version' is set to '1.2' or higher - TBD\n# 2.1.9   Ensure end-to-end TLS encryption is enabled - TBD\n# 2.1.10  Ensure 'Remote debugging' is set to 'Off' - TBD\n# 2.1.11  Ensure incoming client certificates are enabled and required (if in use) - TBD\n# 2.1.12  Ensure 'App Service authentication' is set to 'Enabled' - TBD\n# 2.1.13  Ensure managed identities are configured - TBD\n# 2.1.14  Ensure public network access is disabled - TBD\n# 2.1.15  Ensure App Service plan SKU supports private endpoints - TBD\n# 2.1.16  Ensure private endpoints are used to access App Service apps - TBD\n# 2.1.17  Ensure private endpoints used to access App Service apps use private DNS zones - TBD\n# 2.1.18  Ensure app is integrated with a virtual network - TBD\n# 2.1.19  Ensure configuration is routed through the virtual network integration - TBD\n# 2.1.20  Ensure all traffic is routed through the virtual network - TBD\n# 2.1.21  Ensure cross-origin resource sharing does not allow all origins - TBD\n#\n# 2.2     App Service Deployment Slots\n# 2.2.1   Ensure 'Java version' is currently supported (if in use) - TBD\n# 2.2.2   Ensure 'Python version' is currently supported (if in use) - TBD\n# 2.2.3   Ensure 'PHP version' is currently supported (if in use) - TBD\n# 2.2.4   Ensure 'Basic Authentication Publishing Credentials' are 'Disabled' - TBD\n# 2.2.5   Ensure 'FTP State' is set to 'FTPS only' or 'Disabled' - TBD\n# 2.2.6   Ensure 'HTTP version' is set to '2.0' (if in use) - TBD\n# 2.2.7   Ensure 'HTTPS Only' is set to 'On' - TBD\n# 2.2.8   Ensure 'Minimum Inbound TLS Version' is set to '1.2' or higher - TBD\n# 2.2.9   Ensure end-to-end TLS encryption is enabled - TBD\n# 2.2.10  Ensure 'Remote debugging' is set to 'Off' - TBD\n# 2.2.11  Ensure incoming client certificates are enabled and required (if in use) - TBD\n# 2.2.12  Ensure 'App Service authentication' is set to 'Enabled' - TBD\n# 2.2.13  Ensure managed identities are configured - TBD\n# 2.2.14  Ensure deployment slot is integrated with a virtual network - TBD\n# 2.2.15  Ensure configuration is routed through the virtual network integration - TBD\n# 2.2.16  Ensure all traffic is routed through the virtual network - TBD\n# 2.2.17  Ensure cross-origin resource sharing does not allow all origins - TBD\n# \n# 2.3     Function Apps\n# 2.3.1   Ensure 'Java version' is currently supported (if in use) - TBD\n# 2.3.2   Ensure 'Python version' is currently supported (if in use) - TBD\n# 2.3.3   Ensure 'Basic Authentication Publishing Credentials' are 'Disabled' - TBD\n# 2.3.5   Ensure 'HTTP version' is set to '2.0' (if in use) - TBD\n# 2.3.6   Ensure 'HTTPS Only' is set to 'On' - TBD\n# 2.3.7   Ensure 'Minimum Inbound TLS Version' is set to '1.2' or higher - TBD\n# 2.3.8   Ensure end-to-end TLS encryption is enabled - TBD\n# 2.3.9   Ensure 'Remote debugging' is set to 'Off' - TBD\n# 2.3.10  Ensure incoming client certificates are enabled and required (if in use) - TBD\n# 2.3.11  Ensure 'App Service authentication' is set to 'Enabled' - TBD\n# 2.3.12  Ensure managed identities are configured - TBD\n# 2.3.13  Ensure public network access is disabled - TBD\n# 2.3.14  Ensure function app is integrated with a virtual network - TBD\n# 2.3.15  Ensure configuration is routed through the virtual network integration - TBD\n# 2.3.16  Ensure all traffic is routed through the virtual network - TBD\n# 2.3.17  Ensure cross-origin resource sharing does not allow all origins - TBD\n#\n# 2.4     Functions Deployment Slots\n# 2.4.1   Ensure 'Java version' is currently supported (if in use) - TBD\n# 2.4.2   Ensure 'Python version' is currently supported (if in use) - TBD\n# 2.4.3   Ensure 'Basic Authentication Publishing Credentials' are 'Disabled' - TBD\n# 2.4.4   Ensure 'FTP state' is set to 'FTPS only' or 'Disabled' - TBD\n# 2.4.5   Ensure 'HTTP version' is set to '2.0' (if in use) - TBD\n# 2.4.6   Ensure 'HTTPS Only' is set to 'On' - TBD\n# 2.4.7   Ensure 'Minimum Inbound TLS Version' is set to '1.2' or higher - TBD\n# 2.4.8   Ensure end-to-end TLS encryption is enabled - TBD\n# 2.4.9   Ensure 'Remote debugging' is set to 'Off' - TBD\n# 2.4.10  Ensure incoming client certificates are enabled and required (if in use) - TBD\n# 2.4.11  Ensure managed identities are configured - TBD\n# 2.4.12  Ensure public network access is disabled - TBD\n# 2.4.13  Ensure deployment slot is integrated with a virtual network - TBD\n# 2.4.14  Ensure configuration is routed through the virtual network integration - TBD\n# 2.4.15  Ensure all traffic is routed through the virtual network - TBD\n# 2.4.16  Ensure cross-origin resource sharing does not allow all origins - TBD\n# 2.5     Ensure Azure Key Vaults are Used to Store Secrets - TBD\n# 2.6     Ensure App Service Environment is deployed with an internal load balancer - TBD\n# 2.7     Ensure App Service Environment is provisioned with v3 or higher - TBD\n# 2.8     Ensure App Service Environment has internal encryption enabled - TBD\n# 2.9     Ensure App Service Environment has TLS 1.0 and 1.1 disabled - TBD\n#\n# 3.      Azure Container Instances\n# 3.1     Ensure Private Virtual Networks are used for Container Instances - TBD\n# 3.2     Ensure a Managed Identity is used for interactions with other Azure services - TBD\n# 3.3     Ensure the principle of least privilege is used when assigning roles to a Managed Identity - TBD\n#\n# 4.      Azure CycleCloud\n# 4.1     Ensure SSL is configured for CycleCloud\n#\n# 5.      Azure Dedicated Host\n#\n# 6.      Azure Functions\n#\n# 7.      Azure Kubernetes Service\n#\n# 8.      Azure Quantum\n#\n# 9.      Azure Service Fabric\n#\n# 10.     Azure Spot Virtual Machines\n#\n# 11.     Azure Spring Apps\n#\n# 12.     Azure Virtual Desktop\n#\n# 13.     Azure VM Image Builder\n#\n# 14.     Azure VMware Solution\n#\n# 15.     Azure Batch\n# 15.1    Ensure Batch account is set to use customer-managed keys to encrypt data - TBD\n# 15.2    Ensure Batch pools disk encryption is set enabled - TBD\n# 15.3    Ensure local authentication methods for accounts are disabled - TBD\n# 15.4    Ensure Private endpoints are considered for Batch accounts - TBD\n# 15.5    Ensure public network access is disabled for Batch accounts - TBD\n# 15.6    Ensure private DNS zones for private endpoints that connect to Batch accounts are configured - TBD\n# 15.7    Ensure Diagnostics settings logs for Batch accounts are enabled - TBD\n#\n# 16.     Linux Virtual Machines\n#\n# 17.     SQL Server on Azure Virtual Machines\n#\n# 18.     Static Web Apps\n#\n# 19.     VM Scale Sets\n#\n# 20.     Virtual Machines\n# 20.1    Ensure Virtual Machines are utilizing Managed Disks\n# 20.2    Ensure that 'OS and Data' disks are encrypted with 'Customer Managed Key' (CMK)\n# 20.3    Ensure that 'Unattached disks' are encrypted with 'Customer Managed Key' (CMK)\n# 20.4    Ensure that 'Disk Network Access' is NOT set to 'Enable public access from all networks'\n# 20.5    Ensure that 'Enable Data Access Authentication Mode' is 'Checked'\n# 20.6    Ensure that Only Approved Extensions Are Installed\n# 20.7    Ensure that Endpoint Protection for all Virtual Machines is installed\n# 20.8    [Legacy] Ensure that VHDs are Encrypted\n# 20.9    Ensure only MFA enabled identities can access privileged Virtual Machine \n# 20.10   Ensure Trusted Launch is enabled on Virtual Machines \n# 20.11   Ensure that encryption at host is enabled\n#\n# Refer to Section(s) 2-20 Page(s) 22-341 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_compute_services () {\n  print_function \"audit_azure_compute_services\"\n  check_message  \"Azure Compute Services\"\n  audit_azure_app_service_apps\n  audit_azure_app_service_deployment_slots\n  audit_azure_function_apps\n  audit_azure_function_deployment_slots\n  audit_azure_key_vault_certificates\n  audit_azure_key_vault_secrets\n  audit_azure_app_service_ase\n  audit_azure_container_instances\n  audit_azure_cycle_cloud\n  audit_azure_batch\n  audit_azure_vms\n}\n"
  },
  {
    "path": "modules/azure/compute/vm/audit_azure_vms.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_vms\n#\n# Check Azure Virtual Machines\n#\n# 20.1    Ensure Virtual Machines are utilizing Managed Disks\n# 20.2    Ensure that 'OS and Data' disks are encrypted with 'Customer Managed Key' (CMK)\n# 20.3    Ensure that 'Unattached disks' are encrypted with 'Customer Managed Key' (CMK)\n# 20.4    Ensure that 'Disk Network Access' is NOT set to 'Enable public access from all networks'\n# 20.5    Ensure that 'Enable Data Access Authentication Mode' is 'Checked'\n# 20.6    Ensure that Only Approved Extensions Are Installed\n# 20.7    Ensure that Endpoint Protection for all Virtual Machines is installed\n# 20.8    [Legacy] Ensure that VHDs are Encrypted\n# 20.9    Ensure only MFA enabled identities can access privileged Virtual Machine \n# 20.10   Ensure Trusted Launch is enabled on Virtual Machines \n# 20.11   Ensure that encryption at host is enabled\n#\n# Refer to Section(s) 20 Page(s) 307-41 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_vms () {\n  print_function \"audit_azure_vms\"\n  check_message  \"Azure Virtual Machines\"\n}\n"
  },
  {
    "path": "modules/azure/compute/webapp/apps/audit_azure_app_service_apps.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_app_service_apps\n#\n# Check Azure App Service Apps\n#\n# 2.1.1   Ensure 'Java version' is currently supported (if in use) - TBD\n# 2.1.2   Ensure 'Python version' is currently supported (if in use) - TBD\n# 2.1.3   Ensure 'PHP version' is currently supported (if in use) - TBD\n# 2.1.4   Ensure 'Basic Authentication Publishing Credentials' are 'Disabled' - TBD\n# 2.1.5   Ensure 'FTP State' is set to 'FTPS only' or 'Disabled' - TBD\n# 2.1.6   Ensure 'HTTP version' is set to '2.0' (if in use) - TBD\n# 2.1.7   Ensure 'HTTPS Only' is set to 'On' - TBD\n# 2.1.8   Ensure 'Minimum Inbound TLS Version' is set to '1.2' or higher - TBD\n# 2.1.9   Ensure end-to-end TLS encryption is enabled - TBD\n# 2.1.10  Ensure 'Remote debugging' is set to 'Off' - TBD\n# 2.1.11  Ensure incoming client certificates are enabled and required (if in use) - TBD\n# 2.1.12  Ensure 'App Service authentication' is set to 'Enabled' - TBD\n# 2.1.13  Ensure managed identities are configured - TBD\n# 2.1.14  Ensure public network access is disabled - TBD\n# 2.1.15  Ensure App Service plan SKU supports private endpoints - TBD\n# 2.1.16  Ensure private endpoints are used to access App Service apps - TBD\n# 2.1.17  Ensure private endpoints used to access App Service apps use private DNS zones - TBD\n# 2.1.18  Ensure app is integrated with a virtual network - TBD\n# 2.1.19  Ensure configuration is routed through the virtual network integration - TBD\n# 2.1.20  Ensure all traffic is routed through the virtual network - TBD\n# 2.1.21  Ensure cross-origin resource sharing does not allow all origins - TBD\n#\n# Refer to Section(s) 2.1.1-21 Page(s) 23-89 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_app_service_apps () {\n  print_function \"audit_azure_app_service_apps\"\n  check_message  \"Azure App Service Apps\"\n  command=\"az webapp list --query \\\"[].id\\\" --output tsv\"\n  command_message   \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No App Service Apps found\"\n    return\n  fi\n  # 2.1.1   Ensure 'Java version' is currently supported (if in use) - TBD\n  audit_azure_app_service_java_versions\n  # 2.1.2   Ensure 'Python version' is currently supported (if in use) - TBD\n  audit_azure_app_service_python_versions\n  # 2.1.3   Ensure 'PHP version' is currently supported (if in use) - TBD\n  audit_azure_app_service_php_versions\n  # 2.1.4   Ensure 'Basic Authentication Publishing Credentials' are 'Disabled' - TBD\n  audit_azure_app_service_basic_authentication_publishing_credential_values\n  # 2.1.5   Ensure 'FTP State' is set to 'FTPS only' or 'Disabled' - TBD\n  audit_azure_app_service_ftp_states\n  # 2.1.6   Ensure 'HTTP version' is set to '2.0' (if in use) - TBD\n  # 2.1.7   Ensure 'HTTPS Only' is set to 'On' - TBD\n  audit_azure_app_service_http_values\n  # 2.1.8   Ensure 'Minimum Inbound TLS Version' is set to '1.2' or higher - TBD\n  # 2.1.9   Ensure end-to-end TLS encryption is enabled - TBD\n  audit_azure_app_service_tls_values\n  # 2.1.10  Ensure 'Remote debugging' is set to 'Off' - TBD\n  audit_azure_app_service_remote_debugging\n  # 2.1.11  Ensure incoming client certificates are enabled and required (if in use) - TBD\n  audit_azure_app_service_client_certificates\n  # 2.1.12  Ensure 'App Service authentication' is set to 'Enabled' - TBD\n  audit_azure_app_service_authentication\n  # 2.1.13  Ensure managed identities are configured - TBD\n  audit_azure_app_service_managed_identies\n  # 2.1.14  Ensure public network access is disabled - TBD\n  audit_azure_app_service_public_network_access\n  # 2.1.16  Ensure private endpoints are used to access App Service apps - TBD\n  audit_azure_app_service_private_endpoints\n  # 2.1.17  Ensure private endpoints used to access App Service apps use private DNS zones - TBD\n  audit_azure_app_service_private_dns_zones\n  # 2.1.18  Ensure app is integrated with a virtual network - TBD\n  audit_azure_app_service_virtual_network_integration\n  # 2.1.19  Ensure configuration is routed through the virtual network integration - TBD\n  # 2.1.20  Ensure all traffic is routed through the virtual network - TBD\n  audit_azure_app_service_vnets\n  # 2.1.21  Ensure cross-origin resource sharing does not allow all origins - TBD\n  audit_azure_app_service_cross_origin_resource_sharing\n  # 2.1.15  Ensure App Service plan SKU supports private endpoints - TBD\n  audit_azure_app_service_plans\n}\n"
  },
  {
    "path": "modules/azure/compute/webapp/apps/audit_azure_app_service_ases.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_app_service_ase\n#\n# Check Azure App Service ASE\n#\n# 2.6  Ensure App Service Environment is deployed with an internal load balancer - TBD\n# 2.7  Ensure App Service Environment is provisioned with v3 or higher - TBD\n# 2.8  Ensure App Service Environment has internal encryption enabled - TBD\n# 2.9  Ensure App Service Environment has TLS 1.0 and 1.1 disabled - TBD\n# 2.10 Ensure App Service Environment has TLS cipher suite ordering configured - TBD\n#\n# Refer to Section(s) 2.6-10 Page(s) 243-54 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_app_service_ase () {\n  print_function \"audit_azure_app_service_ase\"\n  check_message  \"Azure App Service ASE\"\n  command=\"az appservice ase list --query \\\"[].name\\\" --output tsv\"\n  command_message  \"${command}\"\n  ase_list=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${ase_list}\" ]; then\n    info_message \"No App Service ASE found\"\n  fi\n  for ase_name in ${ase_list}; do\n    check_azure_app_service_ase_value   \"Deployed with an internal load balancer\"         \"${ase_name}\" \"\"                \"internalLoadBalancingMode\"   \"ne\"  \"None\"\n    check_azure_app_service_ase_value   \"Provisioned with ${azure_ase_version} or higher\" \"${ase_name}\" \"\"                \"kind\"                        \"eq\"  \"${azure_ase_version}\"\n    check_azure_app_service_ase_value   \"Internal encryption enabled\"                     \"${ase_name}\" \"clusterSettings\" \"internalEncryption\"          \"eq\"  \"true\"\n    check_azure_app_service_ase_value   \"TLS 1.0 disabled\"                                \"${ase_name}\" \"clusterSettings\" \"DisableTls1.0\"               \"eq\"  \"1\"\n    check_azure_app_service_ase_value   \"TLS 1.1 disabled\"                                \"${ase_name}\" \"clusterSettings\" \"DisableTls1.1\"               \"eq\"  \"1\"\n    for cipher_suite in \"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384\" \"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256\" \"TLS_AES_256_GCM_SHA384\" \"TLS_AES_128_GCM_SHA256\"; do\n      check_azure_app_service_ase_value \"TLS cipher suite has ${cipher_suite}\"            \"${ase_name}\" \"clusterSettings\" \"FrontEndSSLCipherSuiteOrder\" \"has\" \"${cipher_suite}\"\n    done\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/webapp/apps/audit_azure_app_service_authentication.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_app_service_authentication\n#\n# Check Azure App Service Authentication\n#\n# 2.1.12  Ensure 'App Service authentication' is set to 'Enabled' - TBD\n#\n# Refer to Section(s) 2.1.12 Page(s) 60-2 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_app_service_authentication () {\n  print_function \"audit_azure_app_service_authentication\"\n  check_message  \"Azure App Service Authentication\"\n  command=\"az webapp list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No App Services found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"name\\\" --output tsv\"\n    command_message   \"${command}\"\n    app_name=$( eval  \"${command}\" )\n    check_azure_app_service_app_value \"App Service Auth v1\" \"${app_id}\" \"${app_name}\" \"${res_group}\" \"auth\" \"enabled\"          \"eq\" \"true\" \"--enabled\" \"\"\n    check_azure_app_service_app_value \"App Service Auth v2\" \"${app_id}\" \"${app_name}\" \"${res_group}\" \"auth\" \"platform.enabled\" \"eq\" \"true\" \"--enabled\" \"\"\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/webapp/apps/audit_azure_app_service_basic_authentication_publishing_credential_values.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_app_service_basic_authentication_publishing_credential_values\n#\n# Check Azure App Service Basic Authentication Publishing Credential Values\n#\n# 2.1.4   Ensure 'Basic Authentication Publishing Credentials' are 'Disabled' - TBD\n#\n# Refer to Section(s) 2.1.4 Page(s) 35-8 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_app_service_basic_authentication_publishing_credential_values () {\n  print_function \"audit_azure_app_service_basic_authentication_publishing_credential_values\"\n  check_message  \"Azure App Service Basic Authentication Publishing Credential Values\"\n  command=\"az webapp list --query \\\"[].id\\\" --output tsv\"\n  command_message   \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No App Services found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"name\\\" --output tsv\"\n    command_message   \"${command}\"\n    app_name=$( eval  \"${command}\" )\n    check_azure_basic_authentication_publishing_credential_value \"${app_name}\" \"${res_group}\" \"ftp\" \"Microsoft.Web\" \"basicPublishingCredentialsPolicies\" \"properties.allow\" \"eq\" \"false\" \"--auth-settings.publishing-credentials-enabled\" \"\"\n    check_azure_basic_authentication_publishing_credential_value \"${app_name}\" \"${res_group}\" \"scm\" \"Microsoft.Web\" \"basicPublishingCredentialsPolicies\" \"properties.allow\" \"eq\" \"false\" \"--auth-settings.publishing-credentials-enabled\" \"\"\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/webapp/apps/audit_azure_app_service_client_certificates.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_app_service_client_certificates\n#\n# Check Azure App Service Client Certificates\n#\n# 2.1.11  Ensure incoming client certificates are enabled and required (if in use) - TBD\n#\n# Refer to Section(s) 2.1.11 Page(s) 57-59 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_app_service_client_certificates () {\n  print_function \"audit_azure_app_service_client_certificates\"\n  check_message  \"Azure App Service Client Certificates\"\n  command=\"az webapp list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No App Services found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"name\\\" --output tsv\"\n    command_message   \"${command}\"\n    app_name=$( eval  \"${command}\" )\n    check_azure_app_service_app_value \"Client Certificates\" \"${app_id}\" \"${app_name}\" \"${res_group}\" \"Microsoft.Web/sites\" \"clientCertEnabled\" \"eq\" \"true\" \"clientCertEnabled\" \"\"\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/webapp/apps/audit_azure_app_service_cross_origin_resource_sharing.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_app_service_cross_origin_resource_sharing\n#\n# Check Azure App Service Cross-origin Resource sharing\n#\n# 2.1.21  Ensure cross-origin resource sharing does not allow all origins - TBD\n#\n# Refer to Section(s) 2.1.21 Page(s) 87-9 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_app_service_cross_origin_resource_sharing () {\n  print_function \"audit_azure_app_service_cross_origin_resource_sharing\"\n  check_message  \"Azure App Service Cross-Origin Resource Sharing\"\n  command=\"az webapp list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No App Services found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"name\\\" --output tsv\"\n    command_message   \"${command}\"\n    app_name=$( eval  \"${command}\" )\n    check_azure_app_service_app_value \"Cross-Origin Resource Sharing\" \"${app_id}\" \"${app_name}\" \"${res_group}\" \"cors\" \"siteConfig.cors.allowedOrigins\" \"ne\" \"*\" \"properties.cors.allowedOrigins\" \"\"\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/webapp/apps/audit_azure_app_service_ftp_states.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_app_service_ftp_states\n#\n# Check Azure App Service FTP States\n#\n# 2.1.5   Ensure 'FTP State' is set to 'FTPS only' or 'Disabled' - TBD\n#\n# Refer to Section(s) 2.1.5 Page(s) 39-41 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_app_service_ftp_states () {\n  print_function \"audit_azure_app_service_ftp_states\"\n  check_message  \"Azure App Service FTP States\"\n  command=\"az webapp list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No App Services found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"name\\\" --output tsv\"\n    command_message   \"${command}\"\n    app_name=$( eval  \"${command}\" )\n    check_azure_app_service_app_value \"FTP State\" \"${app_id}\" \"${app_name}\" \"${res_group}\" \"\" \"ftpState\" \"eq\" \"${azure_ftp_state}\" \"--ftp-state\" \"\"\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/webapp/apps/audit_azure_app_service_http_logs.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_app_service_http_logs\n#\n# Check Azure App Service HTTP Logs\n#\n# 6.1.1.6  Ensure that logging for Azure AppService 'HTTP logs' is enabled\n#\n# Refer to Section 6.1.1.6 Page(s) 213-4 CIS Microsoft Azure Foundations Benchmark v5.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_app_service_http_logs () {\n  print_function \"audit_azure_app_service_http_logs\"\n  check_message  \"Azure App Service HTTP Logs\"\n}\n"
  },
  {
    "path": "modules/azure/compute/webapp/apps/audit_azure_app_service_http_values.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_app_service_http_values\n#\n# Check Azure App Service HTTP Values\n#\n# 2.1.6   Ensure 'HTTP version' is set to '2.0' (if in use) - TBD\n# 2.1.7   Ensure 'HTTPS Only' is set to 'On' - TBD\n#\n# Refer to Section(s) 2.1.6-7 Page(s) 42-7 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_app_service_http_values () {\n  print_function \"audit_azure_app_service_http_values\"\n  check_message  \"Azure App Service HTTP Values\"\n  command=\"az webapp list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No App Services found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"name\\\" --output tsv\"\n    command_message   \"${command}\"\n    app_name=$( eval  \"${command}\" )\n    check_azure_app_service_app_value \"HTTP Version\" \"${app_id}\" \"${app_name}\" \"${res_group}\" \"\" \"http20Enabled\" \"eq\" \"true\" \"--http20-enabled\" \"\"\n    check_azure_app_service_app_value \"HTTPS Only\"   \"${app_id}\" \"${app_name}\" \"${res_group}\" \"\" \"httpsOnly\"     \"eq\" \"true\" \"httpsOnly\"        \"\"\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/webapp/apps/audit_azure_app_service_java_versions.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_app_service_java_versions\n#\n# Check Azure App Service Java Versions\n#\n# 2.1.1   Ensure 'Java version' is currently supported (if in use) - TBD\n#\n# Refer to Section(s) 2.1.1 Page(s) 23-28 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_app_service_java_versions () {\n  print_function \"audit_azure_app_service_java_versions\"\n  check_message  \"Azure App Service Java Versions\"\n  command=\"az webapp list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No App Services found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"name\\\" --output tsv\"\n    command_message   \"${command}\"\n    app_name=$( eval  \"${command}\" )\n    check_azure_app_service_app_value \"Java Version\"           \"${app_id}\" \"${app_name}\" \"${res_group}\" \"\" \"javaVersion\"          \"eq\" \"${azure_java_version}\" \"--java-version\"           \"\"\n    check_azure_app_service_app_value \"Java Container Version\" \"${app_id}\" \"${app_name}\" \"${res_group}\" \"\" \"javaContainerVersion\" \"eq\" \"${azure_java_version}\" \"--java-container-version\" \"\"\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/webapp/apps/audit_azure_app_service_managed_identies.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_app_service_managed_identies\n#\n# Check Azure App Service Managed Identities\n#\n# 2.1.13  Ensure managed identities are configured - TBD\n#\n# Refer to Section(s) 2.1.13 Page(s) 63-5 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_app_service_managed_identies () {\n  print_function \"audit_azure_app_service_managed_identies\"\n  check_message  \"Azure App Service Managed Identities\"\n  command=\"az webapp list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No App Services found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"name\\\" --output tsv\"\n    command_message   \"${command}\"\n    app_name=$( eval  \"${command}\" )\n    check_azure_app_service_app_value \"Managed Identities\" \"${app_id}\" \"${app_name}\" \"${res_group}\" \"identity\" \"type\" \"eq\" \"${azure_managed_identity}\" \"\" \"\"\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/webapp/apps/audit_azure_app_service_php_versions.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_app_service_php_versions\n#\n# Check Azure App Service PHP Versions\n#\n# 2.1.3   Ensure 'PHP version' is currently supported (if in use) - TBD\n#\n# Refer to Section(s) 2.1.3 Page(s) 32-4 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_app_service_php_versions () {\n  print_function \"audit_azure_app_service_php_versions\"\n  check_message  \"Azure App Service PHP Versions\"\n  command=\"az webapp list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No App Services found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"name\\\" --output tsv\"\n    command_message   \"${command}\"\n    app_name=$( eval  \"${command}\" )\n    check_azure_app_service_app_value \"PHP Version\" \"${app_id}\" \"${app_name}\" \"${res_group}\" \"\" \"phpVersion\" \"eq\" \"${azure_php_version}\" \"--php-version\" \"\"\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/webapp/apps/audit_azure_app_service_plans.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_app_service_plans\n#\n# Check Azure App Service Plans\n#\n# 2.1.15  Ensure App Service plan SKU supports private endpoints - TBD\n#\n# Refer to Section(s) 2.1.15 Page(s) 69-72 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_app_service_plans () {\n  print_function \"audit_azure_app_service_plans\"\n  check_message  \"Azure App Service Plans\"\n  command=\"az webapp list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No App Services found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"appServicePlanId\\\" --output tsv\"\n    command_message   \"${command}\"\n    app_plans=$( eval \"${command}\" )\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    if [ -z \"${app_plans}\" ]; then\n      info_message \"No App Service Plans found\"\n      return\n    fi\n    for app_plan in ${app_plans}; do\n      check_azure_app_service_plan_value \"${app_plan}\" \"${res_group}\" \"sku.tier\" \"eq\" \"${azure_sku_tier}\" \"--sku\" \"\"\n    done\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/webapp/apps/audit_azure_app_service_private_dns_zones.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_app_service_private_dns_zones\n#\n# Check Azure App Service Private DNS Zones\n#\n# 2.1.17  Ensure private endpoints used to access App Service apps use private DNS zones - TBD\n#\n# Refer to Section(s) 2.1.17 Page(s) 69-72 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_app_service_private_dns_zones () {\n  print_function \"audit_azure_app_service_private_dns_zones\"\n  check_message  \"Azure App Service Private DNS Zones\"\n  command=\"az webapp list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No App Services found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"name\\\" --output tsv\"\n    command_message   \"${command}\"\n    app_name=$( eval  \"${command}\" )\n    check_azure_app_service_app_value \"Private DNS Zones\" \"${app_id}\" \"${app_name}\" \"${res_group}\" \"Microsoft.Web/sites\" \"dnsConfiguration.dnsServers\" \"ne\" \"\" \"\" \"\"\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/webapp/apps/audit_azure_app_service_private_endpoints.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_app_service_private_endpoints\n#\n# Check Azure App Service Private Endpoints\n#\n# 2.1.16  Ensure private endpoints are used to access App Service apps - TBD\n#\n# Refer to Section(s) 2.1.16 Page(s) 73-5 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_app_service_private_endpoints () {\n  print_function \"audit_azure_app_service_private_endpoints\"\n  check_message  \"Azure App Service Private Endpoints\"\n  command=\"az webapp list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No App Services found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    check_azure_network_private_endpoint_value \"${app_id}\" \"[*].privateLinkServiceConnections[*].[privateLinkServiceId,privateLinkServiceConnectionState.status]\" \"eq\" \"Approved\"\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/webapp/apps/audit_azure_app_service_public_network_access.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_app_service_public_network_access\n#\n# Check Azure App Service Public Network Access\n#\n# 2.1.14  Ensure public network access is disabled - TBD\n#\n# Refer to Section(s) 2.1.14 Page(s) 66-8 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_app_service_public_network_access () {\n  print_function \"audit_azure_app_service_public_network_access\"\n  check_message  \"Azure App Service Public Network Access\"\n  command=\"az webapp list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No App Services found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"name\\\" --output tsv\"\n    command_message   \"${command}\"\n    app_name=$( eval  \"${command}\" )\n    check_azure_app_service_app_value \"Public Network Access\" \"${app_id}\" \"${app_name}\" \"${res_group}\" \"\" \"publicNetworkAccess\" \"eq\" \"Disabled\" \"properties.publicNetworkAccess\" \"\"\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/webapp/apps/audit_azure_app_service_python_versions.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_app_service_python_versions\n#\n# Check Azure App Service Python Versions\n#\n# 2.1.2   Ensure 'Python version' is currently supported (if in use) - TBD\n#\n# Refer to Section(s) 2.1.2 Page(s) 29-31 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_app_service_python_versions () {\n  print_function \"audit_azure_app_service_python_versions\"\n  check_message  \"Azure App Service Python Versions\"\n  command=\"az webapp list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No App Services found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"name\\\" --output tsv\"\n    command_message   \"${command}\"\n    app_name=$( eval  \"${command}\" )\n    check_azure_app_service_app_value \"Python Version\" \"${app_id}\" \"${app_name}\" \"${res_group}\" \"\" \"pythonVersion\" \"eq\" \"${azure_python_version}\" \"--python-version\"                               \"\"\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/webapp/apps/audit_azure_app_service_remote_debugging.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_app_service_remote_debugging\n#\n# Check Azure App Service Remote Debugging\n#\n# 2.1.10  Ensure 'Remote debugging' is set to 'Off' - TBD\n#\n# Refer to Section(s) 2.1.10 Page(s) 54-6 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_app_service_remote_debugging () {\n  print_function \"audit_azure_app_service_remote_debugging\"\n  check_message  \"Azure App Service Remote Debugging\"\n  command=\"az webapp list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No App Services found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"name\\\" --output tsv\"\n    command_message   \"${command}\"\n    app_name=$( eval  \"${command}\" )\n    check_azure_app_service_app_value \"Remote Debugging\" \"${app_id}\" \"${app_name}\" \"${res_group}\" \"\" \"remoteDebuggingEnabled\" \"eq\" \"false\" \"--remote-debugging-enabled\" \"\"\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/webapp/apps/audit_azure_app_service_tls_values.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_app_service_tls_values\n#\n# Check Azure App Service TLS Values\n#\n# 2.1.8   Ensure 'Minimum Inbound TLS Version' is set to '1.2' or higher - TBD\n# 2.1.9   Ensure end-to-end TLS encryption is enabled - TBD\n#\n# Refer to Section(s) 2.1.8-9 Page(s) 48-53 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_app_service_tls_values () {\n  print_function \"audit_azure_app_service_tls_values\"\n  check_message  \"Azure App Service TLS Values\"\n  command=\"az webapp list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No App Services found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"name\\\" --output tsv\"\n    command_message   \"${command}\"\n    app_name=$( eval  \"${command}\" )\n    check_azure_app_service_app_value \"Minimum Inbound TLS Version\" \"${app_id}\" \"${app_name}\" \"${res_group}\" \"\"                    \"minTlsVersion\"             \"eq\" \"1.2\"  \"--min-tls-version\"                    \"\"\n    check_azure_app_service_app_value \"End-to-End TLS Encryption\"   \"${app_id}\" \"${app_name}\" \"${res_group}\" \"Microsoft.Web/sites\" \"endToEndEncryptionEnabled\" \"eq\" \"true\" \"properties.endToEndEncryptionEnabled\" \"\"\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/webapp/apps/audit_azure_app_service_virtual_network_integration.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_app_service_virtual_network_integration\n#\n# Check Azure App Service Virtual Network Integration\n#\n# 2.1.18  Ensure app is integrated with a virtual network - TBD\n#\n# Refer to Section(s) 2.1.18 Page(s) 78-81 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_app_service_virtual_network_integration () {\n  print_function \"audit_azure_app_service_virtual_network_integration\"\n  check_message  \"Azure App Service Virtual Network Integration\"\n  command=\"az webapp list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No App Services found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"name\\\" --output tsv\"\n    command_message   \"${command}\"\n    app_name=$( eval  \"${command}\" )\n    check_azure_app_service_app_value \"Virtual Network Integration\" \"${app_id}\" \"${app_name}\" \"${res_group}\" \"\" \"virtualNetworkSubnetId\" \"ne\" \"\" \"\" \"\"\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/webapp/apps/audit_azure_app_service_vnets.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_app_service_vnets\n#\n# Check Azure App Service VNets\n#\n# 2.1.19  Ensure configuration is routed through the virtual network integration - TBD\n# 2.1.20  Ensure all traffic is routed through the virtual network - TBD\n#\n# Refer to Section(s) 2.1.19-20 Page(s) 82-86 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_app_service_vnets () {\n  print_function \"audit_azure_app_service_vnets\"\n  check_message  \"Azure App Service VNets\"\n  command=\"az webapp list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No App Services found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"name\\\" --output tsv\"\n    command_message   \"${command}\"\n    app_name=$( eval  \"${command}\" )\n    check_azure_app_service_app_value \"VNet Image Pull\"    \"${app_id}\" \"${app_name}\" \"${res_group}\" \"Microsoft.Web/sites\" \"vnetRouteAllEnabled\"     \"eq\" \"true\" \"properties.vnetRouteAllEnabled\"     \"\"\n    check_azure_app_service_app_value \"VNet Content Share\" \"${app_id}\" \"${app_name}\" \"${res_group}\" \"Microsoft.Web/sites\" \"vnetContentShareEnabled\" \"eq\" \"true\" \"properties.vnetContentShareEnabled\" \"\"\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/webapp/slots/audit_azure_app_service_deployment_slots.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_app_service_deployment_slots\n#\n# App Service Deployment Slots\n# 2.2.1   Ensure 'Java version' is currently supported (if in use) - TBD\n# 2.2.2   Ensure 'Python version' is currently supported (if in use) - TBD\n# 2.2.3   Ensure 'PHP version' is currently supported (if in use) - TBD\n# 2.2.4   Ensure 'Basic Authentication Publishing Credentials' are 'Disabled' - TBD\n# 2.2.5   Ensure 'FTP State' is set to 'FTPS only' or 'Disabled' - TBD\n# 2.2.6   Ensure 'HTTP version' is set to '2.0' (if in use) - TBD\n# 2.2.7   Ensure 'HTTPS Only' is set to 'On' - TBD\n# 2.2.8   Ensure 'Minimum Inbound TLS Version' is set to '1.2' or higher - TBD\n# 2.2.9   Ensure end-to-end TLS encryption is enabled - TBD\n# 2.2.10  Ensure 'Remote debugging' is set to 'Off' - TBD\n# 2.2.11  Ensure incoming client certificates are enabled and required (if in use) - TBD\n# 2.2.12  Ensure managed identities are configured - TBD\n# 2.2.13  Ensure public network access is disabled - TBD\n# 2.2.14  Ensure deployment slot is integrated with a virtual network - TBD\n# 2.2.15  Ensure configuration is routed through the virtual network integration - TBD\n# 2.2.16  Ensure all traffic is routed through the virtual network - TBD\n# 2.2.17  Ensure cross-origin resource sharing does not allow all origins - TBD\n#\n# Refer to Section(s) 2.2.1-17 Page(s) 90-141 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_app_service_deployment_slots () {\n  print_function \"audit_azure_app_service_deployment_slots\"\n  check_message  \"Azure App Service Deployment Slots\"\n  command=\"az webapp list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message  \"No App Service Apps found\"\n    return\n  fi\n  # 2.2.1   Ensure 'Java version' is currently supported (if in use) - TBD\n  audit_azure_app_service_deployment_slots_java_versions\n  # 2.2.2   Ensure 'Python version' is currently supported (if in use) - TBD\n  audit_azure_app_service_deployment_slots_python_versions\n  # 2.2.3   Ensure 'PHP version' is currently supported (if in use) - TBD\n  audit_azure_app_service_deployment_slots_php_versions\n  # 2.2.4   Ensure 'Basic Authentication Publishing Credentials' are 'Disabled' - TBD\n  audit_azure_app_service_deployment_slots_basic_auth\n  # 2.2.5   Ensure 'FTP State' is set to 'FTPS only' or 'Disabled' - TBD\n  audit_azure_app_service_deployment_slots_ftp_states\n  # 2.2.6   Ensure 'HTTP version' is set to '2.0' (if in use) - TBD\n  # 2.2.7   Ensure 'HTTPS Only' is set to 'On' - TBD\n  audit_azure_app_service_deployment_slots_http_values\n  # 2.2.8   Ensure 'Minimum Inbound TLS Version' is set to '1.2' or higher - TBD\n  # 2.2.9   Ensure end-to-end TLS encryption is enabled - TBD\n  audit_azure_app_service_deployment_slots_tls_values\n  # 2.2.10  Ensure 'Remote debugging' is set to 'Off' - TBD\n  audit_azure_app_service_deployment_slots_remote_debugging\n  # 2.2.11  Ensure incoming client certificates are enabled and required (if in use) - TBD\n  audit_azure_app_service_deployment_slots_client_certificates\n  # 2.2.12  Ensure managed identities are configured - TBD\n  audit_azure_app_service_deployment_slots_managed_identities\n  # 2.2.13  Ensure public network access is disabled - TBD\n  audit_azure_app_service_deployment_slots_public_network_access\n  # 2.2.14  Ensure app is integrated with a virtual network - TBD\n  # 2.2.15  Ensure configuration is routed through the virtual network integration - TBD\n  audit_azure_app_service_deployment_slots_virtual_network_integration\n  # 2.2.17  Ensure cross-origin resource sharing does not allow all origins - TBD\n  audit_azure_app_service_deployment_slots_cross_origin_resource_sharing\n  # 2.2.16  Ensure private endpoints are used to access App Service apps - TBD\n  audit_azure_app_service_deployment_slots_private_endpoints\n}\n"
  },
  {
    "path": "modules/azure/compute/webapp/slots/audit_azure_app_service_deployment_slots_basic_authentication_publishing_credentials.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_app_service_deployment_slots_basic_authentication_publishing_credentials\n#\n# 2.2.4   Ensure 'Basic Authentication Publishing Credentials' are 'Disabled' - TBD\n#\n# Refer to Section(s) 2.2.4 Page(s) 100-3 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_app_service_deployment_slots_basic_authentication_publishing_credentials () {\n  print_function \"audit_azure_app_service_deployment_slots_basic_authentication_publishing_credentials\"\n  check_message  \"Azure App Service Deployment Slot Basic Authentication Publishing Credentials\"\n  command=\"az webapp list --query \\\"[].id\\\" --output tsv\"\n  command_message   \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No App Service Deployment Slots found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"name\\\" --output tsv\"\n    command_message   \"${command}\"\n    app_name=$( eval  \"${command}\" )\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    command=\"az webapp deployment slot list --id \\\"${app_id}\\\" --query \\\"[].id\\\" --output tsv\"\n    command_message   \"${command}\"\n    slot_ids=$( eval  \"${command}\" 2> /dev/null )\n    if [ -z \"${slot_ids}\" ]; then\n      info_message \"No App Service Deployment Slots found\"\n      return\n    fi\n    for slot_id in ${slot_ids}; do\n      check_azure_app_service_deployment_slot_value \"Basic Authentication Publishing Credentials\" \"${slot_id}\" \"${app_name}\" \"${res_group}\" \"basicPublishingCredentialsPolicies\" \"ftp\" \"Microsoft.Web/sites\" \"properties.allow\" \"eq\" \"false\" \"\" \"\"\n      check_azure_app_service_deployment_slot_value \"Basic Authentication Publishing Credentials\" \"${slot_id}\" \"${app_name}\" \"${res_group}\" \"basicPublishingCredentialsPolicies\" \"scm\" \"Microsoft.Web/sites\" \"properties.allow\" \"eq\" \"false\" \"\" \"\"\n    done\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/webapp/slots/audit_azure_app_service_deployment_slots_client_certificates.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_app_service_deployment_slots_client_certificates\n#\n# 2.2.11  Ensure incoming client certificates are enabled and required (if in use) - TBD\n#\n# Refer to Section(s) 2.2.11 Page(s) 122-4 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_app_service_deployment_slots_client_certificates () {\n  print_function \"audit_azure_app_service_deployment_slots_client_certificates\"\n  check_message  \"Azure App Service Deployment Slot Client Certificates\"\n  command=\"az webapp list --query \\\"[].id\\\" --output tsv\"\n  command_message   \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No App Service Deployment Slots found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"name\\\" --output tsv\"\n    command_message   \"${command}\"\n    app_name=$( eval  \"${command}\" )\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    command=\"az webapp deployment slot list --id \\\"${app_id}\\\" --query \\\"[].id\\\" --output tsv\"\n    command_message   \"${command}\"\n    slot_ids=$( eval  \"${command}\" 2> /dev/null )\n    if [ -z \"${slot_ids}\" ]; then\n      info_message \"No App Service Deployment Slots found\"\n      return\n    fi\n    for slot_id in ${slot_ids}; do\n      check_azure_app_service_deployment_slot_value \"Client Certificates\" \"${slot_id}\" \"${app_name}\" \"${res_group}\" \"config\" \"web\" \"Microsoft.Web/sites\" \"clientCertEnabled\" \"eq\" \"true\" \"clientCertEnabled\" \"\"\n    done\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/webapp/slots/audit_azure_app_service_deployment_slots_cross_origin_resource_sharing.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_app_service_deployment_slots_cross_origin_resource_sharing\n#\n# 2.2.17  Ensure cross-origin resource sharing does not allow all origins - TBD\n#\n# Refer to Section(s) 2.2.17 Page(s) 139-41 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_app_service_deployment_slots_cross_origin_resource_sharing () {\n  print_function \"audit_azure_app_service_deployment_slots_cross_origin_resource_sharing\"\n  check_message  \"Azure App Service Deployment Slot Cross-Origin Resource Sharing\"\n  command=\"az webapp list --query \\\"[].id\\\" --output tsv\"\n  command_message   \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No App Service Deployment Slots found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"name\\\" --output tsv\"\n    command_message   \"${command}\"\n    app_name=$( eval  \"${command}\" )\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    command=\"az webapp deployment slot list --id \\\"${app_id}\\\" --query \\\"[].id\\\" --output tsv\"\n    command_message   \"${command}\"\n    slot_ids=$( eval  \"${command}\" 2> /dev/null )\n    if [ -z \"${slot_ids}\" ]; then\n      info_message \"No App Service Deployment Slots found\"\n      return\n    fi\n    for slot_id in ${slot_ids}; do\n      check_azure_app_service_deployment_slot_value \"Cross-Origin Resource Sharing\" \"${slot_id}\" \"${app_name}\" \"${res_group}\" \"config\" \"web\" \"cors\" \"siteConfig.cors.allowedOrigins\" \"ne\" \"*\" \"properties.cors.allowedOrigins\" \"\"\n    done\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/webapp/slots/audit_azure_app_service_deployment_slots_ftp_states.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_app_service_deployment_slots_ftp_states\n#\n# 2.2.5   Ensure 'FTP State' is set to 'FTPS only' or 'Disabled' - TBD\n#\n# Refer to Section(s) 2.2.5 Page(s) 104-6 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_app_service_deployment_slots_ftp_states () {\n  print_function \"audit_azure_app_service_deployment_slots_ftp_states\"\n  check_message  \"Azure App Service Deployment Slot FTP States\"\n  command=\"az webapp list --query \\\"[].id\\\" --output tsv\"\n  command_message   \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No App Service Deployment Slots found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"name\\\" --output tsv\"\n    command_message   \"${command}\"\n    app_name=$( eval  \"${command}\" )\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    command=\"az webapp deployment slot list --id \\\"${app_id}\\\" --query \\\"[].id\\\" --output tsv\"\n    command_message   \"${command}\"\n    slot_ids=$( eval  \"${command}\" 2> /dev/null )\n    if [ -z \"${slot_ids}\" ]; then\n      info_message \"No App Service Deployment Slots found\"\n      return\n    fi\n    for slot_id in ${slot_ids}; do\n      check_azure_app_service_deployment_slot_value \"FTP State\" \"${slot_id}\" \"${app_name}\" \"${res_group}\" \"config\" \"ftp\" \"Microsoft.Web/sites\" \"ftpState\" \"eq\" \"${azure_ftp_state}\" \"--ftp-state\" \"\"\n    done\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/webapp/slots/audit_azure_app_service_deployment_slots_http_values.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_app_service_deployment_slots_http_versions\n#\n# 2.2.6   Ensure 'HTTP version' is set to '2.0' (if in use) - TBD\n# 2.2.7   Ensure 'HTTPS Only' is set to 'On' - TBD\n#\n# Refer to Section(s) 2.2.6 Page(s) 107-12 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_app_service_deployment_slots_http_versions () {\n  print_function \"audit_azure_app_service_deployment_slots_http_versions\"\n  check_message  \"Azure App Service Deployment Slot HTTP Versions\"\n  command=\"az webapp list --query \\\"[].id\\\" --output tsv\"\n  command_message   \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No App Service Deployment Slots found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"name\\\" --output tsv\"\n    command_message   \"${command}\"\n    app_name=$( eval  \"${command}\" )\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    command=\"az webapp deployment slot list --id \\\"${app_id}\\\" --query \\\"[].id\\\" --output tsv\"\n    command_message   \"${command}\"\n    slot_ids=$( eval  \"${command}\" 2> /dev/null )\n    if [ -z \"${slot_ids}\" ]; then\n      info_message \"No App Service Deployment Slots found\"\n      return\n    fi\n    for slot_id in ${slot_ids}; do\n      check_azure_app_service_deployment_slot_value \"HTTP Version\" \"${slot_id}\" \"${app_name}\" \"${res_group}\" \"config\" \"web\" \"Microsoft.Web/sites\" \"http20Enabled\" \"eq\" \"true\" \"--http20-enabled\" \"\"\n      check_azure_app_service_deployment_slot_value \"HTTPS Only\"   \"${slot_id}\" \"${app_name}\" \"${res_group}\" \"config\" \"web\" \"Microsoft.Web/sites\" \"httpsOnly\"     \"eq\" \"true\" \"httpsOnly\"        \"\"\n    done\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/webapp/slots/audit_azure_app_service_deployment_slots_java_versions.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_app_service_deployment_slots_java_versions\n#\n# 2.2.1   Ensure 'Java version' is currently supported (if in use) - TBD\n#\n# Refer to Section(s) 2.2.1 Page(s) 91-93 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_app_service_deployment_slots_java_versions () {\n  print_function \"audit_azure_app_service_deployment_slots_java_versions\"\n  check_message  \"Azure App Service Deployment Slot Java Versions\"\n  command=\"az webapp list --query \\\"[].id\\\" --output tsv\"\n  command_message   \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No App Service Deployment Slots found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"name\\\" --output tsv\"\n    command_message   \"${command}\"\n    app_name=$( eval  \"${command}\" )\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    command=\"az webapp deployment slot list --id \\\"${app_id}\\\" --query \\\"[].id\\\" --output tsv\"\n    command_message   \"${command}\"\n    slot_ids=$( eval  \"${command}\" 2> /dev/null )\n    if [ -z \"${slot_ids}\" ]; then\n      info_message \"No App Service Deployment Slots found\"\n      return\n    fi\n    for slot_id in ${slot_ids}; do\n      check_azure_app_service_deployment_slot_value \"Java Version\"           \"${slot_id}\" \"${app_name}\" \"${res_group}\" \"config\" \"web\" \"Microsoft.Web/sites\" \"javaVersion\"          \"eq\" \"${azure_java_version}\" \"--java-version\"           \"\"\n      check_azure_app_service_deployment_slot_value \"Java Container Version\" \"${slot_id}\" \"${app_name}\" \"${res_group}\" \"config\" \"web\" \"Microsoft.Web/sites\" \"javaContainerVersion\" \"eq\" \"${azure_java_version}\" \"--java-container-version\" \"\"\n    done\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/webapp/slots/audit_azure_app_service_deployment_slots_managed_identities.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_app_service_deployment_slots_managed_identities\n#\n# 2.2.12  Ensure managed identities are configured - TBD\n#\n# Refer to Section(s) 2.2.12 Page(s) 125-7 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_app_service_deployment_slots_managed_identities () {\n  print_function \"audit_azure_app_service_deployment_slots_managed_identities\"\n  check_message  \"Azure App Service Deployment Slot Managed Identities\"\n  command=\"az webapp list --query \\\"[].id\\\" --output tsv\"\n  command_message   \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No App Service Deployment Slots found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"name\\\" --output tsv\"\n    command_message   \"${command}\"\n    app_name=$( eval  \"${command}\" )\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    command=\"az webapp deployment slot list --id \\\"${app_id}\\\" --query \\\"[].id\\\" --output tsv\"\n    command_message   \"${command}\"\n    slot_ids=$( eval  \"${command}\" 2> /dev/null )\n    if [ -z \"${slot_ids}\" ]; then\n      info_message \"No App Service Deployment Slots found\"\n      return\n    fi\n    for slot_id in ${slot_ids}; do\n      check_azure_app_service_deployment_slot_value \"Managed Identities\" \"${slot_id}\" \"${app_name}\" \"${res_group}\" \"config\" \"web\" \"identity\" \"type\" \"eq\" \"${azure_managed_identity}\" \"\" \"\"\n    done\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/webapp/slots/audit_azure_app_service_deployment_slots_php_versions.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_app_service_deployment_slots_php_versions\n#\n# 2.2.3   Ensure 'PHP version' is currently supported (if in use) - TBD\n#\n# Refer to Section(s) 2.2.3 Page(s) 97-99 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_app_service_deployment_slots_php_versions () {\n  print_function \"audit_azure_app_service_deployment_slots_php_versions\"\n  check_message  \"Azure App Service Deployment Slot PHP Versions\"\n  command=\"az webapp list --query \\\"[].id\\\" --output tsv\"\n  command_message   \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No App Service Deployment Slots found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"name\\\" --output tsv\"\n    command_message   \"${command}\"\n    app_name=$( eval  \"${command}\" )\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    command=\"az webapp deployment slot list --id \\\"${app_id}\\\" --query \\\"[].id\\\" --output tsv\"\n    command_message   \"${command}\"\n    slot_ids=$( eval  \"${command}\" 2> /dev/null )\n    if [ -z \"${slot_ids}\" ]; then\n      info_message \"No App Service Deployment Slots found\"\n      return\n    fi\n    for slot_id in ${slot_ids}; do\n      check_azure_app_service_deployment_slot_value \"PHP Version\" \"${slot_id}\" \"${app_name}\" \"${res_group}\" \"config\" \"web\" \"Microsoft.Web/sites\" \"phpVersion\" \"eq\" \"${azure_php_version}\" \"--php-version\" \"\"\n    done\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/webapp/slots/audit_azure_app_service_deployment_slots_private_endpoints.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_app_service_deployment_slots_private_endpoints\n#\n# 2.2.16  Ensure private endpoints are used to access App Service apps - TBD\n#\n# Refer to Section(s) 2.2.16 Page(s) 136-8 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_app_service_deployment_slots_private_endpoints () {\n  print_function \"audit_azure_app_service_deployment_slots_private_endpoints\"\n  check_message  \"Azure App Service Deployment Slot Private Endpoints\"\n  command=\"az webapp list --query \\\"[].id\\\" --output tsv\"\n  command_message   \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No App Service Deployment Slots found\"\n    return\n  fi\n  command=\"az webapp list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  for app_id in ${app_ids}; do\n    check_azure_network_private_endpoint_value \"${app_id}\" \"[*].privateLinkServiceConnections[*].[privateLinkServiceId,privateLinkServiceConnectionState.status]\" \"eq\" \"Approved\"\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/webapp/slots/audit_azure_app_service_deployment_slots_public_network_access.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_app_service_deployment_slots_public_network_access\n#\n# 2.2.13  Ensure public network access is disabled - TBD\n#\n# Refer to Section(s) 2.2.13 Page(s) 128-30 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_app_service_deployment_slots_public_network_access () {\n  print_function \"audit_azure_app_service_deployment_slots_public_network_access\"\n  check_message  \"Azure App Service Deployment Slot Public Network Access\"\n  command=\"az webapp list --query \\\"[].id\\\" --output tsv\"\n  command_message   \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No App Service Deployment Slots found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"name\\\" --output tsv\"\n    command_message   \"${command}\"\n    app_name=$( eval  \"${command}\" )\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    command=\"az webapp deployment slot list --id \\\"${app_id}\\\" --query \\\"[].id\\\" --output tsv\"\n    command_message   \"${command}\"\n    slot_ids=$( eval  \"${command}\" 2> /dev/null )\n    if [ -z \"${slot_ids}\" ]; then\n      info_message \"No App Service Deployment Slots found\"\n      return\n    fi\n    for slot_id in ${slot_ids}; do\n      check_azure_app_service_deployment_slot_value \"Public Network Access\" \"${slot_id}\" \"${app_name}\" \"${res_group}\" \"config\" \"web\" \"Microsoft.Web/sites\" \"publicNetworkAccess\" \"eq\" \"Disabled\" \"properties.publicNetworkAccess\" \"\"\n    done\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/webapp/slots/audit_azure_app_service_deployment_slots_python_versions.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_app_service_deployment_slots_python_versions\n#\n# 2.2.2   Ensure 'Python version' is currently supported (if in use) - TBD\n#\n# Refer to Section(s) 2.2.2 Page(s) 94-96 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_app_service_deployment_slots_python_versions () {\n  print_function \"audit_azure_app_service_deployment_slots_python_versions\"\n  check_message  \"Azure App Service Deployment Slot Python Versions\"\n  command=\"az webapp list --query \\\"[].id\\\" --output tsv\"\n  command_message   \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No App Service Deployment Slots found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"name\\\" --output tsv\"\n    command_message   \"${command}\"\n    app_name=$( eval  \"${command}\" )\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    command=\"az webapp deployment slot list --id \\\"${app_id}\\\" --query \\\"[].id\\\" --output tsv\"\n    command_message   \"${command}\"\n    slot_ids=$( eval  \"${command}\" 2> /dev/null )\n    if [ -z \"${slot_ids}\" ]; then\n      info_message \"No App Service Deployment Slots found\"\n      return\n    fi\n    for slot_id in ${slot_ids}; do\n      check_azure_app_service_deployment_slot_value \"Python Version\" \"${slot_id}\" \"${app_name}\" \"${res_group}\" \"config\" \"web\" \"Microsoft.Web/sites\" \"pythonVersion\" \"eq\" \"${azure_python_version}\" \"--python-version\"\n    done\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/webapp/slots/audit_azure_app_service_deployment_slots_remote_debugging.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_app_service_deployment_slots_remote_debugging\n#\n# 2.2.10  Ensure 'Remote debugging' is set to 'Off' - TBD\n#\n# Refer to Section(s) 2.2.10 Page(s) 119-21 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_app_service_deployment_slots_remote_debugging () {\n  print_function \"audit_azure_app_service_deployment_slots_remote_debugging\"\n  check_message  \"Azure App Service Deployment Slot Remote Debugging\"\n  command=\"az webapp list --query \\\"[].id\\\" --output tsv\"\n  command_message   \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No App Service Deployment Slots found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"name\\\" --output tsv\"\n    command_message   \"${command}\"\n    app_name=$( eval  \"${command}\" )\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    command=\"az webapp deployment slot list --id \\\"${app_id}\\\" --query \\\"[].id\\\" --output tsv\"\n    command_message   \"${command}\"\n    slot_ids=$( eval  \"${command}\" 2> /dev/null )\n    if [ -z \"${slot_ids}\" ]; then\n      info_message \"No App Service Deployment Slots found\"\n      return\n    fi\n    for slot_id in ${slot_ids}; do\n      check_azure_app_service_deployment_slot_value \"Remote Debugging\" \"${slot_id}\" \"${app_name}\" \"${res_group}\" \"config\" \"web\" \"Microsoft.Web/sites\" \"remoteDebuggingEnabled\" \"eq\" \"false\" \"--remote-debugging-enabled\" \"\"\n    done\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/webapp/slots/audit_azure_app_service_deployment_slots_tls_values.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_app_service_deployment_slots_tls_values\n#\n# 2.2.8   Ensure 'Minimum Inbound TLS Version' is set to '1.2' or higher - TBD\n#\n# Refer to Section(s) 2.2.8 Page(s) 113-8 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_app_service_deployment_slots_tls_values () {\n  print_function \"audit_azure_app_service_deployment_slots_tls_values\"\n  check_message  \"Azure App Service Deployment Slot TLS Values\"\n  command=\"az webapp list --query \\\"[].id\\\" --output tsv\"\n  command_message   \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No App Service Deployment Slots found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"name\\\" --output tsv\"\n    command_message   \"${command}\"\n    app_name=$( eval  \"${command}\" )\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    command=\"az webapp deployment slot list --id \\\"${app_id}\\\" --query \\\"[].id\\\" --output tsv\"\n    command_message   \"${command}\"\n    slot_ids=$( eval  \"${command}\" 2> /dev/null )\n    if [ -z \"${slot_ids}\" ]; then\n      info_message \"No App Service Deployment Slots found\"\n      return\n    fi\n    for slot_id in ${slot_ids}; do\n      check_azure_app_service_deployment_slot_value \"Minimum Inbound TLS Version\" \"${slot_id}\" \"${app_name}\" \"${res_group}\" \"config\" \"web\" \"Microsoft.Web/sites\" \"minTlsVersion\"             \"eq\" \"1.2\"  \"--min-tls-version\"                    \"\"\n      check_azure_app_service_deployment_slot_value \"End-to-End TLS Encryption\"   \"${slot_id}\" \"${app_name}\" \"${res_group}\" \"config\" \"web\" \"Microsoft.Web/sites\" \"endToEndEncryptionEnabled\" \"eq\" \"true\" \"properties.endToEndEncryptionEnabled\" \"\"\n    done\n  done\n}\n"
  },
  {
    "path": "modules/azure/compute/webapp/slots/audit_azure_app_service_deployment_slots_virtual_network_integration.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_app_service_deployment_slots_virtual_network_integration\n#\n# 2.2.14  Ensure app is integrated with a virtual network - TBD\n# 2.2.15  Ensure configuration is routed through the virtual network integration - TBD\n#\n# Refer to Section(s) 2.2.14-5 Page(s) 131-5 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_app_service_deployment_slots_virtual_network_integration () {\n  print_function \"audit_azure_app_service_deployment_slots_virtual_network_integration\"\n  check_message  \"Azure App Service Deployment Slot Virtual Network Integration\"\n  command=\"az webapp list --query \\\"[].id\\\" --output tsv\"\n  command_message   \"${command}\"\n  app_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${app_ids}\" ]; then\n    info_message \"No App Service Deployment Slots found\"\n    return\n  fi\n  for app_id in ${app_ids}; do\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"name\\\" --output tsv\"\n    command_message   \"${command}\"\n    app_name=$( eval  \"${command}\" )\n    command=\"az webapp show --id \\\"${app_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    command=\"az webapp deployment slot list --id \\\"${app_id}\\\" --query \\\"[].id\\\" --output tsv\"\n    command_message   \"${command}\"\n    slot_ids=$( eval  \"${command}\" 2> /dev/null )\n    if [ -z \"${slot_ids}\" ]; then\n      info_message \"No App Service Deployment Slots found\"\n      return\n    fi\n    for slot_id in ${slot_ids}; do\n      check_azure_app_service_deployment_slot_value \"Virtual Network Integration\" \"${slot_id}\" \"${app_name}\" \"${res_group}\" \"config\" \"web\" \"Microsoft.Web/sites\" \"virtualNetworkSubnetId\"  \"ne\" \"\"     \"\"                                   \"\"\n      check_azure_app_service_deployment_slot_value \"VNet Image Pull\"             \"${slot_id}\" \"${app_name}\" \"${res_group}\" \"config\" \"web\" \"Microsoft.Web/sites\" \"vnetRouteAllEnabled\"     \"eq\" \"true\" \"properties.vnetRouteAllEnabled\"     \"\"\n      check_azure_app_service_deployment_slot_value \"VNet Content Share\"          \"${slot_id}\" \"${app_name}\" \"${res_group}\" \"config\" \"web\" \"Microsoft.Web/sites\" \"vnetContentShareEnabled\" \"eq\" \"true\" \"properties.vnetContentShareEnabled\" \"\"\n    done\n  done\n}\n"
  },
  {
    "path": "modules/azure/database/audit_azure_cosmos_db.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_cosmos_db\n#\n# Check Azure Cosmos DB\n#\n# 3.1 Ensure That 'Firewalls & Networks' Is Limited to Use Selected Networks Instead of All Networks\n# 3.2 Ensure that Cosmos DB uses Private Endpoints where possible\n# 3.3 Ensure that 'disableLocalAuth' is set to 'true'\n# 3.4 Ensure `Public Network Access` is `Disabled`\n# 3.5 Ensure critical data is encrypted with customer-managed keys (CMK)\n# 3.6 Ensure the firewall does not allow all network traffic\n# 3.7 Ensure that Cosmos DB Logging is Enabled\n#\n# Refer to Section(s) 3 Page(s) 51-72 Microsoft Azure Database Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_cosmos_db () {\n  print_function \"audit_azure_cosmos_db\"\n  check_message  \"Azure Cosmos DB\"\n  command=\"az cosmosdb list --query \\\"[].name\\\" --output tsv\"\n  command_message  \"${command}\"\n  db_names=$( eval \"${command}\" )\n  if [ -z \"${db_names}\" ]; then\n    info_message \"No Cosmos DB instances found\"\n    return\n  fi\n  for db_name in ${db_names}; do\n    command=\"az cosmosdb show --name \\\"${db_name}\\\" --query \\\"[].resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    # 3.1 Ensure That 'Firewalls & Networks' Is Limited to Use Selected Networks Instead of All Networks\n    check_cosmos_db_value \"Firewalls & Networks Filter\"   \"${db_name}\" \"${res_group}\" \"isVirtualNetworkFilterEnabled\" \"eq\" \"true\"     \"\"                            \"\"\n    check_cosmos_db_value \"Firewalls & Networks IP Rules\" \"${db_name}\" \"${res_group}\" \"ipRules\"                       \"ne\" \"\"         \"\"                            \"\"\n    # 3.2 Ensure that Cosmos DB uses Private Endpoints where possible\n    check_cosmos_db_value \"Private Endpoints\"             \"${db_name}\" \"${res_group}\" \"privateEndpointConnections\"    \"ne\" \"\"         \"\"                            \"\"\n    # 3.3 Ensure that 'disableLocalAuth' is set to 'true'\n    check_cosmos_db_value \"Disable Local Auth\"            \"${db_name}\" \"${res_group}\" \"disableLocalAuth\"              \"eq\" \"true\"     \"properties.disableLocalAuth\" \"\"\n    # 3.4 Ensure `Public Network Access` is `Disabled`\n    check_cosmos_db_value \"Public Network Access\"         \"${db_name}\" \"${res_group}\" \"publicNetworkAccess\"           \"eq\" \"Disabled\" \"\"                            \"\"\n    # 3.5 Ensure critical data is encrypted with customer-managed keys (CMK)\n    check_cosmos_db_value \"Customer-Managed Keys\"         \"${db_name}\" \"${res_group}\" \"keyVaultKeyUri\"                \"ne\" \"\"         \"\"                            \"\"\n    # 3.6 Ensure the firewall does not allow all network traffic\n    check_cosmos_db_value \"Firewalls & Networks IP Rules\" \"${db_name}\" \"${res_group}\" \"ipRules\"                       \"ne\" \"0.0.0.0\"  \"--ip-range-filter\"           \"comma-separated-list-of-allowed-ip-addresses\"\n  done\n  command=\"az cosmosdb list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  res_ids=$( eval \"${command}\" )\n  for res_id in ${res_ids}; do\n    check_azure_monitoring_diagnostics_value \"${res_id}\"\n  done\n}\n"
  },
  {
    "path": "modules/azure/database/audit_azure_mysql_db.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_mysql_db\n#\n# Check Azure Database for MySQL\n#\n# Azure Database for MySQL\n# 5.1 Ensure Azure Database for MySQL uses Customer Managed Keys for Encryption at Rest - TBD\n# 5.2 Ensure Azure Database for MySQL uses only Microsoft Entra Authentication - TBD\n# 5.3 Ensure `Public Network Access` is `Disabled` for Azure Database for MySQL - TBD\n# 5.4 Ensure Private Endpoints Are Used for Azure MySQL Databases - TBD\n# 5.5 Ensure server parameter 'audit_log_enabled' is set to 'ON' for MySQL flexible server - TBD\n# 5.6 Ensure server parameter 'audit_log_events' has 'CONNECTION' set for MySQL flexible server - TBD\n# 5.7 Ensure server parameter 'error_server_log_file' is Enabled for MySQL Database Server - TBD\n# 5.8 Ensure server parameter 'require_secure_transport' is set to 'ON' for MySQL Server - TBD\n# 5.9 Ensure server parameter 'tls_version' is set to 'TLSv1.2' (or higher) for MySQL flexible server - TBD\n#\n# Refer to Section(s) 5 Page(s) 84-105 Microsoft Azure Database Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_mysql_db () {\n  print_function \"audit_azure_mysql_db\"\n  check_message  \"Azure Database for MySQL\"\n  command=\"az mysql server list --query \\\"[].name\\\" --output tsv\"\n  command_message       \"${command}\"\n  mysql_servers=$( eval \"${command}\" )\n  if [ \"${mysql_servers}\" = \"\" ]; then\n    info_message \"No MySQL servers found\"\n  else\n    for mysql_server in ${mysql_servers}; do\n      command=\"az mysql server show --name ${mysql_server} --query \\\"resourceGroup\\\" --output tsv\"\n      command_message   \"${command}\"\n      res_group=$( eval \"${command}\" )\n      # 5.1 Ensure Azure Database for MySQL uses Customer Managed Keys for Encryption at Rest - TBD\n      check_mysql_db_value \"Customer-Managed Keys\" \"server\" \"${mysql_server}\" \"${res_group}\" \"\" \"keyVaultKeyUri\"             \"ne\" \"\"         \"\" \"\"\n      # 5.2 Ensure Azure Database for MySQL uses only Microsoft Entra Authentication - TBD\n      # check_mysql_db_value \"Microsoft Entra Authentication\" \"server\" \"${mysql_server}\" \"${res_group}\" \"\" \"\" \"\" \"\" \"\" \"\"\n      # 5.3 Ensure `Public Network Access` is `Disabled` for Azure Database for MySQL - TBD\n      check_mysql_db_value \"Public Network Access\" \"server\" \"${mysql_server}\" \"${res_group}\" \"\" \"publicNetworkAccess\"        \"eq\" \"Disabled\" \"\" \"\"\n      # 5.4 Ensure Private Endpoints Are Used for Azure MySQL Databases - TBD\n      check_mysql_db_value \"Private Endpoints\"     \"server\" \"${mysql_server}\" \"${res_group}\" \"\" \"privateEndpointConnections\" \"ne\" \"\"         \"\" \"\"\n      # 5.5 Ensure server parameter 'audit_log_enabled' is set to 'ON' for MySQL server - TBD\n      # check_mysql_db_value \"Audit Log\"             \"server\" \"${mysql_server}\" \"${res_group}\" \"\" \"audit_log_enabled\"          \"eq\" \"ON\"         \"\" \"\"\n      # 5.6 Ensure server parameter 'audit_log_events' has 'CONNECTION' set for MySQL server - TBD\n      # check_mysql_db_value \"Audit Log Events\"       \"server\" \"${mysql_server}\" \"${res_group}\" \"\" \"audit_log_events\"           \"eq\" \"CONNECTION\"   \"\" \"\"\n      # 5.7 Ensure server parameter 'error_server_log_file' is Enabled for MySQL Database Server - TBD\n      # check_mysql_db_value \"Error Server Log File\" \"server\" \"${mysql_server}\" \"${res_group}\" \"\" \"error_server_log_file\"        \"eq\" \"Enabled\"    \"\" \"\"\n      # 5.8 Ensure server parameter 'require_secure_transport' is set to 'ON' for MySQL Server - TBD\n      # check_mysql_db_value \"Require Secure Transport\" \"server\" \"${mysql_server}\" \"${res_group}\" \"\" \"require_secure_transport\" \"eq\" \"ON\"         \"\" \"\"\n      # 5.9 Ensure server parameter 'tls_version' is set to 'TLSv1.2' (or higher) for MySQL flexible server - TBD\n      # check_mysql_db_value \"TLS Version\" \"server\" \"${mysql_server}\" \"${res_group}\" \"\" \"tls_version\" \"eq\" \"TLSv1.2\" \"\" \"\"\n    done\n  fi\n  command=\"az mysql flexible-server list --query \\\"[].name\\\" --output tsv\"\n  command_message       \"${command}\"\n  mysql_servers=$( eval \"${command}\" )\n  if [ \"${mysql_servers}\" = \"\" ]; then\n    info_message \"No MySQL flexible servers found\"\n  else\n    for mysql_server in ${mysql_servers}; do\n      command=\"az mysql flexible-server show --server-name ${mysql_server} --query \\\"resourceGroup\\\" --output tsv\"\n      command_message   \"${command}\"\n      res_group=$( eval \"${command}\" )\n      command=\"az mysql flexible-server db list --server-name ${mysql_server} --resource-group ${res_group} --query \\\"[].name\\\" --output tsv\"\n      command_message   \"${command}\"\n      db_names=$( eval  \"${command}\" )\n      for db_name in ${db_names}; do\n        # 5.1 Ensure Azure Database for MySQL uses Customer Managed Keys for Encryption at Rest - TBD\n        check_mysql_db_value \"Customer-Managed Keys\" \"flexible-server\" \"${mysql_server}\" \"${res_group}\" \"${db_name}\" \"keyVaultKeyUri\"             \"ne\" \"\"         \"\" \"\"\n        # 5.2 Ensure Azure Database for MySQL uses only Microsoft Entra Authentication - TBD\n        # check_mysql_db_value \"Microsoft Entra Authentication\" \"flexible-server\" \"${mysql_server}\" \"${res_group}\" \"${db_name}\" \"\" \"\" \"\" \"\" \"\"\n        # 5.3 Ensure `Public Network Access` is `Disabled` for Azure Database for MySQL - TBD\n        check_mysql_db_value \"Public Network Access\" \"flexible-server\" \"${mysql_server}\" \"${res_group}\" \"${db_name}\" \"publicNetworkAccess\"        \"eq\" \"Disabled\" \"\" \"\"\n        # 5.4 Ensure Private Endpoints Are Used for Azure MySQL Databases - TBD\n        check_mysql_db_value \"Private Endpoints\"     \"flexible-server\" \"${mysql_server}\" \"${res_group}\" \"${db_name}\" \"privateEndpointConnections\" \"ne\" \"\"         \"\" \"\"\n        # 5.5 Ensure server parameter 'audit_log_enabled' is set to 'ON' for MySQL flexible server - TBD\n        # check_mysql_db_value \"Audit Log\"             \"flexible-server\" \"${mysql_server}\" \"${res_group}\" \"${db_name}\" \"audit_log_enabled\"          \"eq\" \"ON\"       \"\" \"\"\n        # 5.6 Ensure server parameter 'audit_log_events' has 'CONNECTION' set for MySQL flexible server - TBD\n        # check_mysql_db_value \"Audit Log Events\"      \"flexible-server\" \"${mysql_server}\" \"${res_group}\" \"${db_name}\" \"audit_log_events\"           \"eq\" \"CONNECTION\"   \"\" \"\"\n        # 5.7 Ensure server parameter 'error_server_log_file' is Enabled for MySQL Database Server - TBD\n        # check_mysql_db_value \"Error Server Log File\" \"flexible-server\" \"${mysql_server}\" \"${res_group}\" \"${db_name}\" \"error_server_log_file\"        \"eq\" \"Enabled\"    \"\" \"\"\n        # 5.8 Ensure server parameter 'require_secure_transport' is set to 'ON' for MySQL Server - TBD\n        # check_mysql_db_value \"Require Secure Transport\" \"flexible-server\" \"${mysql_server}\" \"${res_group}\" \"${db_name}\" \"require_secure_transport\" \"eq\" \"ON\"         \"\" \"\"\n        # 5.9 Ensure server parameter 'tls_version' is set to 'TLSv1.2' (or higher) for MySQL flexible server - TBD\n        # check_mysql_db_value \"TLS Version\" \"flexible-server\" \"${mysql_server}\" \"${res_group}\" \"${db_name}\" \"tls_version\" \"eq\" \"TLSv1.2\" \"\" \"\"\n      done\n    done\n  fi\n}\n"
  },
  {
    "path": "modules/azure/database/audit_azure_postgresql_db.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_postgresql_db\n#\n# Check Azure Database for PostgreSQL\n#\n# Azure Database for PostgreSQL\n# 6.1  Ensure Azure Database for PostgreSQL uses Customer Managed Keys for Encryption at Rest - TBD\n# 6.2  Ensure Azure Database for PostgreSQL uses only Microsoft Entra Authentication - TBD\n# 6.3  Ensure `Public Network Access` is `Disabled` for Azure Database for PostgreSQL - TBD\n# 6.4  Ensure Private Endpoints Are Used for Azure PostgreSQL Databases - TBD\n# 6.5  Ensure server parameter 'connection_throttle.enable' is set to 'ON' for PostgreSQL server - TBD\n# 6.6  Ensure server parameter 'logfiles.retention_days' is greater than 3 days for PostgreSQL server - TBD\n# 6.7  Ensure server parameter 'log_checkpoints' is set to 'ON' for PostgreSQL server - TBD\n# 6.8  Ensure server parameter 'log_disconnections' is set to 'ON' for PostgreSQL servers - TBD\n# 6.9  Ensure server parameter 'log_connections' is set to 'ON' for PostgreSQL servers - TBD\n# 6.10 Ensure server parameter 'require_secure_transport' is set to 'ON' for PostgreSQL server - TBD\n# 6.11 Ensure server parameter 'tls_version' is set to 'TLSv1.2' (or higher) for PostgreSQL server - TBD\n#\n# Refer to Section(s) 6 Page(s) 106-138 Microsoft Azure Database Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_postgresql_db () {\n  print_function \"audit_azure_postgresql_db\"\n  check_message  \"Azure Database for PostgreSQL\"\n  command=\"az postgresql server list --query \\\"[].name\\\" --output tsv\"\n  command_message     \"${command}\"\n  sql_servers=$( eval \"${command}\" )\n  if [ \"${sql_servers}\" = \"\" ]; then\n    info_message \"No PostgreSQL servers found\"\n  else\n    for sql_server in ${sql_servers}; do\n      command=\"az postgresql server show --name ${sql_server} --query \\\"resourceGroup\\\" --output tsv\"\n      command_message   \"${command}\"\n      res_group=$( eval \"${command}\" )\n      # 6.1 Ensure Azure Database for PostgreSQL uses Customer Managed Keys for Encryption at Rest - TBD\n      check_postgresql_db_value \"Customer-Managed Keys\" \"server\" \"${sql_server}\" \"${res_group}\" \"\" \"keyVaultKeyUri\"             \"ne\" \"\"         \"\" \"\"\n      # 6.2 Ensure Azure Database for PostgreSQL uses only Microsoft Entra Authentication - TBD\n      # check_postgresql_db_value \"Microsoft Entra Authentication\" \"server\" \"${sql_server}\" \"${res_group}\" \"\" \"\" \"\" \"\" \"\" \"\"\n      # 6.3 Ensure `Public Network Access` is `Disabled` for Azure Database for PostgreSQL - TBD\n      check_postgresql_db_value \"Public Network Access\" \"server\" \"${sql_server}\" \"${res_group}\" \"\" \"publicNetworkAccess\"        \"eq\" \"Disabled\" \"\" \"\"\n      # 6.4 Ensure Private Endpoints Are Used for Azure PostgreSQL Databases - TBD\n      check_postgresql_db_value \"Private Endpoints\"     \"server\" \"${sql_server}\" \"${res_group}\" \"\" \"privateEndpointConnections\" \"ne\" \"\"         \"\" \"\"\n      # 6.5  Ensure server parameter 'connection_throttle.enable' is set to 'ON' for PostgreSQL server - TBD\n      # check_postgresql_db_value \"Connection Throttle\" \"server\" \"${sql_server}\" \"${res_group}\" \"\" \"connection_throttle.enable\" \"eq\" \"ON\" \"\" \"\"\n      # 6.6  Ensure server parameter 'logfiles.retention_days' is greater than 3 days for PostgreSQL server - TBD\n      # check_postgresql_db_value \"Log Retention\" \"server\" \"${sql_server}\" \"${res_group}\" \"\" \"logfiles.retention_days\" \"gt\" \"3\" \"\" \"\"\n      # 6.7  Ensure server parameter 'log_checkpoints' is set to 'ON' for PostgreSQL server - TBD\n      # check_postgresql_db_value \"Log Checkpoints\" \"server\" \"${sql_server}\" \"${res_group}\" \"\" \"log_checkpoints\" \"eq\" \"ON\" \"\" \"\"\n      # 6.8  Ensure server parameter 'log_disconnections' is set to 'ON' for PostgreSQL servers - TBD\n      # check_postgresql_db_value \"Log Disconnections\" \"server\" \"${sql_server}\" \"${res_group}\" \"\" \"log_disconnections\" \"eq\" \"ON\" \"\" \"\"\n      # 6.9  Ensure server parameter 'log_connections' is set to 'ON' for PostgreSQL servers - TBD\n      # check_postgresql_db_value \"Log Connections\" \"server\" \"${sql_server}\" \"${res_group}\" \"\" \"log_connections\" \"eq\" \"ON\" \"\" \"\"\n      # 6.10 Ensure server parameter 'require_secure_transport' is set to 'ON' for PostgreSQL server - TBD\n      # check_postgresql_db_value \"Require Secure Transport\" \"server\" \"${sql_server}\" \"${res_group}\" \"\" \"require_secure_transport\" \"eq\" \"ON\" \"\" \"\"\n      # 6.11 Ensure server parameter 'tls_version' is set to 'TLSv1.2' (or higher) for PostgreSQL server - TBD\n      # check_postgresql_db_value \"TLS Version\" \"server\" \"${sql_server}\" \"${res_group}\" \"\" \"tls_version\" \"eq\" \"TLSv1.2\" \"\" \"\"\n    done\n  fi\n  command=\"az postgresql flexible-server list --query \\\"[].name\\\" --output tsv\"\n  command_message   \"${command}\"\n  f_servers=$( eval \"${command}\" )\n  if [ \"${f_servers}\" = \"\" ]; then\n    info_message \"No PostgreSQL flexible servers found\"\n  else\n    for f_server in ${f_servers}; do\n      command=\"az postgresql flexible-server show --server-name ${f_server} --query \\\"resourceGroup\\\" --output tsv\"\n      command_message   \"${command}\"\n      res_group=$( eval \"${command}\" )\n      command=\"az postgresql flexible-server db list --server-name ${f_server} --resource-group ${res_group} --query \\\"[].name\\\" --output tsv\"\n      command_message   \"${command}\"\n      db_names=$( eval  \"${command}\" )\n      for db_name in ${db_names}; do\n        # 6.1 Ensure Azure Database for MySQL uses Customer Managed Keys for Encryption at Rest - TBD\n        check_postgresql_db_value \"Customer-Managed Keys\" \"flexible-server\" \"${f_server}\" \"${res_group}\" \"${db_name}\" \"keyVaultKeyUri\"             \"ne\" \"\"         \"\" \"\"\n        # 6.2 Ensure Azure Database for MySQL uses only Microsoft Entra Authentication - TBD\n        # check_postgresql_db_value \"Microsoft Entra Authentication\" \"flexible-server\" \"${f_server}\" \"${res_group}\" \"${db_name}\" \"\" \"\" \"\" \"\" \"\"\n        # 6.3 Ensure `Public Network Access` is `Disabled` for Azure Database for MySQL - TBD\n        check_postgresql_db_value \"Public Network Access\" \"flexible-server\" \"${f_server}\" \"${res_group}\" \"${db_name}\" \"publicNetworkAccess\"        \"eq\" \"Disabled\" \"\" \"\"\n        # 6.4 Ensure Private Endpoints Are Used for Azure MySQL Databases - TBD\n        check_postgresql_db_value \"Private Endpoints\"     \"flexible-server\" \"${f_server}\" \"${res_group}\" \"${db_name}\" \"privateEndpointConnections\" \"ne\" \"\"         \"\" \"\"\n        # 6.5  Ensure server parameter 'connection_throttle.enable' is set to 'ON' for PostgreSQL server - TBD\n        # check_postgresql_db_value \"Connection Throttle\" \"flexible-server\" \"${f_server}\" \"${res_group}\" \"${db_name}\" \"connection_throttle.enable\" \"eq\" \"ON\" \"\" \"\"\n        # 6.6  Ensure server parameter 'logfiles.retention_days' is greater than 3 days for PostgreSQL server - TBD\n        # check_postgresql_db_value \"Log Retention\" \"flexible-server\" \"${f_server}\" \"${res_group}\" \"${db_name}\" \"logfiles.retention_days\" \"gt\" \"3\" \"\" \"\"\n        # 6.7  Ensure server parameter 'log_checkpoints' is set to 'ON' for PostgreSQL server - TBD\n        # check_postgresql_db_value \"Log Checkpoints\" \"flexible-server\" \"${f_server}\" \"${res_group}\" \"${db_name}\" \"log_checkpoints\" \"eq\" \"ON\" \"\" \"\"\n        # 6.8  Ensure server parameter 'log_disconnections' is set to 'ON' for PostgreSQL servers - TBD\n        # check_postgresql_db_value \"Log Disconnections\" \"flexible-server\" \"${f_server}\" \"${res_group}\" \"${db_name}\" \"log_disconnections\" \"eq\" \"ON\" \"\" \"\"\n        # 6.9  Ensure server parameter 'log_connections' is set to 'ON' for PostgreSQL servers - TBD\n        # check_postgresql_db_value \"Log Connections\" \"flexible-server\" \"${f_server}\" \"${res_group}\" \"${db_name}\" \"log_connections\" \"eq\" \"ON\" \"\" \"\"\n        # 6.10 Ensure server parameter 'require_secure_transport' is set to 'ON' for PostgreSQL server - TBD\n        # check_postgresql_db_value \"Require Secure Transport\" \"flexible-server\" \"${f_server}\" \"${res_group}\" \"${db_name}\" \"require_secure_transport\" \"eq\" \"ON\" \"\" \"\"\n        # 6.11 Ensure server parameter 'tls_version' is set to 'TLSv1.2' (or higher) for PostgreSQL server - TBD\n        # check_postgresql_db_value \"TLS Version\" \"flexible-server\" \"${f_server}\" \"${res_group}\" \"${db_name}\" \"tls_version\" \"eq\" \"TLSv1.2\" \"\" \"\"\n      done\n    done\n  fi\n}\n"
  },
  {
    "path": "modules/azure/database/audit_azure_redis_cache.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_database_services\n#\n# Check Azure Database Services\n#\n# Refer to Section(s) 4 Page(s) 69 CIS Microsoft Azure Foundations Benchmark v5.0.0\n# Refer to CIS Microsoft Azure Database Services Benchmark\n#\n# 2.2  Ensure that 'Allow access only via SSL' is set to 'Yes'\n# 2.3  Ensure that 'Minimum TLS version' is set to TLS v1.2 (or higher)\n# 2.6  Ensure that 'Public Network Access' is 'Disabled'\n# 2.7  Ensure Azure Cache for Redis is Using a Private Link\n# 2.8  Ensure that Azure Cache for Redis is Using Customer-Managed Keys\n# 2.9  Ensure 'Access Keys Authentication' is set to 'Disabled'\n# 2.10 Ensure 'Update Channel' is set to 'Stable' \n#\n# Refer to Section(s) 2 Page(s) 11-12 Microsoft Azure Database Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_redis_cache () {\n  print_function  \"audit_azure_redis_cache\"\n  check_message   \"Azure Redis Cache\"\n  command=\"az redis list --query \\\"[].name\\\" --output tsv\"\n  command_message     \"${command}\"\n  redis_names=$( eval \"${command}\" )\n  if [ -z \"${redis_names}\" ]; then\n    info_message \"No Redis instances found\"\n    return\n  fi\n  for redis_name in ${redis_names}; do\n    command=\"az redis show --name \\\"${redis_name}\\\" --query \\\"[].resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    # 2.2  Ensure that 'Allow access only via SSL' is set to 'Yes'\n    check_redis_cache_value \"Allow access only via SSL\" \"${redis_name}\" \"${res_group}\" \"sslEnabled\"                            \"eq\" \"true\"               \"enableSsl\"\n    # 2.3  Ensure that 'Minimum TLS version' is set to TLS v1.2 (or higher)\n    check_redis_cache_value \"Minimum TLS version\"       \"${redis_name}\" \"${res_group}\" \"minimumTlsVersion\"                     \"eq\" \"1.2\"                \"--minimum-tls-version\"\n    # 2.6  Ensure that 'Public Network Access' is 'Disabled'\n    check_redis_cache_value \"Public Network Access\"     \"${redis_name}\" \"${res_group}\" \"publicNetworkAccess\"                   \"eq\" \"disabled\"           \"--public-network-access\"\n    # 2.7  Ensure Azure Cache for Redis is Using a Private Link\n    check_redis_cache_value \"Private Link\"              \"${redis_name}\" \"${res_group}\" \"properties.privateEndpointConnections\" \"eq\" \"Approved\"           \"privateEndpointConnections[0].privateLinkServiceConnectionState.status\"\n    # 2.9  Ensure 'Access Keys Authentication' is set to 'Disabled'\n    check_redis_cache_value \"Access Keys Authentication\" \"${redis_name}\" \"${res_group}\" \"properties.auth.type\"                 \"eq\" \"Microsoft.KeyVault\" \"--auth-type\"\n    # 2.10 Ensure 'Update Channel' is set to 'Stable' \n    check_redis_cache_value \"Update Channel\"             \"${redis_name}\" \"${res_group}\" \"updateChannel\"                        \"eq\" \"Stable\"             \"updateChannel\"\n  done\n  command=\"az redisenterprise list --query \\\"[].name\\\" --output tsv\"\n  command_message     \"${command}\"\n  redis_names=$( eval \"${command}\" )\n  if [ -z \"${redis_names}\" ]; then\n    info_message \"No Redis Enterprise instances found\"\n    return\n  fi\n  for redis_name in ${redis_names}; do\n    command=\"az redis enterprise show --name \\\"${redis_name}\\\" --query \\\"[].resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    # 2.8  Ensure that Azure Cache for Redis is Using Customer-Managed Keys\n    check_redis_enterprise_cache_value \"Customer-Managed Keys\"     \"${redis_name}\" \"${res_group}\" \"properties.encryption.customerManagedKeyEncryptionEnabled\"    \"eq\" \"true\" \"--customer-managed-key-encryption-enabled\"\n    check_redis_enterprise_cache_value \"Customer-Managed Keys URL\" \"${redis_name}\" \"${res_group}\" \"properties.encryption.customerManagedKeyEncryptionKeyUrl\"     \"ne\" \"\"     \"\"\n  done\n}\n"
  },
  {
    "path": "modules/azure/database/audit_azure_sql_db.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_sql_db\n#\n# Check Azure SQL Database\n#\n# Azure SQL Database\n# 9.1 Ensure that 'Auditing' is set to 'On' - TBD\n# 9.2 Ensure that 'Public Network Access' is set to 'Disable' - TBD\n# 9.3 Ensure no Azure SQL Database firewall rule is overly permissive - TBD\n# 9.4 Ensure SQL server's Transparent Data Encryption (TDE) protector is encrypted with Customer-managed key - TBD\n# 9.5 Ensure that Microsoft Entra authentication is Configured for SQL Servers - TBD\n# 9.6 Ensure that 'Data encryption' is set to 'On' on a SQL Database - TBD\n# 9.7 Ensure that 'Auditing' Retention is 'greater than 90 days' - TBD\n# 9.8 Ensure 'Minimum TLS Version' is set to 'TLS 1.2' or higher - TBD\n#\n# Refer to Section(s) 9 Page(s) 141-170 Microsoft Azure Database Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_sql_db () {\n  print_function \"audit_azure_sql_db\"\n  check_message \"Azure SQL Database\"\n  command=\"az sql server list --query \\\"[].name\\\" --output tsv\"\n  command_message     \"${command}\"\n  sql_servers=$( eval \"${command}\" )\n  if [ \"${sql_servers}\" = \"\" ]; then\n    info_message \"No SQL servers found\" \"info\"\n  else\n    for sql_server in ${sql_servers}; do\n      command=\"az sql server show --name ${sql_server} --query \\\"resourceGroup\\\" --output tsv\"\n      command_message   \"${command}\"\n      res_group=$( eval \"${command}\" )\n      # 9.1 Ensure that 'Auditing' is set to 'On' - TBD\n      check_sql_db_value \"Auditing\"              \"server\" \"${sql_server}\" \"${res_group}\" \"\" \"keyVaultKeyUri\"             \"ne\" \"\"         \"\" \"\"\n      # 9.2 Ensure that 'Public Network Access' is set to 'Disable' - TBD\n      # check_sql_db_value \"Microsoft Entra Authentication\" \"server\" \"${sql_server}\" \"${res_group}\" \"\" \"\" \"\" \"\" \"\" \"\"\n      # 9.3 Ensure no Azure SQL Database firewall rule is overly permissive - TBD\n      check_sql_db_value \"Public Network Access\" \"server\" \"${sql_server}\" \"${res_group}\" \"\" \"publicNetworkAccess\"        \"eq\" \"Disabled\" \"\" \"\"\n      # 9.4 Ensure SQL server's Transparent Data Encryption (TDE) protector is encrypted with Customer-managed key - TBD\n      check_sql_db_value \"Private Endpoints\"     \"server\" \"${sql_server}\" \"${res_group}\" \"\" \"privateEndpointConnections\" \"ne\" \"\"         \"\" \"\"\n      # 9.5 Ensure that Microsoft Entra authentication is Configured for SQL Servers - TBD\n      # check_sql_db_value \"Audit Log\"             \"server\" \"${sql_server}\" \"${res_group}\" \"\" \"audit_log_enabled\"          \"eq\" \"ON\"         \"\" \"\"\n      # 9.6 Ensure that 'Data encryption' is set to 'On' on a SQL Database - TBD\n      # check_sql_db_value \"Audit Log Events\"       \"server\" \"${sql_server}\" \"${res_group}\" \"\" \"audit_log_events\"           \"eq\" \"CONNECTION\"   \"\" \"\"\n      # 9.7 Ensure that 'Auditing' Retention is 'greater than 90 days' - TBD\n      # check_sql_db_value \"Error Server Log File\" \"server\" \"${sql_server}\" \"${res_group}\" \"\" \"error_server_log_file\"        \"eq\" \"Enabled\"    \"\" \"\"\n      # 9.8 Ensure 'Minimum TLS Version' is set to 'TLS 1.2' or higher - TBD\n      # check_sql_db_value \"Require Secure Transport\" \"server\" \"${sql_server}\" \"${res_group}\" \"\" \"require_secure_transport\" \"eq\" \"ON\"         \"\" \"\"\n    done\n  fi\n}\n"
  },
  {
    "path": "modules/azure/logging/audit_azure_activity_log_alerts.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_activity_log_alerts\n#\n# Check Azure Activity Log Alerts\n#\n# 6.1.2.1  Ensure that Activity Log Alert for Create Policy Assignment is enabled\n# 6.1.2.2  Ensure that Activity Log Alert for Delete Policy Assignment is enabled\n# 6.1.2.3  Ensure that Activity Log Alert exists for Create or Update Network Security Group\n# 6.1.2.4  Ensure that Activity Log Alert exists for Delete Network Security Group\n# 6.1.2.5  Ensure that Activity Log Alert exists for Create or Update Security Solution\n# 6.1.2.6  Ensure that Activity Log Alert exists for Delete Security Solution\n# 6.1.2.7  Ensure that Activity Log Alert exists for Create or Update SQL Server Firewall Rule\n# 6.1.2.8  Ensure that Activity Log Alert exists for Delete SQL Server Firewall Rule\n# 6.1.2.9  Ensure that Activity Log Alert exists for Create or Update Public IP Address rule\n# 6.1.2.10 Ensure that Activity Log Alert exists for Delete Public IP Address rule\n# 6.1.2.11 Ensure that Activity Log Alert exists for Service Health\n# Refer to Section(s) 6.1.2.1  Page(s) 227-30 CIS Microsoft Azure Foundations Benchmark v5.0.0\n# Refer to Section(s) 6.1.2.2  Page(s) 231-34 CIS Microsoft Azure Foundations Benchmark v5.0.0\n# Refer to Section(s) 6.1.2.3  Page(s) 235-38 CIS Microsoft Azure Foundations Benchmark v5.0.0\n# Refer to Section(s) 6.1.2.4  Page(s) 239-42 CIS Microsoft Azure Foundations Benchmark v5.0.0\n# Refer to Section(s) 6.1.2.5  Page(s) 243-46 CIS Microsoft Azure Foundations Benchmark v5.0.0\n# Refer to Section(s) 6.1.2.6  Page(s) 247-50 CIS Microsoft Azure Foundations Benchmark v5.0.0\n# Refer to Section(s) 6.1.2.7  Page(s) 251-54 CIS Microsoft Azure Foundations Benchmark v5.0.0\n# Refer to Section(s) 6.1.2.8  Page(s) 255-58 CIS Microsoft Azure Foundations Benchmark v5.0.0\n# Refer to Section(s) 6.1.2.9  Page(s) 259-62 CIS Microsoft Azure Foundations Benchmark v5.0.0\n# Refer to Section(s) 6.1.2.10 Page(s) 263-66 CIS Microsoft Azure Foundations Benchmark v5.0.0\n# Refer to Section(s) 6.1.2.11 Page(s) 267-70 CIS Microsoft Azure Foundations Benchmark v5.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_activity_log_alerts () {\n  print_function \"audit_azure_activity_log_alerts\"\n  check_message  \"Azure Activity Log Alerts\"\n  command=\"az account show --query id --output tsv\"\n  command_message  \"${command}\"\n  sub_ids=\"$( eval \"${command}\" )\"\n  for sub_id in ${sub_ids}; do\n    # 6.1.2.1 Ensure that Activity Log Alert for Create Policy Assignment is enabled\n    check_azure_activity_log_alert_value \"Create Policy Assignment\"                  \"${sub_id}\" \"Microsoft.Authorization/policyAssignments/write\"\n    # 6.1.2.2 Ensure that Activity Log Alert for Delete Policy Assignment is enabled\n    check_azure_activity_log_alert_value \"Delete Policy Assignment\"                  \"${sub_id}\" \"Microsoft.Authorization/policyAssignments/delete\"\n    # 6.1.2.3 Ensure that Activity Log Alert exists for Create or Update Network Security Group\n    check_azure_activity_log_alert_value \"Create or Update Network Security Group\"   \"${sub_id}\" \"Microsoft.Network/networkSecurityGroups/write\"\n    # 6.1.2.4 Ensure that Activity Log Alert exists for Delete Network Security Group\n    check_azure_activity_log_alert_value \"Delete Network Security Group\"             \"${sub_id}\" \"Microsoft.Network/networkSecurityGroups/delete\"\n    # 6.1.2.5 Ensure that Activity Log Alert exists for Create or Update Security Solution\n    check_azure_activity_log_alert_value \"Create or Update Security Solution\"        \"${sub_id}\" \"Microsoft.Security/securitySolutions/write\"\n    # 6.1.2.6 Ensure that Activity Log Alert exists for Delete Security Solution\n    check_azure_activity_log_alert_value \"Delete Security Solution\"                  \"${sub_id}\" \"Microsoft.Security/securitySolutions/delete\"\n    # 6.1.2.7 Ensure that Activity Log Alert exists for Create or Update SQL Server Firewall Rule\n    check_azure_activity_log_alert_value \"Create or Update SQL Server Firewall Rule\" \"${sub_id}\" \"Microsoft.Sql/servers/firewallRules/write\"\n    # 6.1.2.8 Ensure that Activity Log Alert exists for Delete SQL Server Firewall Rule\n    check_azure_activity_log_alert_value \"Delete SQL Server Firewall Rule\"           \"${sub_id}\" \"Microsoft.Sql/servers/firewallRules/delete\"\n    # 6.1.2.9 Ensure that Activity Log Alert exists for Create or Update Public IP Address rule\n    check_azure_activity_log_alert_value \"Create or Update Public IP Address rule\"   \"${sub_id}\" \"Microsoft.Network/publicIPAddresses/write\"\n    # 6.1.2.10 Ensure that Activity Log Alert exists for Delete Public IP Address rule\n    check_azure_activity_log_alert_value \"Delete Public IP Address rule\"             \"${sub_id}\" \"Microsoft.Network/publicIPAddresses/delete\"\n    # 6.1.2.11 Ensure that Activity Log Alert exists for Service Health\n    check_azure_activity_log_alert_value \"Service Health\"                            \"${sub_id}\" \"ServiceHealth\"\n  done\n}\n"
  },
  {
    "path": "modules/azure/logging/audit_azure_activity_logs_cmk.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_activity_logs_cmk\n#\n# Check Azure Activity Logs CMK\n#\n# 6.1.1.3  Ensure that storage account is encrypted with customer-managed key\n#\n# Refer to Section(s) 6.1.1.3 Page(s) 203-6   CIS Microsoft Azure Foundations Benchmark v5.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_activity_logs_cmk () {\n  print_function  \"audit_azure_activity_logs_cmk\"\n  check_message   \"Azure Activity Logs CMK\"\n  command=\"az account list --query \\\"[].id\\\" --output tsv 2>/dev/null\"\n  command_message \"${command}\"\n  sub_ids=$( eval \"${command}\" )\n  for sub_id in ${sub_ids}; do\n    command=\"az monitor diagnostic-settings subscription list --subscription ${sub_id} --query 'value[*].storageAccountId' --output tsv\"\n    command_message    \"${command}\"\n    s_accounts=$( eval \"${command}\" 2> /dev/null )\n    if [ -z \"${s_accounts}\" ]; then\n      info_message \"No Storage Accounts found\"\n      continue\n    fi\n    for s_account in ${s_accounts}; do\n      command=\"az storage account show --name ${s_account} --query 'encryption.keySource' --output tsv 2>/dev/null\"\n      command_message    \"${command}\"\n      key_source=$( eval \"${command}\" )\n      command=\"az storage account show --name ${s_account} --query 'encryption.keyVaultProperties' --output tsv 2>/dev/null\"\n      command_message    \"${command}\"\n      key_vault=$( eval  \"${command}\" )\n      if [ \"${key_source}\" = \"Microsoft.Keyvault\" ]; then\n        if [ ! -z \"${key_vault}\" ] && [ ! \"${key_vault}\" = \"null\" ]; then\n          inc_secure   \"Storage account ${s_account} is encrypted with customer-managed key\"\n        else\n          inc_insecure \"Storage account ${s_account} is encrypted with customer-managed key but no key vault is specified\"\n        fi\n      else\n        inc_insecure   \"Storage account ${s_account} is not encrypted with customer-managed key\"\n      fi\n    done \n  done\n}\n"
  },
  {
    "path": "modules/azure/logging/audit_azure_application_insights.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_application_insights\n#\n# Check Azure Application Insights\n#\n# 6.1.3.1  Ensure that Application Insights is enabled\n#\n# Refer to Section(s) 6.1.3.1 Page(s) 272-74 CIS Microsoft Azure Foundations Benchmark v5.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_application_insights () {\n  print_function  \"audit_azure_application_insights\"\n  verbose_message \"Azure Application Insights\" \"check\"\n  command=\"az monitor app-insights component show --query \\\"[].{ID:appId, Name:name, Tenant:tenantId, Location:location, Provisioning_State:provisioningState}\\\"\"\n  command_message        \"${command}\"\n  insights_check=$( eval \"${command}\" )\n  if [ -z \"${insights_check}\" ]; then\n    inc_secure   \"Application Insights is enabled\"\n  else\n    inc_insecure \"Application Insights is not enabled\"\n  fi \n}\n"
  },
  {
    "path": "modules/azure/logging/audit_azure_diagnostic_setting_categories.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_diagnostic_setting_categories\n#\n# Check Azure Diagnostic Setting Categories\n#\n# 6.1.1.2  Ensure Diagnostic Setting captures appropriate categories\n#\n# Refer to Section(s) 6.1.1.2 Page(s) 199-202 CIS Microsoft Azure Foundations Benchmark v5.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_diagnostic_setting_categories () {\n  print_function  \"audit_azure_diagnostic_setting_categories\"\n  check_message   \"Azure Diagnostic Setting Categories\"\n  command=\"az account list --query \\\"[].id\\\" --output tsv 2>/dev/null\"\n  command_message \"${command}\"\n  sub_ids=$( eval \"${command}\" )\n  for sub_id in ${sub_ids}; do\n    for setting in Administrative Alert Policy Security; do\n      command=\"az monitor diagnostic-settings subscription list --subscription ${sub_id} | grep \\\"${setting}\\\" | grep -i \\\"enabled\\\" | grep true\"\n      command_message  \"${command}\"\n      settings=$( eval \"${command}\" )\n      if [ -z \"${settings}\" ]; then\n        inc_insecure   \"There is no diagnostic setting for ${setting} for subscription ${sub_id}\"\n      else\n        inc_secure     \"There is a diagnostic setting for ${setting} for subscription ${sub_id}\"\n      fi\n    done\n  done\n}\n"
  },
  {
    "path": "modules/azure/logging/audit_azure_entra_diagnostic_settings.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_entra_diagnostic_settings\n#\n# Check Azure Entra Diagnostic Settings\n#\n# 6.1.1.9  Ensure that a Microsoft Entra diagnostic setting exists to send Microsoft Entra activity logs to an appropriate destination\n#\n# Refer to Section(s) 6.1.1.9 Page(s) 220-2 CIS Microsoft Azure Foundations Benchmark v5.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_entra_diagnostic_settings () {\n  print_function \"audit_azure_entra_diagnostic_settings\"\n  check_message  \"Azure Entra Diagnostic Settings\"\n}\n"
  },
  {
    "path": "modules/azure/logging/audit_azure_graph_diagnostic_settings.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_graph_diagnostic_settings\n#\n# Check Azure Graph Diagnostic Settings\n#\n# 6.1.1.8 Ensure that a Microsoft Graph diagnostic setting exists to send Microsoft Graph activity logs to an appropriate destination\n#\n# Refer to Section(s) 6.1.1.8 Page(s) 218-9 CIS Microsoft Azure Foundations Benchmark v5.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_graph_diagnostic_settings () {\n  print_function \"audit_azure_graph_diagnostic_settings\"\n  check_message  \"Azure Graph Diagnostic Settings\"\n}\n"
  },
  {
    "path": "modules/azure/logging/audit_azure_intune_logs.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_intune_logs\n#\n# Check Azure Intune Logs\n#\n# 6.1.1.10 Ensure that a Microsoft Intune diagnostic setting exists to send Microsoft Intune activity logs to an appropriate destination\n#\n# Refer to Section(s) 6.1.1.10 Page(s) 223-5 CIS Microsoft Azure Foundations Benchmark v5.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_intune_logs () {\n  print_function \"audit_azure_intune_logs\"\n  check_message  \"Azure Intune Logs\"\n}\n"
  },
  {
    "path": "modules/azure/logging/audit_azure_logging_and_monitoring.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_logging_and_monitoring\n#\n# Check Azure Logging and Monitoring\n#\n# 6.1.1.1  Ensure that a 'Diagnostic Setting' exists for Subscription Activity Logs\n# 6.1.1.2  Ensure Diagnostic Setting captures appropriate categories\n# 6.1.1.3  Ensure the storage account containing the container with activity logs is encrypted with customer-managed key (CMK)\n# 6.1.1.4  Ensure that logging for Azure Key Vault is 'Enabled'\n# 6.1.1.5  Ensure that Network Security Group Flow logs are captured and sent to Log Analytics - TBD\n# 6.1.1.6  Ensure that logging for Azure AppService 'HTTP logs' is enabled - TBD\n# 6.1.1.7  Ensure that virtual network flow logs are captured and sent to Log Analytics\n# 6.1.1.8  Ensure that a Microsoft Entra diagnostic setting exists to send Microsoft Graph activity logs to an appropriate destination\n# 6.1.1.9  Ensure that a Microsoft Entra diagnostic setting exists to send Microsoft Entra activity logs to an appropriate destination\n# 6.1.1.10 Ensure that Intune logs are captured and sent to Log Analytics\n# 6.1.2.1  Ensure that Activity Log Alert exists for Create Policy Assignment\n# 6.1.2.2  Ensure that Activity Log Alert exists for Delete Policy Assignment\n# 6.1.2.3  Ensure that Activity Log Alert exists for Create or Update Network Security Group\n# 6.1.2.4  Ensure that Activity Log Alert exists for Delete Network Security Group\n# 6.1.2.5  Ensure that Activity Log Alert exists for Create or Update Security Solution\n# 6.1.2.6  Ensure that Activity Log Alert exists for Delete Security\n# 6.1.2.7  Ensure that Activity Log Alert exists for Create or Update SQL Server Firewall Rule\n# 6.1.2.8  Ensure that Activity Log Alert exists for Delete SQL Server Firewall Rule\n# 6.1.2.9  Ensure that Activity Log Alert exists for Create or Update Public IP Address rule\n# 6.1.2.10 Ensure that Activity Log Alert exists for Delete Public IP Address rule\n# 6.1.2.11 Ensure that an Activity Log Alert exists for Service Health\n# 6.1.3.1  Ensure Application Insights are Configured\n# 6.1.4    Ensure that Azure Monitor Resource Logging is Enabled for All Services that Support it\n# 6.1.5    Ensure that SKU Basic/Consumption is not used on artifacts that need to be monitored (Particularly for Production Workloads)\n#\n# Refer to Section(s) 6.1-2 Page(s) 191-286 CIS Microsoft Azure Foundations Benchmark v5.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_logging_and_monitoring () {\n  print_function \"audit_azure_logging_and_monitoring\"\n  check_message  \"Azure Logging and Monitoring\"\n  # 6.1.1.1  Ensure that a 'Diagnostic Setting' exists for Subscription Activity Logs\n  audit_azure_subscription_diagnostic_settings\n  # 6.1.1.2  Ensure Diagnostic Setting captures appropriate categories\n  audit_azure_diagnostic_setting_categories\n  # 6.1.1.3  Ensure the storage account containing the container with activity logs is encrypted with customer-managed key (CMK)\n  audit_azure_activity_logs_cmk\n  # 6.1.1.4  Ensure that logging for Azure Key Vault is 'Enabled'\n  audit_azure_key_vault_logging\n  # 6.1.1.5  Ensure that Network Security Group Flow logs are captured and sent to Log Analytics - TBD\n  audit_azure_nsg_flow_logs\n  # 6.1.1.6  Ensure that logging for Azure AppService 'HTTP logs' is enabled - TBD\n  audit_azure_app_service_http_logs\n  # 6.1.1.7  Ensure that virtual network flow logs are captured and sent to Log Analytics\n  audit_azure_virtual_network_flow_logs\n  # 6.1.1.8  Ensure that a Microsoft Entra diagnostic setting exists to send Microsoft Graph activity logs to an appropriate destination\n  audit_azure_graph_diagnostic_settings\n  # 6.1.1.9  Ensure that a Microsoft Entra diagnostic setting exists to send Microsoft Entra activity logs to an appropriate destination\n  audit_azure_entra_diagnostic_settings\n  # 6.1.1.10 Ensure that Intune logs are captured and sent to Log Analytics\n  audit_azure_intune_logs\n  # 6.1.2.1  Ensure that Activity Log Alert exists for Create Policy Assignment\n  # 6.1.2.2  Ensure that Activity Log Alert exists for Delete Policy Assignment\n  # 6.1.2.3  Ensure that Activity Log Alert exists for Create or Update Network Security Group\n  # 6.1.2.4  Ensure that Activity Log Alert exists for Delete Network Security Group\n  # 6.1.2.5  Ensure that Activity Log Alert exists for Create or Update Security Solution\n  # 6.1.2.6  Ensure that Activity Log Alert exists for Delete Security\n  # 6.1.2.7  Ensure that Activity Log Alert exists for Create or Update SQL Server Firewall Rule\n  # 6.1.2.8  Ensure that Activity Log Alert exists for Delete SQL Server Firewall Rule\n  # 6.1.2.9  Ensure that Activity Log Alert exists for Create or Update Public IP Address rule\n  # 6.1.2.10 Ensure that Activity Log Alert exists for Delete Public IP Address rule\n  # 6.1.2.11 Ensure that an Activity Log Alert exists for Service Health\n  audit_azure_activity_log_alerts\n  # 6.1.3.1  Ensure Application Insights are Configured\n  audit_azure_application_insights\n  # 6.1.4    Ensure that Azure Monitor Resource Logging is Enabled for All Services that Support it\n  audit_azure_resource_logging\n  # 6.1.5    Ensure that SKU Basic/Consumption is not used on artifacts that need to be monitored (Particularly for Production Workloads)\n  audit_azure_sku_basic_consumption\n}\n"
  },
  {
    "path": "modules/azure/logging/audit_azure_resource_logging.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_resource_logging\n#\n# Check Azure Resource Logging\n#\n# 6.1.4 Ensure that Azure Monitor Resource Logging is Enabled for All Services that Support it\n#\n# Refer to Section(s) 6.1.4 Page(s) 275-80 CIS Microsoft Azure Foundations Benchmark v5.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_resource_logging () {\n  print_function \"audit_azure_resource_logging\"\n  check_message  \"Azure Resource Logging\"\n  command=\"az account show --query id --output tsv\"\n  command_message  \"${command}\"\n  sub_ids=\"$( eval \"${command}\" )\"\n  for sub_id in $sub_ids; do\n    command=\"az resource list --subscription \\\"${sub_id}\\\" --query \\\"[].id\\\" --output tsv\"\n    command_message  \"${command}\"\n    res_ids=\"$( eval \"${command}\" )\"\n    for res_id in ${res_ids}; do\n      check_azure_monitoring_diagnostics_value \"${res_id}\"\n    done\n  done\n}\n"
  },
  {
    "path": "modules/azure/logging/audit_azure_subscription_diagnostic_settings.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_subscription_diagnostic_settings\n#\n# Check Azure Subscription Diagnostic Settings\n#\n# 6.1.1.1  Ensure that Diagnostic Settings are enabled for all Azure Subscriptions\n#\n# Refer to Section(s) 6.1.1.1 Page(s) 194-8   CIS Microsoft Azure Foundations Benchmark v5.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_subscription_diagnostic_settings () {\n  print_function \"audit_azure_subscription_diagnostic_settings\"\n  check_message  \"Azure Subscription Diagnostic Settings Activity Logs\"\n  command=\"az account list --query \\\"[].id\\\" --output tsv 2>/dev/null\"\n  command_message \"${command}\"\n  sub_ids=$( eval \"${command}\" )\n  for sub_id in ${sub_ids}; do\n    command=\"az monitor diagnostic-settings list --scope /subscriptions/${sub_id} --query \\\"[].value\\\" --output tsv 2>/dev/null\"\n    command_message  \"${command}\"\n    settings=$( eval \"${command}\" )\n    if [ -z \"${settings}\" ]; then\n      inc_insecure \"There are no diagnostic settings for subscription ${sub_id}\"\n    else\n      inc_secure   \"There are diagnostic settings for subscription ${sub_id}\"\n    fi\n    command=\"az resource list --subscription ${sub_id} --query \\\"[].id\\\" --output tsv\"\n    command_message \"${command}\"\n    res_ids=$( eval \"${command}\" )\n    for res_id in ${res_ids}; do\n      command=\"az monitor diagnostic-settings list --resource ${res_id} --query \\\"[].value\\\" --output tsv 2>/dev/null\"\n      command_message  \"${command}\"\n      settings=$( eval \"${command}\" )\n      if [ -z \"${settings}\" ]; then\n        inc_insecure \"There are no diagnostic settings for resource ${res_id}\"\n      else\n        inc_secure   \"There are diagnostic settings for resource ${res_id}\"\n      fi    \n    done\n  done\n}\n"
  },
  {
    "path": "modules/azure/main/audit_azure_custom_subscription_admin_roles.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_custom_subscription_admin_roles\n#\n# Check Azure Custom Subscription Admin Roles\n#\n# 5.23  Ensure that custom subscription administrator roles are not used\n#\n# Refer to Section(s) 5.23 Page(s) 174-6 CIS Microsoft Azure Foundations Benchmark v5.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_custom_subscription_admin_roles () {\n  print_function \"audit_azure_custom_subscription_admin_roles\"\n  check_message  \"Azure Custom Subscription Admin Roles\"\n  command=\"az role definition list --custom-role-only True | grep -iE \\\"assignableScope|subscription\\\" | grep \\\"*\\\"\"\n  command_message      \"${command}\"\n  actual_value=$( eval \"${command}\" )\n  if [ -z \"${actual_value}\" ]; then\n    inc_secure      \"No custom subscription administrator roles exist\"\n  else\n    inc_insecure    \"Custom subscription administrator roles exist\"\n    verbose_message \"az role definition delete --name <role name>\"\n  fi\n}\n"
  },
  {
    "path": "modules/azure/main/audit_azure_extensions.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_extensions\n#\n# Audit Azure extensions setting\n#\n# Make sure extenstions are not set to auto install and are not set to preview versions\n#\n# Refer to https://learn.microsoft.com/en-us/cli/azure/azure-cli-extensions-overview?view=azure-cli-latest\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_extensions () {\n  print_function \"audit_azure_extensions\"\n  check_message  \"Azure extensions settings\"\n  for parameter_name in \"extension.use_dynamic_install\" \"extension.run_after_dynamic_install\" \"extension.dynamic_install_allow_preview\"; do\n    if [ \"${parameter_name}\" = \"extension.dynamic_install_allow_preview\" ]; then\n      correct_value=\"false\"\n    else\n      correct_value=\"no\"\n    fi\n    check_message \"Azure extensions parameter \\\"${parameter_name}\\\" is set to \\\"${correct_value}\\\"\"\n    command=\"az config get \\\"${parameter_name}\\\" --query value --output tsv 2> /dev/null\"\n    command_message      \"${command}\"\n    actual_value=$( eval \"${command}\" )\n    if [ \"${actual_value}\" = \"${correct_value}\" ]; then\n      inc_secure      \"Azure extensions parameter \\\"${parameter_name}\\\" is set to \\\"${correct_value}\\\"\"\n    else\n      inc_insecure    \"Azure extensions parameter \\\"${parameter_name}\\\" is not set to \\\"${correct_value}\\\"\"\n      verbose_message \"az config set ${parameter_name}=${correct_value}\" \"fix\"\n    fi\n  done\n}\n"
  },
  {
    "path": "modules/azure/main/audit_azure_sku_basic_consumption.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_sku_basic_consumption\n#\n# Check Azure SKU Basic/Consumption\n#\n# 6.1.5 Ensure that SKU Basic/Consumption is not used on artifacts that need to be monitored (Particularly for Production Workloads)\n#\n# Refer to Section(s) 6.1.5 Page(s) 281-3 CIS Microsoft Azure Foundations Benchmark v5.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_sku_basic_consumption () {\n  print_function \"audit_azure_sku_basic_consumption\"\n  check_message  \"Azure SKU Basic/Consumption\"\n  command=\"az graph query -q \\\"Resources | where sku contains 'Basic' or sku contains 'consumption' | order by type\\\" --query count --output tsv 2> /dev/null\"\n  command_message    \"${command}\"\n  res_check=\"$( eval \"${command}\" )\"\n  if [ \"${res_check}\" -eq 0 ]; then\n    inc_secure   \"No resources that are being monitored are using SKU Basic/Consumption\"\n  else\n    inc_insecure \"Resources that are being monitored are using SKU Basic/Consumption\"\n  fi\n}\n"
  },
  {
    "path": "modules/azure/main/audit_azure_subscription_owners.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_subscription_owners\n#\n# Check Azure Subscription Owners\n#\n# 5.27  Ensure that there are no more than 3 members with the Subscription Owner role\n#\n# Refer to Section(s) 5.27 Page(s) 186-8 CIS Microsoft Azure Foundations Benchmark v5.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\naudit_azure_subscription_owners () {\n  print_function  \"audit_azure_subscription_owners\"\n  check_message   \"Azure Subscription Owners\"\n  command=\"az account list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  sub_ids=$( eval \"${command}\" )\n  max_owners=\"3\"\n  for sub_id in ${sub_ids}; do\n    command=\"az role assignment list --role Owner --scope /subscriptions/${sub_id} --query \\\"[].id\\\" --output tsv\"\n    command_message     \"${command}\"\n    role_owners=$( eval \"${command}\" )\n    if [ -z \"${role_owners}\" ]; then\n      inc_secure \"There are members with the Subscription Owner role\"\n    else\n      owner_count=$( echo \"${role_owners}\" | wc -l )\n      if [ \"${owner_count}\" -gt \"${max_owners}\" ]; then\n        inc_insecure \"There are more than ${max_owners} members with the Subscription Owner role\"\n      else\n        inc_secure   \"There are ${owner_count} members with the Subscription Owner role\"\n      fi\n      role_assignment_ids=$( echo \"${role_owners}\" | tr '\\n' ' ' )\n      fix_message \"az role assignment delete --ids \\\"${role_assignment_ids}\\\"\"\n    fi\n  done\n}"
  },
  {
    "path": "modules/azure/main/audit_azure_survey.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_survey\n#\n# Audit Azure survey setting\n#\n# Refer to https://learn.microsoft.com/en-au/cli/azure/command-line-tools-survey-guidance?view=azure-cli-latest\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_survey () {\n  print_function  \"audit_azure_survey\"\n  check_message   \"Azure survey setting\"\n  command=\"az config get core.survey_message --query value --output tsv 2> /dev/null\"\n  command_message \"${command}\"\n  survey=$( eval  \"${command}\" )\n  if [ \"${survey}\" = \"false\" ]; then\n    inc_secure      \"Azure survey reminder is disabled\"\n  else\n    inc_insecure    \"Azure survey reminder is enabled\"\n    verbose_message \"az config set core.survey_message=false\" \"fix\"\n  fi\n}\n"
  },
  {
    "path": "modules/azure/network/audit_azure_network_private_endpoints.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_network_private_endpoints\n#\n# Check Azure Network Private Endpoints\n#\n# 2.2.2.1 Ensure Private Endpoints are used to access {service}\n#\n# Refer to Section(s) 2 Page(s) 25- CIS Microsoft Azure Storage Services Benchmark v1.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_network_private_endpoints () {\n  print_function \"audit_azure_network_private_endpoints\"\n  check_message  \"Azure Network Private Endpoints\"\n  command=\"az network private-endpoint list --query \\\"[].id\\\" --output tsv\"\n  command_message     \"${command}\"\n  p_endpoints=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${p_endpoints}\" ]; then\n    info_message \"No Private Endpoints found\"\n    return\n  fi\n  for p_endpoint in ${p_endpoints}; do\n    command=\"az network private-endpoint show --id \\\"${p_endpoint}\\\" --query \\\"id\\\" --output tsv\"\n    command_message     \"${command}\"\n    res_name=$( eval    \"${command}\" )\n    command=\"az network private-endpoint show --id \\\"${p_endpoint}\\\" --query \\\"name\\\" --output tsv\"\n    command_message     \"${command}\"\n    res_group=$( eval   \"${command}\" )\n    # 2.2.2.1 Ensure Private Endpoints are used to access {service}\n    command=\"az network private-endpoint list --resource-group \\\"${res_group}\\\" --query \\\"[?contains(resourceGroup, '${res_group}') && contains(name, '${res_name}')]\\\" --output tsv\"\n    command_message     \"${command}\"\n    p_end_test=$( eval  \"${command}\" )\n    if [ -z \"${p_end_test}\" ]; then\n      inc_insecure \"Private Endpoints are not used to access ${res_name}\"\n    else\n      inc_secure   \"Private Endpoints are used to access ${res_name}\"\n    fi\n  done\n}\n"
  },
  {
    "path": "modules/azure/network/audit_azure_network_security_perimeter.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_network_security_perimeter\n#\n# Check Azure Network Security Perimeter\n#\n# 7.16 Ensure Azure Network Security Perimeter is used to secure Azure platform-as-a-service resources\n#\n# Refer to Section(s) 7.16 Page(s) 334-7 CIS Microsoft Azure Foundations Benchmark v5.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_network_security_perimeter () {\n  print_function \"audit_azure_network_security_perimeter\"\n  check_message  \"Azure Network Security Perimeter\"\n  command=\"az group list --query '[].name' --output tsv 2> /dev/null\"\n  command_message     \"${command}\"\n  group_names=$( eval \"${command}\" )\n  if [ -z \"${group_names}\" ]; then\n    info_message \"No NSP instances found\"\n    return\n  fi\n  for group_name in ${group_names}; do\n    command=\"az network perimeter list --resource-group \\\"${group_name}\\\" --query '[].name' --output tsv 2> /dev/null\"\n    command_message  \"${command}\"\n    nsp_list=$( eval \"${command}\" )\n    if [ -z \"${nsp_list}\" ]; then\n      inc_insecure  \"No Azure Network Security Perimeter found for resource group \\\"${group_name}\\\"\"\n    else\n      for nsp_name in ${nsp_list}; do\n        check_azure_network_security_perimeter_value \"${nsp_name}\" \"${group_name}\" \"association\" \"[].resourceGroup\" \"eq\" \"${group_name}\"\n      done\n    fi\n  done\n}\n"
  },
  {
    "path": "modules/azure/network/audit_azure_network_watcher.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_network_watcher\n#\n# Check Azure Network Watcher\n#\n# 7.6 Ensure that Network Watcher is 'Enabled' for Azure Regions that are in use\n#\n# Refer to Section(s) 7.6 Page(s) 306-8 CIS Microsoft Azure Foundations Benchmark v5.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_network_watcher () {\n  print_function \"audit_azure_network_watcher\"\n  check_message  \"Azure Network Watcher\"\n  command=\"az network watcher list --query '[].id' --output tsv 2> /dev/null\"\n  command_message     \"${command}\"\n  watcher_ids=$( eval \"${command}\" )\n  if [ -z \"${watcher_ids}\" ]; then\n    info_message \"No Network Watcher instances found\"\n    return\n  fi\n  for watcher_id in ${watcher_ids}; do\n    check_azure_network_watcher_value \"${watcher_id}\" \"provisioningState\" \"Succeeded\"\n  done\n}\n"
  },
  {
    "path": "modules/azure/network/audit_azure_network_watcher_flow_logs.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_network_watcher_flow_logs\n#\n# Check Azure Network Watcher Flow Logs\n#\n# 7.8 Ensure that virtual network flow log retention days is set to greater than or equal to 90\n#\n# Refer to Section(s) 7.8 Page(s) 311-3 CIS Microsoft Azure Foundations Benchmark v5.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_network_watcher_flow_logs () {\n  print_function \"audit_azure_network_watcher_flow_logs\"\n  check_message  \"Azure Network Watcher Flow Logs\"\n  command=\"az network watcher list --query '[].location' --output tsv 2> /dev/null\"\n  command_message    \"${command}\"\n  locations=$( eval  \"${command}\" )\n  if [ -z \"${locations}\" ]; then\n    info_message \"No Network Watcher instances found\"\n    return\n  fi\n  for location in $locations; do\n    command=\"az network watcher list-flow-logs --location \\\"${location}\\\" --query '[].name' --output tsv 2> /dev/null\"\n    command_message   \"${command}\"\n    flow_logs=$( eval \"${command}\" )\n    if [ -z \"${flow_logs}\" ]; then\n      info_message   \"No Flow Logs found\"\n      return\n    fi\n    for flow_log in ${flow_logs}; do\n      check_azure_network_watcher_flow_logs_value \"${location}\" \"${flow_log}\" \"retentionPolicy.days\" \"90\" \"retention\"\n    done\n  done\n}\n"
  },
  {
    "path": "modules/azure/network/audit_azure_networking_services.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_networking_services\n#\n# Audit Azure Networking Services\n#\n# 7.1   Ensure that RDP access from the Internet is evaluated and restricted\n# 7.2   Ensure that SSH access from the Internet is evaluated and restricted\n# 7.3   Ensure that UDP access from the Internet is evaluated and restricted\n# 7.4   Ensure that HTTP(S) access from the Internet is evaluated and restricted\n# 7.5   Ensure that network security group flow log retention days is set to greater than or equal to 90\n# 7.6   Ensure that Network Watcher is 'Enabled' for Azure Regions that are in use\n# 7.7   Ensure that Public IP addresses are Evaluated on a Periodic Basis (Manual)\n# 7.8   Ensure that virtual network flow log retention days is set to greater than or equal to 90\n# 7.9   Ensure 'Authentication type' is set to 'Azure Active Directory' only for Azure VPN Gateway point-to-site configuration - TBD\n# 7.10  Ensure Azure Web Application Firewall (WAF) is enabled on Azure Application Gateway\n# 7.11  Ensure subnets are associated with network security groups\n# 7.12  Ensure the SSL policy's 'Min protocol version' is set to 'TLSv1_2' or higher on Azure Application Gateway\n# 7.13  Ensure 'HTTP2' is set to 'Enabled' on Azure Application Gateway\n# 7.14  Ensure request body inspection is enabled in Azure Web Application Firewall policy on Azure Application Gateway\n# 7.15  Ensure bot protection is enabled in Azure Web Application Firewall policy on Azure Application Gateway\n# 7.16  Ensure Azure Network Security Perimeter is used to secure Azure platform-as-a-service resources\n#\n# Refer to Section(s) 7.1-16 Page(s) 287-337 CIS Microsoft Azure Foundations Benchmark v5.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_networking_services () {\n  print_function \"audit_azure_networking_services\"\n  check_message  \"Azure Networking Services\"\n  audit_azure_nsg_security_rules\n  audit_azure_network_watcher\n  audit_azure_public_ips\n  audit_azure_network_watcher_flow_logs\n  audit_azure_authentication_type\n}\n"
  },
  {
    "path": "modules/azure/network/audit_azure_public_ips.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_public_ips\n#\n# Audit Azure Public IPs\n#\n# 7.7   Ensure that Public IP addresses are Evaluated on a Periodic Basis (Manual)\n#\n# Refer to Section(s) 7.7 Page(s) 309-10 CIS Microsoft Azure Foundations Benchmark v5.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_public_ips () {\n  print_function \"audit_azure_public_ips\"\n  check_message  \"Azure Public IPs\"\n  command=\"az network public-ip list --query '[].id' --output tsv\"\n  command_message \"${command}\"\n  res_ids=$( eval \"${command}\" )\n  if [ -z \"${res_ids}\" ]; then\n    info_message  \"No Public IPs found\"\n    return\n  fi\n  for res_id in ${res_ids}; do\n    check_azure_public_ip_value \"${res_id}\" \"ipAddress\" \"eq\" \"\"\n  done\n}\n"
  },
  {
    "path": "modules/azure/network/audit_azure_virtual_network_flow_logs.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_virtual_network_flow_logs\n#\n# Check Azure Virtual Network Flow Logs\n#\n# 6.1.1.7  Ensure that virtual network flow logs are captured and sent to Log Analytics\n#\n# Refer to Section(s) 6.1.1.7 Page(s) 215-7 CIS Microsoft Azure Foundations Benchmark v5.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_virtual_network_flow_logs () {\n  print_function \"audit_azure_virtual_network_flow_logs\"\n  check_message  \"Azure Virtual Network Flow Logs\"\n}\n"
  },
  {
    "path": "modules/azure/network/audit_azure_vnets.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_vnets\n#\n# Check Azure VNets\n#\n# 7.11 Ensure subnets are associated with network security groups\n#\n# Refer to Section(s) 7.11 Page(s) 319-21 CIS Microsoft Azure Foundations Benchmark v5.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_vnets () {\n  print_function \"audit_azure_vnets\"\n  check_message  \"Azure VNets\"\n  command=\"az network vnet list --query '[].resourceGroup' --output tsv 2> /dev/null\"\n  command_message    \"${command}\"\n  res_groups=$( eval \"${command}\" )\n  if [ -z \"${res_groups}\" ]; then\n    info_message \"No VNets found\"\n    return\n  fi\n  for res_group in $res_groups; do\n    command=\"az network vnet list --resource-group \\\"${res_group}\\\" --query '[].name' --output tsv 2> /dev/null\"\n    command_message   \"${command}\"\n    vnet_list=$( eval \"${command}\" )\n    for vnet_name in $vnet_list; do\n      command=\"az network vnet show --name \\\"${vnet_name}\\\" --resource-group \\\"${res_group}\\\" --query 'subnets[].name' --output tsv 2> /dev/null\"\n      command_message     \"${command}\"\n      subnet_list=$( eval \"${command}\" )\n      for subnet_name in ${subnet_list}; do\n        check_azure_vnet_value \"${vnet_name}\" \"${res_group}\" \"${subnet_name}\" \"networkSecurityGroup.id\" \"ne\" \"\"\n      done\n    done\n  done\n}\n"
  },
  {
    "path": "modules/azure/security/audit_azure_authentication_type.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_authentication_type\n#\n# Check Azure Authentication Type\n#\n# 7.9  Ensure 'Authentication type' is set to 'Azure Active Directory' only for Azure VPN Gateway point-to-site configuration\n#\n# Refer to Section 7.9 Page(s) 315-8 CIS Microsoft Azure Foundations Benchmark v5.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_authentication_type () {\n  print_function \"audit_azure_authentication_type\"\n  check_message  \"Azure Authentication Type\"\n}\n"
  },
  {
    "path": "modules/azure/security/audit_azure_guest_users.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_guest_users\n#\n# Check Azure Guest Users\n#\n# 5.3.2 Ensure that guest user access is restricted\n#\n# Refer to Section(s) 5.3.2 Page(s) 111-4 CIS Microsoft Azure Foundations Benchmark v5.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_guest_users () {\n  print_function \"audit_azure_guest_users\"\n  check_message  \"Azure Guest Users\"\n  command=\"az ad user list --query \\\"[?contains(userType, 'Guest')]\\\" --query \\\"id\\\" --output tsv\"\n  command_message     \"${command}\"\n  guest_users=$( eval \"${command}\" )\n  if [ -z \"${guest_users}\" ]; then\n    inc_secure   \"No guest users found\"\n  else\n    inc_insecure \"Guest users found: ${guest_users}\"\n  fi\n}\n"
  },
  {
    "path": "modules/azure/security/audit_azure_identity_services.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_identity_services\n#\n# Check Azure Identity Services\n#\n# 5.1.1 Ensure that 'security defaults' is enabled in Microsoft Entra ID - TBD\n# 5.1.2 Ensure that 'multifactor authentication' is 'enabled' for all users - TBD\n# 5.1.3 Ensure that 'Allow users to remember multifactor authentication on devices they trust' is disabled - TBD\n# 5.2.1 Ensure that 'trusted locations' are defined - TBD\n# 5.2.2 Ensure that an exclusionary geographic Conditional Access policy is considered - TBD\n# 5.2.3 Ensure that an exclusionary device code flow policy is considered - TBD\n# 5.2.4 Ensure that a multifactor authentication policy exists for all users - TBD\n# 5.2.5 Ensure that multifactor authentication is required for risky sign-ins - TBD\n# 5.2.6 Ensure that multifactor authentication is required for Windows Azure Service Management API - TBD\n# 5.2.7 Ensure that multifactor authentication is required to access Microsoft Admin Portals - TBD\n# 5.2.8 Ensure a Token Protection Conditional Access policy is considered - TBD\n# 5.3.1 Ensure that Azure admin accounts are not used for daily operations - TBD\n# 5.3.2 Ensure that guest users are reviewed on a regular basis\n# 5.3.3 Ensure that use of the 'User Access Administrator' role is restricted\n# 5.3.4 Ensure that all 'privileged' role assignments are periodically reviewed - TBD\n# 5.3.5 Ensure disabled user accounts do not have read, write, or owner permissions - TBD\n# 5.3.6 Ensure 'Tenant Creator' role assignments are periodically reviewed - TBD\n# 5.3.7 Ensure all non-privileged role assignments are periodically reviewed - TBD\n# 5.4   Ensure that 'Restrict non-admin users from creating tenants' is set to 'Yes' - TBD\n# 5.5   Ensure that 'Number of methods required to reset' is set to '2' - TBD\n# 5.6   Ensure that account 'Lockout threshold' is less than or equal to '10' - TBD\n# 5.7   Ensure that account 'Lockout duration in seconds' is greater than or equal to '60' - TBD\n# 5.8   Ensure that a 'Custom banned password list' is set to 'Enforce' - TBD\n# 5.9   Ensure that 'Number of days before users are asked to re-confirm their authentication information' is not set to '0' - TBD\n# 5.10  Ensure that 'Notify users on password resets?' is set to 'Yes' - TBD\n# 5.11  Ensure that 'Notify all admins when other admins reset their password?' is set to 'Yes' - TBD\n# 5.12  Ensure that 'User consent for applications' is set to 'Do not allow user consent'\n# 5.13  Ensure that 'User consent for applications' is set to 'Allow user consent for apps from verified publishers, for selected permissions' - TBD\n# 5.14  Ensure that 'Users can register applications' is set to 'No' - TBD\n# 5.15  Ensure that 'Guest users access restrictions' is set to 'Guest user access is restricted to properties and memberships of their own directory objects' - TBD\n# 5.16  Ensure that 'Guest invite restrictions' is set to 'Only users assigned to specific admin roles [...]' or 'No one [..]' - TBD\n# 5.18  Ensure that 'Restrict user ability to access groups features in My Groups' is set to 'Yes' - TBD\n# 5.19  Ensure that 'Users can create security groups in Azure portals, API or PowerShell' is set to 'No' - TBD\n# 5.20  Ensure that 'Owners can manage group membership requests in My Groups' is set to 'No' - TBD\n# 5.21  Ensure that 'Users can create Microsoft 365 groups in Azure portals, API or PowerShell' is set to 'No' - TBD\n# 5.22  Ensure that 'Require Multifactor Authentication to register or join devices with Microsoft Entra' is set to 'Yes' - TBD\n# 5.23  Ensure that no custom subscription administrator roles exist\n# 5.24  Ensure that a custom role is assigned permissions for administering resource locks - TBD\n# 5.25  Ensure that 'Subscription leaving Microsoft Entra tenant' and 'Subscription entering Microsoft Entra tenant' is set to 'Permit no one' - TBD\n# 5.26  Ensure fewer than 5 users have global administrator assignment - TBD\n# 5.27  Ensure there are between 2 and 3 subscription owners\n# 5.28  Ensure passwordless authentication methods are considered - TBD\n#\n# Refer to Section(s) 5.1-28 Page(s) 70-190 CIS Microsoft Azure Foundations Benchmark v5.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_identity_services () {\n  print_function \"audit_azure_identity_services\"\n  check_message  \"Azure Identity Services\"\n  # 5.1.1 Ensure that 'security defaults' is enabled in Microsoft Entra ID - TBD\n  # 5.1.2 Ensure that 'multifactor authentication' is 'enabled' for all users - TBD\n  # 5.1.3 Ensure that 'Allow users to remember multifactor authentication on devices they trust' is disabled - TBD\n  # 5.2.1 Ensure that 'trusted locations' are defined - TBD\n  # 5.2.2 Ensure that an exclusionary geographic Conditional Access policy is considered - TBD\n  # 5.2.3 Ensure that an exclusionary device code flow policy is considered - TBD\n  # 5.2.4 Ensure that a multifactor authentication policy exists for all users - TBD\n  # 5.2.5 Ensure that multifactor authentication is required for risky sign-ins - TBD\n  # 5.2.6 Ensure that multifactor authentication is required for Windows Azure Service Management API - TBD\n  # 5.2.7 Ensure that multifactor authentication is required to access Microsoft Admin Portals - TBD\n  # 5.2.8 Ensure a Token Protection Conditional Access policy is considered - TBD\n  # 5.3.1 Ensure that Azure admin accounts are not used for daily operations - TBD\n  # 5.3.2 Ensure that guest users are reviewed on a regular basis\n  audit_azure_guest_users\n  # 5.3.3 Ensure that use of the 'User Access Administrator' role is restricted\n  audit_azure_user_access_admin_role\n  # 5.3.4 Ensure that all 'privileged' role assignments are periodically reviewed - TBD\n  # 5.3.5 Ensure disabled user accounts do not have read, write, or owner permissions - TBD\n  # 5.3.6 Ensure 'Tenant Creator' role assignments are periodically reviewed - TBD\n  # 5.3.7 Ensure all non-privileged role assignments are periodically reviewed - TBD\n  # 5.4   Ensure that 'Restrict non-admin users from creating tenants' is set to 'Yes' - TBD\n  # 5.5   Ensure that 'Number of methods required to reset' is set to '2' - TBD\n  # 5.6   Ensure that account 'Lockout threshold' is less than or equal to '10' - TBD\n  # 5.7   Ensure that account 'Lockout duration in seconds' is greater than or equal to '60' - TBD\n  # 5.8   Ensure that a 'Custom banned password list' is set to 'Enforce' - TBD\n  # 5.9   Ensure that 'Number of days before users are asked to re-confirm their authentication information' is not set to '0' - TBD\n  # 5.10  Ensure that 'Notify users on password resets?' is set to 'Yes' - TBD\n  # 5.11  Ensure that 'Notify all admins when other admins reset their password?' is set to 'Yes' - TBD\n  # 5.12  Ensure that 'User consent for applications' is set to 'Do not allow user consent'\n  # 5.13  Ensure that 'User consent for applications' is set to 'Allow user consent for apps from verified publishers, for selected permissions' - TBD\n  # 5.14  Ensure that 'Users can register applications' is set to 'No' - TBD\n  # 5.15  Ensure that 'Guest users access restrictions' is set to 'Guest user access is restricted to properties and memberships of their own directory objects' - TBD\n  # 5.16  Ensure that 'Guest invite restrictions' is set to 'Only users assigned to specific admin roles [...]' or 'No one [..]' - TBD\n  # 5.18  Ensure that 'Restrict user ability to access groups features in My Groups' is set to 'Yes' - TBD\n  # 5.19  Ensure that 'Users can create security groups in Azure portals, API or PowerShell' is set to 'No' - TBD\n  # 5.20  Ensure that 'Owners can manage group membership requests in My Groups' is set to 'No' - TBD\n  # 5.21  Ensure that 'Users can create Microsoft 365 groups in Azure portals, API or PowerShell' is set to 'No' - TBD\n  # 5.22  Ensure that 'Require Multifactor Authentication to register or join devices with Microsoft Entra' is set to 'Yes' - TBD\n  # 5.23  Ensure that no custom subscription administrator roles exist\n  audit_azure_custom_subscription_admin_roles\n  # 5.24  Ensure that a custom role is assigned permissions for administering resource locks - TBD\n  # 5.25  Ensure that 'Subscription leaving Microsoft Entra tenant' and 'Subscription entering Microsoft Entra tenant' is set to 'Permit no one' - TBD\n  # 5.26  Ensure fewer than 5 users have global administrator assignment - TBD\n  # 5.27  Ensure there are between 2 and 3 subscription owners\n  audit_azure_subscription_owners\n  # 5.28  Ensure passwordless authentication methods are considered - TBD\n}\n"
  },
  {
    "path": "modules/azure/security/audit_azure_locks.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_locks\n#\n# Audit Azure Locks\n#\n# This requires the Azure CLI to be installed and configured\n#\n\naudit_azure_locks () {\n  res_type=\"${1}\"\n  lock_type=\"${2}\"\n  print_function \"audit_azure_locks\"\n  check_message  \"Azure Locks with Resource Type ${res_type}\"\n  command=\"az lock list --query \\\"[].name\\\" --resource-type \\\"${res_type}\\\" --output tsv\"\n  command_message    \"${command}\"\n  lock_names=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${lock_names}\" ]; then\n    info_message \"No Locks found\"\n    return\n  fi\n  for lock_name in ${lock_names}; do\n    command=\"az lock show --name \\\"${lock_name}\\\" --query \\\"[].resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    check_azure_lock_value \"${lock_name}\" \"${res_group}\" \"${res_type}\" \"properties.level\" \"eq\" \"${lock_type}\" \"--lock-type\"\n  done\n}"
  },
  {
    "path": "modules/azure/security/audit_azure_microsoft_defender.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_microsoft_defender\n#\n# Check Azure Microsoft Defender\n#\n# 8.1.1.1  Ensure Microsoft Defender CSPM is set to 'On'\n# 8.1.2.1  Ensure Microsoft Defender CWP is set to 'On'\n# 8.1.3.1  Ensure that Defender for Servers is set to 'On'\n# 8.1.3.2  Ensure that 'Vulnerability assessment for machines' component status is set to 'On'\n# 8.1.4.1  Ensure That Microsoft Defender for Containers Is Set To 'On'\n# 8.1.5.1  Ensure That Microsoft Defender for Storage Is Set To 'On'\n# 8.1.6.1  Ensure That Microsoft Defender for App Services Is Set To 'On'\n# 8.1.7.1  Ensure That Microsoft Defender for Azure Cosmos DB Is Set To 'On'\n# 8.1.7.2  Ensure That Microsoft Defender for Open-Source Relational Databases Is Set To 'On'\n# 8.1.7.3  Ensure That Microsoft Defender for (Managed Instance) Azure SQL Databases Is Set To 'On'\n# 8.1.7.4  Ensure That Microsoft Defender for SQL Servers on Machines Is Set To 'On'\n# 8.1.8.1  Ensure That Microsoft Defender for Azure Key Vault Is Set To 'On'\n# 8.1.9.1  Ensure That Microsoft Defender for Resource Manager Is Set To 'On'\n# 8.1.10   Ensure that Microsoft Defender for Cloud is configured to check VM operating systems for updates - TBD\n# 8.1.16   Ensure that Microsoft Defender External Attack Surface Monitoring (EASM) is enabled\n# 8.2.1    Ensure That Microsoft Defender for IoT Hub Is Set To 'On'\n#\n# Refer to Section(s) 8.1.1- Page(s) 338-472 CIS Microsoft Azure Foundations Benchmark v5.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_microsoft_defender () {\n  print_function \"audit_azure_microsoft_defender\"\n  check_message  \"Azure Microsoft Defender\"\n  # 8.1.1.1 Ensure Microsoft Defender CSPM is set to 'On'\n  check_azure_microsoft_defender_value \"Cloud Security Posture Management (CSPM)\"            \"CloudPosture\"                  \"Standard\" \"On\"     \"\"\n  # 8.1.2.1 Ensure Microsoft Defender CWP is set to 'On'\n  check_azure_microsoft_defender_value \"Cloud Workload Protection (CWP)\"                     \"Api\"                           \"Standard\" \"On\"     \"\"\n  # 8.1.3.1 Ensure that Defender for Servers is set to 'On'\n  check_azure_microsoft_defender_value \"Defender for Servers\"                                \"VirtualMachines\"               \"Standard\" \"On\"     \"\"\n  # 8.1.4.1 Ensure That Microsoft Defender for Containers Is Set To 'On'\n  check_azure_microsoft_defender_value \"Defender for Containers\"                             \"ContainerRegistry\"             \"Standard\" \"On\"     \"\"\n  # 8.1.5.1 Ensure That Microsoft Defender for Storage Is Set To 'On'\n  check_azure_microsoft_defender_value \"Defender for Storage\"                                \"StorageAccounts\"               \"Standard\" \"On\"     \"\"\n  # 8.1.6.1 Ensure That Microsoft Defender for App Services Is Set To 'On'\n  check_azure_microsoft_defender_value \"Defender for App Services\"                           \"AppServices\"                   \"Standard\" \"On\"     \"\"\n  # 8.1.7.1 Ensure That Microsoft Defender for Azure Cosmos DB Is Set To 'On'\n  check_azure_microsoft_defender_value \"Defender for Cosmos DB\"                              \"CosmosDbs\"                     \"Standard\" \"On\"     \"\"\n  # 8.1.7.2 Ensure That Microsoft Defender for Open-Source Relational Databases Is Set To 'On'\n  check_azure_microsoft_defender_value \"Defender for Open-Source Relational Databases\"       \"OpenSourceRelationalDatabases\" \"Standard\" \"On\"     \"\"\n  # 8.1.7.3 Ensure That Microsoft Defender for (Managed Instance) Azure SQL Databases Is Set To 'On'\n  check_azure_microsoft_defender_value \"Defender for (Managed Instance) Azure SQL Databases\" \"SqlServers\"                    \"Standard\" \"On\"     \"\"\n  # 8.1.7.4 Ensure That Microsoft Defender for SQL Servers on Machines Is Set To 'On'\n  check_azure_microsoft_defender_value \"Defender for SQL Servers on Machines\"                \"SqlServersVirtualMachines\"     \"Standard\" \"On\"     \"\"\n  # 8.1.8.1 Ensure That Microsoft Defender for Azure Key Vault Is Set To 'On'\n  check_azure_microsoft_defender_value \"Defender for Azure Key Vault\"                        \"KeyVaults\"                     \"Standard\" \"On\"     \"\"\n  # 8.1.9.1 Ensure That Microsoft Defender for Resource Manager Is Set To 'On'\n  check_azure_microsoft_defender_value \"Defender for Resource Manager\"                       \"Arm\"                           \"Standard\" \"On\"     \"\"\n  # 8.1.10  Ensure that Microsoft Defender for Cloud is configured to check VM operating systems for updates - TBD\n  # 8.1.16  Ensure that Microsoft Defender External Attack Surface Monitoring (EASM) is enabled\n  check_azure_microsoft_defender_value \"Defender for External Attack Surface Monitoring\"     \"\"                              \"Standard\" \"Exists\" \"Microsoft.Easm/workspaces\"\n  # 8.2.1 Ensure That Microsoft Defender for IoT Hub Is Set To 'On'\n  # check_azure_microsoft_defender_value \"Defender for IoT Hub\"                                \"IotHubs\"                       \"Standard\" \"On\"     \"Microsoft.Devices/IotHubs\"\n}\n"
  },
  {
    "path": "modules/azure/security/audit_azure_nsg_flow_logs.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_nsg_flow_logs\n#\n# Check Azure NSG Flow Logs\n#\n# 6.1.1.5 Ensure that Network Security Group Flow logs are captured and sent to Log Analytics\n#\n# Refer to Section(s) 6.1.1.5 Page(s) 211-2 CIS Microsoft Azure Foundations Benchmark v5.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_nsg_flow_logs () {\n  print_function \"audit_azure_nsg_flow_logs\"\n  check_message  \"Azure NSG Flow Logs\"\n}\n"
  },
  {
    "path": "modules/azure/security/audit_azure_nsg_security_rules.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_nsg_security_rules\n#\n# Check Azure NSG Security Rules\n#\n# 7.1 Ensure that RDP access from the Internet is evaluated and restricted\n# 7.2 Ensure that SSH access from the Internet is evaluated and restricted\n# 7.3 Ensure that UDP access from the Internet is evaluated and restricted\n# 7.4 Ensure that HTTP(S) access from the Internet is evaluated and restricted\n#\n# Refer to Section(s) 7.1-4 Pages 288-302 CIS Microsoft Azure Foundations Benchmark v5.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_nsg_security_rules () {\n  print_function \"audit_azure_nsg_security_rules\"\n  check_message  \"Azure NSG Security Rules\"\n  command=\"az network nsg list --query \\\"[].id\\\" --output tsv 2> /dev/null\"\n  command_message \"${command}\"\n  res_ids=$( eval \"${command}\" )\n  if [ -z \"${res_ids}\" ]; then\n    info_message  \"No NSG instances found\"\n    return\n  fi\n  for res_id in ${res_ids}; do\n    command=\"az network nsg show --ids ${res_id} --query \\\"name\\\" --output tsv 2> /dev/null\"\n    command_message   \"${command}\"\n    res_name=$( eval  \"${command}\" )\n    command=\"az network nsg show --ids ${res_id} --query \\\"resourceGroup\\\" --output tsv 2> /dev/null\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    command=\"az network nsg rule list --resource-group ${res_group} --nsg-name ${res_name} --query \\\"[].id\\\" --output tsv 2> /dev/null\"\n    command_message   \"${command}\"\n    rule_ids=$( eval  \"${command}\" )\n    for rule_id in ${rule_ids}; do\n      for port_no in 3389 22 53 80 123 161 389 443 1900; do\n        service_name=$( get_service_name_from_port_no \"${port_no}\" )\n        check_azure_nsg_security_rule_value \"${service_name}\" \"${rule_id}\" \"Inbound\" \"access\"                \"ne\" \"Allow\"\n        check_azure_nsg_security_rule_value \"${service_name}\" \"${rule_id}\" \"Inbound\" \"destinationPortRange\"  \"ne\" \"${port_no}\"\n        check_azure_nsg_security_rule_value \"${service_name}\" \"${rule_id}\" \"Inbound\" \"destinationPortRanges\" \"ne\" \"${port_no}\"\n        check_azure_nsg_security_rule_value \"${service_name}\" \"${rule_id}\" \"Inbound\" \"sourceAddressPrefix\"   \"ne\" \"0.0.0.0/0\"\n        check_azure_nsg_security_rule_value \"${service_name}\" \"${rule_id}\" \"Inbound\" \"sourceAddressPrefixes\" \"ne\" \"0.0.0.0/0\"\n      done\n    done  \n  done\n}\n"
  },
  {
    "path": "modules/azure/security/audit_azure_security_contacts.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_security_contacts\n#\n# Check Azure Security Contacts\n#\n# 8.1.12 Ensure That 'All users with the following roles' is set to 'Owner'\n# 8.1.13 Ensure 'Additional email addresses' is Configured with a Security Contact Email\n# 8.1.14 Ensure that 'Notify about alerts with the following severity (or higher)' is enabled\n#\n# Refer to Section(s) 8.1.12 Page(s) 406-8 CIS Microsoft Azure Foundations Benchmark v5.0.0\n#\n# Refer to https://learn.microsoft.com/en-us/cli/azure/security/contact?view=azure-cli-latest\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_security_contacts () {\n  print_function \"audit_azure_security_contacts\"\n  check_message  \"Azure Security Contacts\"\n  command=\"az security contact list --query \\\"[].name\\\" --output tsv 2> /dev/null\"\n  command_message \"${command}\"\n  c_names=$( eval \"${command}\" )\n  if [ -z \"${c_names}\" ]; then\n    inc_insecure    \"No Azure Security Contacts found\"\n    verbose_message \"az security contact create --name <contact-name> --email <email-address> --notifications-by-role '{\\\"state\\\":\\\"On\\\",\\\"roles\\\":[\\\"Owner\\\"]}' --alert-notifications '{\\\"state\\\":\\\"On\\\",\\\"minimalSeverity\\\":\\\"Low\\\"}'\" \"fix\"\n  else\n    for c_name in ${c_names}; do\n      check_azure_security_contact_value \"${c_name}\" \"email\"                              \"ne\" \"\"\n      check_azure_security_contact_value \"${c_name}\" \"alertNotifications.state\"           \"eq\" \"On\"\n      check_azure_security_contact_value \"${c_name}\" \"notificationsByRole.roles\"          \"eq\" \"Owner\"\n      check_azure_security_contact_value \"${c_name}\" \"alertNotifications.minimalSeverity\" \"eq\" \"Low\"\n    done\n  fi\n}\n"
  },
  {
    "path": "modules/azure/security/audit_azure_security_services.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_security_services\n#\n# Check Azure Security Services\n#\n# 8.1.1.1  Ensure Microsoft Defender CSPM is set to 'On'\n# 8.1.2.1  Ensure Microsoft Defender for APIs is set to 'On'\n# 8.1.3.1  Ensure that Defender for Servers is set to 'On'\n# 8.1.3.2  Ensure that 'Vulnerability assessment for machines' component status is set to 'On'\n# 8.1.3.3  Ensure that 'Endpoint protection' component status is set to 'On'\n# 8.1.3.4  Ensure that 'Agentless scanning for machines' component status is set to 'On'\n# 8.1.3.5  Ensure that 'File Integrity Monitoring' component status is set to 'On'\n# 8.1.4.1  Ensure That Microsoft Defender for Containers Is Set To 'On'\n# 8.1.5.1  Ensure That Microsoft Defender for Storage Is Set To 'On'\n# 8.1.5.2  Ensure Advanced Threat Protection Alerts for Storage Accounts Are Monitored\n# 8.1.6.1  Ensure That Microsoft Defender for App Services Is Set To 'On'\n# 8.1.7.1  Ensure That Microsoft Defender for Azure Cosmos DB Is Set To 'On'\n# 8.1.7.2  Ensure That Microsoft Defender for Open-Source Relational Databases Is Set To 'On'\n# 8.1.7.3  Ensure That Microsoft Defender for (Managed Instance) Azure SQL Databases Is Set To 'On'\n# 8.1.7.4  Ensure That Microsoft Defender for SQL Servers on Machines Is Set To 'On'\n# 8.1.8.1  Ensure That Microsoft Defender for Key Vault Is Set To 'On'\n# 8.1.9.1  Ensure That Microsoft Defender for Resource Manager Is Set To 'On'\n# 8.1.10   Ensure that Microsoft Defender for Cloud is configured to check VM operating systems for updates\n# 8.1.11   Ensure that Microsoft Cloud Security Benchmark policies are not set to 'Disabled'\n# 8.1.12   Ensure That 'All users with the following roles' is set to 'Owner'\n# 8.1.13   Ensure 'Additional email addresses' is Configured with a Security Contact Email\n# 8.1.14   Ensure that 'Notify about alerts with the following severity (or higher)' is enabled\n# 8.1.15   Ensure that 'Notify about attack paths with the following risk level (or higher)' is enabled\n# 8.1.16   Ensure that Microsoft Defender External Attack Surface Monitoring (EASM) is enabled\n# 8.2.1    Ensure That Microsoft Defender for IoT Hub Is Set To 'On'\n# 8.3.1    Ensure that the Expiration Date is set for all Keys in RBAC Key Vaults\n# 8.3.2    Ensure that the Expiration Date is set for all Keys in Non-RBAC Key Vaults.\n# 8.3.3    Ensure that the Expiration Date is set for all Secrets in RBAC Key Vaults\n# 8.3.4    Ensure that the Expiration Date is set for all Secrets in Non- RBAC Key Vaults\n# 8.3.5    Ensure 'Purge protection' is set to 'Enabled' (Automated)\n# 8.3.6    Ensure that Role Based Access Control for Azure Key Vault is enabled\n# 8.3.7    Ensure Public Network Access is Disabled\n# 8.3.8    Ensure Private Endpoints are used to access Azure Key Vault\n# 8.3.9    Ensure automatic key rotation is enabled within Azure Key Vault\n# 8.3.10   Ensure that Azure Key Vault Managed HSM is used when required\n# 8.3.11   Ensure certificate 'Validity Period (in months)' is less than or equal to '12'\n# 8.4.1    Ensure an Azure Bastion Host Exists\n# 8.5      Ensure Azure DDoS Network Protection is enabled on virtual networks\n#\n# Refer to Section(s) 8.1-5 Page(s) 338-472 CIS Microsoft Azure Foundations Benchmark v5.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_security_services () {\n  print_function \"audit_azure_security_services\"\n  check_message  \"Azure Security Services\"\n  # 8.1.1.1 Ensure Microsoft Defender CSPM is set to 'On'\n  audit_azure_microsoft_defender\n  # 8.1.3.2 Ensure that 'Vulnerability assessment for machines' component status is set to 'On' - TBD\n  # 8.1.3.3 Ensure that 'Endpoint protection' component status is set to 'On'\n  check_azure_security_setting_value \"Endpoint protection\"             \"WDATP\" \"enabled\" \"true\"\n  # 8.1.3.4 Ensure that 'Agentless scanning for machines' component status is set to 'On'\n  check_azure_security_setting_value \"Agentless scanning for machines\" \"CSPM\"  \"enabled\" \"true\"\n  # 8.1.3.5 Ensure that 'File Integrity Monitoring' component status is set to 'On' - TBD\n  # 8.1.5.2 Ensure Advanced Threat Protection Alerts for Storage Accounts Are Monitored - TBD\n  # 8.1.11 Ensure that Microsoft Cloud Security Benchmark policies are not set to 'Disabled' - TBD\n  # 8.1.12 Ensure That 'All users with the following roles' is set to 'Owner'\n  # 8.1.13 Ensure 'Additional email addresses' is Configured with a Security Contact Email\n  # 8.1.14 Ensure that 'Notify about alerts with the following severity (or higher)' is enabled\n  audit_azure_security_contacts\n  # 8.1.15 Ensure that 'Notify about attack paths with the following risk level (or higher)' is enabled - TBD\n  # 8.3.1 Ensure that the Expiration Date is set for all Keys in RBAC Key Vaults\n  # 8.3.2 Ensure that the Expiration Date is set for all Keys in Non-RBAC Key Vaults\n  # 8.3.3 Ensure that the Expiration Date is set for all Secrets in RBAC Key Vaults\n  # 8.3.4 Ensure that the Expiration Date is set for all Secrets in Non-RBAC Key Vaults\n  audit_azure_key_vault_keys\n  # 8.3.5 Ensure that Purge Protection is enabled for all Key Vaults\n  audit_azure_key_vault_purge_protection\n  # 8.3.6 Ensure that Role Based Access Control for Azure Key Vault is enabled\n  audit_azure_key_vault_rbac \n  # 8.3.7 Ensure Public Network Access is Disabled\n  audit_azure_key_vault_public_network_access\n}\n"
  },
  {
    "path": "modules/azure/security/audit_azure_user_access_admin_role.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_user_access_admin_role\n#\n# Check Azure User Access Administrator Role\n#\n# 5.3.3 Ensure that User Access Administrator Role is restricted\n#\n# Refer to Section(s) 5.3.3 Page(s) 115-6 CIS Microsoft Azure Foundations Benchmark v5.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_user_access_admin_role () {\n  print_function \"audit_azure_user_access_admin_role\"\n  check_message  \"Azure User Access Administrator Role\"\n  command=\"az role assignment list --role \\\"User Access Administrator\\\" --scope \\\"/\\\" --output tsv\"\n  command_message     \"${command}\"\n  assignments=$( eval \"${command}\" )\n  if [ -z \"${assignments}\" ]; then\n    inc_secure      \"User Access Administrator Role is restricted\"\n  else\n    inc_insecure    \"User Access Administrator Role is not restricted\"\n    verbose_message \"az role assignment delete --role \\\"User Access Administrator\\\" --scope \\\"/\\\"\" \"fix\"\n  fi\n}\n"
  },
  {
    "path": "modules/azure/security/audit_azure_waf.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_waf\n#\n# Check Azure WAF\n#\n# 7.10 Ensure Azure Web Application Firewall (WAF) is enabled on Azure Application Gateway\n# 7.13 Ensure 'HTTP2' is set to 'Enabled' on Azure Application Gateway\n#\n# Refer to Section(s) 7.10,13 Page(s) 319-21,325-7 CIS Microsoft Azure Foundations Benchmark v5.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_waf () {\n  print_function \"audit_azure_waf\"\n  check_message  \"Azure WAF\"\n  command=\"az network application-gateway list --query '[].resourceGroup' --output tsv 2> /dev/null\"\n  command_message    \"${command}\"\n  res_groups=$( eval \"${command}\" )\n  if [ -z \"${res_groups}\" ]; then\n    info_message \"No WAF instances found\"\n    return\n  fi\n  for res_group in $res_groups; do\n    command=\"az network application-gateway list --resource-group \\\"${res_group}\\\" --query '[].name' --output tsv 2> /dev/null\"\n    command_message  \"${command}\"\n    waf_list=$( eval \"${command}\" )\n    for waf_name in ${waf_list}; do\n      check_azure_waf_value \"\" \"${waf_name}\" \"${res_group}\" \"firewallPolicy.id\" \"ne\" \"\"     \"\"        \"\"\n      check_azure_waf_value \"\" \"${waf_name}\" \"${res_group}\" \"enableHttp2\"       \"eq\" \"true\" \"--http2\" \"Enabled\"\n    done\n  done\n}\n"
  },
  {
    "path": "modules/azure/security/audit_azure_waf_inspection_policy.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_waf_inspection_policy\n#\n# Check Azure WAF Inspection Policy\n#\n# 7.14 Ensure request body inspection is enabled in Azure Web Application Firewall policy on Azure Application Gateway\n# 7.15 Ensure bot protection is enabled in Azure Web Application Firewall policy on Azure Application Gateway - TBD\n#\n# Refer to Section(s) 7.14-15 Page(s) 328-33 CIS Microsoft Azure Foundations Benchmark v5.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_waf_inspection_policy () {\n  print_function \"audit_azure_waf_inspection_policy\"\n  check_message  \"Azure WAF Inspection Policy\"\n  command=\"az network application-gateway list --query '[].resourceGroup' --output tsv 2> /dev/null\"\n  command_message    \"${command}\"\n  res_groups=$( eval \"${command}\" )\n  if [ -z \"${res_groups}\" ]; then\n    verbose_message \"No WAF instances found\" \"info\"\n    return\n  fi\n  for res_group in ${res_groups}; do\n    command=\"az network application-gateway list --resource-group \\\"${res_group}\\\" --query '[].name' --output tsv 2> /dev/null\"\n    command_message  \"${command}\"\n    waf_list=$( eval \"{$command}\" )\n    for waf_name in ${waf_list}; do\n      command=\"az network application-gateway show --resource-group \\\"${res_group}\\\" --name \\\"${waf_name}\\\" --query 'firewallPolicy.id' --output tsv 2> /dev/null\"\n      command_message  \"${command}\"\n      waf_ids=$( eval  \"${command}\" )\n      for waf_id in ${waf_ids}; do\n        check_azure_waf_value \"waf-policy\" \"${waf_id}\" \"\" \"policySettings.requestBodyCheck\" \"eq\" \"true\"                        \"request-body-check\" \"true\"\n        check_azure_waf_value \"waf-policy\" \"${waf_id}\" \"\" \"managedRules.managedRuleSets\"    \"eq\" \"Microsoft_BotManagerRuleSet\" \"\"                   \"\"\n        check_azure_waf_value \"waf-policy\" \"${waf_id}\" \"\" \"managedRules.managedRuleSets\"    \"ne\" \"Disabled\"                    \"\"                   \"\"\n      done\n    done\n  done\n}\n"
  },
  {
    "path": "modules/azure/security/audit_azure_waf_ssl_policy.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_waf_ssl_policy\n#\n# Check Azure WAF SSL Policy\n#\n# 7.12 Ensure the SSL policy's 'Min protocol version' is set to 'TLSv1_2' or higher on Azure Application Gateway\n#\n# Refer to Section(s) 7.12 Page(s) 322-4 CIS Microsoft Azure Foundations Benchmark v5.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_waf_ssl_policy () {\n  print_function \"audit_azure_waf_ssl_policy\"\n  check_message  \"Azure WAF SSL Policy\"\n  command=\"az network application-gateway list --query '[].resourceGroup' --output tsv 2> /dev/null\"\n  command_message    \"${command}\"\n  res_groups=$( eval \"${command}\" )\n  if [ -z \"${res_groups}\" ]; then\n    info_message \"No WAF instances found\"\n    return\n  fi\n  for res_group in ${res_groups}; do\n    command=\"az network application-gateway list --resource-group \\\"${res_group}\\\" --query '[].name' --output tsv 2> /dev/null\"\n    command_message  \"${command}\"\n    waf_list=$( eval \"${command}\" )\n    for waf_name in ${waf_list}; do\n      check_azure_waf_value \"ssl-policy\" \"${waf_name}\" \"${res_group}\" \"firewallPolicy.id\" \"ne\" \"\" \"\" \"\"\n    done\n  done\n}\n"
  },
  {
    "path": "modules/azure/storage/audit_azure_blob_storage.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_blob_storage\n#\n# Check Azure Blob Storage\n#\n# 9.2.1  Ensure that soft delete for blobs on Azure Blob Storage storage accounts is Enabled\n# 9.2.2  Ensure that soft delete for containers on Azure Blob Storage storage accounts is Enabled\n# 9.2.3  Ensure 'Versioning' is set to 'Enabled' on Azure Blob Storage storage accounts\n#\n# Refer to Section(s) 9.2.1-3 Page(s) 485-95 CIS Microsoft Azure Foundations Benchmark v5.0.0\n#\n# 2.1.2.1.1 Ensure Critical Data is Encrypted with Microsoft Managed Keys - Needs verification\n# 11.3      Ensure that soft delete for blobs on Azure Blob Storage storage accounts is Enabled - TBD\n# 11.4      Ensure stored access policies (SAP) are used when generating shared access signature (SAS) tokens - TBD\n# 11.5      Ensure 'Versioning' is set to 'Enabled' on Azure Blob Storage storage accounts\n# 11.6      Ensure locked immutability policies are used for containers storing business-critical blob data \n# 17.5      Ensure that ‘Enable Infrastructure Encryption’ for Each Storage Blob in Azure Storage is Set to ‘enabled’ \n# 17.7      Ensure Soft Delete is Enabled for Azure Containers and Blob Storage\n#\n# Refer to Section(s) 2 Page(s) 25- CIS Microsoft Azure Storage Services Benchmark v1.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_blob_storage () {\n  print_function \"audit_azure_blob_storage\"\n  check_message  \"Azure Blob Storage\"\n  immutability_state=\"Locked\"\n  retention_days=\"7\"\n  command=\"az storage account list --query \\\"[].name\\\" --output tsv\"\n  command_message    \"${command}\"\n  s_accounts=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${s_accounts}\" ]; then\n    info_message \"No Storage Accounts found\"\n    return\n  fi\n  for s_account in ${s_accounts}; do\n    # 9.2.1 Ensure that soft delete for blobs on Azure Blob Storage storage accounts is Enabled\n    # 17.7  Ensure Soft Delete is Enabled for Azure Containers and Blob Storage\n    check_azure_storage_blob_policy_value       \"Soft delete\"   \"${s_account}\"    \"service-properties\" \"delete-policy\"       \"enabled\" \"eq\"   \"true\"                 \"--enable\"\n    check_azure_storage_blob_policy_value       \"Days retained\" \"${s_account}\"    \"service-properties\" \"delete-policy\"       \"days\"    \"eq\"   \"${retention_days}\"    \"--days-retained\"\n    # 9.2.3 Ensure 'Versioning' is set to 'Enabled' on Azure Blob Storage storage accounts\n    # 11.5  Ensure 'Versioning' is set to 'Enabled' on Azure Blob Storage storage accounts\n    check_azure_storage_account_container_value \"Versioning\"    \"${s_account}\" \"\" \"service-properties\" \"isVersioningEnabled\" \"eq\"      \"true\" \"--enable-versioning\"\n    # 9.2.2 Ensure that soft delete for containers on Azure Blob Storage storage accounts is Enabled\n    command=\"az storage account show --name \\\"${s_account}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    if [ \"${azure_auth_mode}\" = \"login\" ]; then\n      command=\"az storage container list --account-name \\\"${s_account}\\\" --query \\\"[].name\\\" --output tsv --auth-mode \\\"${azure_auth_mode}\\\"\"\n      command_message \"${command}\"\n      c_names=$( eval \"${command}\" )\n    else\n      command=\"az storage container list --account-name \\\"${s_account}\\\" --query \\\"[].name\\\" --output tsv\"\n      command_message \"${command}\"\n      c_names=$( eval \"${command}\" )\n    fi\n    for c_name in ${c_names}; do\n      check_azure_storage_account_container_value \"Soft delete\"                \"${s_account}\" \"${res_group}\" \"service-properties\" \"containerDeleteRetentionPolicy.enabled\" \"eq\" \"true\"                     \"--enable-container-delete-retention\"\n      check_azure_storage_account_container_value \"Days retained\"              \"${s_account}\" \"${res_group}\" \"service-properties\" \"containerDeleteRetentionPolicy.days\"    \"eq\" \"${retention_days}\"        \"--container-delete-retention-days\"\n      # 2.1.2.1.1 Ensure Critical Data is Encrypted with Microsoft Managed Keys - Needs verification\n      check_azure_storage_account_container_value \"Data is encrytped with MMK\" \"${s_account}\" \"${res_group}\" \"encryptionScope.defaultEncryptionScope\"                      \"eq\" \"\\$account-encryption-key\"\n      # 11.6      Ensure locked immutability policies are used for containers storing business-critical blob data \n      check_azure_storage_account_container_value \"Immutability policy state\"  \"${s_account}\" \"${res_group}\" \"immutability-policy\" \"immutabilitySettings.state\"            \"eq\" \"${immutability_state}\"    \"--immutability-policy-state\"\n      # 17.5      Ensure that ‘Enable Infrastructure Encryption’ for Each Storage Blob in Azure Storage is Set to ‘enabled’ \n      command=\"az storage blob list --container-name \\\"${c_name}\\\" --account-name \\\"${s_account}\\\" --query \\\"[].name\\\" --output tsv\"\n      command_message    \"${command}\"\n      blob_names=$( eval \"${command}\" )\n      for blob_name in ${blob_names}; do\n        check_azure_storage_blob_value            \"Infrastructure encryption\"  \"${s_account}\" \"${c_name}\"    \"${blob_name}\"        \"properties.serverEncrypted\"            \"eq\" \"Enabled\"\n      done \n    done \n  done\n}\n"
  },
  {
    "path": "modules/azure/storage/audit_azure_data_factory.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_data_factory\n#\n# Check Azure Data Factory\n#\n# 4.1 Ensure Data Factory is encrypted using Customer Managed Keys\n# 4.2 Ensure Data Factory is using Managed Identities - TBD\n# 4.3 Ensure that Data Factory is using Azure Key Vault to store Credentials and Secrets - TBD\n# 4.4 Ensure that Data Factory is using RBAC to manage privilege assignment - TBD\n#\n# Refer to Section(s) 4 Page(s) 73- Microsoft Azure Database Services Benchmark v1.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_data_factory () {\n  print_function \"audit_azure_data_factory\"\n  check_message  \"Azure Data Factory\"\n  command=\"az datafactory list --query \\\"[].name\\\" --output tsv\"\n  command_message       \"${command}\"\n  factory_names=$( eval \"${command}\" )\n  if [ -z \"${factory_names}\" ]; then\n    info_message \"No Data Factory instances found\"\n    return\n  fi\n  for factory_name in ${factory_names}; do\n    command=\"az datafactory show --name \\\"${factory_name}\\\" --query \\\"[].resourceGroup\\\" --output tsv\"\n    command_message        \"${command}\"\n    resource_group=$( eval \"${command}\" )\n    # 4.1 Ensure Data Factory is encrypted using Customer Managed Keys\n    check_data_factory_value   \"Customer-Managed Keys\" \"${factory_name}\" \"${resource_group}\" \"keyVaultKeyUri\"           \"ne\" \"\"                          \"\"\n    # 4.2 Ensure Data Factory is using Managed Identities - TBD\n    check_data_factory_value   \"Managed Identities\"    \"${factory_name}\" \"${resource_group}\" \"identity.type\"            \"eq\" \"${azure_managed_identity}\" \"\"\n    # 4.3 Ensure that Data Factory is using Azure Key Vault to store Credentials and Secrets - TBD\n    check_data_factory_value   \"Using Azure Key Vault\" \"${factory_name}\" \"${resource_group}\" \"properties.type.baseUrl\"  \"ne\" \"\"                          \"\"\n    # 4.4 Ensure that Data Factory is using RBAC to manage privilege assignment - TBD\n    for item in principalName principalId principalType roleDefinitionName scope; do\n      check_data_factory_value \"Using RBAC\"            \"${factory_name}\" \"${resource_group}\" \"[].${item}\"               \"ne\" \"\"                          \"\"\n    done\n  done\n}\n"
  },
  {
    "path": "modules/azure/storage/audit_azure_database_services.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_database_services\n#\n# Check Azure Database Services\n#\n# Refer to Section(s) 4 Page(s) 69 CIS Microsoft Azure Foundations Benchmark v5.0.0\n#\n# Redis\n# 2.1  Ensure 'Microsoft Entra Authentication' is 'Enabled' - TBD\n# 2.2  Ensure that 'Allow access only via SSL' is set to 'Yes'\n# 2.3  Ensure that 'Minimum TLS version' is set to '1.2'\n# 2.4  Ensure that 'Access Policies' are Implemented and Reviewed Periodically - TBD\n# 2.5  Ensure that 'System Assigned Managed Identity' is set to 'On' - TBD\n# 2.6  Ensure that 'Public Network Access' is 'Disabled'\n# 2.7  Ensure Azure Cache for Redis is Using a Private Link\n# 2.8  Ensure that Azure Cache for Redis is Using Customer-Managed Keys\n# 2.9  Ensure 'Access Keys Authentication' is set to 'Disabled'\n# 2.10 Ensure 'Update Channel' is set to 'Stable' \n#\n# Cosmos DB\n# 3.1  Ensure That 'Firewalls & Networks' Is Limited to Use Selected Networks Instead of All Networks\n# 3.2  Ensure that Cosmos DB uses Private Endpoints where possible\n# 3.3  Ensure that 'disableLocalAuth' is set to 'true'\n# 3.4  Ensure `Public Network Access` is `Disabled`\n# 3.5  Ensure critical data is encrypted with customer-managed keys (CMK)\n# 3.6  Ensure the firewall does not allow all network traffic\n# 3.7  Ensure that Cosmos DB Logging is Enabled\n# 3.8  Ensure Data Factory is encrypted using Customer Managed Keys\n#\n# Data Factory\n# 4.1  Ensure Data Factory is encrypted using Customer Managed Keys\n# 4.2  Ensure Data Factory is using Managed Identities - TBD\n# 4.3  Ensure that Data Factory is using Azure Key Vault to store Credentials and Secrets - TBD\n# 4.4  Ensure that Data Factory is using RBAC to manage privilege assignment - TBD\n# 5.2  Ensure Azure Database for MySQL uses only Microsoft Entra Authentication - TBD\n#\n# Azure Database for MySQL\n# 5.1  Ensure Azure Database for MySQL uses Customer Managed Keys for Encryption at Rest - TBD\n# 5.2  Ensure Azure Database for MySQL uses only Microsoft Entra Authentication - TBD\n# 5.3  Ensure `Public Network Access` is `Disabled` for Azure Database for MySQL - TBD\n# 5.4  Ensure Private Endpoints Are Used for Azure MySQL Databases - TBD\n# 5.5  Ensure server parameter 'audit_log_enabled' is set to 'ON' for MySQL flexible server - TBD\n# 5.6  Ensure server parameter 'audit_log_events' has 'CONNECTION' set for MySQL flexible server - TBD\n# 5.7  Ensure server parameter 'error_server_log_file' is Enabled for MySQL Database Server - TBD\n# 5.8  Ensure server parameter 'require_secure_transport' is set to 'ON' for MySQL Server - TBD\n# 5.9  Ensure server parameter 'tls_version' is set to 'TLSv1.2' (or higher) for MySQL flexible server - TBD\n#\n# Azure Database for PostgreSQL\n# 6.1  Ensure Azure Database for PostgreSQL uses Customer Managed Keys for Encryption at Rest - TBD\n# 6.2  Ensure Azure Database for PostgreSQL uses only Microsoft Entra Authentication - TBD\n# 6.3  Ensure `Public Network Access` is `Disabled` for Azure Database for PostgreSQL - TBD\n# 6.4  Ensure Private Endpoints Are Used for Azure PostgreSQL Databases - TBD\n# 6.5  Ensure server parameter 'connection_throttle.enable' is set to 'ON' for PostgreSQL server - TBD\n# 6.6  Ensure server parameter 'logfiles.retention_days' is greater than 3 days for PostgreSQL server - TBD\n# 6.7  Ensure server parameter 'log_checkpoints' is set to 'ON' for PostgreSQL server - TBD\n# 6.8  Ensure server parameter 'log_disconnections' is set to 'ON' for PostgreSQL servers - TBD\n# 6.9  Ensure server parameter 'log_connections' is set to 'ON' for PostgreSQL servers - TBD\n# 6.10 Ensure server parameter 'require_secure_transport' is set to 'ON' for PostgreSQL server - TBD\n# 6.11 Ensure server parameter 'tls_version' is set to 'TLSv1.2' (or higher) for PostgreSQL server - TBD\n#\n# Azure SQL Database\n# 9.1 Ensure that 'Auditing' is set to 'On' - TBD\n# 9.2 Ensure that 'Public Network Access' is set to 'Disable' - TBD\n# 9.3 Ensure no Azure SQL Database firewall rule is overly permissive - TBD\n# 9.4 Ensure SQL server's Transparent Data Encryption (TDE) protector is encrypted with Customer-managed key - TBD\n# 9.5 Ensure that Microsoft Entra authentication is Configured for SQL Servers - TBD\n# 9.6 Ensure that 'Data encryption' is set to 'On' on a SQL Database - TBD\n# 9.7 Ensure that 'Auditing' Retention is 'greater than 90 days' - TBD\n# 9.8 Ensure 'Minimum TLS Version' is set to 'TLS 1.2' or higher - TBD\n#\n# Refer to Section(s) 2- Page(s) 11- Microsoft Azure Database Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_database_services () {\n  print_function \"audit_azure_database_services\"\n  check_message  \"Azure Database Services\"\n  audit_azure_redis_cache\n  audit_azure_cosmos_db\n  audit_azure_data_factory\n  audit_azure_mysql_db\n  audit_azure_postgresql_db\n  audit_azure_sql_db\n}\n"
  },
  {
    "path": "modules/azure/storage/audit_azure_databox.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_databox\n#\n# Check Azure Databox\n#\n# 12.1 Ensure double encryption is used for Azure Data Box in high-security environments - TBD\n#\n# Refer to Sections(s) 12 Page(s) 142-3 Microsoft Azure Storage Services Benchmark v1.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_databox () {\n  print_function  \"audit_azure_databox\"\n  check_message   \"Azure Databox\"\n  command=\"az databox job list --query '[].id' --output tsv 2> /dev/null\"\n  command_message \"${command}\"\n  job_ids=$( eval \"${command}\" )\n  if [ -z \"${job_ids}\" ]; then\n    info_message  \"No Azure Databox job(s) found\"\n    return\n  fi\n  for job_id in ${job_ids}; do\n    command=\"az databox job show --id ${job_id} --query '[].name' --output tsv 2> /dev/null\"\n    command_message   \"${command}\"\n    job_name=$( eval  \"${command}\" )\n    command=\"az databox job show --id ${job_id} --query '[].resourceGroup' --output tsv 2> /dev/null\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    check_azure_databox_value \"Double encryption\" \"${job_name}\" \"${res_group}\" \"DoubleEncryptionEnabled\" \"eq\" \"true\"\n  done\n}\n"
  },
  {
    "path": "modules/azure/storage/audit_azure_databricks.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_databricks\n#\n# Check Azure Databricks workspaces\n#\n# 2.1.1  Ensure that Azure Databricks is deployed in a customer-managed virtual network (VNet)\n# 2.1.2  Ensure that network security groups are configured for Databricks subnets\n# 2.1.3  Ensure that traffic is encrypted between cluster worker nodes\n# 2.1.4  Ensure that users and groups are synced from Microsoft Entra ID to Azure Databricks\n# 2.1.5  Ensure that Unity Catalog is configured for Azure Databricks\n# 2.1.6  Ensure that usage is restricted and expiry is enforced for Databricks personal access tokens\n# 2.1.7  Ensure that diagnostic log delivery is configured for Azure Databricks\n# 2.1.8  Ensure critical data in Azure Databricks is encrypted with customer-managed keys\n# 2.1.9  Ensure 'No Public IP' is set to 'Enabled'\n# 2.1.10 Ensure 'Allow Public Network Access' is set to 'Disabled'\n# 2.1.11 Ensure private endpoints are used to access Azure Databricks workspaces\n#\n# Refer to Section(s) 2.1.1-11 Page(s) 27-62 CIS Microsoft Azure Foundations Benchmark v5.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_databricks () {\n  print_function \"audit_azure_databricks\"\n  check_message  \"Azure Databricks\"\n  command=\"az databricks workspace list --query \\\"[].name\\\" --output tsv\"\n  command_message    \"${command}\"\n  space_list=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${space_list}\" ]; then\n    info_message \"No Databricks workspaces found\"\n    return\n  fi\n  for space_name in ${space_list}; do\n    command=\"az databricks workspace list --query \\\"[?contains(name, '${space_name}')].[resourceGroup]\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    command=\"az databricks workspace list --query \\\"[?contains(name, '${space_name}')].[id]\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_id=$( eval    \"${command}\" )\n    # 2.1.1  Ensure that Azure Databricks is deployed in a customer-managed virtual network (VNet) - TBD\n    # 2.1.2  Ensure that network security groups are configured for Databricks subnets - TBD\n    # 2.1.3  Ensure that traffic is encrypted between cluster worker nodes - TBD\n    # 2.1.4  Ensure that users and groups are synced from Microsoft Entra ID to Azure Databricks - TBD\n    # 2.1.5  Ensure that Unity Catalog is configured for Azure Databricks\n    # 2.1.6  Ensure that usage is restricted and expiry is enforced for Databricks personal access tokens - TBD\n    # 2.1.7  Ensure that diagnostic log delivery is configured for Azure Databricks\n    # 2.1.8  Ensure critical data in Azure Databricks is encrypted with customer-managed keys\n    # 2.1.9  Ensure 'No Public IP' is set to 'Enabled'\n    # 2.1.10 Ensure 'Allow Public Network Access' is set to 'Disabled'\n    # 2.1.11 Ensure private endpoints are used to access Azure Databricks workspaces - Needs check of each endpoint\n    check_azure_monitor_value    \"Diagnostic Log Delivery\"     \"${space_name}\" \"${res_id}\"    \"diagnostic-settings\"               \"\"   \"ne\"                  \"\"                        \"\"\n    check_azure_databricks_value \"Customer Managed Keys\"       \"${space_name}\" \"${res_group}\" \"encryption.keySource\"              \"eq\" \"Microsoft.KeyVault.\" \"\"\n    check_azure_databricks_value \"No Public IP\"                \"${space_name}\" \"${res_group}\" \"parameters.enableNoPublicIp.value\" \"eq\" \"true\"                \"--enable-no-public-ip\"\n    check_azure_databricks_value \"Allow Public Network Access\" \"${space_name}\" \"${res_group}\" \"publicNetworkAccess\"               \"eq\" \"Disabled\"            \"--public-network-access\"\n    check_azure_databricks_value \"Private Endpoints\"           \"${space_name}\" \"${res_group}\" \"privateEndpointConnections\"        \"ne\" \"\"                    \"\"\n  done\n}"
  },
  {
    "path": "modules/azure/storage/audit_azure_elastic_san.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_elastic_san\n#\n# Check Azure Elastic SAN\n#\n# 2.2.1.1 Ensure public network access is Disabled\n# 15.1    Ensure 'Public network access' is set to 'Disabled' on Azure Elastic SAN\n# 15.2    Ensure customer-managed keys (CMK) are used to encrypt data at rest on Azure Elastic SAN volume groups\n#\n# Refer to Section(s) 2 Page(s) 25- CIS Microsoft Azure Storage Services Benchmark v1.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_elastic_san () {\n  print_function  \"audit_azure_elastic_san\"\n  check_message   \"Azure Elastic SAN\"\n  command=\"az elastic-san list --query \\\"[].id\\\" --output tsv\"\n  command_message \"${command}\"\n  san_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${san_ids}\" ]; then\n    info_message  \"No Elastic SANs found\"\n    return\n  fi\n  for san_id in ${san_ids}; do\n    # 2.2.1.1 Ensure public network access is Disabled\n    # 15.1    Ensure 'Public network access' is set to 'Disabled' on Azure Elastic SAN\n    check_azure_elastic_san_value \"Public Network Access\" \"${san_id}\" \"\" \"\" \"\" \"\" \"publicNetworkAccess\" \"eq\" \"Disabled\" \"--public-network-access\" \"\"\n    # 15.2    Ensure customer-managed keys (CMK) are used to encrypt data at rest on Azure Elastic SAN volume groups\n    command=\"az elastic-san show --id \\\"${san_id}\\\" --query \\\"[].resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    command=\"az elastic-san show --id \\\"${san_id}\\\" --query \\\"[].name\\\" --output tsv\"\n    command_message   \"${command}\"\n    san_name=$( eval  \"${command}\" )\n    command=\"az elastic-san volume-group list --resource-group \\\"${res_group}\\\" --elastic-san \\\"${san_name}\\\" --query \\\"[].name\\\" --output tsv\"\n    volume_group_names=$( eval \"${command}\" )\n    for volume_group_name in ${volume_group_names}; do\n      check_azure_elastic_san_value \"Customer Managed Keys\" \"\" \"${san_name}\" \"${res_group}\" \"${volume_group_name}\" \"encryption\" \"eq\" \"EncryptionAtRestWithCustomerManagedKey\" \"\" \"\"\n    done \n  done\n}\n"
  },
  {
    "path": "modules/azure/storage/audit_azure_file_shares.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_file_shares\n#\n# Check Azure File Shares\n#\n# 9.1.1 Ensure soft delete for Azure File Shares is Enabled\n# 9.1.2 Ensure 'SMB protocol version' is set to 'SMB 3.1.1' or higher for SMB file shares\n# 9.1.3 Ensure 'SMB channel encryption' is set to 'AES-256-GCM' or higher for SMB file shares\n#\n# Refer to Section(s) 9.1.1-3 Page(s) 475-84 CIS Microsoft Azure Foundations Benchmark v5.0.0\n#\n# 8.2 Ensure root squash for NFS file shares is configured \n# 8.3 Ensure 'SMB protocol version' is set to 'SMB 3.1.1' or higher for SMB file shares\n# 8.4 Ensure 'SMB channel encryption' is set to 'AES-256-GCM' or higher for SMB file shares\n#\n# Refer to Sections(s) 8 Page(s) 106-19 Microsoft Azure Storage Services Benchmark v1.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_file_shares () {\n  print_function \"audit_azure_file_shares\"\n  check_message  \"Azure File Shares\"\n  command=\"az storage account list --query \\\"[].name\\\" --output tsv\"\n  command_message    \"${command}\"\n  s_accounts=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${s_accounts}\" ]; then\n    info_message \"No Storage Accounts found\"\n    return\n  fi\n  for s_account in ${s_accounts}; do\n    command=\"az storage account show --name \\\"${storage_account}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    # 9.1.1 Ensure soft delete for Azure File Shares is Enabled\n    check_azure_file_share_value \"Days retained\"             \"${s_account}\" \"${res_group}\" \"service-properties\" \"shareDeleteRetentionPolicy.days\"        \"eq\" \"7\"           \"--share-delete-retention-days\"   \"\"\n    check_azure_file_share_value \"Soft Delete\"               \"${s_account}\" \"${res_group}\" \"service-properties\" \"shareDeleteRetentionPolicy.enabled\"     \"eq\" \"true\"        \"--enable-share-delete-retention\" \"\"\n    command=\"az storage account file-service-properties show --name \\\"${s_account}\\\" --resource-group \\\"${res_group}\\\" |grep -i smb\"\n    command_message        \"${command}\"\n    protocol_check=$( eval \"${command}\" )\n    if [ -n \"${protocol_check}\" ]; then\n      # 9.1.2 Ensure 'SMB protocol version' is set to 'SMB 3.1.1' or higher for SMB file shares\n      # 8.3 Ensure 'SMB protocol version' is set to 'SMB 3.1.1' or higher for SMB file shares\n      check_azure_file_share_value \"SMB Protocol Version\"    \"${s_account}\" \"${res_group}\" \"service-properties\" \"protocolSettings.smb.versions\"          \"eq\" \"SMB3.1.1\"    \"--versions\"\n      # 9.1.3 Ensure 'SMB channel encryption' is set to 'AES-256-GCM' or higher for SMB file shares\n      # 8.4   Ensure 'SMB channel encryption' is set to 'AES-256-GCM' or higher for SMB file shares\n      check_azure_file_share_value \"SMB Channel Encryption\"  \"${s_account}\" \"${res_group}\" \"service-properties\" \"protocolSettings.smb.channelEncryption\" \"eq\" \"AES-256-GCM\" \"--channel-encryption\"\n    fi\n    command=\"az storage account file-service-properties show --name \\\"${s_account}\\\" --resource-group \\\"${res_group}\\\" |grep -i nfs\"\n    command_message        \"${command}\"\n    protocol_check=$( eval \"${command}\" )\n    if [ -n \"${protocol_check}\" ]; then\n      # 8.2 Ensure root squash for NFS file shares is configured \n      check_azure_file_share_value \"NFS Root Squash\"         \"${s_account}\" \"${res_group}\" \"service-properties\" \"protocolSettings.nfs.rootSquash\"        \"eq\"  \"RootSquash\"    \"rootSquash\"\n    fi\n  done\n}\n"
  },
  {
    "path": "modules/azure/storage/audit_azure_managed_lustre.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_managed_lustre\n#\n# Check Azure Managed Lustre\n#\n# 4.1 Ensure 'Key encryption key' is set to a customer-managed key for Azure Managed Lustre file systems\n#\n# Refer to Section(s) 4.1 Page(s) 53-6 CIS Microsoft Azure Storage Services Benchmark v1.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_managed_lustre () {\n  print_function \"audit_azure_managed_lustre\"\n  check_message  \"Azure Managed Lustre\"\n  command=\"az storage account list --query \\\"[].name\\\" --output tsv\"\n  command_message    \"${command}\"\n  s_accounts=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${s_accounts}\" ]; then\n    info_message \"No Storage Accounts found\"\n    return\n  fi\n  for s_account in ${s_accounts}; do\n    command=\"az amlfs list --query \\\"[].resourceGroup\\\" --output tsv\"\n    command_message    \"${command}\"\n    res_groups=$( eval \"${command}\" )\n    if [ -z \"${resource_groups}\" ]; then\n      info_message \"No Managed Lustre instances found\"\n      return\n    fi\n    for res_group in ${res_groups}; do\n      command=\"az amlfs list --resource-group \\\"${res_group}\\\" --query \\\"[].name\\\" --output tsv\"\n      command_message      \"${command}\"\n      file_systems=$( eval \"${command}\" )\n      for file_system in ${file_systems}; do\n        # 4.1 Ensure 'Key encryption key' is set to a customer-managed key for Azure Managed Lustre file systems\n        check_azure_storage_fs_value \"Key encryption key name\"      \"${s_account}\" \"${file_system}\" \"encryption.keyEncryptionKeyId.keyName\"     \"ne\" \"\"\n        check_azure_storage_fs_value \"Key encryption key vault uri\" \"${s_account}\" \"${file_system}\" \"encryption.keyEncryptionKeyId.keyVaultUri\" \"ne\" \"\"\n      done\n    done\n  done\n}\n"
  },
  {
    "path": "modules/azure/storage/audit_azure_netapp_files.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_netapp_files\n#\n# Check Azure NetApp Files\n#\n# 10.1 Ensure 'Encryption key source' is set to 'Customer Managed Key' for Azure NetApp Files accounts\n#\n# Refer to Sections(s) 10 Page(s) 120-4 Microsoft Azure Storage Services Benchmark v1.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_netapp_files () {\n  print_function \"audit_azure_netapp_files\"\n  check_message  \"Azure NetApp Files\"\n  command=\"az netappfiles account list --query \\\"[].name\\\" --output tsv\"\n  command_message    \"${command}\"\n  s_accounts=$( eval \"${command}\" )\n  if [ -z \"${s_accounts}\" ]; then\n    info_message \"No NetApp Files instances found\"\n    return\n  fi\n  for s_account in ${s_accounts}; do\n    command=\"az netappfiles account show --name \\\"${s_account}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    # 10.1 Ensure 'Encryption key source' is set to 'Customer Managed Key' for Azure NetApp Files accounts\n    check_azure_netapp_file_value \"Encryption key source\" \"${s_account}\" \"${res_group}\" \"encryptionKeySource\" \"eq\" \"CustomerManagedKey\"\n  done\n}\n"
  },
  {
    "path": "modules/azure/storage/audit_azure_storage_account_locks.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_storage_account_locks\n#\n# Audit Azure Storage Account Locks\n#\n# 17.14 Ensure Azure Resource Manager Delete locks are applied to Azure Storage Accounts\n# 17.15 Ensure Azure Resource Manager Read-only locks are applied to Azure Storage Accounts\n#\n# Refer to Section(s) 17.14-15 Page(s) 224-8 CIS Microsoft Azure Storage Services Benchmark v1.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#\n\naudit_azure_storage_account_locks () {\n  print_function \"audit_azure_storage_account_locks\"\n  check_message  \"Azure Storage Account Locks\"\n  res_type=\"Microsoft.Storage/storageAccounts\"\n  audit_azure_locks \"${res_type}\" \"CanNotDelete\"\n  audit_azure_locks \"${res_type}\" \"ReadOnly\"\n}\n"
  },
  {
    "path": "modules/azure/storage/audit_azure_storage_accounts.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_storage_accounts\n#\n# Check Azure Storage Accounts\n#\n# 9.3.1.1  Ensure that 'Enable key rotation reminders' is enabled for each Storage Account\n# 9.3.1.2  Ensure that Storage Account access keys are periodically regenerated\n# 9.3.1.3  Ensure 'Allow storage account key access' for Azure Storage Accounts is 'Disabled'\n# 9.3.2.1  Ensure Private Endpoints are used to access Storage Accounts\n# 9.3.2.2  Ensure that 'Public Network Access' is 'Disabled' for storage accounts\n# 9.3.2.3  Ensure default network access rule for storage accounts is set to deny\n# 9.3.3.1  Ensure that 'Default to Microsoft Entra authorization in the Azure portal' is set to 'Enabled'\n# 9.3.4    Ensure that 'Secure transfer required' is set to 'Enabled'\n# 9.3.5    Ensure 'Allow Azure services on the trusted services list to access this storage account' is Enabled for Storage Account Access\n# 9.3.6    Ensure the 'Minimum TLS version' for storage accounts is set to 'Version 1.2'\n# 9.3.7    Ensure 'Cross Tenant Replication' is not enabled (Automated)\n# 9.3.8    Ensure that 'Allow Blob Anonymous Access' is set to 'Disabled'\n# 9.3.9    Ensure Azure Resource Manager Delete locks are applied to Azure Storage Accounts\n# 9.3.10   Ensure Azure Resource Manager ReadOnly locks are considered for Azure Storage Accounts\n# 9.3.11   Ensure Redundancy is set to 'geo-redundant storage (GRS)' on critical Azure Storage Accounts\n#\n# Refer to Section(s) 9.3.1-9.3.11 Page(s) 497-549 CIS Microsoft Azure Foundations Benchmark v5.0.0\n#\n# 2.1.1.1  Ensure 'Allowed Protocols' for shared access signature (SAS) tokens is set to 'HTTPS Only'\n# 2.1.1.3  Ensure stored access policies (SAP) are used when generating shared access signature (SAS) tokens - Needs verification\n# 2.2.1.1  Ensure public network access is Disabled\n# 2.2.1.2  Ensure Network Access Rules are set to Deny-by-default\n# 11.1     Ensure 'Allowed Protocols' for shared access signature (SAS) tokens is set to 'HTTPS Only' - TBD\n# 11.2     Ensure that shared access signature (SAS) tokens expire within an hour - TBD\n# 17.1.1   Ensure that 'Enable key rotation reminders' is enabled for each Storage Account\n# 17.1.2   Ensure 'Allowed Protocols' for shared access signature (SAS) tokens is set to 'HTTPS Only'\n# 17.1.3   Ensure that Storage Account Access Keys are Periodically Regenerated\n# 17.1.4   Ensure that shared access signature (SAS) tokens expire within an hour - TBD\n# 17.1.5   Ensure 'Allow storage account key access' for Azure Storage Accounts is 'Disabled'\n# 17.1.6   Ensure Storage for Critical Data are Encrypted with Customer Managed Keys (CMK) - TBD\n# 17.2.1   Ensure Private Endpoints are used to access Storage Accounts\n# 17.2.2   Ensure that 'Public Network Access' is 'Disabled' for storage accounts\n# 17.2.3   Ensure default network access rule for storage accounts is set to deny\n# 17.4     Ensure that 'Secure transfer required' is set to 'Enabled'\n# 17.5     Ensure that ‘Enable Infrastructure Encryption’ for Each Storage Account in Azure Storage is Set to ‘enabled’\n# 17.6     Ensure 'Allow Azure services on the trusted services list to access this storage account' is Enabled for Storage Account Access\n# 17.11    Ensure the 'Minimum TLS version' for storage accounts is set to 'Version 1.2'\n# 17.12    Ensure 'Cross Tenant Replication' is not enabled\n# 17.13    Ensure that 'Allow Blob Anonymous Access' is set to 'Disabled'\n# 17.16    Ensure Redundancy is set to 'geo-redundant storage (GRS)' on critical Azure Storage Accounts\n# 18.1     Ensure that shared access signature (SAS) tokens expire within an hour - TBD\n# 18.2     Ensure that stored access policies (SAP) are used when generating shared access signature (SAS) tokens - TBD\n# 18.3     Ensure Storage Explorer is using the latest version - TBD\n#\n# Refer to Section(s) 2-19 Page(s) 25-240 CIS Microsoft Azure Storage Services Benchmark v1.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_storage_accounts () {\n  print_function \"audit_azure_storage_accounts\"\n  check_message  \"Azure Storage Accounts\"\n  key_rotation=\"90\"  # days\n  sas_expiration=\"1\" # hours\n  command=\"az storage account list --query \\\"[].name\\\" --output tsv\"\n  command_message    \"${command}\"\n  s_accounts=$( eval \"${command}\" )\n  if [ -z \"${s_accounts}\" ]; then\n    info_message \"No Storage Accounts found\"\n    return\n  fi\n  for s_account in ${s_accounts}; do\n    command=\"az storage account show --name \\\"${s_account}\\\" --query \\\"id\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_id=$( eval    \"${command}\" )\n    command=\"az storage account show --name \\\"${s_account}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message   \"${command}\"\n    res_group=$( eval \"${command}\" )\n    # 9.3.1.2  Ensure that Storage Account access keys are periodically regenerated\n    # 17.1.3   Ensure that Storage Account Access Keys are Periodically Regenerated\n    check_azure_storage_account_keys_rotation                                                     \"${s_account}\"  \"${res_id}\"    \"${key_rotation}\"                                  \n    # 9.3.1.1  Ensure that 'Enable key rotation reminders' is enabled for each Storage Account\n    # 17.1.1   Ensure that 'Enable key rotation reminders' is enabled for each Storage Account\n    check_azure_storage_account_value         \"Enable key rotation reminders\"                     \"${s_account}\"  \"${res_group}\" \"keyPolicy.keyExpirationPeriodInDays\" \"eq\" \"${key_rotation}\" \"--key-expiration-period-in-days\"\n    # 9.3.1.3  Ensure 'Allow storage account key access' for Azure Storage Accounts is 'Disabled'\n    # 17.1.5   Ensure 'Allow storage account key access' for Azure Storage Accounts is 'Disabled'\n    check_azure_storage_account_value         \"Allow storage account key access\"                  \"${s_account}\"  \"${res_group}\" \"allowSharedKeyAccess\"                \"eq\" \"false\"           \"--allow-shared-key-access\"\n    # 9.3.2.1  Ensure Private Endpoints are used to access Storage Accounts\n    # 17.2.1   Ensure Private Endpoints are used to access Storage Accounts\n    check_azure_storage_account_value         \"Private Endpoints are used to access\"              \"${s_account}\"  \"${res_group}\" \"privateEndpointConnections[0].id\"    \"ne\" \"\"                \"\"\n    # 9.3.2.2  Ensure that 'Public Network Access' is 'Disabled' for storage accounts\n    # 17.2.2   Ensure that 'Public Network Access' is 'Disabled' for storage accounts\n    # 2.2.1.1  Ensure public network access is Disabled\n    check_azure_storage_account_value         \"Public Network Access\"                             \"${s_account}\"  \"${res_group}\" \"publicNetworkAccess\"                         \"eq\" \"Disabled\"        \"--public-network-access\"\n    # 9.3.2.3  Ensure default network access rule for storage accounts is set to deny\n    # 17.2.3   Ensure default network access rule for storage accounts is set to deny\n    check_azure_storage_account_value         \"Default network access rule\"                       \"${s_account}\"  \"${res_group}\" \"networkRuleSet.defaultAction\"                \"eq\" \"Deny\"            \"--default-action\"\n    # 9.3.3.1  Ensure that 'Default to Microsoft Entra authorization in the Azure portal' is set to 'Enabled' \n    check_azure_storage_account_value         \"Microsoft Entra authorization\"                     \"${s_account}\"  \"${res_group}\" \"defaultToOAuthAuthentication\"                \"eq\" \"true\"            \"defaultToOAuthAuthentication\"\n    # 9.3.4    Ensure that 'Secure transfer required' is set to 'Enabled'\n    check_azure_storage_account_value         \"Secure transfer required\"                          \"${s_account}\"  \"${res_group}\" \"enableHttpsTrafficOnly\"                      \"eq\" \"true\"            \"--https-only\"\n    # 9.3.5    Ensure 'Allow Azure services on the trusted services list to access this storage account' is Enabled for Storage Account Access\n    # 17.6     Ensure 'Allow Azure services on the trusted services list to access this storage account' is Enabled for Storage Account Access\n    check_azure_storage_account_value         \"Azure services on the trusted services list\"       \"${s_account}\"  \"${res_group}\" \"networkRuleSet.bypass\"                       \"eq\" \"AzureServices\"   \"--bypass\"\n    # 9.3.6    Ensure the 'Minimum TLS version' for storage accounts is set to 'Version 1.2'\n    # 17.11    Ensure the 'Minimum TLS version' for storage accounts is set to 'Version 1.2'\n    check_azure_storage_account_value         \"Minimum TLS version\"                               \"${s_account}\"  \"${res_group}\" \"minimumTlsVersion\"                           \"eq\" \"TLS1_2\"          \"--minimum-tls-version\"\n    # 9.3.7    Ensure 'Cross Tenant Replication' is not enabled\n    # 17.12    Ensure 'Cross Tenant Replication' is not enabled\n    check_azure_storage_account_value         \"Cross Tenant Replication\"                          \"${s_account}\"  \"${res_group}\" \"allowCrossTenantReplication\"                 \"eq\" \"false\"           \"--allow-cross-tenant-replication\"\n    # 9.3.8    Ensure 'Allow blob public access' is set to 'Disabled'\n    # 17.13    Ensure that 'Allow Blob Anonymous Access' is set to 'Disabled'\n    check_azure_storage_account_value         \"Allow Blob Public Access\"                          \"${s_account}\"  \"${res_group}\" \"allowBlobPublicAccess\"                       \"eq\" \"false\"           \"allowBlobPublicAccess\"\n    # 9.3.9    Ensure Azure Resource Manager Delete locks are applied to Azure Storage Accounts\n    check_azure_resource_manager_lock         \"Azure Resource Manager Delete locks are applied\"   \"${s_account}\"  \"${res_group}\" \"[].level\"                                    \"eq\" \"CanNotDelete\"    \"Microsoft.Storage/storageAccounts\"\n    # 9.3.10   Ensure Azure Resource Manager ReadOnly locks are applied to Azure Storage Accounts\n    check_azure_resource_manager_lock         \"Azure Resource Manager ReadOnly locks are applied\" \"${s_account}\"  \"${res_group}\" \"[].level\"                                    \"eq\" \"ReadOnly\"        \"Microsoft.Storage/storageAccounts\"\n    # 9.3.11   Ensure Redundancy is set to 'geo-redundant storage (GRS)' on critical Azure Storage Accounts\n    # 17.16    Ensure Redundancy is set to 'geo-redundant storage (GRS)' on critical Azure Storage Accounts\n    check_azure_storage_account_value         \"Redundancy is set to geo-redundant storage (GRS)\"  \"${s_account}\"  \"${res_group}\" \"sku.name\"                                    \"eq\" \"Standard_GRS\"    \"--sku\"\n    # 2.1.1.1  Ensure 'Allowed Protocols' for shared access signature (SAS) tokens is set to 'HTTPS Only'\n    # 17.1.2   Ensure 'Allowed Protocols' for shared access signature (SAS) tokens is set to 'HTTPS Only'\n    check_azure_storage_account_value         \"Allow Shared Key Access\"                           \"${s_account}\"  \"${res_group}\" \"allowSharedKeyAccess\"                        \"eq\" \"false\"           \"\"\n    # 17.4     Ensure that 'Secure transfer required' is set to 'Enabled'\n    check_azure_storage_account_value         \"Allowed Protocols for SAS tokens is HTTPS Only\"    \"${s_account}\"  \"${res_group}\" \"enableHttpsTrafficOnly\"                      \"eq\" \"true\"            \"\"\n    # 2.1.1.3  Ensure stored access policies (SAP) are used when generating shared access signature (SAS) tokens - Need verification\n    check_azure_storage_account_value         \"SAP are used when generating SAS tokens\"           \"${s_account}\"  \"${res_group}\" \"sasPolicy\"                                   \"ne\" \"\"                \"\"\n    # 2.2.1.2  Ensure Network Access Rules are set to Deny-by-default\n    check_azure_storage_account_value         \"Network Access Rules are set to Deny-by-default\"   \"${s_account}\"  \"${res_group}\" \"networkRuleSet.defaultAction\"                \"eq\" \"Deny\"            \" --default-action\"\n    # 17.5     Ensure that ‘Enable Infrastructure Encryption’ for Each Storage Account in Azure Storage is Set to ‘enabled’\n    check_azure_storage_account_value         \"Enable Infrastructure Encryption\"                  \"${s_account}\"  \"${res_group}\" \"encryption.infrastructureEncryption.enabled\" \"eq\" \"true\"            \"infrastructureEncryptionEnabled\"\n  done\n}\n"
  },
  {
    "path": "modules/azure/storage/audit_azure_storage_logging.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_storage_logging\n#\n# Check Azure Storage Logging\n#\n# 17.8  Ensure Storage Logging is Enabled for Queue Service for 'Read', 'Write', and 'Delete' requests\n# 17.9  Ensure Storage Logging is Enabled for Blob  Service for 'Read', 'Write', and 'Delete' requests\n# 17.10 Ensure Storage Logging is Enabled for Table Service for 'Read', 'Write', and 'Delete' Requests\n#\n# Refer to Section(s) 17.8 Page(s) 205-13 Microsoft Azure Storage Services Benchmark v1.0.0\n#\n# Refer to CIS Microsoft Azure Compute Services Benchmark\n#.\n\naudit_azure_storage_logging () {\n  print_function \"audit_azure_storage_logging\"\n  check_message  \"Azure Storage Logging\"\n  retention_days=\"90\"\n  log_value=\"rwd\"\n  command=\"az storage account list --query \\\"[].name\\\" --output tsv\"\n  command_message    \"${command}\"\n  s_accounts=$( eval \"${command}\" )\n  if [ -z \"${s_accounts}\" ]; then\n    info_message \"No Storage Accounts found\"\n    return\n  fi\n  for s_account in ${s_accounts}; do\n    # 17.8  Ensure Storage Logging is Enabled for Queue Service for 'Read', 'Write', and 'Delete' requests\n    # 17.9  Ensure Storage Logging is Enabled for Blob  Service for 'Read', 'Write', and 'Delete' requests\n    # 17.10 Ensure Storage Logging is Enabled for Table Service for 'Read', 'Write', and 'Delete' Requests\n    for service_type in queue blob table; do\n      for request_type in read write delete; do\n        check_azure_storage_logging_value \"Storage Logging\" \"${s_account}\" \"${service_type}\" \"[].${service_type}.${request_type}\"      \"eq\" \"true\"              \"\"\n      done\n      check_azure_storage_logging_value   \"Storage Logging\" \"${s_account}\" \"${service_type}\" \"[].${service_type}.retentionPolicy.days\" \"eq\" \"${retention_days}\" \"${log_value}\"\n    done\n  done\n}\n"
  },
  {
    "path": "modules/azure/storage/audit_azure_storage_services.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_storage_services\n#\n# Check Azure Storage Services\n#\n# 9.1.1     Ensure soft delete for Azure File Shares is Enabled\n# 9.1.2     Ensure 'SMB protocol version' is set to 'SMB 3.1.1' or higher for SMB file shares\n# 9.1.3     Ensure 'SMB channel encryption' is set to 'AES-256-GCM' or higher for SMB file shares\n# 9.2.1     Ensure that soft delete for blobs on Azure Blob Storage storage accounts is Enabled\n# 9.2.2     Ensure that soft delete for containers on Azure Blob Storage storage accounts is Enabled\n# 9.2.3     Ensure 'Versioning' is set to 'Enabled' on Azure Blob Storage storage accounts\n# 9.3.1.1   Ensure that 'Enable key rotation reminders' is enabled for each Storage Account\n# 9.3.1.2   Ensure that Storage Account access keys are periodically regenerated\n# 9.3.1.3   Ensure 'Allow storage account key access' for Azure Storage Accounts is 'Disabled'\n# 9.3.2.1   Ensure Private Endpoints are used to access Storage Accounts\n# 9.3.2.2   Ensure that 'Public Network Access' is 'Disabled' for storage accounts\n# 9.3.2.3   Ensure default network access rule for storage accounts is set to deny\n# 9.3.3.1   Ensure that 'Default to Microsoft Entra authorization in the Azure portal' is set to 'Enabled'\n# 9.3.4     Ensure that 'Secure transfer required' is set to 'Enabled'\n# 9.3.5     Ensure 'Allow Azure services on the trusted services list to access this storage account' is Enabled for Storage Account Access\n# 9.3.6     Ensure the 'Minimum TLS version' for storage accounts is set to 'Version 1.2'\n# 9.3.7     Ensure 'Cross Tenant Replication' is not enabled (Automated)\n# 9.3.8     Ensure that 'Allow Blob Anonymous Access' is set to 'Disabled'\n# 9.3.9     Ensure Azure Resource Manager Delete locks are applied to Azure Storage Accounts\n# 9.3.10    Ensure Azure Resource Manager ReadOnly locks are considered for Azure Storage Accounts\n# 9.3.11    Ensure Redundancy is set to 'geo-redundant storage (GRS)' on critical Azure Storage Accounts\n#\n# Refer to Section(s) 9 Page(s) 473-549 CIS Microsoft Azure Foundations Benchmark v5.0.0\n#\n# Secrets and Keys\n# Shared Access Signatures\n# 2.1.1.1   Ensure 'Allowed Protocols' for shared access signature (SAS) tokens is set to 'HTTPS Only'\n# 2.1.1.2   Ensure that shared access signature (SAS) tokens expire within an hour - TBD\n# 2.1.1.3   Ensure stored access policies (SAP) are used when generating shared access signature (SAS) tokens - Needs verification\n# 2.1.2.1.1 Ensure Critical Data is Encrypted with Microsoft Managed Keys - Needs verification\n# 2.1.2.2.1 Ensure Critical Data is Encrypted with Customer Managed Keys - TBD\n# 2.2.1.1   Ensure public network access is Disabled\n# Azure Managed Lustre\n# 4.1.1     Ensure 'Key encryption key' is set to a customer-managed key for Azure Managed Lustre file systems\n# 5.1.1     Ensure soft delete on Backup vaults is Enabled\n# Azure Backup\n# Backup Vaults\n# 5.1.2     Ensure immutability for Backup vaults is Enabled\n# 5.1.3     Ensure backup data in Backup vaults is encrypted using customer-managed keys (CMK)\n# 5.1.4     Ensure 'Use infrastructure encryption for this vault' is enabled on Backup vaults\n# 5.1.5     Ensure 'Cross Region Restore' is set to 'Enabled' on Backup vaults\n# 5.1.6     Ensure 'Cross Subscription Restore' is set to 'Disabled' or 'Permanently Disabled' on Backup vaults\n# 5.2.1     Ensure soft delete on Recovery Services vaults is Enabled\n# Recovery Services Vaults\n# 5.2.2     Ensure immutability for Recovery Services vaults is Enabled\n# 5.2.3     Ensure backup data in Recovery Services vaults is encrypted using customer-managed keys (CMK)\n# 5.2.4     Ensure 'Use infrastructure encryption for this vault' is enabled on Recovery Services vaults\n# 5.2.5     Ensure public network access on Recovery Services vaults is Disabled\n# 5.2.6     Ensure 'Cross Region Restore' is set to 'Enabled' on Recovery Services vaults\n# 5.2.7     Ensure 'Cross Subscription Restore' is set to 'Disabled' or 'Permanently Disabled' on Recovery Services vaults\n# Azure Files\n# 8.1       Ensure soft delete for Azure File Shares is Enabled\n# 8.2       Ensure root squash for NFS file shares is configured\n# 8.3       Ensure 'SMB protocol version' is set to 'SMB 3.1.1' or higher for SMB file shares\n# 8.4       Ensure 'SMB channel encryption' is set to 'AES-256-GCM' or higher for SMB file shares\n# Azure NetApp Files\n# 10.1      Ensure 'Encryption key source' is set to 'Customer Managed Key' for Azure NetApp Files accounts\n# Azure Blob Storage\n# 11.1      Ensure 'Allowed Protocols' for shared access signature (SAS) tokens is set to 'HTTPS Only'\n# 11.2      Ensure that shared access signature (SAS) tokens expire within an hour - TBD\n# 11.3      Ensure that soft delete for blobs on Azure Blob Storage storage accounts is Enabled\n# 11.4      Ensure stored access policies (SAP) are used when generating shared access signature (SAS) tokens - TBD\n# 11.5      Ensure 'Versioning' is set to 'Enabled' on Azure Blob Storage storage accounts\n# 11.6      Ensure locked immutability policies are used for containers storing business-critical blob data \n# Azure Data Box\n# 12.1      Ensure double encryption is used for Azure Data Box in high-security environments - TBD\n# Azure Elastic SAN\n# 15.1      Ensure 'Public network access' is set to 'Disabled' on Azure Elastic SAN\n# 15.2      Ensure customer-managed keys (CMK) are used to encrypt data at rest on Azure Elastic SAN volume groups\n# Queue Storage\n# 16.1      Ensure 'Allowed Protocols' for shared access signature (SAS) tokens is set to 'HTTPS Only' - TBD\n# 16.2      Ensure that shared access signature (SAS) tokens expire within an hour - TBD\n# 16.3      Ensure stored access policies (SAP) are used when generating shared access signature (SAS) tokens - TBD\n# Storage Accounts\n# Secrets and Keys\n# 17.1.1    Ensure that 'Enable key rotation reminders' is enabled for each Storage Account\n# 17.1.2    Ensure 'Allowed Protocols' for shared access signature (SAS) tokens is set to 'HTTPS Only'\n# 17.1.3    Ensure that Storage Account Access Keys are Periodically Regenerated\n# 17.1.4    Ensure that shared access signature (SAS) tokens expire within an hour\n# 17.1.5    Ensure 'Allow storage account key access' for Azure Storage Accounts is 'Disabled'\n# 17.1.6    Ensure Storage for Critical Data are Encrypted with Customer Managed Keys (CMK)\n# Networking\n# 17.2.1    Ensure Private Endpoints are used to access Storage Accounts\n# 17.2.2    Ensure that 'Public Network Access' is 'Disabled' for storage accounts\n# 17.2.3    Ensure default network access rule for storage accounts is set to deny\n# Identity and Access Management\n# 17.4      Ensure that 'Secure transfer required' is set to 'Enabled'\n# 17.5      Ensure that ‘Enable Infrastructure Encryption’ for Each Storage Account in Azure Storage is Set to ‘enabled’\n# 17.8      Ensure Storage Logging is Enabled for Queue Service for 'Read', 'Write', and 'Delete' requests\n# 17.9      Ensure Storage Logging is Enabled for Blob Service for 'Read', 'Write', and 'Delete' requests\n# 17.10     Ensure Storage Logging is Enabled for Table Service for 'Read', 'Write', and 'Delete' Requests\n# 17.11     Ensure the 'Minimum TLS version' for storage accounts is set to 'Version 1.2'\n# 17.12     Ensure 'Cross Tenant Replication' is not enabled\n# 17.13     Ensure that 'Allow Blob Anonymous Access' is set to 'Disabled'\n# 17.14     Ensure Azure Resource Manager Delete locks are applied to Azure Storage Accounts\n# 17.15     Ensure Azure Resource Manager Read-only locks are applied to Azure Storage Accounts\n#\n# Refer to Sections(s) 2 Page(s) 25- Microsoft Azure Storage Services Benchmark v1.0.0\n#\n# Refer to CIS Microsoft Azure Compute Services Benchmark\n#.\n\naudit_azure_storage_services () {\n  print_function \"audit_azure_storage_services\"\n  check_message  \"Azure Storage Services\"\n  audit_azure_databricks\n  audit_azure_blob_storage\n  audit_azure_file_shares\n  audit_azure_storage_accounts\n  audit_azure_recovery_services_vaults\n  audit_azure_managed_lustre\n  audit_azure_backup_vaults\n  audit_azure_netapp_files\n  audit_azure_databox\n  audit_azure_elastic_san\n  audit_azure_storage_logging\n  audit_azure_storage_accounts_locks\n}\n"
  },
  {
    "path": "modules/azure/vaults/audit_azure_backup_vaults.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_backup_vaults\n#\n# Check Azure Backup Vaults\n#\n# 5.1.1 Ensure soft delete on Backup vaults is Enabled\n# 5.1.2 Ensure immutability for Backup vaults is Enabled\n# 5.1.3 Ensure backup data in Backup vaults is encrypted using customer-managed keys (CMK)\n# 5.1.4 Ensure 'Use infrastructure encryption for this vault' is enabled on Backup vaults\n# 5.1.5 Ensure 'Cross Region Restore' is set to 'Enabled' on Backup vaults\n# 5.1.6 Ensure 'Cross Subscription Restore' is set to 'Disabled' or 'Permanently Disabled' on Backup vaults\n#\n# Refer to Section(s) 2 Page(s) 25- CIS Microsoft Azure Storage Services Benchmark v1.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_backup_vaults () {\n  print_function \"audit_azure_backup_vaults\"\n  check_message  \"Azure Backup Vaults\"\n  immutability_state=\"Locked\"\n  retention_days=\"90\"\n  command=\"az dataprotection backup-vault list --query \\\"[].id\\\" --output tsv\"\n  command_message   \"${command}\"\n  vault_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${vault_ids}\" ]; then\n    info_message \"No Backup Vaults found\"\n    return\n  fi\n  for vault_id in ${vault_ids}; do\n    command=\"az dataprotection backup-vault show --id \\\"${vault_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message    \"${command}\"\n    res_group=$( eval  \"${command}\" )\n    command=\"az dataprotection backup-vault show --id \\\"${vault_id}\\\" --query \\\"name\\\" --output tsv\"\n    command_message    \"${command}\"\n    vault_name=$( eval \"${command}\" )\n    # 5.1.1 Ensure soft delete on Backup vaults is Enabled\n    check_azure_backup_vault_value    \"Soft Delete\"                     \"${vault_name}\"  \"${res_group}\"                 \"properties.encryption.keyUri\"                 \"ne\" \"\"                      \"\"\n    # 5.1.3 Ensure backup data in Backup vaults is encrypted using customer-managed keys (CMK)\n    check_azure_backup_vault_value    \"Customer Managed Keys\"           \"${vault_name}\"  \"${res_group}\"                 \"properties.softDeleteFeatureState\"            \"eq\" \"Enabled\"               \"properties.softDeleteFeatureState\"\n    # 5.1.4 Ensure 'Use infrastructure encryption for this vault' is enabled on Backup vaults\n    check_azure_backup_vault_value    \"Infrastructure Encryption\"       \"${vault_name}\"  \"${res_group}\"                 \"properties.infrastructureEncryptionEnabled\"   \"eq\" \"true\"                  \"--infrastructure-encryption-enabled\"\n    # 5.1.5 Ensure 'Cross Region Restore' is set to 'Enabled' on Backup vaults\n    check_azure_backup_vault_value    \"Cross Region Restore\"            \"${vault_name}\"  \"${res_group}\"                 \"properties.crossRegionRestoreFlag\"            \"eq\" \"Enabled\"               \"properties.crossRegionRestoreFlag\"\n    # 5.1.6 Ensure 'Cross Subscription Restore' is set to 'Disabled' or 'Permanently Disabled' on Backup vaults\n    check_azure_backup_vault_value    \"Cross Subscription Restore\"      \"${vault_name}\"  \"${res_group}\"                 \"properties.crossSubscriptionRestoreFlag\"      \"eq\" \"Disabled\"              \"properties.crossSubscriptionRestoreFlag\"\n    # 5.1.2 Ensure immutability for Backup vaults is Enabled\n    command=\"az backup policy list --vault-name \\\"${vault_name}\\\" --resource-group \\\"${res_group}\\\" --query \\\"[].name\\\" --output tsv\"\n    command_message      \"${command}\"\n    policy_names=$( eval \"${command}\" )\n    for policy_name in ${policy_names}; do\n      check_azure_backup_policy_value \"Immutability Settings\"           \"${policy_name}\" \"${vault_name}\" \"${res_group}\" \"immutabilitySettings\"                         \"ne\" \"\"                      \"\"\n      check_azure_backup_policy_value \"Immutability State\"              \"${policy_name}\" \"${vault_name}\" \"${res_group}\" \"immutabilitySettings.state\"                   \"eq\" \"${immutability_state}\" \"--immutability-state\"\n      check_azure_backup_policy_value \"Immutability Retention Duration\" \"${policy_name}\" \"${vault_name}\" \"${res_group}\" \"immutabilitySettings.retentionDurationInDays\" \"eq\" \"${retention_days}\"     \"--retention-days\"\n    done\n  done\n}\n"
  },
  {
    "path": "modules/azure/vaults/audit_azure_key_vault_certificates.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_key_vault_certificates\n#\n# Check Azure Key Vault Certificates\n#\n# 2.5 Ensure Azure Key Vaults are Used to Store Secrets\n#\n# Refer to Section(s) 2.5 Page(s) 238-42 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n# Audit account needs to have the 'Key Vault Reader' role\n# To do any changes to the key vaults, the 'Key Vault Administrator' role is required\n#.\n\naudit_azure_key_vault_certificates () {\n  print_function \"audit_azure_key_vault_certificates\"\n  check_message  \"Azure Key Vault Certificates\"\n  command=\"az keyvault list --query \\\"[].id\\\" --output tsv\"\n  command_message    \"${command}\"\n  key_vaults=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${key_vaults}\" ]; then\n    insecure_message \"No Key Vault Certificates found\"\n  else\n    secure_message   \"Key Vault Certificates found\"\n  fi\n}\n"
  },
  {
    "path": "modules/azure/vaults/audit_azure_key_vault_keys.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_key_vault_keys\n#\n# Check Azure Key Vault Keys\n#\n# 8.3.1 Ensure that the Expiration Date is set for all Keys in RBAC Key Vaults\n# 8.3.2 Ensure that the Expiration Date is set for all Keys in Non-RBAC Key Vaults\n# 8.3.3 Ensure that the Expiration Date is set for all Secrets in RBAC Key Vaults\n# 8.3.4 Ensure that the Expiration Date is set for all Secrets in Non-RBAC Key Vaults\n# 8.3.9 Ensure automatic key rotation is enabled within Azure Key Vault\n#\n# Refer to Section(s) 8.3.1-4,9 Page(s) 425-39,456-9 CIS Microsoft Azure Foundations Benchmark v5.0.0\n#\n# Azure and NIST recommend that keys be rotated every two years or less. Refer to\n# 'Table 1: Suggested cryptoperiods for key types' on page 46 of the following document\n# for more information:\n# https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-57pt1r5.pdf\n#\n# This requires the Azure CLI to be installed and configured\n# Audit account needs to have the 'Key Vault Reader' role\n# To do any changes to the key vaults, the 'Key Vault Administrator' role is required\n#.\n\naudit_azure_key_vault_keys () {\n  print_function \"audit_azure_key_vault_keys\"\n  check_message  \"Azure Key Vault Keys\"\n  command=\"az keyvault list --query \\\"[].name\\\" --output tsv\"\n  command_message    \"${command}\"\n  key_vaults=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${key_vaults}\" ]; then\n    info_message \"No Key Vaults found\"\n    return\n  fi\n  for key_vault in ${key_vaults}; do\n    command=\"az keyvault key list --vault-name \\\"${key_vault}\\\" --query \\\"[].name\\\" --output tsv\"\n    command_message  \"${command}\"\n    key_list=$( eval \"${command}\" )\n    for key_name in ${key_list}; do\n      check_azure_key_vault_key_value \"${key_vault}\" \"${key_name}\" \"attributes.enabled\"     \"eq\" \"true\" \"\"                \"\"\n      check_azure_key_vault_key_value \"${key_vault}\" \"${key_name}\" \"attributes.expired\"     \"ne\" \"\"     \"\"                \"\"\n      check_azure_key_vault_key_value \"${key_vault}\" \"${key_name}\" \"\"                       \"ne\" \"\"     \"rotation-policy\" \"Notify\"\n      check_azure_key_vault_key_value \"${key_vault}\" \"${key_name}\" \"timeAfterCreate\"        \"ne\" \"\"     \"rotation-policy\" \"Notify\"\n      check_azure_key_vault_key_value \"${key_vault}\" \"${key_name}\" \"\"                       \"ne\" \"\"     \"rotation-policy\" \"Rotate\"\n      check_azure_key_vault_key_value \"${key_vault}\" \"${key_name}\" \"timeAfterCreate\"        \"ne\" \"\"     \"rotation-policy\" \"Rotate\"\n    done\n  done\n}\n"
  },
  {
    "path": "modules/azure/vaults/audit_azure_key_vault_logging.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_key_vault_logging\n#\n# Check Azure Key Vault Logging\n#\n# 6.1.1.4  Ensure that logging for Azure Key Vault is 'Enabled'\n#\n# Refer to Section(s) 6.1.1.4 Page(s) 207-10 CIS Microsoft Azure Foundations Benchmark v5.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_key_vault_logging () {\n  print_function \"audit_azure_key_vault_logging\"\n  check_message  \"Azure Key Vault Logging\"\n  command=\"az keyvault list --query \\\"[].id\\\" --output tsv 2>/dev/null\"\n  command_message   \"${command}\"\n  vault_ids=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${vault_ids}\" ]; then\n    info_message \"No Key Vaults found\"\n    return\n  fi\n  for vault_id in ${vault_ids}; do\n    command=\"az monitor diagnostic-settings list --resource \\\"${vault_id}\\\" --query \\\"[].name\\\" --output tsv 2>/dev/null\"\n    command_message   \"${command}\"\n    res_names=$( eval \"${command}\" )\n    for res_name in ${res_names}; do\n      command=\"az monitor diagnostic-settings show --resource \\\"${vault_id}\\\" --name \\\"${res_name}\\\" --query \\\"logs\\\" --output tsv 2>/dev/null\"\n      command_message \"${command}\"\n      az monitor diagnostic-settings show --resource \"${vault_id}\" --name \"${res_name}\" --query \"logs\" --output tsv 2>/dev/null |\n      while read -r line; do\n        category=$( echo \"${line}\" | awk '{print $1}' )\n        enabled=$(  echo \"${line}\" | awk '{print $2}' )\n        if [ \"${enabled}\" = \"True\" ]; then\n          inc_secure   \"Key Vault \\\"${res_name}\\\" logging enabled for \\\"${category}\\\"\"\n        else\n          inc_insecure \"Key Vault \\\"${res_name}\\\" logging disabled for \\\"${category}\\\"\"\n        fi\n      done\n    done\n  done\n}\n"
  },
  {
    "path": "modules/azure/vaults/audit_azure_key_vault_private_endpoints.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_key_vault_private_endpoints\n#\n# Check Azure Key Vault Private Endpoints\n#\n# 8.3.7 Ensure Public Network Access is Disabled\n#\n# Refer to Section(s) 8.3.7 Page(s) 447-50 CIS Microsoft Azure Foundations Benchmark v5.0.0\n#\n# This requires the Azure CLI to be installed and configured\n# Audit account needs to have the 'Key Vault Reader' role\n# To do any changes to the key vaults, the 'Key Vault Administrator' role is required\n#.\n\naudit_azure_key_vault_private_endpoints () {\n  print_function \"audit_azure_key_vault_private_endpoints\"\n  check_message  \"Azure Key Vault Private Endpoints\"\n  command=\"az resource list --query \\\"[?type=='Microsoft.KeyVault/vaults'].name\\\" --output tsv\"\n  command_message   \"${command}\"\n  res_names=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${res_names}\" ]; then\n    info_message \"No Key Vaults found\"\n    return\n  fi\n  for res_name in ${res_names}; do\n    command=\"az resource list --name \\\"${res_name}\\\" --query \\\"[].resourceGroup\\\" --output tsv\"\n    command_message    \"${command}\"\n    res_groups=$( eval \"${command}\" )\n    for res_group in ${res_groups}; do\n      check_azure_key_vault_value \"${res_name}\" \"${res_group}\" \"properties.privateEndpointConnections\" \"ne\" \"\" \"\"\n    done\n  done\n}\n"
  },
  {
    "path": "modules/azure/vaults/audit_azure_key_vault_public_network_access.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_key_vault_public_network_access\n#\n# Check Azure Key Vault Public Network Access\n#\n# 8.3.7 Ensure Public Network Access is Disabled\n#\n# Refer to Section(s) 8.3.7 Page(s) 447-50 CIS Microsoft Azure Foundations Benchmark v5.0.0\n#\n# This requires the Azure CLI to be installed and configured\n# Audit account needs to have the 'Key Vault Reader' role\n# To do any changes to the key vaults, the 'Key Vault Administrator' role is required\n#.\n\naudit_azure_key_vault_public_network_access () {\n  print_function \"audit_azure_key_vault_public_network_access\"\n  check_message  \"Azure Key Vault Public Network Access\"\n  command=\"az resource list --query \\\"[?type=='Microsoft.KeyVault/vaults'].name\\\" --output tsv\"\n  command_message   \"${command}\"\n  res_names=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${res_names}\" ]; then\n    info_message \"No Key Vaults found\"\n    return\n  fi\n  for res_name in ${res_names}; do\n    command=\"az resource list --name \\\"${res_name}\\\" --query \\\"[].resourceGroup\\\" --output tsv\"\n    command_message    \"${command}\"\n    res_groups=$( eval \"${command}\" )\n    for res_group in ${res_groups}; do\n      check_azure_key_vault_value \"${res_name}\" \"${res_group}\" \"properties.publicNetworkAccess\" \"eq\" \"Disabled\" \"--public-network-access\"\n    done\n  done\n}\n"
  },
  {
    "path": "modules/azure/vaults/audit_azure_key_vault_purge_protection.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_key_vault_purge_protection\n#\n# Check Azure Key Vault Purge Protection\n#\n# 8.3.5 Ensure that Purge Protection is enabled for all Key Vaults\n#\n# Refer to Section(s) 8.3.5 Page(s) 440-3 CIS Microsoft Azure Foundations Benchmark v5.0.0\n#\n# This requires the Azure CLI to be installed and configured\n# Audit account needs to have the 'Key Vault Reader' role\n# To do any changes to the key vaults, the 'Key Vault Administrator' role is required\n#.\n\naudit_azure_key_vault_purge_protection () {\n  print_function \"audit_azure_key_vault_purge_protection\"\n  check_message  \"Azure Key Vault Purge Protection\"\n  command=\"az resource list --query \\\"[?type=='Microsoft.KeyVault/vaults'].name\\\" --output tsv\"\n  command_message   \"${command}\"\n  res_names=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${res_names}\" ]; then\n    info_message \"No Key Vaults found\"\n    return\n  fi\n  for res_name in ${res_names}; do\n    command=\"az resource list --name \\\"${res_name}\\\" --query \\\"[].resourceGroup\\\" --output tsv\"\n    command_message    \"${command}\"\n    res_groups=$( eval \"${command}\" )\n    for res_group in ${res_groups}; do\n      command=\"az resource show --resource-group \\\"${res_group}\\\" --name \\\"${res_name}\\\" --resource-type \\\"Microsoft.KeyVault/vaults\\\" --query \\\"properties.enablePurgeProtection\\\" --output tsv\"\n      command_message    \"${command}\"\n      protection=$( eval \"${command}\" )\n      check_message \"Azure Key Vault \\\"${res_name}\\\" purge protection\"\n      if [ \"${protection}\" = \"true\" ]; then\n        inc_secure       \"Azure Key Vault \\\"${res_name}\\\" purge protection is enabled\"\n      else\n        inc_insecure     \"Azure Key Vault \\\"${res_name}\\\" purge protection is not enabled\"\n        verbose_message  \"az resource update --resource-group ${res_group} --name ${res_name} --resource-type \\\"Microsoft.KeyVault/vaults\\\" --set properties.enablePurgeProtection=true\" \"fix\"\n      fi\n    done\n  done\n}\n"
  },
  {
    "path": "modules/azure/vaults/audit_azure_key_vault_rbac.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_key_vault_rbac\n#\n# Check Azure Key Vault RBAC\n#\n# 8.3.5 Ensure that Purge Protection is enabled for all Key Vaults\n#\n# Refer to Section(s) 8.3.5 Page(s) 440-3 CIS Microsoft Azure Foundations Benchmark v5.0.0\n#\n# This requires the Azure CLI to be installed and configured\n# Audit account needs to have the 'Key Vault Reader' role\n# To do any changes to the key vaults, the 'Key Vault Administrator' role is required\n#.\n\naudit_azure_key_vault_rbac () {\n  print_function \"audit_azure_key_vault_rbac\"\n  check_message  \"Azure Key Vault RBAC\"\n  command=\"az resource list --query \\\"[?type=='Microsoft.KeyVault/vaults'].name\\\" --output tsv\"\n  command_message   \"${command}\"\n  res_names=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${res_names}\" ]; then\n    info_message \"No Key Vaults found\"\n    return\n  fi\n  for res_name in ${res_names}; do\n    command=\"az resource list --name \\\"${res_name}\\\" --query \\\"[].resourceGroup\\\" --output tsv\"\n    command_message    \"${command}\"\n    res_groups=$( eval \"${command}\" )\n    for res_group in ${res_groups}; do\n      check_azure_key_vault_value \"${res_name}\" \"${res_group}\" \"properties.enableRbacAuthorization\" \"eq\" \"true\" \"--enable-rbac-authorization\"\n    done\n  done\n}"
  },
  {
    "path": "modules/azure/vaults/audit_azure_key_vault_secrets.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_key_vault_secrets\n#\n# Check Azure Key Vault Secrets\n#\n# 2.5 Ensure Azure Key Vaults are Used to Store Secrets\n#\n# Refer to Section(s) 2.5 Page(s) 238-42 CIS Microsoft Azure Compute Services Benchmark v2.0.0\n#\n# This requires the Azure CLI to be installed and configured\n# Audit account needs to have the 'Key Vault Reader' role\n# To do any changes to the key vaults, the 'Key Vault Administrator' role is required\n#.\n\naudit_azure_key_vault_secrets () {\n  print_function \"audit_azure_key_vault_secrets\"\n  check_message  \"Azure Key Vault Secrets\"\n  command=\"az keyvault list --query \\\"[].id\\\" --output tsv\"\n  command_message    \"${command}\"\n  key_vaults=$( eval \"${command}\" 2> /dev/null )\n  if [ -z \"${key_vaults}\" ]; then\n    insecure_message \"No Key Vault Secrets found\"\n  else\n    secure_message   \"Key Vault Secrets found\"\n  fi\n}\n"
  },
  {
    "path": "modules/azure/vaults/audit_azure_recovery_services_vaults.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_azure_recovery_services_vaults\n#\n# Check Azure Recovery Services Vaults\n#\n# 5.2.1 Ensure soft delete on Recovery Services vaults is Enabled\n# 5.2.2 Ensure immutability for Recovery Services vaults is Enabled\n# 5.2.3 Ensure backup data in Recovery Services vaults is encrypted using customer-managed keys (CMK)\n# 5.2.4 Ensure 'Use infrastructure encryption for this vault' is enabled on Recovery Services vaults\n# 5.2.5 Ensure public network access on Recovery Services vaults is Disabled\n# 5.2.6 Ensure 'Cross Region Restore' is set to 'Enabled' on Recovery Services vaults\n# 5.2.7 Ensure 'Cross Subscription Restore' is set to 'Disabled' or 'Permanently Disabled' on Recovery Services vaults\n#\n# Refer to Section(s) 2 Page(s) 25- CIS Microsoft Azure Storage Services Benchmark v1.0.0\n#\n# This requires the Azure CLI to be installed and configured\n#.\n\naudit_azure_recovery_services_vaults () {\n  print_function \"audit_azure_recovery_services_vaults\"\n  check_message  \"Azure Recovery Services Vaults\"\n  immutability_state=\"Locked\"\n  retention_days=\"90\"\n  command=\"az backup vault list --query \\\"[].id\\\" --output tsv\"\n  command_message   \"${command}\"\n  vault_ids=$( eval \"${command}\" )\n  if [ -z \"${vault_ids}\" ]; then\n    info_message \"No Recovery Services Vaults found\"\n    return\n  fi\n  for vault_id in ${vault_ids}; do\n    command=\"az backup vault show --id \\\"${vault_id}\\\" --query \\\"resourceGroup\\\" --output tsv\"\n    command_message    \"${command}\"\n    res_group=$( eval  \"${command}\" )\n    command=\"az backup vault show --id \\\"${vault_id}\\\" --query \\\"name\\\" --output tsv\"\n    command_message    \"${command}\"\n    vault_name=$( eval \"${command}\" )\n    # 5.2.1 Ensure soft delete on Recovery Services vaults is Enabled\n    check_azure_backup_vault_value \"Soft Delete\"                \"${vault_name}\" \"${res_group}\" \"properties.encryption.keyUri\"               \"ne\" \"\"         \"\"\n    # 5.2.3 Ensure backup data in Recovery Services vaults is encrypted using customer-managed keys (CMK)  \n    check_azure_backup_vault_value \"Customer Managed Keys\"      \"${vault_name}\" \"${res_group}\" \"properties.softDeleteFeatureState\"          \"eq\" \"Enabled\"  \"properties.softDeleteFeatureState\"\n    # 5.2.4 Ensure 'Use infrastructure encryption for this vault' is enabled on Recovery Services vaults\n    check_azure_backup_vault_value \"Infrastructure Encryption\"  \"${vault_name}\" \"${res_group}\" \"properties.infrastructureEncryptionEnabled\" \"eq\" \"true\"     \"--infrastructure-encryption-enabled\"\n    # 5.2.6 Ensure 'Cross Region Restore' is set to 'Enabled' on Recovery Services vaults\n    check_azure_backup_vault_value \"Cross Region Restore\"       \"${vault_name}\" \"${res_group}\" \"properties.crossRegionRestoreFlag\"          \"eq\" \"Enabled\"  \"properties.crossRegionRestoreFlag\"\n    # 5.2.7 Ensure 'Cross Subscription Restore' is set to 'Disabled' or 'Permanently Disabled' on Recovery Services vaults \n    check_azure_backup_vault_value \"Cross Subscription Restore\" \"${vault_name}\" \"${res_group}\" \"properties.crossSubscriptionRestoreFlag\"    \"eq\" \"Disabled\" \"properties.crossSubscriptionRestoreFlag\"\n    # 5.2.5 Ensure public network access on Recovery Services vaults is Disabled\n    check_azure_backup_vault_value \"Public Network Access\"      \"${vault_name}\" \"${res_group}\" \"properties.publicNetworkAccess\"             \"eq\" \"Disabled\" \"properties.publicNetworkAccess\"\n    # 5.2.2 Ensure immutability for Recovery Services vaults is Enabled\n    command=\"az backup policy list --vault-name \\\"${vault_name}\\\" --resource-group \\\"${res_group}\\\" --query \\\"[].name\\\" --output tsv\"\n    command_message      \"${command}\"\n    policy_names=$( eval \"${command}\" )\n    for policy_name in ${policy_names}; do\n      check_azure_backup_policy_value \"Immutability Settings\"           \"${policy_name}\" \"${vault_name}\" \"${res_group}\" \"immutabilitySettings\"                         \"ne\" \"\"                      \"\"\n      check_azure_backup_policy_value \"Immutability State\"              \"${policy_name}\" \"${vault_name}\" \"${res_group}\" \"immutabilitySettings.state\"                   \"eq\" \"${immutability_state}\" \"--immutability-state\"\n      check_azure_backup_policy_value \"Immutability Retention Duration\" \"${policy_name}\" \"${vault_name}\" \"${res_group}\" \"immutabilitySettings.retentionDurationInDays\" \"eq\" \"${retention_days}\"     \"--retention-days\"\n    done\n  done\n}\n"
  },
  {
    "path": "modules/bluetooth/audit_bluetooth.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_bluetooth\n#\n# Check bluetooth\n#\n# Refer to Section(s) 2.1.1           Page(s) 8-11        CIS Apple OS X 10.8 Benchmark v1.0.0\n# Refer to Section(s) 2.1.1-3         Page(s) 21-5        CIS Apple OS X 10.12 Benchmark v1.0.0\n# Refer to Section(s) 2.3.3.11,2.4.4  Page(s) 118-20,37-9 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n# Refer to Section(s) 3.1.3           Page(s) 361-3       CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_bluetooth () {\n  print_function \"audit_bluetooth\"\n  string=\"Bluetooth services and file sharing\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    check_osx_defaults_int  \"/Library/Preferences/com.apple.Bluetooth\" \"ControllerPowerState\"      \"0\"\n    check_osx_defaults_int  \"/Library/Preferences/com.apple.Bluetooth\" \"PANServices\"               \"0\"\n    check_osx_defaults_bool \"/Library/Preferences/com.apple.Bluetooth\" \"BluetoothSystemWakeEnable\" \"0\"\n    backup_file=\"bluetooth_discover\"\n    if [ \"${audit_mode}\" != 2 ]; then\n      if [ \"${os_version}\" -ge 14 ]; then\n        command=\"find /Users -maxdepth 1 -type d |grep -vE \\\"localized|Shared\\\" |cut -f3 -d/\"\n        command_message   \"${command}\"\n        user_list=$( eval \"${command}\" )\n        for user_name in ${user_list}; do\n          check_osx_defaults_user \"com.apple.Bluetooth\"           \"PrefKeyServicesEnabled\" \"0\"  \"bool\" \"${user_name}\"\n          check_osx_defaults_user \"com.apple.controlcenter.plist\" \"Bluetooth\"              \"18\" \"int\"  \"${user_name}\"\n        done\n      fi\n      command=\"system_profiler SPBluetoothDataType | grep -i power | cut -f2 -d: | sed \\\"s/ //g\\\"\"\n      command_message  \"${command}\"\n      bt_check=$( eval \"${command}\" )\n      if [ ! \"${bt_check}\" = \"Off\" ]; then\n        command=\"system_profiler SPBluetoothDataType | grep -i discoverable | cut -f2 -d: | sed \\\"s/ //g\\\"\"\n        command_message  \"${command}\"\n        bt_check=$( eval \"${command}\" )\n        if [ \"${bt_check}\" = \"Off\" ]; then\n          inc_secure     \"Bluetooth is not discoverable\"\n        else\n          inc_insecure   \"Bluetooth is discoverable\"\n        fi\n      else\n        inc_secure       \"Bluetooth is turned off\"\n      fi\n      command=\"defaults read com.apple.systemuiserver menuExtras 2>&1 |grep Bluetooth.menu |sed \\\"s/[ ,\\\\\\\",\\\\\\,]//g\\\"\"\n      command_message \"${command}\"\n      defaults_check=$( eval \"${command}\" )\n      if [ \"${defaults_check}\" = \"/System/Library/CoreServices/MenuExtras/Bluetooth.menu\" ]; then\n        inc_secure   \"Bluetooth status menu is enabled\"\n      else\n        inc_insecure \"Bluetooth status menu is not enabled\"\n      fi\n    fi\n  else\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      check_linux_service \"bluez\"     \"off\"\n      check_linux_package \"uninstall\" \"bluez\"\n    else\n      na_message \"${string}\"\n    fi\n  fi\n}\n"
  },
  {
    "path": "modules/boot/audit_boot_server.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_boot_server\n#\n# Turn off boot services\n#.\n\naudit_boot_server () {\n  print_function \"audit_boot_server\"\n  audit_rarp\n  audit_bootparams\n  audit_tftp_server\n  audit_dhcp_server\n}\n"
  },
  {
    "path": "modules/boot/audit_bootparams.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_bootparams\n#\n# Turn off bootparamd\n#.\n\naudit_bootparams () {\n  print_function \"audit_bootparams\"\n  string=\"Bootparams Daemon\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      if [ \"${os_version}\" -gt 9 ]; then\n        check_sunos_service \"svc:/network/rpc/bootparams:default\" \"disabled\"\n      fi\n    fi\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      check_linux_service   \"bootparamd\" \"off\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/boot/audit_grub_security.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_grub_security\n#\n# Check GRUB security\n#\n# Refer to Section(s) 1.5.3   Page(s) 47-8  CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 1.4.1   Page(s) 57    CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 1.4.1   Page(s) 52    CIS Ubuntu 16.04 Benchmark v1.0.0\n# Refer to Section(s) 1.4.1-2 Page(s) 160-4 CIS Ubuntu 24.04 Benchmark v1.0.0\n# Refer to Section(s) 3.1     Page(s) 31-2  CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 1.4.1   Page(s) 50    CIS Amazon Linux Benchmark v2.0.0\n#.\n\naudit_grub_security () {\n  print_function \"audit_grub_security\"\n  string=\"Grub Menu Security\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${my_id}\" != \"0\" ] && [ \"${use_sudo}\" = \"0\" ]; then\n      notice_message \"Requires sudo to check\"\n      return\n    fi\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      for check_file in /etc/grub.conf /boot/grub/grub.cfg /boot/grub/menu.list; do\n        check_file_perms    \"${check_file}\"       \"0600\" \"root\"     \"root\"\n      done\n      check_file_value \"is\" \"/boot/grub/grub.cfg\" \"set superusers\"  \"eq\"      \"root\"  \"hash\"\n      check_file_value \"is\" \"/boot/grub/grub.cfg\" \"password_pbkdf2\" \"space\"   \"root\"  \"hash\"\n      check_file_value \"is\" \"/boot/grub/grub.cfg\" \"selinux\"         \"eq\"      \"1\"     \"hash\"\n      check_file_value \"is\" \"/boot/grub/grub.cfg\" \"enforcing\"       \"eq\"      \"1\"     \"hash\"\n      check_file_value \"is\" \"/etc/default/grub\"   \"audit\"           \"eq\"      \"1\"     \"hash\"\n    fi\n#  if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n#    check_file=\"/boot/grub/menu.lst\"\n#    grub_check=`cat ${check_file} |grep \"^password --md5\" |awk '{print $1}'`\n#    if [ \"$grub_check\" != \"password\" ]; then\n#      if [ \"${audit_mode}\" = 1 ]; then\n#        inc_insecure \"Grub password not set\"\n#      fi\n#      This code needs work\n#      if [ \"${audit_mode}\" = 0 ]; then\n#        echo \"Setting:   Grub password\"\n#        if [ ! -f \"${log_file}\" ]; then\n#          echo \"Saving:    File ${check_file} to ${log_file}\"\n#          find ${check_file} | cpio -pdm ${work_dir} 2> /dev/null\n#        fi\n#        echo -n \"Enter password: \"\n#        read $password_string\n#        password_string=`htpasswd -nb test $password_string |cut -f2 -d:`\n#        echo \"password --md5 $password_string\" >> ${check_file}\n#        chmod 600 ${check_file}\n#        lock_check=`cat ${check_file} |grep lock`\n#        if [ \"$lock_check\" != \"lock\" ]; then\n#          cat ${check_file} |sed 's,Solaris failsafe,Solaris failsafe Lock,g' >> ${temp_file}\n#          cp ${temp_file} ${check_file}\n#          rm ${temp_file}\n#        fi\n#      fi\n#    else\n#      if [ \"${audit_mode}\" = 1 ]; then\n#        inc_secure \"Set-UID not restricted on user mounted devices\"\n#      fi\n#      if [ \"${audit_mode}\" = 2 ]; then\n#        restore_file=\"${restore_dir}${check_file}\"\n#        if [ -f \"${restore_file}\" ]; then\n#          echo \"Restoring:  ${restore_file} to ${check_file}\"\n#          cp -p ${restore_file} ${check_file}\n#          if [ \"${os_version}\" = \"10\" ]; then\n#            pkgchk -f -n -p ${check_file} 2> /dev/null\n#          else\n#            pkg fix `pkg search ${check_file} |grep pkg |awk '{print $4}'`\n#          fi\n#        fi\n#      fi\n#    fi\n#  fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/core/audit_core_dumps.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n# shellcheck disable=SC2043\n\n# audit_core_dumps\n#\n# Check core dumps\n#\n# Refer to Section(s) 1.6.1 Page(s) 44-5  CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 1.6.1 Page(s) 50-1  CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 1.5.1 Page(s) 47    CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 1.4.1 Page(s) 57    CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 4.1   Page(s) 35-6  CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 1.5.1 Page(s) 56-7  CIS Ubuntu 16.04 Benchmark v1.0.0\n# Refer to Section(s) 1.5.3 Page(s) 175-8 CIS Ubuntu 24.04 Benchmark v1.0.0\n# Refer to Section(s) 4.1   Page(s) 16    CIS FreeBSD Benchmark v1.0.5\n# Refer to Section(s) 3.1   Page(s) 25-6  CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 3.2   Page(s) 61-2  CIS Solaris 10 Benchmark v5.1.0\n# Refer to Section(s) 1.5.1 Page(s) 53    CIS Amazon Linux Benchmark v2.0.0\n#.\n\naudit_core_dumps () {\n  print_function \"audit_core_dumps\"\n  string=\"Core Dumps\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"FreeBSD\" ]; then\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      if [ \"${os_version}\" != \"6\" ]; then\n        cores_dir=\"/var/cores\"\n        check_file=\"/etc/coreadm.conf\"\n        command=\"coreadm | head -1 | awk '{print \\$5}' | grep \\\"/var/cores\\\"\"\n        command_message     \"${command}\"\n        cores_check=$( eval \"${command}\" )\n        if [ -z \"${cores_check}\" ]; then\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_insecure \"Cores are not restricted to a private directory\"\n          else\n            if [ \"${audit_mode}\" = 0 ]; then\n              verbose_message \"Making sure restricted to a private directory\" \"set\"\n              if [ -f \"${check_file}\" ]; then\n                verbose_message \"File \\\"${check_file}\\\" to \\\"${work_dir}${check_file}\\\"\" \"save\"\n                find  \"${check_file}\" | cpio -pdm \"${work_dir}\" 2> /dev/null\n              else\n                touch \"${check_file}\"\n                find  \"${check_file}\" | cpio -pdm \"${work_dir}\" 2> /dev/null\n                if [ -f \"${check_file}\" ]; then\n                  rm \"${check_file}\"\n                fi\n                log_file=\"${work_dir}/${check_file}\"\n                coreadm | sed -e 's/^ *//g' | sed 's/ /_/g' | sed 's/:_/:/g' | awk -F: '{ print $1\" \"$2 }' | while read -r option value; do\n                  if [ \"$option\" = \"global_core_file_pattern\" ]; then\n                    echo \"COREADM_GLOB_PATTERN=${value}\" >  \"${log_file}\"\n                  fi\n                  if [ \"$option\" = \"global_core_file_content\" ]; then\n                    echo \"COREADM_GLOB_CONTENT=${value}\" >> \"${log_file}\"\n                  fi\n                  if [ \"$option\" = \"init_core_file_pattern\" ]; then\n                    echo \"COREADM_INIT_PATTERN=${value}\" >> \"${log_file}\"\n                  fi\n                  if [ \"$option\" = \"init_core_file_content\" ]; then\n                    echo \"COREADM_INIT_CONTENT=${value}\" >> \"${log_file}\"\n                  fi\n                  if [ \"$option\" = \"global_core_dumps\" ]; then\n                    if [ \"${value}\" = \"enabled\" ]; then\n                      value=\"yes\"\n                    else\n                      value=\"no\"\n                    fi\n                    echo \"COREADM_GLOB_ENABLED=${value}\" >> \"${log_file}\"\n                  fi\n                  if [ \"$option\" = \"per-process_core_dumps\" ]; then\n                    if [ \"${value}\" = \"enabled\" ]; then\n                      value=\"yes\"\n                    else\n                      value=\"no\"\n                    fi\n                    echo \"COREADM_PROC_ENABLED=${value}\" >> \"${log_file}\"\n                  fi\n                  if [ \"$option\" = \"global_setid_core_dumps\" ]; then\n                    if [ \"${value}\" = \"enabled\" ]; then\n                      value=\"yes\"\n                    else\n                      value=\"no\"\n                    fi\n                    echo \"COREADM_GLOB_SETID_ENABLED=${value}\" >> \"${log_file}\"\n                  fi\n                  if [ \"$option\" = \"per-process_setid_core_dumps\" ]; then\n                    if [ \"${value}\" = \"enabled\" ]; then\n                      value=\"yes\"\n                    else\n                      value=\"no\"\n                    fi\n                    echo \"COREADM_PROC_SETID_ENABLED=${value}\" >> \"${log_file}\"\n                  fi\n                  if [ \"$option\" = \"global_core_dump_logging\" ]; then\n                    if [ \"${value}\" = \"enabled\" ]; then\n                      value=\"yes\"\n                    else\n                      value=\"no\"\n                    fi\n                    echo \"COREADM_GLOB_LOG_ENABLED=${value}\" >> \"${log_file}\"\n                  fi\n                done\n              fi\n              coreadm -g /var/cores/core_%n_%f_%u_%g_%t_%p -e log -e global -e global-setid -d process -d proc-setid\n            fi\n            if [ ! -d \"${cores_dir}\" ]; then\n              mkdir \"${cores_dir}\"\n              chmod 700 \"${cores_dir}\"\n              chown root:root \"${cores_dir}\"\n            fi\n          fi\n        else\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_secure \"Cores are restricted to a private directory\"\n          fi\n        fi\n        if [ \"${audit_mode}\" = 2 ]; then\n          restore_file=\"${restore_dir}${check_file}\"\n          restore_file \"${check_file}\" \"${restore_dir}\"\n          if [ -f \"${restore_file}\" ]; then\n            coreadm -u\n          fi\n        fi\n      fi\n    fi\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      check_message       \"Core Dumps\"\n      check_linux_service \"kdump\"      \"off\"\n      check_append_file                \"/etc/security/limits.conf\" \"* hard core 0\"              \"hash\"\n      check_file_value    \"is\"         \"/etc/sysctl.conf\"          \"fs.suid_dumpable\" \"eq\"  \"0\" \"hash\"\n    fi\n    if [ \"${os_name}\" = \"FreeBSD\" ]; then\n      check_file_value    \"is\"         \"/etc/sysctl.conf\"          \"kern.coredump\"    \"eq\"  \"0\" \"hash\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/core/audit_core_limit.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_core_limit\n#\n# Check core dump limits\n#\n# Refer to Section(s) 2.10 Page(s) 34-35 CIS Apple OS X 10.8 Benchmark v1.0.0\n#.\n\naudit_core_limit () {\n  print_function \"audit_core_limit\"\n  string=\"Core dump limits\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    log_file=\"corelimit\"\n    backup_file=\"${work_dir}/${log_file}\"\n    current_value=$( launchctl limit core | awk '{print $3}' )\n    if [ \"${audit_mode}\" != 2 ]; then\n      if [ \"${ansible_mode}\" = 1 ]; then\n        ansible_counter=$((ansible_counter+1))\n        ansible_value=\"audit_core_limit_${ansible_counter}\"\n        echo \"\"\n        echo \"- name: Checking ${string}\"\n        echo \"  command:  sh -c \\\"launchctl limit core | awk '{print \\$3}'\\\"\"\n        echo \"  register: ${ansible_value}\"\n        echo \"  failed_when: ${ansible_value} == 1\"\n        echo \"  changed_when: false\"\n        echo \"  ignore_errors: true\"\n        echo \"  when: ansible_facts['ansible_system'] == '${os_name}'\"\n        echo \"\"\n        echo \"- name: Fixing ${string}\"\n        echo \"  command: sh -c \\\"launchctl limit core 0\\\"\"\n        echo \"  when: ${ansible_value}.rc == 1 and ansible_facts['ansible_system'] == '${os_name}'\"\n        echo \"\"\n      fi\n      if [ \"${current_value}\" != \"0\" ]; then\n        if [ ! \"${audit_mode}\" = 0 ]; then\n          inc_insecure \"Core dumps unlimited\"\n          fix_message  \"launchctl limit core 0\"\n        fi\n        if [ \"${audit_mode}\" = 0 ]; then\n          set_message \"Core dump limits\"\n          echo \"${current_value}\" > \"${log_file}\"\n          launchctl limit core 0\n        fi\n      else\n        if [ \"${audit_mode}\" = 1 ]; then\n          inc_secure \"Core dump limits exist\"\n        fi\n      fi\n    else\n      restore_file=\"${restore_dir}/${log_file}\"\n      if [ -f \"${restore_file}\" ]; then\n        previous_value=$( cat \"${restore_file}\" )\n        if [ \"${current_value}\" != \"${previous_value}\" ]; then\n          restore_message \"Core limit to \\\"${previous_value}\\\"\"\n          launchctl limit core unlimited\n        fi\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/core/audit_core_storage.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n# shellcheck disable=SC2196\n\n# audit_core_storage\n#\n# Ensure all user core storage volumes are encrypted\n#\n# Refer to Section(s) 5.3.2 Page(s) 339-42 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_core_storage () {\n  print_function \"audit_core_storage\"\n  string=\"Core Storage Volumes\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${long_os_version}\" -ge 1014 ]; then\n      if [ \"${audit_mode}\" != 2 ]; then\n        command=\"diskutil cs list | egrep -v \\\"Snapshot|Not Mounted|Sealed|Capacity\\\" | grep -A1 \\\"/\\\" | grep -v \\\"\\-\\\" | sed \\\"s/\\|//g\\\" | sed \\\"s/ //g\\\" | grep -B1 \\\"FileVault:No\\\" | grep \\\"MountPoint\\\" | cut -f2 -d:\"\n        command_message       \"${command}\"\n        insecure_vols=$( eval \"${command}\" )\n        for volume in ${insecure_vols}; do\n          inc_insecure \"Core Storage Volume \\\"${volume}\\\" is not encrypted\"\n        done\n        command=\"diskutil cs list | egrep -v \\\"Snapshot|Not Mounted|Sealed|Capacity\\\" | grep -A1 \\\"/\\\" | grep -v \\\"\\-\\\" | sed \\\"s/\\|//g\\\" | sed \\\"s/ //g\\\" | grep -B1 \\\"FileVault:Yes\\\" | grep \\\"MountPoint\\\" | cut -f2 -d:\"\n        command_message     \"${command}\"\n        secure_vols=$( eval \"${command}\" )\n        for volume in ${secure_vols}; do\n          inc_secure \"Core Storage Volume \\\"${volume}\\\" is encrypted\"\n        done\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/cron/audit_cron.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_cron\n#\n# Check cron\n#\n# Refer to Section(s) 6.1.1   Page(s) 138-9   CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 6.1.1   Page(s) 121-2   CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 9.1.1   Page(s) 114-5   CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 5.1.1   Page(s) 192     CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 5.1.1   Page(s) 204     CIS Ubuntu 16.04 Benchmark v1.0.0\n# Refer to Section(s) 2.4.1.1 Page(s) 329-30  CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_cron () {\n  print_function \"audit_cron\"\n  string=\"Cron Daemon\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    check_linux_service   \"crond\"   \"on\"\n    if [ \"${anacron_enable}\" = \"yes\" ]; then\n      check_linux_service \"anacron\" \"on\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/cron/audit_cron_allow.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_cron_allow\n#\n# Check cron allow\n#\n# Refer to Section(s) 6.1.10-1            Page(s) 125-7       CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 6.1.10-1            Page(s) 128-30      CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 6.1.10-1            Page(s) 145-7       CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 9.1.8               Page(s) 120         CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 7.4                 Page(s) 25          CIS FreeBSD Benchmark v1.0.5\n# Refer to Section(s) 2.11.8-10,2.12.13-4 Page(s) 196-8,217-8 CIS AIX Benchmark v1.1.0\n# Refer to Section(s) 6.13                Page(s) 56-7        CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 6.9                 Page(s) 93-4        CIS Solaris 10 Benchmark v5.1.0\n# Refer to Section(s) 2.4.1.8-2.1         Page(s) 343-51      CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_cron_allow () {\n  print_function \"audit_cron_allow\"\n  string=\"At/Cron Authorized Users\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"FreeBSD\" ] || [ \"${os_name}\" = \"AIX\" ]; then\n    if [ \"${os_name}\" = \"FreeBSD\" ]; then\n      cron_base_dir=\"/var/cron\"\n      at_base_dir=\"/var/at\"\n      cron_group=\"${wheel_group}\"\n      check_file=\"/etc/crontab\"\n      check_file_perms \"${check_file}\" \"0640\" \"root\" \"${cron_group}\"\n    else\n      if [ \"${os_name}\" = \"AIX\" ]; then\n        cron_base_dir=\"/var/adm/cron\"\n        at_base_dir=\"/var/adm/cron\"\n        cron_group=\"cron\"\n      else\n        if [ \"${os_name}\" = \"SunOS\" ] && [ \"${os_version}\" = \"11\" ] || [ \"${os_name}\" = \"Linux\" ]; then\n          cron_base_dir=\"/etc/cron.d\"\n          at_base_dir=\"/etc/cron.d\"\n          cron_group=\"root\"\n        else\n          cron_base_dir=\"/etc\"\n          at_base_dir=\"/etc\"\n          cron_group=\"root\"\n        fi\n      fi\n    fi\n    check_file_exists \"${cron_base_dir}/cron.deny\"  \"no\"\n    check_file_exists \"${at_base_dir}/at.deny\"      \"no\"\n    check_file_exists \"${cron_base_dir}/cron.allow\" \"yes\"\n    check_file_perms  \"${cron_base_dir}/cron.allow\" \"0400\" \"root\" \"${cron_group}\"\n    check_file_exists \"${at_base_dir}/at.allow\"     \"yes\"\n    check_file_perms  \"${at_base_dir}/at.allow\"     \"0400\" \"root\" \"${cron_group}\"\n    if [ \"${audit_mode}\" = 0 ]; then\n      for dir_name in var/spool/cron var/spool/cron/crontabs ; do\n        if [ -d \"${dir_name}\" ]; then\n          command=\"find \\\"${dir_name}\\\" -maxdepth 1 -type f -exec basename {} \\;\"\n          command_message   \"${command}\"\n          user_list=$( eval \"${command}\" )\n          for user_name in ${user_list}; do\n            command=\"grep \\\"^${user_name}\\\" < /etc/passwd | cut -f 1 -d:\"\n            command_message  \"${command}\"\n            check_id=$( eval \"${command}\" )\n            if [ \"${check_id}\" = \"${user_name}\" ]; then\n              echo \"${user_name}\" >> \"${cron_file}\"\n              echo \"${user_name}\" >> \"${at_file}\"\n            fi\n          done\n        fi\n      done\n      for dir_name in /etc/cron.d /etc/cron.hourly /etc/cron.daily /etc/cron.yearly; do\n        if [ -d \"${dir_name}\" ]; then\n          command=\"find \\\"${dir_name}\\\" -type f -not -user root -printf '%u\\n' | sort -u\"\n          command_message   \"${command}\"\n          user_list=$( eval \"${command}\" )\n          for user_name in ${user_list}; do\n            command=\"grep \\\"${user_name}\\\" \\\"${check_file}\\\"\"\n            command_message    \"${command}\"\n            user_check=$( eval \"${command}\" )\n            if [ \"${user_check}\" != \"${user_name}\" ]; then\n              echo \"${user_name}\" >> \"${at_base_dir}/at.allow\"\n              echo \"${user_name}\" >> \"${cron_base_dir}/cron.allow\"    \n            fi\n          done\n        fi\n      done\n    fi\n    check_file_perms  \"${check_file}\" \"0640\" \"root\" \"root\"\n    check_file=\"/etc/at.allow\"\n    check_file_exists \"${check_file}\" \"yes\"\n    if [ \"${audit_mode}\" = 0 ]; then\n      if [ \"${os_name}\" = \"SunOS\" ]; then\n        f_check=$( wc -l \"${check_file}\" | awk '{print $1}' | sed \"s/ //g\" )\n        if [ \"$f_check\" = \"0\" ]; then\n          dir_name=\"/var/spool/cron/atjobs\"\n          if [ -d \"${dir_name}\" ]; then\n            command=\"ls ${dir_name}\"\n            command_message   \"${command}\"\n            user_list=$( eval \"${command}\" )\n            for user_name in ${user_list}; do\n              command=\"grep \\\"${user_name}\\\" \\\"${check_file}\\\"\"\n              command_message    \"${command}\"\n              user_check=$( eval \"${command}\" )\n              if [ \"${user_check}\" != \"${user_name}\" ]; then\n                echo \"${user_name}\" >> \"${check_file}\"\n              fi\n            done\n          fi\n        fi\n      fi\n      if [ \"${os_name}\" = \"Linux\" ]; then\n        f_check=$( wc -l \"${check_file}\" | awk '{ print $1 }' | sed \"s/ //g\" )\n        if [ \"$f_check\" = \"0\" ]; then\n          dir_name=\"/var/spool/at/spool\"\n          if [ -d \"${dir_name}\" ]; then\n            command=\"ls /var/spool/at/spool\"\n            command_message   \"${command}\"\n            user_list=$( eval \"${command}\" )\n            for user_name in ${user_list}; do\n              command=\"grep \\\"${user_name}\\\" \\\"${check_file}\\\"\"\n              command_message    \"${command}\"\n              user_check=$( eval \"${command}\" )\n              if [ \"${user_check}\" != \"${user_name}\" ]; then\n                echo \"${user_name}\" >> \"${check_file}\"\n              fi\n            done\n          fi\n        fi\n      fi\n    fi\n    command=\"check_file_perms \\\"${check_file}\\\" \\\"0640\\\" \\\"root\\\" \\\"root\\\"\"\n    command_message \"${command}\"\n    eval \"${command}\"\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      for dir_name in /etc/cron.d /etc/cron.hourly /etc/cron.daily /etc/cron.yearly; do\n        command=\"check_file_perms \\\"${dir_name}\\\" \\\"0700\\\" \\\"root\\\" \\\"root\\\"\"\n        command_message \"${command}\"\n        eval \"${command}\"\n      done\n      for file_name in /etc/crontab /etc/anacrontab /etc/cron.allow /etc/at.allow; do\n        check_file_perms \"${check_file}\"  \"0600\" \"root\" \"root\"\n      done\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/cron/audit_cron_logging.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_cron_logging\n#\n# Check cron logging\n#\n# Refer to Section(s) 4.7 Page(s) 71 CIS Solaris 10 Benchmark v5.1.0\n#.\n\naudit_cron_logging () {\n  print_function \"audit_cron_logging\"\n  string=\"Cron Logging\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ]; then\n      check_file_value  \"is\" \"/etc/default/cron\" \"CRONLOG\" \"eq\"   \"YES\"  \"hash\"\n      check_file_perms       \"/var/cron/log\"     \"0640\"    \"root\" \"root\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/cron/audit_cron_perms.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_cron_perms\n#\n# Check cron permissions\n#\n# Refer to Section(s) 6.1.2-9   Page(s) 119-125 CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 6.1.2-9   Page(s) 138-9   CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 6.1.2-9   Page(s) 122-8   CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 5.1.2-9   Page(s) 210-7   CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 9.1.2-8   Page(s) 115-9   CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 5.1.2-9   Page(s) 193-200 CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 5.1.2-8   Page(s) 205-12  CIS Ubuntu 16.04 Benchmark v1.0.0\n# Refer to Section(s) 2.4.1.2-7 Page(s) 331-42  CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_cron_perms () {\n  print_function \"audit_cron_perms\"\n  string=\"Cron Permissions\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    for check_file in /etc/crontab /var/spool/cron /etc/cron.daily /etc/cron.d \\\n    /etc/cron.weekly /etc/cron.monthly /etc/cron.hourly /etc/anacrontab; do\n        check_file_perms \"${check_file}\" \"0700\" \"root\" \"root\"\n    done\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_account_lockout.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_account_lockout\n#\n# Check Account Lockout\n#\n# Refer to Section(s) 5.18 Page(s) 66-67 CIS Apple OS X 10.8 Benchmark v1.0.0\n#.\n\naudit_account_lockout () {\n  print_function \"audit_account_lockout\"\n  string=\"Account Lockout\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    check_pwpolicy \"maxFailedLoginAttempts\" \"3\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_account_switching.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_account_switching\n#\n# Disabling the administrator's and/or user's ability to log into another user's active and\n# locked session prevents unauthorized persons from viewing potentially sensitive and/or\n# personal information.\n#\n# Refer to Section(s) 5.7 Page(s) 350-1 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_account_switching () {\n  print_function \"audit_account_switching\"\n  string=\"Administrator Account Login to Another User Session\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${long_os_version}\" -ge 1014 ]; then\n      ansible_counter=$((ansible_counter+1))\n      ansible_value=\"audit_account_switching_${ansible_counter}\"\n      if [ \"${my_id}\" != \"0\" ] && [ \"${use_sudo}\" = \"0\" ]; then\n        verbose_message \"Requires sudo to check\" \"notice\"\n        return\n      fi\n      if [ \"${audit_mode}\" != 2 ]; then\n        correct_value=\"0\"\n        get_command=\"sudo /usr/bin/security authorizationdb read system.login.screensaver 2>&1 | /usr/bin/grep -c 'use-login-window-ui'\"\n        set_command=\"sudo /usr/bin/security authorizationdb write system.login.screensaver use-login-window-ui\"\n        current_value=$( eval \"${get_command}\" )\n        if [ \"${current_value}\" = \"${correct_value}\" ]; then\n          inc_secure   \"Administrator Account Login to Another User Session is set to \\\"${correct_value}\\\"\"\n        else\n          inc_insecure \"Administrator Account Login to Another User Session is not set to \\\"${correct_value}\\\"\"\n        fi\n        if [ \"${ansible_mode}\" = 1 ]; then\n          echo \"\"\n          echo \"- name: Checking ${string}\"\n          echo \"  command: sh -c \\\"${get_command}\\\"\"\n          echo \"  register: ${ansible_value}\"\n          echo \"  failed_when: ${ansible_value} != 0\"\n          echo \"  changed_when: false\"\n          echo \"  ignore_errors: true\"\n          echo \"  when: ansible_facts['ansible_system'] == '${os_name}'\"\n          echo \"\"\n          echo \"- name: Fixing ${string}\"\n          echo \"  command: sh -c \\\"${set_command}\\\"\"\n          echo \"  when: ${ansible_value}.rc == 1 and ansible_facts['ansible_system'] == '${os_name}'\"\n          echo \"\"\n        else\n          lock_command=\"${set_command}\"\n          lock_message=\"Disable ${string}\"\n          run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n        fi\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_ad_tracking.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_ad_tracking\n#\n# Organizations should manage advertising settings on computers rather than allow users\n# to configure the settings.\n#\n# Refer to Section(s) 2.6.4 Page(s) 170- CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_ad_tracking () {\n  print_function \"audit_ad_tracking\"\n  string=\"Ad Tracking\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${long_os_version}\" -ge 1014 ]; then\n      if [ \"${audit_mode}\" != 2 ]; then\n        command=\"find /Users -maxdepth 1 | grep -vE \\\"localized|Shared\\\" | cut -f3 -d/\"\n        command_message \"${command}\"\n        user_list=$( eval \"${command}\" )\n        for user_name in ${user_list}; do\n          check_osx_defaults_user \"com.apple.AdLib.plist\" \"allowApplePersonalizedAdvertising\" \"0\" \"bool\" \"${user_name}\"\n        done\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_air_drop.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_air_drop\n#\n# AirDrop can allow malicious files to be downloaded from unknown sources. Contacts\n# Only limits may expose personal information to devices in the same area.\n#\n# Refer to Section(s) 2.3.1.1 Page(s) 72-6 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_air_drop () {\n  print_function \"audit_air_drop\"\n  string=\"Air Drop\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${long_os_version}\" -ge 1014 ]; then\n      if [ \"${audit_mode}\" != 2 ]; then\n        command=\"find /Users -maxdepth 1 | grep -vE \\\"localized|Shared\\\" | cut -f3 -d/\"\n        command_message \"${command}\"\n        user_list=$( eval \"${command}\" )\n        for user_name in ${user_list}; do\n          check_osx_defaults_user \"com.apple.NetworkBrowser\" \"DisableAirDrop\" \"1\" \"bool\" \"${user_name}\"\n        done\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_air_play.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_air_play\n#\n# AirDrop can allow malicious files to be downloaded from unknown sources. Contacts\n# Only limits may expose personal information to devices in the same area.\n#\n# Refer to Section(s) 2.3.1.2 Page(s) 77-80 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_air_play () {\n  print_function \"audit_air_play\"\n  string=\"Air Play Receiver\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${long_os_version}\" -ge 1014 ]; then\n      if [ \"${audit_mode}\" != 2 ]; then\n        command=\"find /Users -maxdepth 1 | grep -vE \\\"localized|Shared\\\" | cut -f3 -d/\"\n        command_message \"${command}\"\n        user_list=$( eval \"${command}\" )\n        for user_name in ${user_list}; do\n          check_osx_defaults_user \"com.apple.controlcenter.plist\" \"AirplayRecieverEnabled\" \"0\" \"bool\" \"currentHost\" \"${user_name}\"\n        done\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_amfi.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_amfi\n#\n# Apple Mobile File Integrity validates that application code is validated.\n#\n# Refer to Section(s) 5.1.3 Page(s) 303-4 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_amfi () {\n  print_function \"audit_amfi\"\n  string=\"Apple Mobile File Integrity\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${long_os_version}\" -ge 1012 ]; then\n      if [ \"${my_id}\" != \"0\" ] && [ \"${use_sudo}\" = \"0\" ]; then\n        verbose_message \"Requires sudo to check\" \"notice\"\n        return\n      fi\n      get_command=\"sh -c \\\"sudo nvram -p > /dev/null 2>&1 | grep -c amfi | sed 's/ //g'\"\n      set_command=\"sudo /usr/sbin/nvram boot-args=\\\\\\\"\\\\\\\"\"\n      if [ \"${audit_mode}\" != 2 ]; then\n        command=\"sudo nvram -p > /dev/null 2>&1 | grep -c amfi | sed 's/ //g'\"\n        command_message \"${command}\"\n        check_value=$( eval \"${command}\" )\n        if [ \"${check_value}\" = \"0\" ]; then\n          inc_secure   \"Apple Mobile File Integrity is not \\\"disabled\\\"\"\n        else\n          inc_insecure \"Apple Mobile File Integrity is set to \\\"${check_value}\\\"\"\n        fi\n        if [ \"${ansible_mode}\" = 1 ]; then\n          ansible_counter=$((ansible_counter+1))\n          ansible_value=\"audit_amfi_${ansible_counter}\"\n          echo \"\"\n          echo \"- name: Checking ${string}\"\n          echo \"  command: sh -c \\\"${get_command}'\\\"\"\n          echo \"  register: ${ansible_value}\"\n          echo \"  failed_when: ${ansible_value} != 0\"\n          echo \"  changed_when: false\"\n          echo \"  ignore_errors: true\"\n          echo \"  when: ansible_facts['ansible_system'] == '${os_name}'\"\n          echo \"\"\n          echo \"- name: Fixing ${string}\"\n          echo \"  command: sh -c \\\"${set_command}\\\"\"\n          echo \"  when: ${ansible_value}.rc == 1 and ansible_facts['ansible_system'] == '${os_name}'\"\n          echo \"\"\n        else\n          lock_command=\"sudo /usr/sbin/nvram boot-args=\\\"\\\"\"\n          lock_message=\"Enable ${string}\"\n          run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n        fi\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_apfs.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n# shellcheck disable=SC2196\n\n# audit_apfs\n#\n# Ensure all user storage APFS volumes are encrypted\n#\n# Refer to Section(s) 5.3.1 Page(s) 335-8 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_apfs () {\n  print_function \"audit_apfs\"\n  string=\"APFS Volumes\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${long_os_version}\" -ge 1014 ]; then\n      if [ \"${audit_mode}\" != 2 ]; then\n        command=\"diskutil ap list | grep -Ev \\\"Snapshot|Not Mounted|Sealed|Capacity\\\" | grep -A1 \\\"/\\\" | grep -v \\\"\\-\\\" | sed \\\"s/\\|//g\\\" | sed \\\"s/ //g\\\" | grep -B1 \\\"FileVault:No\\\" | grep \\\"MountPoint\\\" | cut -f2 -d:\"\n        command_message       \"${command}\"\n        insecure_vols=$( eval \"${command}\" )\n        for volume in ${insecure_vols}; do\n          inc_insecure \"APFS Volume \\\"${volume}\\\" is not encrypted\"\n        done\n        command=\"diskutil ap list | grep -Ev \\\"Snapshot|Not Mounted|Sealed|Capacity\\\" | grep -A1 \\\"/\\\" | grep -v \\\"\\-\\\" | sed \\\"s/\\|//g\\\" | sed \\\"s/ //g\\\" | grep -B1 \\\"FileVault:Yes\\\" | grep \\\"MountPoint\\\" | cut -f2 -d:\"\n        command_message     \"${command}\"\n        secure_vols=$( eval \"${command}\" )\n        for volume in ${secure_vols}; do\n          inc_secure \"APFS Volume \\\"${volume}\\\" is encrypted\"\n        done\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_app_perms.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_app_perms\n#\n# Check Application Permissions\n# \n# Refer to Section(s) 5.1.2   Page(s) 109    CIS Apple OS X 10.12 Benchmark v1.0.0\n# Refer to Section(s) 5.1.5-6 Page(s) 307-10 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_app_perms () {\n  print_function \"audit_app_perms\"\n  string=\"Application Permissions\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${audit_mode}\" != 2 ]; then\n      OFS=$IFS\n      IFS=$(printf '\\n+'); IFS=${IFS%?}\n      for check_dir in Applications System; do\n        test_dirs=$( find /${check_dir} -maxdepth 1 -type d )\n        for test_dir in ${test_dirs}; do\n          check_file_perms \"${test_dir}\" \"0755\" \"\" \"\"\n        done\n      done\n      IFS=$OFS\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_asl.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_asl\n#\n# Check how long system logs are being kept for\n#\n# Refer to Section(s) 3.1.1-3,3.5 Page(s) 85-60,94-5  CIS Apple OS X 10.12 Benchmark v1.0.0\n# Refer to Section(s) 3.3         Page(s) 276-7       CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_asl () {\n  print_function \"audit_asl\"\n  string=\"System Logging\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    check_append_file \"/etc/asl.conf\"              \"> system.log mode=0640 format=bsd rotate=utc compress file_max=5M ttl=90\"                 \"hash\"\n    check_append_file \"/etc/asl.conf\"              \"> appfirewall.log mode=0640 format=bsd rotate=utc compress file_max=5M ttl=90\"            \"hash\"\n    check_append_file \"/etc/asl/com.apple.authd\"   \"* file /var/log/authd.log mode=0640 format=bsd rotate=utc compress file_max=5M ttl=90\"    \"hash\"\n    check_append_file \"/etc/asl/com.apple.install\" \"* file /var/log/install.log mode=0640 format=bsd rotate=utc compress file_max=5M ttl=365\" \"hash\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_asset_cache.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_asset_cache\n#\n# The main use case for Mac computers is as mobile user endpoints. P2P sharing\n# services should not be enabled on laptops that are using untrusted networks. Content\n# Caching can allow a computer to be a server for local nodes on an untrusted network.\n# While there are certainly logical controls that could be used to mitigate risk, they add to\n# the management complexity. Since the value of the service is in specific use cases,\n#\n# Refer to Section(s) 2.3.3.9 Page(s) 111-3 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_asset_cache () {\n  print_function \"audit_asset_cache\"\n  string=\"Asset Cache Activation\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${long_os_version}\" -ge 1013 ]; then\n      if [ \"${my_id}\" != \"0\" ] && [ \"${use_sudo}\" = \"0\" ]; then\n        notice_message \"Requires sudo to check\"\n        return\n      fi\n      if [ \"${audit_mode}\" != 2 ]; then\n        get_command=\"sudo AssetCacheManagerUtil status 2>&1 | grep Activated | awk '{print \\$2}' | grep -ci false | sed 's/ //g'\"\n        set_command=\"sudo /usr/bin/AssetCacheManagerUtil deactivate\"\n        check_value=$( eval \"${get_command}\" )\n        if [ \"${check_value}\" = \"0\" ]; then\n          inc_secure   \"Content Caching is not activated\"\n        else\n          inc_insecure \"Content Caching is activated\"\n        fi\n        if [ \"${ansible_mode}\" = 1 ]; then\n          ansible_counter=$((ansible_counter+1))\n          ansible_value=\"audit_asset_cache_${ansible_counter}\"\n          echo \"\"\n          echo \"- name: Checking ${string}\"\n          echo \"  command: sh -c \\\"${get_command}\\\"\"\n          echo \"  register: ${ansible_value}\"\n          echo \"  failed_when: ${ansible_value} != 0\"\n          echo \"  changed_when: false\"\n          echo \"  ignore_errors: true\"\n          echo \"  when: ansible_facts['ansible_system'] == '${os_name}'\"\n          echo \"\"\n          echo \"- name: Fixing ${string}\"\n          echo \"  command: sh -c \\\"${set_command}\\\"\"\n          echo \"  when: ${ansible_value}.rc == 1 and ansible_facts['ansible_system'] == '${os_name}'\"\n          echo \"\"\n        else\n          lock_command=\"${set_command}\"\n          lock_message=\"Disable ${string}\"\n          run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n        fi\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_auto_login.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_auto_login\n#\n# Disabling automatic login decreases the likelihood of an unauthorized person gaining\n# access to a system.\n#\n# Refer to Section(s) 5.7       Page(s) 53-54  CIS Apple OS X 10.8 Benchmark v1.0.0\n# Refer to Section(s) 5.8,6.1.1 Page(s) 152-3  CIS Apple OS X 10.12 Benchmark v1.0.0\n# Refer to Section(s) 2.12.3    Page(s) 248-50 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_auto_login() {\n  print_function \"audit_auto_login\"\n  string=\"Autologin\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    check_osx_defaults_bool \"/Library/Preferences/.GlobalPreferences\" \"com.apple.userspref.DisableAutoLogin\" \"yes\"\n    if [ ! \"${audit_mode}\" != 2 ]; then\n      get_command=\"defaults read /Library/Preferences/com.apple.loginwindow | grep -c autoLoginUser | sed 's/ //g'\"\n      set_command=\"sudo /usr/bin/defaults delete /Library/Preferences/com.apple.loginwindow autoLoginUser\"\n      defaults_check=$( eval \"${get_command}\" ) \n      if [ \"${defaults_check}\" = \"0\" ]; then\n        inc_insecure  \"${string} Disabled\"\n      else\n        inc_secure    \"${string} Enabled\"\n      fi\n      if [ \"${ansible_mode}\" = 1 ]; then\n        ansible_counter=$((ansible_counter+1))\n        ansible_value=\"audit_auto_login_${ansible_counter}\"\n        echo \"\"\n        echo \"- name: Checking ${string}\"\n        echo \"  command: sh -c \\\"${get_command}\\\"\"\n        echo \"  register: ${ansible_value}\"\n        echo \"  failed_when: ${ansible_value} != 0\"\n        echo \"  changed_when: false\"\n        echo \"  ignore_errors: true\"\n        echo \"  when: ansible_facts['ansible_system'] == '${os_name}'\"\n        echo \"\"\n        echo \"- name: Fixing ${string}\"\n        echo \"  command: sh -c \\\"${set_command}\\\"\"\n        echo \"  when: ${ansible_value}.rc == 1 and ansible_facts['ansible_system'] == '${os_name}'\"\n        echo \"\"\n      else\n        lock_command=\"${set_command}\"\n        lock_message=\"Disable ${string}\"\n        run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}"
  },
  {
    "path": "modules/darwin/audit_auto_logout.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_auto_logout\n#\n# Check AutoLogout\n#\n# Refer to Section(s) 5.11 Page(s) 57-58 CIS Apple OS X 10.8 Benchmark v1.0.0\n#.\n\naudit_auto_logout () {\n  print_function \"audit_auto_logout\"\n  string=\"Autologout\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    check_osx_defaults_int \"/Library/Preferences/.GlobalPreferences\" \"com.apple.autologout.AutoLogOutDelay\" \"0\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_bonjour_advertising.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n# shellcheck disable=SC2028\n\n# audit_bonjour_advertising\n#\n# Refer to Section(s) 3.4-7     Page(s) 39-40 CIS Apple OS X 10.8 Benchmark v1.0.0\n# Refer to Section(s) 2.4.14.14 Page(s) 62-3  CIS Apple OS X 10.5 Benchmark v1.1.0\n# Refer to Section(s) 4.1       Page(s) 96-7  CIS Apple OS X 10.5 Benchmark v1.1.0\n# Refer to Section(s) 4.1       Page(s) 290-1 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_bonjour_advertising() {\n  print_function \"audit_bonjour_advertising\"\n  string=\"Bonjour Multicast Advertising\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    check_file=\"/System/Library/LaunchDaemons/com.apple.mDNSResponder.plist\"\n    if [ \"${long_os_version}\" -ge 1014 ]; then\n      check_osx_defaults_bool \"/Library/Preferences/com.apple.mDNSResponder.plist\" \"NoMulticastAdvertisements\" \"1\"\n    else\n      temp_file=\"${temp_dir}/mdnsmcast\"\n      if [ \"${audit_mode}\" = 2 ]; then\n        restore_file \"${check_file}\" \"${restore_dir}\"\n      else\n        get_command=\"cat ${check_file} |grep NoMulticastAdvertisements\"\n        set_command=\"sed 's,mDNSResponder</string>,&X                <string>-NoMulticastAdvertisements</string>,g' < ${check_file} | tr X '\\n' > ${temp_file} ; cat ${temp_file} > ${check_file} ; rm ${temp_file}\"\n        multicast_test=$( grep -c \"NoMulticastAdvertisements\" \"${check_file}\" )\n        if [ -n \"${ansible_mode}\" ]; then\n          ansible_counter=$((ansible_counter+1))\n          ansible_value=\"audit_bonjour_advertising_${ansible_counter}\"\n          echo \"\"\n          echo \"- name: Checking ${string}\"\n          echo \"  command: sh -c \\\"${get_command}\\\"\"\n          echo \"  register: ${ansible_value}\"\n          echo \"  failed_when: ${ansible_value} == 1\"\n          echo \"  changed_when: false\"\n          echo \"  ignore_errors: true\"\n          echo \"  when: ansible_facts['ansible_system'] == '${os_name}'\"\n          echo \"\"\n          echo \"- name: Fixing ${string}\"\n          echo \"  command: sh -c \\\"${set_command}\\\"\"\n          echo \"  when: ${ansible_value}.rc == 1 and ansible_facts['ansible_system'] == '${os_name}'\"\n          echo \"\"\n        fi \n        if [ -n \"$multicast_test\" ]; then\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_insecure \"Bonjour Multicast Advertising enabled\"\n            fix_message  \"${set_command}\"\n          fi\n          if [ \"${audit_mode}\" = 0 ]; then\n            backup_file      \"${check_file}\"\n            lock_message=\"Bonjour Multicast Advertising disabled\"\n            lock_command=\"${set_command}\"\n            run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n          fi\n        else\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_secure   \"Bonjour Multicast Advertising disabled\"\n          fi\n        fi\n      fi\n    fi\n    if [ \"$osx_mdns_enable\" != \"yes\" ]; then\n      check_launchctl_service \"com.apple.mDNSResponder\"       \"off\"\n      check_launchctl_service \"com.apple.mDNSResponderHelper\" \"off\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_cd_sharing.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_cd_sharing\n#\n# Check CD sharing\n# \n# Refer to Section(s) 2.4.6   Page(s) 22   CIS Apple OS X 10.8  Benchmark v1.0.0\n# Refer to Section(s) 2.4.6   Page(s) 44   CIS Apple OS X 10.12 Benchmark v1.0.0\n# Refer to Section(s) 2.3.3.1 Page(s) 90-1 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_cd_sharing () {\n  print_function \"audit_cd_sharing\"\n  string=\"DVD/CD Sharing\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${audit_mode}\" != 2 ]; then\n      check_launchctl_service \"com.apple.ODSAgent\" \"off\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_file_sharing.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_file_sharing\n#\n# Refer to Section 2.4.8       Page(s) 23-4       CIS Apple OS X 10.8 Benchmark v1.0.0\n# Refer to Section 2.4.8,6.1.4 Page(s) 46-7,158-9 CIS Apple OS X 10.12 Benchmark v1.0.0\n# Refer to Section 2.3.3.3     Page(s) 95-7       CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_file_sharing () {\n  print_function \"audit_file_sharing\"\n  string=\"File Sharing\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    check_osx_defaults_bool \"/Library/Preferences/SystemConfiguration/com.apple.smb.server\" \"AllowGuestAccess\" \"no\"\n    check_launchctl_service \"com.apple.AppleFileServer\" \"off\"\n    check_launchctl_service \"nmbd\"  \"off\"\n    check_launchctl_service \"smbd\"  \"off\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_file_vault.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_file_vault\n#\n# FileVault secures a system's data by automatically encrypting its boot volume and\n# requiring a password or recovery key to access it.\n#\n# Refer to Section 2.6.1 Page(s) 28     CIS Apple OS X 10.8 Benchmark v1.0.0\n# Refer to Section 2.6.5 Page(s) 177-80 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_file_vault () {\n  print_function \"audit_file_vault\"\n  string=\"File Vault\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${audit_mode}\" != 2 ]; then\n      actual_value=$( diskutil cs list )\n      if [ \"${actual_value}\" = \"No CoreStorage logical volume groups found\" ]; then\n        if [ \"${audit_mode}\" = 1 ]; then\n          inc_insecure \"File Vault is not enabled\"\n        fi\n        if [ \"${audit_mode}\" = 1 ] || [ \"${audit_mode}\" = 0 ]; then\n          verbose_message \"Open System Preferences\"   \"fix\"\n          verbose_message \"Select Security & Privacy\" \"fix\"\n          verbose_message \"Select FileVault\"          \"fix\"\n          verbose_message \"Select Turn on FileVault\"  \"fix\"\n        fi\n      else\n        if [ \"${audit_mode}\" = 1 ]; then\n          inc_secure \"File Vault is enabled\"\n        fi\n      fi\n    else\n      verbose_message     \"Open System Preferences\"   \"fix\"\n      verbose_message     \"Select Security & Privacy\" \"fix\"\n      verbose_message     \"Select FileVault\"          \"fix\"\n      verbose_message     \"Select Turn on FileVault\"  \"fix\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_gate_keeper.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_gate_keeper\n#\n# Gatekeeper is Apple’s application that utilizes allowlisting to restrict downloaded\n# applications from launching. It functions as a control to limit applications from unverified\n# sources from running without authorization. In an update to Gatekeeper in macOS 13\n# Ventura, Gatekeeper checks every application on every launch, not just quarantined apps.\n#\n# Refer to Section 2.5.1 Page(s) 26-27 CIS Apple OS X 10.8  Benchmark v1.0.0\n# Refer to Section 2.6.2 Page(s) 55    CIS Apple OS X 10.12 Benchmark v1.0.0\n# Refer to Section 2.6.5 Page(s) 174-6 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_gate_keeper () {\n  print_function \"audit_gate_keeper\"\n  string=\"Gatekeeper\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${my_id}\" != \"0\" ] && [ \"${use_sudo}\" = \"0\" ]; then\n      notice_message \"Requires sudo to check\"\n      return\n    fi\n    log_file=\"gatekeeper.log\"\n    if [ \"${audit_mode}\" != 2 ]; then\n      actual_value=$( sudo spctl --status | awk '{print $2}' | sed 's/d$//g' )\n      if [ \"${actual_value}\" = \"disable\" ]; then\n        if [ \"${audit_mode}\" = 1 ]; then\n          inc_insecure  \"Gatekeeper is not enabled\"\n        fi\n        if [ \"${audit_mode}\" = 0 ]; then\n          set_message \"Gatekeeper to enabled\"\n          echo \"${actual_value}\" > \"${work_dir}/${log_file}\"\n          sudo spctl --master-enable\n        fi\n      else\n        if [ \"${audit_mode}\" = 1 ]; then\n          inc_secure \"Gatekeeper is enabled\"\n        fi\n      fi\n    else\n      restore_file=\"${restore_dir}/${log_file}\"\n      if [ -f \"${restore_file}\" ]; then\n        restore_value=$( cat \"${restore_file}\" )\n        if [ \"${restore_value}\" != \"${actual_value}\" ]; then\n          restore_message \"Gatekeeper to \\\"${restore_value}\\\"\"\n          eval \"sudo spctl --master-${restore_value}\"\n        fi\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_guest_sharing.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_guest_sharing\n#\n# Not allowing guests to connect to shared folders mitigates the risk of an untrusted user\n# doing basic reconnaissance and possibly using privilege escalation attacks to take\n# control of the system.\n#\n# Refer to Section(s) 6.1.4      Page(s) 75-6        CIS Apple OS X 10.8 Benchmark v1.0.0\n# Refer to Section(s) 2.12.2,5.9 Page(s) 246-7,355-6 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_guest_sharing () {\n  print_function \"audit_guest_sharing\"\n  string=\"Guest account file sharing\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    check_osx_defaults_bool \"/Library/Preferences/com.apple.AppleFileServer\"                \"guestAccess\"      \"no\"\n    check_osx_defaults_bool \"/Library/Preferences/SystemConfiguration/com.apple.smb.server\" \"AllowGuestAccess\" \"no\"\n    if [ \"${long_os_version}\" -ge 1014 ]; then\n      check_sysadminctl     \"smbGuestAccess\" \"off\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_icloud_drive.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_icloud_drive\n#\n# Organizations should review third party storage solutions pertaining to existing data\n# confidentiality and integrity requirements.\n#\n# Refer to Section(s) 2.1.1.2 Page(s) 45-8 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_icloud_drive () {\n  print_function \"audit_icloud_drive\"\n  string=\"iCloud Drive\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${long_os_version}\" -ge 1014 ]; then\n      if [ \"${my_id}\" != \"0\" ] && [ \"${use_sudo}\" = \"0\" ]; then\n        verbose_message \"Requires sudo to check\" \"notice\"\n        return\n      fi\n      if [ \"${audit_mode}\" != 2 ]; then\n        command=\"find /Users -maxdepth 1 |grep -vE \\\"localized|Shared\\\" |cut -f3 -d/\"\n        command_message \"${command}\"\n        user_list=$( eval \"${command}\" )\n        for user_name in ${user_list}; do\n          for dir_name in Documents Desktop; do\n            if [ -f \"/Users/${user_name}/Library/Mobile\\ Documents/com~apple~CloudDocs/${dir_name}\" ]; then\n              command=\"sudo -u \\\"${user_name}\\\" sh -c \\\"ls -l /Users/${user_name}/Library/Mobile\\ Documents/com~apple~CloudDocs/${dir_name}/\\\" | grep -c total | sed \\\"s/ //g\\\"\"\n              command_message \"${command}\"\n              check_value=$( eval \"${command}\" )\n              if [ \"${check_value}\" = \"0\" ]; then\n                inc_secure   \"Documents in \\\"${dir_name}\\\" for \\\"${user_name}\\\" are not syncing \"\n              else\n                inc_insecure \"Documents in \\\"${dir_name}\\\" for \\\"${user_name}\\\" are syncing \"\n              fi\n            fi\n          done\n        done\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_infrared_remote.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_infrared_remote\n#\n# Check Infrared Remote\n#\n# Refer to Section(s) 1.4.13.7 Page(s) 48-9  CIS Apple OS X 10.6 Benchmark v1.0.0\n# Refer to Section(s) 2.9      Page(s) 79-80 CIS Apple OS X 10.12 Benchmark v1.0.0\n#\n# Refer to http://support.apple.com/kb/PH11060\n#.\n\naudit_infrared_remote () {\n  print_function \"audit_infrared_remote\"\n  string=\"Apple Remote Activation\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    check_osx_defaults_bool \"/Library/Preferences/com.apple.driver.AppleIRController\" \"DeviceEnabled\" \"no\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_internet_sharing.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_internet_sharing\n#\n# Check Internet Sharing\n#\n# Refer to Section(s) 2.4.2    Page(s) 17-18   CIS Apple OS X 10.8 Benchmark v1.0.0\n# Refer to Section(s) 2.3.3.8  Page(s) 108-10  CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_internet_sharing () {\n  print_function \"audit_internet_sharing\"\n  string=\"Internet Sharing\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    check_osx_defaults_dict \"/Library/Preferences/SystemConfiguration/com.apple.nat\" \"NAT\" \"Enabled\" \"dict\" \"0\" \"int\"\n    check_launchctl_service \"com.apple.InternetSharing\" \"off\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_java.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_java\n#\n# Check Java\n#\n# Refer to Section 2.11 Page(s) 82 CIS Apple OS X 10.8 Benchmark v1.0.0\n#.\n\naudit_java () {\n  print_function \"audit_java\"\n  string=\"Java\"\n  check_message  \"${string}\"\n  minimum_value=7\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${audit_mode}\" != 2 ]; then\n      java_bin=$( command -v java )\n      if [ -n \"$java_bin\" ]; then\n        verbose_message \"Java version\" \"check\"\n        command=\"java -version 2>&1 | awk -F '\\\"' '/version/ {print \\$2}' | cut -f1 -d.\"\n        command_message \"${command}\"\n        version_value=$( eval \"${command}\" )\n        if [ -n \"${version_value}\" ]; then\n          if [ \"${version_value}\" -ge \"${minimum_value}\" ]; then\n            inc_secure   \"Java version is greater than \\\"${minimum_value}\\\"\"\n          else\n            inc_insecure \"Java version is less than \\\"${minimum_value}\\\"\"\n          fi\n        fi\n        inc_secure \"Java not installed\"\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_keychain_lock.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_keychain_lock\n#\n# Check keychain lock\n#\n# Refer to Section(s) 5.2 Page(s) 49-50 CIS Apple OS X 10.8 Benchmark v1.0.0\n# Refer to Section(2) 5.5 Page(s) 164-5 CIS Apple OS X 10.12 Benchmark v1.0.0\n#.\n\naudit_keychain_lock () {\n  print_function \"audit_keychain_lock\"\n  string=\"Keychain Lock\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    timeout=\"21600\"\n    if [ \"${audit_mode}\" != 2 ]; then\n      for check_value in timeout lock-on-sleep; do\n        check_message \"Keychain has \\\"${check_value}\\\" set\"\n        command=\"security show-keychain-info 2> /dev/null | grep \\\"${check_value}\\\" | grep -c \\\"${timeout}\\\" | sed 's/ //g'\"\n        command_message \"${command}\"\n        actual_value=$( eval \"${command}\" )\n        if [ \"${actual_value}\" = \"0\" ]; then\n          inc_insecure \"Keychain \\\"${check_value}\\\" does not have \\\"${timeout}\\\" set\"\n        else\n          inc_secure   \"Keychain \\\"${check_value}\\\" has \\\"${timeout}\\\" set\"\n        fi\n        if [ \"${ansible_mode}\" = 1 ]; then\n          ansible_counter=$((ansible_counter+1))\n          ansible_value=\"audit_keychain_lock_${ansible_counter}\"\n          echo \"\"\n          echo \"- name: Checking ${string}\"\n          echo \"  command: sh -c \\\"security show-keychain-info 2> /dev/null | grep '${check_value}' | grep -c '${timeout}' | sed 's/ //g'\\\"\"\n          echo \"  register: ${ansible_value}\"\n          echo \"  failed_when: ${ansible_value} != 0\"\n          echo \"  changed_when: false\"\n          echo \"  ignore_errors: true\"\n          echo \"  when: ansible_facts['ansible_system'] == '${os_name}'\"\n          echo \"\"\n          echo \"- name: Fixing ${string}\"\n          if [ \"${check_value}\" = \"timeout\" ]; then\n            echo \"  command: sh -c \\\"set-keychain-settings -u -t ${timeout}\\\"\"\n          else\n            echo \"  command: sh -c \\\"set-keychain-settings -l -t ${timeout}\\\"\"\n          fi\n          echo \"  when: ${ansible_value}.rc == 1 and ansible_facts['ansible_system'] == '${os_name}'\"\n          echo \"\"\n        else\n          run_lockdown \"sudo /usr/bin/security authorizationdb write system.login.screensaver use-login-window-ui\" \"Disable ${string}\"\n        fi\n      done\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_keychain_sync.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_keychain_sync\n#\n# Ensure that the iCloud keychain is used consistently with organizational requirements.\n#\n# Refer to ection(s) 2.1.1.1 Page(s) 41-44 CIS macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_keychain_sync () {\n  print_function \"audit_keychain_sync\"\n  string=\"Keychain sync\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${long_os_version}\" -ge 1014 ]; then\n      verbose_message \"Keychain sync\" \"check\"\n      if [ \"${my_id}\" != \"0\" ] && [ \"${use_sudo}\" = \"0\" ]; then\n        verbose_message \"Requires sudo to check\" \"notice\"\n        return\n      fi\n      if [ \"${audit_mode}\" != 2 ]; then\n        command=\"find /Users -maxdepth 1 | grep -vE \\\"localized|Shared\\\" | cut -f3 -d/ | grep \\\"[a-z]\\\"\"\n        command_message \"${command}\"\n        user_list=$( eval \"${command}\" )\n        for user_name in ${user_list}; do\n          command=\"sudo -u \\\"${user_name}\\\" defaults read /Users/${user_name}/Library/Preferences/MobileMeAccounts 2> /dev/null |grep -B 1 KEYCHAIN_SYNC |head -1 |cut -f2 -d= |cut -f1 -d\\; |sed 's/ //g'\"\n          command_message \"${command}\"\n          check_value=$( eval \"${command}\" )\n          if [ \"${check_value}\" = \"${keychain_sync}\" ]; then\n            inc_secure   \"Keychain sync enable for \\\"${user_name}\\\" is set to \\\"${keychain_sync}\\\"\"\n          else\n            inc_insecure \"Keychain sync enable for \\\"${user_name}\\\" is not set to \\\"${keychain_sync}\\\"\"\n          fi\n        done\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_location_services.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_location_services\n#\n# There are some use cases where it is important that the computer not be able to report\n# its exact location. While the general use case is to enable Location Services, it should\n# not be allowed if the physical location of the computer and the user should not be public\n# knowledge.\n#\n# Refer to Section(s) 2.6.1.1-2 Page(s) 153-7 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_location_services () {\n  print_function \"audit_location_services\"\n  string=\"Location Services\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${long_os_version}\" -ge 1014 ]; then\n      if [ \"${audit_mode}\" != 2 ]; then\n        check_osx_defaults_bool \"/var/db/locationd/Library/Preferences/ByHost/com.apple.locationd\" \"LocationServicesEnabled\" \"0\"\n        check_osx_defaults_bool \"/Library/Preferences/com.apple.locationmenu.plist\"                \"ShowSystemServices\"      \"1\"\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_lockdown.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_lockdown\n#\n# When lockdown mode is enabled, specific trusted websites can be excluded from\n# Lockdown protection if necessary.\n#\n# Refer to Section(s) 2.6.7 Page(s) 181-2 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_lockdown () {\n  print_function \"audit_lockdown\"\n  string=\"Lockdown Mode\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${long_os_version}\" -ge 1014 ]; then\n      if [ \"${my_id}\" != \"0\" ] && [ \"${use_sudo}\" = \"0\" ]; then\n        notice_message \"Requires sudo to check\"\n        return\n      fi\n      if [ \"${audit_mode}\" != 2 ]; then\n        command=\"find /Users -maxdepth 1 | grep -vE \\\"localized|Shared\\\" | cut -f3 -d/\"\n        command_message   \"${command}\"\n        user_list=$( eval \"${command}\" )\n        for user_name in ${user_list}; do\n          check_osx_defaults_bool \".GlobalPreferences\" \"LDMGlobalEnabled\" \"1\"\n        done\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_media_sharing.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_media_sharing\n#\n# Disabling Media Sharing reduces the remote attack surface of the system.\n#\n# Refer to Section(s) 2.3.3.10 Page(s) 114-7 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_media_sharing () {\n  print_function \"audit_media_sharing\"\n  string=\"Media Sharing\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${long_os_version}\" -ge 1014 ]; then\n      if [ \"${audit_mode}\" != 2 ]; then\n        command=\"find /Users -maxdepth 1 | grep -vE \\\"localized|Shared\\\" | cut -f3 -d/\"\n        command_message   \"${command}\"\n        user_list=$( eval \"${command}\" )\n        for user_name in ${user_list}; do\n          check_osx_defaults_user \"com.apple.amp.mediasharingd\" \"home-sharing-enabled\" \"0\" \"bool\" \"${user_name}\"\n        done\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_remote_apple_events.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_remote_apple_events\n#\n# Check Apple remote events\n#\n# Refer to Section(s) 5.20    Page(s) 68-9  CIS Apple OS X 10.8 Benchmark v1.0.0\n# Refer to Section(s) 2.4.2   Page(s) 38    CIS Apple OS X 10.12 Benchmark v1.0.0\n# Refer to Section(s) 2.3.3.7 Page(s) 106-7 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_remote_apple_events () {\n  print_function \"audit_remote_apple_events\"\n  string=\"Remote Apple Events\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${long_os_version}\" -ge 1008 ]; then\n      check_osx_systemsetup   \"getremoteappleevents\" \"off\"\n    else\n      check_launchctl_service \"eppc\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_safari_allow_popups.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_safari_allow_popups\n#\n# Check Safari Popups\n#\n# Refer to Section(s) 6.3.9 Page(s) 406-7 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_safari_allow_popups () {\n  print_function \"audit_safari_allow_popups\"\n  string=\"Safari Allow Popups\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${long_os_version}\" -ge 1014 ]; then\n      if [ \"${my_id}\" != \"0\" ] && [ \"${use_sudo}\" = \"0\" ]; then\n        notice_message \"Requires sudo to check\"\n        return\n      fi\n      if [ \"${audit_mode}\" != 2 ]; then\n        command=\"find /Users -maxdepth 1 | grep -vE \\\"localized|Shared\\\" | cut -f3 -d/\"\n        command_message   \"${command}\"\n        user_list=$( eval \"${command}\" )\n        for user_name in ${user_list}; do\n          check_osx_defaults_user \"com.apple.Safari\" \"safariAllowPopups\" \"0\" \"bool\" \"${user_name}\"\n        done\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_safari_auto_fill.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_safari_auto_fill\n#\n# Check Safari Auto Fill\n#\n# Refer to Section(s) 6.3.8 Page(s) 403-5 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_safari_auto_fill () {\n  print_function \"audit_safari_auto_fill\"\n  string=\"Safari Auto Fill\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${long_os_version}\" -ge 1014 ]; then\n      if [ \"${my_id}\" != \"0\" ] && [ \"${use_sudo}\" = \"0\" ]; then\n        notice_message \"Requires sudo to check\"\n        return\n      fi\n      if [ \"${audit_mode}\" != 2 ]; then\n        user_list=$( find /Users -maxdepth 1 | grep -vE \"localized|Shared\" | cut -f3 -d/ )\n        for user_name in ${user_list}; do\n          for parameter in AutoFillFromAddressBook AutoFillPasswords AutoFillCreditCardData AutoFillMiscellaneousForms; do\n            check_osx_defaults_user \"com.apple.Safari\" \"${parameter}\" \"0\" \"bool\" \"${user_name}\"\n          done\n        done\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_safari_auto_run.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_safari_auto_run\n#\n# Check Safari settingd\n#\n# Refer to Section(s) 6.3   Page(s) 78     CIS Apple OS X 10.8 Benchmark v1.0.0\n# Refer to Section(s) 6.3-4 Page(s) 164-6  CIS Apple OS X 10.12 Benchmark v1.0.0\n# Refer to Section(s) 6.3.1 Page(s) 369-73 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_safari_auto_run () {\n  print_function \"audit_safari_auto_run\"\n  string=\"Safari Auto-run\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${audit_mode}\" != 2 ]; then\n      check_osx_defaults_int    \"com.apple.Safari AutoOpenSafeDownloads\" \"0\" \"int\"\n      check_osx_defaults_string \"$HOME/Library/Preferences/com.apple.safari.plist\" \"PlugInFirstVisitPolicy\" \"PlugInPolicyAllowWithSecurityRestrictions\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_safari_history.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_safari_history\n#\n# Check Safari history limit\n#\n# Refer to Section(s) 6.3.2 Page(s) 374-79 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_safari_history () {\n  print_function \"audit_safari_history\"\n  string=\"Safari History\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${long_os_version}\" -ge 1014 ]; then\n      if [ \"${my_id}\" != \"0\" ] && [ \"${use_sudo}\" = \"0\" ]; then\n        notice_message \"Requires sudo to check\"\n        return\n      fi\n      if [ \"${audit_mode}\" != 2 ]; then\n        command=\"find /Users -maxdepth 1 | grep -vE \\\"localized|Shared\\\" | cut -f3 -d/\"\n        command_message   \"${command}\"\n        user_list=$( eval \"${command}\" )\n        for user_name in ${user_list}; do\n          check_osx_defaults_user \"com.apple.Safari\" \"HistoryAgeInDaysLimit\" \"31\" \"int\" \"${user_name}\"\n        done\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_safari_javascript.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_safari_javascript\n#\n# Check Safari Javascript\n#\n# Refer to Section(s) 6.3.10 Page(s) 408-9 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_safari_javascript () {\n  print_function \"audit_safari_javascript\"\n  string=\"Safari Javascript\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${long_os_version}\" -ge 1014 ]; then\n      if [ \"${my_id}\" != \"0\" ] && [ \"${use_sudo}\" = \"0\" ]; then\n        notice_message \"Requires sudo to check\"\n        return\n      fi\n      if [ \"${audit_mode}\" != 2 ]; then\n        command=\"find /Users -maxdepth 1 | grep -vE \\\"localized|Shared\\\" | cut -f3 -d/\"\n        command_message   \"${command}\"\n        user_list=$( eval \"${command}\" )\n        for user_name in ${user_list}; do\n          check_osx_defaults_user \"com.apple.Safari\" \"WebKitPreferences.javaScriptEnabled\" \"0\" \"bool\" \"${user_name}\"\n        done\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_safari_show_statusbar.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC2034\n# shellcheck disable=SC1090\n# shellcheck disable=SC2154\n\n# audit_safari_show_statusbar\n#\n# Check Safari Popups\n#\n# Refer to Section(s) 6.3.11 Page(s) 410-11 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_safari_show_statusbar () {\n  print_function \"audit_safari_show_statusbar\"\n  string=\"Safari Show Status Bar\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${long_os_version}\" -ge 1014 ]; then\n      if [ \"${my_id}\" != \"0\" ] && [ \"${use_sudo}\" = \"0\" ]; then\n        notice_message \"Requires sudo to check\"\n        return\n      fi\n      if [ \"${audit_mode}\" != 2 ]; then\n        command=\"find /Users -maxdepth 1 | grep -vE \\\"localized|Shared\\\" | cut -f3 -d/\"\n        command_message   \"${command}\"\n        user_list=$( eval \"${command}\" )\n        for user_name in ${user_list}; do\n          check_osx_defaults_user \"com.apple.Safari\" \"ShowOverlayStatusBar\" \"1\" \"bool\" \"${user_name}\"\n        done\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_safari_tracking.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2010\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_safari_tracking\n#\n# Check Safari Tracking\n#\n# Refer to Section(s) 6.3.4-6 Page(s) 385-402 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_safari_tracking () {\n  print_function \"audit_safari_tracking\"\n  string=\"Safari Cross-site Tracking\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${long_os_version}\" -ge 1014 ]; then\n      if [ \"${my_id}\" != \"0\" ] && [ \"${use_sudo}\" = \"0\" ]; then\n        notice_message \"Requires sudo to check\"\n        return\n      fi\n      if [ \"${audit_mode}\" != 2 ]; then\n        command=\"ls /Users | grep -v Shared\"\n        command_message   \"${command}\"\n        user_list=$( eval \"${command}\" )\n        for user_name in ${user_list}; do\n          check_osx_defaults_user \"com.apple.Safari\" \"BlockStoragePolicy\"                               \"2\"        \"int\"  \"${user_name}\"\n          check_osx_defaults_user \"com.apple.Safari\" \"WebKitStorageBlockingPolicy\"                      \"1\"        \"int\"  \"${user_name}\"\n          check_osx_defaults_user \"com.apple.Safari\" \"WebKitPreferences.storageBlockingPolicy\"          \"1\"        \"int\"  \"${user_name}\"\n          check_osx_defaults_user \"com.apple.Safari\" \"WBSPrivacyProxyAvailabilityTraffic\"               \"33422572\" \"int\"  \"${user_name}\"\n          check_osx_defaults_user \"com.apple.Safari\" \"WebKitPreferences.privateClickMeasurementEnabled\" \"1\"        \"bool\" \"${user_name}\"\n          check_osx_defaults_user \"com.apple.Safari\" \"ShowFullURLInSmartSearchField\"                    \"1\"        \"bool\" \"${user_name}\"\n        done\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_safari_warn.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_safari_warn\n#\n# Attackers use crafted web pages to social engineer users to load unwanted content.\n# Warning users prior to loading the content enables better security.\n#\n# Refer to Section(s) 6.3.2 Page(s) 380-4 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_safari_warn () {\n  print_function \"audit_safari_warn\"\n  string=\"Safari Fraudulent Website Warning\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${long_os_version}\" -ge 1014 ]; then\n      if [ \"${my_id}\" != \"0\" ] && [ \"${use_sudo}\" = \"0\" ]; then\n        notice_message \"Requires sudo to check\"\n        return\n      fi\n      if [ \"${audit_mode}\" != 2 ]; then\n        command=\"find /Users -maxdepth 1 | grep -vE \\\"localized|Shared\\\" | cut -f3 -d/\"\n        command_message \"${command}\"\n        user_list=$( eval \"${command}\" )\n        for user_name in ${user_list}; do\n          check_osx_defaults_user \"com.apple.Safari\" \"WarnAboutFraudulentWebsites\" \"1\" \"bool\" \"${user_name}\"\n        done\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_safe_downloads.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_safe_downloads\n#\n# Check safe downloads\n#\n# Refer to Section(s) 2.6.3 Page(s) 29-30 CIS Apple OS X 10.8 Benchmark v1.0.0\n#.\n\naudit_safe_downloads () {\n  print_function \"audit_safe_downloads\"\n  string=\"Safe Downloads list\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${audit_mode}\" != 2 ]; then\n      update_file=\"/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/XProtect.plist\"\n      if [ ! -f \"${update_file}\" ]; then\n        actual_value=\"not-found\"\n      else\n        actual_value=$( find \"${update_file}\" -mtime -30 )\n      fi\n      if [ \"${actual_value}\" != \"${update_file}\" ]; then\n        if [ \"${audit_mode}\" = 1 ]; then\n          inc_insecure   \"Safe Downloads list has not be updated recently\"\n          notice_message \"Open System Preferences\"\n          notice_message \"Select Security & Privacy\"\n          notice_message \"Select the General tab\"\n          notice_message \"Select Advanced\"\n          notice_message \"Check Automatically update safe downloads list\"\n          notice_message \"sudo /usr/libexec/XProtectUpdater\"\n        fi\n        if [ \"${audit_mode}\" = 0 ]; then\n          verbose_message \"Updating:  Safe Downloads list\"\n          sudo /usr/libexec/XProtectUpdater\n        fi\n      else\n        if [ \"${audit_mode}\" = 1 ]; then\n          inc_secure \"Safe Downloads list has been updated recently\"\n        fi\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_screen_corner.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_screen_corner\n#\n# Hot Corners can be configured to disable the screen saver by moving the mouse cursor\n# to a corner of the screen.\n#\n# Refer to Section(s) 2.7.1 Page(s) 188-92 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_screen_corner () {\n  print_function \"audit_screen_corner\"\n  string=\"Screen Saver Corners\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${long_os_version}\" -ge 1014 ]; then\n      if [ \"${my_id}\" != \"0\" ] && [ \"${use_sudo}\" = \"0\" ]; then\n        notice_message \"Requires sudo to check\"\n        return\n      fi\n      if [ \"${audit_mode}\" != 2 ]; then\n        command=\"find /Users -maxdepth 1 | grep -vE \\\"localized|Shared\\\" | cut -f3 -d/\"\n        command_message   \"${command}\"\n        user_list=$( eval \"${command}\" )\n        for user_name in ${user_list}; do\n          for corner in wvous-tl-corner wvous-bl-corner wvous-tr-corner wvous-tr-corner; do\n            check_osx_defaults_user \"com.apple.NetworkBrowser\" \"${corner}\" \"6\" \"int\" \"${user_name}\"\n          done\n        done\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_screen_lock.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_screen_lock\n#\n# Setting an inactivity interval for the screen saver prevents unauthorized persons from\n# viewing a system left unattended for an extensive period of time.\n#\n# Refer to Section(s) 2.3.1-2           Page(s) 13-14             CIS Apple OS X 10.8 Benchmark v1.0.0\n# Refer to Section(s) 2.3.1-2,4,5.9,11  Page(s) 32-4,7,137,140-1  CIS Apple OS X 10.12 Benchmark v1.0.0\n# Refer to Section(s) 5.5               Page(s) 51-52             CIS Apple OS X 10.8 Benchmark v1.0.0\n# Refer to Section(s) 2.10.1            Page(s) 218-21            CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_screen_lock () {\n  print_function \"audit_screen_lock\"\n  string=\"Screen Lock\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${long_os_version}\" -ge 1014 ]; then\n      if [ \"${audit_mode}\" != 2 ]; then\n        command=\"find /Users -maxdepth 1 | grep -vE \\\"localized|Shared\\\" | cut -f3 -d/\"\n        command_message   \"${command}\"\n        user_list=$( eval \"${command}\" )\n        for user_name in ${user_list}; do\n          check_osx_defaults_user \"com.apple.screensaver\" \"idleTime\" \"600\" \"int\" \"currentHost\" \"${user_name}\"\n        done\n      fi\n    fi\n    check_message \"Screen Lock\"\n    check_osx_defaults_host \"com.apple.screensaver\"  \"askForPassword\" \"1\"   \"int\"\n    check_osx_defaults_host \"com.apple.screensaver\"  \"idleTime\"       \"900\" \"int\"\n    check_append_file       \"/etc/pam.d/screensaver\" \"account    required     pam_group.so no_warn group=admin,wheel fail_safe\" \"hash\"\n    if [ \"${audit_mode}\" != 2 ]; then\n      if [ -f \"$HOME/Library/Preferences/com.apple.dock\" ]; then\n        command=\"defaults read ~/Library/Preferences/com.apple.dock |grep corner |grep -c 1 |sed \\\"s/ //g\\\"\"\n        command_message     \"${command}\"\n        screen_test=$( eval \"${command}\" )\n        if [ \"${screen_test}\" = \"1\" ]; then\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_insecure \"Screensaver disable hot corner is enabled\"\n          fi\n          if [ \"${audit_mode}\" = 1 ] || [ \"${audit_mode}\" = 0 ]; then\n            fix_message  \"Open System Preferences\"\n            fix_message  \"Mission Control\"\n            fix_message  \"Hot Corners\"\n            fix_message  \"Remove any corners which are set to Disable Screen Saver\"\n          fi\n        else\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_secure   \"No screensaver disable hot corners enabled\"\n          fi\n        fi\n      else\n        if [ \"${audit_mode}\" = 1 ]; then\n          inc_secure \"No screensaver disable hot corners enabled\"\n        fi\n      fi\n    else\n      notice_message \"Open System Preferences\"\n      notice_message \"Mission Control\"\n      notice_message \"Hot Corners\"\n      notice_message \"Remove any corners which are set to Disable Screen Saver\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_screen_sharing.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_screen_sharing\n#\n# Check sreen sharing settings\n#\n# Refer to Section(s) 2.4.3   Page(s) 40   CIS Apple OS X 10.12 Benchmark v1.0.0\n# Refer to Section(s) 2.3.3.2 Page(s) 92-4 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#\n# Refer to http://support.apple.com/kb/ph11151\n#.\n\naudit_screen_sharing () {\n  print_function \"audit_screen_sharing\"\n  string=\"Screen Sharing\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${audit_mode}\" != 2 ]; then\n      check_launchctl_service \"com.apple.screensharing\" \"off\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_siri.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_siri\n#\n# Where \"normal\" user activity is already limited, Siri use should be controlled as well.\n#\n# Refer to Section(s) 2.5.1 Page(s) 141-8 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_siri () {\n  print_function \"audit_siri\"\n  string=\"Siri Settings\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${long_os_version}\" -ge 1014 ]; then\n      if [ \"${audit_mode}\" != 2 ]; then\n        command=\"find /Users -maxdepth 1 | grep -vE \\\"localized|Shared\\\" | cut -f3 -d/\"\n        command_message \"${command}\"\n        user_list=$( eval \"${command}\" )\n        for user_name in ${user_list}; do\n          check_osx_defaults_user \"com.apple.Siri.plist\"              \"StatusMenuVisible\"       \"1\" \"bool\" \"${user_name}\"\n          check_osx_defaults_user \"com.apple.Siri.plist\"              \"LockscreenEnabled\"       \"0\" \"bool\" \"${user_name}\"\n          check_osx_defaults_user \"com.apple.Siri.plist\"              \"VoiceTriggerUserEnabled\" \"0\" \"bool\" \"${user_name}\"\n          check_osx_defaults_user \"com.apple.Siri.plist\"              \"TypeToSiriEnabled\"       \"0\" \"bool\" \"${user_name}\"\n          check_osx_defaults_user \"com.apple.assistant.support.plist\" \"Assistant Enabled\"       \"0\" \"bool\" \"${user_name}\"\n        done\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_sleep.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_sleep\n#\n# MacBooks should be set so that the standbydelay is 15 minutes (900 seconds) or less.\n# This setting should allow laptop users in most cases to stay within physically secured\n# areas while going to a conference room, auditorium, or other internal location without\n# having to unlock the encryption. When the user goes home at night, the laptop will auto-\n# hibernate after 15 minutes and require the FileVault password to unlock prior to logging\n# back into the system when it resumes.\n# MacBooks should also be set to a hibernate mode that removes power from the RAM.\n# This will stop the possibility of cold boot attacks on the system.\n# Macs running Apple silicon chips, rather than Intel chips, do not require the same\n# configuration as Intel-based Macs.\n#\n# Full Disk Encryption (FDE) is a Data-at-Rest (DAR) solution. It ensures that when the\n# data on the drive is not in use it is full encrypted, but it can be decrypted (unlocked) as\n# needed. When a Mac sleeps, the encryption keys remain in memory so that the drive is\n# encrypted but unlocked. There are attacks available to interact with the OS and data on\n# the unlocked drive. FileVault volumes should be locked when not in use to resist attack.\n# The purpose of DAR is to ensure data is encrypted while at rest. If the volume is always\n# unlocked it is not sufficient.\n#\n# Refer to Section(s) 2.5.2           Page(s) 52-3   CIS Apple OS X 10.12 Benchmark v1.0.0\n# Refer to Section(s) 2.9.1.1-3,2.9.2 Page(s) 200-11 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_sleep () {\n  print_function \"audit_sleep\"\n  string=\"Sleep\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${long_os_version}\" -ge 1014 ]; then\n      if [ \"${os_machine}\" = \"arm64\" ]; then\n        check_pmset \"sleep\"                 \"10\"\n        check_pmset \"displaysleep\"          \"15\"\n        check_pmset \"hibernatemode\"         \"25\"\n      else\n        check_pmset \"standbydelaylow\"       \"900\"\n        check_pmset \"standbydelayhigh\"      \"900\"\n        check_pmset \"highstandbythreshold\"  \"90\"\n        check_pmset \"destroyfvkeyonstandby\" \"1\"\n        check_pmset \"hibernatemode\"         \"25\"\n        check_pmset \"powernap\"              \"0\"\n      fi\n      check_pmset   \"destroyfvkeyonstandby\" \"1\"\n    else\n      check_pmset   \"sleep\"                 \"off\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_software_update.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_software_update\n#\n# Check software update settings\n#\n# Refer to http://pubs.vmware.com/vsphere-55/topic/com.vmware.vsphere.update_manager.doc/GUID-EF6BEE4C-4583-4A8C-81B9-5B074CA2E272.html\n#\n# Refer to                  Page(s) 8     CIS Apple OS X 10.8 Benchmark v1.0.0\n# Refer to Section(s) 1.2-5 Page(s) 13-20 CIS Apple OS X 10.12 Benchmark v1.0.0o\n# Refer to Section(s) 1.2-7 Page(s) 16-34 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_software_update () {\n  print_function \"audit_software_update\"\n  string=\"Software Update\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"VMkernel\" ]; then\n    vmware_depot=\"http://hostupdate.vmware.com/software/VUM/PRODUCTION/main/vmw-depot-index.xml\"\n    current_update=$( esxcli software profile get 2>&1 | head -1 )\n    log_file=\"softwareupdate.log\"\n    backup_file=\"${work_dir}/${log_file}\"\n    command=\"esxcli software sources profile list -d \\\"${vmware_depot}\\\" | grep \\\"${os_version}\\\" | head -1 | awk '{print \\$1}'\"\n    command_message \"${command}\"\n    available_update=$( eval \"${command}\" )\n    if [ \"${audit_mode}\" != 2 ]; then\n      if [ \"${current_update}\" != \"${available_update}\" ]; then\n        if [ \"${audit_mode}\" = 0 ]; then\n          notice_message \"Updating software\"\n          esxcli software profile install -d \"${vmware_depot}\" -p \"${available_update}\" --ok-to-remove\n        fi\n        if [ \"${audit_mode}\" = 1 ]; then\n          inc_insecure \"Software is not up to date (Current: ${current_update} Available: ${available_update})\"\n          fix_message  \"esxcli software profile install -d ${vmware_depot} -p ${available_update} --ok-to-remove\"\n        fi\n      else\n        if [ \"${audit_mode}\" = 1 ]; then\n          inc_secure   \"Software is up to date\"\n        fi\n      fi\n    else\n      restore_file=\"${restore_dir}/${log_file}\"\n      if [ -f \"${restore_file}\" ]; then\n        previous_update=$( cat \"${restore_file}\" )\n        if [ \"${current_update}\" != \"${previous_update}\" ]; then\n          restore_message \"Software to \\\"${previous_value}\\\"\"\n          esxcli software profile install -d \"${vmware_depot}\" -p \"${previous_update}\" --ok-to-remove --alow-downgrades\n        fi\n      fi\n    fi\n  fi\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${long_os_version}\" -ge 1012 ]; then\n      check_osx_defaults_int    \"/Library/Preferences/com.apple.SoftwareUpdate\" \"AutomaticCheckEnabled\"            \"1\"\n      check_osx_defaults_bool   \"/Library/Preferences/com.apple.commerce\"       \"AutoUpdate\"                       \"1\"\n      check_osx_defaults_bool   \"/Library/Preferences/com.apple.SoftwareUpdate\" \"ConfigDataInstall\"                \"1\"\n      check_osx_defaults_bool   \"/Library/Preferences/com.apple.SoftwareUpdate\" \"CriticalUpdateInstall\"            \"1\"\n      check_osx_defaults_bool   \"/Library/Preferences/com.apple.commerce\"       \"AutoUpdateRestartRequired\"        \"1\"\n      if [ \"${long_os_version}\" -ge 1013 ]; then\n        check_osx_defaults_bool \"/Library/Preferences/com.apple.SoftwareUpdate\" \"AutomaticDownload\"                \"1\"\n        check_osx_defaults_bool \"/Library/Preferences/com.apple.SoftwareUpdate\" \"AutomaticallyInstallMacOSUpdates\" \"1\"\n      fi\n    else\n      check_message \"Software Autoupdate\"\n      if [ \"${my_id}\" != \"0\" ] && [ \"${use_sudo}\" = \"0\" ]; then\n        notice_message \"Requires sudo to check\"\n        return\n      fi\n      command=\"sudo softwareupdate --schedule |awk '{print \\$4}'\"\n      command_message       \"${command}\"\n      actual_status=$( eval \"${command}\" )\n      log_file=\"softwareupdate.log\"\n      correct_status=\"on\"\n      if [ \"${audit_mode}\" != 2 ]; then\n       verbose_message \"If Software Update is enabled\"\n        if [ \"${actual_status}\" != \"${correct_status}\" ]; then\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_insecure \"Software Update is not \\\"${correct_status}\\\"\"\n            command_line=\"sudo softwareupdate --schedule ${correct_status}\"\n            fix_message  \"${command_line}\"\n          else\n            if [ \"${audit_mode}\" = 0 ]; then\n              log_file=\"${work_dir}/${log_file}\"\n              echo \"${actual_status}\" > \"${log_file}\"\n              set_message \"Software Update schedule to \\\"${correct_status}\\\"\"\n              sudo softwareupdate --schedule ${correct_status}\n            fi\n          fi\n        else\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_secure \"Software Update is ${correct_status}\"\n          fi\n        fi\n      else\n        restore_file=\"${restore_dir}/${log_file}\"\n        if [ -f \"${restore_file}\" ]; then\n          previous_status=$( cat \"${restore_file}\" )\n          if [ \"${previous_status}\" != \"${actual_status}\" ]; then\n            restore_message \"Software Update to \\\"${previous_status}\\\"\"\n            sudo softwareupdate --schedule \"${previous_status}\"\n          fi\n        fi\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_sys_suspend.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_sys_suspend\n#\n# Refer to Section(s) 10.4 Page(s) 140 CIS Solaris 10 Benchmark v1.1.0\n#.\n\naudit_sys_suspend () {\n  print_function \"audit_sys_suspend\"\n  string=\"System Suspend\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    check_file_value \"is\" \"/etc/default/sys-suspend\" \"PERMS\" \"eq\" \"-\" \"hash\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_system_preferences.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_system_preferences\n#\n# Chec whether a password is required to access system-wide preferences\n#\n# Refer to Section(s) 5.8 Page(s) 138-9 CIS Apple OS X 10.12 Benchmark v1.0.0\n#.\n\naudit_system_preferences () {\n  print_function \"audit_system_preferences\"\n  string=\"System Preferences\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ ! \"${audit_mode}\" != 2 ]; then\n      check=$( security authorizationdb read system.preferences 2> /dev/null | grep -A1 shared | grep true )\n      if [ \"${check}\" ]; then\n        inc_insecure \"An Administrator password is not required to access system-wide preferences\"\n      else\n        inc_secure   \"An Administrator password is required to access system-wide preferences\"\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_time_machine.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_time_machine\n#\n# Backups should automatically run whenever the backup drive is available.\n#\n# Refer to Section(s) 2.3.4.1 Page(s) 125-8 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_time_machine () {\n  print_function \"audit_time_machine\"\n  string=\"Time Machine\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${os_version}\" -ge 14 ]; then\n      check_osx_defaults_bool \"/Library/Preferences/com.apple.TimeMachine.plist\" \"AutoBackup\" \"1\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_touch_id.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_touch_id\n#\n# Touch ID allows for an account-enrolled fingerprint to access a key that uses a\n# previously provided password.\n#\n# Refer to Section(s) 2.11.2 Page(s) 237-40 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_touch_id () {\n  print_function \"audit_touch_id\"\n  string=\"Touch ID\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${long_os_version}\" -ge 1014 ]; then\n      if [ \"${my_id}\" != \"0\" ] && [ \"${use_sudo}\" = \"0\" ]; then\n        notice_message \"Requires sudo to check\"\n        return\n      fi\n      if [ \"${audit_mode}\" != 2 ]; then\n        get_command=\"sudo bioutil -r -s | grep timeout | head -1 | cut -f2 -d: | grep -c ${touchid_timeout} | sed 's/ //g'\"\n        set_command=\"/usr/bin/sudo usr/bin/bioutil -w -s -o ${touchid_timeout}\"\n        check_value=$( eval \"${get_command}\" )\n        if [ \"${check_value}\" = \"${touchid_timeout}\" ]; then\n          inc_secure   \"Touch ID Timeout for system is set to \\\"${touchid_timeout}\\\"\"\n        else\n          inc_insecure \"Touch ID Timeout for system is not set to \\\"${touchid_timeout}\\\"\"\n        fi\n        if [ \"${ansible_mode}\" = 1 ]; then\n          ansible_counter=$((ansible_counter+1))\n          ansible_value=\"audit_touch_id_${ansible_counter}\"\n          echo \"\"\n          echo \"- name: Checking ${string}\"\n          echo \"  command: sh -c \\\"${get_command}\\\"\"\n          echo \"  register: ${ansible_value}\"\n          echo \"  failed_when: ${ansible_value} != 1\"\n          echo \"  changed_when: false\"\n          echo \"  ignore_errors: true\"\n          echo \"  when: ansible_facts['ansible_system'] == '${os_name}'\"\n          echo \"\"\n          echo \"- name: Fixing ${string}\"\n          echo \"  command: sh -c \\\"${set_command}\\\"\"\n          echo \"  when: ${ansible_value}.rc == 1 and ansible_facts['ansible_system'] == '${os_name}'\"\n          echo \"\"\n        else\n          lock_command=\"${set_command}\" \n          lock_message=\"${string}\"\n          run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n        fi\n        for item in unlock ApplePay ; do\n          string=\"Touch ID ${item}\"\n          check_message  \"${string}\"\n          command=\"find /Users -maxdepth 1 | grep -vE \\\"localized|Shared\\\" | cut -f3 -d/\"\n          command_message   \"${command}\"\n          user_list=$( eval \"${command}\" )\n          for user_name in ${user_list}; do\n            command=\"sudo -u \\\"${user_name}\\\" bioutil -r -s | grep \\\"${item}\\\" | head -1 | cut -f2 -d: | sed \\\"s/ //g\\\" > /dev/null 2>&1\"\n            command_message     \"${command}\"\n            check_value=$( eval \"${command}\" )\n            if [ \"${check_value}\" = \"${touchid_timeout}\" ]; then\n              inc_secure   \"Touch ID Timeout for user \\\"${user_name}\\\" is set to \\\"${touchid_timeout}\\\"\"\n            else\n              inc_insecure \"Touch ID Timeout for for user \\\"${user_name}\\\" is not set to \\\"${touchid_timeout}\\\"\"\n            fi\n            if [ \"${ansible_mode}\" = 1 ]; then\n              echo \"\"\n              echo \"- name: Checking ${string} for ${user_name}\"\n              echo \"  command: sh -c \\\"sudo -u ${user_name} bioutil -r -s | grep ${item} | head -1 | cut -f2 -d: | sed 's/ //g'\\\"\"\n              echo \"  register: audit_touch_id_check\"\n              echo \"  failed_when: audit_touch_id_check != 1\"\n              echo \"  changed_when: false\"\n              echo \"  ignore_errors: true\"\n              echo \"  when: ansible_facts['ansible_system'] == '${os_name}'\"\n              echo \"\"\n              echo \"- name: Fixing ${string}\"\n              if [ \"${item}\" = \"unlock\" ]; then\n                echo \"  command: sh -c \\\"/usr/bin/sudo usr/bin/bioutil -w -u 1\\\"\"\n              else\n                echo \"  command: sh -c \\\"/usr/bin/sudo usr/bin/bioutil -w -a 1\\\"\"\n              fi\n              echo \"  when: audit_touch_id_check.rc == 1 and ansible_facts['ansible_system'] == '${os_name}'\"\n              echo \"\"\n            else\n              if [ \"${item}\" = \"unlock\" ]; then\n                lock_command=\"/usr/bin/sudo usr/bin/bioutil -w -u 1\"\n              else\n                lock_command=\"/usr/bin/sudo usr/bin/bioutil -w -s 1\"\n              fi\n            fi\n            lock_message=\"${string}\"\n            run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n          done\n        done\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_universal_control.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_universal_control\n#\n# Universal Control is an Apple feature that allows Mac users to control multiple other\n# Macs and iPads with the same keyboard, mouse, and trackpad using the same Apple\n# ID. The technology relies on already available iCloud services, particularly Handoff.\n#\n# Refer to Section(s) 2.8.1 Page(s) 194-7 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_universal_control () {\n  print_function \"audit_universal_control\"\n  string=\"Universal Control\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${long_os_version}\" -ge 1014 ]; then\n      if [ \"${my_id}\" != \"0\" ] && [ \"${use_sudo}\" = \"0\" ]; then\n        notice_message \"Requires sudo to check\"\n        return\n      fi\n      if [ \"${audit_mode}\" != 2 ]; then\n        command=\"find /Users -maxdepth 1 | grep -vE \\\"localized|Shared\\\" | cut -f3 -d/\"\n        command_message \"${command}\"\n        user_list=$( eval \"${command}\" )\n        for user_name in ${user_list}; do\n          for parameter in Disable DisableMagicEdges; do\n            check_osx_defaults_user \"com.apple.universalcontrol\" \"${parameter}\" \"1\" \"bool\" \"${user_name}\"\n          done\n        done\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_usage_data.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_usage_data\n#\n# Apple provides a mechanism to send diagnostic and analytics data back to Apple to\n# help them improve the platform. Information sent to Apple may contain internal\n# organizational information that should be controlled and not available for processing by\n# Apple. Turn off all Analytics and Improvements sharing.\n#\n# Refer to Section(s) 2.6.3 Page(s) 164-9 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_usage_data () {\n  print_function \"audit_usage_data\"\n  string=\"Usage Data\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${long_os_version}\" -ge 1014 ]; then\n      check_osx_defaults_bool \"Library/Application Support/CrashReporter/DiagnosticMessagesHistory.plist\"  \"AutoSubmit\"           \"0\"\n      check_osx_defaults_bool \"Library/Application Support/CrashReporter/DiagnosticMessagesHistory.plist\"  \"ThirdPartyDataSubmit\" \"0\"\n      check_file_perms        \"/Library/Application Support/CrashReporter/DiagnosticMessagesHistory.plist\" \"644\" \"root\" \"admin\"\n      check_message           \"Siri Data Sharing\"\n      if [ \"${my_id}\" != \"0\" ] && [ \"${use_sudo}\" = \"0\" ]; then\n        notice_message \"Requires sudo to check\"\n        return\n      fi\n      if [ \"${audit_mode}\" != 2 ]; then\n        command=\"find /Users -maxdepth 1 | grep -vE \\\"localized|Shared\\\" | cut -f3 -d/\"\n        command_message   \"${command}\"\n        user_list=$( eval \"${command}\" )\n        for user_name in ${user_list}; do\n          check_osx_defaults_user \"com.apple.assistant.support\" \"Siri Data Sharing Opt-In Status\" \"2\" \"int\" \"${user_name}\"\n        done\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_wake_on_lan.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_wake_on_lan\n#\n# Refer to Section(s) 2.5.1 Page(s) 26-7  CIS Apple OS X 10.8  Benchmark v1.0.0\n# Refer to Section(s) 2.5.1 Page(s) 50-1  CIS Apple OS X 10.12 Benchmark v1.0.0\n# Refer to Section(s) 2.9.3 Page(s) 212-6 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_wake_on_lan() {\n  print_function \"audit_wake_on_lan\"\n  string=\"Wake on Lan\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    check_pmset \"womp\" \"off\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_web_sharing.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_web_sharing\n#\n# Turn off web sharing\n#\n# Refer to Section(s) 1.4.14.7 Page(s) 55-6  CIS Apple OS X 10.7  Benchmark v1.0.0\n# Refer to Section(s) 4.4      Page(s) 101-2 CIS Apple OS X 10.12 Benchmark v1.0.0\n# Refer to Section(s) 4.2      Page(s) 292-3 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_web_sharing () {\n  print_function \"audit_web_sharing\"\n  string=\"Web sharing\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    check_file_value \"is\"   \"/etc/apache2/httpd.conf\" \"ServerTokens\"    \"space\" \"Prod\"     \"hash\"\n    check_file_value \"is\"   \"/etc/apache2/httpd.conf\" \"ServerSignature\" \"space\" \"Off\"      \"hash\"\n    check_file_value \"is\"   \"/etc/apache2/httpd.conf\" \"UserDir\"         \"space\" \"Disabled\" \"hash\"\n    check_file_value \"is\"   \"/etc/apache2/httpd.conf\" \"TraceEnable\"     \"space\" \"Off\"      \"hash\"\n    check_launchctl_service \"org.apache.httpd\"        \"off\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/darwin/audit_wireless.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_wireless\n#\n# Wireless checks\n#\n# Refer to Section(s) 4.2   Page(s) 98-9    CIS Apple OS X 10.12 Benchmark v1.0.0\n# Refer to Section(s) 3.1.2 Page(s) 177-9   CIS Ubuntu 22.04 Benchmark v1.0.0\n# Refer to Section(s) 3.1.2 Page(s) 357-60  CIS Ubuntu 24.04 Benchmark v1.0.0\n# Refer to Section(s) 2.4.1 Page(s) 133-6   CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_wireless () {\n  print_function \"audit_wireless\"\n  string=\"Wifi information menu\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${my_id}\" != \"0\" ] && [ \"${use_sudo}\" = \"0\" ]; then\n      notice_message \"Requires sudo to check\"\n      return\n    fi\n    if [ \"${os_name}\" = \"Darwin\" ] && [ \"${os_version}\" -ge 14 ]; then\n      command=\"find /Users -maxdepth 1 | grep -vE \\\"localized|Shared\\\" | cut -f3 -d/\"\n      command_message \"${command}\"\n      user_list=$( eval \"${command}\" )\n      for user_name in ${user_list}; do\n        check_osx_defaults_user \"com.apple.controlcenter.plist\" \"WiFi\" \"2\" \"int\" \"currentHost\" \"${user_name}\"\n      done\n    else\n      # answer=\"/System/Library/CoreServices/MenuExtras/AirPort.menu\"\n      command=\"defaults read com.apple.systemuiserver menuExtras 2> /dev/null | grep \\\"AirPort.menu\\\" | sed \\\"s/[ ,\\\\\\\",\\\\\\,]//g\\\" | grep -c \\\"AirPort\\\" |sed \\\"s/ //g\\\"\"\n      command_message \"${command}\"\n      check=$( eval   \"${command}\" )\n      if [ \"${check}\" = \"0\" ]; then\n        inc_secure   \"Wireless status menu is not enabled\"\n      else\n        inc_insecure \"Wireless status menu is enabled\"\n      fi\n    fi\n  else\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      command=\"command -v nmcli 2> /dev/null | sed \\\"s/ //g\\\"\"\n      command_message \"${command}\"\n      check=$( eval   \"${command}\" )\n      if [ \"${check}\" = \"1\" ]; then\n        command=\"nmcli radio all | grep -c enabled\"\n        command_message \"${command}\"\n        check=$( eval   \"${command}\" )\n      else\n        command=\"find /sys/class/net/*/ -type d -name wireless | wc -l | sed \\\"s/ //g\\\"\"\n        command_message \"${command}\"\n        check=$( eval   \"${command}\" )\n      fi\n      if [ \"${check}\" = \"0\" ]; then\n        inc_secure   \"Wireless is enabled\"\n      else\n        inc_insecure \"Wireless not enabled\"\n      fi\n    else\n      na_message \"${string}\"\n    fi\n  fi\n}\n"
  },
  {
    "path": "modules/dhcp/audit_dhcp_server.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_dhcp_server\n#\n# Check DHCP server\n#\n# Refer to Section(s) 3.5   Page(s) 61-2  CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 3.3   Page(s) 74    CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 3.5   Page(s) 64-5  CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 2.2.5 Page(s) 105   CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 6.4   Page(s) 54-5  CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 2.2.5 Page(s) 97    CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 2.2.5 Page(s) 105   CIS Ubuntu 16.04 Benchmark v1.0.0\n# Refer to Section(s) 2.1.3 Page(s) 234-6 CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_dhcp_server () {\n  print_function \"audit_dhcp_server\"\n  string=\"DHCP Server\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n        check_sunos_service \"svc:/network/dhcp-server:default\" \"disabled\"\n      fi\n    fi\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      check_linux_service \"isc-dhcp-server\"  \"off\"\n      check_linux_service \"isc-dhcp-server6\" \"off\"\n      check_linux_service \"dhcpd\"            \"off\"\n      check_linux_package \"uninstall\"        \"dhcpd\"\n      check_linux_package \"uninstall\"        \"isc-dhcp-server\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/dhcp/audit_dhcpcd.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_dhcpcd\n#\n# Check DHCP client\n#\n# Refer to Section(s) 1.3.8 Page(s) 43-4 CIS AIX Benchmark v1.1.0\n#.\n\naudit_dhcpcd () {\n  print_function \"audit_dhcpcd\"\n  string=\"DHCP Client Daemon\"\n  check_message  \"${string}\"\n  if [ \"${dhcpcd_disable}\" = \"yes\" ]; then\n    if [ \"${os_name}\" = \"AIX\" ]; then\n      check_rctcp \"dhcpcd\" \"off\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/dhcp/audit_dhcprd.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_dhcprd\n#\n# Check DHCP relay\n#\n# Refer to Section(s) 1.3.9 Page(s) 44-5 CIS AIX Benchmark v1.1.0\n#.\n\naudit_dhcprd () {\n  print_function \"audit_dhcprd\"\n  string=\"DHCP Relay Daemon\"\n  check_message  \"${string}\"\n  if [ \"${dhcprd_disable}\" = \"yes\" ]; then\n    if [ \"${os_name}\" = \"AIX\" ]; then\n      check_rctcp \"dhcprd\" \"off\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/dhcp/audit_dhcpsd.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_dhcpscd\n#\n# Check DHCP server\n#\n# Refer to Section(s) 1.3.10 Page(s) 45-6 CIS AIX Benchmark v1.1.0\n#.\n\naudit_dhcpsd () {\n  print_function \"audit_dhcpsd\"\n  string=\"DHCP Server Daemon\"\n  check_message  \"${string}\"\n  if [ \"${dhcpsd_disable}\" = \"yes\" ]; then\n    if [ \"${os_name}\" = \"AIX\" ]; then\n      check_rctcp \"dhcpsd\" \"off\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/dns/audit_dns_client.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_dns_client\n#\n# Turn off Name Server Caching Daemon\n#.\n\naudit_dns_client () {\n  print_function \"audit_dns_client\"\n  string=\"Name Server Caching Daemon\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    check_linux_service \"nscd\" \"off\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/dns/audit_dns_server.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_dns_server\n#\n# Refer to Section(s) 3.9     Page(s) 65-6    CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 3.9     Page(s) 77-8    CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 3.9     Page(s) 68      CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 2.2.8   Page(s) 108     CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 6.8     Page(s) 58      CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 3.6     Page(s) 11      CIS FreeBSD Benchmark v1.0.5\n# Refer to Section(s) 1.3.14  Page(s) 50-1    CIS AIX Benchmark v1.1.0\n# Refer to Section(s) 2.2.8   Page(s) 100     CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 2.2.8-9 Page(s) 108-9   CIS Ubuntu 16.04 Benchmark v1.0.0\n# Refer to Section(s) 2.1.4-5 Page(s) 237-41  CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_dns_server () {\n  print_function \"audit_dns_server\"\n  string=\"DNS Server\"\n  check_message  \"${string}\"\n  if [ \"${named_disable}\" = \"yes\" ]; then\n    if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"FreeBSD\" ]; then\n      verbose_message \"DNS Server\" \"check\"\n      if [ \"${os_name}\" = \"AIX\" ]; then\n        check_rctcp \"named\" \"off\"\n      fi\n      if [ \"${os_name}\" = \"SunOS\" ]; then\n        if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n          check_sunos_service \"svc:/network/dns/server:default\" \"disabled\"\n        fi\n      fi\n      if [ \"${os_name}\" = \"Linux\" ]; then\n        for service_name in dnsmasq named bind9; do\n          check_linux_service \"${service_name}\" \"off\"\n          check_linux_package \"uninstall\"    \"${service_name}\"\n        done\n        if [ \"${os_vendor}\" = \"CentOS\" ] || [ \"${os_vendor}\" = \"Red\" ] || [ \"${os_vendor}\" = \"Amazon\" ]; then\n          check_linux_package \"uninstall\"    \"bind\"\n        fi\n      fi\n      if [ \"${os_name}\" = \"FreeBSD\" ]; then\n        check_file_value \"is\" \"/etc/rc.conf\" \"named_enable\" \"eq\" \"NO\" \"hash\"\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/docker/audit_docker_daemon.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_docker_daemon\n#\n# Check that Docker daemon activities are audited\n#\n# Refer to Section(s) 1.5-13  Page(s) 18-35   CIS Docker Benchmark 1.13.0\n# Refer to Section(s) 2.4-13  Page(s) 41-58   CIS Docker Benchmark 1.13.0\n# Refer to Section(s) 2.14    Page(s) 60-1    CIS Docker Benchmark 1.13.0\n# Refer to Section(s) 2.18    Page(s) 67-8    CIS Docker Benchmark 1.13.0\n# Refer to Section(s) 2.20-3  Page(s) 70-5    CIS Docker Benchmark 1.13.0\n# Refer to Section(s) 3.1-20  Page(s) 77-104  CIS Docker Benchmark 1.13.0\n# Refer to Section(s) 5.10-1  Page(s) 142-5   CIS Docker Benchmark 1.13.0\n# Refer to Section(s) 5.14    Page(s) 150-1   CIS Docker Benchmark 1.13.0\n#\n# Refer to https://containerd.tools/\n# Refer to https://windsock.io/the-docker-proxy/\n# Refer to https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Security_Guide/chap-system_auditing.html\n# Refer to https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Security_Guide/chap-system_auditing.html\n# Refer to https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Security_Guide/chap-system_auditing.html\n# Refer to https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Security_Guide/chap-system_auditing.html\n# Refer to https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Security_Guide/chap-system_auditing.html\n# Refer to https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Security_Guide/chap-system_auditing.html\n# Refer to https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Security_Guide/chap-system_auditing.html\n# Refer to https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Security_Guide/chap-system_auditing.html\n# Refer to https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Security_Guide/chap-system_auditing.html\n# Refer to https://man7.org/linux/man-pages/man7/user_namespaces.7.html\n# Refer to https://github.com/twistlock/authz\n# Refer to https://github.com/docker/docker-registry/issues/612\n# Refer to https://github.com/docker/docker/issues/8093\n# Refer to https://github.com/docker/docker/issues/9015\n# Refer to https://github.com/docker/docker/issues/14856\n# Refer to https://github.com/docker/docker/issues/21050\n# Refer to https://github.com/docker/docker/issues/22741\n# Refer to https://github.com/docker/docker/issues/26713\n# Refer to https://github.com/docker/docker/pull/20662\n# Refer to https://github.com/docker/docker/pull/23213\n# Refer to https://github.com/docker/docker/pull/26276\n# Refer to https://github.com/docker/docker/pull/27223\n# Refer to https://github.com/opencontainers/runc\n# Refer to https://github.com/YungSang/fedora-atomic-packer/blob/master/oem/docker.socket\n# Refer to https://github.com/mstanleyjones/docker.github.io/blob/af7dfdba8504f9b102fb31a78cd08a06c33a8975/engine/swarm/swarm_manager_locking.md\n# Refer to https://docs.docker.com/registry/insecure/\n# Refer to https://docs.docker.com/articles/https/\n# Refer to https://docs.docker.com/engine/reference/commandline/daemon/#daemon-configuration-file\n# Refer to https://docs.docker.com/reference/commandline/cli/#daemon-storage-driver-option\n# Refer to https://docs.docker.com/engine/userguide/storagedriver/\n# Refer to https://docs.docker.com/engine/reference/commandline/daemon/\n# Refer to https://docs.docker.com/engine/reference/commandline/daemon/#default-ulimits\n# Refer to https://docs.docker.com/engine/reference/commandline/daemon/#storage-driver-options\n# Refer to https://docs.docker.com/engine/reference/commandline/daemon/#access- authorization\n# Refer to https://docs.docker.com/engine/extend/authorization/\n# Refer to https://docs.docker.com/registry/spec/api/\n# Refer to https://docs.docker.com/engine/userguide/networking/default_network/binding/\n# Refer to https://docs.docker.com/engine/admin/systemd/\n# Refer to https://docs.docker.com/articles/basics/#bind-docker-to-another-hostport-or-a-unix-socket\n# Refer to https://docs.docker.com/articles/certificates/\n# Refer to https://docs.docker.com/reference/commandline/cli/#insecure-registries\n# Refer to https://docs.docker.com/reference/commandline/cli/#daemon-socket-option\n# Refer to https://docs.docker.com/articles/basics/#bind-docker-to-another-hostport-or-a-unix-socket\n# Refer to https://docs.docker.com/engine/reference/commandline/daemon/#daemon-configuration-file\n# Refer to https://docs.docker.com/engine/admin/configuring/\n# Refer to https://docs.docker.com/articles/runmetrics/\n# Refer to https://docs.docker.com/reference/commandline/cli/#run\n# Refer to https://docs.docker.com/reference/commandline/cli/#restart-policies\n# Refer to https://www.slideshare.net/Docker/docker-registry-v2\n# Refer to https://goldmann.pl/blog/2014/09/11/resource-management-in-docker/\n# Refer to https://goldmann.pl/blog/2014/09/11/resource-management-in-docker/\n# Refer to https://muehe.org/posts/switching-docker-from-aufs-to-devicemapper/\n# Refer to https://daviddaeschler.com/2014/12/14/centos-7rhel-7-and-docker-containers-on-boot/\n# Refer to https://blog.docker.com/2015/07/new-tool-v1-registry-docker-trusted-registry-v2-open-source/\n# Refer to https://events.linuxfoundation.org/sites/events/files/slides/User%20Namespaces%20-%20ContainerCon%202015%20-%2016-9-final_0.pdf\n# Refer to https://daviddaeschler.com/2014/12/14/centos-7rhel-7-and-docker-containers-on-boot/\n# Refer to https://jpetazzo.github.io/assets/2015-03-05-deep-dive-into-docker-storage-drivers.html#1\n# Refer to https://the.binbashtheory.com/creating-private-docker-registry-2-0-with-token-authentication-service/\n#.\n\naudit_docker_daemon () {\n  print_function \"audit_docker_daemon\"\n  string=\"Docker Daemon\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"Darwin\" ]; then\n    docker_bin=$( command -v docker )\n    if [ \"${docker_bin}\" ]; then\n      check_file=\"/etc/audit/audit.rules\"\n      for docker_file in /usr/bin/docker /var/lib/docker /etc/docker /etc/default/docker /etc/docker/daemon.json /usr/bin/docker-containerd /usr/bin/docker-runc; do\n        check_auditctl    \"${docker_file}\" \"docker_file\"\n        check_append_file \"${check_file}\"  \"-w ${docker_file} -k docker\" \"hash\"\n      done\n      systemctl_check=$( command -v systemctl )\n      if [ \"${systemctl_check}\" ]; then\n        for docker_service in docker.service docker.socket; do\n          check_auditctl \"${docker_service}\" \"docker_service\"\n          docker_file=$( systemctl show -p FragmentPath ${docker_service} 2> /dev/null )\n          check_append_file \"${check_file}\" \"-w ${docker_file} -k docker\" \"hash\"\n          check_file_perms  \"${check_file}\" \"0640\" \"root\" \"root\"\n        done\n      fi\n      for check_file in /etc/docker /etc/docker/certs.d; do\n        check_file_perms ${check_file} 0750 root root\n      done\n      if [ -e \"/etc/docker/certs.d\" ]; then\n        file_list=$( find /etc/docker/certs.d/ -type f )\n        for check_file in ${file_list}; do\n          check_file_perms \"${check_file}\" \"440\" \"root\" \"root\"\n        done\n      fi\n      check_file_perms /var/run/docker.sock 660 root docker\n      for check_file in /etc/default/docker /etc/docker/daemon.json; do\n        check_file_perms \"${check_file}\" \"640\" \"root\" \"root\"\n      done\n      tlscert_file=\"\"\n      tlscacert_file=\"\"\n      tlskey_file=\"\"\n      for check_file in ${tlscert_file} ${tlscacert_file} ${tlskey_file}; do\n        check_file_perms \"${check_file}\" \"400\" \"root\" \"root\"\n      done\n      check_dockerd     \"unused\"      \"daemon\" \"insecure-registry\"        \"\"\n      check_dockerd     \"unused\"      \"daemon\" \"storage-driver\"           \"aufs\"\n      check_dockerd     \"unused\"      \"daemon\" \"net host\"                 \"\"\n      check_dockerd     \"unused\"      \"info\"   \"Storage Driver\"           \"aufs\"\n      check_dockerd     \"used\"        \"daemon\" \"tlsverify\"                \"\"\n      check_dockerd     \"used\"        \"daemon\" \"tlscacert\"                \"\"\n      check_dockerd     \"used\"        \"daemon\" \"tlscert\"                  \"\"\n      check_dockerd     \"used\"        \"daemon\" \"tlskey\"                   \"\"\n      check_dockerd     \"used\"        \"daemon\" \"default-ulimit\"           \"\"\n      check_dockerd     \"used\"        \"daemon\" \"cgroup-parent\"            \"\"\n      check_dockerd     \"used\"        \"daemon\" \"userns-remap\"             \"\"\n      check_file_exists \"/etc/subuid\" \"yes\"\n      check_file_exists \"/etc/subgid\" \"yes\"\n      check_dockerd     \"unused\"      \"daemon\" \"storage-opt\"\n      check_dockerd     \"used\"        \"daemon\" \"authorization-plugin\"     \"\"\n      check_dockerd     \"used\"        \"daemon\" \"disable-legacy-registry\"  \"\"\n      check_dockerd     \"used\"        \"daemon\" \"live-restore\"             \"\"\n      check_dockerd     \"used\"        \"daemon\" \"userland-proxy\"           \"false\"\n      check_dockerd     \"used\"        \"daemon\" \"seccomp-profile\"          \"\"\n      check_dockerd     \"unused\"      \"daemon\" \"experimental\"             \"\"\n      if [ \"${audit_mode}\" != 2 ]; then\n        check=$( docker swarm unlock-key 2> /dev/null )\n        if [ \"${check}\" = \"no unlock key is set\" ]; then\n          inc_insecure \"Docker swarm unlock is not set\"\n        else\n          inc_secure   \"Docker swarm unlock key is not set or swarm is not running\"\n        fi\n        check_dockerd   \"notequal\"    \"config\" \"Memory\"                   \"0\"\n        check_dockerd   \"notequal\"    \"config\" \"CpuShares\"                \"0\"\n        check_dockerd   \"notequal\"    \"config\" \"CpuShares\"                \"1024\"\n        check_dockerd   \"notequal\"    \"config\" \"RestartPolicy.Name\"       \"always\"\n        check_dockerd   \"equal\"       \"config\" \"RestartPolicy.Name\"       \"on-failure\"\n        check_dockerd   \"equal\"       \"config\" \"MaximumRetryCount\"        \"5\"\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/docker/audit_docker_logging.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_docker_logging\n#\n# Check Docker logging\n#\n# Refer to Section(s) 2.2  Page(s) 38   CIS Docker Benchmark 1.13.0\n# Refer to Section(s) 2.12 Page(s) 56-7 CIS Docker Benchmark 1.13.0\n#\n# Refer to https://docs.docker.com/engine/reference/commandline/daemon/\n# Refer to https://docs.docker.com/engine/admin/logging/overview/\n#.\n\naudit_docker_logging () {\n  print_function \"audit_docker_logging\"\n  string=\"Docker Logging\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    docker_bin=$( command -v docker )\n    if [ \"${docker_bin}\" ]; then\n      check_dockerd \"unused\" \"daemon\" \"log-level\"  \"info\"\n      check_dockerd \"used\"   \"daemon\" \"log-driver\" \"\"\n      check_dockerd \"used\"   \"daemon\" \"log-opt\"    \"\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/docker/audit_docker_monitoring.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_docker_monitoring\n#\n# Check Docker monitoring\n#\n# Refer to Section(s) 4.6  Page(s) 115 CIS Docker Benchmark 1.13.0\n# Refer to Section(s) 5.26 Page(s) 172 CIS Docker Benchmark 1.13.0\n#\n# Refer to https://github.com/docker/docker/pull/22719\n# Refer to https://github.com/docker/docker/pull/22719\n#.\n\naudit_docker_monitoring () {\n  print_function \"audit_docker_monitoring\"\n  string=\"Docker Healthcheck\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${audit_mode}\" != 2 ]; then\n      docker_bin=$( command -v docker )\n      if [ \"${docker_bin}\" ]; then\n        string=\"Docker Healthcheck\"\n        check_message  \"${string}\"\n        check_dockerd \"equal\" \"config\" \"Health\" \"\"\n        docker_ids=$( docker ps --quiet --all | xargs docker inspect --format '{{ .Id }}' 2> /dev/null )\n        for docker_id in ${docker_ids}; do\n          check=$( docker inspect --format='{{ .Config.Healthcheck }}' \"${docker_id}\" )\n          if [ ! \"${check}\" = \"<nil>\" ]; then\n            inc_secure   \"Docker instance \\\"${docker_id}\\\" has a Healthcheck instruction\"\n          else\n            inc_insecure \"Docker instance \\\"${docker_id}\\\" has no Healthcheck instruction\"\n          fi\n        done\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/docker/audit_docker_network.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_docker_network\n#\n# Check that Docker does not allow communication between containers\n#\n# Refer to Section(s) 2.1  Page(s) 36-7  CIS Docker Benchmark 1.13.0\n# Refer to Section(s) 2.3  Page(s) 39-40 CIS Docker Benchmark 1.13.0\n# Refer to Section(s) 2.19 Page(s) 69    CIS Docker Benchmark 1.13.0\n# Refer to Section(s) 5.13 Page(s) 148-9 CIS Docker Benchmark 1.13.0\n# Refer to Section(s) 5.29 Page(s) 177   CIS Docker Benchmark 1.13.0\n#\n# Refer to https://arxiv.org/pdf/1501.02967\n# Refer to https://github.com/nyantec/narwhal\n# Refer to https://github.com/docker/docker/issues/24253\n# Refer to https://docs.docker.com/articles/networking\n# Refer to https://docs.docker.com/engine/userguide/networking/overlay-security-model/\n# Refer to https://docs.docker.com/articles/networking/#binding-container-ports-to-the-host\n# Refer to https://docs.docker.com/engine/userguide/networking/dockernetworks/\n#.\n\naudit_docker_network () {\n  print_function \"audit_docker_network\"\n  string=\"Docker Network\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"Darwin\" ]; then\n    docker_bin=$( command -v docker )\n    if [ \"${docker_bin}\" ]; then\n      backup_file=\"network_bridge\"\n      new_state=\"false\"\n      old_state=\"true\"\n      if [ \"${audit_mode}\" != 2 ]; then\n        check_dockerd notequal config NetworkMode \"NetworkMode=host\"\n        check_dockerd notinclude config Ports \"0.0.0.0\"\n        docker_check=$( docker network ls --quiet | xargs docker network inspect --format '{{ .Name }}: {{ .Options }}' | grep 'docker0' )\n        if [ \"${docker_check}\" ]; then\n          inc_insecure \"Docker is using default bridge docker0\"\n        else\n          inc_secure   \"Docker is not using default bridge docker0\"\n        fi\n        docker_check=$( docker network ls --quiet | xargs docker network inspect --format '{{ .Name }}: {{ .Options }}' | grep 'com.docker.network.bridge.enable_icc' | grep \"${new_state}\" )\n        if [ ! \"${docker_check}\" ]; then\n          inc_insecure \"Traffic is allowed between containers\"\n          if [ \"${audit_mode}\" = 0 ]; then\n            log_file=\"${work_dir}/${backup_file}\"\n            echo \"${old_state}\" > \"${log_file}\"\n            set_message \"Docker network bridge enabled to \\\"${new_state}\\\"\"\n            eval \"/usr/bin/dockerd --icc=${new_state}\"\n          fi\n        else\n          inc_secure \"Traffic is not allowed between containers\"\n        fi\n      else\n        restore_file=\"${restore_dir}/${backup_file}\"\n        old_state=$( cat \"${restore_file}\" )\n        restore_message \"Docker network bridge enabled to \\\"${old_state}\\\"\"\n        eval \"/usr/bin/dockerd --icc=${old_state}\"\n      fi\n      check_dockerd \"unused\" \"daemon\" \"iptables\" \"true\"\n      check_dockerd \"used\"   \"daemon\" \"opt\"      \"encrypted\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/docker/audit_docker_security.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_docker_security\n#\n# Docker security\n#\n# Refer to Section(s) 2.8     Page(s) 49-50   CIS Docker Benchmark 1.13.0\n# Refer to Section(s) 5.1-4   Page(s) 126-32  CIS Docker Benchmark 1.13.0\n# Refer to Section(s) 5.9     Page(s) 141     CIS Docker Benchmark 1.13.0\n# Refer to Section(s) 5.12    Page(s) 146-7   CIS Docker Benchmark 1.13.0\n# Refer to Section(s) 5.15-7  Page(s) 152-9   CIS Docker Benchmark 1.13.0\n# Refer to Section(s) 5.19-25 Page(s) 160-71  CIS Docker Benchmark 1.13.0\n# Refer to Section(s) 5.28    Page(s) 175-6   CIS Docker Benchmark 1.13.0\n# Refer to Section(s) 5.30    Page(s) 178     CIS Docker Benchmark 1.13.0\n# Refer to Section(s) 5.31    Page(s) 179     CIS Docker Benchmark 1.13.0\n#\n# Refer to https://lwn.net/Articles/475678/\n# Refer to https://lwn.net/Articles/475362/\n# Refer to https://docs.docker.com/articles/networking/#how-docker-networks-a-container\n# Refer to https://docs.docker.com/articles/security/#linux-kernel-capabilities\n# Refer to https://docs.docker.com/articles/security/#other-kernel-security-features\n# Refer to https://docs.docker.com/engine/security/apparmor/\n# Refer to https://docs.docker.com/engine/reference/commandline/run/\n# Refer to https://docs.docker.com/engine/reference/commandline/run/#/run\n# Refer to https://docs.docker.com/engine/security/seccomp/\n# Refer to https://docs.docker.com/engine/reference/commandline/exec/\n# Refer to https://docs.docker.com/engine/reference/run/#specifying-custom-cgroups\n# Refer to https://docs.docker.com/engine/reference/run/\n# Refer to https://docs.docker.com/reference/run/#security-configuration\n# Refer to https://docs.docker.com/reference/run/#security-configuration\n# Refer to https://docs.docker.com/reference/commandline/cli\n# Refer to https://docs.docker.com/reference/commandline/cli/#run\n# Refer to https://docs.docker.com/reference/run/#pid-settings\n# Refer to https://docs.docker.com/reference/run/#pid-settings\n# Refer to https://docs.docker.com/reference/commandline/cli/#run\n# Refer to https://docs.docker.com/reference/commandline/cli/#setting-ulimits-in-a-container\n# Refer to https://docs.docker.com/engine/reference/commandline/daemon/\n# Refer to https://docs.fedoraproject.org/en-US/Fedora/13/html/Security-Enhanced_Linux/\n# Refer to https://github.com/docker/docker/blob/master/docs/security/apparmor.md\n# Refer to https://github.com/docker/docker/blob/master/daemon/execdriver/native/template/default_template.go\n# Refer to https://github.com/docker/docker/blob/master/profiles/seccomp/default.json\n# Refer to https://github.com/docker/docker/issues/6401\n# Refer to https://github.com/docker/docker/issues/21050\n# Refer to https://github.com/docker/docker/issues/21109\n# Refer to https://github.com/docker/docker/issues/22870\n# Refer to https://github.com/docker/docker/pull/12648\n# Refer to https://github.com/docker/docker/pull/17034\n# Refer to https://github.com/docker/docker/pull/18697\n# Refer to https://github.com/docker/docker/pull/20727\n# Refer to https://github.com/projectatomic/atomic-site/issues/269 \n# Refer to https://man7.org/linux/man-pages/man7/capabilities.7.html\n# Refer to https://man7.org/linux/man-pages/man7/pid_namespaces.7.html\n# Refer to https://man7.org/linux/man-pages/man7/user_namespaces.7.html\n# Refer to https://man7.org/linux/man-pages/man7/namespaces.7.html\n# Refer to https://www.oreilly.com/webops-perf/free/files/docker-security.pdf\n# Refer to https://www.oreilly.com/webops-perf/free/files/docker-security.pdf\n# Refer to https://www.kernel.org/doc/Documentation/filesystems/sharedsubtree.txt\n# Refer to https://www.kernel.org/doc/Documentation/prctl/no_new_privs.txt\n# Refer to https://www.kernel.org/doc/Documentation/prctl/seccomp_filter.txt\n# Refer to https://blog.scalock.com/new-docker-security-features-and-what-they-mean-seccomp-profiles\n# Refer to https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Resource_Management_Guide/ch01.html\n# Refer to https://events.linuxfoundation.org/sites/events/files/slides/User%20Namespaces%20-%20ContainerCon%202015%20-%2016-9-final_0.pdf\n# Refer to https://events.linuxfoundation.org/sites/events/files/slides/User%20Namespaces%20-%20ContainerCon%202015%20-%2016-9-final_0.pdf\n# Refer to https://raesene.github.io/blog/2016/03/06/The-Dangers-Of-Docker.sock/\n# Refer to https://forums.docker.com/t/docker-in-docker-vs-mounting-var-run-docker-sock/9450/2\n#.\n\naudit_docker_security () {\n  print_function \"audit_docker_security\"\n  string=\"Docker Security\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"Darwin\" ]; then\n    docker_bin=$( command -v docker )\n    if [ \"${docker_bin}\" ]; then\n      check_dockerd   \"notequal\"  \"config\"  \"SecurityOpt\"     \"<no value>\"\n      check_dockerd   \"include\"   \"config\"  \"SecurityOpt\"     \"userns\"\n      check_dockerd   \"include\"   \"config\"  \"SecurityOpt\"     \"no-new-privileges\"\n      check_dockerd   \"equal\"     \"config\"  \"Privileged\"      \"false\"\n      check_dockerd   \"notequal\"  \"config\"  \"AppArmorProfile\" \"\"\n      check_dockerd   \"equal\"     \"config\"  \"ReadonlyRootfs\"  \"true\"\n      check_dockerd   \"notequal\"  \"config\"  \"PidMode\"         \"host\"\n      check_dockerd   \"notequal\"  \"config\"  \"IpcMode\"         \"host\"\n      check_dockerd   \"notequal\"  \"config\"  \"UsernsMode\"      \"host\"\n      check_dockerd   \"equal\"     \"config\"  \"Devices\"         \"\"\n      check_dockerd   \"equal\"     \"config\"  \"Ulimits\"         \"<no value>\"\n      check_dockerd   \"notequal\"  \"config\"  \"Propagation\"     \"shared\"\n      check_dockerd   \"notequal\"  \"config\"  \"UTSMode\"         \"shared\"\n      check_ausearch  \"equal\"     \"docker\"  \"exec\"            \"privileged\" \"\"\n      check_ausearch  \"equal\"     \"docker\"  \"exec\"            \"user\"       \"\"\n      check_dockerd   \"equal\"     \"config\"  \"CgroupParent\"    \"\"\n      check_dockerd   \"notequal\"  \"config\"  \"PidsLimit\"       \"0\"\n      check_dockerd   \"notequal\"  \"config\"  \"PidsLimit\"       \"-1\"\n      for param in NET_ADMIN SYS_ADMIN SYS_MODULE; do\n        check_dockerd unused kernel ${param}\n      done\n      if [ \"${audit_mode}\" != 2 ]; then\n        docker_check=$( docker ps --quiet --all | xargs docker inspect --format '{{ .Id }}: Volumes={{ .Mounts }}' | grep docker.sock )\n        if [ \"${docker_check}\" ]; then\n          inc_insecure \"Docker socket is mounted inside a container\"\n        else\n          inc_secure   \"Docker socket is not mounted inside a container\"\n        fi\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/docker/audit_docker_users.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_docker_users\n#\n# Check users in docker group have recently logged in, if not lock them\n# Warn of any users in group with UID greate than 100 and lock\n#\n# Refer to Section(s) 1.4 Page(s) 16-7  CIS Docker Benchmark 1.13.0\n# Refer to Section(s) 4.1 Page(s) 105-6 CIS Docker Benchmark 1.13.0\n#\n# Refer to https://github.com/docker/docker/issues/2918\n# Refer to https://github.com/docker/docker/pull/4572\n# Refer to https://github.com/docker/docker/issues/7906\n# Refer to https://www.altiscale.com/hadoop-blog/making-docker-work-yarn/\n# Refer to https://docs.docker.com/articles/security/\n# Refer to https://docs.docker.com/articles/security/#docker-daemon-attack-surface\n# Refer to https://www.andreas-jung.com/contents/on-docker-security-docker-group-considered-harmful\n# Refer to https://www.projectatomic.io/blog/2015/08/why-we-dont-let-non-root-users-run-docker-in-centos-fedora-or-rhel/\n#.\n\naudit_docker_users () {\n  print_function \"audit_docker_users\"\n  string=\"Docker Users\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"Darwin\" ]; then\n    docker_bin=$( command -v docker )\n    if [ \"${docker_bin}\" ]; then\n      check_file=\"/etc/group\"\n      if [ \"${audit_mode}\" != 2 ]; then\n        user_list=$( grep \"^${docker_group}:\" \"${check_file}\" | cut -f4 -d: | sed 's/,/ /g' )\n        for user_name in ${user_list}; do\n          last_login=$( last -1 \"${user_name}\" | grep '[a-z]' | awk '{print $1}' )\n          if [ \"${last_login}\" = \"wtmp\" ]; then\n            if test -r \"/etc/shadow\"; then\n              lock_test=$( grep \"^${user_name}:\" /etc/shadow | grep -v 'LK' | cut -f1 -d: )\n              if [ \"${lock_test}\" = \"${user_name}\" ]; then\n                if [ \"${audit_mode}\" = 1 ]; then\n                  inc_insecure \"User \\\"${user_name}\\\" in group \\\"${docker_group}\\\" and has not logged in recently and their account is not locked\"\n                fi\n                if [ \"${audit_mode}\" = 0 ]; then\n                  backup_file \"${check_file}\"\n                  set_message \"User \\\"${user_name}\\\" to locked\"\n                  passwd -l \"${user_name}\"\n                fi\n              else\n                inc_secure \"User \\\"${user_name}\\\" in group \\\"${docker_group}\\\" has not logged in recently and their account is locked\"\n              fi\n            fi\n          fi\n        done\n      else\n        restore_file \"${check_file}\" \"${restore_dir}\"\n      fi\n      if [ \"${audit_mode}\" != 2 ]; then\n        user_list=$( grep \"^${docker_group}:\" \"${check_file}\" | cut -f4 -d: | sed 's/,/ /g' )\n        for user_name in ${user_list}; do\n          user_id=$( uid -u \"${user_name}\" )\n          if [ \"${user_id}\" -gt \"${max_super_user_id}\" ] ; then\n            if test -r \"/etc/shadow\"; then\n              lock_test=$( grep \"^${user_name}:\" /etc/shadow | grep -v 'LK' | cut -f1 -d: )\n              if [ \"${lock_test}\" = \"${user_name}\" ]; then\n                if [ \"${audit_mode}\" = 1 ]; then\n                  inc_insecure \"User \\\"${user_name}\\\" is in group \\\"${docker_group}\\\" has and ID greater than \\\"${max_super_user_id}\\\" and their account is not locked\"\n                fi\n                if [ \"${audit_mode}\" = 0 ]; then\n                  backup_file  \"${check_file}\"\n                  set_message  \"User \\\"${user_name}\\\" to locked\"\n                  passwd -l \"${user_name}\"\n                fi\n              else\n                inc_secure \"User \\\"${user_name}\\\" in group \\\"${docker_group}\\\" has an id less than \\\"${max_super_user_id}\\\" and their account is locked\"\n              fi\n            fi\n          fi\n        done\n      else\n        restore_file \"${check_file}\" \"${restore_dir}\"\n      fi\n      if [ \"${audit_mode}\" != 2 ]; then\n        check_dockerd \"notequal\" \"config\" \"User\" \"\"\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/esxi/audit_dcui.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_dcui\n#\n# Check DCUI\n#\n# Refer to http://pubs.vmware.com/vsphere-55/topic/com.vmware.vsphere.security.doc/GUID-6779F098-48FE-4E22-B116-A8353D19FF56.html\n#.\n\naudit_dcui () {\n  print_function \"audit_dcui\"\n  string=\"DCUI\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"VMkernel\" ]; then\n    service_name=\"DCUI\"\n    verbose_message     \"${service_name} Lockdown\" \"check\"\n    check_linux_service \"${service_name}\" \"off\"\n    backup_file=\"${work_dir}/dvfilter\"\n    command=\"vim-cmd -U dcui vimsvc/auth/lockdown_is_enabled\"\n    command_message \"${command}\"\n    current_value=$( eval \"${command}\" )\n    if [ \"${audit_mode}\" != \"2\" ]; then\n      if [ \"${current_value}\" != \"true\" ]; then\n        if [ \"${audit_mode}\" = \"0\" ]; then\n          echo \"${current_value}\" > \"${backup_file}\"\n          set_message \"DCUI Lockdown to true\"\n          command=\"vim-cmd -U dcui vimsvc/auth/lockdown_mode_enter\"\n          command_message \"${command}\"\n          eval \"${command}\"\n        fi\n        if [ \"${audit_mode}\" = \"1\" ]; then\n          inc_insecure \"DCUI Lockdown is disabled\"\n          fix_message  \"vim-cmd -U dcui vimsvc/auth/lockdown_mode_enter\"\n        fi\n      else\n        if [ \"${audit_mode}\" = \"1\" ]; then\n          inc_secure   \"DCUI Lockdown is enabled\"\n        fi\n      fi\n    else\n      restore_file=\"${restore_dir}/$test\"\n      if [ -f \"${restore_file}\" ]; then\n        previous_value=$( cat \"${restore_file}\" )\n        if [ \"${previous_value}\" != \"${current_value}\" ]; then\n          verbose_message \"DCUI Lockdown to ${previous_value}\" \"restore\"\n          if [ \"${previous_value}\" = \"true\" ]; then\n            command=\"vim-cmd -U dcui vimsvc/auth/lockdown_mode_enter\"\n            command_message \"${command}\"\n            eval \"${command}\"\n          else\n            command=\"vim-cmd -U dcui vimsvc/auth/lockdown_mode_exit\"\n            command_message \"${command}\"\n            eval \"${command}\"\n          fi\n        fi\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/esxi/audit_dvfilter.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_dvfilter\n#\n# Check Dvfilter\n#\n# Refer to http://pubs.vmware.com/vsphere-55/topic/com.vmware.vsphere.ext_solutions.doc/GUID-6013E15D-92CE-4970-953C-ACCB36ADA8AD.html\n# Refer to http://pubs.vmware.com/vsphere-55/topic/com.vmware.vsphere.security.doc/GUID-CD0783C9-1734-4B9A-B821-ED17A77B0206.html\n#.\n\naudit_dvfilter () {\n  print_function \"audit_dvfilter\"\n  string=\"Dvfilter\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"VMkernel\" ]; then\n    backup_file=\"${work_dir}/dvfilter\"\n    command=\"esxcli --formatter=csv --format-param=fields=Path,Int Value system settings advanced list | grep /Net/DVFilterBindIpAddress | cut -f2 -d,\"\n    command_message \"${command}\"\n    current_value=$( eval \"${command}\" )\n    if [ \"${audit_mode}\" != \"2\" ]; then\n      if [ \"${current_value}\" != \"0\" ]; then\n        if [ \"${audit_mode}\" = \"0\" ]; then\n          echo \"${current_value}\" > \"${backup_file}\"\n          set_message \"Dvfilter to disabled\"\n          command=\"esxcli system settings advanced set -o /Net/DVFilterBindIpAddress -d\"\n          command_message \"${command}\"\n          eval \"${command}\"\n        fi\n        if [ \"${audit_mode}\" = \"1\" ]; then\n          inc_insecure \"Dvfilter enabled\"\n          fix_message  \"esxcli system settings advanced set -o /Net/DVFilterBindIpAddress -d\"\n        fi\n      else\n        if [ \"${audit_mode}\" = \"1\" ]; then\n          inc_secure   \"Dvfilter disabled\"\n        fi\n      fi\n    else\n      restore_file=\"${restore_dir}/dvfilter\"\n      if [ -f \"${restore_file}\" ]; then\n        previous_value=$( cat \"${restore_file}\" )\n        if [ \"${previous_value}\" != \"${current_value}\" ]; then\n          restore_message \"Dvfilter to \\\"${previous_value}\\\"\"\n          command=\"esxcli system settings advanced set -o /Net/DVFilterBindIpAddress -i \\\"${previous_value}\\\"\"\n          command_message \"${command}\"\n          eval \"${command}\"\n        fi\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/esxi/audit_esxi_shell.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_esxi_shell\n#\n# Check ESXi Shell\n#\n# Refer to http://kb.vmware.com/kb/2004746\n# Refer to http://pubs.vmware.com/vsphere-55/topic/com.vmware.vsphere.security.doc/GUID-B5144CE9-F8BB-494D-8F5D-0D5621D65DAE.html\n#.\n\naudit_esxi_shell () {\n  print_function \"audit_esxi_shell\"\n  string=\"ESXShell\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"VMkernel\" ]; then\n    check_linux_service \"ESXShell\" \"off\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/esxi/audit_mob.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_mob\n#\n# Check Managed Object Browser\n# \n# Refer to http://pubs.vmware.com/vsphere-51/index.jsp?topic=%2Fcom.vmware.vsphere.security.doc%2FGUID-0EF83EA7-277C-400B-B697-04BDC9173EA3.html\n#.\n\naudit_mob () {\n  print_function \"audit_mob\"\n  string=\"Managed Object Browser\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"VMkernel\" ]; then\n    log_file=\"mob_status\"\n    backup_file=\"${work_dir}/${log_file}\"\n    command=\"vim-cmd proxysvc/service_list | grep \\\"/mob\\\" | awk '{print \\$3}' | cut -f1 -d, | sed 's/\\\"//g'\"\n    command_message \"${command}\"\n    current_value=$( eval \"${command}\" )\n    if [ \"${current_value}\" = \"/mob\" ]; then\n      current_value=\"enabled\"\n    else\n      current_value=\"disabled\"\n    fi\n    if [ \"${audit_mode}\" != \"2\" ]; then\n      if [ \"${current_value}\" != \"disabled\" ]; then\n        if [ \"${audit_mode}\" = \"0\" ]; then\n          if [ \"${syslog_server}\" != \"\" ]; then\n            echo \"enabled\" > \"${backup_file}\"\n            set_message \"Managed Object Browser to disabled\"\n            command=\"vim-cmd proxysvc/remove_service \\\"/mob\\\" \\\"httpsWithRedirect\\\"\"\n            command_message \"${command}\"\n            eval \"${command}\"\n          fi\n        fi\n        if [ \"${audit_mode}\" = \"1\" ]; then\n          inc_insecure \"Managed Object Browser enabled\"\n          fix_message  \"vim-cmd proxysvc/remove_service \\\"/mob\\\" \\\"httpsWithRedirect\\\"\"\n        fi\n      else\n        if [ \"${audit_mode}\" = \"1\" ]; then\n          inc_secure  \"Managed Object Browser disabled\"\n        fi\n      fi\n    else\n      restore_file=\"${restore_dir}/${log_file}\"\n      if [ -f \"${restore_file}\" ]; then\n        previous_value=$( cat \"${restore_file}\" )\n        if [ \"${previous_value}\" = \"enabled\" ]; then\n          restore_message \"Managed Object Browser to enabled\"\n          command=\"vim-cmd proxysvc/add_np_service \\\"/mob\\\" httpsWithRedirect /var/run/vmware/proxy-mob\"\n          command_message \"${command}\"\n          eval \"${command}\"\n        fi\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/firewall/audit_firewall_setting.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_firewall_setting\n#\n# Apple's firewall will protect your computer from certain incoming attacks.\n# Apple offers three firewall options: Allow all, Allow only essential, and\n# Allow access for specific incoming connections. Unless you have a specific\n# need to allow incoming connection (for services such as SSH, file sharing,\n# or web services), set the firewall to \"Allow only essential services,\"\n# otherwise use the \"allow access for specific incoming connections\" option.\n#\n# 0 = off\n# 1 = on for specific services\n# 2 = on for essential services\n#\n# Refer to Section(s) 2.6.4       Page(s)            CIS Apple OS X 10.8  Benchmark v1.0.0\n# Refer to Section(s) 2.6.3       Page(s) 56-7       CIS Apple OS X 10.12 Benchmark v1.0.0\n# Refer to Section(s) 2.2.1-2,3.6 Page(s) 60-9,283-6 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_firewall_setting () {\n  print_function \"audit_firewall_setting\"\n  string=\"Firewall Settings\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    check_osx_defaults_int \"/Library/Preferences/com.apple.alf\" \"globalstate\" \"1\"\n    if [ \"${audit_mode}\" != 2 ]; then\n     \tcommand=\"sudo /usr/libexec/ApplicationFirewall/socketfilterfw --getstealthmode | grep -cE \\\"enabled|on\\\" | sed \\\"s/ //g\\\"\"\n      command_message \"${command}\"\n      check=$( eval   \"${command}\" )\n      if [ \"${check}\" = \"1\" ]; then\n        inc_secure    \"Firewall stealth mode enabled\"\n      else\n        inc_insecure  \"Firewall stealth mode is not enabled\"\n        run_lockdown  \"sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setstealthmode on\"     \"Stealth mode on\"\n      fi\n      command=\"sudo /usr/libexec/ApplicationFirewall/socketfilterfw --getloggingmode | grep -cE \\\"enabled|on\\\" | sed \\\"s/ //g\\\"\"\n      command_message \"${command}\"\n      check=$( eval   \"${command}\" )\n      if [ \"${check}\" = \"1\" ]; then\n        inc_secure    \"Firewall logging mode enable\"\n      else\n        inc_insecure  \"Firewall logging mode is not enabled\"\n        run_lockdown \"sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setloggingmode on\"     \"Logging mode on\"\n      fi\n      command=\"sudo /usr/libexec/ApplicationFirewall/socketfilterfw --getloggingopt | grep -c detail | sed \\\"s/ //g\\\"\"\n      command_message \"${command}\"\n      check=$( eval   \"${command}\" )\n      if [ \"${check}\" = \"1\" ]; then\n        inc_secure    \"Firewall logging option detailed\"\n      else\n        inc_insecure  \"Firewall logging option is not detailed\"\n        run_lockdown  \"sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setloggingopt detail\"  \"Logging output detail\"\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/firewall/audit_ipfilter.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_ipfilter\n#\n# Turn off IP filter\n#.\n\naudit_ipfilter () {\n  print_function \"audit_ipfilter\"\n  string=\"IP Filter\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n      check_sunos_service \"svc:/network/ipfilter:default\" \"disabled\"\n      check_sunos_service \"svc:/network/pfil:default\"     \"disabled\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/firewall/audit_ipfw.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_ipfw\n#\n# Check IP Firewall\n#\n# Refer to Section 1.3 Page(s) 3-4 CIS FreeBSD Benchmark v1.0.5\n#.\n\naudit_ipfw () {\n  print_function \"audit_ipfw\"\n  string=\"IP Firewall\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"FreeBSD\" ]; then\n    check_file_value \"is\" \"/etc/rc.conf\"  \"firewall_enable\" \"eq\" \"YES\"    \"hash\"\n    check_file_value \"is\" \"/etc/rc.conf\"  \"firewall_type\"   \"eq\" \"client\" \"hash\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/firewall/audit_ipsec.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_ipsec\n#\n# Turn off IPSEC\n#.\n\naudit_ipsec () {\n  print_function \"audit_ipsec\"\n  string=\"IPSEC Services\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n      check_sunos_service \"svc:/network/ipsec/manual-key:default\" \"disabled\"\n      check_sunos_service \"svc:/network/ipsec/ike:default\"        \"disabled\"\n      check_sunos_service \"svc:/network/ipsec/ipsecalgs:default\"  \"disabled\"\n      check_sunos_service \"svc:/network/ipsec/policy:default\"     \"disabled\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/firewall/audit_iptables.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_iptables\n#\n# Turn on iptables\n#\n# Refer to Section(s) 5.7-8   Page(s) 114-8  CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 4.7-8   Page(s) 101-3  CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 4.7-8   Page(s) 92-3   CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 3.6.1   Page(s) 153-4  CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 3.6.1   Page(s) 139-40 CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 3.6.1-3 Page(s) 149-52 CIS Ubuntu 16.04 Benchmark v1.0.0\n#.\n\naudit_iptables () {\n  print_function \"audit_iptables\"\n  string=\"IP Tables\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    check_linux_package \"install\"   \"iptables\"\n    check_linux_service \"iptables\"  \"on\"\n    check_linux_service \"ip6tables\" \"on\"\n    if [ \"${audit_mode}\" != 2 ]; then\n      iptables_check=$( command -v iptables 2> /dev/null )\n      if [ \"${iptables_check}\" ]; then\n        if [ \"${my_id}\" = \"0\" ]; then\n          command=\"iptables -L INPUT -v -n | grep \\\"127.0.0.0\\\" | grep \\\"0.0.0.0\\\" | grep DROP | uniq | wc -l | sed \\\"s/ //g\\\"\"\n          command_message \"${command}\"\n          rules_check=$( eval \"${command}\" )\n        fi\n        if [ \"${rules_check}\" = \"0\" ]; then\n          inc_insecure \"All other devices allow trafic to the loopback network\"\n        else\n          inc_secure   \"All other devices deny trafic to the loopback network\"\n        fi\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/firewall/audit_routing_daemons.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_routing_daemons\n#\n# Turn off routing services if not required\n#\n# AIX:\n#\n# Refer to Section(s) 1.3.12-3,5 Page(s) 47-50,51-2 CIS AIX Benchmark v1.1.0\n#.\n\naudit_routing_daemons () {\n  print_function \"audit_routing_daemons\"\n  string=\"Routing Daemons\"\n  check_message  \"${string}\"\n  if [ \"$routed_disable\" = \"yes\" ]; then\n    if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"AIX\" ]; then\n      if [ \"${os_name}\" = \"SunOS\" ]; then\n        if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n          for service_name in \"svc:/network/routing/zebra:quagga\" \\\n            \"svc:/network/routing/ospf:quagga\" \\\n            \"svc:/network/routing/rip:quagga\" \\\n            \"svc:/network/routing/ripng:default\" \\\n            \"svc:/network/routing/ripng:quagga\" \\\n            \"svc:/network/routing/ospf6:quagga\" \\\n            \"svc:/network/routing/bgp:quagga\" \\\n            \"svc:/network/routing/legacy-routing:ipv4\" \\\n            \"svc:/network/routing/legacy-routing:ipv6\" \\\n            \"svc:/network/routing/rdisc:default\" \\\n            \"svc:/network/routing/route:default\" \\\n            \"svc:/network/routing/ndp:default\"; do\n            check_sunos_service \"${service_name}\" \"disabled\"\n          done\n        fi\n      fi\n      if [ \"${os_name}\" = \"Linux\" ]; then\n        for service_name in bgpd ospf6d ospfd ripd ripngd; do\n          check_linux_service \"${service_name}\" \"off\"\n        done\n      fi\n    fi\n    if [ \"${os_name}\" = \"AIX\" ]; then\n      for service_name in gated mrouted routed; do\n        check_rctcp \"${service_name}\" \"off\"\n      done\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/firewall/audit_routing_params.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_routing_params\n#\n# Network Routing\n# Source Packet Forwarding\n# Directed Broadcast Packet Forwarding\n# Response to ICMP Timestamp Requests\n# Response to ICMP Broadcast Timestamp Requests\n# Response to ICMP Broadcast Netmask Requests\n# Response to Broadcast ICMPv4 Echo Request\n# Response to Multicast Echo Request\n# Ignore ICMP Redirect Messages\n# Strict Multihoming\n# ICMP Redirect Messages\n# TCP Reverse IP Source Routing\n# Maximum Number of Half-open TCP Connections\n# Maximum Number of Incoming Connections\n#\n# Refer to Section(s) 3.4-17 Page(s) 28-39 CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 3.5    Page(s) 64-5  CIS Solaris 10 Benchmark v5.1.0\n#.\n\naudit_routing_params () {\n  print_function \"audit_routing_params\"\n  string=\"Routing Parameters\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n      check_message       \"IP Routing\"\n      check_command_value \"routeadm\"       \"ipv4-routing\"       \"disabled\"\n      check_command_value \"routeadm\"       \"ipv6-routing\"       \"disabled\"\n      check_message       \"IP Forwarding\"\n      check_command_value \"routeadm\"       \"ipv4-forwarding\"    \"disabled\"\n      check_command_value \"routeadm\"       \"ipv6-forwarding\"    \"disabled\"\n      check_file_exists   \"/etc/notrouter\" \"yes\"\n    fi\n    if [ \"${os_version}\" = \"11\" ]; then\n      check_message       \"IP Routing\"\n      audit_ipadm_value   \"_forward_src_routed\"                 \"ipv4\" \"0\"\n      audit_ipadm_value   \"_forward_src_routed\"                 \"ipv6\" \"0\"\n      audit_ipadm_value   \"_rev_src_routes\"                     \"tcp\"  \"0\"\n      check_message       \"Broadcasting\"\n      audit_ipadm_value   \"_forward_directed_broadcasts\"        \"ip\"   \"0\"\n      audit_ipadm_value   \"_respond_to_timestamp\"               \"ip\"   \"0\"\n      audit_ipadm_value   \"_respond_to_timestamp_broadcast\"     \"ip\"   \"0\"\n      audit_ipadm_value   \"_respond_to_address_mask_broadcast\"  \"ip\"   \"0\"\n      audit_ipadm_value   \"_respond_to_echo_broadcast\"          \"ip\"   \"0\"\n      check_message       \"Multicasting\"\n      audit_ipadm_value   \"_respond_to_echo_multicast\"          \"ipv4\" \"0\"\n      audit_ipadm_value   \"_respond_to_echo_multicast\"          \"ipv6\" \"0\"\n      check_message       \"IP Redirecting\"\n      audit_ipadm_value   \"_ignore_redirect\"                    \"ipv4\" \"1\"\n      audit_ipadm_value   \"_ignore_redirect\"                    \"ipv6\" \"1\"\n      audit_ipadm_value   \"_send_redirects\"                     \"ipv4\" \"0\"\n      audit_ipadm_value   \"_send_redirects\"                     \"ipv6\" \"0\"\n      check_message       \"Multihoming\"\n      audit_ipadm_value   \"_strict_dst_multihoming\"             \"ipv4\" \"1\"\n      audit_ipadm_value   \"_strict_dst_multihoming\"             \"ipv6\" \"1\"\n      check_message       \"Queue Sizing\"\n      audit_ipadm_value   \"_conn_req_max_q0\"                    \"tcp\"  \"4096\"\n      audit_ipadm_value   \"_conn_req_max_q\"                     \"tcp\"  \"1024\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/firewall/audit_suse_firewall.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_suse_firewall\n#\n# Check SuSE Firewall enabled\n#\n# Refer to Section(s) 7.7 Page(s) 83-4 SLES 11 Benchmark v1.0.0\n#.\n\naudit_suse_firewall () {\n  print_function \"audit_suse_firewall\"\n  string=\"SuSE Firewall\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${os_vendor}\" = \"SuSE\" ]; then\n      check_linux_service \"SuSEfirewall2_init\"  \"on\"\n      check_linux_service \"SuSEfirewall2_setup\" \"on\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/firewall/audit_ufw.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_ufw\n#\n# Chec UFW is enabled\n#\n# Refer to Section(s) 3.5.1.1-3 Page(s) 216-20 CIS Ubuntu 22.04 Benchmark v1.0.0\n# Refer to Section(s) 4.2.1-7   Page(s) 447-56 CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_ufw () {\n  print_function \"audit_ufw\"\n  string=\"UFW\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ] && [ \"${os_vendor}\" = \"Ubuntu\" ]; then\n    check_linux_package \"install\"   \"ufw\"\n    check_linux_service \"ufw\"       \"on\"\n    check_file_value    \"is\"        \"/etc/ufw/ufw.conf\"   \"LOGLEVEL\" \"eq\" \"high\" \"hash\"\n    check_linux_package \"uninstall\" \"iptables-persistent\"\n  else\n    na_message \"${string}\"\n  fi\n}"
  },
  {
    "path": "modules/fs/audit_autofs.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_autofs\n#\n# Check Automount services\n#\n# Refer to Section(s) 2.9     Page(s) 21     CIS Solaris 11.1 v1.0.0\n# Refer to Section(s) 1.1.22  Page(s) 47     CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 1.1.21  Page(s) 45     CIS Ubuntu LTS 16.04 Benchmark v1.0.0\n# Refer to Section(s) 2.1.1   Page(s) 228-30 CIS Ubuntu LTS 24.04 Benchmark v1.0.0\n# Refer to Section(s) 2.2.10  Page(s) 30     CIS Solaris 10 v5.1.0\n# Refer to Section(s) 2.25    Page(s) 31     CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 1.1.19  Page(s) 43     CIS Amazon Linux Benchmark v2.0.0\n#.\n\naudit_autofs () {\n  print_function \"audit_autofs\"\n  string=\"Automount Services\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n        check_sunos_service \"svc:/system/filesystem/autofs\" \"disabled\"\n      fi\n    fi\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      check_linux_service   \"autofs\" \"off\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/fs/audit_file_extensions.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_file_extensions\n#\n# Check File Extensions\n#\n# Refer to Section(s) 6.2   Page(s) 77-8  CIS Apple OS X 10.8 Benchmark v1.0.0\n# Refer to Section(s) 6.2   Page(s) 162-3 CIS Apple OS X 10.12 Benchmark v1.0.0\n# Refer to Section(s) 6.1.1 Page(s) 362-4 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_file_extensions() {\n  print_function \"audit_file_extensions\"\n  string=\"File Extensions\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    check_osx_defaults_int \"NSGlobalDomain\" \"AppleShowAllExtensions\" \"1\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/fs/audit_file_metadata.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_file_metadata\n#\n# Check Auditing of File Metadata Modification Events\n#\n# Refer to Section(s) 4.3 Page(s) 41-2 CIS Solaris 11.1 Benchmark v1.0.0\n#.\n\naudit_file_metadata () {\n  print_function \"audit_file_metadata\"\n  string=\"Auditing of File Metadata Modification Events\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"11\" ]; then\n      check_append_file \"/etc/security/audit_event\" \"lck:AUE_CHMOD\"   \"hash\"\n      check_append_file \"/etc/security/audit_event\" \"lck:AUE_CHOWN\"   \"hash\"\n      check_append_file \"/etc/security/audit_event\" \"lck:AUE_FCHOWN\"  \"hash\"\n      check_append_file \"/etc/security/audit_event\" \"lck:AUE_FCHMOD\"  \"hash\"\n      check_append_file \"/etc/security/audit_event\" \"lck:AUE_LCHOWN\"  \"hash\"\n      check_append_file \"/etc/security/audit_event\" \"lck:AUE_ACLSET\"  \"hash\"\n      check_append_file \"/etc/security/audit_event\" \"lck:AUE_FACLSET\" \"hash\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/fs/audit_file_perms.sh",
    "content": "#!/bin/sh\n\n# -> Needs checking of obase/ibase etc\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2012\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n# shellcheck disable=SC2216\n\n# audit_file_perms\n#\n# It is important to ensure that system files and directories are maintained\n# with the permissions they were intended to have from the OS vendor (Oracle).\n#.\n\naudit_file_perms () {\n  print_function \"audit_file_perms\"\n  string=\"System File Permissions\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    log_file=\"fileperms.log\"\n    if [ \"${audit_mode}\" != 2 ]; then\n      if [ \"${os_version}\" = \"11\" ]; then\n        error=0\n        command=$( pkg verify | grep file | awk '{print $2}' )\n      else\n        command=$( pkgchk -n 2>&1 |grep ERROR | awk '{print $2}' )\n      fi\n      for check_file in ${command}; do\n        if [ \"${audit_mode}\" = 1 ]; then\n          inc_insecure \"Incorrect permissions on file \\\"${check_file}\\\"\"\n        fi\n        if [ \"${audit_mode}\" = 0 ]; then\n          if [ \"${os_version}\" = \"10\" ]; then\n            verbose_message \"Setting:   Correct permissions on file \\\"${check_file}\\\"\"\n            log_file=\"${work_dir}/${log_file}\"\n            command=\"ls -l \\\"${check_file}\\\" | echo \\\"obase=8;ibase=2;\\`awk '{print \\$1}' | cut -c2-10 | tr 'xrws-' '11110'\\`\\\" | /usr/bin/bc\"\n            command_message \"${command}\"\n            file_perms=$( eval \"${command}\" )\n            command=\"ls -l \\\"${check_file}\\\" | awk '{print \\$3\\\",\\\"\\$4}'\"\n            command_message \"${command}\"\n            file_owner=$( eval \"${command}\" )\n            echo \"${check_file},${file_perms},${file_owner}\" >> \"${log_file}\"\n            pkgchk -f -n -p \"${file_name}\" 2> /dev/null\n          else\n            error=1\n          fi\n        fi\n      done\n      if [ \"${os_version}\" = \"11\" ]; then\n        if [ \"${audit_mode}\" = 0 ]; then\n          if [ \"$error\" = 1 ]; then\n            log_file=\"${work_dir}/${log_file}\"\n            command=\"ls -l \\\"${check_file}\\\" | echo \\\"obase=8;ibase=2;\\`awk '{print \\$1}' | cut -c2-10 | tr 'xrws-' '11110'\\`\\\" | /usr/bin/bc\"\n            command_message \"${command}\"\n            file_perms=$( eval \"${command}\" )\n            command=\"ls -l \\\"${check_file}\\\" | awk '{print \\$3\\\",\\\"\\$4}'\"\n            command_message \"${command}\"\n            file_owner=$( eval \"${command}\" )\n            echo \"${check_file},${file_perms},${file_owner}\" >> \"${log_file}\"\n            pkg fix\n          fi\n        fi\n      fi\n    else\n      restore_file=\"${restore_dir}/${log_file}\"\n      if [ -f \"${restore_file}\" ]; then\n        restore_check=$( grep \"${check_file}\" \"${restore_file}\" | cut -f1 -d, )\n        if [ \"$restore_check\" = \"${check_file}\" ]; then\n          restore_info=$( grep \"${check_file}\" \"${restore_file}\" )\n          restore_perms=$( echo \"${restore_info}\" | cut -f2 -d, )\n          restore_owner=$( echo \"${restore_info}\" | cut -f3 -d, )\n          restore_group=$( echo \"${restore_info}\" | cut -f4 -d, )\n          verbose_message \"Restoring: File ${check_file} to previous permissions\"\n          chmod \"${restore_perms}\" \"${check_file}\"\n          if [ \"${restore_owner}\" != \"\" ]; then\n            chown \"${restore_owner}:${restore_group}\" \"${check_file}\"\n          fi\n        fi\n      fi\n    fi\n  fi\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    verbose_message \"System File Permissions\"\n    log_file=\"fileperms.log\"\n    if [ \"${audit_mode}\" != 2 ]; then\n      verbose_message \"File permissions [This may take a while]\"\n\n      # Check specific to Debian\n      if [ \"${os_vendor}\" = \"Ubuntu\" ] || [ \"${os_vendor}\" = \"Debian\" ]; then\n        # TODO\n        echo \"\"\n      fi\n\n      # Check specific to Red Hat/CentOS\n      if [ \"${os_vendor}\" = \"CentOS\" ] || [ \"${os_vendor}\" = \"Red\" ]; then\n        file_list=$( rpm -Va --nomtime --nosize --nomd5 --nolinkt | awk '{print $2}' ) \n        for check_file in ${file_list}; do\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_insecure \"Incorrect permissions on ${file_name}\"\n            verbose_message \"yum reinstall ${rpm_name}\" \"fix\"\n          fi\n          if [ \"${audit_mode}\" = 0 ]; then\n            verbose_message \"Setting:   Correct permissions on file \\\"${file_name}\\\"\"\n            log_file=\"${work_dir}/${log_file}\"\n            file_perms=$( stat -c %a \"${check_file}\" )\n            file_owner=$( ls -l \"${check_file}\" | awk '{print $3\",\"$4}' )\n            echo \"${check_file},${file_perms},${file_owner}\" >> \"${log_file}\"\n            yum reinstall \"${rpm_name}\"\n          fi\n        done\n      fi\n    else\n      restore_file=\"${restore_dir}/${log_file}\"\n      if [ -f \"${restore_file}\" ]; then\n        restore_check=$( grep \"${check_file}\" \"${restore_file}\" | cut -f1 -d, )\n        if [ \"$restore_check\" = \"${check_file}\" ]; then\n          restore_info=$(  grep \"${check_file}\" \"${restore_file}\" )\n          restore_perms=$( echo \"${restore_info}\" | cut -f2 -d, )\n          restore_owner=$( echo \"${restore_info}\" | cut -f3 -d, )\n          restore_group=$( echo \"${restore_info}\" | cut -f4 -d, )\n          verbose_message \"Restoring: File \\\"${check_file}\\\" to previous permissions\"\n          chmod \"${restore_perms}\" \"${check_file}\"\n          if [ \"${restore_owner}\" != \"\" ]; then\n            chown \"${restore_owner}:${restore_group}\" \"${check_file}\"\n          fi\n        fi\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/fs/audit_hotplug.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_hotplug\n#\n# Turn off hotplug\n#.\n\naudit_hotplug () {\n  print_function \"audit_hotplug\"\n  string=\"Hotplug Service\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n        check_sunos_service \"svc:/system/hotplug:default\" \"disabled\"\n      fi\n    fi\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      for service_name in pcscd haldaemon kudzu; do\n        check_linux_service \"${service_name}\" \"off\"\n      done\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/fs/audit_nfs.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_nfs\n#\n# Check NFS\n#\n# Refer to Section(s) 3.8       Page(s) 64-5        CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 3.8       Page(s) 77          CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 3.8       Page(s) 67-8        CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 2.2.7     Page(s) 107         CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 6.7       Page(s) 57-8        CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 3.7-11    Page(s) 11-3        CIS FreeBSD Benchmark v1.0.5\n# Refer to Section(s) 1.3.5     Page(s) 39          CIS AIX Benchmark v1.1.0\n# Refer to Section(s) 2.2.7     Page(s) 99          CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 2.2.7     Page(s) 107         CIS Ubuntu 16.04 Benchmark v1.0.0\n# Refer to Section(s) 2.1.9,12  Page(s) 251-3,60-2  CIS Ubuntu 24.04 Benchmark v1.0.0\n# Refer to Section(s) 4.6       Page(s) 105-6       CIS Apple OS X 10.12 Benchmark v1.0.0\n# Refer to Section(s) 4.3       Page(s) 294-5       CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_nfs () {\n  print_function \"audit_nfs\"\n  string=\"NFS Services\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"FreeBSD\" ] || [ \"${os_name}\" = \"AIX\" ] || [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"$nfsd_disable\" = \"yes\" ]; then\n      if [ \"${os_name}\" = \"AIX\" ]; then\n        check_itab \"rcnfs\" \"off\"\n      fi\n      if [ \"${os_name}\" = \"Darwin\" ]; then\n        check_launchctl_service \"com.apple.nfsd\" \"off\"\n      fi\n      if [ \"${os_name}\" = \"SunOS\" ]; then\n        if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n          for service_name in \"svc:/network/nfs/mapid:default\" \\\n            \"svc:/network/nfs/status:default\" \"svc:/network/nfs/cbd:default\" \\\n            \"svc:/network/nfs/nlockmgr:default\" \"svc:/network/nfs/client:default\" \\\n            \"svc:/network/nfs/server:default\"; do\n            check_sunos_service \"${service_name}\" \"disabled\"\n          done\n        fi\n        if [ \"${os_version}\" != \"11\" ]; then\n          check_sunos_service \"nfs.server\" \"disabled\"\n        fi\n        check_file_value \"is\" \"/etc/system\" \"nfssrv:nfs_portmon\" \"eq\" \"1\" \"star\"\n      fi\n      if [ \"${os_name}\" = \"Linux\" ]; then\n        for service_name in nfs nfslock rpc nfs-kerner-server rpcbind; do\n          check_linux_service \"${service_name}\" \"off\"\n        done\n      fi\n      if [ \"${os_name}\" = \"FreeBSD\" ]; then\n        check_file_value    \"is\" \"/etc/rc.conf\" \"nfs_reserved_port_only\"      \"eq\" \"YES\" \"hash\"\n        check_file_value    \"is\" \"/etc/rc.conf\" \"weak_mountd_authentication\"  \"eq\" \"NO\"  \"hash\"\n        check_file_value    \"is\" \"/etc/rc.conf\" \"rpc_lockd_enable\"            \"eq\" \"NO\"  \"hash\"\n        check_file_value    \"is\" \"/etc/rc.conf\" \"rpc_statd_enable\"            \"eq\" \"NO\"  \"hash\"\n        if [ \"${os_version}\" -lt 5 ]; then\n          check_file_value  \"is\" \"/etc/rc.conf\" \"portmap_enable\"              \"eq\" \"NO\" \"hash\"\n          check_file_value  \"is\" \"/etc/rc.conf\" \"nfs_server_enable\"           \"eq\" \"NO\" \"hash\"\n          check_file_value  \"is\" \"/etc/rc.conf\" \"single_mountd_enable\"        \"eq\" \"NO\" \"hash\"\n        else\n          check_file_value  \"is\" \"/etc/rc.conf\" \"rpcbind_enable\"              \"eq\" \"NO\" \"hash\"\n          check_file_value  \"is\" \"/etc/rc.conf\" \"nfs_server_enable\"           \"eq\" \"NO\" \"hash\"\n          check_file_value  \"is\" \"/etc/rc.conf\" \"mountd_enable\"               \"eq\" \"NO\" \"hash\"\n        fi\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/fs/audit_samba.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_samba\n#\n# Check Samba settings\n#\n# Refer to Section(s) 3.13     Page(s) 68    CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 3.13     Page(s) 80    CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 2.2.12   Page(s) 112   CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 6.12     Page(s) 60-1  CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 2.4.14.4 Page(s) 55    CIS OS X 10.5 Benchmark v1.1.0\n# Refer to Section(s) 2.2.9    Page(s) 29-30 CIS Solaris 10 Benchmark v5.1.0\n# Refer to Section(s) 2.2.12-3 Page(s) 104-5 CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 2.2.12-3 Page(s) 112-3 CIS Ubuntu 16.04 Benchmark v1.0.0\n#.\n\naudit_samba () {\n  print_function \"audit_samba\"\n  string=\"Samba Daemons\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      if [ \"${os_version}\" = \"10\" ]; then\n        if [ \"${os_update}\" -ge 4 ]; then\n          check_sunos_service \"svc:/network/samba\" \"disabled\"\n        else\n          check_sunos_service \"samba\" \"disabled\"\n        fi\n      fi\n    fi\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      check_linux_service \"smb\"       \"off\"\n      check_linux_package \"uninstall\" \"samba\"\n    fi\n    for check_dir in /etc /etc/sfw /etc/samba /usr/local/etc /usr/sfw/etc /opt/sfw/etc; do\n      check_file=\"${check_dir}/smb.conf\"\n      if [ -f \"${check_file}\" ]; then\n        check_file_value_with_position \"is\" \"${check_file}\" \"restrict anonymous\" \"eq\" \"2\"   \"semicolon\" \"after\" \"\\[Global\\]\"\n        check_file_value_with_position \"is\" \"${check_file}\" \"guest OK\"           \"eq\" \"no\"  \"semicolon\" \"after\" \"\\[Global\\]\"\n        check_file_value_with_position \"is\" \"${check_file}\" \"client ntlmv2 auth\" \"eq\" \"yes\" \"semicolon\" \"after\" \"\\[Global\\]\"\n      fi\n    done\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/fs/audit_setup_file.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_setup_file\n#\n# Check Setup File permissions \n#.\n\naudit_setup_file () {\n  print_function \"audit_setup_file\"\n  string=\"Setup file\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    check_file_perms \"/var/db/.AppleSetupDone\" \"0400\" \"root\" \"${wheel_group}\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/fs/audit_smbconf_perms.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC2034\n# shellcheck disable=SC1090\n# shellcheck disable=SC2154\n\n# audit_smbconf_perms\n#\n# Check SMB config permissions\n#\n# Refer to Section(s) 11.2-3 Page(s) 143-4 CIS Solaris 10 Benchmark v1.1.0\n#.\n\naudit_smbconf_perms () {\n  print_function \"audit_smbconf_perms\"\n  string=\"SMB Config Permissions\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    check_file_perms  \"/etc/samba/smb.conf\" \"0644\" \"root\" \"root\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/fs/audit_sticky_bit.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC2034\n# shellcheck disable=SC1090\n# shellcheck disable=SC2154\n\n# audit_sticky_bit\n#\n# Check sticky bits set of files\n#\n# Refer to Section(s) 1.17   Page(s) 26    CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 1.1.21 Page(s) 46    CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 1.1.17 Page(s) 28    CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 1.1.17 Page(s) 27    CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 2.17   Page(s) 26    CIS SLES 11 Benchmark v1.2.0\n# Refer to Section(s) 6.3    Page(s) 21-22 CIS FreeBSD Benchmark v1.0.5\n# Refer to Section(s) 5.3    Page(s) 77-8  CIS Solaris 10 Benchmark v5.1.0\n# Refer to Section(s) 1.1.18 Page(s) 42    CIS Amazon Linux Benchmark v2.0.0\n#.\n\naudit_sticky_bit () {\n  print_function \"audit_sticky_bit\"\n  string=\"World Writable Directories and Sticky Bits\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"FreeBSD\" ]; then\n    if [ \"${do_fs}\" = 1 ]; then\n      if [ \"${os_version}\" = \"10\" ]; then\n        log_file=\"sticky_bits\"\n        file_list=$( find / \\( -fstype nfs -o -fstype cachefs \\\n          -o -fstype autofs -o -fstype ctfs \\\n          -o -fstype mntfs -o -fstype objfs \\\n          -o -fstype proc \\) -prune -o -type d \\\n          \\( -perm -0002 -a -perm -1000 \\) -print )\n        for check_dir in ${file_list}; do\n          lock_command=\"sudo chmod +t ${check_dir}\"\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_insecure \"Sticky bit not set on \\\"${check_dir}\\\"\"\n            fix_message  \"${lock_command}\"\n          fi\n          if [ \"${audit_mode}\" = 0 ]; then\n            update_log   \"${log_file}\" \"${check_dir}\"\n            set_message  \"Sticky bit on \\\"${check_dir}\\\"\"\n            run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n          fi\n          if [ \"${ansible_mode}\" = 1 ]; then\n            echo \"\"\n            echo \"- name: Checking ${string} on ${check_dir}\"\n            echo \"  command: sh -c \\\"sudo chmod +t ${check_dir}\\\"\"\n            echo \"  ignore_errors: true\"\n            echo \"  when: ansible_facts['ansible_system'] == '${os_name}'\"\n            echo \"\"\n          else\n            lock_message=\"Sticky bit from \\\"${check_dir}\\\"\"\n            run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n          fi\n        done\n        if [ \"${audit_mode}\" = 2 ]; then\n          restore_file=\"${restore_dir}/sticky_bits\"\n          if [ -f \"${restore_file}\" ]; then\n            check_dirs=$( cat \"${restore_file}\" )\n            for check_dir in ${check_dirs}; do\n              if [ -d \"${check_dir}\" ]; then\n                restore_command=\"sudo chmod -t ${check_dir}\"\n                restore_message=\"Removing sticky bit from \\\"${check_dir}\\\"\"\n                execute_restore \"${restore_command}\" \"${restore_message}\" \"sudo\"\n              fi\n            done\n          fi\n        fi\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/fs/audit_suid_files.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1083\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_suid_files\n#\n# Check Set UID/GID on files\n#\n# Refer to Section(s) 9.1.13-4 Page(s) 161-2 CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 9.1.13-4 Page(s) 186-7 CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 9.1.13-4 Page(s) 164-5 CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 6.1.12-4 Page(s) 272-4 CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 12.11-12 Page(s) 152-3 CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 6.5      Page(s) 22    CIS FreeBSD Benchmark v1.0.5\n# Refer to Section(s) 2.16.1   Page(s) 231-2 CIS AIX Benchmark v1.1.0\n# Refer to Section(s) 9.23     Page(s) 88-9  CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 6.1.12-4 Page(s) 250-2 CIS Amazon Linux Benchmark v1.0.0\n# Refer to Section(s) 6.1.13-4 Page(s) 264-5 CIS Ubuntu 16.04 Benchmark v1.0.0\n# Refer to Section(s) 7.1.13   Page(s) 961-3 CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_suid_files () {\n  print_function \"audit_suid_files\"\n  string=\"Set UID/GID Files\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"FreeBSD\" ] || [ \"${os_name}\" = \"AIX\" ]; then\n    log_file=\"setuidfiles.log\"\n    if [ \"${audit_mode}\" = 1 ]; then\n      if [ \"${os_name}\" = \"Linux\" ]; then\n        command=\"df --local -P | awk {'if (NR!=1) print \\$6'}\"\n        command_message \"${command}\"\n        file_systems=$( eval \"${command}\" )\n        for file_system in ${file_systems}; do\n          command=\"find \\\"${file_system}\\\" -xdev -type f -perm -4000 -print 2> /dev/null\"\n          command_message \"${command}\"\n          check_files=$( eval \"${command}\" )\n          for check_file in ${check_files}; do\n            inc_insecure \"File \\\"${check_file}\\\" is SUID/SGID\"\n            lock_command=\"chmod o-S \\\"${check_file}\\\"\"\n            lock_message=\"Setting file \\\"${check_file}\\\" to be non world writable\"\n            if [ \"${ansible_mode}\" = 1 ]; then\n              echo \"\"\n              echo \"- name: Checking write permissions for \\\"${check_file}\\\"\"\n              echo \"  file:\"\n              echo \"    path: \\\"${check_file}\\\"\"\n              echo \"    mode: o-S\"\n              echo \"\"\n            fi\n            if [ \"${audit_mode}\" = 1 ]; then\n              inc_insecure \"File \\\"${check_file}\\\" is world writable\"\n              run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n            fi\n            if [ \"${audit_mode}\" = 0 ]; then\n              echo \"${check_file}\" >> \"${log_file}\"\n              run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n            fi\n          done\n        done\n      else\n        if [ \"${os_name}\" = \"SunOS\" ]; then\n          find_command=\"find / \\( -fstype nfs -o -fstype cachefs \\\n          -o -fstype autofs -o -fstype ctfs -o -fstype mntfs \\\n          -o -fstype objfs -o -fstype proc \\) -prune \\\n          -o -type f \\( -perm -4000 -o -perm -2000 \\) -print\"\n        fi\n        if [ \"${os_name}\" = \"AIX\" ]; then\n          find_command=\"find / \\( -fstype jfs -o -fstype jfs2 \\) \\\n          \\( -perm -04000 -o -perm -02000 \\) -typ e f -ls\"\n        fi\n        lock_command=\"chmod o-S ${check_file}\"\n        lock_message=\"Setting file \\\"${check_file}\\\" to be non world writable\"\n        for check_file in $( ${find_command} ); do\n          inc_insecure \"File ${check_file} is SUID/SGID\"\n          if [ \"${ansible_mode}\" = 1 ]; then\n            echo \"\"\n            echo \"- name: Checking write permissions for ${check_file}\"\n            echo \"  file:\"\n            echo \"    path: ${check_file}\"\n            echo \"    mode: o-S\"\n            echo \"\"\n          fi\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_insecure \"File \\\"${check_file}\\\" is world writable\"\n            run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n          fi\n          if [ \"${audit_mode}\" = 0 ]; then\n            update_log   \"${log_file}\" \"${check_file}\"\n            run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n          fi\n        done\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/fs/audit_unowned_files.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1083\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_unowned_files\n#\n# Find unowned files\n#\n# Refer to Section(s) 9.1.11-2 Page(s) 160-1  CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 9.1.11-2 Page(s) 184-6  CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 9.1.11-2 Page(s) 163-4  CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 6.1.11-2 Page(s) 270-1  CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 12.9-10  Page(s) 151-2  CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 6.7      Page(s) 23     CIS FreeBSD Benchmark v1.0.5\n# Refer to Section(s) 2.16.2   Page(s) 232-3  CIS AIX Benchmark v1.1.0\n# Refer to Section(s) 9.24     Page(s) 89-90  CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 9.24     Page(s) 135-6  CIS Solaris 10 Benchmark v1.1.0\n# Refer to Section(s) 6.1.11-2 Page(s) 248-9  CIS Amazon Linux Benchmark v1.0.0\n# Refer to Section(s) 6.1.11-2 Page(s) 262-3  CIS Ubuntu 16.04 Benchmark v1.0.0\n# Refer to Section(s) 7.1.12   Page(s) 958-60 CIS Ubuntu 16.04 Benchmark v1.0.0\n#.\n\naudit_unowned_files () {\n  print_function \"audit_unowned_files\"\n  string=\"Unowned Files and Directories\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"FreeBSD\" ] || [ \"${os_name}\" = \"AIX\" ]; then\n    if [ \"${my_id}\" != \"0\" ] && [ \"${use_sudo}\" = \"0\" ]; then\n      verbose_message \"Requires sudo to check\" \"notice\"\n      return\n    fi\n    if [ \"${audit_mode}\" = 1 ]; then\n      if [ \"${os_name}\" = \"Linux\" ]; then\n        command=\"df --local -P | awk {'if (NR!=1) print \\$6'}\"\n        command_message \"${command}\"\n        file_systems=$( eval \"${command}\" )\n        for file_system in ${file_systems}; do\n          command=\"find \\\"${file_system}\\\" -xdev -nouser -ls 2> /dev/null\"\n          command_message \"${command}\"\n          check_files=$( eval \"${command}\" )\n          for check_file in ${check_files}; do\n            inc_insecure \"File \\\"${check_file}\\\" is unowned\"\n          done\n        done\n      else\n        if [ \"${os_name}\" = \"SunOS\" ]; then\n          find_command=\"find / \\( -fstype nfs -o -fstype cachefs \\\n          -o -fstype autofs -o -fstype ctfs -o -fstype mntfs \\\n          -o -fstype objfs -o -fstype proc \\) -prune \\\n          -o \\( -nouser -o -nogroup \\) -print\"\n        fi\n        if [ \"${os_name}\" = \"AIX\" ]; then\n          find_command=\"find / \\( -fstype jfs -o -fstype jfs2 \\) \\\n          \\( -type d -o -type f \\) \\( -nouser -o -nogroup \\) -ls\"\n        fi\n        check_files=$( eval \"${find_command}\" )\n        for check_file in ${check_file}s; do\n          inc_insecure \"File \\\"${check_file}\\\" is unowned\"\n        done\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/fs/audit_user_dotfiles.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_user_dotfiles\n#\n# Check permissions on user dot file\n#\n# Refer to Section(s) 9.2.8  Page(s) 167-168 CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 6.2.10 Page(s) 284     CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 9.2.8  Page(s) 193-4   CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 13.8   Page(s) 159     CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 7.2    Page(s) 25      CIS FreeBSD Benchmark v1.0.5\n# Refer to Section(s) 9.8    Page(s) 77-8    CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 9.8    Page(s) 122     CIS Solaris 10 Benchmark v1.1.0\n# Refer to Section(s) 6.2.10 Page(s) 262     CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 6.2.10 Page(s) 276     CIS Ubuntu 16.04 Benchmark v1.0.0\n# Refer to Section(s) 7.2.10 Page(s) 986-92      CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_user_dotfiles () {\n  print_function \"audit_user_dotfiles\"\n  string=\"User Dot Files\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"FreeBSD\" ]; then\n    if [ \"${my_id}\" != \"0\" ] && [ \"${use_sudo}\" = \"0\" ]; then\n      notice_message \"Requires sudo to check\"\n      return\n    fi\n    home_dirs=$( grep -v \"^/$\" < /etc/passwd | cut -f6 -d:)\n    for home_dir in ${home_dirs}; do\n      command=\"find \\\"${home_dir}\\\" -depth 1 -name \\\".[A-Za-z0-9]*\\\" 2>/dev/null\"\n      command_message \"${command}\"\n      file_list=$( eval \"${command}\" )\n      for check_file in ${file_list}; do\n        if [ -f \"${check_file}\" ]; then\n          check_file_perms \"${check_file}\" \"0600\" \"\" \"\"\n        fi\n      done\n    done\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/fs/audit_user_netrc.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_user_netrc\n#\n# Check for netrc files\n#\n# Refer to Section(s) 9.2.9    Page(s) 168-169     CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 9.2.9,20 Page(s) 194-5,205-6 CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 9.2.9    Page(s) 171-2       CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 6.2.13-4 Page(s) 286-8       CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 13.9,18  Page(s) 160-1,167   CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 6.2.13-4 Page(s) 265-7       CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 7.2      Page(s) 25          CIS FreeBSD Benchmark v1.0.5\n# Refer to Section(s) 1.5.1    Page(s) 101-2       CIS AIX Benchmark v1.1.0\n# Refer to Section(s) 9.9,20   Page(s) 78-9,86     CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 9.9,20   Page(s) 122-3,132-3 CIS Solaris 10 Benchmark v1.1.0\n# Refer to Section(s) 7.2.10   Page(s) 986-92      CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_user_netrc () {\n  print_function \"audit_user_netrc\"\n  string=\"User Netrc Files\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"FreeBSD\" ] || [ \"${os_name}\" = \"AIX\" ]; then\n    if [ \"${my_id}\" != \"0\" ] && [ \"${use_sudo}\" = \"0\" ]; then\n      verbose_message \"Requires sudo to check\" \"notice\"\n      return\n    fi\n    check_fail=0\n    command=\"grep -v '^/$' < /etc/passwd | cut -f6 -d':'\"\n    command_message \"${command}\"\n    home_dirs=$( eval \"${command}\" )\n    for home_dir in ${home_dirs}; do\n      check_file=\"${home_dir}/.netrc\"\n      if [ -f \"${check_file}\" ]; then\n        check_fail=1\n        check_file_perms \"${check_file}\" \"0600\"\n      fi\n    done\n    if [ \"${check_fail}\" != 1 ]; then\n      if [ \"${audit_mode}\" = 1 ]; then\n        inc_secure   \"No user netrc files exist\"\n      else\n        inc_insecure \"User netrc files exist\"\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/fs/audit_user_rhosts.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_user_rhosts\n#\n# Check for rhosts files\n#\n# Refer to Section(s) 9.2.10 Page(s) 169-70 CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 9.2.10 Page(s) 195-6  CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 9.2.10 Page(s) 172-3  CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 6.2.14 Page(s) 289    CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 13.10  Page(s) 161    CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 7.2    Page(s) 25     CIS FreeBSD Benchmark v1.0.5\n# Refer to Section(s) 1.5.1  Page(s) 101-2  CIS AIX Benchmark v1.1.0\n# Refer to Section(s) 9.10   Page(s) 79     CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 9.10   Page(s) 124    CIS Solaris 10 Benchmark v1.1.0\n# Refer to Section(s) 6.2.14 Page(s) 267-8  CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 6.2.14 Page(s) 281    CIS Ubuntu 16.04 Benchmark v2.0.0\n# Refer to Section(s) 7.2.10 Page(s) 986-92 CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_user_rhosts () {\n  print_function \"audit_user_rhosts\"\n  string=\"User RHosts Files\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"FreeBSD\" ] || [ \"${os_name}\" = \"AIX\" ]; then\n    check_fail=0\n    command=\"grep -v '^/$' < /etc/passwd | cut -f6 -d':'\"\n    command_message \"${command}\"\n    home_dirs=$( eval \"${command}\" )\n    for home_dir in ${home_dirs}; do\n      check_file=\"${home_dir}/.rhosts\"\n      if [ -f \"${check_file}\" ]; then\n        check_fail=1\n        check_file_exists \"${check_file}\" \"no\"\n      fi\n    done\n    if [ \"${check_fail}\" != 1 ]; then\n      if [ \"${audit_mode}\" = 1 ]; then\n        inc_secure   \"No user rhosts files exist\"\n      else\n        inc_insecure \"User rhosts files exist\"\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/fs/audit_winbind.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_winbind\n#\n# Turn off winbind if not required\n#.\n\naudit_winbind () {\n  print_function \"audit_winbind\"\n  string=\"Winbind Daemon\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n      check_sunos_service \"svc:/network/winbind:default\" \"disabled\"\n    fi\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      check_linux_service \"winbind\" \"off\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/fs/audit_writable_files.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1083\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_writable_files\n#\n# Refer to Section(s) 9.1.10   Page(s) 159-160 CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 9.1.10   Page(s) 183-4   CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 9.1.10   Page(s) 162-3   CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 6.1.10   Page(s) 269     CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 12.8     Page(s) 150-1   CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 6.1.10   Page(s) 247     CIS Amazon Linux Benchmark v1.0.0\n# Refer to Section(s) 6.4      Page(s) 22      CIS FreeBSD Benchmark v1.0.5\n# Refer to Section(s) 2.16.3   Page(s) 233-4   CIS AIX Benchmark v1.1.0\n# Refer to Section(s) 5.1,9.22 Page(s) 45,88   CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 9.22     Page(s) 134     CIS Solaris 10 Benchmark v1.1.0\n# Refer to Section(s) 6.1.10   Page(s) 261     CIS Ubuntu 16.04 Benchmark v1.0.0\n# Refer to Section(s) 7.1.11   Page(s) 954-7   CIS Ubuntu 24.04 Benchmark v1.0.0\n# Refer to Section(s) 5.1.3-4  Page(s) 110-1   CIS Apple OS X 10.12 Benchmark v1.0.0\n# Refer to Section(s) 5.1.7    Page(s) 311-4   CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_writable_files () {\n  print_function \"audit_writable_files\"\n  string=\"World Writable Files\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"FreeBSD\" ] || [ \"${os_name}\" = \"AIX\" ]; then\n    if [ \"${do_fs}\" = 1 ]; then\n      log_file=\"worldwritablefiles.log\"\n      if [ \"${audit_mode}\" = 0 ]; then\n        log_file=\"${work_dir}/${log_file}\"\n      fi\n      if [ \"${audit_mode}\" != 2 ]; then\n        if [ \"${os_name}\" = \"Linux\" ]; then\n          command=\"df --local -P | awk {'if (NR!=1) print \\$6'} 2> /dev/null\"\n          command_message \"${command}\"\n          file_systems=$( eval \"${command}\" )\n          for file_system in ${file_systems}; do\n            command=\"find \\\"${file_system}\\\" -xdev -type f -perm -0002 2> /dev/null\"\n            command_message \"${command}\"\n            check_files=$( eval \"${command}\" )\n            for check_file in ${check_files}; do\n              if [ \"${ansible_mode}\" = 1 ]; then\n                echo \"\"\n                echo \"- name: Checking write permissions for ${check_file}\"\n                echo \"  file:\"\n                echo \"    path: ${check_file}\"\n                echo \"    mode: o-w\"\n                echo \"\"\n              fi\n              if [ \"${audit_mode}\" = 1 ]; then\n                inc_insecure \"File ${check_file} is world writable\"\n                fix_message  \"chmod o-w ${check_file}\"\n              fi\n              if [ \"${audit_mode}\" = 0 ]; then\n                update_log   \"${log_file}\" \"${check_file}\"\n                lock_message=\"File \\\"${check_file}\\\" to be non world writable\"\n                lock_command=\"chmod o-w ${check_file}\"\n                run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n              fi\n            done\n          done\n        else\n          if [ \"${os_name}\" = \"SunOS\" ]; then\n            find_command=\"find / \\( -fstype nfs -o -fstype cachefs \\\n            -o -fstype autofs -o -fstype ctfs -o -fstype mntfs \\\n            -o -fstype objfs -o -fstype proc \\) -prune \\\n            -o -type f -perm -0002 -print\"\n          fi\n          if [ \"${os_name}\" = \"AIX\" ]; then\n            find_command=\"find / \\( -fstype jfs -o -fstype jfs2 \\) \\\n            \\( -type d -o -type f \\) -perm -o+w -ls\"\n          fi\n          if [ \"${os_name}\" = \"FreeBSD\" ]; then\n            find_command=\"find / \\( -fstype ufs -type file -perm -0002 \\\n            -a ! -perm -1000 \\) -print\"\n          fi\n          for check_file in $( ${find_command} ); do\n            if [ \"${ansible_mode}\" = 1 ]; then\n              echo \"\"\n              echo \"- name: Checking write permissions for ${check_file}\"\n              echo \"  file:\"\n              echo \"    path: ${check_file}\"\n              echo \"    mode: o-w\"\n              echo \"\"\n            fi\n            if [ \"${audit_mode}\" = 1 ]; then\n              inc_insecure \"File ${check_file} is world writable\"\n              fix_message  \"chmod o-w ${check_file}\"\n            fi\n            if [ \"${audit_mode}\" = 0 ]; then\n              update_log  \"${log_file}\" \"${check_file}\"\n              lock_message=\"File \\\"${check_file}\\\" to be non world writable\"\n              lock_command=\"chmod o-w ${check_file}\"\n              run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n            fi\n          done\n        fi\n      fi\n      if [ \"${audit_mode}\" = 2 ]; then\n        restore_file=\"${restore_dir}/${log_file}\"\n        if [ -f \"${restore_file}\" ]; then\n          check_files=$( cat \"${restore_file}\" )\n          for check_file in ${check_file}s; do\n            if [ -f \"${check_file}\" ]; then\n              restore_message=\"File \\\"${check_file}\\\" to previous permissions\"\n              restore_command=\"chmod o+w ${check_file}\"\n              execute_restore \"${restore_command}\" \"${restore_message}\" \"sudo\"\n            fi\n          done\n        fi\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/ftp/audit_ftp_banner.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_ftp_banner\n#\n# Refer to Section(s) 2.12.11 Page(s) 215-6 CIS AIX Benchmark v1.1.0\n# Refer to Section(s) 8.4     Page(s) 70-1  CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 8.4     Page(s) 114   CIS Solaris 10 Benchmark v5.1.0\n#.\n\naudit_ftp_banner () {\n  print_function \"audit_ftp_banner\"\n  string=\"FTP Warning Banner\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"AIX\" ]; then\n    if [ \"${os_name}\" = \"AIX\" ]; then\n      package_name=\"bos.msg.${language_suffix}.net.tcp.client\"\n      check_lslpp \"${package_name}\"\n      if [ \"${lslpp_check}\" = \"${package_name}\" ]; then\n        message_file=\"/usr/lib/nls/msg/${language_suffix}/ftpd.cat\"\n        command=\"dspcat -g \\\"${message_file}\\\" | grep \\\"^9[[:blank:]]\\\" | awk '{print \\$3}'\"\n        command_message \"${command}\"\n        actual_value=$( eval \"${command}\" )\n        if [ \"${audit_mode}\" != 2 ]; then\n          if [ \"${actual_value}\" != \"Authorised\" ]; then\n            if [ \"${audit_mode}\" = 1 ]; then\n              inc_secure  \"FTP warning message isn't enabled\"\n              fix_message \"dspcat -g \\\"${message_file}\\\" > \\\"${temp_dir}/ftpd.tmp\\\"\"\n              fix_message \"sed \\\"s/\\\"\\%s FTP server (\\%s) ready.\\\"/\\\"\\%s Authorised uses only. All activity may be monitored and reported\\\"/\\\" \\\"${temp_dir}/ftpd.tmp\\\" > \\\"${temp_dir}/ftpd.msg\\\"\"\n              fix_message \"gencat \\\"${message_file}\\\" \\\"${temp_dir}/ftpd.msg\\\"\"\n              fix_message \"rm \\\"${temp_dir}/ftpd.tmp\\\" \\\"${temp_dir}/ftpd.msg\\\"\"\n            fi\n            if [ \"${audit_mode}\" = 0 ]; then\n              backup_file \"${message_file}\"\n              command=\"dspcat -g \\\"${message_file}\\\" > \\\"${temp_dir}/ftpd.tmp\\\"\"\n              command_message \"${command}\"\n              eval \"${command}\"\n              sed    \"s/\\\"\\%s FTP server (\\%s) ready.\\\"/\\\"\\%s Authorised uses only. All activity may be monitored and reported\\\"/\" \"${temp_dir}/ftpd.tmp\" > \"${temp_dir}/ftpd.msg\"\n              command=\"gencat \\\"${message_file}\\\" \\\"${temp_dir}/ftpd.msg\\\"\"\n              command_message \"${command}\"\n              eval \"${command}\"\n              command=\"rm \\\"${temp_dir}/ftpd.tmp\\\" \\\"${temp_dir}/ftpd.msg\\\"\"\n              command_message \"${command}\"\n              eval \"${command}\"\n            fi\n          else\n            if [ \"${audit_mode}\" = 1 ]; then\n              inc_secure \"FTP warning message enabled\"\n            fi\n          fi\n        else\n          restore_file  \"${message_file}\" \"${restore_dir}\"\n        fi\n      else\n        verbose_message \"Package \\\"${package_name}\\\" is not installed\" fix\n      fi\n    fi\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      if [ \"${os_version}\" = \"10\" ]; then\n        check_file=\"/etc/ftpd/banner.msg\"\n        check_file_value is \"${check_file}\" Authorised space \"users only\" hash\n        if [ \"${audit_mode}\" = 0 ]; then\n          check_file_perms \"${check_file}\" 0444 root root\n        fi\n      fi\n      if [ \"${os_version}\" = \"11\" ]; then\n        check_file=\"/etc/proftpd.conf\"\n        check_file_value is \"${check_file}\" DisplayConnect space /etc/issue hash\n        if [ \"${audit_mode}\" = 0 ]; then\n          svcadm restart ftp\n        fi\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/ftp/audit_ftp_client.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_ftp_client\n#\n# Refer to Section(s) 2.2.6 Page(s) 302-3 CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_ftp_client () {\n  print_function \"audit_ftp_client\"\n  string=\"FTP Client\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    for package in ftp tnftp; do\n      check_linux_package \"uninstall\" \"${package}\"\n    done\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/ftp/audit_ftp_conf.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_ftp_conf\n#\n# Audit FTP Configuration\n#.\n\naudit_ftp_conf () {\n  print_function \"audit_ftp_conf\"\n  string=\"FTP users\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"AIX\" ]; then\n    if [ \"${os_name}\" = \"AIX\" ]; then\n      audit_ftp_users \"/etc/ftpusers\"\n    fi\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      audit_ftp_users \"/etc/ftpd/ftpusers\"\n    fi\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      audit_ftp_users \"/etc/vsftpd/ftpusers\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/ftp/audit_ftp_logging.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_ftp_logging\n#\n# Check FTP logging\n#\n# Refer to Section(s) 4.2 Page(s) 67 CIS Solaris 10 Benchmark v5.1.0\n#.\n\naudit_ftp_logging () {\n  print_function \"audit_ftp_logging\"\n  string=\"FTPD Daemon Logging\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      if [ \"${os_version}\" = \"10\" ]; then\n        get_command=\"svcprop -p inetd_start/exec svc:/network/ftp:default\"\n        check_value=$( ${get_command} | grep -c \"\\-d\" )\n        file_header=\"ftpd_logging\"\n        if [ \"${audit_mode}\" != 2 ]; then\n         check_message \"File ${file_header}\"\n        fi\n        log_file=\"${work_dir}/${file_header}.log\"\n        if [ \"${audit_mode}\" = 1 ]; then\n          if [ \"${check_value}\" -eq 0 ]; then\n            inc_insecure \"FTP daemon logging not enabled\"\n            fix_message  \"inetadm -m svc:/network/ftp exec=\\\"/usr/sbin/in.ftpd -a -l -d\\\"\"\n          else\n            inc_secure   \"FTP daemon logging enabled\"\n          fi\n        else\n          if [ \"${audit_mode}\" = 0 ]; then\n            if [ \"${check_value}\" -eq 0 ]; then\n              set_message \"FTP daemon logging to enabled\"\n              eval \"${get_command} > ${log_file}\"\n              eval \"inetadm -m svc:/network/ftp exec=\\\"/usr/sbin/in.ftpd -a -l -d\\\"\"\n            fi\n          else\n            if [ \"${audit_mode}\" = 2 ]; then\n              restore_file=\"${restore_dir}/${file_header}.log\"\n              if [ -f \"${restore_file}\" ]; then\n                exec_string=$( cat \"${restore_file}\" )\n                restore_message \"Previous value for FTP daemon to \\\"${exec_string}\\\"\"\n                evel \"inetadm -m svc:/network/ftp exec=\\\"${exec_string}\\\"\"\n              fi\n            fi\n          fi\n        fi\n      fi\n    fi\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      check_file=\"/etc/vsftpd.conf\"\n      if [ -f \"${check_file}\" ]; then\n        check_file_value \"is\" \"${check_file}\" \"log_ftp_protocol\"   \"eq\" \"YES\" \"hash\"\n        check_file_value \"is\" \"${check_file}\" \"ftpd_banner\"        \"eq\" \"Authorized users only. All activity may be monitored and reported.\" \"hash\"\n        check_file_perms      \"${check_file}\" \"0600\" \"root\" \"root\"\n      fi\n      check_file=\"/etc/vsftpd/vsftpd.conf\"\n      if [ -f \"${check_file}\" ]; then\n        check_file_value \"is\" \"${check_file}\" \"log_ftp_protocol\"   \"eq\" \"YES\" \"hash\"\n        check_file_value \"is\" \"${check_file}\" \"ftpd_banner\"        \"eq\" \"Authorized users only. All activity may be monitored and reported.\" \"hash\"\n        check_file_perms      \"${check_file}\" \"0600\" \"root\" \"root\"\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/ftp/audit_ftp_server.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_ftp_server\n#\n# Turn off ftp server\n#\n# Refer to Section(s) 3.10  Page(s) 66    CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 3.10  Page(s) 78-9  CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 3.10  Page(s) 68-9  CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 2.2.9 Page(s) 109   CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 2.2.9 Page(s) 101   CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 2.2.9 Page(s) 109   CIS Ubuntu 16.04 Benchmark v1.0.0\n# Refer to Section(s) 2.1.6 Page(s) 242-4 CIS Ubuntu 24.04 Benchmark v1.0.0\n# Refer to Section(s) 4.5   Page(s) 103-4 CIS Apple OS X 10.12 Benchmark v1.0.0\n#.\n\naudit_ftp_server () {\n  print_function \"audit_ftp_server\"\n  string=\"FTP Server\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n        check_sunos_service \"svc:/network/ftp:default\" \"disabled\"\n      fi\n    fi\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      check_linux_service \"vsftpd\"    \"off\"\n      check_linux_package \"uninstall\" \"vsftpd\"\n    fi\n    if [ \"${os_name}\" = \"Darwin\" ]; then\n      check_launchctl     \"ftp\"       \"off\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/ftp/audit_ftp_umask.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_ftp_umask\n#\n# Check FTP umask\n#\n# Refer to Section(s) 2.12.10 Page(s) 214-5 CIS AIX Benchmark v1.1.0\n# Refer to Section(s) 7.4     Page(s) 65-6  CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 7.7     Page(s) 106-7 CIS Solaris 10 Benchmark v5.1.0\n#.\n\naudit_ftp_umask () {\n  print_function \"audit_ftp_umask\"\n  string=\"Default umask for FTP Users\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"AIX\" ]; then\n    if [ \"${os_name}\" = \"AIX\" ]; then\n      check_file_value    \"is\" \"/etc/inetd.conf\"     \"/usr/sbin/ftpd\" \"space\" \"ftpd -l -u077\" \"hash\"\n    fi\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      if [ \"${os_version}\" = \"10\" ]; then\n        check_file_value  \"is\" \"/etc/ftpd/ftpaccess\" \"defumask\"       \"space\" \"077\"           \"hash\"\n      fi\n      if [ \"${os_version}\" = \"11\" ]; then\n        check_file_value  \"is\" \"/etc/proftpd.conf\"   \"Umask\"          \"space\" \"027\"           \"hash\"\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/ftp/audit_ftp_users.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_ftp_users\n#\n# Check FTP users\n#\n# Refer to Section(s) 2.12.9 Page(s) 213-4 CIS AIX Benchmark v1.1.0\n# Refer to Section(s) 6.9    Page(s) 52-3  CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 6.5    Page(s) 89-91 CIS Solaris 10 Benchmark v5.1.0\n#.\n\naudit_ftp_users () {\n  print_function \"audit_ftp_users\"\n  string=\"FTP Users\"\n  check_message  \"${string}\"\n  check_file=\"${1}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"AIX\" ]; then\n    if [ \"${os_name}\" = \"AIX\" ]; then\n      for user_name in $( lsuser -c ALL | grep -v ^#name | grep -v root | cut -f1 -d: ); do\n        command=\"lsuser -f \\\"${user_name}\\\" | grep id | cut -f2 -d=\"\n        command_message \"${command}\"\n        user_check=$( eval \"${command}\" )\n        if [ \"${user_check}\" -lt 200 ]; then\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_insecure  \"User \\\"${user_name}\\\" not in \\\"${check_file}\\\"\"\n          fi\n          if [ \"${audit_mode}\" = 0 ]; then\n            backup_file       \"${check_file}\"\n            set_message       \"User \\\"${user_name}\\\" to not be allowed ftp access\"\n            check_append_file \"${check_file}\" \"${user_name}\" \"hash\"\n          fi\n        else\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_secure        \"User \\\"${user_name}\\\" in \\\"${check_file}\\\"\"\n          fi\n        fi\n      done\n      if [ \"${audit_mode}\" = 2 ]; then\n        restore_file \"${check_file}\" \"${restore_dir}\"\n      fi\n    fi\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      for user_name in adm bin daemon gdm listen lp noaccess \\\n        nobody nobody4 nuucp postgres root smmsp svctag \\\n        sys uucp webserverd; do\n        command=\"cut -f1 -d:< /etc/passwd | grep \\\"^${user_name}$\\\"\"\n        command_message \"${command}\"\n        user_check=$( eval \"${command}\" )\n        user_check=$( expr \"${user_check}\" : \"[A-z]\" )\n        if [ \"${user_check}\" = 1 ]; then\n          command=\"grep -v '^#' < \\\"${check_file}\\\" | grep \\\"^${user_name}$\\\"\"\n          command_message \"${command}\"\n          ftpuser_check=$( eval \"${command}\" )\n          ftpuser_check=$( expr \"${ftpuser_check}\" : \"[A-z]\" )\n          if [ \"${ftpuser_check}\" != 1 ]; then\n            if [ \"${audit_mode}\" = 1 ]; then\n              inc_insecure \"User \\\"${user_name}\\\" not in \\\"${check_file}\\\"\"\n            fi\n            if [ \"${audit_mode}\" = 0 ]; then\n              backup_file       \"${check_file}\"\n              set_message       \"User \\\"${user_name}\\\" to not be allowed ftp access\"\n              check_append_file \"${check_file}\" \"${user_name}\" \"hash\"\n            fi\n          else\n            if [ \"${audit_mode}\" = 1 ]; then\n              inc_secure  \"User \\\"${user_name}\\\" in \\\"${check_file}\\\"\"\n            fi\n          fi\n        fi\n      done\n      if [ \"${audit_mode}\" = 2 ]; then\n        restore_file \"${check_file}\" \"${restore_dir}\"\n      fi\n    fi\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      for user_name in root bin daemon adm lp sync shutdown halt mail \\\n        news uucp operator games nobody; do\n        command=\"cut -f1 -d:< /etc/passwd | grep \\\"^${user_name}$\\\"\"\n        command_message \"${command}\"\n        user_check=$( eval \"${command}\" )\n        user_check=$( expr \"${user_check}\" : \"[A-z]\" )\n        if [ \"${user_check}\" = 1 ]; then\n          command=\"grep -v '^#' < \\\"${check_file}\\\" | grep \\\"^${user_name}$\\\"\"\n          command_message \"${command}\"\n          ftpuser_check=$( eval \"${command}\" )\n          ftpuser_check=$( expr \"${ftpuser_check}\" : \"[A-z]\" )\n          if [ \"${ftpuser_check}\" != 1 ]; then\n            if [ \"${audit_mode}\" = 1 ]; then\n              inc_insecure  \"User \\\"${user_name}\\\" not in \\\"${check_file}\\\"\"\n            fi\n            if [ \"${audit_mode}\" = 0 ]; then\n              backup_file       \"${check_file}\"\n              set_message       \"User \\\"${user_name}\\\" to not be allowed ftp access\"\n              check_append_file \"${check_file}\" \"${user_name}\" \"hash\"\n            fi\n          else\n            if [ \"${audit_mode}\" = 1 ]; then\n              inc_secure  \"User \\\"${user_name}\\\" in \\\"${check_file}\\\"\"\n            fi\n          fi\n        fi\n      done\n      if [ \"${audit_mode}\" = 2 ]; then\n        restore_file \"${check_file}\" \"${restore_dir}\"\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/ftp/audit_tftp_client.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_tftp_client\n#\n# Turn off TFTP\n#\n# Refer to Section(s) 2.1.7 Page(s) 51   CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 2.1.7 Page(s) 59   CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 2.1.7 Page(s) 54-5 CIS RHEL 6 Benchmark v1.2.0\n#.\n\naudit_tftp_client () {\n  print_function \"audit_tftp_client\"\n  string=\"TFTP Client\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${os_vendor}\" = \"CentOS\" ] || [ \"${os_vendor}\" = \"Red\" ]; then\n      check_linux_package \"uninstall\" \"tftp\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/ftp/audit_tftp_server.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_tftp_server\n#\n# Turn off tftp\n#\n# Refer to Section(s) 2.1.8   Page(s) 52    CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 2.1.8   Page(s) 60    CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 2.2.20  Page(s) 121   CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 5.1.8   Page(s) 45    CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 6.9     Page(s) 58-9  CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 2.1.16  Page(s) 270-2 CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_tftp_server () {\n  print_function \"audit_tftp_server\"\n  string=\"TFTP Server\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n        check_file_perms    \"/tftpboot\"                      \"0744\" \"root\" \"root\"\n        check_file_perms    \"/etc/netboot\"                   \"0744\" \"root\" \"root\"\n        check_sunos_service \"svc:/network/tftp/udp6:default\" \"disabled\"\n        check_sunos_service \"svc:/network/tftp/udp4:default\" \"disabled\"\n      fi\n    fi\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      check_linux_service   \"tftp\"          \"off\"\n      check_file_perms      \"/tftpboot\"     \"0744\" \"root\"    \"root\"\n      check_file_perms      \"/var/tftpboot\" \"0744\" \"root\"    \"root\"\n      if [ \"${os_vendor}\" = \"CentOS\" ] || [ \"${os_vendor}\" = \"Red\" ] || [ \"${os_vendor}\" = \"Amazon\" ]; then\n        check_linux_service \"tftp.socket\"   \"off\"\n        check_linux_package \"uninstall\"     \"tftp-server\"\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/full/full_audit_accounting_services.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# full_audit_accounting_services\n#\n# Audit accounting services\n#.\n\nfull_audit_accounting_services() {\n  print_function \"full_audit_accounting_services\"\n  audit_system_accounting\n  audit_process_accounting\n  audit_audit_class\n  audit_sar_accounting\n  audit_prelink\n  audit_aide\n}\n"
  },
  {
    "path": "modules/full/full_audit_disk_services.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# full_audit_disk_services\n#\n# Audit disk and hardware related services\n#.\n\nfull_audit_disk_services () {\n  print_function \"full_audit_disk_services\"\n  audit_svm\n  audit_svm_gui\n  audit_iscsi\n}\n"
  },
  {
    "path": "modules/full/full_audit_file_services.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# full_audit_file_services\n#\n# Audit file permissions\n#.\n\nfull_audit_file_services () {\n  print_function \"full_audit_file_services\"\n  audit_syslog_perms\n  audit_volfs\n  audit_autofs\n  audit_dfstab\n  audit_mount_setuid\n  audit_mount_nodev\n  audit_mount_noexec\n  audit_mount_fdi\n  audit_nfs\n  audit_uucp\n  audit_cd_sharing\n  audit_filesystem_partitions\n}\n"
  },
  {
    "path": "modules/full/full_audit_firewall_services.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# full_audit_firewall_services\n#\n# Audit firewall related services\n#.\n\nfull_audit_firewall_services () {\n  print_function \"full_audit_firewall_services\"\n  audit_ipsec\n  audit_ipfilter\n  audit_tcp_wrappers\n  audit_iptables\n  audit_ipfw\n  audit_suse_firewall\n}\n"
  },
  {
    "path": "modules/full/full_audit_ftp_services.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# full_audit_ftp_services\n#\n# Audit FTP Services\n\nfull_audit_ftp_services () {\n  print_function \"full_audit_ftp_services\"\n  audit_ftp_logging\n  audit_ftp_umask\n  audit_ftp_conf\n  audit_ftp_client\n  audit_ftp_server\n  audit_tftp_server\n  audit_ftp_banner\n}\n"
  },
  {
    "path": "modules/full/full_audit_hardware_services.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# full_audit_hardware_services\n#\n# Audit hardware related services\n#.\n\nfull_audit_hardware_services () {\n  print_function \"full_audit_hardware_services\"\n  audit_hotplug\n}\n"
  },
  {
    "path": "modules/full/full_audit_kernel_services.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# full_audit_kernel_services\n#\n# Audit kernel services\n#.\n\nfull_audit_kernel_services () {\n  print_function \"full_audit_kernel_services\"\n  audit_sysctl\n  #audit_kernel_modules\n  audit_kernel_accounting\n  audit_kernel_params\n  audit_tcp_syn_cookie\n  audit_stack_protection\n  audit_tcp_strong_iss\n  audit_routing_params\n  audit_modprobe_conf\n  audit_unconfined_daemons\n  audit_selinux\n  audit_execshield\n  audit_apparmor\n  audit_virtual_memory\n  audit_ptrace_scope\n}\n"
  },
  {
    "path": "modules/full/full_audit_log_services.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# full_audit_log_services\n#\n# Audit log files and log related services\n#.\n\nfull_audit_log_services () {\n  print_function \"full_audit_log_services\"\n  audit_syslog_server\n  audit_linux_logfiles\n  audit_syslog_conf\n  audit_debug_logging\n  audit_syslog_auth\n  audit_core_dumps\n  audit_cron_logging\n  audit_logrotate\n}\n"
  },
  {
    "path": "modules/full/full_audit_mail_services.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# full_audit_mail_services\n#\n# Audit sendmail\n\nfull_audit_mail_services () {\n  print_function \"full_audit_mail_services\"\n  audit_sendmail_daemon\n  audit_sendmail_greeting\n  audit_sendmail_aliases\n  audit_email_daemons\n  audit_postfix_daemon\n  audit_exim\n}\n"
  },
  {
    "path": "modules/full/full_audit_naming_services.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# full_audit_naming_services\n#\n# Audit Naming Services\n#.\n\nfull_audit_naming_services () {\n  print_function \"full_audit_naming_services\"\n  audit_nis_server\n  audit_nis_client\n  audit_nisplus\n  audit_ldap_cache\n  audit_kerberos_tgt\n  audit_gss\n  audit_keyserv\n  audit_dns_client\n  audit_dns_server\n  audit_krb5\n  audit_nis_entries\n  audit_avahi_server\n  audit_avahi_conf\n}\n"
  },
  {
    "path": "modules/full/full_audit_network_services.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# full_audit_network_services\n#\n# Audit Network Service\n#.\n\nfull_audit_network_services () {\n  print_function \"full_audit_network_services\"\n  audit_snmp\n  audit_ntp\n  audit_ipmi\n  audit_echo\n  audit_ocfserv\n  audit_tname\n  audit_service_tags\n  audit_ticotsord\n  audit_boot_server\n  audit_slp\n  audit_tnd\n  audit_nobody_rpc\n  audit_dhcpcd\n  audit_dhcprd\n  audit_dhcpsd\n  audit_mob\n  audit_dvfilter\n  audit_wireless\n  audit_ufw\n}\n"
  },
  {
    "path": "modules/full/full_audit_osx_services.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# full_audit_osx_services\n#\n# Audit All System\n#.\n\nfull_audit_osx_services () {\n  print_function \"full_audit_osx_services\"\n  audit_bluetooth\n  audit_guest_sharing\n  audit_file_sharing\n  audit_web_sharing\n  audit_login_warning\n  audit_firewall_setting\n  audit_infrared_remote\n  audit_setup_file\n  audit_screen_lock\n  audit_screen_sharing\n  audit_sleep\n  audit_secure_swap\n  audit_login_guest\n  audit_login_details\n  audit_core_limit\n  audit_remote_apple_events\n  audit_remote_management\n  audit_wake_on_lan\n  audit_file_vault\n  audit_gate_keeper\n  audit_safe_downloads\n  audit_secure_keyboard_entry\n  audit_bonjour_advertising\n  audit_keychain_lock\n  audit_keychain_sync\n  audit_auto_login\n  audit_auto_logout\n  audit_file_extensions\n  audit_internet_sharing\n  audit_java\n  audit_asl\n  audit_auditd\n  audit_wireless\n  audit_app_perms\n  audit_login_root\n  audit_system_preferences\n  audit_system_integrity\n  audit_icloud_drive\n  audit_air_drop\n  audit_air_play\n  audit_asset_cache\n  audit_media_sharing\n  audit_time_machine\n  audit_siri\n  audit_location_services\n  audit_usage_data\n  audit_screen_corner\n  audit_lockdown\n  audit_universal_control\n  audit_touch_id\n  audit_apfs\n  audit_core_storage\n  audit_amfi\n  audit_sudo_timeout\n  audit_sudo_timestamp\n  audit_sudo_authenticate\n  audit_sudo_nopassword\n  audit_sudo_logfile\n  audit_sudo_usepty\n  audit_sudo_perms\n  audit_safari_auto_run\n  audit_safari_history\n  audit_safari_warn\n  audit_safari_tracking\n  audit_safari_auto_fill\n  audit_safari_allow_popups\n  audit_safari_javascript\n  audit_safari_show_statusbar\n  audit_account_switching\n}\n"
  },
  {
    "path": "modules/full/full_audit_other_daemons.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# full_audit_other_daemons\n#\n# Audit other daemons and startup services\n#.\n\nfull_audit_other_daemons () {\n  print_function \"full_audit_other_daemons\"\n  audit_xinetd\n  audit_other_daemons\n  audit_legacy\n  audit_inetd\n  audit_inetd_logging\n  audit_online_documentation\n  audit_ncs\n  audit_i4ls\n}\n"
  },
  {
    "path": "modules/full/full_audit_other_services.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# full_audit_other_services\n#\n# Other remaining services\n#.\n\nfull_audit_other_services () {\n  print_function \"full_audit_other_services\"\n  audit_bluetooth\n  audit_postgresql\n  audit_encryption_kit\n  audit_biosdevname\n  audit_apport\n  audit_pae\n}\n"
  },
  {
    "path": "modules/full/full_audit_password_services.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# full_audit_password_services\n#\n# Audit password related services\n#.\n\nfull_audit_password_services () {\n  print_function \"full_audit_password_services\"\n  audit_rsa_securid_pam\n  audit_system_auth\n  audit_system_auth_use_uid\n  audit_password_expiry\n  audit_password_strength\n  audit_passwd_perms\n  audit_retry_limit\n  audit_login_records\n  audit_failed_logins\n  audit_login_delay\n  audit_pass_req\n  audit_pam_wheel\n  audit_pam_authtok\n  audit_password_hashing \"${password_hashing}\"\n  audit_pam_deny\n  audit_crypt_policy\n  audit_account_lockout\n  audit_sudo_timeout\n  audit_sudo_timestamp\n  audit_sudo_authenticate\n  audit_sudo_nopassword\n  audit_sudo_logfile\n  audit_sudo_usepty\n  audit_sudo_perms\n}\n"
  },
  {
    "path": "modules/full/full_audit_power_services.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# full_audit_power_services\n#.\n# Audit power related services\n#.\n\nfull_audit_power_services () {\n  print_function \"full_audit_power_services\"\n  audit_power_management\n  audit_sys_suspend\n}\n"
  },
  {
    "path": "modules/full/full_audit_print_services.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# full_audit_print_services\n#\n# Audit print services\n#.\n\nfull_audit_print_services () {\n  print_function \"full_audit_print_services\"\n  audit_ppd_cache\n  audit_print\n  audit_cups\n  audit_printer_sharing\n}\n"
  },
  {
    "path": "modules/full/full_audit_routing_services.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# full_audit_routing_services\n#\n# Audit routing services\n#.\n\nfull_audit_routing_services () {\n  print_function 'full_audit_routing_services'\n  audit_routing_daemons\n  audit_routing_params\n}\n"
  },
  {
    "path": "modules/full/full_audit_shell_services.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# full_audit_shell_services\n#\n# Audit remote shell services\n#.\n\nfull_audit_shell_services () {\n  print_function \"full_audit_shell_services\"\n  audit_issue_banner\n  audit_ssh_config\n  audit_ssh_perms\n  audit_remote_consoles\n  audit_ssh_forwarding\n  audit_remote_shell\n  audit_console_login\n  audit_security_banner\n  audit_xinetd_server\n  audit_telnet_banner\n  audit_telnet_server\n  audit_talk_server\n  audit_talk_client\n  audit_pam_rhosts\n  audit_user_netrc\n  audit_user_rhosts\n  audit_rhosts_files\n  audit_netrc_files\n  audit_serial_login\n  audit_sulogin\n  audit_shell_timeout\n  audit_esxi_shell\n}\n"
  },
  {
    "path": "modules/full/full_audit_update_services.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# full_audit_update_services\n#\n# Update services\n#.\n\nfull_audit_update_services () {\n  print_function \"full_audit_update_services\"\n  audit_yum_conf\n  audit_software_update\n}\n"
  },
  {
    "path": "modules/full/full_audit_user_services.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# full_audit_user_services\n#\n# Audit users and groups\n#.\n\nfull_audit_user_services () {\n  print_function \"full_audit_user_services\"\n  audit_root_access\n  audit_root_home\n  audit_root_path\n  audit_root_primary_group\n  audit_root_ssh_keys\n  audit_mesgn\n  audit_writesrv\n  audit_groups_exist\n  audit_home_perms\n  audit_home_ownership\n  audit_duplicate_users\n  audit_duplicate_groups\n  audit_user_dotfiles\n  audit_forward_files\n  audit_default_umask\n  audit_password_fields\n  audit_password_lock\n  audit_password_history\n  audit_group_fields\n  audit_reserved_ids\n  audit_super_users\n  audit_daemon_umask\n  audit_cron_perms\n  audit_wheel_group\n  audit_wheel_su\n  audit_old_users\n  audit_cron_allow\n  audit_cron\n  audit_system_accounts\n  audit_shadow_group\n  audit_dcui\n}\n"
  },
  {
    "path": "modules/full/full_audit_virtualisation_services.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# full_audit_virtualisation_services\n#\n# Audit vitualisation services\n#.\n\nfull_audit_virtualisation_services () {\n  print_function \"full_audit_virtualisation_services\"\n  audit_zones\n  audit_xen\n}\n"
  },
  {
    "path": "modules/full/full_audit_web_services.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# full_audit_web_services\n#\n# Audit web services\n\nfull_audit_web_services () {\n  print_function \"full_audit_web_services\"\n  audit_webconsole\n  audit_wbem\n  audit_apache\n  audit_webmin\n}\n"
  },
  {
    "path": "modules/full/full_audit_windows_services.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# full_audit_windows_services\n#\n# Audit windows services\n#.\n\nfull_audit_windows_services () {\n  print_function \"full_audit_windows_services\"\n  audit_smbpasswd_perms\n  audit_smbconf_perms\n  audit_samba\n  audit_wins\n  audit_winbind\n}\n"
  },
  {
    "path": "modules/full/full_audit_x11_services.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# full_audit_x11_services\n#\n# Audit X11 Services\n#.\n\nfull_audit_x11_services () {\n  print_function \"full_audit_x11_services\"\n  audit_cde_ttdb\n  audit_cde_cal\n  audit_cde_spc\n  audit_cde_print\n  audit_xlogin\n  audit_gdm_conf\n  audit_cde_banner\n  audit_gnome_banner\n  audit_cde_screen_lock\n  audit_gnome_screen_lock\n  audit_gnome_automount\n  audit_opengl\n  audit_font_server\n  audit_vnc\n  audit_xwindows_server\n}\n"
  },
  {
    "path": "modules/groups/audit_duplicate_groups.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_duplicate_groups\n#\n# Check duplicate groups\n#\n# Refer to Section(s) 9.2.15,17 Page(s) 173-5         CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 9.2.16,19 Page(s) 204-5         CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 9.2.15,17 Page(s) 176-9         CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 10.15,17  Page(s) 164-7         CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 2.2.17    Page(s) 220           CIS AIX Benchmark v1.1.0\n# Refer to Section(s) 9.16,19   Page(s) 83-4,5-6      CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 9.16,19   Page(s) 129-30,131-2  CIS Solaris 10 Benchmark v1.1.0\n# Refer to Section(s) 6.2.17,19 Page(s) 270,72        CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 6.2.17,19 Page(s) 284,6         CIS Ubuntu 16.04 Benchmark v1.0.0\n# Refer to Section(s) 7.2.6,8   Page(s) 975-6,979-80  CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_duplicate_groups () {\n  print_function \"audit_duplicate_groups\"\n  string=\"Duplicate Groups\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"AIX\" ]; then\n    audit_duplicate_ids \"1\" \"groups\" \"name\" \"/etc/group\"\n    audit_duplicate_ids \"3\" \"groups\" \"id\"   \"/etc/group\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/groups/audit_group_fields.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n\n# audit_group_fields\n#\n# Refer to Section(s) 5.4.2.3 Page(s) 698-9 CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_group_fields () {\n  print_function \"audit_group_fields\"\n  string=\"Group Fields\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"FreeBSD\" ] || [ \"${os_name}\" = \"AIX\" ]; then\n    if [ \"${audit_mode}\" != 2 ]; then\n      check_file=\"/etc/group\"\n      group_list=$( awk -F: '($3 == 0) { print $1 }' \"${check_file}\" | grep -v root )\n      if [ \"${group_list}\" = \"\" ]; then\n        inc_secure \"No non root groups have GID 0\"\n      else\n        for group_name in ${group_list}; do\n          if [ \"$group_name\" != \"root\" ]; then\n            inc_insecure \"Non root group ${group_name} has GID 0\"\n          fi\n        done\n      fi\n    else\n      check_file=\"/etc/group\"\n      restore_file \"${check_file}\" \"${restore_dir}\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/groups/audit_groups_exist.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2046\n# shellcheck disable=SC2154\n\n# audit_groups_exist\n#\n# Check groups\n#\n# Refer to Section(s) 9.2.11 Page(s) 170-1 CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 9.2.11 Page(s) 196-7 CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 9.2.11 Page(s) 173-4 CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 6.2.15 Page(s) 282   CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 13.11  Page(s) 161-2 CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 9.11   Page(s) 80    CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 9.11   Page(s) 124-5 CIS Solaris 10 Benchmark v1.1.0\n# Refer to Section(s) 6.2.15 Page(s) 269   CIS Amazon Linux Benchmark v2.1.0\n# Refer to Section(s) 6.2.15 Page(s) 282   CIS Ubuntu 16.04 Benchmark v1.0.0       \n# Refer to Section(s) 7.2.3  Page(s) 970-1 CIS Ubuntu 24.04 Benchmark v1.0.0       \n#.\n\naudit_groups_exist () {\n  print_function \"audit_groups_exist\"\n  string=\"User Groups\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ]; then\n    check_file=\"/etc/group\"\n    group_fail=0\n    if [ \"${audit_mode}\" != 2 ]; then\n      for group_id in $( getent passwd | cut -f4 -d \":\" ); do\n        group_exists=$( grep -v \"^#\" \"${check_file}\" | cut -f3 -d:| grep -c \"^${group_id}$\" | sed \"s/ //g\" )\n        if [ \"$group_exists\" = 0 ]; then\n          group_fail=1\n          if [ \"${audit_mode}\" = 1 ];then\n            inc_insecure \"Group \\\"${group_id}\\\" does not exist in group file \\\"${check_file}\\\"\"\n          fi\n        fi\n      done\n      if [ \"${group_fail}\" != 1 ]; then\n        if [ \"${audit_mode}\" = 1 ];then\n          inc_secure \"No non existant group issues\"\n        fi\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/groups/audit_root_primary_group.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_root_primary_group\n#\n# Check root primary group\n#\n# Refer to Section(s) 7.3   Page(s) 147     CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 7.3   Page(s) 170     CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 7.3   Page(s) 150     CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 5.4.3 Page(s) 253     CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 10.3  Page(s) 139-140 CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 5.4.3 Page(s) 232     CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 7.4   Page(s) 104-5   CIS Solaris 10 Benchmark v5.1.0\n# Refer to Section(s) 5.4.3 Page(s) 245     CIS Ubuntu 16.04 Benchmark v1.0.0\n#.\n\naudit_root_primary_group () {\n  print_function \"audit_root_primary_group\"\n  string=\"Root Primary Group\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ]; then\n    log_file=\"root_primary_group.log\"\n    check_file=\"/etc/group\"\n    group_check=$( grep \"^root:\" /etc/passwd | cut -f4 -d: )\n    if [ \"${audit_mode}\" != 2 ]; then\n      if [ \"${group_check}\" != \"0\" ];then\n        if [ \"${audit_mode}\" = 1 ]; then\n          inc_insecure \"Group \\\"${group_id}\\\" does not exist in group file \\\"${check_file}\\\"\"\n          fix_message  \"usermod -g 0 root\"\n        fi\n        if [ \"${audit_mode}\" = 0 ];then\n          log_file=\"${work_dir}/${log_file}\"\n          echo \"${group_check}\" > \"${log_file}\"\n          set_message \"Primary group for root to root\"\n          usermod -g 0 root\n        fi\n      else\n        if [ \"${audit_mode}\" = 1 ]; then\n          inc_secure \"Primary group for root is root\"\n        fi\n      fi\n    else\n      restore_file=\"${restore_dir}/${log_file}\"\n      if [ -e \"${restore_file}\" ]; then\n        restore_value=$( cat \"${restore_file}\" )\n        if [ \"${restore_value}\" != \"${group_check}\" ]; then\n          verbose_message \"Restoring: Primary root group to \\\"${restore_value}\\\"\" \"restore\"\n          usermod -g \"${restore_value}\" root\n        fi\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/gui/audit_font_server.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_font_server\n#\n# Turn off font server\n#.\n\naudit_font_server () {\n  print_function \"audit_font_server\"\n  string=\"Font Server\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n        for service_name in \"svc:/application/x11/xfs:default\" \\\n          \"svc:/application/font/stfsloader:default\" \\\n          \"svc:/application/font/fc-cache:default\"; do\n          check_sunos_service \"${service_name}\" \"disabled\"\n        done\n      fi\n    fi\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      service_name=\"xfs\"\n      check_linux_service \"${service_name}\" \"off\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/gui/audit_gdm_conf.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_gdm_conf\n#\n# Gnome Display Manager should not be used on a server, but if it is it\n# should be locked down to disable root access.\n#\n# Refer to Section(s) 1.8.10    Page(s) 193-4       CIS Ubuntu 22.04 Benchmaek v1.0.0\n# Refer to Section(s) 1.7.1,10  Page(s) 197-8,223-5 CIS Ubuntu 24.04 Benchmaek v1.0.0\n#.\n\naudit_gdm_conf () {\n  print_function \"audit_gdm_conf\"\n  string=\"GDM Configuration\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    check_file=\"/etc/X11/gdm/gdm.conf\"\n    if [ -e \"${check_file}\" ]; then\n      check_linux_package \"uninstall\" \"gdm3\"\n      check_message       \"${string}\" \"check\"\n      check_file_value    \"is\" \"${check_file}\" \"AllowRoot\"           \"eq\" \"false\" \"hash\"\n      check_file_value    \"is\" \"${check_file}\" \"AllowRemoteRoot\"     \"eq\" \"false\" \"hash\"\n      check_file_value    \"is\" \"${check_file}\" \"Use24Clock\"          \"eq\" \"true\"  \"hash\"\n      check_file_perms         \"${check_file}\" \"0644\" \"root\"\"root\"\n    fi\n    check_file=\"/etc/gdm3/greeter.dconf-defaults\"\n    if [ -e \"${check_file}\" ]; then\n      check_message       \"GDM3 Greeter User List Configuration\"\n      check_file_value    \"is\" \"${check_file}\" \"disable-user-list\"   \"eq\" \"true\"  \"hash\"\n    fi\n    for check_file in /etc/gdm/custom.conf /etc/gdm3/custom.conf /etc/gdm/daemon.conf /etc/gdm3/daemon.conf; do\n      if [ -e \"${check_file}\" ]; then\n        verbose_message  \"GDM3 XDMCP Configuration\" \"check\"\n        check_file_value_with_position \"is\" \"${check_file}\" \"Enable\" \"eq\" \"false\" \"hash\" \"after\" \"xdmcp\"\n      fi\n    done\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/gui/audit_gnome_automount.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2046\n# shellcheck disable=SC2129\n# shellcheck disable=SC2154\n\n# audit_gnome_automount\n#\n# Check Gnome Automount\n#\n# Refer to Section(s) 1.8.6-9 Page(s) 172-92  CIS Ubuntu 22.04 Benchmaek v1.0.0\n# Refer to Section(s) 1.7.7-9 Page(s) 214-22  CIS Ubuntu 24.04 Benchmaek v1.0.0\n#.\n\naudit_gnome_automount () {\n  print_function \"audit_gnome_automount\"\n  string=\"Automount/Autorun for GNOME Users\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    check_gsettings_value \"org.gnome.desktop.media-handling\" \"automount-open\" \"false\"\n    check_gsettings_value \"org.gnome.desktop.media-handling\" \"automount\"      \"false\"\n    check_gsettings_value \"org.gnome.desktop.media-handling\" \"autorun-never\"  \"true\"\n    if [ \"${os_vendor}\" = \"Ubuntu\" ]; then\n      if [ \"${os_version}\" -ge 22 ]; then \n        if [ -d \"/etc/dconf\" ]; then\n          check_file=\"/etc/dconf/db/ibus.d/00-media-automount\"\n          if [ \"${ansible_mode}\" = 1 ]; then\n            string=\"Automount GNOME Users\"\n            echo \"- name: ${string}\"\n            echo \"  copy:\"\n            echo \"    content: |\"\n            echo \"             [org/gnome/desktop/media-handling]\"\n            echo \"             automount-open=false\"\n            echo \"             automount=false\"\n            echo \"    dest: ${check_file}\"\n          fi\n          if [ -f \"${check_file}\" ]; then\n            check_file_value_with_position \"is\" \"${check_file}\" \"automount-open\" \"eq\" \"false\" \"hash after\" \"handling\"\n            check_file_value_with_position \"is\" \"${check_file}\" \"automount\"      \"eq\" \"false\" \"hash after\" \"handling\"\n            check_file_value_with_position \"is\" \"${check_file}\" \"autorun-never\"  \"eq\" \"true\"  \"hash after\" \"handling\"\n          else\n            if [ \"${audit_mode}\" = 1 ]; then\n              fix_message \"echo \\\"[org/gnome/desktop/media-handling]\\\"  >  ${check_file}\"\n              fix_message \"echo \\\"automount-open=false\\\"                >> ${check_file}\"\n              fix_message \"echo \\\"automount=false\\\"                     >> ${check_file}\"\n              fix_message \"echo \\\"autorun-never=true\\\"                  >> ${check_file}\"\n              fix_message \"dconf update\" \"fix\"\n            fi \n            if [ \"${audit_mode}\" = 0 ]; then\n              echo \"[org/gnome/desktop/media-handling]\" >  \"${check_file}\"\n              echo \"automount-open=false\"               >> \"${check_file}\"\n              echo \"automount=false\"                    >> \"${check_file}\"\n              echo \"autorun-never=true\"                 >> \"${check_file}\"\n              dconf update\n            fi          \n            if [ \"${audit_mode}\" = 2 ]; then\n              if [ -f \"${check_file}\" ]; then\n                rm \"${check_file}\"\n              fi\n            fi\n          fi\n          check_file=\"/etc/dconf/db/ibus.d/locks/00-media-automount\"\n          if [ \"${ansible_mode}\" = 1 ]; then\n            string=\"Automount/Autorun Lock GNOME Users\"\n            echo \"- name: ${string}\"\n            echo \"  copy:\"\n            echo \"    content: |\"\n            echo \"             /org/gnome/desktop/media-handling/automount\"\n            echo \"             /org/gnome/desktop/media-handling/automount-open\"\n            echo \"             /org/gnome/desktop/media-handling/autorun-never\"\n            echo \"    dest: ${check_file}\"\n          fi\n          if [ -f \"${check_file}\" ]; then\n            check_append_file \"${check_file}\" \"/org/gnome/desktop/media-handling/automount-false\" \"hash\"\n            check_append_file \"${check_file}\" \"/org/gnome/desktop/media-handling/automount\"       \"hash\"\n            check_append_file \"${check_file}\" \"/org/gnome/desktop/media-handling/autorun-never\"   \"hash\"\n          else\n            if [ \"${audit_mode}\" = 1 ]; then\n              fix_message \"mkdir -p /etc/dconf/db/ibus.d/locks\"\n              fix_message \"echo \\\"/org/gnome/desktop/media-handling/automount\\\"       >  ${check_file}\"\n              fix_message \"echo \\\"/org/gnome/desktop/media-handling/automount-open\\\"  >> ${check_file}\"\n              fix_message \"echo \\\"/org/gnome/desktop/media-handling/autorun-never\\\"   >> ${check_file}\"\n              fix_message \"dconf update\" \"fix\"\n            fi \n            if [ \"${audit_mode}\" = 0 ]; then\n              mkdir -p /etc/dconf/db/ibus.d/locks\n              echo \"/org/gnome/desktop/media-handling/automount\"      > \"${check_file}\"\n              echo \"/org/gnome/desktop/media-handling/automount-open\" > \"${check_file}\"\n              echo \"/org/gnome/desktop/media-handling/autorun-never\"  > \"${check_file}\"\n              dconf update\n            fi          \n            if [ \"${audit_mode}\" = 2 ]; then\n              if [ -f \"${check_file}\" ]; then\n                rm \"${check_file}\"\n              fi\n            fi\n          fi\n        fi\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/gui/audit_gnome_banner.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2046\n# shellcheck disable=SC2086\n# shellcheck disable=SC2154\n\n# audit_gnome_banner\n#\n# Create Warning Banner for GNOME Users\n#\n# Refer to Section(s) 8.3   Page(s) 151   CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 8.2   Page(s) 174-5 CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 8.3   Page(s) 154-5 CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 11.3  Page(s) 143-4 CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 1.7.2 Page(s) 84-5  CIS Ubuntu 16.04 Benchmark v1.0.0\n# Refer to Section(s) 8.3   Page(s) 69-70 CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 8.3   Page(s) 113-4 CIS Solaris 10 Benchmark v5.1.0\n#.\n\naudit_gnome_banner () {\n  print_function \"audit_gnome_banner\"\n  string=\"Gnome Warning Banner\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      if [ \"${os_version}\" = \"10\" ]; then\n        check_file_value \"is\" \"/etc/X11/gdm.conf\" \"Welcome\" \"eq\" \"Authorised users only\" \"hash\"\n      fi\n      if [ \"${os_version}\" = \"11\" ]; then\n        check_file=\"/etc/gdm/Init/Default\"\n        if [ \"${audit_mode}\" != 2 ]; then\n          if [ -f \"${check_file}\" ]; then\n            gdm_check=$( grep 'Security Message' \"${check_file}\" | cut -f3 -d= )\n            if [ \"${gdm_check}\" != \"/etc/issue\" ]; then\n              if [ \"${audit_mode}\" = 1 ]; then\n                inc_insecure \"Warning banner not found in \\\"${check_file}\\\"\"\n                fix_message  \"echo \\\"   --title=\\\"Security Message\\\" --filename=/etc/issue\\\" >> ${check_file}\"\n              fi\n              if [ \"${audit_mode}\" = 0 ]; then\n                backup_file \"${check_file}\"\n                verbose_message \"Setting:   Warning banner in \\\"${check_file}\\\"\"\n                echo \"   --title=\\\"Security Message\\\" --filename=/etc/issue\" >> \"${check_file}\"\n                if [ \"${os_version}\" = \"10\" ]; then\n                  eval \"pkgchk -f -n -p ${check_file} 2> /dev/null\"\n                else\n                  pkg fix $( pkg search \"${check_file}\" | grep pkg | awk '{print $4}' )\n                fi\n              fi\n            fi\n            if [ \"${file_entry}\" = \"\" ]; then\n              if [ \"${audit_mode}\" = 1 ]; then\n                inc_secure \"Warning banner in \\\"${check_file}\\\"\"\n              fi\n            fi\n          else\n            restore_file \"${check_file}\" \"${restore_dir}\"\n          fi\n        fi\n      fi\n    fi\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      check_file=\"/etc/dconf/profile/gdm\"\n      if [ -f \"${check_file}\" ]; then\n        check_file_value \"is\" \"${check_file}\" \"user-db\"               \"colon\" \"user\"  \"hash\"\n        check_file_value \"is\" \"${check_file}\" \"system-db\"             \"colon\" \"gdm\"   \"hash\"\n        check_file_value \"is\" \"${check_file}\" \"file-db\"               \"colon\" \"/usr/share/gdm/greeter-dconf-defaults\" \"hash\"\n      fi\n      check_file=\"/etc/dconf/db/gdm.d/01-banner-message\"\n      if [ -f \"${check_file}\" ]; then\n        check_file_value \"is\" \"${check_file}\" \"banner-message-enable\" \"eq\"    \"true\"  \"hash\"\n        check_file_value \"is\" \"${check_file}\" \"banner-message-text\"   \"eq\"    \"Authorized uses only. All activity may be monitored and reported.\" \"hash\"\n      fi\n      check_file=\"/etc/gdm3/greeter.dconf-defaults\"\n      if [ -f \"${check_file}\" ]; then\n        check_file_value \"is\" \"${check_file}\" \"banner-message-enable\" \"eq\"    \"true\"  \"hash\"\n        check_file_value \"is\" \"${check_file}\" \"banner-message-text\"   \"eq\"    \"Authorized uses only. All activity may be monitored and reported.\" \"hash\"\n      fi\n    fi\n    gconf_test=$( command -v gconftool 2> /dev/null | wc -l | sed \"s/ //g\" )\n    if [ \"$gconf_test\" = \"1\" ]; then\n      gconf_bin=$( command -v gconftool 2> /dev/null )\n    fi\n    if [ \"${os_name}\" = \"Linux\" ] && [ \"$gconf_test\" = \"1\" ]; then\n      warn_message=\"Authorised users only\"\n      actual_value=$( gconftool-2 --get /apps/gdm/simple-greeter/banner_message_text )\n      log_file=\"gnome_banner_warning\"\n      if [ \"${audit_mode}\" != 2 ]; then\n        if [ \"${actual_value}\" != \"${warning_message}\" ]; then\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_insecure \"Warning banner not found in \\\"${check_file}\\\"\"\n            fix_message  \"gconftool-2 -direct -config-source=xml:readwrite:$HOME/.gconf -t string -s /apps/gdm/simple-greeter/banner_message_text \\\"${warning_message}\\\"\"\n          fi\n          if [ \"${audit_mode}\" = 0 ]; then\n            verbose_message \"Setting:   Warning banner to \\\"${warning_message}\\\"\"\n            log_file=\"${work_dir}/${log_file}\"\n            echo \"${actual_value}\" > \"${log_file}\"\n            gconftool-2 -direct -config-source=xml:readwrite:$HOME/.gconf -t string -s /apps/gdm/simple-greeter/banner_message_text \\\"${warning_message}\\\"\n          fi\n        else\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_secure \"Warning banner is set to \\\"${warning_message}\\\"\"\n          fi\n        fi\n      else\n        log_file=\"${restore_dir}/${log_file}\"\n        if [ -f \"${log_file}\" ]; then\n          restore_value=$( cat \"${log_file}\" )\n          if [ \"${restore_value}\" != \"${actual_value}\" ]; then\n            verbose_message \"Restoring: Warning banner to ${previous_value}\"\n            eval \"gconftool-2 -direct -config-source=xml:readwrite:$HOME/.gconf -t string -s /apps/gdm/simple-greeter/banner_message_text ${restore_value}\"\n          fi\n        fi\n      fi\n      actual_value=$( gconftool-2 --get /apps/gdm/simple-greeter/banner_message_enable )\n      log_file=\"gnome_banner_status\"\n      if [ \"${audit_mode}\" != 2 ]; then\n        if [ \"${actual_value}\" != \"true\" ]; then\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_insecure \"Warning banner not found in \\\"${check_file}\\\"\"\n            fix_message  \"gconftool-2 -direct -config-source=xml:readwrite:$HOME/.gconf -type bool -set /apps/gdm/simple-greeter/banner_message_enable true\"\n          fi\n          if [ \"${audit_mode}\" = 0 ]; then\n            set_message \"Warning banner to \\\"${warning_message}\\\"\"\n            log_file=\"${work_dir}/${log_file}\"\n            echo \"${actual_value}\" > \"${log_file}\"\n            eval \"gconftool-2 -direct -config-source=xml:readwrite:$HOME/.gconf -type bool -set /apps/gdm/simple-greeter/banner_message_enable true\"\n          fi\n        else\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_secure \"Warning banner is set to \\\"${warning_message}\\\"\"\n          fi\n        fi\n      else\n        log_file=\"${restore_dir}/${log_file}\"\n        if [ -f \"${log_file}\" ]; then\n          restore_value=$( cat \"${log_file}\" )\n          if [ \"${restore_value}\" != \"${actual_value}\" ]; then\n            verbose_message \"Restoring: Warning banner to ${previous_value}\"\n            eval \"gconftool-2 -direct -config-source=xml:readwrite:$HOME/.gconf -type bool -set /apps/gdm/simple-greeter/banner_message_enable ${restore_value}\"\n          fi\n        fi\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/gui/audit_gnome_screen_lock.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2129\n# shellcheck disable=SC2154\n\n# audit_gnome_screen_lock\n#\n# Check Gnome Screen Lock\n#\n# Refer to Section(s) 6.12  Page(s) 55-56  CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 6.8   Page(s) 92-3   CIS Solaris 10 Benchmark v5.1.0\n# Refer to Section(s) 1.8.4 Page(s) 162-5  CIS Ubuntu 22.04 Benchmaek v1.0.0\n# Refer to Section(s) 1.8.5 Page(s) 167-71 CIS Ubuntu 22.04 Benchmaek v1.0.0\n#.\n\naudit_gnome_screen_lock () {\n  print_function \"audit_gnome_screen_lock\"\n  string=\"Screen Lock for GNOME Users\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    check_file_value \"is\" \"/usr/openwin/lib/app-defaults/XScreenSaver\" \"*timeout:\"     \"space\" \"0:10:00\" \"bang\"\n    check_file_value \"is\" \"/usr/openwin/lib/app-defaults/XScreenSaver\" \"*lockTimeout:\" \"space\" \"0:00:00\" \"bang\"\n  fi\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    check_gsettings_value \"org.gnome.desktop.session\"     \"idle-delay\" \"uint32 900\"\n    check_gsettings_value \"org.gnome.desktop.screensaver\" \"lock-delay\" \"uint32 5\" \n    if [ \"${os_vendor}\" = \"Ubuntu\" ]; then\n      if [ \"${os_version}\" -ge 22 ]; then \n        if [ -d \"/etc/dconf\" ]; then\n          check_file=\"/etc/dconf/db/ibus.d/00-screensaver\"\n          if [ -f \"${check_file}\" ]; then\n            if [ \"${ansible_mode}\" = 1 ]; then\n              string=\"Screen Lock for GNOME Users\"\n              echo \"- name: ${string}\"\n              echo \"  copy:\"\n              echo \"    content: |\"\n              echo \"             [org/gnome/desktop/session]\"\n              echo \"             idle-delay=uint32 900\"\n              echo \"             [org/gnome/desktop/screensaver]\"\n              echo \"             lock-delay=uint32 5\"\n              echo \"    dest: ${check_file}\"\n            fi\n            check_file_value_with_position \"is\" \"${check_file}\" \"idle-delay\" \"eq\" \"uint32 900\" \"hash\" \"after\" \"session\"\n            check_file_value_with_position \"is\" \"${check_file}\" \"lock-delay\" \"eq\" \"uint32 5\"   \"hash\" \"after\" \"screensaver\"\n          else\n            if [ \"${audit_mode}\" = 1 ]; then\n              fix_message \"echo \\\"[org/gnome/desktop/session]\\\" > ${check_file}\"\n              fix_message \"echo \\\"idle-delay=uint32 900\\\" >> ${check_file}\"\n              fix_message \"echo \\\"[org/gnome/desktop/screensaver]\\\" >> ${check_file}\"\n              fix_message \"echo \\\"lock-delay=uint32 5\\\" >> ${check_file}\"\n              fix_message \"dconf update\"\n            fi \n            if [ \"${audit_mode}\" = 0 ]; then\n              echo  \"[org/gnome/desktop/session]\"      > \"${check_file}\"\n              echo  \"idle-delay=uint32 900\"           >> \"${check_file}\"\n              echo  \"[org/gnome/desktop/screensaver]\" >> \"${check_file}\"\n              echo  \"lock-delay=uint32 5\"             >> \"${check_file}\"\n              dconf update\n            fi          \n            if [ \"${audit_mode}\" = 2 ]; then\n              if [ -f \"${check_file}\" ]; then\n                rm \"${check_file}\"\n              fi\n            fi\n          fi\n        fi\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/gui/audit_kdm_config.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_kdm_config\n#\n# Turn off kdm config\n#.\n\naudit_kdm_config () {\n  print_function \"audit_kdm_config\"\n  string=\"Graphics Configuration\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n      check_sunos_service \"svc:/platform/i86pc/kdmconfig:default\" \"disabled\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/gui/audit_opengl.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_opengl\n#\n# OpenGL. Not required unless running a GUI. Not required on a server.\n#.\n\naudit_opengl () {\n  print_function \"audit_opengl\"\n  string=\"OpenGL\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ]; then\n      check_sunos_service \"svc:/application/opengl/ogl-select:default\" \"disabled\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/gui/audit_xwindows_server.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_xwindows_server\n#\n# Refer to Section(s) 3.2     Page(s) 59-60 CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 3.3     Page(s) 72-3  CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 3.2     Page(s) 62-3  CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 6.1     Page(s) 52    CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 2.1.20  Page(s) 283-4 CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_xwindows_server () {\n  print_function \"audit_xwindows_server\"\n  string=\"X Windows Server\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${os_vendor}\" = \"CentOS\" ] || [ \"${os_vendor}\" = \"Red\" ]; then\n      no_rego=$( yum grouplist 2>&1 | grep \"not registered\" )\n      if [ -z \"${no_rego}\" ]; then\n        check_linux_package_with_group \"uninstalled\" \"X Windows Server\" \"group\"\n      else\n        warn_message \"System not registered with a repository\"\n      fi\n    else\n      if [ \"${os_vendor}\" = \"Ubuntu\" ]; then\n        check_linux_package \"uninstall\" \"xserver-common\"\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/kerberos/audit_kerberos_tgt.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_kerberos_tgt\n#\n# Check Kerberos Ticket Warning\n#\n# Refer to Section(s) 2.6   Page(s) 19   CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 2.2.6 Page(s) 26-7 CIS Solaris 10 Benchmark v5.1.0\n#.\n\naudit_kerberos_tgt () {\n  print_function \"audit_kerberos_tgt\"\n  string=\"Kerberos Ticket Warning\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n      check_sunos_service \"svc:/network/security/ktkt_warn\" \"disabled\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/kerberos/audit_krb5.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_krb5\n#\n# Turn off kerberos if not required\n#.\n\naudit_krb5 () {\n  print_function \"audit_krb5\"\n  string=\"Kerberos\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n        for service_name in \"svc:/network/security/krb5kdc:default\" \\\n          \"svc:/network/security/kadmin:default\" \\\n          \"svc:/network/security/krb5_prop:default\"; do\n          check_sunos_service \"${service_name}\" \"disabled\"\n        done\n      fi\n    fi\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      for service_name in kadmin kprop krb524 krb5kdc; do\n        check_linux_service \"${service_name}\" \"off\"\n      done\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/kernel/audit_kernel_modules.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_kernel_modules\n#\n# Check Kernel Modules\n#\n# Refer to http://kb.vmware.com/kb/2042473.\n#.\n\naudit_kernel_modules () {\n  print_function \"audit_kernel_modules\"\n  string=\"Kernel Module Signing\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"VMkernel\" ]; then\n    for module in $( esxcli system module list | grep '^[a-z]' | awk '($3 == \"true\") {print $1}' ); do\n      log_file=\"kernel_module_${module_name}\"\n      backup_file=\"${work_dir}/${log_file}\"\n      current_value=$( esxcli system module get -m \"${module_name}\" | grep \"Signed Status\" | awk -F': ' '{print $2}' )\n      if [ \"${audit_mode}\" != \"2\" ]; then\n        if [ \"${current_value}\" != \"VMware Signed\" ]; then\n          if [ \"${audit_mode}\" = \"0\" ]; then\n            if [ \"${syslog_server}\" != \"\" ]; then\n              set_message   \"Kernel module ${module_name} to disabled\"\n              echo \"true\" > \"${backup_file}\"\n              esxcli system module set -e false -m \"${module_name}\"\n            fi\n          fi\n          if [ \"${audit_mode}\" = \"1\" ]; then\n            inc_insecure \"Kernel module \\\"${module_name}\\\" is not signed by VMware\"\n            fix_message  \"esxcli system module set -e false -m ${module_name}\"\n          fi\n        else\n          if [ \"${audit_mode}\" = \"1\" ]; then\n            inc_secure   \"Kernel module \\\"${module_name}\\\" is signed by VMware\"\n          fi\n        fi\n      else\n        restore_file=\"${restore_dir}/${log_file}\"\n        if [ -f \"${restore_file}\" ]; then\n          previous_value=$( cat \"${restore_file}\" )\n          if [ \"${previous_value}\" != \"${current_value}\" ]; then\n            restore_message \"Kernel module to \\\"${previous_value}\\\"\" \"restore\"\n            esxcli system module set -e \"${previous_value}\" -m \"${module_name}\"\n          fi\n        fi\n      fi\n    done\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/kernel/audit_kernel_params.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_kernel_params\n#\n# Check Kernel Parameters\n#\n# Refer to Section(s) 4.2,5.3  Page(s) 16-19   CIS FreeBSD Benchmark v1.0.5\n# Refer to Section(s) 1.6.1-21 Page(s) 103-131 CIS AIX Benchmark v1.1.0\n# Refer to Section(s) 1.6.1-21 Page(s)         CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 3.1.1-18 Page(s) 38-61   CIS Solaris 10 Benchmark v5.1.0\n#.\n\naudit_kernel_params () {\n  print_function \"audit_kernel_params\"\n  string=\"Kernel Parameters\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"FreeBSD\" ] || [ \"${os_name}\" = \"AIX\" ]; then\n    if [ \"${os_name}\" = \"AIX\" ]; then\n      check_no \"ipsrcrouteforward\"      \"0\"\n      check_no \"ipignoreredirects\"      \"1\"\n      check_no \"clean_partial_conns\"    \"1\"\n      check_no \"ipsrcroutesend\"         \"0\"\n      check_no \"ipforwarding\"           \"0\"\n      check_no \"ipsendredirects\"        \"0\"\n      check_no \"ip6srcrouteforward\"     \"0\"\n      check_no \"directed_broadcast\"     \"0\"\n      check_no \"tcp_pmtu_discover\"      \"0\"\n      check_no \"bcastping\"              \"0\"\n      check_no \"icmpaddressmask\"        \"0\"\n      check_no \"udp_pmtu_discover\"      \"0\"\n      check_no \"ipsrcrouterecv\"         \"0\"\n      check_no \"nonlocsrcroute\"         \"0\"\n      check_no \"tcp_tcpsecure\"          \"7\"\n      check_no \"sockthresh\"             \"60\"\n      check_no \"rfc1323\"                \"1\"\n      check_no \"tcp_sendspace\"          \"262144\"\n      check_no \"tcp_recvspace\"          \"262144\"\n      check_no \"tcp_mssdflt\"            \"1448\"\n      check_no \"portcheck\"              \"1\"\n      check_no \"nfs_use_reserved_ports\" \"1\"\n    fi\n    if [ \"${os_name}\" = \"FreeBSD\" ]; then\n      check_file_value    \"is\" \"/etc/sysctl.conf\" \"kern.securelevel\"            \"eq\"  \"1\" \"hash\"\n      check_file_value    \"is\" \"/etc/sysctl.conf\" \"net.inet.tcp.log_in_vain\"    \"eq\"  \"1\" \"hash\"\n      check_file_value    \"is\" \"/etc/sysctl.conf\" \"net.inet.udp.log_in_vain\"    \"eq\"  \"1\" \"hash\"\n      if [ \"${os_version}\" -gt 5 ]; then\n        check_file_value  \"is\" \"/etc/sysctl.conf\" \"security.bsd.see_other_uids\" \"0\"       \"hash\"\n        check_file_value  \"is\" \"/etc/sysctl.conf\" \"security.bsd.see_other_gids\" \"0\"       \"hash\"\n      fi\n    fi\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      if [ \"${os_version}\" != \"11\" ]; then\n        create_nddscript\n        check_file=\"/etc/init.d/ndd-netconfig\"\n        audit_ndd_value   \"/dev/ip\" \"ip_forward_src_routed\"                 \"0\"\n        audit_ndd_value   \"/dev/ip\" \"ip_forwarding\"                         \"0\"\n        if [ \"${os_version}\" -gt 7 ]; then\n          audit_ndd_value \"/dev/ip\"  \"ip6_forward_src_routed\"               \"0\"\n          audit_ndd_value \"/dev/tcp\" \"tcp_rev_src_routes\"                   \"0\"\n          audit_ndd_value \"/dev/ip\"  \"ip6_forwarding\"                       \"0\"\n        fi\n        audit_ndd_value   \"/dev/ip\"  \"ip_forward_directed_broadcasts\"       \"0\"\n        audit_ndd_value   \"/dev/tcp\" \"tcp_conn_req_max_q0\"                  \"4096\"\n        audit_ndd_value   \"/dev/tcp\" \"tcp_conn_req_max_q\"                   \"1024\"\n        audit_ndd_value   \"/dev/ip\"  \"ip_respond_to_timestamp\"              \"0\"\n        audit_ndd_value   \"/dev/ip\"  \"ip_respond_to_timestamp_broadcast\"    \"0\"\n        audit_ndd_value   \"/dev/ip\"  \"ip_respond_to_address_mask_broadcast\" \"0\"\n        audit_ndd_value   \"/dev/ip\"  \"ip_respond_to_echo_multicast\"         \"0\"\n        if [ \"${os_version}\" -gt 7 ]; then\n          audit_ndd_value \"/dev/ip\" \"ip6_respond_to_echo_multicast\"         \"0\"\n        fi\n        audit_ndd_value   \"/dev/ip\"  \"ip_respond_to_echo_broadcast\"         \"0\"\n        audit_ndd_value   \"/dev/arp\" \"arp_cleanup_interval\"                 \"60000\"\n        audit_ndd_value   \"/dev/ip\"  \"ip_ire_arp_interval\"                  \"60000\"\n        audit_ndd_value   \"/dev/ip\"  \"ip_ignore_redirect\"                   \"1\"\n        if [ \"${os_version}\" -gt 7 ]; then\n          audit_ndd_value \"/dev/ip\"  \"ip6_ignore_redirect\" \"1\"\n        fi\n        audit_ndd_value   \"/dev/tcp\" \"tcp_extra_priv_ports_add\"             \"6112\"\n        audit_ndd_value   \"/dev/ip\"  \"ip_strict_dst_multihoming\"            \"1\"\n        if [ \"${os_version}\" -gt 7 ]; then\n          audit_ndd_value \"/dev/ip\"  \"ip6_strict_dst_multihoming\"           \"1\"\n        fi\n        audit_ndd_value   \"/dev/ip\"  \"ip_send_redirects\"                    \"0\"\n        if [ \"${os_version}\" -gt 7 ]; then\n          audit_ndd_value \"/dev/ip\"  \"ip6_send_redirects\"                   \"0\"\n        fi\n      fi\n      if [ \"${audit_mode}\" = 2 ]; then\n        if [ \"${os_name}\" = \"AIX\" ]; then\n          for parameter_name in ipsrcrouteforward ipignoreredirects \\\n          clean_partial_conns ipsrcroutesend ipforwarding ipsendredirects \\\n          ip6srcrouteforward directed_broadcast tcp_pmtu_discover bcastping \\\n          icmpaddressmask udp_pmtu_discover ipsrcrouterecv nonlocsrcroute \\\n          tcp_tcpsecure sockthresh rfc1323 tcp_sendspace tcp_recvspace \\\n          tcp_mssdflt portcheck nfs_use_reserved_ports; do\n            check_no \"${parameter_name}\"\n          done\n        else\n          if [ -f \"${check_file}\" ]; then\n            check_file_exists \"${check_file}\" \"no\"\n          fi\n        fi\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/kubernetes/audit_kubernetes_apiserver.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2009\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_kubernetes_apiserver\n#\n# Check Kubernetes API server\n#\n# Refer to Section(s) 1.1.1-39 Page(s) 13-88   CIS Kubernetes Benchmark v1.4.0\n# Refer to Section(s) 1.4.1-21 Page(s) 109-128 CIS Kubernetes Benchmark v1.4.0\n# Refer to Section(s) 1.5.1-7  Page(s) 151-164 CIS Kubernetes Benchmark v1.4.0\n# Refer to Section(s) 1.6.1-8  Page(s) 165-180 CIS Kubernetes Benchmark v1.4.0\n# Refer to Section(s) 1.7.1-7  Page(s) 181-194 CIS Kubernetes Benchmark v1.4.0\n# Refer to Section(s) 2.1.1-14 Page(s) 195-222 CIS Kubernetes Benchmark v1.4.0\n# Refer to Section(s) 2.2.1-10 Page(s) 223-242 CIS Kubernetes Benchmark v1.4.0\n#\n# Still to be completed\n#.\n\naudit_kubernetes_apiserver () {\n  print_function \"audit_kubernetes_apiserver\"\n  string=\"Kubernetes API Server\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"Darwin\" ]; then\n    daemon_check=$( ps -ef | grep \"kube-apiserver\" |grep -v grep )\n    if [ \"${daemon_check}\" ]; then\n      check_file=\"/etc/kubernetes/manifests/kube-apiserver.yaml\"\n      if [ -f \"${check_file}\" ]; then\n        disable_value           \"${check_file}\"   \"--basic-auth-file\"             \"hash\"\n        disable_value           \"${check_file}\"   \"--insecure-allow-any-token\"    \"hash\"\n        disable_value           \"${check_file}\"   \"--insecure-bind-address\"       \"hash\"\n        disable_value           \"${check_file}\"   \"--token-auth-file\"             \"hash\"\n        check_file_perms        \"${check_file}\"   \"0644\" \"root\" \"root\"\n        check_file_value \"is\"   \"${check_file}\"   \"--anonymous-auth\"              \"eq\" \"false\"      \"hash\" \n        check_file_value \"is\"   \"${check_file}\"   \"--kubelet-https\"               \"eq\" \"true\"       \"hash\"\n        check_file_value \"is\"   \"${check_file}\"   \"--insecure-port\"               \"eq\" \"0\"          \"hash\"\n        check_file_value \"is\"   \"${check_file}\"   \"--profiling\"                   \"eq\" \"false\"      \"hash\" \n        check_file_value \"is\"   \"${check_file}\"   \"--repair-malformed-updates\"    \"eq\" \"false\"      \"hash\" \n        check_file_value \"is\"   \"${check_file}\"   \"--audit-log-maxage\"            \"eq\" \"30\"         \"hash\"\n        check_file_value \"is\"   \"${check_file}\"   \"--audit-log-maxbackup\"         \"eq\" \"10\"         \"hash\"\n        check_file_value \"is\"   \"${check_file}\"   \"--audit-log-maxsize\"           \"eq\" \"100\"        \"hash\"\n        check_file_value \"set\"  \"${check_file}\"   \"--enable-admission-plugins\"    \"eq\" \"na\"         \"hash\"\n        check_file_value \"set\"  \"${check_file}\"   \"--kubelet-client-certificate\"  \"eq\" \"na\"         \"hash\"\n        check_file_value \"set\"  \"${check_file}\"   \"--kubelet-client-key\"          \"eq\" \"na\"         \"hash\"\n        check_file_value \"is\"   \"${check_file}\"   \"--service-account-lookup\"      \"eq\" \"true\"       \"hash\"\n        check_file_value \"set\"  \"${check_file}\"   \"--service-account-key-file\"    \"eq\" \"na\"         \"hash\"\n        check_file_value \"set\"  \"${check_file}\"   \"--etcd-certfile\"               \"eq\" \"na\"         \"hash\"\n        check_file_value \"set\"  \"${check_file}\"   \"--etcd-keyfile\"                \"eq\" \"na\"         \"hash\"\n        check_file_value \"set\"  \"${check_file}\"   \"--tls-cert-file\"               \"eq\" \"na\"         \"hash\"\n        check_file_value \"set\"  \"${check_file}\"   \"--tls-private-key-file\"        \"eq\" \"na\"         \"hash\"\n        check_file_value \"set\"  \"${check_file}\"   \"--client-ca-file\"              \"eq\" \"na\"         \"hash\"\n        check_file_value \"set\"  \"${check_file}\"   \"--etcd-cafile\"                 \"eq\" \"na\"         \"hash\"\n        check_file_value \"is\"   \"${check_file}\"   \"--authorization-mode\"          \"eq\" \"Node,RBAC\"  \"hash\"\n        check_file_value \"set\"  \"${check_file}\"   \"--admission-control-config-file\"                 \"eq\" \"na\" \"hash\"\n        check_file_value \"set\"  \"${check_file}\"   \"--experimental-encryption-provider-config\"       \"eq\" \"na\" \"hash\"\n        check_file_value \"not\"  \"${check_file}\"   \"--enable-admission-plugins\"    \"eq\" \"AlwaysAdmit\"          \"hash\" # no\n        check_file_value \"is\"   \"${check_file}\"   \"--enable-admission-plugins\"    \"eq\" \"AlwaysPullImages\"     \"hash\" # yes\n        check_file_value \"is\"   \"${check_file}\"   \"--enable-admission-plugins\"    \"eq\" \"DenyEscalatingExec\"   \"hash\" # yes\n        check_file_value \"is\"   \"${check_file}\"   \"--enable-admission-plugins\"    \"eq\" \"SecurityContextDeny\"  \"hash\" # yes\n        check_file_value \"is\"   \"${check_file}\"   \"--enable-admission-plugins\"    \"eq\" \"NamespaceLifecycle\"   \"hash\" # no\n        check_file_value \"is\"   \"${check_file}\"   \"--enable-admission-plugins\"    \"eq\" \"PodSecurityPolicy\"    \"hash\" # yes\n        check_file_value \"not\"  \"${check_file}\"   \"--enable-admission-plugins\"    \"eq\" \"ServiceAccount\"       \"hash\" # no\n        check_file_value \"is\"   \"${check_file}\"   \"--enable-admission-plugins\"    \"eq\" \"NodeRestriction\"      \"hash\" # yes\n        check_file_value \"is\"   \"${check_file}\"   \"--enable-admission-plugins\"    \"eq\" \"EventRateLimit\"       \"hash\" # yes\n        check_file_value \"not\"  \"${check_file}\"   \"--feature-gates\"               \"eq\" \"AdvancedAuditing=false\"        \"hash\" # no\n        check_file_value \"is\"   \"${check_file}\"   \"--audit-log-path\"              \"eq\" \"/var/log/apiserver/audit.log\"  \"hash\"\n        check_file_value \"is\"   \"${check_file}\"   \"--tls-cipher-suites\"           \"eq\" \"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AE S_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM _SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM _SHA384,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_128_GCM_SHA256\" \"hash\"\n      fi\n      if [ -f \"${check_file}\" ]; then\n        check_file_value \"is\"   \"/etc/kubernetes/apiserver\" \"KUBE_API_ARGS\"       \"eq\" \"--feature-gates=AllAlpha=true\" \"hash\"\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}"
  },
  {
    "path": "modules/kubernetes/audit_kubernetes_controller.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2009\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_kubernetes_controller\n#\n# Check Kubernetes controller\n#\n# Refer to Section(s) 1.1.1-39 Page(s) 13-88   CIS Kubernetes Benchmark v1.4.0\n# Refer to Section(s) 1.4.1-21 Page(s) 109-128 CIS Kubernetes Benchmark v1.4.0\n# Refer to Section(s) 1.5.1-7  Page(s) 151-164 CIS Kubernetes Benchmark v1.4.0\n# Refer to Section(s) 1.6.1-8  Page(s) 165-180 CIS Kubernetes Benchmark v1.4.0\n# Refer to Section(s) 1.7.1-7  Page(s) 181-194 CIS Kubernetes Benchmark v1.4.0\n# Refer to Section(s) 2.1.1-14 Page(s) 195-222 CIS Kubernetes Benchmark v1.4.0\n# Refer to Section(s) 2.2.1-10 Page(s) 223-242 CIS Kubernetes Benchmark v1.4.0\n#\n# Still to be completed\n#.\n\naudit_kubernetes_controller () {\n  print_function \"audit_kubernetes_controller\"\n  string=\"Kubernetes Controller\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"Darwin\" ]; then\n    daemon_check=$( ps -ef | grep \"kube-controller-manager\" | grep -v grep )\n    if [ \"${daemon_check}\" ]; then\n      check_file=\"/etc/kubernetes/manifests/kube-controller-manager.yaml\"\n      if [ -f \"${check_file}\" ]; then\n        check_file_value \"is\"  \"${check_file}\" \"--terminated-pod-gc-threshold\"      \"eq\" \"10\"   \"hash\"\n        check_file_value \"is\"  \"${check_file}\" \"--use-service-account-credentials\"  \"eq\" \"true\" \"hash\"\n        check_file_value \"set\" \"${check_file}\" \"--service-account-private-key-file\" \"eq\" \"na\"   \"hash\"\n        check_file_value \"set\" \"${check_file}\" \"--root-ca-file\"                     \"eq\" \"na\"   \"hash\"\n        check_file_value \"is\"  \"${check_file}\" \"--feature-gates\"                    \"eq\" \"RotateKubeletServerCertificate=true\" \"hash\" # yes\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}"
  },
  {
    "path": "modules/kubernetes/audit_kubernetes_etcd.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2009\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_kubernetes_etcd\n#\n# Check Kubernetes etcd\n#\n# Refer to Section(s) 1.1.1-39 Page(s) 13-88   CIS Kubernetes Benchmark v1.4.0\n# Refer to Section(s) 1.4.1-21 Page(s) 109-128 CIS Kubernetes Benchmark v1.4.0\n# Refer to Section(s) 1.5.1-7  Page(s) 151-164 CIS Kubernetes Benchmark v1.4.0\n# Refer to Section(s) 1.6.1-8  Page(s) 165-180 CIS Kubernetes Benchmark v1.4.0\n# Refer to Section(s) 1.7.1-7  Page(s) 181-194 CIS Kubernetes Benchmark v1.4.0\n# Refer to Section(s) 2.1.1-14 Page(s) 195-222 CIS Kubernetes Benchmark v1.4.0\n# Refer to Section(s) 2.2.1-10 Page(s) 223-242 CIS Kubernetes Benchmark v1.4.0\n#\n# Still to be completed\n#.\n\naudit_kubernetes_etcd () {\n  print_function \"audit_kubernetes_etcd\"\n  string=\"Kubernetes etcd\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"Darwin\" ]; then\n    daemon_check=$( ps -ef | grep \"etcd\" |grep -v grep )\n    if [ \"${daemon_check}\" ]; then\n      check_file=\"/etc/kubernetes/manifests/etcd.yaml\"\n      if [ -f \"${check_file}\" ]; then\n        check_file_perms  \"${check_file}\"       \"0644\" \"root\" \"root\"\n        check_file_value  \"is\"  \"${check_file}\" \"--client-cert-auth\"      \"eq\" \"true\"  \"hash\"\n        check_file_value  \"set\" \"${check_file}\" \"--cert-file\"             \"eq\" \"na\"    \"hash\"\n        check_file_value  \"set\" \"${check_file}\" \"--key-file\"              \"eq\" \"na\"    \"hash\"\n        check_file_value  \"is\"  \"${check_file}\" \"--peer-client-cert-auth\" \"eq\" \"true\"  \"hash\"\n        check_file_value  \"is\"  \"${check_file}\" \"--peer-auto-tls\"         \"eq\" \"false\" \"hash\"\n        check_file_value  \"set\" \"${check_file}\" \"--trusted-ca-file\"       \"eq\" \"na\"    \"hash\"\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}"
  },
  {
    "path": "modules/kubernetes/audit_kubernetes_kubelet.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2009\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_kubernetes_kubelet\n#\n# Check Kubernetes kubelet\n#\n# Refer to Section(s) 1.1.1-39 Page(s) 13-88   CIS Kubernetes Benchmark v1.4.0\n# Refer to Section(s) 1.4.1-21 Page(s) 109-128 CIS Kubernetes Benchmark v1.4.0\n# Refer to Section(s) 1.5.1-7  Page(s) 151-164 CIS Kubernetes Benchmark v1.4.0\n# Refer to Section(s) 1.6.1-8  Page(s) 165-180 CIS Kubernetes Benchmark v1.4.0\n# Refer to Section(s) 1.7.1-7  Page(s) 181-194 CIS Kubernetes Benchmark v1.4.0\n# Refer to Section(s) 2.1.1-14 Page(s) 195-222 CIS Kubernetes Benchmark v1.4.0\n# Refer to Section(s) 2.2.1-10 Page(s) 223-242 CIS Kubernetes Benchmark v1.4.0\n#\n# Still to be completed\n#.\n\naudit_kubernetes_kubelet () {\n  print_function \"audit_kubernetes_kubelet\"\n  string=\"Kubernetes kubelet\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"Darwin\" ]; then\n    daemon_check=$( ps -ef | grep \"kubelet\" | grep -v grep )\n    if [ \"${daemon_check}\" ]; then\n      check_file=\"/etc/systemd/system/kubelet.service.d/10-kubeadm.conf\"\n      if [ -f \"${check_file}\" ]; then\n        check_file_perms       \"${check_file}\"  \"0755\" \"root\" \"root\"\n        check_file_value \"is\"  \"${check_file}\"  \"KUBELET_SYSTEM_PODS_ARGS\" \"eq\" \"--anonymous-auth=false\"                 \"hash\"\n        check_file_value \"is\"  \"${check_file}\"  \"KUBELET_AUTHZ_ARGS\"       \"eq\" \"--authorization-mode=Webhook\"           \"hash\"\n        check_file_value \"is\"  \"${check_file}\"  \"KUBELET_AUTHZ_ARGS\"       \"eq\" \"--client-ca-file=[A-Z,a-z]\"             \"hash\"\n        check_file_value \"is\"  \"${check_file}\"  \"KUBELET_SYSTEM_PODS_ARGS\" \"eq\" \"--read-only-port=0\"                     \"hash\"\n        check_file_value \"is\"  \"${check_file}\"  \"KUBELET_SYSTEM_PODS_ARGS\" \"eq\" \"--streaming-connection-idle-timeout=5m\" \"hash\"\n        check_file_value \"is\"  \"${check_file}\"  \"KUBELET_SYSTEM_PODS_ARGS\" \"eq\" \"--protect-kernel-defaults=true\"         \"hash\"\n        check_file_value \"not\" \"${check_file}\"  \"KUBELET_SYSTEM_PODS_ARGS\" \"eq\" \"--make-iptables-util-chains\"            \"hash\"\n        check_file_value \"not\" \"${check_file}\"  \"KUBELET_SYSTEM_PODS_ARGS\" \"eq\" \"--hostname-override\"                    \"hash\"\n        check_file_value \"is\"  \"${check_file}\"  \"KUBELET_SYSTEM_PODS_ARGS\" \"eq\" \"--event-qps=0\"                          \"hash\"\n        check_file_value \"is\"  \"${check_file}\"  \"KUBELET_CERTIFICATE_ARGS\" \"eq\" \"--tls-cert-file=[A-Z,a-z]\"              \"hash\"\n        check_file_value \"is\"  \"${check_file}\"  \"KUBELET_CERTIFICATE_ARGS\" \"eq\" \"--tls-private-key-file=[A-Z,a-z]\"       \"hash\"\n        check_file_value \"is\"  \"${check_file}\"  \"KUBELET_CADVISOR_ARGS\"    \"eq\" \"--cadvisor-port=0\"                      \"hash\"\n        check_file_value \"is\"  \"${check_file}\"  \"KUBELET_CERTIFICATE_ARGS\" \"eq\" \"--rotate-certificates=true\"             \"hash\"\n        check_file_value \"is\"  \"${check_file}\"  \"KUBELET_CERTIFICATE_ARGS\" \"eq\" \"--feature-gates=RotateKubeletServerCertificate=true\" \"hash\"\n        check_file_value \"is\"  \"${check_file}\"  \"--tls-cipher-suites\"      \"eq\" \"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AE S_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM _SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM _SHA384,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_128_GCM_SHA256\" \"hash\"\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}"
  },
  {
    "path": "modules/kubernetes/audit_kubernetes_perms.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2009\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_kubernetes_perms\n#\n# Check Kubernetes permissions\n#\n# Refer to Section(s) 1.1.1-39 Page(s) 13-88   CIS Kubernetes Benchmark v1.4.0\n# Refer to Section(s) 1.4.1-21 Page(s) 109-128 CIS Kubernetes Benchmark v1.4.0\n# Refer to Section(s) 1.5.1-7  Page(s) 151-164 CIS Kubernetes Benchmark v1.4.0\n# Refer to Section(s) 1.6.1-8  Page(s) 165-180 CIS Kubernetes Benchmark v1.4.0\n# Refer to Section(s) 1.7.1-7  Page(s) 181-194 CIS Kubernetes Benchmark v1.4.0\n# Refer to Section(s) 2.1.1-14 Page(s) 195-222 CIS Kubernetes Benchmark v1.4.0\n# Refer to Section(s) 2.2.1-10 Page(s) 223-242 CIS Kubernetes Benchmark v1.4.0\n#\n# Still to be completed\n#.\n\naudit_kubernetes_perms () {\n  print_function \"audit_kubernetes_perms\"\n  string=\"Kubernetes permissions\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"Darwin\" ]; then\n    check_file=\"/var/lib/etcd\"\n    if [ -f \"${check_file}\" ]; then\n      check_file_perms    \"${check_file}\" \"0700\" \"etcd\" \"etcd\"\n    fi\n    for check_file in /etc/kubernetes/admin.conf /etc/kubernetes/scheduler.conf /etc/kubernetes/controller-manager.conf /etc/kubernetes/kubelet.conf; do\n      if [ -f \"${check_file}\" ]; then\n        check_file_perms  \"${check_file}\" \"0644\" \"root\" \"root\"\n      fi\n    done\n    check_dir=\"/etc/kubernetes/pki\"\n    if [ -d \"${check_dir}\" ]; then\n      file_list=$( find   \"${check_dir}\" -name \"*.crt\" -type f -maxdepth 1 )\n      for check_file in ${file_list}; do\n        check_file_perms  \"${check_file}\" \"0644\" \"root\" \"root\"\n      done\n      file_list=$( find   \"${check_dir}\" -name \"*.key\" -type f -maxdepth 1 )\n      for check_file in ${file_list}; do\n        check_file_perms  \"${check_file}\" \"0600\" \"root\" \"root\"\n      done\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}"
  },
  {
    "path": "modules/kubernetes/audit_kubernetes_scheduler.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2009\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_kubernetes_scheduler\n#\n# Check Kubernetes scheduler\n#\n# Refer to Section(s) 1.1.1-39 Page(s) 13-88   CIS Kubernetes Benchmark v1.4.0\n# Refer to Section(s) 1.4.1-21 Page(s) 109-128 CIS Kubernetes Benchmark v1.4.0\n# Refer to Section(s) 1.5.1-7  Page(s) 151-164 CIS Kubernetes Benchmark v1.4.0\n# Refer to Section(s) 1.6.1-8  Page(s) 165-180 CIS Kubernetes Benchmark v1.4.0\n# Refer to Section(s) 1.7.1-7  Page(s) 181-194 CIS Kubernetes Benchmark v1.4.0\n# Refer to Section(s) 2.1.1-14 Page(s) 195-222 CIS Kubernetes Benchmark v1.4.0\n# Refer to Section(s) 2.2.1-10 Page(s) 223-242 CIS Kubernetes Benchmark v1.4.0\n#\n# Still to be completed\n#.\n\naudit_kubernetes_scheduler () {\n  print_function \"audit_kubernetes_scheduler\"\n  string=\"Kubernetes scheduler\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"Darwin\" ]; then\n    daemon_check=$( ps -ef | grep \"kube-scheduler\" | grep -v grep )\n    if [ \"${daemon_check}\" ]; then\n      check_file=\"/etc/kubernetes/manifests/kube-scheduler.yaml\"\n      if [ -f \"${check_file}\" ]; then\n        check_file_perms      \"${check_file}\" \"0644\" \"root\" \"root\"\n        check_file_value \"is\" \"${check_file}\" \"--audit-policy-file\" \"eq\" \"/etc/kubernetes/audit-policy.yaml\" \"hash\"\n        check_file_value \"is\" \"${check_file}\" \"--request-timeout\"   \"eq\" \"300s\"                              \"hash\"\n        check_file_value \"is\" \"${check_file}\" \"--address\"           \"eq\" \"127.0.0.1\"                         \"hash\"\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}"
  },
  {
    "path": "modules/ldap/audit_ldap.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_ldap\n#\n# Turn off ldap\n#\n# Refer to Section(s) 2.3.5 Page(s) 115   CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 2.3.5 Page(s) 128   CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 2.3.3 Page(s) 121   CIS Ubuntu 16.04 Benchmark v1.0.0\n# Refer to Section(s) 2.2.5 Page(s) 300-1 CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_ldap () {\n  print_function \"audit_ldap\"\n  string=\"LDAP Client\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n        check_sunos_service \"svc:/network/ldap/client:default\" \"disabled\"\n      fi\n    fi\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      check_linux_package   \"uninstall\" \"openldap-clients\"\n      check_linux_package   \"uninstall\" \"ldap-utils\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/ldap/audit_ldap_cache.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_ldap_cache\n#\n# Check LDAP cache\n#\n# Refer to Section(s) 2.2.5 Page(s) 25-6 CIS Solaris 10 Benchmark v5.1.0\n#.\n\naudit_ldap_cache () {\n  print_function \"audit_ldap_cache\"\n  string=\"LDAP Cache\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      if [ \"${os_version}\" = \"10\" ]; then\n        check_sunos_service \"svc:/network/ldap/client\" \"disabled\"\n      fi\n    fi\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      check_linux_service   \"ldap\" \"off\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/ldap/audit_ldap_server.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_ldap_server\n#\n# Check LDAP server\n#\n# Refer to Section(s) 3.7   Page(s) 63-4  CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 3.7   Page(s) 76    CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 3.7   Page(s) 66-7  CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 2.2.6 Page(s) 106   CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 6.6   Page(s) 56-7  CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 2.2.6 Page(s) 98    CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 2.2.6 Page(s) 106   CIS Ubuntu 16.04 Benchmark v1.0.0\n# Refer to Section(s) 2.1.7 Page(s) 245-6 CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_ldap_server () {\n  print_function \"audit_ldap_server\"\n  string=\"LDAP Server\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    check_linux_service \"slapd\"     \"off\"\n    check_linux_package \"uninstall\" \"slapd\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/linux/audit_aide.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_aide\n#\n# Check AIDE\n#\n# Refer to Section(s) 1.3.1-2          Page(s) 73-7        CIS Ubuntu LTS 16.04 Benchmark v2.0.0\n# Refer to Section(s) 1.3.1-2          Page(s) 73-7        CIS Ubuntu LTS 18.04 Benchmark v2.1.0\n# Refer to Section(s) 1.3.1-2          Page(s) 74-8        CIS Ubuntu LTS 20.04 Benchmark v1.0.0\n# Refer to Section(s) 1.3.1-2,4.1.4.11 Page(s) 104-8,551-2 CIS Ubuntu LTS 22.04 Benchmark v1.0.0\n# Refer to Section(s) 6.3.1-3          Page(s) 924-31      CIS Ubuntu LTS 24.04 Benchmark v1.0.0\n#.\n\naudit_aide () {\n  print_function \"audit_aide\"\n  string=\"AIDE\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    check_linux_package \"install\" \"aide\"\n    check_linux_package \"install\" \"aide-common\"\n    if [ -d \"/etc/aide\" ]; then\n      check_file_value    \"is\" \"/etc/aide/aide.conf\"  \"/sbin/auditctl\"   \"space\" \"p+i+n+u+g+s+b+acl+xattrs+sha512\"    \"hash\"\n      check_file_value    \"is\" \"/etc/aide/aide.conf\"  \"/sbin/auditd\"     \"space\" \"p+i+n+u+g+s+b+acl+xattrs+sha512\"    \"hash\"\n      check_file_value    \"is\" \"/etc/aide/aide.conf\"  \"/sbin/ausearch\"   \"space\" \"p+i+n+u+g+s+b+acl+xattrs+sha512\"    \"hash\"\n      check_file_value    \"is\" \"/etc/aide/aide.conf\"  \"/sbin/aureport\"   \"space\" \"p+i+n+u+g+s+b+acl+xattrs+sha512\"    \"hash\"\n      check_file_value    \"is\" \"/etc/aide/aide.conf\"  \"/sbin/autrace\"    \"space\" \"p+i+n+u+g+s+b+acl+xattrs+sha512\"    \"hash\"\n      check_file_value    \"is\" \"/etc/aide/aide.conf\"  \"/sbin/augenrules\" \"space\" \"p+i+n+u+g+s+b+acl+xattrs+sha512\"    \"hash\"\n    fi\n    if [ \"${os_vendor}\" = \"Ubuntu\" ]; then\n      if [ \"${os_version}\" -lt 24 ]; then\n        check_append_file   \"/etc/cron.d/aide\" \"0 5 * * * /usr/bin/aide.wrapper --config /etc/aide/aide.conf --check\" \"hash\"\n      else\n        check_linux_service \"dailyaidecheck.timer\" \"on\"\n      fi\n    else\n      check_append_file   \"/etc/cron.d/aide\" \"0 5 * * * /usr/bin/aide.wrapper --config /etc/aide/aide.conf --check\"   \"hash\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/linux/audit_apparmor.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_apparmor\n#\n# Check AppArmor\n#\n# Refer to Section(s) 4.5           Page(s) 38-9        CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 1.6.2.1,1.6.3 Page(s) 69-70,73-4  CIS Ubuntu 16.04 Benchmark v1.0.0\n# Refer to Section(s) 1.3.1.1-2     Page(s) 151-4       CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_apparmor () {\n  print_function \"audit_apparmor\"\n  string=\"AppArmor Unconfined Applications\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    do_grub_test=0\n    do_app_test=1\n    package_name=\"apparmor\"\n    app_name=\"AppArmor\"\n    if [ \"${my_id}\" != \"0\" ] && [ \"${use_sudo}\" = \"0\" ]; then\n      verbose_message \"Requires sudo to check\" \"notice\"\n      return\n    fi\n    if [ \"${os_vendor}\" = \"SuSE\" ]; then \n      check_list=\"/boot/grub/menu.lst\"\n      do_test=1\n    fi\n    if [ \"${os_vendor}\" = \"Ubuntu\" ] && [ \"${os_version}\" -ge 16 ]; then\n      check_list=\"/boot/grub/grub.cfg /etc/default/grub\"\n      do_grub_test=1\n      do_app_test=1\n    fi\n    if [ \"${do_app_test}\" = 1 ]; then\n      get_command=\"apparmor_status |grep \\\"unconfined mode\\\" |awk '{print \\$1}'\"\n      set_command=\"sudo aa-enforce /etc/apparmor.d/*\"\n      command_message      \"${get_command}\"\n      profile_test=$( eval \"${get_command}\" )\n      if [ \"${profile_test}\" = \"0\" ]; then\n        inc_secure   \"There are no unconfined applications\"\n      else\n        inc_insecure \"There are unconfined applications\"\n      fi\n      if [ \"${ansible_mode}\" = 1 ]; then\n        ansible_counter=$((ansible_counter+1))\n        ansible_value=\"apparmor_check_${ansible_counter}\"\n        echo \"\"\n        echo \"- name: Checking ${string}\"\n        echo \"  command: sh -c \\\"${get_command}\\\"\"\n        echo \"  register: ${ansible_value}\"\n        echo \"  failed_when: ${ansible_value} != 0\"\n        echo \"  changed_when: false\"\n        echo \"  ignore_errors: true\"\n        echo \"  when: ansible_facts['ansible_system'] == '${os_name}'\"\n        echo \"\"\n        echo \"- name: Fixing ${string}\"\n        echo \"  command: sh -c \\\"${set_command}\\\"\"\n        echo \"  when: ${ansible_value}.rc == 1 and ansible_facts['ansible_system'] == '${os_name}'\"\n        echo \"\"\n      else\n        lock_command=\"${set_command}\"\n        lock_message=\"Confine AppArmor Applications\"\n        run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n      fi\n    fi\n    for check_file in ${check_list}; do\n      if [ \"${do_grub_test}\" = 1 ]; then\n        ansible_counter=$((ansible_counter+1))\n        string=\"Package \\\"${app_name}\\\"\"\n        ansible_value=\"apparmor_check_${ansible_counter}\"\n        check_message \"${string}\"\n        check_linux_package \"install\" \"${package_name}\"\n        if [ \"${audit_mode}\" = 2 ]; then\n          restore_file \"${check_file}\" \"${restore_dir}\"\n        else\n          if [ -f \"${check_file}\" ]; then\n            disabled_get_command=\"grep '${package_name}=0' ${check_file} | head -1 | wc -l | sed 's/ //g'\"\n            package_disabled_test=$( grep \"${package_name}=0\" \"${check_file}\" | head -1 | wc -l | sed \"s/ //g\" )\n            package_enabled_test=$(  grep \"${package_name}=1\" \"${check_file}\" | head -1 | wc -l | sed \"s/ //g\" )\n          else\n            package_disabled_test=0\n            package_enabled_test=0\n          fi\n          if [ \"${package_disabled_test}\" = \"1\" ]; then\n            inc_insecure \"Application \\\"${app_name}\\\" is disabled in \\\"${check_file}\\\"\"\n            temp_file=\"${temp_dir}/${package_name}\"\n            backup_file \"${check_file}\"\n            lock_command=\"cat ${check_file} |sed 's/${package_name}=0//g' > ${temp_file} ; cat ${temp_file} > ${check_file} ; aa-enforce /etc/${package_name}.d/*\"\n            lock_message=\"Disabled Application/Package \\\"${app_name}\\\" in \\\"${check_file}\\\" to removed\"\n            if [ \"${ansible_mode}\" = 1 ]; then\n              ansible_counter=$((ansible_counter+1))\n              ansible_value=\"apparmor_check_${ansible_counter}\"\n              echo \"\"\n              echo \"- name: Checking ${string}\"\n              echo \"  command: sh -c \\\"${disabled_get_command}\\\"\"\n              echo \"  register: ${ansible_value}\"\n              echo \"  failed_when: ${ansible_value} != 0\"\n              echo \"  changed_when: false\"\n              echo \"  ignore_errors: true\"\n              echo \"  when: ansible_facts['ansible_system'] == '${os_name}'\"\n              echo \"\"\n              echo \"- name: Fixing ${string}\"\n              echo \"  command: sh -c \\\"${lock_command}\\\"\"\n              echo \"  when: ${ansible_value}.rc == 1 and ansible_facts['ansible_system'] == '${os_name}'\"\n              echo \"\"\n            fi\n          fi\n          if [ \"${package_enabled_test}\" = \"1\" ]; then\n            inc_secure   \"Application \\\"${app_name}\\\" is enabled in \\\"${check_file}\\\"\"\n          else\n            inc_insecure \"Application \\\"${app_name}\\\" is not enabled in \\\"${check_file}\\\"\"\n            temp_file=\"${temp_dir}/${package_name}\"\n            backup_file \"${check_file}\"\n            if [ \"${check_file}\" = \"/etc/default/grub\" ]; then\n              command=\"grep -c \\\"^GRUB_CMDLINE_LINUX\\\" \\\"${check_file}\\\"\"\n              command_message    \"${command}\"\n              line_check=$( eval \"${command}\" )\n              if [ -n \"${line_check}\" ]; then\n                command=\"grep \\\"^GRUB_CMDLINE_LINUX\\\" < \\\"${check_file}\\\" |cut -f2 -d= |sed \\\"s/\\\"//g\\\"\"\n                command_message        \"${command}\"\n                existing_value=$( eval \"${command}\" )\n                new_value=\"GRUB_CMDLINE_LINUX=\\\"apparmor=1 security=apparmor ${existing_value}\\\"\"\n                lock_command=\"cat ${check_file} |sed 's/^GRUB_CMDLINE_LINUX/GRUB_CMDLINE_LINUX=\\\"${new_value}\\\"/g' > ${temp_file} ; cat ${temp_file} > ${check_file}\"\n                lock_message=\"Disabled Application/Package \\\"${app_name}\\\" removed\"\n                run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n              else\n                lock_command=\"echo 'GRUB_CMDLINE_LINUX=\\\"apparmor=1 security=apparmor\\\"' >> ${check_file}\"\n                lock_message=\"Enabled ${app_name}\"\n                run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n              fi\n            else\n              if [ \"${check_file}\" = \"/boot/grub/grub.cfg\" ]; then\n                lock_command=\"cat ${check_file} |sed 's/^\\s*linux.*/& apparmor=1 security=apparmor/g' > ${temp_file} ; cat ${temp_file} > ${check_file} ; aa-enforce /etc/${package_name}.d/*\"\n                lock_message=\"Application/Package \\\"${app_name}\\\" in \\\"${check_file}\\\" to enabled\"\n                run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n              else\n                lock_command=\"cat ${check_file} |sed 's/^\\s*kernel.*/& apparmor=1 security=apparmor/g' > ${temp_file} ; cat ${temp_file} > ${check_file} ; enforce /etc/${package_name}.d/*\"\n                lock_message=\"Application/Package \\\"${app_name}\\\" in \\\"${check_file}\\\" to enabled\"\n                run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n              fi\n            fi\n          fi\n        fi\n      fi\n    done \n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/linux/audit_apport.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_apport\n#\n# Check Automatic Error Reporting\n#\n# Refer to Section(s) 1.5.3 Page(s) 124   CIS Ubuntu 22.04 Benchmark v1.0.0\n# Refer to Section(s) 1.5.5 Page(s) 181-2 CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_apport () {\n  print_function \"audit_apport\"\n  string=\"Automatic Error Reporting\"\n  check_message  \"${string}\"\n  if [ \"${os_vendor}\" = \"Ubuntu\" ] && [ \"${os_version}\" -ge 22 ]; then\n    check_file_value    \"is\"     \"/etc/default/apport\"  \"enabled\" \"eq\" \"0\" \"hash\"\n    check_linux_service \"apport\" \"off\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/linux/audit_avahi_conf.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_avahi_conf\n#\n# Check Avahi Configuration\n# \n# Refer to Section(s) 3.1.3-6 Page(s) 68-72 CIS RHEL 5 Benchmark v2.1.0\n#.\n\naudit_avahi_conf () {\n  print_function \"audit_avahi_conf\"\n  string=\"Multicast DNS Server\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    for check_file in /etc/avahi/avahi-daemon.conf /usr/local/etc/avahi/avahi-daemon.conf; do\n      if [ -f \"${check_file}\" ]; then\n        check_file_value_with_position \"is\" \"${check_file}\" \"disable-user-service-publishing\" \"eq\" \"yes\" \"hash\" \"after\" \"\\[publish\\]\"\n        check_file_value_with_position \"is\" \"${check_file}\" \"disable-publishing\"              \"eq\" \"yes\" \"hash\" \"after\" \"\\[publish\\]\"\n        check_file_value_with_position \"is\" \"${check_file}\" \"publish-address\"                 \"eq\" \"no\"  \"hash\" \"after\" \"\\[publish\\]\"\n        check_file_value_with_position \"is\" \"${check_file}\" \"publish-binfo\"                   \"eq\" \"no\"  \"hash\" \"after\" \"\\[publish\\]\"\n        check_file_value_with_position \"is\" \"${check_file}\" \"publish-workstation\"             \"eq\" \"no\"  \"hash\" \"after\" \"\\[publish\\]\"\n        check_file_value_with_position \"is\" \"${check_file}\" \"publish-domain\"                  \"eq\" \"no\"  \"hash\" \"after\" \"\\[publish\\]\"\n        check_file_value_with_position \"is\" \"${check_file}\" \"disallow-other-stacks\"           \"eq\" \"yes\" \"hash\" \"after\" \"\\[server\\]\"\n        check_file_value_with_position \"is\" \"${check_file}\" \"check-response-ttl\"              \"eq\" \"yes\" \"hash\" \"after\" \"\\[server\\]\"\n      fi\n    done\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/linux/audit_avahi_server.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_avahi_server\n#\n# Check Avahi Server\n#\n# Refer to Section(s) 3.3   Page(s) 60    CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 3.3   Page(s) 67    CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 3.3   Page(s) 63    CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 2.2.3 Page(s) 103   CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 6.2   Page(s) 52-3  CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 2.2.3 Page(s) 95    CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 2.2.3 Page(s) 103   CIS Ubuntu 16.04 Benchmark v1.0.0\n# Refer to Section(s) 2.1.2 Page(s) 231-3 CIS Ubuntu 16.04 Benchmark v1.0.0\n#.\n\naudit_avahi_server () {\n  print_function \"audit_avahi_server\"\n  string=\"Avahi Server\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    for service_name in avahi avahi-autoipd avahi-daemon avahi-dnsconfd; do\n      check_linux_service \"${service_name}\" \"off\"\n    done\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/linux/audit_biosdevname.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_biosdevname\n#\n# Check BIOS dev names\n#\n# Refer to Section(s) 6.17 Page(s) 64 SLES 11 Benchmark v1.0.0\n#.\n\naudit_biosdevname () {\n  print_function \"audit_biosdevname\"\n  string=\"BIOS Devname\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${os_vendor}\" = \"SuSE\" ]; then\n      check_linux_package \"uninstall\" \"biosdevname\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/linux/audit_execshield.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_execshield\n#\n# Execshield is made up of a number of kernel features to provide protection\n# against buffer overflow attacks. These features include prevention of\n# execution in memory data space, and special handling of text buffers.\n#\n# Enabling any feature that can protect against buffer overflow attacks\n# enhances the security of the system.\n#\n# Refer to Section(s) 1.6.2   Page(s) 45-46   CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 1.6.2,4 Page(s) 51,52-3 CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 1.6.2   Page(s) 48      CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 4.2     Page(s) 36-7    CIS SLES 11 Benchmark v1.0.0\n#.\n\naudit_execshield () {\n  print_function \"audit_execshield\"\n  string=\"XD/NS Support\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${os_vendor}\" = \"CentOS\" ] || [ \"${os_vendor}\" = \"Red\" ]; then\n      if [ \"${os_version}\" -gt 4 ]; then\n        check_linux_package      \"install\"          \"kernel-PAE\"\n        check_file_value    \"is\" \"/etc/sysctl.conf\" \"kernel.exec-shield\" \"eq\" \"1\" \"hash\"\n        check_file_value    \"is\" \"/etc/sysctl.conf\" \"fs.suid.dumpable\"   \"eq\" \"0\" \"hash\"\n      fi\n    else\n      if [ \"${os_vendor}\" = \"SuSE\" ]; then\n        check_linux_package \"install\" \"kernel-pae\"\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/linux/audit_linux_logfiles.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_linux_logfiles\n#\n# Check permission on log files under Linux. Make sure they are only readable\n# by system accounts. \n#.\n\naudit_linux_logfiles () {\n  print_function \"audit_linux_logfiles\"\n  string=\"Log File Permissions\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    for log_file in boot.log btml cron dmesg ksyms httpd lastlog maillog \\\n      mailman messages news pgsql rpm pkgs sa samba scrollkeeper.log \\\n      secure spooler squid vbox wtmp; do\n      if [ -f \"/var/log/${log_file}\" ]; then\n        check_file_perms \"/var/log/${log_file}\" \"0600\" \"root\" \"root\"\n      fi\n    done\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/linux/audit_modprobe_conf.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_modprobe_conf\n#\n# Check modprobe on filesystems\n#\n# Refer to Section(s) 1.18-24,5.6.1-4     Page(s) 26-30,114-6   CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 1.18-24,4.6.1-4     Page(s) 27-32,90-2    CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 1.1.1.1-8,3.5.1-4   Page(s) 17-25,149-152 CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 1.1.1.1-8,3.5.1-4   Page(s) 16-24,144-7   CIS Ubuntu LTS 16.04 Benchmark v1.0.0\n# Refer to Section(s) 1.1.1.1-10,3.2.1-4  Page(s) 23-73,365-84  CIS Ubuntu LTS 24.04 Benchmark v1.0.0\n# Refer to Section(s) 2.18-24,7.5.1-4     Page(s) 26-30,80-3    CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 1.1.18-24,4.6.1-2   Page(s) 28-33,98-100  CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 1.1.1.1-18,3.5.1-4  Page(s) 16-24,135-8   CIS Amazon Linux Benchmark v2.0.0\n#.\n\naudit_modprobe_conf () {\n  print_function \"audit_modprobe_conf\"\n  string=\"Modprobe Configuration\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    for module in cramfs freevxfs hfs hfsplus jffs2 overlayfs squashfs udf usb-storage afs ceph \\\n      cifs ext fat fscache fuse gfs2 nfs_common nfsd smbfs_common tipc rds sctp dccp vfat; do\n      check_append_file \"/etc/modprobe.conf\" \"install ${module} /bin/false\" \"hash\"\n    done\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/linux/audit_pae.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_pae\n#\n# Check PAE settings\n#\n# Refer to Section(s) 1.5.1 Page(s) 88-9 CIS Ubuntu 22.04 Benchmark v1.0.0\n#.\n\naudit_pae () {\n  print_function \"audit_pae\"\n  string=\"XD/NX Support\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${os_platform}\" = \"x86_64\" ]; then\n      if [ -f \"/var/log/dmesg\" ]; then\n        check_nx=$( grep NX < /var/log/dmesg | grep \"protection: active\" | tail -1 | grep -c active | sed \"s/ //g\" )\n        if [ \"${check_nx}\" = \"1\" ]; then\n          inc_secure   \"XD/NX is enabled\"\n        else\n          inc_insecure \"XD/NX is not enabled\"\n        fi\n      else\n        na_message \"XD/NX Support is not available on ${os_platform}\"\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/linux/audit_prelink.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_prelink\n#\n# Check prelinking\n#\n# Refer to Section(s) 1.3.1-2       Page(s) 34-5    CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 1.3.1-2       Page(s) 39-40   CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 1.3.1-2       Page(s) 36-7    CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 1.3.1-2,1.5.4 Page(s) 54-6,66 CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 1.3.1-2       Page(s) 49-52   CIS Ubuntu LTS 16.04 Benchmark v1.0.0\n# Refer to Section(s) 1.5.2         Page(s) 122-3   CIS Ubuntu LTS 22.04 Benchmark v1.0.0\n# Refer to Section(s) 1.5.4         Page(s) 179-80  CIS Ubuntu LTS 24.04 Benchmark v1.0.0\n# Refer to Section(s) 8.3.1-2       Page(s) 112-3   CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 1.3.1-2       Page(s) 47-9    CIS Amazon Linux Benchmark v2.0.0\n#.\n\naudit_prelink () {\n  print_function \"audit_prelink\"\n  string=\"Prelinking\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${os_vendor}\" = \"CentOS\" ] || [ \"${os_vendor}\" = \"Red\" ] || [ \"${os_vendor}\" = \"Amazon\" ]; then\n      check_file=\"/etc/sysconfig/prelink\"\n    else\n      check_file=\"/etc/default/prelink\"\n    fi\n    if [ -f \"${check_file}\" ]; then\n      prelink_check=$( grep PRELINKING \"${check_file}\" | cut -f2 -d= | sed 's/ //g' )\n    else\n      prelink_check=\"no\"\n    fi\n    if [ \"${prelink_check}\" = \"yes\" ]; then\n      run_lockdown      \"prelink -ua\" \"Prelink to disabled\"\n    fi\n    check_linux_package \"uninstall\"   \"prelink\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/linux/audit_ptrace_scope.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_ptrace_scope\n#\n# Refer to Section(s) 1.5.2 Page(s) 170-4 CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_ptrace_scope () {\n  print_function \"audit_ptrace_scope\"\n  string=\"Ptrace scope is restricted\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${os_vendor}\" = \"Ubuntu\" ]; then\n      if [ \"${os_version}\" -ge 24 ]; then\n        check_file_value \"is\" \"/etc/sysctl.conf\" \"kernel.yama.ptrace_scope\" \"eq\" \"1\" \"hash\"\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}"
  },
  {
    "path": "modules/linux/audit_selinux.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_selinux\n#\n# Make sure SELinux is configured appropriately.\n#\n# Refer to Section(s) 1.4.1-5,1.5.1-2 Page(s) 36-40,41-2  CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 1.4.1-5,1.5.1-2 Page(s) 41-45,46-7  CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 1.4.1-5,1.5.1-2 Page(s) 39-42,43-4  CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 1.6.1.1-5       Page(s) 69-74       CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 1.6.1.1-3       Page(s) 64-7        CIS Ubuntu 16.04 Benchmark v1.0.0\n# Refer to Section(s) 1.6.1.1-5       Page(s) 60-66       CIS Amazon Linux Benchmark v2.0.0\n#.\n\naudit_selinux () {\n  print_function \"audit_selinux\"\n  string=\"SELinux\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    check_file_value     \"is\" \"/etc/selinux/config\" \"SELINUX\"     \"eq\"   \"enforcing\" \"hash\"\n    check_file_value     \"is\" \"/etc/selinux/config\" \"SELINUXTYPE\" \"eq\"   \"targeted\"  \"hash\"\n    check_file_perms          \"/etc/selinux/config\" \"0400\" \"root\" \"root\"\n    for check_file in /etc/grub.conf /boot/grub/grub.cfg; do\n      if [ -e \"${check_file}\" ]; then\n        check_file_perms      \"${check_file}\"       \"0400\"        \"root\" \"root\"\n        check_file_value \"is\" \"${check_file}\"       \"selinux\"     \"eq\"   \"1\"         \"hash\"\n        check_file_value \"is\" \"${check_file}\"       \"enforcing\"   \"eq\"   \"1\"         \"hash\"\n      fi\n    done\n    check_linux_package  \"uninstall\" \"setroubleshoot\"\n    check_linux_package  \"uninstall\" \"mctrans\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/linux/audit_sysctl.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_sysctl\n#\n# Check sysctl settings\n#\n# Refer to Section(s) 5.1-5.2.8,5.4.1,2             Page(s) 98-107                  CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 4.1.1-2,4.2.1-8,4.4.1         Page(s) 82-94                   CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 4.1.1-2,4.2.1-8,4.4.1.1       Page(s) 73-81,83-4              CIS RHEL 5 Benchmark v2.1.\n# Refer to Section(s) 1.4.1,1.5.3,3.1.1-8,3.3.1-3   Page(s) 57,65,129-142           CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 7.1.1-8,7.3.1-2               Page(s) 65-76                   CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 1.5.3,3.3.1-2,3.2.1-8,3.3.1-3 Page(s) 60-1,125-6,127-35,136-8 CIS Ubuntu 16.04 Benchmark v1.0.0\n# Refer to Section(s) 3.3.1-11                      Page(s) 386-436                 CIS Ubuntu 24.04 Benchmark v1.0.0\n# Refer to Section(s) 1.1.2,1.5.1,3,3.1.1-8,3.3.1-3 Page(s) 24-6,53,57,116-29       CIS Amazon Linux Benchmark v2.0.0\n#.\n\naudit_sysctl () {\n  print_function \"audit_sysctl\"\n  string=\"Sysctl Configuration\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    check_file_value  \"is\" \"/etc/sysctl.conf\"     \"net.ipv4.conf.default.secure_redirects\"     \"eq\"   \"0\"    \"hash\"\n    check_file_value  \"is\" \"/etc/sysctl.conf\"     \"net.ipv4.conf.all.secure_redirects\"         \"eq\"   \"0\"    \"hash\"\n    check_file_value  \"is\" \"/etc/sysctl.conf\"     \"net.ipv4.icmp_echo_ignore_broadcasts\"       \"eq\"   \"1\"    \"hash\"\n    check_file_value  \"is\" \"/etc/sysctl.conf\"     \"net.ipv4.conf.all.accept_redirects\"         \"eq\"   \"0\"    \"hash\"\n    check_file_value  \"is\" \"/etc/sysctl.conf\"     \"net.ipv4.conf.default.accept_redirects\"     \"eq\"   \"0\"    \"hash\"\n    check_file_value  \"is\" \"/etc/sysctl.conf\"     \"net.ipv4.tcp_syncookies\"                    \"eq\"   \"1\"    \"hash\"\n    check_file_value  \"is\" \"/etc/sysctl.conf\"     \"net.ipv4.tcp_max_syn_backlog\"               \"eq\"   \"4096\" \"hash\"\n    check_file_value  \"is\" \"/etc/sysctl.conf\"     \"net.ipv4.conf.all.rp_filter\"                \"eq\"   \"1\"    \"hash\"\n    check_file_value  \"is\" \"/etc/sysctl.conf\"     \"net.ipv4.conf.default.rp_filter\"            \"eq\"   \"1\"    \"hash\"\n    check_file_value  \"is\" \"/etc/sysctl.conf\"     \"net.ipv4.conf.all.accept_source_route\"      \"eq\"   \"0\"    \"hash\"\n    check_file_value  \"is\" \"/etc/sysctl.conf\"     \"net.ipv4.conf.default.accept_source_route\"  \"eq\"   \"0\"    \"hash\"\n    check_file_value  \"is\" \"/etc/sysctl.conf\"     \"net.ipv4.tcp_max_orphans\"                   \"eq\"   \"256\"  \"hash\"\n    check_file_value  \"is\" \"/etc/sysctl.conf\"     \"net.ipv4.conf.all.log_martians\"             \"eq\"   \"1\"    \"hash\"\n    check_file_value  \"is\" \"/etc/sysctl.conf\"     \"net.ipv4.ip_forward\"                        \"eq\"   \"0\"    \"hash\"\n    check_file_value  \"is\" \"/etc/sysctl.conf\"     \"net.ipv4.conf.all.send_redirects\"           \"eq\"   \"0\"    \"hash\"\n    check_file_value  \"is\" \"/etc/sysctl.conf\"     \"net.ipv4.conf.default.send_redirects\"       \"eq\"   \"0\"    \"hash\"\n    check_file_value  \"is\" \"/etc/sysctl.conf\"     \"net.ipv4.icmp_ignore_bogus_error_responses\" \"eq\"   \"1\"    \"hash\"\n    check_file_value  \"is\" \"/etc/sysctl.conf\"     \"net.ipv6.conf.default.accept_redirects\"     \"eq\"   \"0\"    \"hash\"\n    check_file_value  \"is\" \"/etc/sysctl.conf\"     \"net.ipv6.conf.all.accept_ra\"                \"eq\"   \"0\"    \"hash\"\n    check_file_value  \"is\" \"/etc/sysctl.conf\"     \"net.ipv6.conf.default.accept_ra\"            \"eq\"   \"0\"    \"hash\"\n    check_file_value  \"is\" \"/etc/sysctl.conf\"     \"net.ipv6.route.flush\"                       \"eq\"   \"1\"    \"hash\"\n    check_file_value  \"is\" \"/etc/sysctl.conf\"     \"kernel.randomize_va_space\"                  \"eq\"   \"2\"    \"hash\"\n    check_append_file \"/etc/security/limits.conf\" \"* hard core 0\"                              \"hash\"\n    check_file_perms  \"/etc/sysctl.conf\"          \"0600\"                                       \"root\" \"root\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/linux/audit_virtual_memory.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_virtual_memory\n#\n# Refer to Section(s) 1.6.3 Page(s) 46    CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 1.6.3 Page(s) 51-2  CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 1.6.3 Page(s) 48-9  CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 4.3   Page(s) 37    CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 1.5.3 Page(s) 57    CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 1.5.1 Page(s) 166-9 CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_virtual_memory () {\n  print_function \"audit_virtual_memory\"\n  string=\"Randomised Virtual Memory Region Placement\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${os_vendor}\" = \"CentOS\" ] || [ \"${os_vendor}\" = \"Red\" ] || [ \"${os_vendor}\" = \"Ubuntu\" ]; then\n      if [ \"${os_version}\" -gt 5 ]; then\n        check_file_value \"is\" \"/etc/sysctl.conf\" \"kernel.randomize_va_space\" \"eq\" \"2\" \"hash\"\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/linux/audit_xen.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_xen\n#\n# Turn off Xen services if they are not being used.\n#.\n\naudit_xen () {\n  print_function \"audit_xen\"\n  string=\"Xen Daemons\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    for service_name in xend xendomains; do\n      check_linux_service \"${service_name}\" \"off\"\n    done\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/linux/audit_xinetd.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_xinetd\n#\n# Check inetd services\n#\n# Refer to Section(s) 2.1.12-8  Page(s) 54-8  CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 2.1.12-8  Page(s) 63-6  CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 2.1.12-8  Page(s) 57-61 CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 2.1.1-7   Page(s) 91-7  CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 2.1.10-1  Page(s) 88-9  CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 2.1.19    Page(s) 280-2 CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_xinetd () {\n  print_function \"audit_xinetd\"\n  string=\"Xinetd Services\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    check_dir=\"/etc/xinetd.d\"\n    if [ -d \"${check_dir}\" ]; then\n      check=$( find \"${check_dir}\" -type f )\n      if [ -n \"${check}\" ]; then\n        verbose_message \"Xinet Services\" \"check\"\n        command=\"grep disable \\\"${check_dir}/*\\\" | awk '{print \\$3}' | grep no | head -1 | grep -c no |sed \\\"s/ //g\\\"\"\n        command_message \"${command}\"\n        xinetd_check=$( eval \"${command}\" )\n        if [ \"${xinetd_check}\" = \"1\" ]; then\n          for service_name in amanda amandaidx amidxtape auth chargen-dgram \\\n            chargen-stream cvs daytime-dgram daytime-stream discard-dgram \\\n            echo-dgram echo-stream eklogin ekrb5-telnet gssftp klogin krb5-telnet \\\n            kshell ktalk ntalk rexec rlogin rsh rsync talk tcpmux-server telnet \\\n            tftp time-dgram time-stream uucp; do\n            check_xinetd_service \"${service_name}\" \"disable\" \"yes\"\n          done\n        else\n          check_linux_service \"xinetd\" \"off\"\n        fi\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/linux/audit_xinetd_server.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_xinetd_server\n#\n# Refer to Section(s) 2.1.11 Page(s) 54   CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 2.1.11 Page(s) 62   CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 2.1.11 Page(s) 46-7 CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 2.1.7  Page(s) 97   CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 5.1.9  Page(s) 45-6 CIS SLES 11 Benchmark v1.0.0\n#.\n\naudit_xinetd_server () {\n  print_function \"audit_xinetd_server\"\n  string=\"Xinetd Server Daemon\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    service_name=\"xinetd\"\n    check_linux_service \"${service_name}\" \"off\"\n    if [ \"${os_vendor}\" = \"CentOS\" ] || [ \"${os_vendor}\" = \"Red\" ]; then\n      check_linux_package \"uninstall\" \"${service_name}\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/linux/audit_yum_conf.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_yum_conf\n#\n# Make sure GPG checks are enabled for yum so that malicious sofware can not\n# be installed.\n#\n# Refer to Section(s) 1.2.3 Page(s) 32 CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 1.2.2 Page(s) 50 CIS RHEL 7 Benchmark v1.0.0\n# Refer to Section(s) 1.2.3 Page(s) 34 CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 1.1.3 Page(s) 34 CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 1.2.3 Page(s) 46 CIS Amazon Linux Benchmark v2.0.0\n#.\n\naudit_yum_conf () {\n  print_function \"audit_yum_conf\"\n  string=\"Yum Configuration\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${os_vendor}\" = \"CentOS\" ] || [ \"${os_vendor}\" = \"Red\" ]; then\n      check_file_value \"is\" \"/etc/yum.conf\" \"gpgcheck\" \"eq\" \"1\" \"hash\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/login/audit_console_login.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2028\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_console_login\n#\n# Check console login\n#\n# Refer to Section(s) 6.4   Page(s) 142-3 CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 6.4   Page(s) 165   CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 6.4   Page(s) 145   CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 5.5   Page(s) 256   CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 9.3.4 Page(s) 134-5 CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 6.14  Page(s) 57    CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 6.10  Page(s) 95-6  CIS Solaris 10 Benchamrk v5.1.0\n# Refer to Section(s) 5.5   Page(s) 248   CIS Ubuntu 16.04 Benchmark v1.0.0\n#.\n\naudit_console_login () {\n  print_function \"audit_console_login\"\n  string=\"Root Login to System Console\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ]; then\n      check_file=\"/etc/default/login\"\n      check_file_value \"is\" \"${check_file}\" \"CONSOLE\" \"eq\" \"/dev/console\" \"hash\"\n    fi\n    if [ \"${os_version}\" = \"11\" ]; then\n      service_name=\"svc:/system/console-login:terma\"\n      check_sunos_service \"svc:/system/console-login:terma\" \"disabled\"\n      service_name=\"svc:/system/console-login:termb\"\n      check_sunos_service \"${service_name}\" \"disabled\"\n    fi\n  fi\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    check_file=\"/etc/securetty\"\n    if [ -f \"${check_file}\" ]; then\n      string=\"Root Login to System Console\"\n      check_message  \"${string}\"\n      disable_ttys=0\n      console_list=\"\"\n      if [ \"${audit_mode}\" != 2 ]; then\n        if [ \"${ansible_mode}\" = 1 ]; then\n          echo \"\"\n          echo \"- name: ${string}\"\n          echo \"  lineinfile:\"\n          echo \"    path: ${check_file}\"\n          echo \"    regexp: '^tty[0-9]\"\n          echo \"    replace: '#\\1'\"\n          echo \"  when: ansible_facts['ansible_system'] == '${os_name}'\"\n          echo \"\"\n        fi\n        device_list=$( grep '^tty[0-9]' ${check_file} )\n        for console_device in $device_list; do\n          disable_ttys=1\n          console_list=\"$console_list ${console_device}\"\n        done\n        if [ \"${disable_ttys}\" = 1 ]; then\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_insecure \"Consoles enabled on \\\"$console_list\\\"\"\n            fix_message  \"ed 's/^tty[0-9].*//g' < ${check_file} | grep '[a-z]' > ${temp_file}\"\n            fix_message  \"cat ${temp_file} > ${check_file}\"\n            fix_message  \"rm ${temp_file}\"\n          fi\n          if [ \"${audit_mode}\" = 0 ]; then\n            backup_file  \"${check_file}\"\n            set_message  \"Consoles to disabled on \\\"$console_list\\\"\"\n            command=\"sed \\\"s/tty[0-9].*//g\\\" < \\\"${check_file}\\\" | grep '[a-z]' > \\\"${temp_file}\\\"\"\n            command_message \"${command}\"\n            eval \"${command}\"\n            command=\"cat \\\"${temp_file}\\\" > \\\"${check_file}\\\"\"\n            command_message \"${command}\"\n            eval \"${command}\"\n            if [ -f \"${temp_file}\" ]; then\n              rm \"${temp_file}\"\n            fi\n          fi\n        else\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_secure \"No consoles enabled on tty[0-9]*\"\n          fi\n        fi\n      else\n        restore_file \"${check_file}\" \"${restore_dir}\"\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/login/audit_failed_logins.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_failed_logins\n#\n# Check failed logins\n#\n# Refer to Section(s) 4.6 Page(s) 70-1 CIS Solaris 10 Benchmark v5.1.0\n#.\n\naudit_failed_logins () {\n  print_function \"audit_failed_logins\"\n  string=\"Failed Login Attempts\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ]; then\n      check_file_value \"is\" \"/etc/default/login\" \"SYSLOG_FAILED_LOGINS\" \"eq\" \"0\"    \"hash\"\n      check_file_value \"is\" \"/etc/default/login\" \"SYSLOG\"               \"eq\" \"YES\"  \"hash\"\n      check_file_value \"is\" \"/etc/default/su\"    \"SYSLOG\"               \"eq\" \"YES\"  \"hash\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/login/audit_issue_banner.sh",
    "content": "#!/bin/sh -eu\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2129\n# shellcheck disable=SC2154\n\n# audit_issue_banner\n#\n# Check security banner\n#\n# Refer to Section(s) 8.1-2     Page(s) 149-151 CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 8.1.1-2   Page(s) 172-4   CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 8.1-2     Page(s) 152-4   CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 1.7.1.1-3 Page(s) 78-83   CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 11.1-2    Page(s) 142-3   CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 7.4       Page(s) 25      CIS FreeBSD Benchmark v1.0.5\n# Refer to Section(s) 1.7.1.1-3 Page(s) 68-73   CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 1.7.1.1-6 Page(s) 75-83   CIS Ubuntu 16.04 Benchmark v1.0.0\n# Refer to Section(s) 1.6.1-6   Page(s) 184-95  CIS Ubuntu 24.04 Benchmark v1.0.0\n# Refer to Section(s) 5.13      Page(s) 143     CIS Apple OS X 10.12 Benchmark v1.0.0\n# Refer to Section(s) 5.8       Page(s) 352-4   CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_issue_banner () {\n  print_function \"audit_issue_banner\"\n  string=\"Security Warning Message\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"FreeBSD\" ] || [ \"${os_name}\" = \"Darwin\" ] || [ \"${os_name}\" = \"AIX\" ]; then\n    if [ \"${os_name}\" = \"Darwin\" ]; then\n      file_list=\"/etc/issue /etc/motd /etc/issue.net /Library/Security/PolicyBanner.txt\"\n    else\n      file_list=\"/etc/issue /etc/motd /etc/issue.net\"\n    fi\n    for check_file in ${file_list}; do\n      if [ -f \"${check_file}\" ]; then\n        check_file_perms    \"${check_file}\" 0644 root root\n        command=\"grep -cE \\\"NOTICE TO USERS|UNAUTHORIZED ACCESS\\\" \\\"${check_file}\\\" | sed \\\"s/ //g\\\"\"\n        command_message     \"${command}\"\n        issue_check=$( eval \"${command}\" )\n      else\n        issue_check=0\n      fi\n      if [ \"${audit_mode}\" != 2 ]; then\n       verbose_message \"Security message in \\\"${check_file}\\\"\" \"check\"\n        if [ \"${issue_check}\" = 0 ]; then\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_insecure \"No security message in \\\"${check_file}\\\"\"\n          fi\n          if [ \"${audit_mode}\" = 0 ]; then\n            set_message \"Security message in \\\"${check_file}\\\"\"\n            backup_file \"${check_file}\"\n            echo \"###############################################################################\" >  \"${check_file}\"\n            echo \"#                             NOTICE TO USERS                                 #\" >> \"${check_file}\"\n            echo \"#                             ---------------                                 #\" >> \"${check_file}\"\n            echo \"# This computer system is the private property of this company:               #\" >> \"${check_file}\"\n            echo \"# Whether individual, corporate or government. It is for authorized use only. #\" >> \"${check_file}\"\n            echo \"# Users (authorized & unauthorized) have no explicit/implicit expectation of  #\" >> \"${check_file}\"\n            echo \"# privacy.                                                                    #\" >> \"${check_file}\"\n            echo \"#                                                                             #\" >> \"${check_file}\"\n            echo \"# Any or all uses of this system and all files on this system may be          #\" >> \"${check_file}\"\n            echo \"# intercepted, monitored, recorded, copied, audited, inspected, and           #\" >> \"${check_file}\"\n            echo \"# disclosed to your employer, to authorized site, government, and/or          #\" >> \"${check_file}\"\n            echo \"# law enforcement personnel, as well as authorized officials of government    #\" >> \"${check_file}\"\n            echo \"# agencies, both domestic and foreign.                                        #\" >> \"${check_file}\"\n            echo \"#                                                                             #\" >> \"${check_file}\"\n            echo \"# By using this system, the user expressly consents to such interception,     #\" >> \"${check_file}\"\n            echo \"# monitoring, recording, copying, auditing, inspection, and disclosure at     #\" >> \"${check_file}\"\n            echo \"# the discretion of such officials. Unauthorized or improper use of this      #\" >> \"${check_file}\"\n            echo \"# system may result in civil and criminal penalties and administrative or     #\" >> \"${check_file}\"\n            echo \"# disciplinary action, as appropriate. By continuing to use this system       #\" >> \"${check_file}\"\n            echo \"# you indicate your awareness of and consent to these terms and conditions.   #\" >> \"${check_file}\"\n            echo \"#                                                                             #\" >> \"${check_file}\"\n            echo \"# LOG OFF IMMEDIATELY if you do not agree to the conditions in this warning.  #\" >> \"${check_file}\"\n            echo \"###############################################################################\" >> \"${check_file}\"\n            # Alternate message\n            # echo \"---------------------------------------------------------------------------------\" >> \"${check_file}\"\n            # echo \"UNAUTHORIZED ACCESS TO THIS DEVICE IS PROHIBITED                                 \" >> \"${check_file}\"\n            # echo \"You must have explicit, authorized permission to access or configure this device.\" >> \"${check_file}\"\n            # echo \"Unauthorized attempts and actions to access or use this system may result in     \" >> \"${check_file}\"\n            # echo \"civil and/or criminal penalties.                                                 \" >> \"${check_file}\"\n            # echo \"All activities performed on this device are logged and monitored.                \" >> \"${check_file}\"\n            # echo \"---------------------------------------------------------------------------------\" >> \"${check_file}\"\n            echo \"\" >> \"${check_file}\"\n          fi\n        else\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_secure \"Security message in \\\"${check_file}\\\"\"\n          fi\n        fi\n      else\n        restore_file \"${check_file}\" \"${restore_dir}\"\n      fi\n    done\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/login/audit_login_delay.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_login_delay\n#\n# Refer to Section(s) 6.10 Page(s) 53-4 CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 6.6  Page(s) 91   CIS Solaris 10 Benchmark v5.1.0\n#.\n\naudit_login_delay () {\n  print_function \"audit_login_delay\"\n  string=\"Delay between Failed Login Attempts\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    check_file_value \"is\" \"/etc/default/login\" \"SLEEPTIME\" \"eq\" \"4\" \"hash\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/login/audit_login_details.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_login_details\n#\n# Refer to Section 6.1.1  Page(s) 72-73 CIS Apple OS X 10.8 Benchmark v1.0.0\n# Refer to Section 2.10.4 Page(s) 226-8 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_login_details () {\n  print_function \"audit_login_details\"\n  string=\"Login display details\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    check_osx_defaults_bool \"/Library/Preferences/com.apple.loginwindow\" \"SHOWFULLNAME\" \"yes\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/login/audit_login_guest.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_login_guest\n#\n# Refer to Section 1.4.2.7 Page(s)       CIS Apple OS X 10.6 Benchmark v1.0.0\n# Refer to Section 6.1.3   Page(s) 156-7 CIS Apple OS X 10.12 Benchmark v1.0.0\n# Refer to Section 2.12.1  Page(s) 242-5 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_login_guest () {\n  print_function \"audit_login_guest\"\n  string=\"Guest login\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    check_osx_defaults_bool   \"/Library/Preferences/com.apple.loginwindow.plist\" \"GuestEnabled\" \"no\"\n    check_dscl \"/Users/Guest\" \"AuthenticationAuthority\" \";basic;\"\n    check_dscl \"/Users/Guest\" \"passwd\"                  \"*\"\n    check_dscl \"/Users/Guest\" \"UserShell\"               \"/sbin/nologin\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/login/audit_login_records.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_login_records\n#\n# Refer to Section(s) 4.5 Page(s) 69-70 CIS Solaris 10 Benchmark v5.1.0\n#.\n\naudit_login_records () {\n  print_function \"audit_login_records\"\n  string=\"Login Records\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ]; then\n      audit_logadm_value \"loginlog\" \"none\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/login/audit_login_root.sh",
    "content": "#!/bin/sh\n\n# -> Needs fixing\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_login_root\n#\n# Check root login\n#\n# Refer to Section(s) 5.7 Page(s) 135 CIS Apple OS X 10.12 Benchmark v1.0.0\n# Refer to Section(s) 5.6 Page(s) 348-9 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_login_root () {\n  print_function \"audit_login_root\"\n  string=\"Root login\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    check_dscl \"/Users/root\" \"AuthenticationAuthority\" \"No such key: AuthenticationAuthority\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/login/audit_login_warning.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_login_warning\n#\n# An access warning may reduce a casual attacker's tendency to target the system.\n# Access warnings may also aid in the prosecution of an attacker by evincing the\n# attacker's knowledge of the system's private status, acceptable use policy, and\n# authorization requirements.\n#\n# Refer to Section(s) 5.19   Page(s) 67-8  CIS Apple OS X 10.8 Benchmark v1.0.0\n# Refer to Section(s) 5.12   Page(s) 142   CIS Apple OS X 10.12 Benchmark v1.0.0\n# Refer to Section(s) 2.10.1 Page(s) 226-8 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_login_warning () {\n  print_function \"audit_login_warning\"\n  string=\"Login message warning\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    check_osx_defaults_value \"com.apple.loginwindow\" \"LoginwindowText\" \"Authorised users only\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/login/audit_remote_login.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_remote_login\n#\n# Check remote login\n#\n# Refer to Section(s) 2.4.5   Page(s) 42-3  CIS Apple OS X 10.12 Benchmark v1.0.0\n# Refer to Section(s) 2.3.3.5 Page(s) 100-3 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_remote_login () {\n  print_function \"audit_remote_login\"\n  string=\"Remote Login\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    check_osx_systemsetup \"getremotelogin\" \"off\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/login/audit_retry_limit.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_retry_limit\n#\n# Check retry limit for account lockout\n#\n# Refer to Section(s) 1.2.1-6 Page(s) 26-31 CIS AIX Benchmark v1.1.0\n# Refer to Section(s) 6.15    Page(s) 57-9  CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 6.11    Page(s) 96-7  CIS Solaris 10 Benchmark v5.1.0\n#.\n\naudit_retry_limit () {\n  print_function \"audit_retry_limit\"\n  string=\"Retry Limit for Account Lockout\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"AIX\" ]; then\n    if [ \"${os_name}\" = \"AIX\" ]; then\n      check_chsec \"/etc/security/login.cfg\" \"default\" \"logininterval\" \"300\"\n      check_chsec \"/etc/security/login.cfg\" \"default\" \"logindisable\"  \"10\"\n      check_chsec \"/etc/security/login.cfg\" \"default\" \"loginreenable\" \"360\"\n      check_chsec \"/etc/security/login.cfg\" \"usw\"     \"logintimeout\"  \"30\"\n      check_chsec \"/etc/security/login.cfg\" \"default\" \"logindelay\"    \"10\"\n      check_chsec \"/etc/security/user\"      \"default\" \"loginretries\"  \"3\"\n    fi\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n        check_file_value \"is\" \"/etc/default/login\"        \"RETRIES\"            \"eq\" \"3\"   \"hash\"\n        check_file_value \"is\" \"/etc/security/policy.conf\" \"LOCK_AFTER_RETRIES\" \"eq\" \"YES\" \"hash\"\n        if [ \"${os_version}\" = \"11\" ]; then\n          svcadm \"restart\" \"svc:/system/name-service/cache\"\n        fi\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/login/audit_security_banner.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_security_banner\n#\n# Check Security banner\n#\n# Refer to Section(s) 7.4             Page(s) 25 CIS  CIS FreeBSD Benchmark v1.0.5\n# Refer to Section(s) 2.11.11,2.12.12 Page(s) 198,216 CIS AIX Benchmark v1.1.0\n# Refer to Section(s) 8.1.1           Page(s) 172-3   CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 8.1             Page(s) 152-3   CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 1.7.1.4-6       Page(s) 84-8    CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 11.1            Page(s) 142-3   CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 8.1             Page(s) 68-9    CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 8.1             Page(s) 111-2   CIS Solaris 10 Benchmark v5.1.0\n# Refer to Section(s) 1.7.1.4-6       Page(s) 74-6    CIS Amazon Linux Benchmark v2.0.0\n#.\n\naudit_security_banner () {\n  print_function \"audit_security_banner\"\n  string=\"Warnings for Standard Login Services\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"FreeBSD\" ] || [ \"${os_name}\" = \"AIX\" ]; then\n    if [ \"${os_name}\" = \"AIX\" ]; then\n      user_name=\"bin\"\n      group_name=\"bin\"\n    else\n      user_name=\"root\"\n      group_name=\"root\"\n    fi\n    check_file=\"/etc/motd\"\n    check_file_exists  \"${check_file}\" \"yes\"\n    if [ -f \"${check_file}\" ]; then\n      check_file_perms \"${check_file}\" \"0644\" \"${user_name}\" \"${group_name}\"\n    fi\n    check_file=\"/etc/issue\"\n    check_file_exists  \"${check_file}\" \"yes\"\n    if [ -f \"${check_file}\" ]; then\n      check_file_perms \"${check_file}\" \"0644\" \"${user_name}\" \"${group_name}\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/login/audit_serial_login.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC2034\n# shellcheck disable=SC1090\n# shellcheck disable=SC2154\n\n# audit_serial_login\n#\n# Refer to Section(s) 3.1    Page(s) 9     CIS FreeBSD Benchmark v1.0.5\n# Refer to Section(s) 2.12.1 Page(s) 206-7 CIS AIX Benchmark v1.1.0\n# Refer to Section(s) 6.1    Page(s) 46-7  CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 6.2    Page(s) 87-8  CIS Solaris 10 Benchmark v5.1.0\n#.\n\naudit_serial_login () {\n  print_function \"audit_serial_login\"\n  string=\"Login on Serial Ports\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"FreeBSD\" ] || [ \"${os_name}\" = \"AIX\" ]; then\n    if [ \"${os_name}\" = \"AIX\" ]; then\n      command=\"lsitab –a | grep \\\"on:/usr/sbin/getty\\\" | awk '{print \\$2}'\"\n      command_message  \"${command}\"\n      tty_list=$( eval \"${command}\" )\n      if [ -z \"${tty_list}\" ]; then\n        if [ \"${audit_mode}\" = 1 ]; then\n          inc_secure \"Serial port logins disabled\"\n        fi\n        if [ \"${audit_mode}\" = 2 ]; then\n          command=\"lsitab –a | grep \\\"/usr/sbin/getty\\\" | awk '{print \\$2}'\"\n          command_message  \"${command}\"\n          tty_list=$( eval \"${command}\" )\n          for tty_name in ${tty_list}; do\n            log_file=\"${restore_dir}/${tty_name}\"\n            if [ -f \"${log_file}\" ]; then\n              command=\"cat \\\"${log_file}\\\"\"\n              command_message \"${command}\"\n              previous_value=$( eval \"${command}\" )\n              restore_message \"TTY \\\"${tty_name}\\\" to \\\"${previous_value}\\\"\"\n              command=\"chitab \\\"${previous_value} ${tty_name}\\\"\"\n              command_message \"${command}\"\n              eval \"${command}\"\n            fi\n          done\n        fi\n      else\n        for tty_name in ${tty_list}; do\n          if [ \"${audit_mode}\" != 2 ]; then\n            log_file=\"${work_dir}/${tty_name}\"\n            command=\"lsitab -a | grep \\\"on:/usr/sbin/getty\\\" | grep \\\"${tty_name}\\\"\"\n            command_message      \"${command}\"\n            actual_value=$( eval \"${command}\" )\n            command=\"echo \\\"${actual_value}\\\" | sed 's/on/off/g'\"\n            command_message      \"${command}\"\n            new_value=$( eval    \"${command}\" )\n            if [ \"${audit_mode}\" = 1 ]; then\n              inc_insecure \"Serial port logins not disabled on \\\"${tty_name}\\\"\"\n              fix_message  \"chitab \\\"${new_value}\\\"\"\n            fi\n            if [ \"${audit_mode}\" = 0 ]; then\n              command=\"echo \\\"${actual_value}\\\" > \\\"${log_file}\\\"\"\n              command_message \"${command}\"\n              eval \"${command}\"\n              command=\"chitab \\\"${new_value} ${tty_name}\\\"\"\n              command_message \"${command}\"\n              eval \"${command}\"\n            fi\n          else\n            log_file=\"${restore_dir}/${tty_name}\"\n            if [ -f \"${log_file}\" ]; then\n              command=\"cat \\\"${log_file}\\\"\"\n              command_message        \"${command}\"\n              previous_value=$( eval \"${command}\" )\n              verbose_message \"Restoring: TTY \\\"${tty_name}\\\" to \\\"${previous_value}\\\"\"\n              command=\"chitab \\\"${previous_value} ${tty_name}\\\"\"\n              command_message \"${command}\"\n              eval \"${command}\"\n            fi\n          fi\n        done\n      fi\n    fi\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      if [ \"${os_version}\" != \"11\" ]; then\n        command=\"pmadm -L | grep -E \\\"ttya|ttyb\\\" | cut -f4 -d \\\":\\\" | grep -c \\\"ux\\\"\"\n        command_message      \"${command}\"\n        serial_test=$( eval  \"${command}\" )\n        log_file=\"${work_dir}/pmadm.log\"\n        command=\"expr \\\"$serial_test\\\" : \\\"2\\\"\"\n        command_message      \"${command}\"\n        serial_check=$( eval \"${command}\" )\n        if [ \"${serial_check}\" = \"1\" ]; then\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_secure \"Serial port logins disabled\"\n          fi\n        else\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_insecure \"Serial port logins not disabled\"\n            fix_message  \"pmadm -d -p zsmon -s ttya\"\n            fix_message  \"pmadm -d -p zsmon -s ttyb\"\n          fi\n          if [ \"${audit_mode}\" = 0 ]; then\n            set_message \"Serial port logins to disabled\"\n            command=\"echo \\\"ttya,ttyb\\\" >> \\\"${log_file}\\\"\"\n            command_message \"${command}\"\n            eval \"${command}\"\n            command=\"pmadm -d -p zsmon -s ttya\"\n            command_message \"${command}\"\n            eval \"${command}\"\n            command=\"pmadm -d -p zsmon -s ttyb\"\n            command_message \"${command}\"\n            eval \"${command}\"\n          fi\n        fi\n        if [ \"${audit_mode}\" = 2 ]; then\n          restore_file=\"${restore_dir}/pmadm.log\"\n          if [ -f \"${restore_file}\" ]; then\n            restore_message \"Serial port logins to enabled\"\n            command=\"pmadm -e -p zsmon -s ttya\"\n            command_message \"${command}\"\n            eval \"${command}\"\n            command=\"pmadm -e -p zsmon -s ttyb\"\n            command_message \"${command}\"\n            eval \"${command}\"\n          fi\n        fi\n      fi\n    fi\n    if [ \"${os_name}\" = \"FreeBSD\" ]; then\n      check_file=\"/etc/ttys\"\n      check_string=\"dialup\"\n      command=\"grep \\\"${check_string}\\\" \\\"${check_file}\\\" |awk '{print \\$5}'\"\n      command_message   \"${command}\"\n      ttys_test=$( eval \"${command}\" )\n      if [ \"${ttys_test}\" != \"off\" ]; then\n        if [ \"${audit_mode}\" != 2 ]; then\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_insecure \"Serial port logins not disabled\"\n          fi\n          if [ \"${audit_mode}\" = 2 ]; then\n            set_message \"Serial port logins to disabled\"\n            backup_file \"${check_file}\"\n            temp_file=\"${temp_dir}/ttys_${check_string}\"\n            command=\"awk '(\\\\$4 == \\\"dialup\\\") { \\\\$5 = \\\"off\\\" } { print }' < \\\"${check_file}\\\" > \\\"${temp_file}\\\"\"\n            command_message \"${command}\"\n            eval \"${command}\"\n            command=\"cat \\\"${temp_file}\\\" > \\\"${check_file}\\\"\"\n            command_message \"${command}\"\n            eval \"${command}\"\n          fi\n        else\n          restore_file \"${check_file}\" \"${restore_dir}\"\n        fi\n      else\n        if [ \"${audit_mode}\" = 1 ]; then\n          inc_secure \"Serial port logins disabled\"\n        fi\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/login/audit_sulogin.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_sulogin\n#\n# Check single user mode requires password\n#\n# Refer to Section(s) 1.5.4-5 Page(s) 43-44 CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 1.4.3   Page(s) 60    CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 3.2     Page(s) 9     CIS FreeBSD Benchmark v1.0.5\n# Refer to Section(s) 3.4     Page(s) 33-4  CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 1.5.4-5 Page(s) 48-9  CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 1.5.4-5 Page(s) 45-6  CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 1.4.2-3 Page(s) 51-2  CIS Amazon Linux Benchmark v2.0.0\n#.\n\naudit_sulogin () {\n  print_function \"audit_sulogin\"\n  string=\"Single User Mode Requires Password\"\n  check_message  \"${string}\"\n  temp_file=\"${temp_dir}/audit_sulogin\"\n  if [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"FreeBSD\" ]; then\n    if [ \"${os_name}\" = \"FreeBSD\" ]; then\n      check_file=\"/etc/ttys\"\n      check_string=\"console\"\n      command=\"grep \\\"${check_string}\\\" \\\"${check_file}\\\" |awk '{print \\$5}'\"\n      command_message \"${command}\"\n      ttys_test=$( eval \"${command}\" )\n      if [ \"${ttys_test}\" != \"insecure\" ]; then\n        if [ \"${audit_mode}\" != 2 ]; then\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_insecure \"Single user mode does not require a password\"\n          fi\n          if [ \"${audit_mode}\" = 2 ]; then\n            set_message  \"Single user mode to require a password\"\n            backup_file  \"${check_file}\"\n            lock_command=\"awk '($4 == \\\"console\\\") { $5 = \\\"insecure\\\" } { print }' < ${check_file} > ${temp_file} ; cat ${temp_file} > ${check_file}\"\n            run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n          fi\n        else\n          restore_file \"${check_file}\" \"${restore_dir}\"\n        fi\n      else\n        if [ \"${audit_mode}\" = 1 ]; then\n          inc_secure \"Single user login requires password\"\n        fi\n      fi\n    fi\n    if [ \"${os_name}\" = \"Linux\" ] && [ \"${os_vendor}\" = \"Red\" ] && [ \"${os_version}\" = \"7\" ]; then\n      check_file_value \"is\" \"/usr/lib/systemd/system/rescue.service\"    \"ExecStart\" \"eq\" \"-/bin/sh -c \\\"/sbin/sulogin; /usr/bin/systemctl --fail --no-block default\\\"\" \"hash\" \"2\" \"blockdefault\"\n      check_file_value \"is\" \"/usr/lib/systemd/system/emergency.service\" \"ExecStart\" \"eq\" \"-/bin/sh -c \\\"/sbin/sulogin; /usr/bin/systemctl --fail --no-block default\\\"\" \"hash\" \"2\" \"blockdefault\"\n    fi\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      check_file=\"/etc/inittab\"\n      if [ -f \"${check_file}\" ]; then\n        command=\"grep -l sulogin \\\"${check_file}\\\"\"\n        command_message \"${command}\"\n        sulogin_check=$( eval \"${command}\" )\n        if [ -z \"$sulogin_check\" ]; then\n          lock_message=\"Single user mode to require authentication\"\n          lock_command=\"awk '{ print }; /^id:[0123456sS]:initdefault:/ { print \\\"~~:S:wait:/sbin/sulogin\\\" }' < ${check_file} > ${temp_file} ; cat ${temp_file} > ${check_file} ; rm $temp_file\"\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_insecure \"No Authentication required for single usermode\"\n            fix_message  \"${lock_command}\"\n          fi\n          if [ \"${audit_mode}\" = 0 ]; then\n            backup_file  \"${check_file}\"\n            run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n          fi\n        else\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_secure     \"Single usermode requires authentication\"\n            run_lockdown   \"${lock_command}\" \"${lock_message}\" \"sudo\"\n          fi\n          if [ \"${audit_mode}\" = 2 ]; then\n            restore_file   \"${check_file}\"   \"${restore_dir}\"\n          fi\n          check_file_perms \"${check_file}\"   \"0600\" \"root\"     \"root\"\n        fi\n        check_file=\"/etc/sysconfig/init\"\n        check_file_value \"is\" \"/etc/sysconfig/init\" \"SINGLE\" \"eq\"   \"/sbin/sulogin\" \"hash\"\n        check_file_value \"is\" \"/etc/sysconfig/init\" \"PROMPT\" \"eq\"   \"no\"            \"hash\"\n        check_file_perms      \"/etc/sysconfig/init\" \"0600\"   \"root\" \"root\"\n      fi\n      check_file_value   \"is\" \"/etc/sysconfig/boot\" \"PROMPT_FOR_CONFIRM\" \"eq\" \"no\" \"hash\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/login/audit_xlogin.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_xlogin\n#\n# Refer to Section(s) 7.7   Page(s) 26 CIS FreeBSD Benchmark v1.0.5\n# Refer to Section(s) 1.3.4 Page(s) 38 CIS AIX Benchmark v1.1.0\n# Refer to Section(s) 2.1   Page(s) 15 CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 2.1.3 Page(s) 19 CIS Solaris 10 Benchmark v5.1.0\n#.\n\naudit_xlogin () {\n  print_function \"audit_xlogin\"\n  string=\"X Windows\"\n  check_message  \"${string}\"\n  temp_file=\"${temp_dir}/audit_xlogin\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"AIX\" ] || [ \"${os_name}\" = \"FreeBSD\" ] || [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${os_name}\" = \"AIX\" ]; then\n      check_message \"CDE Startup\" \"check\"\n      check_itab    \"dt\" \"off\"\n    fi\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n       check_message \"XDMCP Listening\"\n      fi\n      if [ \"${os_version}\" = \"10\" ]; then\n        check_sunos_service \"svc:/application/gdm2-login\"                  \"disabled\"\n        check_sunos_service \"svc:/application/graphical-login/cde-login\"   \"disabled\"\n      fi\n      if [ \"${os_version}\" = \"11\" ]; then\n        check_sunos_service \"svc:/application/graphical_login/gdm:default\" \"disabled\"\n      fi\n      if [ \"${os_version}\" = \"10\" ]; then\n        check_sunos_service \"dtlogin\" \"disabled\"\n      fi\n    fi\n    if [ \"${os_name}\" = \"FreeBSD\" ]; then\n      check_file=\"/etc/ttys\"\n      check_string=\"nodaemon\"\n      command=\"grep ${check_string} ${check_file} | awk '{print \\$5}'\"\n      command_message   \"${command}\"\n      ttys_test=$( eval \"${command}\" )\n      secure_string=\"X Wrapper is disabled\"\n      insecure_string=\"X Wrapper is not disabled\"\n      check_message \"${secure_string}\" \"check\"\n      if [ \"${ttys_test}\" != \"on\" ]; then\n        if [ \"${audit_mode}\" != 2 ]; then\n          if [ \"${ansible_mode}\" = 1 ]; then\n            echo \"\"\n            echo \"- name: Checking ${secure_string}\"\n            echo \"  lineinfile:\"\n            echo \"    path: ${check_file}\"\n            echo \"    regexp: '/xdm -nodaemon/s/off/on/'\"\n            echo \"  when: ansible_facts['ansible_system'] == '${os_name}'\"\n          fi\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_insecure     \"${insecure_string}\"\n          fi\n          if [ \"${audit_mode}\" = 2 ]; then\n            backup_file      \"${check_file}\"\n            lock_message=\"X wrapper to disabled\"\n            lock_command=\"sed -e '/xdm -nodaemon/s/off/on/' ${check_file} > ${temp_file} ; cat ${temp_file} > ${check_file} ; rm ${temp_file}\"\n            run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n          fi\n        else\n          restore_file \"${check_file}\" \"${restore_dir}\"\n        fi\n      else\n        if [ \"${audit_mode}\" = 1 ]; then\n          inc_secure \"${secure_string}\"\n        fi\n      fi\n    fi\n    if [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"FreeBSD\" ]; then\n      check_file=\"/etc/X11/xdm/Xresources\"\n      if [ -f \"${check_file}\" ]; then\n        check_message \"X Security Message\"\n        if [ \"${audit_mode}\" != 2 ]; then\n          command=\"grep 'private system' \\\"${check_file}\\\"\"\n          command_message \"${command}\"\n          greet_check=$( eval \"${command}\" )\n          if [ -z \"${greet_check}\" ]; then\n            check_message \"File ${check_file} for security message\"\n            greet_mesg=\"This is a private system --- Authorized use only!\"\n            lock_command=\"awk '/xlogin\\*greeting:/ { print GreetValue; next }; { print }' GreetValue=\\\"${greet_mesg}\\\" < ${check_file} > ${temp_file} ; cat ${temp_file} > ${check_file} ; rm ${temp_file}\"\n            if [ \"${audit_mode}\" = 1 ]; then\n              inc_insecure \"File ${check_file} does not have a security message\"\n              fix_message  \"${lock_command}\"\n            else\n              backup_file  \"${check_file}\"\n              lock_message=\"Security message in ${check_file}\"\n              run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n            fi\n          else\n            inc_secure \"File \\\"${check_file}\\\" has security message\"\n          fi\n        else\n          restore_file \"${check_file}\" \"${restore_dir}\"\n        fi\n      fi\n      check_file=\"/etc/X11/xdm/kdmrc\"\n      if [ -f \"${check_file}\" ]; then\n        verbose_message \"X Security Message\" \"check\"\n        if [ \"${audit_mode}\" != 2 ]; then\n          command=\"grep -c 'private system' ${check_file}\"\n          command_message \"${command}\"\n          greet_check=$( eval \"${command}\" )\n          greet_mesg=\"This is a private system --- Authorized USE only!\"\n          if [ \"${greet_check}\" != 1 ]; then\n            verbose_message \"File ${check_file} for security message\"\n            lock_message=\"cat ${check_file} |awk '/GreetString=/ { print \\\"GreetString=\\\" GreetString; next }; { print }' GreetString=\\\"${greet_mesg}\\\" > ${temp_file} ; cat ${temp_file} > ${check_file} ; rm ${temp_file}\"\n            if [ \"${audit_mode}\" = 1 ]; then\n              inc_insecure \"File ${check_file} does not have a security message\"\n              fix_message  \"${lock_command}\"\n            else\n              backup_file  \"${check_file}\"\n              lock_message=\"Security message in ${check_file}\"\n              run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n            fi\n          else\n            inc_secure \"File ${check_file} has security message\"\n          fi\n        else\n          restore_file \"${check_file}\" \"${restore_dir}\"\n        fi\n      fi\n      check_file=\"/etc/X11/xdm/Xservers\"\n      if [ -f \"${check_file}\" ]; then\n        verbose_message \"X Listening\"\n        if [ \"${audit_mode}\" != 2 ]; then\n          command=\"grep -c 'nolisten tcp' \\\"${check_file}\\\"\"\n          command_message \"${command}\"\n          greet_check=$( eval \"${command}\" )\n          if [ \"${greet_check}\" != 1 ]; then\n            verbose_message \"For X11 nolisten directive in file \\\"${check_file}\\\"\" \"check\"\n            lock_command_1=\"awk '( \\$1 !~ /^#/ && \\$3 == \\\"/usr/X11R6/bin/X\\\" ) { \\$3 = \\$3 \\\" -nolisten tcp\\\" }; { print }' < ${check_file} > ${temp_file}\"\n            lock_command_2=\"awk '( \\$1 !~ /^#/ && \\$3 == \\\"/usr/bin/X\\\" ) { \\$3 = \\$3 \\\" -nolisten tcp\\\" }; { print }' < ${check_file} > ${temp_file}\"\n            lock_command_3=\"cat ${temp_file} > ${check_file} ; rm ${temp_file}\"\n            if [ \"${audit_mode}\" = 1 ]; then\n              inc_insecure \"X11 nolisten directive not found in file \\\"${check_file}\\\"\"\n              fix_message  \"${lock_command_1}\"\n              fix_message  \"${lock_command_2}\"\n              fix_message  \"${lock_command_3}\"\n            else\n              backup_file  \"${check_file}\"\n              lock_message=\"Security message in file \\\"${check_file}\\\"\"\n              run_lockdown \"${lock_command_1}\" \"${lock_message}\" \"sudo\"\n              run_lockdown \"${lock_command_2}\" \"${lock_message}\" \"sudo\"\n              run_lockdown \"${lock_command_3}\" \"${lock_message}\" \"sudo\"\n            fi\n          else\n            inc_secure \"X11 nolisten directive found in file \\\"${check_file}\\\"\"\n          fi\n        else\n          restore_file \"${check_file}\" \"${restore_dir}\"\n        fi\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/logs/audit_debug_logging.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_debug_logging\n#\n# Connections to server should be logged so they can be audited in the event\n# of and attack.\n#.\n\naudit_debug_logging () {\n  print_function \"audit_debug_logging\"\n  string=\"Connection Logging\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ]; then\n      audit_logadm_value \"connlog\" \"daemon.debug\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/logs/audit_inetd_logging.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_inetd_logging\n#\n# Check inetd logging\n#\n# Refer to Section(s) 4.1 Page(s) 66-7 CIS Solaris 10 Benchmark v5.1.0\n#.\n\naudit_inetd_logging () {\n  print_function \"audit_inetd_logging\"\n  string=\"Logging for inetd\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    check_file_value \"is\" \"/etc/default/syslogd\"    \"LOG_FROM_REMOTE\"           \"eq\" \"NO\" \"hash\"\n    if [ \"${os_version}\" = \"10\" ]; then\n      check_command_value \"inetadm\" \"tcp_trace\"     \"TRUE\" \"tcp\"\n    fi\n    if [ \"${os_version}\" = \"9\" ]; then\n      check_file_value    \"is\" \"/etc/default/inetd\" \"ENABLE_CONNECTION_LOGGING\" \"eq\" \"YES\" \"hash\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/logs/audit_logadm_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2028\n# shellcheck disable=SC2034\n# shellcheck disable=SC2046\n# shellcheck disable=SC2154\n\n# audit_logadm_value\n#\n# Enable Debug Level Daemon Logging. Improved logging capability.\n#\n# Refer to Section(s) 4.3 Page(s) 67-8 CIS Solaris 10 Benchmark v5.1.0\n#.\n\naudit_logadm_value () {\n  print_function \"audit_logadm_value\"\n  string=\"Debug Level Daemon Logging\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ]; then\n      log_name=\"${1}\"\n      log_facility=\"${2}\"\n      check_file=\"/etc/logadm.conf\"\n      command=\"logadm -V | grep -v '^#' | grep \\\"${log_name}\\\"\"\n      command_message \"${command}\"\n      check_log=$( eval \"${command}\" )\n      log_file=\"/var/log/${log_name}\"\n      if [ -z \"$log_check\" ]; then\n        if [ \"${audit_mode}\" = 1 ]; then\n          inc_insecure \"Logging for \\\"${log_name}\\\" not enabled\"\n          fix_message  \"logadm -w ${log_name} -C 13 -a 'pkill -HUP syslogd' ${log_file}\"\n          fix_message  \"svcadm refresh svc:/system/system-log\"\n        else\n          if [ \"${audit_mode}\" = 0 ]; then\n            set_message \"Syslog to capture \\\"${log_facility}\\\"\"\n          fi\n          backup_file \"${check_file}\"\n          if [ \"${log_facility}\" != \"none\" ]; then\n            check_file=\"/etc/syslog.conf\"\n            if [ ! -f \"${work_dir}${check_file}\" ]; then\n              echo \"Saving:    File ${check_file} to ${work_dir}${check_file}\"\n              command=\"find \\\"${check_file}\\\" | cpio -pdm \\\"${work_dir}\\\" 2> /dev/null\"\n              command_message \"${command}\"\n              eval \"${command}\"\n            fi\n          fi\n          echo  \"${log_facility}\\t\\t\\t${log_file}\" >> \"${check_file}\"\n          touch \"${log_file}\"\n          chown root:root \"${log_file}\"\n          if [ \"${log_facility}\" = \"none\" ]; then\n            command=\"logadm -w \\\"${log_name}\\\" -C 13 \\\"${log_file}\\\"\"\n            command_message \"${command}\"\n            eval \"${command}\"\n          else\n            command=\"logadm -w \\\"${log_name}\\\" -C 13 -a 'pkill -HUP syslogd' \\\"${log_file}\\\"\"\n            command_message \"${command}\"\n            eval \"${command}\"\n            svcadm refresh svc:/system/system-log\n          fi\n        fi\n        if [ \"${audit_mode}\" = 2 ]; then\n          if [ -f \"${restore_dir}/${check_file}\" ]; then\n            cp -p \"${restore_dir}/${check_file}\" \"${check_file}\"\n            if [ \"${os_version}\" != \"11\" ]; then\n              command=\"pkgchk -f -n -p ${check_file} 2> /dev/null\"\n              command_message \"${command}\"\n              eval \"${command}\"\n            else\n              command=\"pkg fix \\$( pkg search ${check_file} | grep pkg | awk '{print \\$4}' )\"\n              command_message \"${command}\"\n              eval \"${command}\"\n            fi\n          fi\n          if [ \"${log_facility}\" = \"none\" ]; then\n            check_file=\"/etc/syslog.conf\"\n            if [ -f \"${restore_dir}/${check_file}\" ]; then\n              cp -p \"${restore_dir}/${check_file}\" \"${check_file}\"\n              if [ \"${os_version}\" != \"11\" ]; then\n                command=\"pkgchk -f -n -p \\\"${check_file}\\\" 2> /dev/null\"\n                command_message \"${command}\"\n                eval \"${command}\"\n              else\n                command=\"pkg fix \\$( pkg search \\\"${check_file}\\\" | grep pkg | awk '{print \\$4}' )\"\n                command_message \"${command}\"\n                eval \"${command}\"\n              fi\n            fi\n            svcadm refresh svc:/system/system-log\n          fi\n        fi\n      else\n        if [ \"${audit_mode}\" = 1 ]; then\n          inc_secure \"Logging for \\\"${log_name}\\\" already enabled\"\n        fi\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/logs/audit_logrotate.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2046\n# shellcheck disable=SC2154\n\n# audit_logrotate\n#\n# Check logrotate\n#\n# Refer to Section(s) 4.3     Page(s) 97    CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 5.3     Page(s) 120-1 CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 4.3     Page(s) 208   CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 8.4     Page(s) 113-4 CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 4.3     Page(s) 191   CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 6.1.3.8 Page(s) 787-8 CIS Ubuntu LTS 24.04 Benchmark v1.0.0\n#.\n\naudit_logrotate () {\n  print_function \"audit_logrotate\"\n  string=\"Log Rotate Configuration\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    for check_file in /etc/logrotate.d/syslog /etc/logrotate.d/rsyslog; do\n      if [ -f \"${check_file}\" ]; then\n        if [ \"${audit_mode}\" != 2 ]; then\n          if [ \"${os_vendor}\" = \"SuSE\" ]; then\n            search_string=\"/var/log/warn /var/log/messages /var/log/allmessages /var/log/localmessages /var/log/firewall /var/log/acpid /var/log/NetworkManager /var/log/mail /var/log/mail.info /var/log/mail.warn /var/log/mail.err /var/log/news/news.crit /var/log/news/news.err /var/log/news/news.notice\"\n          else\n            search_string=\"/var/log/messages /var/log/secure /var/log/maillog /var/log/spooler /var/log/boot.log /var/log/cron\"\n          fi\n          command=\"grep \\\"${search_string}\\\" \\\"${check_file}\\\" | sed 's/ {//g'\"\n          command_message     \"${command}\"\n          check_value=$( eval \"${command}\" )\n          if [ \"${check_value}\" != \"${search_string}\" ]; then\n            if [ \"${audit_mode}\" = 1 ]; then\n              inc_insecure \"Log rotate is not configured for ${search_string}\"\n              fix_message  \"cat ${check_file} |sed 's,.*{,${search_string} {,' > ${temp_file}\"\n              fix_message  \"cat ${temp_file} > ${check_file}\"\n              fix_message  \"rm ${temp_file}\"\n            fi\n            if [ \"${audit_mode}\" = 0 ]; then\n              backup_file \"${check_file}\"\n              echo  \"Removing:  Configuring logrotate\"\n              command=\"sed \\\"s,.*{,${search_string} {,\\\" \\\"${check_file}\\\" > \\\"${temp_file}\\\"\"\n              command_message \"${command}\"\n              eval \"${command}\"\n              command=\"cat \\\"${temp_file}\\\" > \\\"${check_file}\\\"\"\n              command_message \"${command}\"\n              eval \"${command}\"\n              if [ -f \"${temp_file}\" ]; then\n                rm \"${temp_file}\"\n              fi\n            fi\n          else\n            if [ \"${audit_mode}\" = 1 ]; then\n              inc_secure \"Log rotate is configured\"\n            fi\n          fi\n        else\n          restore_file \"${check_file}\" \"${restore_dir}\"\n        fi\n      fi\n    done\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/mail/audit_email_daemons.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_email_daemons\n#\n# Check email daemons\n#\n# Refer to Section(s) 3.12    Page(s) 67    CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 2.2.11  Page(s) 111   CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 3.12    Page(s) 79-80 CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 6.11    Page(s) 60    CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 2.2.11  Page(s) 111   CIS Ubuntu 16.04 Benchmark v1.0.0\n# Refer to Section(s) 2.1.8   Page(s) 247-9 CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_email_daemons () {\n  print_function \"audit_email_daemons\"\n  string=\"Mail Daemons\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    for service_name in cyrus imapd qpopper dovecot; do\n      check_linux_service \"${service_name}\" \"off\"\n      check_linux_package \"uninstall\"       \"${service_name}\"\n    done\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/mail/audit_exim.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_exim\n#\n# Check exim\n#\n# Refer to Section(s) 1.5.1 Page(s) 88-9 CIS Ubuntu 22.04 Benchmark v1.0.0\n#.\n\naudit_exim () {\n  print_function \"audit_exim\"\n  string=\"Exim\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    check_file=\"/etc/exim4/update-exim4.conf\"\n    if [ -f \"${check_file}\" ]; then\n      check_file_value  \"is\" \"${check_file}\" \"dc_eximconfig_configtype\" \"eq\" \"'local'\"           \"hash\"\n      check_file_value  \"is\" \"${check_file}\" \"dc_local_interfaces\"      \"eq\" \"'127.0.0.1 ; ::1'\" \"hash\"\n      check_file_value  \"is\" \"${check_file}\" \"dc_readhost\"              \"eq\" \"''\"                \"hash\"\n      check_file_value  \"is\" \"${check_file}\" \"dc_relay_domains\"         \"eq\" \"''\"                \"hash\"\n      check_file_value  \"is\" \"${check_file}\" \"dc_minimaldns\"            \"eq\" \"'false'\"           \"hash\"\n      check_file_value  \"is\" \"${check_file}\" \"dc_relay_nets\"            \"eq\" \"''\"                \"hash\"\n      check_file_value  \"is\" \"${check_file}\" \"dc_smarthost\"             \"eq\" \"''\"                \"hash\"\n      check_file_value  \"is\" \"${check_file}\" \"dc_use_split_config\"      \"eq\" \"'false'\"           \"hash\"\n      check_file_value  \"is\" \"${check_file}\" \"dc_hide_mailname\"         \"eq\" \"''\"                \"hash\"\n      check_file_value  \"is\" \"${check_file}\" \"dc_mailname_in_oh\"        \"eq\" \"'true'\"            \"hash\"\n      check_file_value  \"is\" \"${check_file}\" \"dc_localdelivery\"         \"eq\" \"'mail_spool'\"      \"hash\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}"
  },
  {
    "path": "modules/mail/audit_postfix_daemon.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_postfix_daemon\n#\n# Refer to Section(s) 3.16   Page(s) 69-70 CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 2.2.15 Page(s) 115-6 CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 2.2.15 Page(s) 107-8 CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 2.2.15 Page(s) 115-6 CIS Ubuntu 16.04 Benchmark v1.0.0\n# Refer to Section(s) 2.1.21 Page(s) 285-7 CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_postfix_daemon () {\n  print_function \"audit_postfix_daemon\"\n  string=\"Postfix Daemon\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${os_vendor}\" = \"SuSE\" ]; then\n      check_file_value  \"is\" \"/etc/sysconfig/mail\"  \"SMTPD_LISTEN_REMOTE\" \"eq\" \"no\" \"hash\"\n    fi\n    if [ \"${os_vendor}\" = \"Ubuntu\" ] && [ \"${os_version}\" -ge 24 ]; then\n      check_file_value  \"is\" \"/etc/postfix/main.cf\" \"inet_interfaces\"     \"eq\" \"loopbank-only\" \"hash\"\n    else\n      check_file_value  \"is\" \"/etc/postfix/main.cf\" \"inet_interfaces\"     \"eq\" \"localhost\"     \"hash\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/mail/audit_sendmail_aliases.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_sendmail_aliases\n#\n# Make sure sendmail aliases are configured appropriately.\n# Remove decode/uudecode alias\n#.\n\naudit_sendmail_aliases () {\n  print_function \"audit_sendmail_aliases\"\n  string=\"Sendmail Aliases\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ]; then\n    disable_value    \"/etc/aliases\" \"decode\" \"hash\"\n    check_file_perms \"/etc/aliases\" \"0644\"   \"root\" \"root\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/mail/audit_sendmail_daemon.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_sendmail_daemon\n#\n# Check sendmail daemon settings \n#\n# Refer to Section(s) 3.16  Page(s) 82    CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 3.16  Page(s) 72-3  CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 3.5   Page(s) 10    CIS FreeBSD Benchmark v1.0.5\n# Refer to Section(s) 6.15  Page(s) 62-3  CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 1.3.6 Page(s) 40-1  CIS AIX Benchmark v1.1.0\n# Refer to Section(s) 2.2   Page(s) 15-6  CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 2.1.4 Page(s) 19-20 CIS Solaris 10 Benchmark v5.1.0\n#.\n\naudit_sendmail_daemon() {\n  print_function \"audit_sendmail_daemon\"\n  string=\"Sendmail Daemon\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"FreeBSD\" ] || [ \"${os_name}\" = \"AIX\" ]; then\n    if [ \"$sendmail_disable\" = \"yes\" ]; then\n      if [ \"${os_name}\" = \"AIX\" ]; then\n        check_rctcp \"sendmail\" \"off\"\n      fi\n      if [ \"${os_name}\" = \"SunOS\" ]; then\n        if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n          check_sunos_service \"svc:/network/smtp:sendmail\" \"disabled\"\n        fi\n        if [ \"${os_version}\" = \"10\" ]; then\n          check_sunos_service \"sendmail\" \"disabled\"\n        fi\n        if [ \"${os_version}\" = \"9\" ] || [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n          check_file_value  \"is\" \"/etc/default/sendmail\" \"QUEUEINTERVAL\" \"eq\" \"15m\" \"hash\"\n          check_append_file      \"/etc/default/sendmail\" \"MODE=\" \"hash\"\n        else\n          check_initd_service \"sendmail\" \"disable\"\n          check_file=\"/var/spool/cron/crontabs/root\"\n          check_string=\"0 * * * * /usr/lib/sendmail -q\"\n          check_append_file \"${check_file}\" \"${check_string}\" \"hash\"\n        fi\n      fi\n      if [ \"${os_name}\" = \"Linux\" ]; then\n        check_linux_service \"sendmail\" \"off\"\n        check_file_value    \"is\" \"/etc/sysconfig/sendmail\" \"DAEMON\" \"eq\" \"no\" \"hash\"\n        check_file_value    \"is\" \"/etc/sysconfig/sendmail\" \"QUEUE\"  \"eq\" \"1h\" \"hash\"\n      fi\n      if [ \"${os_name}\" = \"FreeBSD\" ]; then\n        check_file=\"/etc/rc.conf\"\n        if [ \"${os_version}\" -lt 5 ]; then\n          check_file_value  \"is\" \"/etc/rc.conf\" \"sendmail_enable\" \"eq\" \"NONE\" \"hash\"\n        else\n          if [ \"${os_version}\" -gt 5 ]; then\n            if [ \"${os_version}\" = \"5\" ] && [ \"${os_update}\" = \"0\" ]; then\n              check_file_value \"is\" \"/etc/rc.conf\" \"sendmail_enable\"           \"eq\" \"NONE\" \"hash\"\n            else\n              check_file_value \"is\" \"/etc/rc.conf\" \"sendmail_enable\"           \"eq\" \"NO\"   \"hash\"\n              check_file_value \"is\" \"/etc/rc.conf\" \"sendmail_submit_enable\"    \"eq\" \"NO\"   \"hash\"\n              check_file_value \"is\" \"/etc/rc.conf\" \"sendmail_outbound_enable\"  \"eq\" \"NO\"   \"hash\"\n              check_file_value \"is\" \"/etc/rc.conf\" \"sendmail_msp_queue_enable\" \"eq\" \"NO\"   \"hash\"\n            fi\n          fi\n        fi\n      fi\n    fi\n    if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"FreeBSD\" ]; then\n      check_file=\"/etc/mail/sendmail.cf\"\n      if [ -f \"${check_file}\" ]; then\n        verbose_message \"Sendmail Configuration\"\n        search_string=\"Addr=127.0.0.1\"\n        if [ \"${audit_mode}\" != 2 ]; then\n         verbose_message \"Mail transfer agent is running in local-only mode\"\n         command=\"grep -v '^#' \\\"${check_file}\\\" | grep \\\"O DaemonPortOptions\\\" | awk '{print \\$3}' | grep \\\"${search_string}\\\"\"\n         command_message     \"${command}\"\n         check_value=$( eval \"${command}\" )\n          if [ \"${check_value}\" = \"${search_string}\" ]; then\n            if [ \"${audit_mode}\" = \"1\" ]; then\n              inc_insecure \"Mail transfer agent is not running in local-only mode\"\n              fix_message  \"cp ${check_file} ${temp_file}\"\n              fix_message  \"cat ${temp_file} |awk 'O DaemonPortOptions=/ { print \\\"O DaemonPortOptions=Port=smtp, Addr=127.0.0.1, ansible_value=MTA\\\"; next} { print }' > ${check_file}\"\n              fix_message  \"rm ${temp_file}\"\n            fi\n            if [ \"${audit_mode}\" = 0 ]; then\n              backup_file  \"${check_file}\"\n              set_message  \"Mail transfer agent to run in local-only mode\"\n              command=\"cp \\\"${check_file}\\\" \\\"${temp_file}\\\"\"\n              command_message \"${command}\"\n              eval \"${command}\"\n              command=\"awk 'O DaemonPortOptions=/ { print \\\"O DaemonPortOptions=Port=smtp, Addr=127.0.0.1, ansible_value=MTA\\\"; next} { print }' < \\\"${temp_file}\\\" > \\\"${check_file}\\\"\"\n              command_message \"${command}\"\n              eval \"${command}\"\n              if [ -f \"${temp_file}\" ]; then\n                rm \"${temp_file}\"\n              fi\n            fi\n          else\n            if [ \"${audit_mode}\" = \"1\" ]; then\n              inc_secure \"Mail transfer agent is running in local-only mode\"\n            fi\n          fi\n        else\n          restore_file \"${check_file}\" \"${restore_dir}\"\n        fi\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/mail/audit_sendmail_greeting.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_sendmail_greeting\n#\n# Check sendmail greeting\n#.\n\naudit_sendmail_greeting () {\n  print_function \"audit_sendmail_greeting\"\n  string=\"Sendmail Greeting\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ]; then\n    check_file=\"/etc/mail/sendmail.cf\"\n    if [ -f \"${check_file}\" ]; then\n      search_string=\"v/\"\n      if [ \"${audit_mode}\" != 2 ]; then\n        command=\"grep -v \\\"^#\\\" \\\"${check_file}\\\" | grep \\\"O SmtpGreetingMessage\\\" | awk '{print \\$4}' | grep \\\"${search_string}\\\"\"\n        command_message     \"${command}\"\n        check_value=$( eval \"${command}\" )\n        if [ \"${check_value}\" = \"${search_string}\" ]; then\n          if [ \"${audit_mode}\" = \"1\" ]; then\n            inc_insecure \"Found version information in sendmail greeting\"\n            fix_message  \"cp ${check_file} ${temp_file}\"\n            fix_message  \"awk '/O SmtpGreetingMessage=/ { print \\\"O SmtpGreetingMessage=Mail Server Ready; \\$b\\\"; next} { print }' < ${temp_file} > ${check_file}\"\n            fix_message  \"rm ${temp_file}\"\n          fi\n          if [ \"${audit_mode}\" = 0 ]; then\n            backup_file \"${check_file}\"\n            set_message \"Sendmail greeting to have no version information\"\n            command=\"cp \\\"${check_file}\\\" \\\"${temp_file}\\\"\"\n            command_message \"${command}\"\n            eval \"${command}\"\n            command=\"awk '/O SmtpGreetingMessage=/ { print \\\"O SmtpGreetingMessage=Mail Server Ready; \\$b\\\"; next} { print }' < \\\"${temp_file}\\\" > \\\"${check_file}\\\"\"\n            command_message \"${command}\"\n            eval \"${command}\"\n            if [ -f \"${temp_file}\" ]; then\n              rm \"${temp_file}\"\n            fi\n          fi\n        else\n          if [ \"${audit_mode}\" = \"1\" ]; then\n            inc_secure \"No version information in sendmail greeting\"\n          fi\n        fi\n      else\n        restore_file \"${check_file}\" \"${restore_dir}\"\n      fi\n      disable_value \"${check_file}\" \"O HelpFile\" \"hash\"\n      if [ \"${audit_mode}\" != 2 ]; then\n        check_value=$( grep -v '^#' \"${check_file}\" | grep \"${search_string}\" )\n        if [ \"${check_value}\" = \"${search_string}\" ]; then\n          if [ \"${audit_mode}\" = \"1\" ]; then\n            inc_insecure \"Found help information in sendmail greeting\"\n          fi\n          if [ \"${audit_mode}\" = 0 ]; then\n            backup_file \"${check_file}\"\n            set_message \"Sendmail to have no help information\"\n            command=\"cp \\\"${check_file}\\\" \\\"${temp_file}\\\"\"\n            command_message  \"${command}\"\n            eval \"${command}\"\n            command=\"sed 's/^O HelpFile=/#O HelpFile=/' < \\\"${temp_file}\\\" > \\\"${check_file}\\\"\"\n            command_message  \"${command}\"\n            eval \"${command}\"\n            if [ -f \"${temp_file}\" ]; then\n              rm \"${temp_file}\"\n            fi\n          fi\n        else\n          if [ \"${audit_mode}\" = \"1\" ]; then\n            inc_secure \"No help information in sendmail greeting\"\n          fi\n        fi\n      else\n        restore_file   \"${check_file}\" \"${restore_dir}\"\n      fi\n      check_file_perms \"${check_file}\" \"0444\" \"root\" \"root\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/mounts/audit_mount_fdi.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2129\n# shellcheck disable=SC2154\n\n# audit_mount_fdi\n#\n# User mountable file systems on Linux.\n#\n# This can stop possible vectors of attack and escalated privileges.\n#.\n\naudit_mount_fdi () {\n  print_function \"audit_mount_fdi\"\n  string=\"User Mountable Filesystems\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    check_dir=\"/usr/share/hal/fdi/95userpolicy\"\n    if [ -e \"${check_dir}\" ]; then\n      check_file=\"${check_dir}/floppycdrom.fdi\"\n    else\n      check_dir=\"/usr/share/hal/fdi/policy/20thirdparty\"\n      check_file=\"${check_dir}/floppycdrom.fdi\"\n    fi\n    if [ -d \"${check_dir}\" ]; then\n      if [ ! -f \"${check_file}\" ]; then\n        touch \"${check_file}\"\n        chmod 640 \"${check_file}\"\n        chown root:root \"${check_file}\"\n      fi\n    fi\n    if [ -f \"${check_file}\" ]; then\n      if [ \"${audit_mode}\" != \"2\" ]; then\n        command=\"grep -v \\\"Default policies\\\" \\\"${check_file}\\\" | head -1 | wc -l | sed \\\"s/ //g\\\"\"\n        command_message   \"${command}\"\n        fdi_check=$( eval \"${command}\" )\n        if [ \"$fdi_check\" = 1 ]; then\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_insecure \"User mountable filesystems enabled\"\n            fix_message  \"echo '<?xml version=\\\"1.0\\\" encoding=\\\"ISO-8859-1\\\"?> <!-- -*- SGML -*- --> >' > ${temp_file}\"\n            fix_message  \"echo '<deviceinfo version=\\\"0.2\\\">' >> ${temp_file}\"\n            fix_message  \"echo '  <!-- Default policies merged onto computer root object -->' >> ${temp_file}\"\n            fix_message  \"echo '  <device>' >> ${temp_file}\"\n            fix_message  \"echo '    <match key=\\\"info.udi\\\" string=\\\"/org/freedesktop/Hal/devices/computer\\\">' >> ${temp_file}\"\n            fix_message  \"echo '      <merge key=\\\"storage.policy.default.mount_option.nodev\\\" type=\\\"bool\\\">true</merge>' >> ${temp_file}\"\n            fix_message  \"echo '      <merge key=\\\"storage.policy.default.mount_option.nosuid\\\" type=\\\"bool\\\">true</merge>' >> ${temp_file}\"\n            fix_message  \"echo '    </match>' >> ${temp_file}\"\n            fix_message  \"echo '  </device>' >> ${temp_file}\"\n            fix_message  \"echo '</deviceinfo>' >> ${temp_file}\"\n            fix_message  \"cat ${temp_file} > ${check_file}\"\n            fix_message  \"rm ${temp_file}\" \"fix\"\n          fi\n          if [ \"${audit_mode}\" = 0 ]; then\n            verbose_message \"Disabling user mountable filesystems\" \"set\"\n            backup_file     \"${check_file}\"\n            echo '<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?> <!-- -*- SGML -*- --> >' > \"${temp_file}\"\n            echo '<deviceinfo version=\"0.2\">' >> \"${temp_file}\"\n            echo '  <!-- Default policies merged onto computer root object -->' >> \"${temp_file}\"\n            echo '  <device>' >> \"${temp_file}\"\n            echo '    <match key=\"info.udi\" string=\"/org/freedesktop/Hal/devices/computer\">' >> \"${temp_file}\"\n            echo '      <merge key=\"storage.policy.default.mount_option.nodev\" type=\"bool\">true</merge>' >> \"${temp_file}\"\n            echo '      <merge key=\"storage.policy.default.mount_option.nosuid\" type=\"bool\">true</merge>' >> \"${temp_file}\"\n            echo '    </match>' >> \"${temp_file}\"\n            echo '  </device>' >> \"${temp_file}\"\n            echo '</deviceinfo>' >> \"${temp_file}\"\n            cat \"${temp_file}\" > \"${check_file}\"\n            if [ -f \"${temp_file}\" ]; then\n              rm \"${temp_file}\"\n            fi\n          fi\n        else\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_secure \"User mountable filesystems disabled\"\n          fi\n          if [ \"${audit_mode}\" = 2 ]; then\n            restore_file \"${check_file}\" \"${restore_dir}\"\n          fi\n        fi\n      fi\n    fi\n    check_file_perms \"${check_file}\" \"0640\" \"root\" \"root\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/mounts/audit_mount_nodev.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_mount_nodev\n#\n# Check nodev on mounts\n#\n# Refer to Section(s) 1.1.2,4,10,11,14,16 Page(s) 15-25         CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 1.1.2,4,10,11,14,16 Page(s) 16-26         CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 1.1.2,4,10,11,14,16 Page(s) 16-26         CIS RHEL 6 Benchmark v1.0.0\n# Refer to Section(s) 1.1.3,8,14,15,18    Page(s) 33,39,40,43   CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 1.1.3,8,14,15,18    Page(s) 27,31,37-8,41 CIS Ubuntu LTS 16.04 Benchmark v1.0.0\n# Refer to Section(s) 1.1.2.[1-7].2       Page(s) 80-1,89-90,\n#                                                 99-100,107-8\n#                                                 123-4,132-3   CIS Ubuntu LTS 24.04 Benchmark v1.0.0\n# Refer to Section(s) 2.2,4,10,11,14,16   Page(s) 15-25         CIS SLES 11 Benchmark v1.2.0\n# Refer to Section(s) 1.1.8,14,17         Page(s) 32,38-9       CIS Amazon Linux Benchmark v2.0.0\n#.\n\naudit_mount_nodev () {\n  print_function \"audit_mount_nodev\"\n  string=\"File Systems mounted with nodev\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    check_file=\"/etc/fstab\"\n    if [ -e \"${check_file}\" ]; then\n      if [ \"${audit_mode}\" != \"2\" ]; then\n        command=\"grep -v \\\"^#\\\" \\\"${check_file}\\\" | grep -E \\\"ext2|ext3|swap|tmpfs\\\" | grep -v '/ ' | grep -cv '/boot' | sed \\\"s/ //g\\\"\"\n        command_message     \"${command}\"\n        nodev_check=$( eval \"${command}\" )\n        if [ \"$nodev_check\" = 1 ]; then\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_insecure \"Found filesystems that should be mounted nodev\"\n            fix_message  \"cat ${check_file} | awk '( \\$3 ~ /^ext[2,3,4]|tmpfs$/ && \\$2 != \\\"/\\\" ) { \\$4 = \\$4 \\\",nodev\\\" }; { printf \\\"%-26s %-22s %-8s %-16s %-1s %-1s\\\\\\n\\\",\\$1,\\$2,\\$3,\\$4,\\$5,\\$6 }' > \\\"${temp_file}\\\"\"\n            fix_message  \"cat \\\"${temp_file}\\\" > \\\"${check_file}\\\"\"\n            fix_message  \"rm \\\"${temp_file}\\\"\"\n          fi\n          if [ \"${audit_mode}\" = 0 ]; then\n            set_message  \"Setting nodev on filesystems\"\n            backup_file  \"${check_file}\"\n            command=\"awk '( \\$3 ~ /^ext[2,3,4]|tmpf$/ && \\$2 != \\\"/\\\" ) { \\$4 = \\$4 \\\",nodev\\\" }; { printf \\\"%-26s %-22s %-8s %-16s %-1s %-1s\\\\\\n\\\",\\$1,\\$2,\\$3,\\$4,\\$5,\\$6 }' < \\\"${check_file}\\\" > \\\"${temp_file}\\\"\"\n            command_message \"${command}\"\n            eval \"${command}\"\n            command=\"cat \\\"${temp_file}\\\" > \\\"${check_file}\\\"\"\n            command_message \"${command}\"\n            eval \"${command}\"\n            if [ -f \"${temp_file}\" ]; then\n              rm \"${temp_file}\"\n            fi\n          fi\n        else\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_secure   \"No filesystem that should be mounted with nodev\"\n          fi\n          if [ \"${audit_mode}\" = 2 ]; then\n            restore_file \"${check_file}\" \"${restore_dir}\"\n          fi\n        fi\n      fi\n      check_file_perms \"${check_file}\" \"0644\" \"root\" \"root\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/mounts/audit_mount_noexec.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_mount_noexec\n#\n# Check No-exec on mounts\n#\n# Refer to Section(s) 1.1.4         Page(s) 14-5        CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 1.1.4         Page(s) 17-8        CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 1.1.10,17,20  Page(s) 35,42,45    CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 2.4           Page(s) 16-7        CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 1.1.2.[1-7].4 Page(s) 84-5,93-4,\n#                                           118-9,127-8\n#                                           136-7       CIS Ubuntu LTS 24.04 Benchmark v1.0.0\n# Refer to Section(s) 1.1.3,5,10,17 Page(s) 27,29,34,41 CIS Amazon Linux Benchmark v2.0.0\n#.\n\naudit_mount_noexec () {\n  print_function \"audit_mount_noexec\"\n  string=\"No-exec on /tmp\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    check_file=\"/etc/fstab\"\n    if [ -e \"${check_file}\" ]; then\n      verbose_message \"Temp File Systems mounted with noexec\" \"check\"\n      if [ \"${audit_mode}\" != \"2\" ]; then\n        command=\"grep -v \\\"^#\\\" \\\"${check_file}\\\" | grep \\\"tmpfs\\\" | grep -v noexec | head -1 | wc -l | sed \\\"s/ //g\\\"\"\n        command_message     \"${command}\"\n        nodev_check=$( eval \"${command}\" )\n        if [ \"${nodev_check}\" = 1 ]; then\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_insecure \"Found tmpfs filesystems that should be mounted noexec\"\n            fix_message  \"cat ${check_file} | awk '( \\$3 ~ /^tmpfs$/ ) { \\$4 = \\$4 \\\",noexec\\\" }; { printf \\\"%-26s %-22s %-8s %-16s %-1s %-1s\\n\\\",\\$1,\\$2,\\$3,\\$4,\\$5,\\$6 }' > ${temp_file}\"\n            fix_message  \"cat ${temp_file} > ${check_file}\"\n            fix_message  \"rm ${temp_file}\"\n          fi\n          if [ \"${audit_mode}\" = 0 ]; then\n            set_message  \"Setting noexec on tmpfs\"\n            backup_file  \"${check_file}\"\n            command=\"awk '( \\$3 ~ /^tmpfs$/ ) { \\$4 = \\$4 \\\",noexec\\\" }; { printf \\\"%-26s %-22s %-8s %-16s %-1s %-1s\\\\n\\\",\\$1,\\$2,\\$3,\\$4,\\$5,\\$6 }' < \\\"${check_file}\\\" > \\\"${temp_file}\\\"\"\n            command_message \"${command}\"\n            eval \"${command}\"\n            command=\"cat \\\"${temp_file}\\\" > \\\"${check_file}\\\"\"\n            command_message \"${command}\"\n            eval \"${command}\"\n            if [ -f \"${temp_file}\" ]; then\n              rm \"${temp_file}\"\n            fi\n          fi\n        else\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_secure   \"No filesystem that should be mounted with noexec\"\n          fi\n          if [ \"${audit_mode}\" = 2 ]; then\n            restore_file \"${check_file}\" \"${restore_dir}\"\n          fi\n        fi\n      fi\n      check_file_perms \"${check_file}\" \"0644\" \"root\" \"root\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/mounts/audit_mount_setuid.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_mount_setuid\n#\n# Check Set-UID on mounts\n#\n# Refer to Section(s) 1.1.3,13,15   Page(s) 14-25               CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 1.1.3,13,15   Page(s) 17-27               CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 1.1.4,9,16,19 Page(s) 29,34,41,44         CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 1.1.4,9,16,19 Page(s) 28,33,40,43         CIS Ubuntu LTS 16.04 Benchmark v1.0.0\n# Refer to Section(s) 1.1.2.[1-7].3 Page(s) 82-3,91-2,101-2,\n#                                           109-10,116-7,125-6\n#                                           134-5               CIS Ubuntu LTS 24.04 Benchmark v1.0.0\n# Refer to Section(s) 2.3,13,15     Page(s) 16-25               CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 6.1           Page(s) 21                  CIS FreeBSD Benchmark v1.0.5\n# Refer to Section(s) 5.2           Page(s) 76-7                CIS Solaris 10 Benchmark v5.1.0\n# Refer to Section(s) 1.1.4,9,16    Page(s) 28,33,40            CIS Amazon Linux Benchmark v2.0.0\n#.\n\naudit_mount_setuid () {\n  print_function \"audit_mount_setuid\"\n  string=\"Set-UID on Mounted Devices\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"FreeBSD\" ]; then\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      if [ \"${os_version}\" = \"10\" ]; then\n        check_file=\"/etc/rmmount.conf\"\n        if [ -f \"${check_file}\" ]; then\n          command=\"grep -v \\\"^#\\\" \\\"${check_file}\\\" | grep \\\"\\\\-o nosuid\\\"\"\n          command_message \"${command}\"\n          nosuid_check=$( eval \"${command}\" )\n          log_file=\"${work_dir}/${check_file}\"\n          if [ -n \"$nosuid_check\" ]; then\n            if [ \"${audit_mode}\" = 1 ]; then\n              inc_insecure      \"Set-UID not restricted on user mounted devices\"\n            fi\n            if [ \"${audit_mode}\" = 0 ]; then\n              check_message     \"Set-UID restricted on user mounted devices\"\n              backup_file       \"${check_file}\"\n              check_append_file \"${check_file}\" \"mount * hsfs udfs ufs -o nosuid\" \"hash\"\n            fi\n          else\n            if [ \"${audit_mode}\" = 1 ]; then\n              inc_secure \"Set-UID not restricted on user mounted devices\"\n            fi\n            if [ \"${audit_mode}\" = 2 ]; then\n              restore_file \"${check_file}\" \"${restore_dir}\"\n            fi\n          fi\n        fi\n      fi\n    fi\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      check_file=\"/etc/fstab\"\n      if [ -e \"${check_file}\" ]; then\n        verbose_message \"File Systems mounted with nodev\" \"check\"\n        if [ \"${audit_mode}\" != \"2\" ]; then\n          command=\"grep -v \\\"^#\\\" \\\"${check_file}\\\" | grep -E \\\"ext2|ext3|ext4|swap|tmpfs\\\" | grep -v '/ ' | grep -cv '/boot' | sed \\\"s/ //g\\\"\"\n          command_message \"${command}\"\n          nodev_check=$( eval \"${command}\" )\n          if [ ! \"$nodev_check\" = \"0\" ]; then\n            if [ \"${audit_mode}\" = 1 ]; then\n              inc_insecure    \"Found filesystems that should be mounted nodev\"\n              verbose_message \"cat ${check_file} | awk '( \\$3 ~ /^ext[2,3,4]|tmpfs$/ && \\$2 != \\\"/\\\" ) { \\$4 = \\$4 \\\",nosuid\\\" }; { printf \\\"%-26s %-22s %-8s %-16s %-1s %-1s\\\\n\\\",\\$1,\\$2,\\$3,\\$4,\\$5,\\$6 }' > ${temp_file}\" \"fix\"\n              verbose_message \"cat ${temp_file} > ${check_file}\" \"fix\"\n              verbose_message \"rm ${temp_file}\" \"fix\"\n            fi\n            if [ \"${audit_mode}\" = 0 ]; then\n              verbose_message \"Setting nodev on filesystems\" \"set\"\n              backup_file     \"${check_file}\"\n              command=\"awk '( \\$3 ~ /^ext[2,3,4]|tmpfs$/ && \\$2 != \\\"/\\\" ) { \\$4 = \\$4 \\\",nosuid\\\" }; { printf \\\"%-26s %-22s %-8s %-16s %-1s %-1s\\\\n\\\",\\$1,\\$2,\\$3,\\$4,\\$5,\\$6 }' < \\\"${check_file}\\\" > \\\"${temp_file}\\\"\"\n              command_message \"${command}\"\n              eval \"${command}\"\n              command=\"cat \\\"${temp_file}\\\" > \\\"${check_file}\\\"\"\n              command_message \"${command}\"\n              eval \"${command}\"\n              if [ -f \"${temp_file}\" ]; then\n                rm \"${temp_file}\"\n              fi\n            fi\n          else\n            if [ \"${audit_mode}\" = 1 ]; then\n              inc_secure \"No filesystem that should be mounted with nodev\"\n            fi\n            if [ \"${audit_mode}\" = 2 ]; then\n              restore_file \"${check_file}\" \"${restore_dir}\"\n            fi\n          fi\n        fi\n        check_file_perms \"${check_file}\" \"0644\" \"root\" \"root\"\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/nis/audit_crypt_policy.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_crypt_policy\n#\n# Set default cryptographic algorithms\n#.\n\naudit_crypt_policy () {\n  print_function \"audit_crypt_policy\"\n  string=\"Cryptographic Algorithms\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    check_file_value  \"is\" \"/etc/security/policy.conf\" \"CRYPT_DEFAULT\"          \"eq\" \"6\" \"hash\"\n    check_file_value  \"is\" \"/etc/security/policy.conf\" \"CRYPT_ALGORITHMS_ALLOW\" \"eq\" \"6\" \"hash\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/nis/audit_disk_encryption.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_disk_encryption\n#\n# Check Disk Encryption is enabled\n#\n# Refer to Section(s) 2.6.1 Page(s) 54 CIS Apple OS X 10.12 Benchmark v1.0.0\n#.\n\naudit_disk_encryption () {\n  print_function \"audit_disk_encryption\"\n  string=\"Disk Encryption\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${audit_mode}\" != 2 ]; then\n      disk_check=$( diskutil cs list | grep -i encryption | grep AES-XTS )\n      if [ \"${disk_check}\" ]; then\n        inc_secure   \"Disk encryption is enabled\"\n      else\n        inc_insecure \"Disk encryption is not enabled\"\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/nis/audit_encryption_kit.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_encryption_kit\n#\n# Check Encryption Kit\n#\n# Refer to Section(s) 1.3 Page(s) 15-6 CIS Solaris 10 Benchmark v5.1.0\n#.\n\naudit_encryption_kit () {\n  print_function \"audit_encryption_kit\"\n  string=\"Encryption Toolkit\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ]; then\n      check_solaris_package   \"SUNWcry\"\n      check_solaris_package   \"SUNWcryr\"\n      if [ \"${os_update}\" -le 4 ]; then\n        check_solaris_package \"SUNWcryman\"\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/nis/audit_nis_client.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_nis_client\n#\n# Check NIS client\n#\n# Refer to Section(s) 2.5   Page(s) 18      CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 2.2.3 Page(s) 24-5    CIS Solaris 10 Benchmrk v5.1.0\n# Refer to Section(s) 2.1.5 Page(s) 58      CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 2.1.5 Page(s) 53      CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 2.3.1 Page(s) 123     CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 5.1.2 Page(s) 41      CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 2.3.1 Page(s) 110-1   CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 2.3.1 Page(s) 119-20  CIS Ubuntu 16.04 Benchmark v2.0.0\n# Refer to Section(s) 2.2.1 Page(s) 292-3   CIS Ubuntu 16.04 Benchmark v2.0.0\n#.\n\naudit_nis_client () {\n  print_function \"audit_nis_client\"\n  string=\"NIS Client Daemons\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n        check_sunos_service \"svc:/network/nis/client\" \"disabled\"\n      fi\n    fi\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      for service_name in ypbind nis; do\n        check_linux_service \"${service_name}\"         \"off\"\n        check_linux_package \"uninstall\"               \"${service_name}\"\n      done\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/nis/audit_nis_entries.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2046\n# shellcheck disable=SC2154\n\n# audit_nis_entries\n#\n# Check NIS entries\n#\n# Refer to Section(s) 9.2.2-4 Page(s) 163-5   CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 9.2.2-4 Page(s) 188-190 CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 9.2.2-4 Page(s) 166-8   CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 13.2-4  Page(s) 154-6   CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 9.4     Page(s) 118-9   CIS Solaris 10 Benchmark v1.1.0\n#.\n\naudit_nis_entries () {\n  print_function \"audit_nis_entries\"\n  string=\"NIS Map Entries\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ]; then\n    for check_file in /etc/passwd /etc/shadow /etc/group; do\n      if test -r \"${check_file}\"; then\n        if [ \"${audit_mode}\" != 2 ]; then\n          command=\"grep -c \\\"^+\\\" \\\"${check_file}\\\" | sed \\\"s/ //g\\\"\"\n          command_message \"${command}\"\n          entry_check=$( eval \"${command}\" )\n          if [ ! \"${entry_check}\" = \"0\" ]; then\n            command=\"grep \\\"^+\\\" \\\"${check_file}\\\"\"\n            command_message      \"${command}\"\n            file_entries=$( eval \"${command}\" )\n            for file_entry in ${file_entries}; do\n              if [ \"${audit_mode}\" = 1 ]; then\n                inc_insecure \"NIS entry \\\"${file_entry}\\\" in ${check_file}\"\n                fix_message  \"sed -e \\\"s/^+/#&/\\\" < ${check_file} > ${temp_file}\"\n                fix_message  \"cat ${temp_file} > ${check_file}\"\n              fi\n              if [ \"${audit_mode}\" = 0 ]; then\n                backup_file \"${check_file}\"\n                set_message \"File \\\"${check_file}\\\" to have no NIS entries\"\n                command=\"sed -e \\\"s/^+/#&/\\\" < \\\"${check_file}\\\" > \\\"${temp_file}\\\"\"\n                command_message   \"${command}\"\n                file_list=$( eval \"${command}\" )\n                command=\"cat \\\"${temp_file}\\\" > \\\"${check_file}\\\"\"\n                command_message   \"${command}\"\n                file_list=$( eval \"${command}\" )\n                if [ \"${os_name}\" = \"SunOS\" ]; then\n                  if [ \"${os_version}\" != \"11\" ]; then\n                    command=\"pkgchk -f -n -p \\\"${check_file}\\\" 2> /dev/null\"\n                    command_message   \"${command}\"\n                    file_list=$( eval \"${command}\" )\n                  else\n                    command=\"pkg fix $( pkg search \\\"${check_file}\\\" | grep pkg | awk '{print \\$4}' )\"\n                    command_message   \"${command}\"\n                    file_list=$( eval \"${command}\" )\n                  fi\n                fi\n                if [ -f \"${temp_file}\" ]; then\n                  rm \"${temp_file}\"\n                fi\n              fi\n            done\n            if [ \"${file_entry}\" = \"\" ]; then\n              if [ \"${audit_mode}\" = 1 ]; then\n                inc_secure \"No NIS entries in \\\"${check_file}\\\"\"\n              fi\n            fi\n          fi\n        else\n          restore_file \"${check_file}\" \"${restore_dir}\"\n        fi\n      fi\n    done\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/nis/audit_nis_server.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_nis_server\n#\n# Check NIS daemon settings\n#\n# Refer to Section(s) 2.1.7   Page(s) 51-52 CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 2.1.6   Page(s) 58-9  CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 2.1.6   Page(s) 53-4  CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 2.2.16  Page(s) 117   CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 5.1.1   Page(s) 40    CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 3.12-3  Page(s) 13-14 CIS FreeBSD Benchmark v1.0.5\n# Refer to Section(s) 2.4     Page(s) 17-8  CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 2.2.2   Page(s) 23-4  CIS Solaris 10 Benchmark v5.1.0\n# Refer to Section(s) 2.2.16  Page(s) 109   CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 2.2.17  Page(s) 118   CIS Ubuntu 16.04 Benchmark v2.0.0\n# Refer to Section(s) 2.1.10  Page(s) 254-6 CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_nis_server () {\n  print_function \"audit_nis_server\"\n  string=\"NIS Server Daemons\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"FreeBSD\" ]; then\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      if [ \"${os_version}\" = \"10\" ]; then\n        for service_name in \"svc:/network/nis/server\" \\\n          \"svc:/network/nis/passwd\" \"svc:/network/nis/update\" \\\n          \"svc:/network/nis/xfr\"; do\n          check_sunos_service \"${service_name}\" \"disabled\"\n        done\n      fi\n      if [ \"${os_version}\" = \"11\" ]; then\n        check_sunos_service \"svc:/network/nis/server\" \"disabled\"\n        check_sunos_service \"svc:/network/nis/domain\" \"disabled\"\n      fi\n    fi\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      for service_name in yppasswdd ypserv ypxfrd; do\n        check_linux_service \"${service_name}\" \"off\"\n        check_linux_package \"uninstall\"       \"${service_name}\"\n      done\n    fi\n    if [ \"${os_name}\" = \"FreeBSD\" ]; then\n      check_file_value \"is\" \"/etc/rc.conf\" \"nis_server_enable\"    \"eq\" \"NO\" \"hash\"\n      check_file_value \"is\" \"/etc/rc.conf\" \"nis_ypxfrd_enable\"    \"eq\" \"NO\" \"hash\"\n      check_file_value \"is\" \"/etc/rc.conf\" \"nis_yppasswdd_enable\" \"eq\" \"NO\" \"hash\"\n      check_file_value \"is\" \"/etc/rc.conf\" \"rpc_ypupdated_enable\" \"eq\" \"NO\" \"hash\"\n      check_file_value \"is\" \"/etc/rc.conf\" \"nis_client_enable\"    \"eq\" \"NO\" \"hash\"\n      check_file_value \"is\" \"/etc/rc.conf\" \"nis_ypset_enable\"     \"eq\" \"NO\" \"hash\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/nis/audit_nisplus.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_nisplus\n#\n# Check NIS+ daemons\n#\n# Refer to Section(s) 2.2.4 Page(s) 25 CIS Solaris 10 Benchmark v5.1.0\n#.\n\naudit_nisplus () {\n  print_function \"audit_nisplus\"\n  string=\"NIS+ Daemons\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ]; then\n      check_sunos_service \"svc:/network/rpc/nisplus\" \"disabled\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/ntp/audit_ntp.sh",
    "content": "#!/bin/sh\n\n# -> Needs fixing\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_ntp\n#\n# Check NTP settings\n#\n# Refer to Section(s) 3.6           Page(s) 62-3    CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 3.6           Page(s) 75-6    CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 3.6           Page(s) 65-6    CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 2.2.1.1-2     Page(s) 98-101  CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 2.4.5.1       Page(s) 35-6    CIS Apple OS X 10.5 Benchmark v1.1.0\n# Refer to Section(s) 2.2.1-3       Page(s) 26-31   CIS Apple OS X 10.12 Benchmark v1.0.0\n# Refer to Section(s) 2.3.2.1-2     Page(s) 82-6    CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n# Refer to Section(s) 6.5           Page(s) 55-6    CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 1.9.2         Page(s) 16-7    CIS ESX Server 4 Benchmark v1.1.0\n# Refer to Section(s) 2.2.1.1-2     Page(s) 90-2    CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 2.2.1.1-3     Page(s) 98-101  CIS Ubuntu 16.04 Benchmark v1.0.0\n# Refer to Section(s) 2.3.1.1-3.3.3 Page(s) 306-26  CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_ntp () {\n  print_function \"audit_ntp\"\n  string=\"Network Time Protocol\"\n  check_message  \"${string}\"\n  ntp_package=\"chrony\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"Darwin\" ] || [ \"${os_name}\" = \"VMkernel\" ]; then\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      check_file_value \"is\" \"/etc/inet/ntp.conf\" \"server\" \"space\" \"pool.ntp.org\" \"hash\"\n      if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n        check_sunos_service \"svc:/network/ntp4:default\" \"enabled\"\n      fi\n    fi\n    if [ \"${os_name}\" = \"Darwin\" ]; then\n      check_file_value   \"is\" \"/private/etc/hostconfig\" \"TIMESYNC\" \"eq\" \"-YES-\" \"hash\"\n      check_launchctl_service \"org.ntp.ntpd\" \"on\"\n      #check_file=\"/private/etc/ntp.conf\"\n      if [ \"${long_os_version}\" -ge 1009 ]; then\n        check_file_value      \"is\" \"/etc/ntp-restrict.conf\" \"restrict\" \"space\" \"lo interface ignore wildcard interface listen lo\" \"hash\"\n        check_osx_systemsetup \"getusingnetworktime\" \"on\"\n        timeserver=\"${country_suffix}.pool.ntp.org\"\n        check_osx_systemsetup \"getnetworktimeserver\" \"${timeserver}\"\n      fi\n    fi\n    if [ \"${os_name}\" = \"VMkernel\" ]; then\n      check_linux_service \"ntpd\" \"on\"\n      check_append_file   \"/etc/ntp.conf\" \"restrict 127.0.0.1\" \"hash\"\n    fi\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      check_file=\"/etc/ntp.conf\"\n      log_file=\"ntp.log\"\n      do_chrony=0\n      if [ \"${os_vendor}\" = \"Red\" ] || [ \"${os_vendor}\" = \"CentOS\" ] && [ \"${os_version}\" -ge 7 ]; then\n        do_chrony=1\n      fi\n      if [ \"${os_vendor}\" = \"Ubuntu\" ] && [ \"${os_version}\" -ge 16 ]; then\n        do_chrony=1\n      fi\n      if [ \"${os_vendor}\" = \"Amazon\" ]; then\n        do_chrony=1\n      fi\n      if [ \"${do_chrony}\" -eq 1 ] && [ \"${ntp_package}\" = \"chrony\" ]; then\n        old_package=\"systemd-timesyncd\"\n        check_linux_package \"uninstall\"       \"${old_package}\"\n        check_linux_service \"${old_package}\"  \"off\"\n        check_linux_package \"install\"         \"${ntp_package}\"\n        check_linux_service \"${ntp_package}\"  \"on\"\n        check_file_value    \"is\"              \"/etc/sysconfig/chronyd\"   \"OPTIONS\" \"eq\" \"\\\"-u chrony\\\"\"        \"hash\"\n        for server_number in $( seq 0 3 ); do\n          ntp_server=\"${server_number}.${country_suffix}.pool.ntp.org\"\n          check_file_value  \"is\"              \"/etc/chrony/chrony.conf\"  \"pool\" \"space\" \"${ntp_server} iburst\" \"hash\"\n        done\n      else\n        if [ \"${ntp_package}\" = \"systemd-timesyncd\" ]; then\n          old_package=\"chrony\"\n          check_linux_package     \"uninstall\"       \"${old_package}\"\n          check_linux_service     \"${old_package}\"  \"off\"\n          check_linux_package     \"install\"         \"${ntp_package}\"\n          check_linux_service     \"${ntp_package}\"  \"on\"\n          conf_file=\"/etc/systemd/timesyncd.conf\"\n          ntp_server=\"0.${country_suffix}.pool.ntp.org\"\n          check_file_value  \"is\"  \"${conf_file}\"    \"NTP\"         \"eq\"   \"${ntp_server}\" \"hash\"\n          ntp_server=\"1.${country_suffix}.pool.ntp.org\"\n          check_file_value  \"is\"  \"${conf_file}\"    \"FallbackNTP\" \"eq\"   \"${ntp_server}\" \"hash\"\n        else\n          check_linux_package     \"install\" \"ntp\"\n          if [ -f \"/usr/bin/systemctl\" ]; then\n            check_append_file     \"/usr/lib/systemd/system/ntpd.service\" \"restrict default kod nomodify nopeer notrap noquery\"    \"hash\"\n            check_append_file     \"/usr/lib/systemd/system/ntpd.service\" \"restrict -6 default kod nomodify nopeer notrap noquery\" \"hash\"\n            check_file_value \"is\" \"/usr/lib/systemd/system/ntpd.service\" \"OPTIONS\"   \"eq\" \"\\\"-u ntp:ntp -p /var/run/ntpd.pid\\\"\"   \"hash\"\n            check_file_value \"is\" \"/usr/lib/systemd/system/ntpd.service\" \"ExecStart\" \"eq\" \"/usr/sbin/ntpd -u ntp:ntp \\$OPTIONS\"   \"hash\"\n          else\n            check_linux_service \"ntp\" \"on\"\n          fi\n          for server_number in $( seq 0 3 ); do\n            ntp_server=\"${server_number}.${country_suffix}.pool.ntp.org\"\n            check_file_value    \"is\" \"/etc/ntp.conf\" \"server\" \"space\" \"${ntp_server}\" \"hash\"\n          done\n        fi\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/pam/audit_pam_authtok.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2028\n# shellcheck disable=SC2034\n# shellcheck disable=SC2046\n# shellcheck disable=SC2154\n\n# audit_pam_authtok\n#\n# Check PAM use_authok\n#\n#.\n\naudit_pam_authtok () {\n  print_function \"audit_pam_authtok\"\n  pam_module=\"use_authtok\"\n  string=\"PAM ${pam_module} Configuration\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    check_string=\"PAM ${pam_module} Configuration\"\n    verbose_message \"${check_string}\" \"check\"\n    if [ \"${os_vendor}\" = \"Ubuntu\" ] && [ \"${os_version}\" -ge 24 ]; then\n      check_dir=\"/etc/pam.d\"\n      if [ \"${audit_mode}\" = 2 ]; then\n        restore_file \"${check_file}\" \"${restore_dir}\"\n      else\n        pam_check=$( grep -cPH -- \"^\\h*password\\h+([^#\\n\\r]+)\\h+pam_unix\\.so\\h+([^#\\n\\r]+\\h+)?${pam_module}\\b\" < \"${check_file}\" )\n        if [ \"${ansible_mode}\" = 1 ]; then\n          ansible_counter=$((ansible_counter+1))\n          ansible_value=\"audit_pam_authtok_${ansible_counter}\"\n          echo \"\"\n          echo \"- name: Checking ${check_string}\"\n          echo \"  command: sh -c \\\"grep -cPH -- '^\\h*password\\h+\\([^#\\n\\r]+\\)\\h+pam_unix\\.so\\h+\\([^#\\n\\r]+\\h+\\)?${pam_module}\\b' < ${check_file}\\\"\" \n          echo \"  register: ${ansible_value}\"\n          echo \"  failed_when: ${ansible_value} == 0\"\n          echo \"  changed_when: false\"\n          echo \"  ignore_errors: true\"\n          echo \"  when: ansible_facts['ansible_system'] == '${os_name}'\"\n          echo \"\"\n          echo \"- name: Fixing ${check_string}\"\n          echo \"  command: sh -c \\\"sed \\\\\"s/\\(^password.*pam_unix\\.so\\)\\(.*\\)/\\\\1 ${pam_module} \\\\2/g\\\\\" ${check_file}\\\"\"\n          echo \"  when: ${ansible_value}.rc == 0 and ansible_facts['ansible_system'] == '${os_name}'\"\n          echo \"\"\n        fi\n        if [ \"${pam_check}\" = \"0\" ]; then\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_insecure \"PAM ${pam_module} not enabled in \\\"${check_file}\\\"\"\n            fix_message  \"sed \\\"s/\\(^password.*pam_unix\\.so\\)\\(.*\\)/\\1 ${pam_module} \\2/g\\\" < ${check_file} > ${temp_file}\"\n            fix_message  \"cat ${temp_file} > ${check_file}\"\n            fix_message  \"rm ${temp_file}\"\n          fi\n          if [ \"${audit_mode}\" = 0 ]; then\n            backup_file \"${check_file}\"\n            fix_message \"PAM ${pam_module} enabled in \\\"${check_file}\\\"\"\n            sed \"s/\\(^password.*pam_unix\\.so\\)\\(.*\\)/\\1 ${pam_module} \\2/g\" < \"${check_file}\" > \"${temp_file}\"\n            cat \"${temp_file}\" > \"${check_file}\"\n            if [ -f \"${temp_file}\" ]; then\n              rm \"${temp_file}\"\n            fi\n          fi\n        else\n          inc_secure \"PAM ${pam_module} enabled in \\\"${check_file}\\\"\"\n        fi\n      fi\n    else\n      na_message \"${string}\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/pam/audit_pam_deny.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_pam_deny\n#\n# Add pam.deny to pam config files\n#\n# Refer to Section(s) 6.7   Page(s) 23  CIS FreeBSD Benchmark v1.0.5\n# Refer to Section(s) 6.3.3 Page(s) 162 CIS RHEL 5 Benchmark v2.1.0\n#.\n\naudit_pam_deny () {\n  print_function \"audit_pam_deny\"\n  string=\"PAM Deny Weak Authentication Services\"\n  tab=$( printf \"\\t\" )\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"FreeBSD\" ] || [ \"${os_name}\" = \"Linux\" ]; then\n    pam_module=\"pam_deny\"\n    if [ \"${os_name}\" = \"FreeBSD\" ]; then\n      if [ \"${os_version}\" -lt 5 ]; then\n        check_append_file \"/etc/pam.conf\" \"rexecd${tab}auth${tab}required${tab}${pam_module}.so\" \"hash\"\n        check_append_file \"/etc/pam.conf\" \"rsh${tab}auth${tab}required${tab}${pam_module}.so\"    \"hash\"\n      else\n        :\n        # Need to insert code here\n        # sed -i .preCIS -e 's/nologin/deny/g' /etc/pam.d/rsh /etc/pam.d/rexecd\n      fi\n    fi\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      check_append_file \"/etc/pam.d/sshd\" \"auth${tab}requisite${tab}${pam_module}.so\" \"hash\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/pam/audit_pam_gdm_autologin.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_pam_gdm_autologin\n#\n# Check PAM GDM autologin settings\n#\n# Refer to Section(s) 16.11 Page(s) 54-5 Solaris 11.1 Benchmark v1.0.0\n#.\n\naudit_pam_gdm_autologin () {\n  print_function \"audit_pam_gdm_autologin\"\n  string=\"Gnome Autologin\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"11\" ]; then\n      pam_module=\"gdm-autologin\"\n      check_file=\"/etc/pam.d/${pam_module}\"\n      temp_file=\"${temp_dir}/${pam_module}\"\n      if [ \"${audit_mode}\" = 2 ]; then\n        restore_file \"${check_file}\" \"${restore_dir}\"\n      fi\n      if [ \"${audit_mode}\" != 2 ]; then\n        if [ \"${ansible_mode}\" = 1 ]; then\n          ansible_counter=$((ansible_counter+1))\n          ansible_value=\"audit_pam_gdm_autologin_${ansible_counter}\"\n          echo \"\"\n          echo \"- name: Checking ${string}\"\n          echo \"  command:  sh -c \\\"cat ${check_file} |grep -v '^#' |grep '^${pam_module}' |head -1 |wc -l\\\"\"\n          echo \"  register: ${ansible_value}\"\n          echo \"  failed_when: ${ansible_value} == 1\"\n          echo \"  changed_when: false\"\n          echo \"  ignore_errors: true\"\n          echo \"  when: ansible_facts['ansible_system'] == '${os_name}'\"\n          echo \"\"\n          echo \"- name: Fixing ${string}\"\n          echo \"  command: sh -c \\\"sed -i 's/^${pam_module}/#&/g' ${check_file}\\\"\"\n          echo \"  when: ${ansible_value} .rc == 1 and ansible_facts['ansible_system'] == '${os_name}'\"\n          echo \"\"\n        fi\n        command=\"grep -v \\\"^#\\\" \\\"${check_file}\\\" | grep \\\"^${pam_module}\\\" | head -1 | wc -l | sed \\\"s/ //g\\\"\"\n        command_message   \"${command}\"\n        gdm_check=$( eval \"${command}\" )\n        if [ \"${gdm_check}\" != 0 ]; then\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_insecure \"${string} is enabled\"\n            fix_message  \"cat ${check_file} |sed 's/^${pam_module}/#&/g' > ${temp_file}\"\n            fix_message  \"cat ${temp_file} > ${check_file}\"\n            fix_message  \"rm ${temp_file}\"\n          fi\n          if [ \"${audit_mode}\" = 0 ]; then\n            backup_file \"${check_file}\"\n            sed \"s/^${pam_module}/#&/g\" \"${check_file}\" > \"${temp_file}\"\n            cat \"${temp_file}\" > \"${check_file}\"\n            if [ -f \"${temp_file}\" ]; then\n              rm \"${temp_file}\"\n            fi\n          fi\n        else\n          if [ \"${audit_mode}\" = 1 ];then\n            inc_secure \"${string} is disabled\"\n          fi\n        fi\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/pam/audit_pam_rhosts.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2046\n# shellcheck disable=SC2154\n\n# audit_pam_rhosts\n#\n# Check PAM rhost settings\n#\n# Bug: Need to implement backup_file to after the ansible_mode check\n#\n# Refer to Section(s) 6.8 Page(s) 51-52 CIS Solaris 11.1 Benchmark  v1.0.0\n# Refer to Section(s) 6.4 Page(s) 89    CIS Solaris 10 Benchmark v5.1.0\n#.\n\naudit_pam_rhosts () {\n  print_function \"audit_pam_rhosts\"\n  pam_module=\"pam_rhosts_auth\"\n  string=\"PAM ${pam_module} Configuration\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      check_file=\"/etc/pam.conf\"\n      if [ \"${audit_mode}\" = 2 ]; then\n        restore_file \"${check_file}\" \"${restore_dir}\"\n      else\n        if [ -f \"${check_file}\" ]; then\n          command=\"grep -v \\\"^#\\\" \\\"${check_file}\\\" | grep \\\"${pam_module}\\\" | head -1 | wc -l | sed \\\"s/ //g\\\"\"\n          command_message   \"${command}\"\n          pam_check=$( eval \"${command}\" )\n          if [ \"${ansible_mode}\" = 1 ]; then\n            ansible_counter=$((ansible_counter+1))\n            ansible_value=\"audit_pam_rhosts_${ansible_counter}\"\n            echo \"\"\n            echo \"- name: Checking ${string}\"\n            echo \"  command:  sh -c \\\"cat ${check_file} | grep -v '^#' |grep '${pam_module}' |head -1 |wc -l | sed 's/ //g'\\\"\"\n            echo \"  register: ${ansible_value}\"\n            echo \"  failed_when: ${ansible_value} == 1\"\n            echo \"  changed_when: false\"\n            echo \"  ignore_errors: true\"\n            echo \"  when: ansible_facts['ansible_system'] == '${os_name}'\"\n            echo \"\"\n            echo \"- name: Fixing ${string}\"\n            echo \"  command: sh -c \\\"sed -i 's/^.*${pam_module}/#&/' ${check_file}\\\"\"\n            echo \"  when: ${ansible_value}.rc == 1 and ansible_facts['ansible_system'] == '${os_name}'\"\n            echo \"\"\n          fi\n          if [ \"${pam_check}\" = \"1\" ]; then\n            if [ \"${audit_mode}\" = 1 ]; then\n              inc_insecure \"Rhost authentication enabled in \\\"${check_file}\\\"\"\n              fix_message  \"sed -e 's/^.*${pam_module}/#&/' < ${check_file} > ${temp_file}\"\n              fix_message  \"cat ${temp_file} > ${check_file}\"\n              fix_message  \"rm ${temp_file}\"\n            else\n              log_file=\"${work_dir}${check_file}\"\n              if [ ! -f \"${log_file}\" ]; then\n                save_message \"File ${check_file} to ${work_dir}${check_file}\"\n                command=\"find \\\"${check_file}\\\" | cpio -pdm \\\"${work_dir}\\\" 2> /dev/null\"\n                command_message   \"${command}\"\n                file_list=$( eval \"${command}\" )\n              fi\n              set_message \"Rhost authentication to disabled in ${check_file}\"\n              command=\"sed -e 's/^.*${pam_module}/#&/' \\\"${check_file}\\\" > \\\"${temp_file}\\\"\"\n              command_message   \"${command}\"\n              file_list=$( eval \"${command}\" )\n              command=\"cat \\\"${temp_file}\\\" > \\\"${check_file}\\\"\"\n              command_message   \"${command}\"\n              file_list=$( eval \"${command}\" )\n              if [ -f \"${temp_file}\" ]; then\n                rm \"${temp_file}\"\n              fi\n              if [ \"${os_version}\" != \"11\" ]; then\n                command=\"pkgchk -f -n -p \\\"${check_file}\\\" 2> /dev/null\"\n                command_message   \"${command}\"\n                file_list=$( eval \"${command}\" )\n              else\n                command=\"pkg fix $( pkg search \\\"${check_file}\\\" | grep pkg | awk '{print \\$4}' )\"\n                command_message   \"${command}\"\n                file_list=$( eval \"${command}\" )\n              fi\n            fi\n          else\n            inc_secure \"Rhost authentication disabled in \\\"${check_file}\\\"\"\n          fi\n        fi\n      fi\n    fi\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      check_dir=\"/etc/pam.d\"\n      if [ -d \"${check_dir}\" ]; then\n        command=\"find \\\"${check_dir}\\\" -type f\"\n        command_message \"${command}\"\n        file_list=$( eval \"${command}\" )\n        for check_file in ${file_list}; do\n          if [ \"${audit_mode}\" = 2 ]; then\n            restore_file \"${check_file}\" \"${restore_dir}\"\n          else\n            pam_check=$( grep -v \"^#\" \"${check_file}\" | grep -c \"rhosts_auth\" | sed \"s/ //g\" )\n            if [ \"${ansible_mode}\" = 1 ]; then\n              ansible_counter=$((ansible_counter+1))\n              ansible_value=\"audit_pam_rhosts_${ansible_counter}\"\n              echo \"\"\n              echo \"- name: Checking ${string}\"\n              echo \"  command:  sh -c \\\"cat ${check_file} | grep -v '^#' |grep 'rhosts_auth' |head -1 |wc -l | sed 's/ //g'\\\"\"\n              echo \"  register: ${ansible_value}\"\n              echo \"  failed_when: ${ansible_value} == 1\"\n              echo \"  changed_when: false\"\n              echo \"  ignore_errors: true\"\n              echo \"  when: ansible_facts['ansible_system'] == '${os_name}'\"\n              echo \"\"\n              echo \"- name: Fixing ${string}\"\n              echo \"  command: sh -c \\\"sed -i 's/^.*rhosts_auth/#&/' ${check_file}\\\"\"\n              echo \"  when: ${ansible_value}.rc == 1 and ansible_facts['ansible_system'] == '${os_name}'\"\n              echo \"\"\n            fi\n            if [ \"${pam_check}\" = \"1\" ]; then\n              if [ \"${audit_mode}\" = 1 ]; then\n                inc_insecure  \"Rhost authentication enabled in \\\"${check_file}\\\"\"\n                fix_message  \"sed -e 's/^.*rhosts_auth/#&/' < ${check_file} > ${temp_file}\"\n                fix_message  \"cat ${temp_file} > ${check_file}\"\n                fix_message  \"rm ${temp_file}\"\n              fi\n              if [ \"${audit_mode}\" = 0 ]; then\n                backup_file \"${check_file}\"\n                set_message \"Rhost authentication to disabled in \\\"${check_file}\\\"\"\n                command=\"sed -e 's/^.*rhosts_auth/#&/' < \\\"${check_file}\\\" > \\\"${temp_file}\\\"\"\n                command_message \"${command}\"\n                file_list=$( eval \"${command}\" )\n                command=\"cat \\\"${temp_file}\\\" > \\\"${check_file}\\\"\"\n                command_message \"${command}\"\n                file_list=$( eval \"${command}\" )\n                if [ -f \"${temp_file}\" ]; then\n                  rm \"${temp_file}\"\n                fi\n              fi\n            else\n              inc_secure \"Rhost authentication disabled in \\\"${check_file}\\\"\"\n            fi\n          fi\n        done\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/pam/audit_rsa_securid_pam.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2028\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_rsa_securid_pam\n#\n# Check that RSA is installed\n#.\n\naudit_rsa_securid_pam () {\n  print_function \"audit_rsa_securid_pam\"\n  string=\"RSA SecurID PAM Agent Configuration\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"SunOS\" ]; then\n    check_file=\"/etc/sd_pam.conf\"\n    if [ -f \"${check_file}\" ]; then\n      search_string=\"pam_securid.so\"\n      if [ \"${os_name}\" = \"SunOS\" ]; then\n        check_file=\"/etc/pam.conf\"\n        if [ -f \"${check_file}\" ]; then\n          command=\"grep \\\"${search_string}\\\" \\\"${check_file}\\\" | awk '{print \\$3}'\"\n          command_message \"${command}\"\n          check_value=$( eval \"${command}\" )\n        fi\n      fi\n      if [ \"${os_name}\" = \"Linux\" ]; then\n        check_file=\"/etc/pam.d/sudo\"\n        if [ -f \"${check_file}\" ]; then\n          command=\"grep \\\"${search_string}\\\" \\\"${check_file}\\\" | awk '{print \\$4}'\"\n          command_message \"${command}\"\n          check_value=$( eval \"${command}\" )\n        fi\n      fi\n      if [ \"${audit_mode}\" != 2 ]; then\n        if [ \"${check_value}\" != \"${search_string}\" ]; then\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_insecure \"RSA SecurID PAM Agent is not enabled for sudo\"\n            if [ \"${os_name}\" = \"Linux\" ]; then\n              fix_message \"cat ${check_file} |sed 's/^auth/#\\&/' > ${temp_file}\"\n              fix_message \"cat ${temp_file} > ${check_file}\"\n              fix_message \"echo \\\"auth\\trequired\\tpam_securid.so reserve\\\" >> ${check_file}\"\n              fix_message \"rm ${temp_file}\"\n            fi\n            if [ \"${os_name}\" = \"SunOS\" ]; then\n              fix_message \"echo \\\"sudo\\tauth\\trequired\\tpam_securid.so reserve\\\" >> ${check_file}\"\n            fi\n          fi\n          if [ \"${audit_mode}\" = 0 ]; then\n            backup_file \"${check_file}\"\n            set_message \"Configuring RSA SecurID PAM Agent for sudo\"\n            if [ \"${os_name}\" = \"Linux\" ]; then\n              command=\"sed -e 's/^auth/#\\\\&/' < \\\"${check_file}\\\" > \\\"${temp_file}\\\"\"\n              command_message \"${command}\"\n              file_list=$( eval \"${command}\" )\n              command=\"cat \\\"${temp_file}\\\" > \\\"${check_file}\\\"\"\n              command_message \"${command}\"\n              file_list=$( eval \"${command}\" )\n              command=\"echo \\\"auth\\trequired\\tpam_securid.so reserve\\\" >> \\\"${check_file}\\\"\"\n              command_message \"${command}\"\n              file_list=$( eval \"${command}\" )\n              if [ -f \"${temp_file}\" ]; then\n                rm \"${temp_file}\"\n              fi\n            fi\n            if [ \"${os_name}\" = \"SunOS\" ]; then\n              echo \"sudo\\tauth\\trequired\\tpam_securid.so reserve\" >> \"${check_file}\"\n            fi\n            #echo \"Removing:  Configuring logrotate\"\n            #cat ${check_file} |sed 's,.*{,${search_string} {,' > ${temp_file}\n            #cat ${temp_file} > ${check_file}\n            #rm ${temp_file}\n          fi\n        else\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_secure \"RSA SecurID PAM Agent is configured for sudo\"\n          fi\n        fi\n      else\n        restore_file \"${check_file}\" \"${restore_dir}\"\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/password/audit_pass_req.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_pass_req\n#\n# Set PASSREQ to YES in /etc/default/login to prevent users from loging on\n# without a password\n#.\n\naudit_pass_req () {\n  print_function \"audit_pass_req\"\n  string=\"Password Required\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    check_file_value \"is\" \"/etc/default/login\"  \"PASSREQ\" \"eq\" \"YES\" \"hash\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/password/audit_passwd_perms.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_passwd_perms\n#\n# Refer to Section(s) 9.1.2-9  Page(s) 153-9   CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 9.1.2-9  Page(s) 177-83  CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 9.2.2-9  Page(s) 157-62  CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 6.1.2-9  Page(s) 261-8   CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 12.2-7   Page(s) 146-50  CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 6.1.2-9  Page(s) 239-46  CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 6.1      Page(s) 21      CIS FreeBSD Benchmark v1.0.5\n# Refer to Section(s) 2.11.1-3 Page(s) 192-4   CIS AIX Benchmark v1.1.0\n# Refer to Section(s) 6.1.2-9  Page(s) 253-60  CIS Ubuntu 16.04 Benchmark v1.0.0\n# Refer to Section(s) 7.1.1-8  Page(s) 934-49  CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_passwd_perms () {\n  print_function \"audit_passwd_perms\"\n  string=\"Group and Password File Permissions\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"FreeBSD\" ] || [ \"${os_name}\" = \"AIX\" ]; then\n    if [ \"${os_name}\" = \"AIX\" ]; then\n      for check_file in /etc/passwd /etc/group; do\n        check_file_perms \"${check_file}\" \"0644\" \"root\" \"security\"\n      done\n      check_dir=\"/etc/security\"\n      check_file_perms   \"${check_dir}\" \"0750\"  \"root\" \"security\"\n    fi\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      check_file_perms   \"/etc/passwd\"          \"0644\" \"root\" \"root\"\n      check_file_perms   \"/etc/group\"           \"0644\" \"root\" \"root\"\n      check_file_perms   \"/etc/shadow\"          \"0600\" \"root\" \"root\"\n      check_file_perms   \"/etc/gshadow\"         \"0600\" \"root\" \"root\"\n      check_file_perms   \"/etc/group-\"          \"0600\" \"root\" \"root\"\n      check_file_perms   \"/etc/passwd-\"         \"0600\" \"root\" \"root\"\n      check_file_perms   \"/etc/shadow-\"         \"0600\" \"root\" \"root\"\n      check_file_perms   \"/etc/gshadow-\"        \"0600\" \"root\" \"root\"\n    fi\n    if [ \"${os_name}\" = \"FreeBSD\" ]; then\n      check_file_perms   \"/etc/passwd\"          \"0644\" \"root\" \"${wheel_group}\"\n      check_file_perms   \"/etc/group\"           \"0644\" \"root\" \"${wheel_group}\"\n      check_file_perms   \"/etc/pwd.db_file\"     \"0644\" \"root\" \"${wheel_group}\"\n      check_file_perms   \"/etc/master.passwd\"   \"0600\" \"root\" \"${wheel_group}\"\n      check_file_perms   \"/etc/spwd.db\"         \"0600\" \"root\" \"${wheel_group}\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/password/audit_password_expiry.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC2034\n# shellcheck disable=SC1090\n# shellcheck disable=SC2154\n\n# audit_password_expiry\n#\n# Refer to Section(s) 7.1.1-3   Page(s) 143-146 CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 7.1.1-3   Page(s) 166-8   CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 7.1.1-3   Page(s) 147-9   CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 5.4.1.1-4 Page(s) 245-51  CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 10.1.1-3  Page(s) 136-8   CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 8.3       Page(s) 27      CIS FreeBSD Benchmark v1.0.5\n# Refer to Section(s) 1.1.1-11  Page(s) 17-26   CIS AIX Benchmark v1.1.0\n# Refer to Section(s) 7.1       Page(s) 61-62   CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 7.2       Page(s) 101-3   CIS Solaris 10 Benchmark v5.1.0\n# Refer to Section(s) 5.4.1.1-4 Page(s) 226-30  CIS Amazon Linux v2.0.0\n# Refer to Section(s) 5.4.1.1-4 Page(s) 238-43  CIS Ubuntu 16.04 v1.0.0\n# Refer to Section(s) 5.4.1.1-3 Page(s) 677-85  CIS Ubuntu 24.04 v1.0.0\n#.\n\naudit_password_expiry () {\n  print_function \"audit_password_expiry\"\n  string=\"Password Expiration Parameters on Active Accounts\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"FreeBSD\" ] || [ \"${os_name}\" = \"AIX\" ]; then\n    if [ \"${os_name}\" = \"AIX\" ]; then\n      check_chsec \"/etc/security/user\" \"default\"  \"mindiff\"       \"4\"\n      check_chsec \"/etc/security/user\" \"default\"  \"minage\"        \"1\"\n      check_chsec \"/etc/security/user\" \"default\"  \"maxage\"        \"13\"\n      check_chsec \"/etc/security/user\" \"default\"  \"minlen\"        \"8\"\n      check_chsec \"/etc/security/user\" \"default\"  \"minalpha\"      \"2\"\n      check_chsec \"/etc/security/user\" \"default\"  \"minother\"      \"2\"\n      check_chsec \"/etc/security/user\" \"default\"  \"maxrepeats\"    \"2\"\n      check_chsec \"/etc/security/user\" \"default\"  \"histexpire\"    \"13\"\n      check_chsec \"/etc/security/user\" \"default\"  \"histsize\"      \"20\"\n      check_chsec \"/etc/security/user\" \"default\"  \"maxexpired\"    \"2\"\n      if [ \"${os_version}\" -gt 4 ]; then\n        if [ \"${os_version}\" = \"5\" ]; then\n          if [ \"${os_update}\" -gt 3 ]; then\n            check_chsec \"/etc/security/login.cfg\" \"usw\" \"pwd_algorithm\" \"ssha256\"\n          fi\n        else\n          check_chsec   \"/etc/security/login.cfg\" \"usw\" \"pwd_algorithm\" \"ssha256\"\n        fi\n      fi\n    fi\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      check_file_value \"is\" \"/etc/default/passwd\" \"MAXWEEKS\"      \"eq\"  \"13\"    \"hash\"\n      check_file_value \"is\" \"/etc/default/passwd\" \"MINWEEKS\"      \"eq\"  \"1\"     \"hash\"\n      check_file_value \"is\" \"/etc/default/passwd\" \"WARNWEEKS\"     \"eq\"  \"4\"     \"hash\"\n      check_file_value \"is\" \"/etc/default/login\"  \"DISABLETIME\"   \"eq\"  \"3600\"  \"hash\"\n    fi\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      check_file_value \"is\" \"/etc/login.defs\"     \"PASS_MAX_DAYS\" \"eq\"  \"90\"    \"hash\"\n      check_file_value \"is\" \"/etc/login.defs\"     \"PASS_MIN_DAYS\" \"eq\"  \"7\"     \"hash\"\n      check_file_value \"is\" \"/etc/login.defs\"     \"PASS_WARN_AGE\" \"eq\"  \"14\"    \"hash\"\n      check_file_value \"is\" \"/etc/login.defs\"     \"PASS_MIN_LEN\"  \"eq\"  \"9\"     \"hash\"\n      check_file_perms      \"/etc/login.defs\"     \"0640\" \"root\"   \"root\"\n    fi\n    if [ \"${os_name}\" = \"FreeBSD\" ]; then\n      if [ \"${os_version}\" -gt 5 ]; then\n        check_file_value \"is\" \"/etc/adduser.conf\" \"passwdtype\"    \"eq\"  \"yes\"   \"hash\"\n        check_file_value \"is\" \"/etc/adduser.conf\" \"upwexpire\"     \"eq\"  \"91d\"   \"hash\"\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/password/audit_password_fields.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n\n# audit_password_fields\n#\n# Ensure Password Fields are Not Empty\n# Verify System Account Default Passwords\n# Ensure Password Fields are Not Empty\n#\n# Refer to Section(s) 9.2.1           Page(s) 162-3       CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 9.2.1           Page(s) 187-8       CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 9.2.1           Page(s) 166         CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 6.2.1           Page(s) 274         CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 13.1            Page(s) 154         CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 8.2             Page(s) 27          CIS FreeBSD Benchmark v1.0.5\n# Refer to Section(s) 2.2.15          Page(s) 219         CIS AIX Benchmark v1.1.0\n# Refer to Section(s) 9.4             Page(s) 75          CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 9.3             Page(s) 118         CIS Solaris 10 Benchmark v1.1.0\n# Refer to Section(s) 6.2.1           Page(s) 252         CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 6.2.1-4         Page(s) 266-9       CIS Ubuntu 16.04 Benchmark v1.0.0\n# Refer to Section(s) 5.4.2.1,7.2.1-2 Page(s) 695-7,965-9 CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_password_fields () {\n  print_function \"audit_password_fields\"\n  string=\"Password Fields\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"FreeBSD\" ] || [ \"${os_name}\" = \"AIX\" ]; then\n    if [ \"${audit_mode}\" != 2 ]; then\n      check_file=\"/etc/passwd\"\n      command=\"awk -F: '(\\$3 == 0) { print \\$1 }' \\\"${check_file}\\\" | grep -v root\"\n      command_message   \"${command}\"\n      user_list=$( eval \"${command}\" )\n      if [ \"$user_list\" = \"\" ]; then\n        inc_secure \"No non root users have UID 0\"\n      else\n        for user_name in ${user_list}; do\n          if [ \"${user_name}\" != \"root\" ]; then\n            inc_insecure \"Non root user ${user_name} has UID 0\"\n          fi\n        done\n      fi\n    else\n      check_file=\"/etc/passwd\"\n      restore_file \"${check_file}\" \"${restore_dir}\"\n    fi\n    verbose_message \"Shadow Fields\" \"check\"\n    if [ \"${my_id}\" != \"0\" ] && [ \"${use_sudo}\" = \"0\" ]; then\n      verbose_message \"Requires sudo to check\" \"notice\"\n      return\n    fi\n    if [ \"${audit_mode}\" != 2 ]; then\n      check_file=\"/etc/shadow\"\n      empty_count=0\n      if [ \"${os_name}\" = \"AIX\" ]; then\n        command=\"pwdck –n ALL\"\n        command_message   \"${command}\"\n        user_list=$( eval \"${command}\" )\n      else\n        command=\"awk -F':' '{ print \\$1\\\":\\\"\\$2\\\":\\\" }' < /etc/shadow | grep \\\"::$\\\" | cut -f1 -d:\"\n        command_message   \"${command}\"\n        user_list=$( eval \"${command}\" )\n      fi\n      for user_name in ${user_list}; do\n        empty_count=1\n        if [ \"${audit_mode}\" = 1 ]; then\n          inc_insecure \"No password field for \\\"${user_name}\\\" in \\\"${check_file}\\\"\"\n          fix_message        \"passwd -d ${user_name}\"\n          if [ \"${os_name}\" = \"SunOS\" ]; then\n            fix_message      \"passwd -N ${user_name}\"\n          fi\n        fi\n        if [ \"${audit_mode}\" = 0 ]; then\n          backup_file \"${check_file}\"\n          set_message \"No password for \\\"${user_name}\\\"\"\n          passwd -d \"${user_name}\"\n          if [ \"${os_name}\" = \"SunOS\" ]; then\n            passwd -N \"${user_name}\"\n          fi\n        fi\n      done\n      if [ \"$empty_count\" = 0 ]; then\n        inc_secure \"No empty password entries\"\n      fi\n      for check_file in /etc/passwd /etc/shadow; do\n        if test -r \"${check_file}\"; then\n          command=\"grep '^+:' ${check_file} | head -1 | wc -l | sed \\\"s/ //g\\\"\"\n          command_message      \"${command}\"\n          legacy_check=$( eval \"${command}\" )\n          if [ \"${legacy_check}\" != \"0\" ]; then\n            if [ \"${audit_mode}\" = 1 ]; then\n              inc_insecure \"Legacy field found in \\\"${check_file}\\\"\"\n              fix_message        \"grep -v '^+:' : ${check_file} > ${temp_file}\"\n              fix_message        \"cat ${temp_file}  > ${check_file}\"\n            fi\n            if [ \"${audit_mode}\" = 0 ]; then\n              backup_file    \"${check_file}\"\n              remove_message \"Legacy entries from \\\"${check_file}\\\"\"\n              command=\"grep -v \\\"^+:\\\" \\\"${check_file}\\\" > \\\"${temp_file}\\\"\"\n              command_message \"${command}\"\n              eval \"${command}\"\n              command=\"cat \\\"${temp_file}\\\"  > \\\"${check_file}\\\"\"\n              command_message \"${command}\"\n              eval \"${command}\"\n            fi\n          else\n            inc_secure \"No legacy entries in \\\"${check_file}\\\"\"\n          fi\n        fi\n      done\n    else\n      check_file=\"/etc/shadow\"\n      restore_file \"${check_file}\" \"${restore_dir}\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/password/audit_password_hashing.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_password_hashing\n#\n# Check that password hashing is set to SHA512.\n#\n# Refer to Section(s) 6.3.1   Page(s) 138-9 CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 6.3.4   Page(s) 162-3 CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 6.3.1   Page(s) 141-2 CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 5.3.4   Page(s) 234-5 CIS RHEL 7 Benchmark v1.2.0\n# Refer to Section(s) 5.3.4   Page(s) 224-5 CIS Amazon Linux Benchmark v1.2.0\n# Refer to Section(s) 5.4.1.4 Page(s) 666-8 CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_password_hashing () {\n  print_function \"audit_password_hashing\"\n  string=\"Password Hashing\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    hashing=\"${1}\"\n    if [ \"${1}\" = \"\" ]; then\n      hashing=\"sha512\"\n    fi\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      if [ -f \"/usr/sbin/authconfig\" ]; then\n        verbose_message \"Password Hashing\" \"check\"\n        if [ \"${audit_mode}\" != 2 ]; then\n          log_file=\"hashing.log\"\n          check_value=$( authconfig --test | grep hashing | awk '{print $5}' )\n          if [ \"${check_value}\" != \"${hashing}\" ]; then\n            if [ \"${audit_mode}\" = \"1\" ]; then\n              inc_insecure \"Password hashing not set to \\\"${hashing}\\\"\"\n              fix_message  \"authconfig --passalgo=${hashing}\"\n            fi\n            if [ \"${audit_mode}\" = 0 ]; then\n              set_message \"Password hashing to \\\"${hashing}\\\"\"\n              log_file=\"${work_dir}/${log_file}\"\n              echo \"${check_value}\" > \"${log_file}\"\n              eval \"authconfig --passalgo=${hashing}\"\n            fi\n          else\n            if [ \"${audit_mode}\" = \"1\" ]; then\n              inc_secure \"Password hashing set to \\\"${hashing}\\\"\"\n            fi\n          fi\n        else\n          restore_file=\"${restore_dir}/${log_file}\"\n          if [ -f \"${restore_file}\" ]; then\n            check_value=$( cat \"${restore_file}\" )\n            restore_message \"Password hashing to \\\"${check_value}\\\"\"\n            eval \"authconfig --passalgo=${check_value}\"\n          fi\n        fi\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/password/audit_password_hints.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_password_hints\n#\n# Password hints make it easier for unauthorized persons to gain access to systems by\n# displaying information provided by the user to assist in remembering the password. This\n# info could include the password itself or other information that might be readily\n# discerned with basic knowledge of the end user.\n#\n# Refer to Section 6.1.2  Page(s) 73-4  CIS Apple OS X 10.8  Benchmark v1.0.0\n# Refer to Section 6.1.2  Page(s) 154-5 CIS Apple OS X 10.12 Benchmark v1.0.0\n# Refer to Section 2.10.5 Page(s) 231-3 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_login_details () {\n  print_function \"audit_login_details\"\n  string=\"Login display details\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    check_osx_defaults_int \"/Library/Preferences/com.apple.loginwindow\" \"RetriesUntilHint\" \"0\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/password/audit_password_history.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n\n# audit_password_history\n#\n# Refer to Section(s) 5.4.1.6 Page(s) 692-3 CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_password_history () {\n  print_function \"audit_password_history\"\n  string=\"Password History\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${my_id}\" != \"0\" ] && [ \"${use_sudo}\" = \"0\" ]; then\n      verbose_message \"Requires sudo to check\" \"notice\"\n      return\n    fi\n    if [ \"${audit_mode}\" != 2 ]; then\n      check_file=\"/etc/shadow\"\n      current_date=$( date +%s )\n      command=\"awk -F: '\\$2~/^\\$.+\\$/{print \\$1}' \\\"${check_file}\\\"\"\n      command_message   \"${command}\"\n      user_list=$( eval \"${command}\" )\n      for user_name in ${user_list}; do\n        command=\"date -d \\\"\\$(chage --list \\\"${user_name}\\\" | grep '^Last password change' | cut -d: -f2 | grep -v 'never\\$')\\\" +%s\"\n        command_message     \"${command}\"\n        change_date=$( eval \"${command}\" )\n        if [ \"${change_date}\" -gt \"${current_date}\" ]; then\n          inc_insecure \"User ${user_name} has a last password change date in the future\"\n        else\n          inc_secure   \"User ${user_name} has a last password change date in the past\"\n        fi\n      done\n    else\n      for check_file in /etc/passwd /etc/shadow; do\n        restore_file \"${check_file}\" \"${restore_dir}\"\n      done\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/password/audit_password_lock.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n\n# audit_password_lock\n#\n# Refer to Section(s) 5.4.1.5 Page(s) 689-91 CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_password_lock () {\n  print_function \"audit_password_lock\"\n  string=\"Inactive Password Lock\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${my_id}\" != \"0\" ] && [ \"${use_sudo}\" = \"0\" ]; then\n      verbose_message \"Requires sudo to check\" \"notice\"\n      return\n    fi\n    if [ \"${audit_mode}\" != 2 ]; then\n      check_file=\"/etc/shadow\"\n      inactive_time=\"45\"\n      command=\"useradd -D | grep INACTIVE | cut -f2 -d=\"\n      command_message       \"${command}\"\n      inactive_test=$( eval \"${command}\" )\n      if [ \"${inactive_test}\" -lt \"${inactive_time}\" ]; then\n        inc_insecure  \"Inactive password lock is less than ${inactive_time}\"\n      else\n        inc_secure    \"Inactive password lock is equal to or greater than ${inactive_time}\"\n      fi\n      user_list=$( awk -F: '($2~/^\\$.+\\$/) {if($7 > $inactive || $7 < 0)print $1 }' \"${check_file}\" )\n      if [ \"${user_list}\" = \"\" ]; then\n        inc_secure    \"No users with inactive password locks less that ${inactive_time}\"\n      else\n        for user_name in ${user_list}; do\n          inc_insecure  \"User ${user_name} has an inactive password lock less than ${inactive_time}\"\n        done\n      fi\n    else\n      for check_file in /etc/passwd /etc/shadow; do\n        restore_file \"${check_file}\" \"${restore_dir}\"\n      done\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/password/audit_password_strength.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_password_strength\n#\n# Refer to Section(s) 5.12-19 Page(s) 58-66  CIS Apple OS X 10.8 Benchmark v1.0.0\n# Refer to Section(s) 5.2.1-6 Page(s) 112-27 CIS Apple OS X 10.12 Benchmark v1.0.0\n# Refer to Section(s) 8.10    Page(s)        CIS FreeBSD Benchmark v1.0.5\n# Refer to Section(s) 7.2     Page(s) 63-4   CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 7.3     Page(s) 103-4  CIS Solaris 10 Benchmark v5.1.0\n# Refer to Section(s) 5.2.1-8 Page(s) 315-30 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_password_strength () {\n  print_function \"audit_password_strength\"\n  string=\"Strong Password Creation Policies\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Darwin\" ] || [ \"${os_name}\" = \"FreeBSD\" ]; then\n    if  [ \"${os_name}\" = \"SunOS\" ]; then\n      check_file_value \"is\" \"/etc/default/passwd\" \"PASSLENGTH\"    \"eq\"    \"8\"                         \"hash\"\n      check_file_value \"is\" \"/etc/default/passwd\" \"NAMECHECK\"     \"eq\"    \"YES\"                       \"hash\"\n      check_file_value \"is\" \"/etc/default/passwd\" \"HISTORY\"       \"eq\"    \"10\"                        \"hash\"\n      check_file_value \"is\" \"/etc/default/passwd\" \"MINDIFF\"       \"eq\"    \"3\"                         \"hash\"\n      check_file_value \"is\" \"/etc/default/passwd\" \"MINALPHA\"      \"eq\"    \"2\"                         \"hash\"\n      check_file_value \"is\" \"/etc/default/passwd\" \"MINUPPER\"      \"eq\"    \"1\"                         \"hash\"\n      check_file_value \"is\" \"/etc/default/passwd\" \"MINLOWER\"      \"eq\"    \"1\"                         \"hash\"\n      check_file_value \"is\" \"/etc/default/passwd\" \"MINDIGIT\"      \"eq\"    \"1\"                         \"hash\"\n      check_file_value \"is\" \"/etc/default/passwd\" \"MINNONALPHA\"   \"eq\"    \"1\"                         \"hash\"\n      check_file_value \"is\" \"/etc/default/passwd\" \"MAXREPEATS\"    \"eq\"    \"0\"                         \"hash\"\n      check_file_value \"is\" \"/etc/default/passwd\" \"WHITESPACE\"    \"eq\"    \"YES\"                       \"hash\"\n      check_file_value \"is\" \"/etc/default/passwd\" \"DICTIONDBDIR\"  \"eq\"    \"/var/passwd\"               \"hash\"\n      check_file_value \"is\" \"/etc/default/passwd\" \"DICTIONLIST\"   \"eq\"    \"/usr/share/lib/dict/words\" \"hash\"\n    fi\n    if [ \"${os_name}\" = \"Darwin\" ]; then\n      check_pwpolicy    \"requiresAlpha\"     \"1\"\n#      check_pwpolicy   \"minimumAlphaCharacters\" \"1\"\n      check_pwpolicy    \"requiresSymbol\"    \"1\"\n#      check_pwpolicy   \"minimumSymbolCharacters\" \"1\"\n      check_pwpolicy    \"RequiresNumeric\"   \"1\"\n#      check_pwpolicy \"minimumNumericCharacters\" \"1\"\n      if [ \"${long_os_version}\" -ge 1014 ]; then\n        check_pwpolicy  \"requiresMixedCase\" \"1\"\n        check_pwpolicy  \"usingHistory\"      \"15\"\n      fi\n      check_pwpolicy    \"maxMinutesUntilChangePassword\"                   \"86400\"\n      check_pwpolicy    \"minChars\"                                        \"15\"\n      check_pwpolicy    \"passwordCannotBeName\"                            \"1\"\n      check_pwpolicy    \"minutesUntilFailedLoginReset\"                    \"0\"\n      check_pwpolicy    \"policyAttributeMaximumFailedAuthentications\"     \"15\"\n    fi\n    if [ \"${os_name}\" = \"FreeBSD\" ]; then\n      check_file_value  \"is\" \"/etc/login.conf\" \"passwd_format\" \"eq\" \"blf\" \"hash\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/password/audit_shadow_group.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_shadow_group\n#\n# Check shadow group\n#\n# Refer to Section(s) 13.20   Page(s) 168-9 CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 6.2.20  Page(s) 287   CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 7.2.4   Page(s) 972-3 CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_shadow_group () {\n  print_function \"audit_shadow_group\"\n  string=\"Shadow Group\"\n  check_message  \"${string}\" \n  if [ \"${os_name}\" = \"Linux\" ]; then\n    check_file=\"/etc/group\"\n    temp_file=\"${temp_dir}/group\"\n    if [ \"${audit_mode}\" = 2 ]; then\n      restore_file \"${check_file}\" \"${restore_dir}\"\n    fi\n    if [ \"${audit_mode}\" != 2 ]; then\n      shadow_check=$( grep -v \"^#\" \"${check_file}\" | grep ^shadow | cut -f4 -d:| wc -c | sed \"s/ //g\" )\n      if [ \"$shadow_check\" != 0 ]; then\n        if [ \"${audit_mode}\" = 1 ]; then\n          inc_insecure \"Shadow group contains members\"\n          fix_message  \"cat ${check_file} |awk -F':' '( \\$1 == \\\"shadow\\\" ) {print \\$1\\\":\\\"\\$2\\\":\\\"\\$3\\\":\\\" ; next}; {print}' > ${temp_file}\"\n          fix_message  \"cat ${temp_file} > ${check_file}\"\n          fix_message  \"rm ${temp_file}\"\n        fi\n        if [ \"${audit_mode}\" = 0 ]; then\n          backup_file \"${check_file}\"\n          command=\"awk -F':' '( \\$1 == \\\"shadow\\\" ) {print \\$1\\\":\\\"\\${2}\\\":\\\"\\${3}\\\":\\\" ; next}; {print}' < \\\"${check_file}\\\" > \\\"${temp_file}\\\"\"\n          command_message \"${command}\"\n          eval \"${command}\"\n          command=\"cat \\\"${temp_file}\\\" > \\\"${check_file}\\\"\"\n          command_message \"${command}\"\n          eval \"${command}\"\n          command=\"rm \\\"${temp_file}\\\"\"\n          command_message \"${command}\"\n          eval \"${command}\"\n        fi\n      else\n        if [ \"${audit_mode}\" = 1 ];then\n          inc_secure \"No members in shadow group\"\n        fi\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/password/audit_smbpasswd_perms.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_smbpasswd_perms\n#\n# Check SMB Password sttings\n#\n# Refer to Section(s) 11.4-5 Page(s) 144-5 CIS Solaris 10 Benchmark v1.1.0\n#.\n\naudit_smbpasswd_perms () {\n  print_function \"audit_smbpasswd_perms\"\n  string=\"SMB Password File\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    check_file_perms \"/etc/sfw/private/smbpasswd\" \"0600\" \"root\" \"root\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/password/audit_system_auth_password_hashing.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_system_auth_password_hashing\n#\n# heck password hashing settings\n#\n# Refer to Section(s) 5.3.4 Page(s) 243   CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 5.3.4 Page(s) 224   CIS Amazon Linux Benchmark v2.0.0\n#.\n\naudit_system_auth_password_hashing () {\n  print_function \"audit_system_auth_password_hashing\"\n  auth_string=\"${1}\"\n  search_string=\"${2}\"\n  temp_file=\"${temp_dir}/audit_system_auth_password_hashing\"\n  check_file=\"/etc/pam.d/common-password\"\n  string=\"Password minimum strength enabled in \\\"${check_file}\\\"\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${audit_mode}\" != 2 ]; then\n      if [ -f \"${check_file}\" ]; then\n        command=\"grep \\\"^${auth_string}\\\" \\\"${check_file}\\\" | grep \\\"${search_string}$\\\" | awk '{print \\$8}'\"\n        command_message     \"${command}\"\n        check_value=$( eval \"${command}\" )\n        lock_command=\"sed 's/^password\\ssufficient\\spam_unix.so/password sufficient pam_unix.so sha512/g' < ${check_file} > ${temp_file} ; cat ${temp_file} > ${check_file} ; rm ${temp_file}\"\n        if [ \"${check_value}\" != \"${search_string}\" ]; then\n          if [ \"${audit_mode}\" = \"1\" ]; then\n            inc_insecure \"Password strength settings not enabled in ${check_file}\"\n            fix_message  \"${lock_command}\"\n          fi\n          if [ \"${audit_mode}\" = 0 ]; then\n            backup_file  \"${check_file}\"\n            lock_message=\"Password minimum length in \\\"${check_file}\\\"\"\n            run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n          fi\n        else\n          if [ \"${audit_mode}\" = \"1\" ]; then\n            inc_secure \"Password strength settings enabled in \\\"${check_file}\\\"\"\n          fi\n        fi\n      fi\n    else\n      restore_file=\"/etc/pam.d/common-password\"\n      restore_file \"${restore_file}\" \"${restore_dir}\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/password/audit_system_auth_password_history.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_system_auth_password_history\n#\n# Check password history settings\n#\n# Refer to Section(s) 6.3.4   Page(s) 141-2 CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 6.3.4   Page(s) 144-5 CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 5.3.3   Page(s) 242   CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 5.3.3   Page(s) 233   CIS Amazon Linux Benchmark v1.2.0\n# Refer to Section(s) 9.3.3   Page(s) 134   CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 7.1.10  Page(s) 952-3 CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_system_auth_password_history () {\n  print_function \"audit_system_auth_password_history\"\n  auth_string=\"${1}\"\n  search_string=\"${2}\"\n  search_value=\"${3}\"\n  temp_file=\"${temp_dir}/audit_system_auth_password_history\"\n  check_file=\"/etc/security/opasswd\"\n  string=\"Password entry \\\"${search_string}\\\" set to \\\"${search_value}\\\" in \\\"${check_file}\\\"\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    check_file_exists \"${check_file}\" \"yes\"\n    for check_file in /etc/security/opasswd /etc/security/opasswd.old; do\n      check_file_perms \"${check_file}\" \"0600\" \"root\" \"root\"\n    done\n    for check_file in /etc/pam.d/common-auth /etc/pam.d/system-auth; do\n      if [ -f \"${check_file}\" ]; then\n        if [ \"${audit_mode}\" != 2 ]; then\n          verbose_message \"Password entry \\\"${search_string}\\\" set to \\\"${search_value}\\\" in \\\"${check_file}\\\"\" \"check\"\n          command=\"grep \\\"^${auth_string}\\\" \\\"${check_file}\\\" | grep \\\"${search_string}$\\\" | awk -F \\\"${search_string}=\\\" '{print \\$2}' | awk '{print \\$1}'\"\n          command_message \"${command}\"\n          check_value=$( eval \"${command}\" )\n          lock_command=\"awk '( \\$1 == \\\"password\\\" && \\$3 == \\\"pam_unix.so\\\" ) { print \\$0 \\\" ${search_string}=${search_value}\\\"; next };' < ${check_file} > ${temp_file} ; cat ${temp_file} > ${check_file} ; rm ${temp_file}\"\n          if [ \"${check_value}\" != \"${search_value}\" ]; then\n            if [ \"${audit_mode}\" = \"1\" ]; then\n              inc_insecure \"Password entry \\\"${search_string}\\\" is not set to \\\"${search_value}\\\" in \\\"${check_file}\\\"\"\n              fix_message  \"${lock_command}\"\n            fi\n            if [ \"${audit_mode}\" = 0 ]; then\n              backup_file  \"${check_file}\"\n              fix_message  \"Password entry in \\\"${check_file}\\\"\"\n              run_lockdown \"${lock_command}\" \"Password entry in ${check_file}\" \"sudo\"\n            fi\n          else\n            if [ \"${audit_mode}\" = \"1\" ]; then\n              inc_secure \"Password entry \\\"${search_string}\\\" set to \\\"${search_value}\\\" in \\\"${check_file}\\\"\"\n            fi\n          fi\n        else\n          for restore_file in /etc/pam.d/common-auth /etc/pam.d/system-auth; do\n            restore_file \"${restore_file}\" \"${restore_dir}\"\n          done \n        fi\n      fi\n    done\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/password/audit_system_auth_password_policy.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_system_auth_password_policy\n#\n# Check password policy settings\n#\n# Refer to Section(s) 6.3.2 Page(s) 139-140 CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 6.3.2 Page(s) 142-3   CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 9.3.1 Page(s) 132-3   CIS SLES 11 Benchmark v1.0.0\n#.\n\naudit_system_auth_password_policy () {\n  print_function \"audit_system_auth_password_policy\"\n  auth_string=\"${1}\"\n  search_string=\"${2}\"\n  search_value=\"${3}\"\n  temp_file=\"${temp_dir}/audit_system_auth_password_policy\"\n  string=\"Password policy\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${audit_mode}\" != 2 ]; then\n      for check_file in /etc/pam.d/common-auth /etc/pam.d/system-auth; do\n        if [ -f \"${check_file}\" ]; then\n          verbose_message \"Password \\\"${search_string}\\\" is set to \\\"${search_value}\\\" in \\\"${check_file}\\\"\" \"check\"\n          command=\"grep \\\"^${auth_string}\\\" \\\"${check_file}\\\" | grep \\\"${search_string}$\\\" | awk -F \\\"${search_string}=\\\" '{print \\$2}' | awk '{print \\$1}'\"\n          command_message     \"${command}\"\n          check_value=$( eval \"${command}\" )\n          lock_command=\"awk '( \\$1 == \\\"password\\\" && \\$2 == \\\"requisite\\\" && \\$3 == \\\"pam_cracklib.so\\\" ) { print \\$0  \\\" dcredit=-1 lcredit=-1 ocredit=-1 ucredit=-1 minlen=9\\\"; next }; { print }' < ${check_file} > ${temp_file} ; cat ${temp_file} > ${check_file} ; rm ${temp_file}\"\n          if [ \"${check_value}\" != \"${search_value}\" ]; then\n            if [ \"${audit_mode}\" = \"1\" ]; then\n              inc_insecure \"Password \\\"${search_string}\\\" is not set to \\\"${search_value}\\\" in \\\"${check_file}\\\"\"\n              fix_message  \"${lock_command}\"\n            fi\n            if [ \"${audit_mode}\" = 0 ]; then\n              backup_file  \"${check_file}\"\n              lock_message=\"Password \\\"${search_string}\\\" to \\\"${search_value}\\\" in \\\"${check_file}\\\"\"\n              run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n            fi\n          else\n            if [ \"${audit_mode}\" = \"1\" ]; then\n              inc_secure \"Password \\\"${search_string}\\\" set to \\\"${search_value}\\\" in \\\"${check_file}\\\"\"\n            fi\n          fi\n        fi\n      done\n    else\n      for check_file in /etc/pam.d/common-auth /etc/pam.d/system-auth; do\n        restore_file \"${check_file}\" \"${restore_dir}\"\n      done\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/password/audit_system_auth_password_strength.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_system_auth_password_strength\n#\n# Check password minimum strength enabled\n#.\n\naudit_system_auth_password_strength () {\n  print_function \"audit_system_auth_password_strength\"\n  auth_string=\"${1}\"\n  search_string=\"${2}\"\n  temo_file=\"${temp_dir}/audit_system_auth_password_strength\"\n  string=\"Password minimum strength\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${audit_mode}\" != 2 ]; then\n      for check_file in /etc/pam.d/common-auth /etc/pam.d/system-auth; do\n        if [ -f \"${check_file}\" ]; then\n          verbose_message \"Password minimum strength enabled in \\\"${check_file}\\\"\" \"check\"\n          command=\"grep \\\"^${auth_string}\\\" \\\"${check_file}\\\" | grep \\\"${search_string}$\\\" | awk '{print \\$8}'\"\n          command_message     \"${command}\"\n          check_value=$( eval \"${command}\" )\n          lock_command=\"sed 's/^password.*pam_deny.so$/&\\npassword\\t\\trequisite\\t\\t\\tpam_passwdqc.so min=disabled,disabled,16,12,8/' < ${check_file} > ${temo_file} ; cat ${temp_file} > ${check_file} ; rm ${temp_file}\"\n          if [ \"${check_value}\" != \"${search_string}\" ]; then\n            if [ \"${audit_mode}\" = \"1\" ]; then\n              inc_insecure \"Password strength settings not enabled in \\\"${check_file}\\\"\"\n              fix_message  \"${lock_command}\"\n            fi\n            if [ \"${audit_mode}\" = 0 ]; then\n              backup_file  \"${check_file}\"\n              lock_message=\"Password minimum length in \\\"${check_file}\\\"\"\n              run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n            fi\n          else\n            if [ \"${audit_mode}\" = \"1\" ]; then\n              inc_secure \"Password strength settings enabled in \\\"${check_file}\\\"\"\n            fi\n          fi\n        fi\n      done\n    else\n      for check_file in /etc/pam.d/common-auth /etc/pam.d/system-auth; do\n        restore_file \"${check_file}\" \"${restore_dir}\"\n      done\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/power/audit_power_management.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_power_management\n#\n# Refer to Section(s) 2.12.5 Page(s) 209-210 CIS AIX Benchmark v1.1.0\n# Refer to Section(s) 10.1   Page(s) 91-2    CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 10.3   Page(s) 139     CIS Solaris 10 Benchmark v1.1.0\n#.\n\naudit_power_management () {\n  print_function \"audit_power_management\"\n  string=\"Power Management\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"AIX\" ]; then\n    if [ \"${os_name}\" = \"AIX\" ]; then\n      check_itab \"pmd\" \"off\"\n    fi\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      if [ \"${os_version}\" = \"10\" ]; then\n        check_file_value \"is\" \"/etc/default/power\" \"PMCHANGEPERM\"  \"eq\" \"-\" \"hash\"\n        check_file_value \"is\" \"/etc/default/power\" \"CPRCHANGEPERM\" \"eq\" \"-\" \"hash\"\n      fi\n      if [ \"${os_version}\" = \"11\" ]; then\n        command=\"poweradm list | grep suspend | awk '{print \\$2}' | cut -f2 -d\\\"=\\\"\"\n        command_message       \"${command}\"\n        poweradm_test=$( eval \"${command}\" )\n        log_file=\"poweradm.log\"\n        if [ \"${audit_mode}\" = 2 ]; then\n          restore_file=\"${restore_dir}/#log_file\"\n          if [ -f \"${log_file}\" ]; then\n            restore_value=$( cat \"${restore_file}\" )\n            if [ \"${poweradm_test}\" != \"${restore_value}\" ]; then\n              restore_message \"Power suspend to \\\"${restore_value}\\\"\"\n              eval \"poweradm set suspend-enable=${restore_value}\"\n              eval \"poweradm update\"\n            fi\n          fi\n        fi\n        if [ \"${poweradm_test}\" != \"false\" ]; then\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_insecure \"Power suspend enabled\"\n            fix_message  \"poweradm set suspend-enable=false\"\n            fix_message  \"poweradm update\"\n          fi\n          if [ \"${audit_mode}\" = 0 ]; then\n            backup_file=\"${work_dir}/${log_file}\"\n            set_message \"Power suspend to disabled\"\n            echo \"${poweradm_test}\" > \"${backup_file}\"\n            eval \"poweradm set suspend-enable=false\"\n            eval \"poweradm update\"\n          fi\n        else\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_secure \"Power suspend disabled\"\n          fi\n        fi\n      fi\n    fi\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      check_linux_service \"apmd\" \"off\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/print/audit_cups.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_cups\n#\n# Check CUPS\n#\n# Refer to Section(s) 3.4     Page(s) 61    CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 3.4     Page(s) 73-4  CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 3.4     Page(s) 64    CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 2.2.4   Page(s) 104   CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 6.3     Page(s) 53-4  CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 2.2.4   Page(s) 96    CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 2.2.3   Page(s) 104   CIS Ubuntu 16.04 Benchmark v1.0.0\n# Refer to Section(s) 2.1.11  Page(s) 257-9 CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_cups () {\n  print_function \"audit_cups\"\n  string=\"Printing Services\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    for service_name in cups cups-lpd cupsrenice; do\n      check_linux_service \"${service_name}\" \"off\"\n    done\n    check_file_perms      \"/etc/init.d/cups\"      \"0744\"  \"root\"  \"root\"\n    check_file_perms      \"/etc/cups/client.conf\" \"0644\"  \"root\"  \"lp\"\n    check_file_perms      \"/etc/cups/cupsd.conf\"  \"0600\"  \"lp\"    \"sys\"\n    check_file_value \"is\" \"/etc/cups/cupsd.conf\"  \"User\"  \"space\" \"lp\"    \"hash\"\n    check_file_value \"is\" \"/etc/cups/cupsd.conf\"  \"Group\" \"space\" \"sys\"   \"hash\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/print/audit_ppd_cache.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_ppd_cache\n#\n# Cache for Printer Descriptions. Not required unless using print services.\n#.\n\naudit_ppd_cache () {\n  print_function \"audit_ppd_cache\"\n  string=\"PPD Cache\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ]; then\n      check_sunos_service \"svc:/application/print/ppd-cache-update:default\" \"disabled\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/print/audit_print.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_print\n#\n# Refer to Section(s) 3.14    Page(s) 14-15 CIS FreeBSD Benchmark v1.0.5\n# Refer to Section(s) 1.3.1-2 Page(s) 34-36 CIS AIX Benchmark v1.1.0\n# Refer to Section(s) 2.1.7   Page(s) 22    CIS Solaris 10 Benchmark v5.1.0\n#.\n\naudit_print () {\n  print_function \"audit_print\"\n  string=\"Printing Daemons\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"FreeBSD\" ] || [ \"${os_name}\" = \"AIX\" ]; then\n    if [ \"${os_name}\" = \"AIX\" ]; then\n      check_itab \"qdaemon\" \"off\"\n      check_itab \"lpd\"     \"off\"\n      check_itab \"piobe\"   \"off\"\n    fi\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      if [ \"${os_version}\" = \"10\" ]; then\n        check_sunos_service \"svc:/application/print/ipp-listener:default\" \"disabled\"\n        check_sunos_service \"svc:/application/print/rfc1179\"              \"disabled\"\n        check_sunos_service \"svc:/application/print/server:default\"       \"disabled\"\n      fi\n    fi\n    if [ \"${os_name}\" = \"FreeBSD\" ]; then\n      check_file_value      \"is\" \"/etc/rc.conf\" \"lpd_enable\" \"eq\" \"NO\"    \"hash\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/print/audit_printer_sharing.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_printer_sharing\n#\n# Refer to Section(s) 2.2.4   Page(s) 19-20 CIS Apple OS X 10.8  Benchmark v1.0.0\n# Refer to Section(s) 2.2.4   Page(s) 41    CIS Apple OS X 10.12 Benchmark v1.0.0\n# Refer to Section(s) 2.3.3.4 Page(s) 98-9  CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n# Refer to http://support.apple.com/kb/PH11450\n#\n# Printer sharing can be disabled via: cupsctl --no-share-printers\n# Need to update this code\n#.\n\naudit_printer_sharing () {\n  print_function \"audit_printer_sharing\"\n  string=\"Printer Sharing\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${audit_mode}\" != 2 ]; then\n      if [ \"${long_os_version}\" -ge 1014 ]; then\n        command=\"/usr/bin/sudo /usr/sbin/cupsctl | grep -c \\\"_share_printers=0\\\"\"\n        command_message      \"${command}\"\n        printer_test=$( eval \"${command}\" )\n      else\n        command=\"system_profiler SPPrintersDataType | grep Shared | awk '{print \\$2}' | grep -c 'Yes' | sed \\\"s/ //g\\\"\"\n        command_message      \"${command}\"\n        printer_test=$( eval \"${command}\" )\n      fi\n      if [ \"${printer_test}\" = \"0\" ]; then\n        inc_insecure \"Printer sharing is enabled\"\n        fix_message  \"Open System Preferences\"\n        fix_message  \"Select Sharing\"\n        fix_message  \"Uncheck Printer Sharing\"\n      else\n        inc_secure   \"Printer Sharing is disabled\"\n      fi\n    else\n      fix_message    \"Open System Preferences\"\n      fix_message    \"Select Sharing\"\n      fix_message    \"Uncheck Printer Sharing\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/remote/audit_remote_consoles.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_remote_consoles\n#\n# Check remote consoles\n#\n# Refer to Section(s) 9.1 Page(s) 72  CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 9.1 Page(s) 116 CIS Solaris 10 Benchmark v5.1.0\n#.\n\naudit_remote_consoles () {\n  print_function \"audit_remote_consoles\"\n  string=\"Remote Consoles\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${my_id}\" != \"0\" ] && [ \"${use_sudo}\" = \"0\" ]; then\n      verbose_message \"Requires sudo to check\" \"notice\"\n      return\n    fi\n    log_file=\"remoteconsoles.log\"\n    if [ \"${audit_mode}\" != 2 ]; then\n      disable_ttys=0\n      log_file=\"${work_dir}/${log_file}\"\n      command=\"/usr/sbin/consadm -p\"\n      command_message      \"${command}\"\n      console_list=$( eval \"${command}\" )\n      for console_device in $console_list; do\n        disable_ttys=1\n        if [ \"${audit_mode}\" = 1 ]; then\n          inc_insecure \"Console enabled on \\\"${console_device}\\\"\"\n          fix_message  \"consadm -d ${console_device}\"\n        fi\n        if [ \"${audit_mode}\" = 0 ]; then\n          echo \"${console_device}\" >> \"${log_file}\"\n          set_message \"Console disabled on \\\"${console_device}\\\"\"\n          command=\"consadm -d \\\"${console_device}\\\"\"\n          command_message \"${command}\"\n          eval \"${command}\"\n        fi\n      done\n      if [ \"${disable_ttys}\" = 0 ]; then\n        if [ \"${audit_mode}\" = 1 ]; then\n          inc_secure  \"No remote consoles enabled\"\n        fi\n      fi\n    else\n      restore_file=\"${restore_dir}${log_file}\"\n      if [ -f \"${restore_file}\" ]; then\n        command=\"cat \\\"${restore_file}\\\"\"\n        command_message      \"${command}\"\n        restore_list=$( eval \"${command}\" )\n        for console_device in ${restore_list}; do\n          restore_message \"Console to enabled on \\\"${console_device}\\\"\"\n          command=\"consadm -a \\\"${console_device}\\\"\"\n          command_message \"${command}\"\n          eval \"${command}\"\n        done\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/remote/audit_remote_info.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_remote_info\n#\n# Turn off remote info services like rstat and finger\n#\n# Refer to Section(s) 1.3.16 Page(s) 52-3 CIS AIX Benchmark v1.1.0\n#.\n\naudit_remote_info () {\n  print_function \"audit_remote_info\"\n  string=\"Remote Information Services\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"AIX\" ]; then\n    if [ \"${os_name}\" = \"AIX\" ]; then\n      check_rctcp \"rwhod\" \"off\"\n    fi\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n        check_sunos_service \"svc:/network/rpc/rstat:default\"  \"disabled\"\n        check_sunos_service \"svc:/network/nfs/rquota:default\" \"disabled\"\n        check_sunos_service \"svc:/network/rpc/rusers:default\" \"disabled\"\n        check_sunos_service \"svc:/network/finger:default\"     \"disabled\"\n        check_sunos_service \"svc:/network/rpc/wall:default\"   \"disabled\"\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/remote/audit_remote_management.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_remote_management\n#\n# Check remote management\n#\n# Refer to Section(s) 2.2.9   Page(s) 25-6  CIS Apple OS X 10.8  Benchmark v1.0.0\n# Refer to Section(s) 2.2.9   Page(s) 48-9  CIS Apple OS X 10.12 Benchmark v1.0.0\n# Refer to Section(S) 2.3.3.6 Page(s) 104-5 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_remote_management () {\n  print_function \"audit_remote_management\"\n  string=\"Remote Management\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${audit_mode}\" != 2 ]; then\n      command=\"launchctl list |awk '{print \\$3}' |grep -c ARDAgent |sed \\\"s/ //g\\\"\"\n      command_message      \"${command}\"\n      actual_value=$( eval \"${command}\" )\n      if [ \"${actual_value}\" = \"1\" ]; then\n        inc_insecure \"Remote Management is enabled\"\n        fix_message  \"Open System Preferences\"\n        fix_message  \"Select Sharing\"\n        fix_message  \"Uncheck Remote Management\"\n      else\n        inc_secure   \"Remote Management is disabled\"\n      fi\n    else\n      fix_message    \"Open System Preferences\"\n      fix_message    \"Select Sharing\"\n      fix_message    \"Uncheck Remote Management\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/remote/audit_remote_shell.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_remote_shell\n#\n# Turn off remote shell services\n#\n# Refer to Section(s) 1.2.7,9 Page(s) 31,33 CIS AIX Benchmark v1.1.0\n#.\n\naudit_remote_shell () {\n  print_function \"audit_remote_shell\"\n  string=\"Remote Shell\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"AIX\" ] || [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${os_name}\" = \"AIX\" ]; then\n      check_chsec \"/etc/security/user\" \"root\" \"rlogin\" \"false\"\n      for user_name in daemon bin sys adm uucp nobody lpd; do\n        check_chuser \"login\" \"false\" \"rlogin\" \"false\" \"${user_name}\"\n      done\n    fi\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n        for service_name in \"svc:/network/shell:kshell\" \\\n          \"svc:/network/login:eklogin\"   \"svc:/network/login:klogin\" \\\n          \"svc:/network/rpc/rex:default\" \"svc:/network/rexec:default\" \\\n          \"svc:/network/shell:default\"   \"svc:/network/login:rlogin\" \\\n          \"svc:/network/telnet:default\"; do\n          check_sunos_service \"${service_name}\" \"disabled\"\n        done\n      fi\n    fi\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      for service_name in telnet login rlogin rsh shell; do\n        check_linux_service \"${service_name}\" \"off\"\n      done\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/remote/audit_vnc.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_vnc\n#\n# Turn off VNC\n#.\n\naudit_vnc () {\n  print_function \"audit_vnc\"\n  string=\"VNC Daemons\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n        check_sunos_service \"svc:/application/x11/xvnc-inetd:default\" \"disabled\"\n      fi\n    fi\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      check_linux_service   \"vncserver\" \"off\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/rpc/audit_nobody_rpc.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_nobody_rpc\n#\n# Check Nobody Access for RPC Encryption Key Storage Service\n#\n# Refer to Section(s) 6.2 Page(s) 47 CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 6.3 Page(s) 88 CIS Solaris 10 Benchmark v5.1.0\n#.\n\naudit_nobody_rpc () {\n  print_function \"audit_nobody_rpc\"\n  string=\"Nobody Access for RPC Encryption Key Storage Service\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ]; then\n      check_file_value \"is\" \"/etc/default/keyserv\" \"ENABLE_NOBODY_KEYS\" \"eq\"  \"NO\" \"hash\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/rpc/audit_rpc_bind.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_rpc_bind\n#\n# Check that rpc bind has tcp wrappers enabled in case it's turned on.\n#\n# Refer to Section(s) 2.2.14 Page(s) 34-5 CIS Solaris 10 Benchmark v5.1.0\n#.\n\naudit_rpc_bind () {\n  print_function \"audit_rpc_bind\"\n  string=\"RPC Bind\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n      audit_svccfg_value  \"svc:/network/rpc/bind\" \"config/enable_tcpwrappers\" \"true\"\n    fi\n    if [ \"${os_version}\" = \"11\" ]; then\n      check_sunos_service \"svc:/network/rpc/bind\" \"disabled\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/rsh/audit_rsh_client.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_rsh_client\n#\n# Check RSH client\n#\n# Refer to Section(s) 2.1.4 Page(s) 49    CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 2.1.4 Page(s) 57    CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 2.1.4 Page(s) 52-3  CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 2.3.2 Page(s) 125   CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 5.1.4 Page(s) 42-3  CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 2.3.2 Page(s) 112   CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 2.3.2 Page(s) 121   CIS Ubuntu 16.04 Benchmark v1.0.0\n# Refer to Section(s) 2.2.2 Page(s) 294-5 CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_rsh_client () {\n  print_function \"audit_rsh_client\"\n  string=\"RSH Client\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    check_linux_package \"uninstall\" \"rsh\"\n    check_linux_package \"uninstall\" \"rsh-client\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/rsh/audit_rsh_server.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_rsh_server\n#\n# check RSH server\n#\n# Refer to Section(s) 2.1.3  Page(s) 48   CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 2.1.3  Page(s) 56-7 CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 2.1.3  Page(s) 51-2 CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 2.2.17 Page(s) 118  CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 5.1.3  Page(s) 41-2 CIS SLES 11 Benchmark v1.0.0\n#.\n\naudit_rsh_server () {\n  print_function \"audit_rsh_server\"\n  string=\"RSH Server Daemon\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${os_vendor}\" = \"CentOS\" ] || [ \"${os_vendor}\" = \"Red\" ] || [ \"${os_vendor}\" = \"Amazon\" ]; then\n      for service_name in rsh.socket rlogin.socket rexec.socket; do\n        check_linux_service \"${service_name}\" \"off\"\n      done\n      check_linux_package   \"uninstall\"       \"rsh-server\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/security/audit_secure_empty_trash.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_secure_empty_trash\n#\n# Check secure empty trash settings\n#\n# Refer to Section(s) 2.8 Page(s) 33 CIS Apple OS X 10.8 Benchmark v1.0.0\n#.\n\naudit_secure_empty_trash () {\n  print_function \"audit_secure_empty_trash\"\n  string=\"Secure Empty Trash\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    check_osx_defaults_int \"com.apple.finder\" \"EmptyTrashSecurely\" \"1\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/security/audit_secure_keyboard_entry.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_secure_keyboard_entry\n#\n# Check secure keyboard entry settings\n#\n# Refer to Section(s) 2.8   Page(s) 33    CIS Apple OS X 10.8 Benchmark v1.0.0\n# Refer to Section(S) 2.10  Page(s) 81    CIS Apple OS X 10.12 Benchmark v1.0.0\n# Refer to Section(s) 6.4.1 Page(s) 413-6 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_secure_keyboard_entry () {\n  print_function \"audit_secure_keyboard_entry\"\n  string=\"Secure Keyboard Entry\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    check_osx_defaults_int \"Terminal\" \"SecureKeyboardEntry\" \"1\" \"int\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/security/audit_secure_swap.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_secure_swap\n#\n# Check secure swap settings\n#\n# Refer to Section(s) 1.4.13.6 Page(s) 47-8 CIS Apple OS X 10.6 Benchmark v1.0.0\n#.\n\naudit_secure_swap () {\n  print_function \"audit_secure_swap\"\n  string=\"Secure Swap\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ]; then\n    check_osx_defaults_bool \"/Library/Preferences/com.apple.virtualMemory\" \"UseEncryptedSwap\" \"yes\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/services/audit_inetd.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_inetd\n#\n# Check inetd\n#\n# Refer to Section(s) 10.6 Page(s) 141-2 CIS Solaris 10 Benchmark v1.1.0\n#.\n\naudit_inetd () {\n  print_function \"audit_inetd\"\n  string=\"Inetd\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n      check_sunos_service \"svc:/network/inetd:default\" \"disabled\"\n    fi\n  else\n    na_message \"Inetd\"\n  fi\n}\n"
  },
  {
    "path": "modules/services/audit_ipmi.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_ipmi\n#\n# Turn off ipmi environment daemon\n#.\n\naudit_ipmi () {\n  print_function \"audit_ipmi\"\n  string=\"IPMI\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n        check_sunos_service \"svc:/network/ipmievd:default\" \"disabled\"\n      fi\n    fi\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      check_linux_service \"ipmi\" \"off\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/services/audit_ipv6.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_ipv6\n#\n# Check IPv6\n#\n# Refer to Section(s) 1.3.11,22-3 Page(s) 47,60-2 CIS AIX Benchmark v1.1.0\n# Refer to Section(s) 4.4.2       Page(s) 94      CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 4.4.2       Page(s) 85-6    CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 7.3.3       Page(s) 76      CIS SLES 11 Benchmark v1.0.0\n#.\n\naudit_ipv6 () {\n  print_function \"audit_ipv6\"\n  string=\"IPv6\"\n  check_message  \"${string}\"\n  if [ \"$ipv6_disable\" = \"yes\" ]; then\n    if [ \"${os_name}\" = \"AIX\" ]; then\n      for service_name in autoconf6 ndpd-host ndpd-router; do\n        check_rctcp \"${service_name}\" \"off\"\n      done\n    fi\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      if [ \"$disable_ipv6\" = \"yes\" ]; then\n        check_append_file \"/etc/modprobe.conf\" \"options ipv6 \\\"disable=1\\\"\" \"hash\"\n        if [ \"${os_vendor}\" = \"CentOS\" ] || [ \"${os_vendor}\" = \"Red\" ]; then\n          check_file_value \"is\" \"/etc/sysconfig/network\" \"NETWORKING_IPV6\" \"eq\" \"no\" \"hash\"\n          check_file_value \"is\" \"/etc/sysconfig/network\" \"IPV6INIT\"        \"eq\" \"no\" \"hash\"\n        fi\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/services/audit_iscsi.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_iscsi\n#\n# Turn off iscsi target\n#.\n\naudit_iscsi () {\n  print_function \"audit_iscsi\"\n  string=\"iSCSI Target Service\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n        check_sunos_service \"svc:/system/iscsitgt:default\" \"disabled\"\n      fi\n    fi\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      check_linux_service \"iscsi\"  \"off\"\n      check_linux_service \"iscsid\" \"off\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/services/audit_legacy.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_legacy\n#\n# Check legacy services\n#\n# Refer to Section(s) 2.1-8        Page(s) 4-8        CIS FreeBSD Benchmark v1.0.5\n# Refer to Section(s) 1.3.17,24-52 Page(s) 54-5,63-96 CIS AIX Benchmark v1.1.0\n# Refer to Section(s) 4.5          Page(s) 38-9       CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 2.1.1-10     Page(s) 88-97      CIS Ubuntu 16.04 Benchmark v1.0.0\n# Refer to Section(s) 5.2-11       Page(s) 46-51      CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 2.1.1-9      Page(s) 79-87      CIS Amazon Linux Benchmark v2.0.0\n#.\n\naudit_legacy_inet () {\n  print_function \"audit_legacy_inet\"\n  string=\"Inet Services\"\n  check_message  \"${string}\"\n  for service_name in time echo discard daytime chargen fs dtspc \\\n    exec comsat talk finger uucp name xaudio netstat ufsd rexd \\\n    systat sun-dr uuidgen krb5_prop 100068 100146 100147 100150 \\\n    100221 100232 100235 kerbd rstatd rusersd sprayd walld \\\n    printer shell login telnet ftp tftp 100083 100229 100230  \\\n    100242 100234 100134 100155 rquotad 100424 100422; do\n    check_inetd_service \"${service_name}\" \"disabled\"\n  done\n}\n\naudit_legacy_init () {\n  print_function \"audit_legacy_init\"\n  string=\"Init Services\"\n  check_message  \"${string}\"\n  for service_name in llc2 pcmcia ppd slpd boot.server autoinstall \\\n    power bdconfig cachefs.daemon cacheos.finish asppp uucp flashprom \\\n    PRESERVE ncalogd ncad ab2mgr dmi mipagent nfs.client autofs rpc \\\n    directory ldap.client lp spc volmgt dtlogin ncakmod samba dhcp \\\n    nfs.server kdc.master kdc apache snmpdx; do\n    check_initd_service \"${service_name}\" \"disabled\"\n  done\n}\n\naudit_legacy () {\n  print_function 'audit_legacy'\n  string=\"Legacy Inet/Init Services\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"FreeBSD\" ] || [ \"${os_name}\" = \"AIX\" ]; then\n    if [ \"${os_name}\" = \"AIX\" ]; then\n      check_rctcp     \"timed\"      \"off\"\n      check_subserver \"telnet\"     \"tcp6\"       \"off\"\n      check_subserver \"exec\"       \"tcp6\"       \"off\"\n      check_subserver \"daytime\"    \"udp\"        \"off\"\n      check_subserver \"shell\"      \"tcp6\"       \"off\"\n      check_subserver \"cmsd\"       \"sunrpc_tcp\" \"off\"\n      check_subserver \"ttdbserver\" \"sunrpc_tcp\" \"off\"\n      check_subserver \"uucp\"       \"tcp\"        \"off\"\n      check_subserver \"time\"       \"udp\"        \"off\"\n      check_subserver \"login\"      \"tcp\"        \"off\"\n      check_subserver \"talk\"       \"udp\"        \"off\"\n      check_subserver \"ntalk\"      \"udp\"        \"off\"\n      check_subserver \"ftp\"        \"tcp6\"       \"off\"\n      check_subserver \"chargen\"    \"tcp\"        \"off\"\n      check_subserver \"discard\"    \"tcp\"        \"off\"\n      check_subserver \"dtspc\"      \"tcp\"        \"off\"\n      check_subserver \"echo\"       \"tcp\"        \"off\"\n      check_subserver \"echo\"       \"udp\"        \"off\"\n      check_subserver \"pcnfsd\"     \"udp\"        \"off\"\n      check_subserver \"rstatd\"     \"udp\"        \"off\"\n      check_subserver \"rusersd\"    \"udp\"        \"off\"\n      check_subserver \"rwalld\"     \"udp\"        \"off\"\n      check_subserver \"sprayd\"     \"udp\"        \"off\"\n      check_subserver \"klogin\"     \"tcp\"        \"off\"\n      check_subserver \"rquotad\"    \"udp\"        \"off\"\n      check_subserver \"tftp\"       \"udp\"        \"off\"\n      check_subserver \"imap2\"      \"tcp\"        \"off\"\n      check_subserver \"pop3\"       \"tcp\"        \"off\"\n      check_subserver \"finger\"     \"tcp\"        \"off\"\n      check_subserver \"instsrv\"    \"tcp\"        \"off\"\n    else\n      if [ \"${os_name}\" = \"SunOS\" ]; then\n        if [ \"${os_version}\" != \"11\" ]; then\n          audit_legacy_inet\n          audit_legacy_init\n        fi\n      else\n        audit_legacy_inet\n        audit_legacy_init\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/services/audit_other_daemons.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_other_daemons\n#\n# Check chkconfig and other daemons\n#\n# Refer to Section(s) 1.2.4-5       Page(s) 36-7    CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 1.2.4-5       Page(s) 34-5    CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 1.2.5,2.2.11  Page(s) 53,122  CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 6.16          Page(s) 63-4    CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 2.2.11        Page(s) 103     CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 2.1.13        Page(s) 264-4   CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_other_daemons () {\n  print_function \"audit_other_daemons\"\n  string=\"Miscellaneous Services\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    for service_name in wu-ftpd ftp vsftpd aaeventd tftp acpid \\\n      amd arptables_jg arpwatch atd netfs irda isdn bluetooth \\\n      capi conman cpuspeed cryrus-imapd dc_client dc_server \\\n      dhcdbd dhcp6s dhcrelay chargen chargen-udp dovecot dund \\\n      gpm hidd hplip ibmasm innd ip6tables lisa lm_sensors \\\n      mailman mctrans mdmonitor mdmpd microcode_ctl mysqld \\\n      netplugd network NetworkManager openibd yum-updatesd \\\n      pand postfix psacct mutipathd daytime daytime-udp radiusd \\\n      radvd rdisc readahead_early readahead_later rhnsd rpcgssd \\\n      rpcimapd rpcsvcgssd rstatd rusersd rwhod saslauthd \\\n      settroubleshoot smartd spamassasin echo echo-udp time \\\n      time-udp vnc svcgssd rpmconfigcheck rsh rsync rsyncd \\\n      saslauthd powerd raw rexec rlogin rpasswdd openct \\\n      ipxmount joystick esound evms fam gpm gssd pcscd \\\n      tog-pegasus tux wpa_supplicant zebra ncpfs; do\n      check_linux_service \"${service_name}\" \"off\"\n    done\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/services/audit_postgresql.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_postgresql\n#\n# Turn off postgresql if not required\n# Recommend removing this from base install as it slows down patching significantly\n#.\n\naudit_postgresql () {\n  print_function \"audit_postgresql\"\n  string=\"PostgreSQL Database\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n        for service_name in \"svc:/application/database/postgresql_83:default_32bit\" \\\n          \"svc:/application/database/postgresql_83:default_64bit\" \\\n          \"svc:/application/database/postgresql:version_81\" \\\n          \"svc:/application/database/postgresql:version_82\" \\\n          \"svc:/application/database/postgresql:version_82_64bit\"; do\n          check_sunos_service \"${service_name}\" \"disabled\"\n        done\n      fi\n    fi\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      check_linux_service \"postgresql\" \"off\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/services/audit_rarp.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_rarp\n#\n# rarp: Turn off rarp if not in use\n# rarp is required for jumpstart servers\n#.\n\naudit_rarp () {\n  print_function \"audit_rarp\"\n  string=\"RARP Daemon\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n        check_sunos_service \"svc:/network/rarp:default\" \"disabled\"\n      fi\n    fi\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      check_linux_service \"rarpd\" \"off\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/services/audit_snmp.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_snmp\n#\n# Check SNMP configuration\n#\n# Refer to Section(s) 3.15        Page(s) 69         CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 3.15        Page(s) 81-2       CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 3.15        Page(s) 71-2       CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 2.2.14      Page(s) 114        CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 6.14        Page(s) 61-2       CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 1.3.7,18-21 Page(s) 41-2,55-60 CIS AIX Benchmark v1.1.0\n# Refer to Section(s) 1.13        Page(s) 43-4       CIS ESX Server 4 Benchmark v1.1.0\n# Refer to Section(s) 2.2.14      Page(s) 106        CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 2.2.14      Page(s) 114        CIS Ubuntu 16.04 Benchmark v1.0.0\n# Refer to Section(s) 2.1.15      Page(s) 267-9      CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_snmp () {\n  print_function \"audit_snmp\"\n  string=\"SNMP Daemons and Log Permissions\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"AIX\" ] || [ \"${os_name}\" = \"VMkernel\" ]; then\n    if [ \"$snmpd_disable\" = \"yes\" ]; then\n      if [ \"${os_name}\" = \"VMkernel\" ]; then\n        log_file=\"snmpstatus\"\n        backup_file=\"${work_dir}/${log_file}\"\n        current_value=$( esxcli system snmp get | grep Enable | awk '{print $2}' )\n        if [ \"${audit_mode}\" != \"2\" ]; then\n          if [ \"${current_value}\" = \"true\" ]; then\n            if [ \"${audit_mode}\" = \"0\" ]; then\n              echo \"${current_value}\" > \"${backup_file}\"\n              verbose_message \"SNMP to disabled\" \"set\"\n              esxcli system snmp set --enable=\"false\"\n            fi\n            if [ \"${audit_mode}\" = \"1\" ]; then\n              inc_insecure \"SNMP is not enabled\"\n              fix_message  \"esxcli system snmp set --enable=\\\"false\\\"\"\n            fi\n          else\n            if [ \"${audit_mode}\" = \"1\" ]; then\n              inc_secure \"SNMP is disabled\"\n            fi\n          fi\n        else\n          restore_file=\"${restore_dir}/${log_file}\"\n         if [ -f \"${restore_file}\" ]; then\n            previous_value=$( cat \"${restore_file}\" )\n            if [ \"${previous_value}\" != \"${current_value}\" ]; then\n              verbose_message \"Restoring: SNMP to ${previous_value}\"\n              esxcli system snmp set --enable=\"${previous_value}\"\n            fi\n          fi\n        fi\n      fi\n      if [ \"${os_name}\" = \"AIX\" ]; then\n        for service_name in snmpd dpid2 hostmibd snmpmibd aixmibd; do\n          check_rctcp \"${service_name}\" \"off\"\n        done\n        for check_file in /var/tmp/snmpd.log /var/tmp/hostmibd.log \\\n        /var/tmp/dpid2.log /var/ct/RMstart.log /smit.log; do\n          check_file_perms \"${check_file}\" \"0640\" \"root\" \"system\"\n        done\n        check_file_perms \"/var/adm/ras\" \"0700\" \"root\" \"system\"\n      fi\n      if [ \"${os_name}\" = \"SunOS\" ]; then\n        verbose_message \"SNMP Daemons\" \"check\"\n        if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n          for service_name in \"svc:/application/management/seaport:default\" \\\n            \"svc:/application/management/snmpdx:default\" \\\n            \"svc:/application/management/dmi:default\" \\\n            \"svc:/application/management/sma:default\"; do\n            check_sunos_service \"${service_name}\" \"disabled\"\n          done\n        else\n          for service_name in init.dmi init.sma init.snmpdx; do\n            check_sunos_service \"${service_name}\" \"disabled\"\n          done\n        fi\n      fi\n      if [ \"${os_name}\" = \"Linux\" ]; then\n        for service_name in snmp snmptrapd; do\n          check_linux_service \"${service_name}\" \"off\"\n        done\n        check_append_file   \"/etc/snmp/snmpd.conf\" \"com2sec notConfigUser default public\" \"hash\"\n        check_linux_package \"uninstall\" \"net-snmp\"\n      fi\n    else\n      if [ \"${os_name}\" = \"AIX\" ]; then\n        for check_file in /var/tmp/snmpd.log /var/tmp/hostmibd.log \\\n        /var/tmp/dpid2.log /var/ct/RMstart.log /smit.log; do\n          check_file_perms \"${check_file}\" \"0640\" \"root\" \"system\"\n        done\n        check_file_perms   \"/var/adm/ras\"  \"0700\" \"root\" \"system\"\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/services/audit_unconfined_daemons.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2009\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_unconfined_daemons\n#\n# Check for unconfined daemons\n#\n# Refer to Section(s) 1.4.6   Page(s) 40   CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 1.4.6   Page(s) 45-6 CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 1.4.6   Page(s) 43   CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 1.6.1.4 Page(s) 68   CIS Ubuntu 16.04 Benchmark v1.0.0\n#.\n\naudit_unconfined_daemons () {\n  print_function \"audit_unconfined_daemons\"\n  string=\"Unconfined Daemons\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    command=\"ps -eZ 2> /dev/null | grep \\\"initrc\\\" | grep -Evw \\\"tr|ps|egrep|bash|awk\\\" | tr ':' ' ' | awk '{ print \\$NF }'\"\n    command_message \"${command}\"\n    daemon_check=$( eval \"${command}\" )\n    if [ -z \"${daemon_check}\" ]; then\n      if [ \"${audit_mode}\" = 1 ]; then\n        inc_insecure \"Unconfined daemons \\\"${daemon_check}\\\"\"\n      fi\n    else\n      if [ \"${audit_mode}\" = 1 ]; then\n        inc_secure   \"No unconfined daemons\"\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/ssh/audit_root_ssh_keys.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_root_ssh_keys\n#\n# Make sure there are not ssh keys for root\n#.\n\naudit_root_ssh_keys () {\n  print_function \"audit_root_ssh_keys\"\n  string=\"Root SSH keys\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${audit_mode}\" != 2 ]; then\n      command=\"grep '^root' /etc/passwd | cut -f6 -d:\"\n      command_message   \"${command}\"\n      root_home=$( eval \"${command}\" )\n      for check_file in $root_home/.ssh/authorized_keys $root_home/.ssh/authorized_keys2; do\n        if [ -f \"${check_file}\" ]; then\n          command=\"wc -l \\\"${check_file}\\\" | awk '{print \\$1}'\"\n          command_message   \"${command}\"\n          key_check=$( eval \"${command}\" )\n          if [ \"${key_check}\" -ge 1 ]; then\n            if [ \"${audit_mode}\" = 1 ]; then\n              inc_insecure \"Keys file \\\"${check_file}\\\" ${exists}\"\n              fix_message  \"mv ${check_file} ${check_file}.disabled\"\n            fi\n            if [ \"${audit_mode}\" = 0 ]; then\n              backup_file    \"${check_file}\"\n              remove_message \"Keys file \\\"${check_file}\\\"\"\n              if [ -f \"${check_file}\" ]; then\n                rm \"${check_file}\"\n              fi\n            fi\n          else\n            if [ \"${audit_mode}\" = 1 ]; then\n              inc_secure \"Keys file \\\"${check_file}\\\" does not contain any keys\"\n            fi\n          fi\n        else\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_secure \"Keys file \\\"${check_file}\\\" does not exist\"\n          fi\n        fi\n      done\n    else\n      restore_file \"${check_file}\" \"${restore_dir}\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/ssh/audit_ssh_config.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_ssh_config\n#\n# Check SSH config\n#\n# Refer to Section(s) 6.2.1-15  Page(s) 127-37 CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 6.2.1-15  Page(s) 147-59 CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 6.2.1-15  Page(s) 130-41 CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 5.2.1-16  Page(s) 218-37 CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 9.2.1-15  Page(s) 121-31 CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 2.4.14.9  Page(s) 57-60  CIS OS X 10.5 Benchmark v1.1.0\n# Refer to Section(s) 1.2       Page(s) 2-3    CIS FreeBSD Benchmark v1.0.5\n# Refer to Section(s) 6.3-7     Page(s) 47-51  CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 6.1.1-11  Page(s) 78-87  CIS Solaris 10 Benchmark v5.1.0\n# Refer to Section(s) 5.2.1-16  Page(s) 201-18 CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 5.2.1-16  Page(s) 213-31 CIS Ubuntu 16.04 Benchmark v2.0.0\n# Refer to Section(s) 5.1.1-22  Page(s) 523-78 CIS Ubuntu 24.04 Benchmark v1.0.0\n#\n# Refer to http://pubs.vmware.com/vsphere-55/index.jsp?topic=%2Fcom.vmware.vsphere.security.doc%2FGUID-12E27BF3-3769-4665-8769-DA76C2BC9FFE.html\n# Refer to https://wiki.mozilla.org/Security/Guidelines/OpenSSH\n#.\n\naudit_ssh_config () {\n  print_function \"audit_ssh_config\"\n  string=\"SSH Config\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"VMkernel\" ] || [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"Darwin\" ] || [ \"${os_name}\" = \"FreeBSD\" ] || [ \"${os_name}\" = \"AIX\" ]; then\n    if [ \"${os_name}\" = \"VMkernel\" ]; then\n      check_linux_service \"SSH\" \"off\"\n    fi\n    for check_file in /etc/sshd_config /etc/ssh/sshd_config /usr/local/etc/sshd_config /opt/local/ssh/sshd_config; do\n      if [ -f \"${check_file}\" ]; then\n        if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"Darwin\" ] || [ \"${os_name}\" = \"FreeBSD\" ] || [ \"${os_name}\" = \"AIX\" ]; then\n          if [ \"${os_name}\" = \"Darwin\" ]; then\n            check_file_value   \"is\" \"${check_file}\" \"GSSAPIAuthentication\"             \"space\" \"yes\"                \"hash\"\n            check_file_value   \"is\" \"${check_file}\" \"GSSAPICleanupCredentials\"         \"space\" \"yes\"                \"hash\"\n          fi\n          check_file_perms          \"${check_file}\" \"0600\" \"root\" \"root\"\n          check_file_value     \"is\" \"${check_file}\" \"UseLogin\"                         \"space\" \"no\"                 \"hash\"\n          check_file_value     \"is\" \"${check_file}\" \"X11Forwarding\"                    \"space\" \"no\"                 \"hash\"\n          check_file_value     \"is\" \"${check_file}\" \"MaxAuthTries\"                     \"space\" \"4\"                  \"hash\"\n          check_file_value     \"is\" \"${check_file}\" \"MaxAuthTriesLog\"                  \"space\" \"0\"                  \"hash\"\n          check_file_value     \"is\" \"${check_file}\" \"RhostsAuthentication\"             \"space\" \"no\"                 \"hash\"\n          check_file_value     \"is\" \"${check_file}\" \"IgnoreRhosts\"                     \"space\" \"yes\"                \"hash\"\n          check_file_value     \"is\" \"${check_file}\" \"StrictModes\"                      \"space\" \"yes\"                \"hash\"\n          check_file_value     \"is\" \"${check_file}\" \"AllowTcpForwarding\"               \"space\" \"no\"                 \"hash\"\n          check_file_value     \"is\" \"${check_file}\" \"DisableForwarding\"                \"space\" \"yes\"                \"hash\"\n          check_file_value     \"is\" \"${check_file}\" \"Protocol\"                         \"space\" \"${ssh_protocol}\"    \"hash\"\n          if [ \"$ssh_protocol\" = \"1\" ]; then\n            check_file_value   \"is\" \"${check_file}\" \"ServerKeyBits\"                    \"space\" \"$ssh_key_size\"      \"hash\"\n          fi\n          check_file_value     \"is\"  \"${check_file}\" \"GatewayPorts\"                    \"space\" \"no\"                 \"hash\"\n          check_file_value     \"is\"  \"${check_file}\" \"RhostsRSAAuthentication\"         \"space\" \"no\"                 \"hash\"\n          check_file_value     \"is\"  \"${check_file}\" \"PermitRootLogin\"                 \"space\" \"no\"                 \"hash\"\n          check_file_value     \"is\"  \"${check_file}\" \"PermitEmptyPasswords\"            \"space\" \"no\"                 \"hash\"\n          check_file_value     \"is\"  \"${check_file}\" \"PermitUserEnvironment\"           \"space\" \"no\"                 \"hash\"\n          check_file_value     \"is\"  \"${check_file}\" \"HostbasedAuthentication\"         \"space\" \"no\"                 \"hash\"\n          check_file_value     \"is\"  \"${check_file}\" \"PrintMotd\"                       \"space\" \"no\"                 \"hash\"\n          check_file_value     \"is\"  \"${check_file}\" \"ClientAliveInterval\"             \"space\" \"300\"                \"hash\"\n          check_file_value     \"is\"  \"${check_file}\" \"ClientAliveCountMax\"             \"space\" \"0\"                  \"hash\"\n          check_file_value     \"is\"  \"${check_file}\" \"RSAAuthentication\"               \"space\" \"no\"                 \"hash\"\n          check_file_value     \"is\"  \"${check_file}\" \"Banner\"                          \"space\" \"/etc/issue\"         \"hash\"\n          check_file_value     \"is\"  \"${check_file}\" \"LogLevel\"                        \"space\" \"VERBOSE\"            \"hash\"\n          if [ ! \"${ssh_allowusers}\" = \"\" ]; then\n            check_file_value   \"is\" \"${check_file}\" \"AllowUsers\"                       \"space\" \"${ssh_allowusers}\"  \"hash\"\n          fi\n          if [ ! \"${ssh_allowgroups}\" = \"\" ]; then\n            check_file_value   \"is\" \"${check_file}\" \"AllowUsers\"                       \"space\" \"${ssh_allowgroups}\" \"hash\"\n          fi\n          if [ ! \"${ssh_denyusers}\" = \"\" ]; then\n            check_file_value   \"is\" \"${check_file}\" \"DenyUsers\"                        \"space\" \"${ssh_denyusers}\"    \"hash\"\n          fi\n          if [ ! \"${ssh_denygroups}\" = \"\" ]; then\n            check_file_value   \"is\" \"${check_file}\" \"DenyGroups\"                       \"space\" \"${ssh_denygroups}\"   \"hash\"\n          fi\n          if [ \"$ssh_sandbox\" = \"yes\" ]; then\n            check_file_value   \"is\" \"${check_file}\" \"UsePrivilegeSeparation\"           \"space\" \"sandbox\"             \"hash\"\n          else\n            check_file_value   \"is\" \"${check_file}\" \"UsePrivilegeSeparation\"           \"space\" \"yes\"                 \"hash\"\n          fi\n          if [ \"${os_vendor}\" = \"Ubuntu\" ] && [ \"${os_version}\" -ge 24 ]; then\n            check_file_value   \"is\" \"${check_file}\" \"MaxStartups\"                      \"space\" \"10:30:60\"            \"hash\"\n            check_file_value   \"is\" \"${check_file}\" \"MaxSessions\"                      \"space\" \"10\"                  \"hash\"\n          fi\n          check_file_value     \"is\" \"${check_file}\" \"LoginGraceTime\"                   \"space\" \"60\"                  \"hash\"\n          # Check for kerbero s\n          check_file=\"/etc/krb5/krb5.conf\"\n          if [ -f \"${check_file}\" ]; then\n            admin_check=$( grep -v '^#' \"${check _file}\" | grep \"admin_server\" | cut -f2 -d= | sed 's/ //g' | wc -l | sed 's/ //g' )\n            if [ \"$admin_server\" != \"0\" ]; then\n              check_file=\"/etc/ssh/sshd_config\"\n              check_file_value \"is\" \"${check_file}\" \"UsePAM\"                           \"space\" \"yes\"                 \"hash\"\n              check_file_value \"is\" \"${check_file}\" \"GSSAPIAuthentication\"             \"space\" \"yes\"                 \"hash\"\n              check_file_value \"is\" \"${check_file}\" \"GSSAPIKeyExchange\"                \"space\" \"yes\"                 \"hash\"\n              check_file_value \"is\" \"${check_file}\" \"GSSAPIStoreDelegatedCredentials\"  \"space\" \"yes\"                 \"hash\"\n            fi\n          fi\n          if [ \"${os_name}\" = \"FreeBSD\" ]; then\n            check_file_value   \"is\" \"/etc/rc.conf\"   \"sshd_enable\"                     \"eq\"    \"YES\"                 \"hash\"\n          fi\n        fi\n      fi\n    done\n    verbose_message \"SSH MACs\" \"check\"\n    ignore_list=\"\"\n    command=\"sshd -T 2> /dev/null | grep \\\"^macs\\\" | sed \\\"s/,/ /g\\\" | sed \\\"s/^macs //g\\\"\"\n    command_message  \"${command}\"\n    mac_list=$( eval \"${command}\" )\n    for mac_name in ${mac_list}; do\n      case \"${mac_name}\" in\n        hmac-md5|hmac-md5-96|hmac-ripemd160|hmac-sha1-96|umac-64@openssh.com|hmac-md5-etm@openssh.com|hmac-md5-96-etm@openssh.com|hmac-ripemd160-etm@openssh.com|mac-sha1-96-etm@openssh.com|umac-64-etm@openssh.com|umac-128-etm@openssh.com)\n          inc_insecure \"MAC ${mac_name} is enabled\"\n          if [ \"${ignore_list}\" = \"\" ]; then\n            ignore_list=\"${mac_name}\"\n          else\n            ignore_list=\"${ignore_list},${mac_name}\"\n          fi\n          ;;\n        *)\n          inc_secure \"MAC ${mac_name} is enabled\"\n          ;;\n      esac\n    done\n    if [ ! \"${ignore_list}\" = \"\" ]; then\n      for check_file in /etc/sshd_config /etc/ssh/sshd_config /usr/local/etc/sshd_config /opt/local/ssh/sshd_config; do\n        if [ -f \"${check_file}\" ]; then\n          check_file_value \"is\" \"${check_file}\" \"MACs\" \"space\" \"-${ignore_list}\" \"hash\"\n        fi\n      done\n    fi\n    check_message \"SSH KexAlgorithms\"\n    ignore_list=\"\"\n    command=\"sshd -T 2> /dev/null | grep \\\"^kexalgorithms\\\" | sed \\\"s/,/ /g\\\" | sed \\\"s/^kexalgorithms //g\\\"\"\n    command_message  \"${command}\"\n    kex_list=$( eval \"${command}\" )\n    for kex_name in ${kex_list}; do\n      case \"${kex_name}\" in\n        diffie-hellman-group1-sha1|diffie-hellman-group14-sha1|diffie-hellman-group-exchange-sha1) \n          inc_insecure \"Kex Algoritm ${kex_name} is enabled\"\n          if [ \"${ignore_list}\" = \"\" ]; then\n            ignore_list=\"${kex_name}\"\n          else\n            ignore_list=\"${ignore_list},${kex_name}\"\n          fi\n          ;;\n        *)\n          inc_secure \"Kex Algoritm ${kex_name} is enabled\"\n          ;;\n      esac\n    done\n    if [ ! \"${ignore_list}\" = \"\" ]; then\n      for check_file in /etc/sshd_config /etc/ssh/sshd_config /usr/local/etc/sshd_config /opt/local/ssh/sshd_config; do\n        if [ -f \"${check_file}\" ]; then\n          check_file_value \"is\" \"${check_file}\" \"KexAlgorithms\" \"space\" \"-${ignore_list}\" \"hash\"\n        fi\n      done\n    fi\n    check_message \"SSH Ciphers\"\n    ignore_list=\"\"\n    command=\"sshd -T 2> /dev/null | grep \\\"^ciphers\\\" | sed \\\"s/,/ /g\\\" | sed \\\"s/^ciphers //g\\\"\"\n    command_message     \"${command}\"\n    cipher_list=$( eval \"${command}\" )\n    for cipher_name in ${cipher_list}; do\n      case \"${cipher_name}\" in\n        3des-cbc|aes128-cbc|aes192-cbc|aes256-cbc) \n          inc_insecure  \"Cipher ${cipher_name} is enabled\"\n          if [ \"${ignore_list}\" = \"\" ]; then\n            ignore_list=\"${cipher_name}\"\n          else\n            ignore_list=\"${ignore_list},${cipher_name}\"\n          fi\n          ;;\n        *)\n          inc_secure    \"Cipher ${cipher_name} is enabled\"\n          ;;\n      esac\n    done\n    if [ ! \"${ignore_list}\" = \"\" ]; then\n      for check_file in /etc/sshd_config /etc/ssh/sshd_config /usr/local/etc/sshd_config /opt/local/ssh/sshd_config; do\n        if [ -f \"${check_file}\" ]; then\n          check_file_value \"is\" \"${check_file}\" \"Ciphers\" \"space\" \"-${ignore_list}\" \"hash\"\n        fi\n      done\n    fi\n  else\n    na_message \"SSH\"\n  fi\n}\n"
  },
  {
    "path": "modules/ssh/audit_ssh_forwarding.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_ssh_forwarding\n#\n# This one is optional, generally required for apps\n#\n# Refer to Section(s) 11.1 Page(s) 142-3 CIS Solaris 10 Benchmark v1.1.0\n#.\n\naudit_ssh_forwarding () {\n  print_function \"audit_ssh_forwarding\"\n  string=\"SSH Forwarding\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"Darwin\" ]; then\n    if [ \"${os_name}\" = \"Darwin\" ]; then\n      check_file=\"/etc/sshd_config\"\n    else\n      check_file=\"/etc/ssh/sshd_config\"\n    fi\n    check_file_value \"is\" \"${check_file}\" \"AllowTcpForwarding\" \"space\" \"no\" \"hash\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/ssh/audit_ssh_perms.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_ssh_perms\n#\n# Check SSH file permission for keys etc \n#.\n\naudit_ssh_perms () {\n  print_function \"audit_ssh_perms\"\n  string=\"SSH Permissions\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"Darwin\" ]; then\n    for check_dir in /etc/ssh /usr/local/etc/ssh; do\n      if [ -d \"${check_dir}\" ]; then\n        command=\"find \\\"${check_dir}\\\" -name \\\"*_key\\\" -type f\"\n        command_message   \"${command}\"\n        file_list=$( eval \"${command}\" )\n        for check_file in ${file_list}; do\n          check_file_perms \"${check_file}\" \"0600\" \"root\" \"root\"\n        done\n        command=\"find \\\"${check_dir}\\\" -name \\\"*.pub\\\" -type f\"\n        command_message   \"${command}\"\n        file_list=$( eval \"${command}\" )\n        for check_file in ${file_list}; do\n          check_file_perms \"${check_file}\" \"0640\" \"root\" \"root\"\n        done\n      fi\n    done\n    check_message \"User SSH Permissions\"\n    if [ \"${my_id}\" != \"0\" ] && [ \"${use_sudo}\" = \"0\" ]; then\n      notice_message \"Requires sudo to check\"\n      return\n    fi\n    while IFS=\":\" read -r user _ uid gid _ home shell; do\n      if [ -d \"${home}/.ssh\" ]; then\n        check_file_perms \"${home}/.ssh\" \"0700\" \"${uid}\" \"${gid}\"\n        command=\"find \\\"${home}/.ssh\\\" -type f\"\n        command_message   \"${command}\"\n        file_list=$( eval \"${command}\" )\n        for check_file in ${file_list}; do\n          check_file_perms \"${check_file}\" \"0600\" \"${uid}\" \"${gid}\"\n        done\n      fi\n    done < /etc/passwd \n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sudo/audit_sudo_authenticate.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_sudo_authenticate\n#\n# Check sudo authenticate\n#\n# Refer to Section(s) 5.2.5 Page(s) 592-3 CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_sudo_authenticate () {\n  print_function \"audit_sudo_authenticate\"\n  string=\"Sudo authenticate\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${my_id}\" != \"0\" ] && [ \"${use_sudo}\" = \"0\" ]; then\n      verbose_message \"Requires sudo to check\" \"notice\"\n      return\n    fi\n    check_file=\"/etc/sudoers\"\n    if [ -f \"${check_file}\" ]; then\n      command=\"grep \\\"^[^#].*\\\\!authenticate\\\" < \\\"${check_file}\\\"\"\n      command_message   \"${command}\"\n      auth_test=$( eval \"${command}\" )\n      if [ -n \"${auth_test}\" ]; then\n        inc_insecure   \"Re-authentication is not disabled for sudo in ${check_file}\"\n      else\n        inc_secure     \"Re-authentication is disabled for sudo in ${check_file}\"\n      fi\n      check_file_perms \"${check_file}\" \"440\" \"root\" \"${wheel_group}\"\n    fi\n    if [ -d \"/etc/sudoers.d\" ]; then\n      command=\"find /etc/sudoers.d -type file\"\n      command_message   \"${command}\"\n      file_list=$( eval \"${command}\" )\n      for check_file in ${file_list}; do\n        command=\"grep \\\"^[^#].*\\\\!authenticate\\\" < \\\"${check_file}\\\"\"\n        command_message   \"${command}\"\n        auth_test=$( eval \"${command}\" )\n        if [ -n \"${auth_test}\" ]; then\n          inc_insecure   \"Re-authentication is not disabled for sudo in ${check_file}\"\n        else\n          inc_secure     \"Re-authentication is disabled for sudo in ${check_file}\"\n        fi\n        check_file_perms \"${check_file}\" \"440\" \"root\" \"${wheel_group}\"\n      done\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sudo/audit_sudo_logfile.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_sudo_logfile\n#\n# Check sudo logfile\n#\n# Refer to Section(s) 5.2.3 Page(s) 585-7 CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_sudo_logfile () {\n  print_function \"audit_sudo_logfile\"\n  string=\"Sudo logfile\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${my_id}\" != \"0\" ] && [ \"${use_sudo}\" = \"0\" ]; then\n      verbose_message \"Requires sudo to check\" \"notice\"\n      return\n    fi\n    if [ -d \"/etc/sudoers.d\" ]; then\n      check_file=\"/etc/sudoers.d/logfile\"\n    else\n      check_file=\"/etc/sudoers\"\n    fi\n    check_file_value \"is\"  \"${check_file}\" \"Defaults logfile\" \"eq\" \"/var/log/sudo.log\" \"hash\"\n    check_file_perms       \"${check_file}\" \"440\" \"root\"            \"${wheel_group}\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sudo/audit_sudo_nopassword.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_sudo_nopassword\n#\n# Check sudo NOPASSWD\n#\n# Refer to Section(s) 5.2.4 Page(s) 588-9 CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_sudo_nopassword () {\n  print_function \"audit_sudo_nopassword\"\n  string=\"Sudo NOPASSWD\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${my_id}\" != \"0\" ] && [ \"${use_sudo}\" = \"0\" ]; then\n      verbose_message \"Requires sudo to check\" \"notice\"\n      return\n    fi\n    check_file=\"/etc/sudoers\"\n    if [ -f \"${check_file}\" ]; then\n      command=\"grep \\\"^[^#].*NOPASSWD\\\" < \\\"${check_file}\\\"\"\n      command_message   \"${command}\"\n      auth_test=$( eval \"${command}\" )\n      if [ -n \"${auth_test}\" ]; then\n        inc_insecure \"NOPASSWD entry for sudo in ${check_file}\"\n      else\n        inc_secure   \"No NOPASSWD entry for sudo in ${check_file}\"\n      fi\n      check_file_perms \"${check_file}\" \"440\" \"root\" \"${wheel_group}\"\n    fi\n    if [ -d \"/etc/sudoers.d\" ]; then\n      command=\"find /etc/sudoers.d -type file\"\n      command_message   \"${command}\"\n      file_list=$( eval \"${command}\" )\n      for check_file in ${file_list}; do\n        command=\"grep \\\"^[^#].*NOPASSWD\\\" < \\\"${check_file}\\\"\"\n        command_message   \"${command}\"\n        auth_test=$( eval \"${command}\" )\n        if [ -n \"${auth_test}\" ]; then\n          inc_insecure \"NOPASSWD entry for sudo in ${check_file}\"\n        else\n          inc_secure   \"No NOPASSWD entry for sudo in ${check_file}\"\n        fi\n        check_file_perms \"${check_file}\" \"440\" \"root\" \"${wheel_group}\" \n      done\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sudo/audit_sudo_perms.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_sudo_perms\n#\n# Check sudo file permissions\n#.\n\naudit_sudo_perms () {\n  print_function \"audit_sudo_perms\"\n  string=\"Sudo file permissions\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"SunOS\" ]; then\n    check_file=\"/etc/sudoers\"\n    if [ -f \"${check_file}\" ]; then\n      check_file_perms \"${check_file}\" \"440\" \"root\" \"${wheel_group}\" \n    fi\n    if [ -d \"/etc/sudoers.d\" ]; then\n      if [ \"${my_id}\" != \"0\" ] && [ \"${use_sudo}\" = \"0\" ]; then\n        verbose_message \"May require sudo to check\" \"notice\"\n      fi\n      file_list=$( find /etc/sudoers.d -type f 2> /dev/null )\n      for check_file in ${file_list}; do\n        check_file_perms \"${check_file}\" \"440\" \"root\" \"${wheel_group}\" \n      done\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sudo/audit_sudo_timeout.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_sudo_timeout\n#\n# Check sudo timeout\n#\n# Refer to Section(s) 5.1   Page(s) 48-9  CIS Apple OS X 10.8 Benchmark v1.0.0\n# Refer to Section(s) 5.3   Page(s) 128-9 CIS Apple OS X 10.12 Benchmark v1.0.0\n# Refer to Section(s) 5.4   Page(s) 343-5 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n# Refer to Section(s) 5.2.6 Page(s) 592-3 CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_sudo_timeout () {\n  print_function \"audit_sudo_timeout\"\n  string=\"Sudo timeout\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${my_id}\" != \"0\" ] && [ \"${use_sudo}\" = \"0\" ]; then\n      verbose_message \"Requires sudo to check\" \"notice\"\n      return\n    fi\n    if [ -d \"/etc/sudoers.d\" ]; then\n      check_file=\"/etc/sudoers.d/timeout\"\n    else\n      check_file=\"/etc/sudoers\"\n    fi\n    check_file_value \"is\" \"${check_file}\" \"Defaults timestamp_timeout\" \"eq\" \"15\" \"hash\"\n    check_file_perms      \"${check_file}\" \"440\" \"root\" \"${wheel_group}\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sudo/audit_sudo_timestamp.sh",
    "content": "#!/bin/sh -eu\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_sudo_timestanp\n#\n# Check sudo timestamp\n#\n# Refer to Section(s) 5.5   Page(s) 346-7 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n# Refer to Section(s) 5.2.6 Page(s) 592-3 CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_sudo_timestamp () {\n  print_function \"audit_sudo_timestamp\"\n  string=\"Sudo timestamp\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${my_id}\" != \"0\" ] && [ \"${use_sudo}\" = \"0\" ]; then\n      verbose_message \"Requires sudo to check\" \"notice\"\n      return\n    fi\n    command=\"sudo --version | head -1 | awk '{print \\$3}' | cut -f1 -d.\"\n    command_message   \"${command}\"\n    major_ver=$( eval \"${command}\" )\n    command=\"sudo --version | head -1 | awk '{print \\$3}' | cut -f2 -d.\"\n    command_message   \"${command}\"\n    minor_ver=$( eval \"${command}\" )\n    check_sudo=\"0\"\n    if [ \"$major_ver\" -gt 1 ]; then\n      check_sudo=\"1\"\n    else\n      if [ \"$major_ver\" -eq 1 ] && [ \"$minor_ver\" -ge 8 ]; then\n        check_sudo=\"1\"\n      fi\n    fi\n    if [ -d \"/etc/sudoers.d\" ]; then\n      check_file=\"/etc/sudoers.d/timestamp\"\n    else\n      check_file=\"/etc/sudoers\"\n    fi\n    if [ \"$check_sudo\" = \"1\" ]; then\n      check_file_value \"is\" \"${check_file}\" \"Defaults timestamp_type\" \"eq\" \"tty\" \"hash\"\n      check_file_perms      \"${check_file}\" \"440\" \"root\"              \"${wheel_group}\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sudo/audit_sudo_usepty.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_sudo_usepty\n#\n# Check sudo use_pty\n#\n# Refer to Section(s) 5.2.2 Page(s) 582-4 CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_sudo_usepty () {\n  print_function \"audit_sudo_usepty\"\n  string=\"Sudo use_pty\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Darwin\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${my_id}\" != \"0\" ] && [ \"${use_sudo}\" = \"0\" ]; then\n      verbose_message \"Requires sudo to check\" \"notice\"\n      return\n    fi\n    if [ -d \"/etc/sudoers.d\" ]; then\n      check_file=\"/etc/sudoers.d/use_pty\"\n    else\n      check_file=\"/etc/sudoers\"\n    fi\n    check_append_file \"${check_file}\" \"Defaults use_pty\" \"hash\"\n    check_file_perms  \"${check_file}\" \"440\" \"root\"       \"${wheel_group}\" \n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sudo/audit_wheel_sudo.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2028\n# shellcheck disable=SC2154\n\n# audit_wheel_sudo\n#\n# Check wheel group settings in sudoers\n#.\n\naudit_wheel_sudo () {\n  print_function \"audit_wheel_sudo\"\n  string=\"Sudoers group settings\"\n  check_message  \"${string}\"\n  temp_file=\"${temp_dir}/audit_wheel_sudo\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"Darwin\" ]; then\n    for check_dir in /etc /usr/local/etc /usr/sfw/etc /opt/csw/etc; do\n      check_dir=\"${check_dir}/sudoers.d\"\n      if [ -d \"${check_dir}\" ]; then\n        check_files=$( find \"${check_dir}\" -type f )\n        for check_file in ${check_file}s; do\n          check_file_perms \"${check_file}\" \"0440\" \"root\" \"root\"\n          if [ \"${audit_mode}\" != 2 ]; then\n            wheel_groups=$( grep NOPASSWD \"${check_file}\" | grep ALL | grep -v '^#' | awk '{print $1}' )\n            for wheel_group in ${wheel_groups} ; do\n              if [ \"${ansible_mode}\" = 1 ]; then\n                echo \"\"\n                echo \"- name: Checking NOPASSWD for ${wheel_group} in ${check_file}\"\n                echo \"  lineinfile:\"\n                echo \"    path: ${check_file}\"\n                echo \"    regexp: ''(.*NOPASSWD.*)'\"\n                echo \"    replace: '#\\1'\"\n                echo \"\"\n              fi\n              lock_command=\"sed 's/^\\(%.*NOPASSWD.*\\)/#\\1/g' < ${check_file} > ${temp_file} ; cat ${temp_file} > ${check_file}\"\n              lock_message=\"Disabling group \\\"${wheel_group}\\\" NOPASSWD entry\"\n              if [ \"${audit_mode}\" = 1 ]; then\n                inc_insecure \"Group ${wheel_group} does not require password to escalate privileges\"\n                run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n              fi\n              if [ \"${audit_mode}\" = 0 ]; then\n                backup_file  \"${check_file}\"\n                run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n              fi\n            done\n          else\n            restore_file \"${check_file}\" \"${restore_dir}\"\n          fi\n        done\n      fi\n      check_file=\"${check_dir}/sudoers\"\n      if [ -f \"${check_file}\" ]; then\n        check_file_perms ${check_file} 0440 root root\n        if [ \"${audit_mode}\" != 2 ]; then\n          wheel_groups=$( grep NOPASSWD \"${check_file}\" | grep ALL | grep -v '^#' | awk '{print $1}' )\n          for wheel_group in ${wheel_groups} ; do\n            if [ \"${ansible_mode}\" = 1 ]; then\n              echo \"\"\n              echo \"- name: Checking NOPASSWD for ${wheel_group} in ${check_file}\"\n              echo \"  lineinfile:\"\n              echo \"    path: ${check_file}\"\n              echo \"    regexp: ''(.*NOPASSWD.*)'\"\n              echo \"    replace: '#\\1'\"\n              echo \"\"\n            fi\n            lock_command=\"sed 's/^\\(%.*NOPASSWD.*\\)/#\\1/g' < ${check_file} > ${temp_file} ; cat ${temp_file} > ${check_file}\"\n            lock_message=\"Disabling group \\\"${wheel_group}\\\" NOPASSWD entry\"\n            if [ \"${audit_mode}\" = 1 ]; then\n              inc_insecure \"Group \\\"${wheel_group}\\\" does not require password to escalate privileges\"\n              run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n            fi\n            if [ \"${audit_mode}\" = 0 ]; then\n              backup_file  \"${check_file}\"\n              run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n            fi\n          done\n        else\n          restore_file \"${check_file}\" \"${restore_dir}\"\n        fi\n      fi\n    done\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sunos/audit_apocd.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_apocd\n#\n# Check APOC\n#\n# Turn off apocd\n#.\n\naudit_apocd () {\n  print_function \"audit_apocd\"\n  string=\"APOC Daemons\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n      check_sunos_service \"svc:/network/apocd/udp:default\" \"disabled\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sunos/audit_audit_class.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_audit_class\n#\n# Check audit class\n# \n# Refer to Section(s) 4.1-5 Page(s) 39-45 CIS Solaris 11.1 v1.0.0\n#.\n\naudit_audit_class () {\n  print_function \"audit_audit_class\"\n  string=\"Audit Class\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"11\" ]; then\n      audit_create_class\n      audit_network_connections\n      audit_file_metadata\n      audit_privilege_events\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sunos/audit_bpcd.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_bpcd\n#\n# Turn off bpcd\n#.\n\naudit_bpcd () {\n  print_function \"audit_bpcd\"\n  string=\"BPC Daemon\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n      check_sunos_service \"svc:/network/bpcd/tcp:default\" \"disabled\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sunos/audit_bpjava_msvc.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_bpjava_msvc\n#\n# Turn off bpjava-msvc if not required. It is associated with NetBackup.\n#.\n\naudit_bpjava_msvc () {\n  print_function \"audit_bpjava_msvc\"\n  string=\"BPJava Service\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n      check_sunos_service \"svc:/network/bpjava-msvc/tcp:default\" \"disabled\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sunos/audit_cde_banner.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_cde_banner\n#\n# Check CDE Warning Banner\n#\n# Refer to Section(s) 8.2 Page(s) 112-3 CIS Solaris 10 v5.1.0\n#.\n\naudit_cde_banner () {\n  print_function \"audit_cde_banner\"\n  string=\"CDE Warning Banner\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    for cde_file in /usr/dt/config/*/Xresources ; do\n      dir_name=$( dirname\" ${cde_file}\" | sed \"s/usr/etc/\" )\n      check_file=\"${dir_name}/Xresources\"\n      if [ -f \"${check_file}\" ]; then\n        check_file_value \"is\" \"${check_file}\" \"Dtlogin*greeting.labelString\"     \"colon\" \"Authorized uses only\" \"star\"\n        check_file_value \"is\" \"${check_file}\" \"Dtlogin*greeting.persLabelString\" \"colon\" \"Authorized uses only\" \"star\"\n      fi\n    done\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sunos/audit_cde_cal.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_cde_cal () {\n#\n# Check Local CDE Calendar Manager\n#\n# Refer to Section(s) 2.1.2 Page(s) 18-9 CIS Solaris 10 v5.1.0\n#.\n\naudit_cde_cal () {\n  print_function \"audit_cde_cal\"\n  string=\"Local CDE Calendar Manager\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ]; then\n      check_sunos_service \"svc:/network/rpc/cde-calendar-manager:default\" \"disabled\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sunos/audit_cde_print.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_cde_print\n#\n# CDE Printing services. Not required unless running CDE applications.\n#.\n\naudit_cde_print () {\n  print_function \"audit_cde_print\"\n  string=\"CDE Print\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ]; then\n      check_sunos_service \"svc:/application/cde-printinfo:default\" \"disabled\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sunos/audit_cde_screen_lock.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_cde_screen_lock\n#\n# Check Screen Lock for CDE Users\n#\n# Refer to Section(s) 6.7 Page(s) 91-2 CIS Solaris 10 Benchmark v5.1.0\n#.\n\naudit_cde_screen_lock () {\n  print_function \"audit_cde_screen_lock\"\n  string=\"Screen Lock for CDE Users\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    file_list=$( find /usr/dt/config/*/sys.resources -t file -maxdepth 1 2> /dev/null )\n    for cde_file in ${file_list}; do\n      dir_name=$( dirname \"$cde_file\" | sed \"s/usr/etc/\" )\n      if [ ! -d \"${dir_name}\" ]; then\n        mkdir -p \"${dir_name}\"\n      fi\n      check_file=\"${dir_name}/sys.resources\"\n      check_file_value \"is\" \"${check_file}\" \"dtsession*saverTimeout\" \"colon\" \" 10\" \"star\"\n      check_file_value \"is\" \"${check_file}\" \"dtsession*lockTimeout\"  \"colon\" \" 10\" \"star\"\n      check_file_perms      \"${check_file}\" \"0444\" \"root\" \"sys\"\n    done\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sunos/audit_cde_spc.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_cde_spc\n#\n# CDE Subprocess control. Not required unless running CDE applications.\n#.\n\naudit_cde_spc () {\n  print_function \"audit_cde_spc\"\n  string=\"CDE Subprocess control\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ]; then\n      check_sunos_service \"svc:/network/cde-spc:default\" \"disabled\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sunos/audit_cde_ttdb.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_cde_ttdb\n#\n# Check CDE ToolTalk Database Server\n#\n# Refer to Section(s) 2.1.1 Page(s) 17-8 CIS Solaris 10 v5.1.0\n#.\n\naudit_cde_ttdb () {\n  print_function \"audit_cde_ttdb\"\n  string=\"CDE ToolTalk Database Server\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ]; then\n      check_sunos_service \"svc:/network/rpc/cde-ttdbserver:tcp\" \"disabled\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sunos/audit_create_class.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_create_class\n#\n# Creating Audit Classes improves the auditing capabilities of Solaris.\n#\n# Refer to Section(s) 4.1-5 Page(s) 39-45 CIS Solaris 11.1 v1.0.0\n#.\n\naudit_create_class () {\n  print_function \"audit_create_class\"\n  string=\"Audit Classes\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    check_file=\"/etc/security/audit_class\"\n    if [ -f \"${check_file}\" ]; then\n      check_append_file \"${check_file}\" \"0x0100000000000000:lck:Security Lockdown\" \"hash\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sunos/audit_dfstab.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_dfstab\n#\n# Check dfstab\n#\n# Refer to Section(s) 10.2 Page(s) 138-9 CIS Solaris 10 Benchmark v1.1.0\n#.\n\naudit_dfstab () {\n  print_function \"audit_dfstab\"\n  string=\"Full Path Names in Exports\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    replace_file_value \"/etc/dfs/dfstab\" \"share\" \"/usr/bin/share\" \"start\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sunos/audit_echo.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_echo\n#\n# Turn off echo and chargen services\n#.\n\naudit_echo () {\n  print_function \"audit_echo\"\n  string=\"Echo and Chargen Services\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n      for service_name in \"svc:/network/echo:dgram\" \\\n        \"svc:/network/echo:stream\"    \"svc:/network/time:dgram\" \\\n        \"svc:/network/time:stream\"    \"svc:/network/tname:default\" \\\n        \"svc:/network/comsat:default\" \"svc:/network/discard:dgram\" \\\n        \"svc:/network/discard:stream\" \"svc:/network/chargen:dgram\" \\\n        \"svc:/network/chargen:stream\" \"svc:/network/rpc/spray:default\" \\\n        \"svc:/network/daytime:dgram\"  \"svc:/network/daytime:stream\" \\\n        \"svc:/network/talk:default\"; do\n        check_sunos_service \"${service_name}\" \"disabled\"\n      done\n    fi\n  else\n    na_message \"${string}\"\n  fi\n#  if [ \"${os_name}\" = \"Linux\" ]; then\n#    verbose_message \"Telnet and Rlogin Services\"\n#    for service_name in telnet login rlogin rsh shell; do\n#      check_linux_service ${service_name} off\n#    done\n#  fi\n}\n"
  },
  {
    "path": "modules/sunos/audit_eeprom_security.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_eeprom_security\n#\n# Check EEPROM security\n#\n# Refer to Section(s) 6.15 Page(s) 59-60 CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 6.12 Page(s) 97-8  CIS Solaris 10 Benchmark v5.1.0\n#.\n\naudit_eeprom_security () {\n  print_function \"audit_eeprom_security\"\n  string=\"EEPROM Password\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${audit_mode}\" = 2 ]; then\n      echo \"EEPROM password to none\" \"restore\"\n      eeprom security-mode=none\n    fi\n    if [ \"${audit_mode}\" != 2 ]; then\n      eeprom_check=$( eeprom security-mode | awk -F= '{ print $2 }' )\n      if [ \"${eeprom_check}\" = \"none\" ]; then\n        if [ \"${audit_mode}\" = 1 ]; then\n          inc_insecure \"EEPROM password is not enabled\"\n          fix_message  \"eeprom security-mode=command\"\n          fix_message  \"eeprom security-#badlogins=0\"\n        fi\n        if [ \"${audit_mode}\" = 0 ]; then\n          eeprom security-mode=command\n          eeprom security-#badlogins=0\n        fi\n      else\n        if [ \"${audit_mode}\" = 1 ];then\n          inc_secure \"EEPROM password is enabled\"\n        fi\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sunos/audit_extended_attributes.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_extended_attributes\n#\n# Check extended attributes\n#\n# Refer to Section(s) 9.25 Page(s) 90-1  CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 9.25 Page(s) 136-7 CIS Solaris 10 Benchmark v1.1.0\n#.\n\naudit_extended_attributes () {\n  print_function \"audit_extended_attributes\"\n  string=\"Extended Attributes\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${audit_mode}\" = 1 ]; then\n      file_list=$( find / \\( -fstype nfs -o -fstype cachefs \\\n      -o -fstype autofs -o -fstype ctfs -o -fstype mntfs \\\n      -o -fstype objfs  -o -fstype proc \\) -prune \\\n      -o -xattr -print )\n      for check_file in ${file_list}; do\n        inc_insecure \"File \\\"${check_file}\\\" has extended attributes\"\n      done\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sunos/audit_gss.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_gss\n#\n# Check Generic Security Services\n#\n# Refer to Section(s) 2.7   Page(s) 19-20 CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 2.2.7 Page(s) 27    CIS Solaris 10 Benchmark v5.1.0\n#.\n\naudit_gss () {\n  print_function \"audit_gss\"\n  string=\"Generic Security Services\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n      check_sunos_service \"svc:/network/rpc/gss\" \"disabled\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sunos/audit_ipadm_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_ipadm_value\n#\n# Code to drive ipadm on Solaris 11\n#.\n\naudit_ipadm_value () {\n  print_function \"audit_ipadm_value\"\n  string=\"IPadm Value\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"11\" ]; then\n      ipadm_name=\"${1}\"\n      ipadm_property=\"${2}\"\n      correct_value=\"${3}\"\n      command=\"ipadm show-prop -p \\\"${ipadm_name}\\\" -co current \\\"${ipadm_property}\\\"\"\n      command_message       \"${command}\"\n      current_value=$( eval \"${command}\" )\n      file_header=\"ipadm\"\n      log_file=\"${work_dir}/${file_header}.log\"\n      if [ \"${audit_mode}\" = 2 ]; then\n        restore_file=\"${restore_dir}/${file_header}.log\"\n        if [ -f \"${restore_file}\" ]; then\n          restore_property=$( grep \"${ipadm_property},\" \"${restore_file}\" | cut -f2 -d',' )\n          restore_value=$(    grep \"${ipadm_property},\" \"${restore_file}\" | cut -f3 -d',' )\n          restore_check=$(    expr \"${restore_property}\" : \"[A-z]\" )\n          if [ \"${restore_check}\" = 1 ]; then\n            if [ \"${current_value}\" != \"${restore_value}\" ]; then\n              restore_message \"\\\"${ipadm_name}\\\" \\\"${ipadm_property}\\\" to \\\"${restore_value}\\\"\"\n              eval \"ipadm set-prop -p ${ipadm_name}=${restore_value} ${ipadm_property}\"\n            fi\n          fi\n        fi\n      else\n        info_message \"Value of \\\"${ipadm_name}\\\" for \\\"${ipadm_property}\\\" is \\\"${correct_value}\\\"\"\n      fi\n      if [ \"${current_value}\" -ne \"${correct_value}\" ]; then\n        command_line=\"ipadm set-prop -p ${ipadm_name}=${correct_value} ${ipadm_property}\"\n        if [ \"${audit_mode}\" = 1 ]; then\n          inc_insecure \"Value of \\\"${ipadm_name} ${ipadm_property}\\\" not set to \\\"${correct_value}\\\"\"\n          fix_message  \"${command_line}\"\n        else\n          if [ \"${audit_mode}\" = 0 ]; then\n            info_message \"Value of \\\"${ipadm_name} ${ipadm_property}\\\" to \\\"${correct_value}\\\"\"\n            echo \"${ipadm_name},${ipadm_property},${correct_value}\" >> \"${log_file}\"\n            eval \"${command_line}\"\n          fi\n        fi\n      else\n        if [ \"${audit_mode}\" != 2 ]; then\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_secure \"Value of \\\"${ipadm_name} ${ipadm_property}\\\" already set to \\\"${correct_value}\\\"\"\n          fi\n        fi\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sunos/audit_keyserv.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_keyserv\n#\n# Refer to Section(s) 2.3   Page(s) 16-17 CIS Solaris 11.1  Benchmark v1.0.0\n# Refer to Section(s) 2.2.1 Page(s) 23    CIS Solaris 10    Benchmark v5.1.0\n#.\n\naudit_keyserv () {\n  print_function \"audit_keyserv\"\n  string=\"RPC Encryption Key\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n      check_sunos_service \"svc:/network/rpc/keyserv\" \"disabled\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sunos/audit_labeld.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_labeld\n#\n# Turn off labeld\n#.\n\naudit_labeld () {\n  print_function \"audit_labeld\"\n  string=\"Label Daemon\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n      check_sunos_service \"svc:/system/labeld:default\" \"disabled\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sunos/audit_ncs.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_ncs\n#\n# Check NCS\n#\n# Refer to Section(s) 2.12.3 Page(s) 208 CIS AIX Benchmark v1.1.0\n#.\n\naudit_ncs () {\n  print_function \"audit_ncs\"\n  string=\"NCS\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"AIX\" ]; then\n    check_itab \"ncs\" \"off\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sunos/audit_ndd_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_ndd_value\n#\n# Modify Network Parameters\n# Checks and sets ndd values\n#.\n\naudit_ndd_value () {\n  print_function \"audit_ndd_value\"\n  string=\"NDD Value\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ]; then\n      ndd_name=\"${1}\"\n      ndd_property=\"${2}\"\n      correct_value=\"${3}\"\n      if [ \"${ndd_property}\" = \"tcp_extra_priv_ports_add\" ]; then\n        command=\"ndd -get \\\"${ndd_name}\\\" tcp_extra_priv_ports | grep \\\"${correct_value}\\\"\"\n        command_message       \"${command}\"\n        current_value=$( eval \"${command}\" )\n      else\n        command=\"ndd -get \\\"${ndd_name}\\\" \\\"${ndd_property}\\\"\"\n        command_message       \"${command}\"\n        current_value=$( eval \"${command}\" )\n      fi\n      file_header=\"ndd\"\n      log_file=\"${work_dir}/${file_header}.log\"\n      if [ \"${audit_mode}\" = 2 ]; then\n        restore_file=\"${restore_dir}/${file_header}.log\"\n        if [ -f \"${restore_file}\" ]; then\n          restore_property=$( grep \"${ndd_property},\" \"${restore_file}\" | cut -f2 -d',' )\n          restore_value=$(    grep \"${ndd_property},\" \"${restore_file}\" | cut -f3 -d',' )\n          if [ -n \"${restore_value}\"  ]; then\n            if [ \"${ndd_property}\" = \"tcp_extra_priv_ports_add\" ]; then\n              command=\"ndd -get \\\"${ndd_name}\\\" tcp_extra_priv_ports | grep \\\"${restore_value}\\\"\"\n              command_message       \"${command}\"\n              current_value=$( eval \"${command}\" )\n            fi\n            if [ -n \"${current_value}\" ]; then\n              if [ \"${current_value}\" != \"${restore_value}\" ]; then\n                if [ \"${ndd_property}\" = \"tcp_extra_priv_ports_add\" ]; then\n                  ndd_property=\"tcp_extra_priv_ports_del\"\n                fi\n                fix_message \"Restoring: \\\"${ndd_name}\\\" \\\"${ndd_property}\\\" to \\\"${restore_value}\\\"\"\n                command=\"ndd -set \\\"${ndd_name}\\\" \\\"${ndd_property}\\\" \\\"${restore_value}\\\"\"\n                command_message \"${command}\"\n                eval \"${command}\"\n              fi\n            fi\n          fi\n        fi\n      else\n        verbose_message \"NDD ${ndd_name} ${ndd_property}\"\n      fi\n      if [ \"${current_value}\" -ne \"${correct_value}\" ]; then\n        command_line=\"ndd -set ${ndd_name} ${ndd_property} ${correct_value}\"\n        command_message \"${command_line}\"\n        if [ \"${audit_mode}\" = 1 ]; then\n          inc_insecure \"NDD \\\"${ndd_name} ${ndd_property}\\\" not set to \\\"${correct_value}\\\"\"\n          fix_message  \"${command_line}\"\n        else\n          if [ \"${audit_mode}\" = 0 ]; then\n            fix_message \"NDD \\\"${ndd_name} ${ndd_property}\\\" to \\\"${correct_value}\\\"\"\n            echo \"${ndd_name},${ndd_property},${correct_value}\" >> \"${log_file}\"\n            eval \"${command_line}\"\n          fi\n        fi\n      else\n        if [ \"${audit_mode}\" != 2 ]; then\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_secure \"NDD \\\"${ndd_name} ${ndd_property}\\\" already set to \\\"${correct_value}\\\"\"\n          fi\n        fi\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sunos/audit_network_connections.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_network_connections\n#\n# Auditing of Incoming Network Connections\n#.\n\naudit_network_connections () {\n  print_function \"audit_network_connections\"\n  string=\"Auditing of Incomming Network Connections\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"11\" ]; then\n      check_append_file \"/etc/security/audit_event\" \"lck:AUE_ACCEPT\"        \"hash\"\n      check_append_file \"/etc/security/audit_event\" \"lck:AUE_CONNECT\"       \"hash\"\n      check_append_file \"/etc/security/audit_event\" \"lck:AUE_SOCKACCEPT\"    \"hash\"\n      check_append_file \"/etc/security/audit_event\" \"lck:AUE_SOCKCONNECT\"   \"hash\"\n      check_append_file \"/etc/security/audit_event\" \"lck:AUE_inetd_connect\" \"hash\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sunos/audit_ocfserv.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_ocfserv\n#\n# Turn off ocfserv\n#.\n\naudit_ocfserv () {\n  print_function \"audit_ocfserv\"\n  string=\"OCF Service\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n      check_sunos_service \"svc:/network/rpc/ocfserv:default\" \"disabled\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sunos/audit_online_documentation.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_online_documentation\n#\n# Check online documentation daemon settings\n#\n# Refer to Section(s) 2.12.4 Page(s) 209 CIS AIX Benchmark v1.1.0\n#.\n\naudit_online_documentation () {\n  print_function \"audit_online_documentation\"\n  string=\"Online Documentation\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"AIX\" ] || [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_name}\" = \"AIX\" ]; then\n      check_itab \"httpdlite\" \"off\"\n    fi\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      check_initd_service \"ab2mgr\" \"disabled\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sunos/audit_privilege_events.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_privilege_events\n#\n# Auditing of Process and Privilege Events\n#\n# Refer to Section(s) 4.4 Page(s) 43-44 CIS Solaris 11.1 Benchmark v1.0.0\n#.\n\naudit_privilege_events () {\n  print_function \"audit_privilege_events\"\n  string=\"Auditing of Privileged Events\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"11\" ]; then\n      check_append_file \"/etc/security/audit_event\" \"lck:AUE_CHROOT\"      \"hash\"\n      check_append_file \"/etc/security/audit_event\" \"lck:AUE_SETREUID\"    \"hash\"\n      check_append_file \"/etc/security/audit_event\" \"lck:AUE_SETREGID\"    \"hash\"\n      check_append_file \"/etc/security/audit_event\" \"lck:AUE_FCHROOT\"     \"hash\"\n      check_append_file \"/etc/security/audit_event\" \"lck:AUE_PFEXEC\"      \"hash\"\n      check_append_file \"/etc/security/audit_event\" \"lck:AUE_SETUID\"      \"hash\"\n      check_append_file \"/etc/security/audit_event\" \"lck:AUE_NICE\"        \"hash\"\n      check_append_file \"/etc/security/audit_event\" \"lck:AUE_SETGID\"      \"hash\"\n      check_append_file \"/etc/security/audit_event\" \"lck:AUE_PRIOCNTLSYS\" \"hash\"\n      check_append_file \"/etc/security/audit_event\" \"lck:AUE_SETEGID\"     \"hash\"\n      check_append_file \"/etc/security/audit_event\" \"lck:AUE_SETEUID\"     \"hash\"\n      check_append_file \"/etc/security/audit_event\" \"lck:AUE_SETPPRIV\"    \"hash\"\n      check_append_file \"/etc/security/audit_event\" \"lck:AUE_SETSID\"      \"hash\"\n      check_append_file \"/etc/security/audit_event\" \"lck:AUE_SETPGID\"     \"hash\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sunos/audit_service_tags.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_service_tags\n#\n# Turn off Service Tags if not being used. It can provide information that can\n# be used as vector of attack.\n#.\n\naudit_service_tags () {\n  print_function \"audit_service_tags\"\n  string=\"Service Tags\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n      check_sunos_service \"svc:/network/stdiscover:default\"   \"disabled\"\n      check_sunos_service \"svc:/network/stlisten:default\"     \"disabled\"\n      check_sunos_service \"svc:/application/stosreg:default\"  \"disabled\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sunos/audit_slp.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_slp\n#\n# Turn off slp\n#.\n\naudit_slp () {\n  print_function \"audit_slp\"\n  string=\"SLP Daemon\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n      check_sunos_service \"svc:/network/slp:default\" \"disabled\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sunos/audit_solaris_auditing.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2046\n# shellcheck disable=SC2154\n\n# audit_solaris_auditing\n#\n# Check auditing setup on Solaris 11\n# Need to investigate more auditing capabilities on Solaris 10\n#.\n\naudit_solaris_auditing () {\n  print_function \"audit_solaris_auditing\"\n  string=\"Solaris Auditing\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"11\" ]; then\n      check_command_output \"getcond\"\n      check_command_output \"getpolicy\"\n      check_command_output \"getnaflags\"\n      check_command_output \"getplugin\"\n      check_command_output \"userattr\"\n      if [ \"${audit_mode}\" != 1 ]; then\n        audit -s\n      fi\n      check_file=\"/var/spool/cron/crontabs/root\"\n      if [ \"${audit_mode}\" = 0 ]; then\n        log_file=\"$workdir${check_file}\"\n        rolemod -K audit_flags=lo,ad,ft,ex,lck:no root\n        if [ -f \"${check_file}\" ]; then\n          command=\"grep \\\"audit -n\\\" \\\"${check_file}\\\" | cut -f4 -d'/'\"\n          command_message     \"${command}\"\n          audit_check=$( eval \"${command}\" )\n          if [ \"$audit_check\" != \"audit -n\" ]; then\n            if [ ! -f \"${log_file}\" ]; then\n              verbose_message \"File ${check_file} to ${work_dir}${check_file}\" \"save\"\n              command=\"find \\\"${check_file}\\\" | cpio -pdm \\\"${work_dir}\\\" 2> /dev/null\"\n              command_message \"${command}\"\n              eval \"${command}\"\n            fi\n            command=\"echo \\\"0 * * * * /usr/sbin/audit -n\\\" >> \\\"${check_file}\\\"\"\n            command_message \"${command}\"\n            eval \"${command}\"\n            command=\"chown root:root /var/audit\"\n            command_message \"${command}\"\n            eval \"${command}\"\n            command=\"chmod 750 /var/audit\"\n            command_message \"${command}\"\n            eval \"${command}\"\n            command=\"pkg   fix $( pkg search \\\"${check_file}\\\" | grep pkg | awk '{print \\$4}' )\"\n            command_message \"${command}\"\n            eval \"${command}\"\n          fi\n        fi\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sunos/audit_stack_protection.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_stack_protection\n#\n# Check Stack Protection\n#\n# Checks for the following values in /etc/system:\n#\n# set noexec_user_stack=1\n# set noexec_user_stack_log=1\n#\n# Refer to Section(s) 3.2 Page(s) 26-7 CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 3.3 Page(s) 62-3 CIS Solaris 10 Benchmark v5.1.0\n#.\n\naudit_stack_protection () {\n  print_function \"audit_stack_protection\"\n  string=\"Stack Protection\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    check_file_value \"is\" \"/etc/system\" \"set noexec_user_stack\"     \"eq\" \"1\" \"star\"\n    check_file_value \"is\" \"/etc/system\" \"set noexec_user_stack_log\" \"eq\" \"1\" \"star\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sunos/audit_svccfg_value.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_svccfg_value\n#\n# Check syscfg settings\n#.\n\naudit_svccfg_value () {\n  print_function \"audit_svccfg_value\"\n  string=\"RPC Port Mapping\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    service_name=\"${1}\"\n    service_property=\"${2}\"\n    correct_value=\"${3}\"\n    command=\"svccfg -s \\\"${service_name}\\\" listprop \\\"${service_property}\\\" | awk '{print \\$3}'\"\n    command_message       \"${command}\"\n    current_value=$( eval \"${command}\" )\n    file_header=\"svccfg\"\n    log_file=\"${work_dir}/${file_header}.log\"\n    if [ \"${audit_mode}\" = 2 ]; then\n      restore_file=\"${restore_dir}/${file_header}.log\"\n      if [ -f \"${restore_file}\" ]; then\n        command=\"grep \\\"${service_name}\\\" \\\"${restore_file}\\\" | cut -f2 -d','\"\n        command_message          \"${command}\"\n        restore_property=$( eval \"${command}\" )\n        command=\"grep \\\"${service_name}\\\" \\\"${restore_file}\\\" | cut -f3 -d','\"\n        command_message       \"${command}\"\n        restore_value=$( eval \"${command}\" )\n        command=\"expr \\\"${restore_property}\\\" : \\\"[A-z]\\\"\"\n        command_message       \"${command}\"\n        restore_check=$( eval \"${command}\" )\n        if [ \"${restore_check}\" = \"1\" ]; then\n          if [ \"${current_value}\" != \"${restore_value}\" ]; then\n            restore_message=\"Service \\\"${service_name}\\\" Property \\\"${restore_property}\\\" to \\\"${restore_value}\\\"\"\n            restore_command=\"svccfg -s ${service_name} setprop ${restore_property} = ${restore_value}\"\n            command_message \"${restore_command}\"\n            execute_restore \"${restore_command}\" \"${restore_message}\" \"sudo\"\n          fi\n        fi\n      fi\n    else\n      verbose_message \"Service ${service_name}\"\n    fi\n    if [ \"${current_value}\" != \"${correct_value}\" ]; then\n      lock_command=\"svccfg -s ${service_name} setprop ${service_property} = ${correct_value}\"\n      if [ \"${audit_mode}\" = 1 ]; then\n        inc_insecure \"Service \\\"${service_name}\\\" Property \\\"${service_property}\\\" not set to \\\"${correct_value}\\\"\"\n        fix_message  \"${lock_command}\"\n      else\n        if [ \"${audit_mode}\" = 0 ]; then\n          update_log   \"${log_file}\" \"${service_name},${service_property},${current_value}\"\n          lock_message=\"${service_name} ${service_property} to ${correct_value}\"\n          run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n        fi\n      fi\n    else\n      if [ \"${audit_mode}\" != 2 ]; then\n        if [ \"${audit_mode}\" = 1 ]; then\n          inc_secure \"Service \\\"${service_name}\\\" Property \\\"${service_property}\\\" already set to \\\"${correct_value}\\\"\"\n        fi\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sunos/audit_svm.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_svm\n#\n# Check volume manager daemons disabled\n#\n# Refer to Section(s) 2.2.8,12 Page(s) 28,32-3 CIS Solaris 10 Benchmark v5.1.0\n#.\n\naudit_svm () {\n  print_function \"audit_svm\"\n  string=\"Solaris Volume Manager Daemons\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ]; then\n      check_sunos_service   \"svc:/system/metainit\"              \"disabled\"\n      check_sunos_service   \"svc:/system/mdmonitor\"             \"disabled\"\n      if [ \"${os_update}\" -lt 4 ]; then\n        check_sunos_service \"svc:/platform/sun4u/mpxio-upgrade\" \"disabled\"\n      else\n        check_sunos_service \"svc:/system/device/mpxio-upgrade\"  \"disabled\"\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sunos/audit_svm_gui.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_svm_gui\n#\n# Check Solaris Volume Manager GUI daemons disabled\n#\n# Refer to Section(s) 2.2.13 Page(s) 33-4 CIS Solaris 10 Benchmark v5.1.0\n#.\n\naudit_svm_gui () {\n  print_function \"audit_svm_gui\"\n  string=\"Solaris Volume Manager GUI Daemons\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ]; then\n      check_sunos_service \"svc:/network/rpc/mdcomm\"  \"disabled\"\n      check_sunos_service \"svc:/network/rpc/meta\"    \"disabled\"\n      check_sunos_service \"svc:/network/rpc/metamed\" \"disabled\"\n      check_sunos_service \"svc:/network/rpc/metamh\"  \"disabled\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sunos/audit_ticotsord.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_ticotsord\n#\n# Turn off ticotsord\n#.\n\naudit_ticotsord () {\n  print_function \"audit_ticotsord\"\n  string=\"Ticotsord Daemon\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n      check_sunos_service \"svc:/network/rpc-100235_1/rpc_ticotsord:default\" \"disabled\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sunos/audit_tname.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_tname\n#\n# Turn off tname\n#.\n\naudit_tname () {\n  print_function \"audit_tname\"\n  string=\"Tname Daemon\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n      check_sunos_service \"svc:/network/tname:default\" \"disabled\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sunos/audit_tnd.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_tnd\n#\n# Turn off tnd\n#.\n\naudit_tnd () {\n  print_function \"audit_tnd\"\n  string=\"TN Daemon\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n      check_sunos_service \"svc:/network/tnd:default\" \"disabled\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sunos/audit_uucp.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_uucp\n#\n# Turn off uucp and swat\n#.\n\naudit_uucp () {\n  print_function \"audit_uucp\"\n  string=\"UUCP Service\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n      verbose_message     \"Samba Web Configuration Deamon\" \"check\"\n      check_sunos_service \"svc:/network/swat:defaulte\"     \"disabled\"\n    fi\n    if [ \"${os_version}\" = \"10\" ]; then\n      verbose_message     \"UUCP Service\" \"check\"\n      check_sunos_service \"uucp\"         \"disabled\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sunos/audit_vnetd.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_vnetd\n#\n# VNET Daemon\n#\n# Turn off vnetd\n#.\n\naudit_vnetd () {\n  print_function \"audit_vnetd\"\n  string=\"VNET Daemon\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n      check_sunos_service \"svc:/network/vnetd/tcp:default\" \"disabled\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sunos/audit_volfs.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_volfs\n#\n# Refer to Section(s) 2.8 Page(s) 20-1 CIS Solaris 11.1 Benchmark v1.0.0\n#.\n\n\naudit_volfs () {\n  print_function \"audit_volfs\"\n  string=\"Volume Management Daemons\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ]; then\n      check_sunos_service \"svc:/system/filesystem/volfs\"    \"disabled\"\n    fi\n    if [ \"${os_version}\" = \"11\" ]; then\n      check_sunos_service \"svc:/system/filesystem/rmvolmgr\" \"disabled\"\n    fi\n    if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n      check_sunos_service \"svc:/network/rpc/smserver\"       \"disabled\"\n    fi\n    if [ \"${os_version}\" = \"10\" ]; then\n      check_sunos_service \"volmgt\"                          \"disabled\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sunos/audit_vopied.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_vopied\n#\n# Veritas Online Passwords In Everything\n#\n# Turn off vopied if not required. It is associated with Symantec products.\n#.\n\naudit_vopied () {\n  print_function \"audit_vopied\"\n  string=\"VOPIE Daemon\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n      check_sunos_service \"svc:/network/vopied/tcp:default\" \"disabled\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sunos/audit_wbem.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_wbem\n#\n# Turn off Web Based Enterprise Management\n#\n# Refer to Section(s) 2.1.6 Page(s) 21-2 CIS Solaris 10 Benchmark v5.1.0\n#.\n\naudit_wbem () {\n  print_function \"audit_wbem\"\n  string=\"Web Based Enterprise Management\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ]; then\n      check_sunos_service \"svc:/application/management/wbem\" \"disabled\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sunos/audit_webconsole.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_webconsole\n#\n# Turn of Web Console service\n#\n# Refer to Section(s) 2.1.5 Page(s) 20-1 CIS Solaris 10 Benchmark v5.1.0\n#.\n\naudit_webconsole () {\n  print_function \"audit_webconsole\"\n  string=\"Web Console\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ]; then\n      check_sunos_service \"svc:/system/webconsole:console\" \"disabled\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sunos/audit_webmin.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_webmin\n#\n# Turn off webmin if it is not being used.\n#.\n\naudit_webmin () {\n  print_function \"audit_webmin\"\n  string=\"Webmin Daemon\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n      check_sunos_service \"svc:/application/management/webmin:default\" \"disabled\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sunos/audit_wins.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_wins\n#\n# Turn off wins if not required\n#.\n\naudit_wins () {\n  print_function \"audit_wins\"\n  string=\"WINS Daemon\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n      check_sunos_service \"svc:/network/wins:default\" \"disabled\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/sunos/audit_zones.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_zones\n#\n# Turn off Zone services if zones are not being used.\n#.\n\naudit_zones () {\n  print_function \"audit_zones\"\n  string=\"Zone Daemons\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n      zone_check=$( zoneadm list -civ | awk '{print $1}' | grep 1 )\n      if [ \"${zone_check}\" != \"1\" ]; then\n        check_sunos_service \"svc:/system/rcap:default\"       \"disabled\"\n        check_sunos_service \"svc:/system/pools:default\"      \"disabled\"\n        check_sunos_service \"svc:/system/tsol-zones:default\" \"disabled\"\n        check_sunos_service \"svc:/system/zones:default\"      \"disabled\"\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/syslog/audit_syslog_auth.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_syslog_auth\n#\n# Check auth log\n#\n# Refer to Section(s) 4.4 Page(s) 68-9 CIS Solaris 10 Benchmark v5.1.0\n#.\n\naudit_syslog_auth () {\n  print_function \"audit_syslog_auth\"\n  string=\"SYSLOG AUTH Messages\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_version}\" = \"10\" ]; then\n      audit_logadm_value \"authlog\" \"auth.info\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/syslog/audit_syslog_conf.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_syslog_conf\n#\n# Check syslog confg\n#\n# Refer to Section(s) 3.4     Page(s) 10    CIS FreeBSD Benchmark v1.0.5\n# Refer to Section(s) 5.1.1   Page(s) 104-5 CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 1.11.13 Page(s) 39-40 CIS ESX Server 4 Benchmark v1.1.0\n#\n# Refer to http://kb.vmware.com/kb/1033696\n# Refer to http://pubs.vmware.com/vsphere-55/topic/com.vmware.vsphere.security.doc/GUID-9F67DB52-F469-451F-B6C8-DAE8D95976E7.html\n#.\n\naudit_syslog_conf () {\n  print_function \"audit_syslog_conf\"\n  string=\"Syslog Configuration\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"FreeBSD\" ] || [ \"${os_name}\" = \"VMkernel\" ]; then\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      check_file=\"/etc/syslog.conf\"\n      if [ -f \"/etc/rsyslog.conf\" ]; then\n        systemd_check=$(command -v systemctl 2> /dev/null )\n        if [ -n \"$systemd_check\" ]; then\n          command=\"sudo systemctl | grep rsyslog | grep active | awk '{print \\$1}'\"\n          command_message       \"${command}\"\n          rsyslog_check=$( eval \"${command}\" )\n          if [ \"$rsyslog_check\" = \"rsyslog.service\" ]; then\n            if [ -f \"/etc/rsyslog.d/90-cis.conf\" ]; then\n              check_file=\"/etc/rsyslog.d/90-cis.conf\"\n            else\n              check_file=\"/etc/rsyslog.conf\"\n            fi\n          fi\n        fi\n      fi\n      check_file_value \"is\" \"${check_file}\" \"authpriv.*\" \"tab\" \"/var/log/secure\"     \"hash\"\n      check_file_value \"is\" \"${check_file}\" \"auth.*\"     \"tab\" \"/var/log/messages\"   \"hash\"\n      check_file_value \"is\" \"${check_file}\" \"daemon.*\"   \"tab\" \"/var/log/daemon.log\" \"hash\"\n      check_file_value \"is\" \"${check_file}\" \"syslog.*\"   \"tab\" \"/var/log/syslog\"     \"hash\"\n      check_file_value \"is\" \"${check_file}\" \"lpr,news,uucp,local0,local1,local2,local3,local4,local5,local6.*\" \"tab\" \"/var/log/unused.log\" \"hash\"\n    fi\n    if [ \"${os_name}\" = \"FreeBSD\" ]; then\n      check_file_value \"is\" \"/etc/rc.conf\" \"syslogd_flags\" \"eq\" \"-s\" \"hash\"\n    fi\n    if [ \"${os_name}\" = \"VMkernel\" ]; then\n      log_file=\"sysloglogdir\"\n      backup_file=\"${work_dir}/${log_file}\"\n      command=\"esxcli system syslog config get | grep 'Local Log Output:' | awk '{print \\$4}'\"\n      command_message \"${command}\"\n      current_value=$( eval \"${command}\" )\n      if [ \"${audit_mode}\" != \"2\" ]; then\n        if [ \"${current_value}\" = \"/scratch/log\" ]; then\n          if [ \"${audit_mode}\" = \"0\" ]; then\n            if [ \"${syslog_logdir}\" != \"\" ]; then\n              echo \"${current_value}\" > \"${backup_file}\"\n              verbose_message \"Setting:   Syslog log directory to a persistent datastore\"\n              esxcli system syslog config set --logdir=\"${syslog_logdir}\"\n            fi\n          fi\n          if [ \"${audit_mode}\" = \"1\" ]; then\n            inc_insecure  \"Syslog log directory is not persistent\"\n            if [ \"${syslog_logdir}\" != \"\" ]; then\n              fix_message \"esxcli system syslog config set --logdir=${syslog_logdir}\"\n            fi\n          fi\n        else\n          if [ \"${audit_mode}\" = \"1\" ]; then\n            inc_secure    \"Syslog log directory is on a persistent datastore\"\n          fi\n        fi\n      else\n        restore_file=\"${restore_dir}/${log_file}\"\n        if [ -f \"${restore_file}\" ]; then\n          previous_value=$( cat \"${restore_file}\" )\n          if [ \"${previous_value}\" != \"${current_value}\" ]; then\n            verbose_message \"Restoring: Syslog log directory to ${previous_value}\"\n            command=\"esxcli system syslog config set --logdir=\\\"${previous_value}\\\"\"\n            command_message \"${command}\"\n            eval \"${command}\"\n          fi\n        fi\n      fi\n      log_file=\"syslogremotehost\"\n      backup_file=\"${work_dir}/${log_file}\"\n      command=\"esxcli system syslog config get | grep Remote | awk '{print \\$3}'\"\n      command_message       \"${command}\"\n      current_value=$( eval \"${command}\" )\n      if [ \"${audit_mode}\" != \"2\" ]; then\n        if [ \"${current_value}\" = \"<none>\" ]; then\n          if [ \"${audit_mode}\" = \"0\" ]; then\n            if [ \"${syslog_server}\" != \"\" ]; then\n              echo \"${current_value}\" > \"${backup_file}\"\n              command=\"esxcli system syslog config set --loghost=\\\"${syslog_server}\\\"\"\n              command_message \"${command}\"\n              eval \"${command}\"\n            fi\n          fi\n          if [ \"${audit_mode}\" = \"1\" ]; then\n            inc_insecure \"Syslog remote host is not enabled\"\n            if [ \"${syslog_server}\" = \"\" ]; then\n              fix_message \"esxcli system syslog config set --loghost=XXX.XXX.XXX.XXX\"\n            else\n              fix_message \"esxcli system syslog config set --loghost=${syslog_server}\"\n            fi\n          fi\n        else\n          if [ \"${audit_mode}\" = \"1\" ]; then\n            inc_secure \"Syslog remote host is enabled\"\n          fi\n        fi\n      else\n        restore_file=\"${restore_dir}/${log_file}\"\n        if [ -f \"${restore_file}\" ]; then\n          previous_value=$( cat \"${restore_file}\" )\n          if [ \"${previous_value}\" != \"${current_value}\" ]; then\n            verbose_message \"Restoring: Syslog loghost to \\\"${previous_value}\\\"\"\n            command=\"esxcli system syslog config set --loghost=\\\"${previous_value}\\\"\"\n            command_message \"${command}\"\n            eval \"${command}\"\n          fi\n        fi\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/syslog/audit_syslog_perms.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_syslog_perms\n#\n# Check syslog permissions\n#\n# Refer to Section(s) 11.7-8 Page(s) 146-7 CIS Solaris 10 Benchmark v1.1.0\n# Refer to Section(s) 5.1.2  Page(s) 105-6 CIS RHEL 5 Benchmark v2.1.0\n#.\n\naudit_syslog_perms () {\n  print_function \"audit_syslog_perms\"\n  string=\"Syslog Permissions\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      check_file_perms \"/var/log/syslog\"     \"0600\" \"root\" \"sys\"\n    fi\n    if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ]; then\n      check_file_perms \"/var/log/secure\"     \"0600\" \"root\" \"root\"\n      check_file_perms \"/var/log/messages\"   \"0600\" \"root\" \"root\"\n      check_file_perms \"/var/log/daemon.log\" \"0600\" \"root\" \"root\"\n      check_file_perms \"/var/log/unused.log\" \"0600\" \"root\" \"root\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/syslog/audit_syslog_server.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2063\n# shellcheck disable=SC2154\n\n# audit_syslog_server\n#\n# Check syslog server settings\n#\n# Refer to Section(s) 4.1.1-8           Page(s) 71-76   CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 5.2.1-8           Page(s) 108-113 CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 5.1.1-8           Page(s) 94-9    CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 4.2.1.1-5         Page(s) 192-198 CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 8.2.1-8           Page(s) 106-111 CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 5.1               Page(s) 18      CIS FreeBSD Benchmark v1.0.5\n# Refer to Section(s) 4.2.1.1-5         Page(s) 176-82  CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 4.2.1.1-5         Page(s) 187-93  CIS Ubuntu 16.04 Benchmark v1.0.0\n# Refer to Section(s) 4.2.1.1-4.2.2.7   Page(s) 556-92  CIS Ubuntu 22.04 Benchmark v1.0.0\n# Refer to Section(s) 6.1.1.1.1-6.1.3.7 Page(s) 728-86  CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_syslog_server () {\n  print_function \"audit_syslog_server\"\n  string=\"Syslog Server\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"FreeBSD\" ]; then\n    if [ \"${os_name}\" = \"FreeBSD\" ]; then\n      if [ \"${os_version}\" -lt 5 ]; then\n        check_file_value  \"is\" \"/etc/syslog.conf\"      \"daemon.debug\" \"tab\"  \"/var/log/daemon.log\" \"hash\"\n        check_file_exists      \"/var/log/daemon.log\"   \"file\"         \"yes\"\n        funct_file_perms       \"/var/log/daemon.log\"   \"600\"          \"root\" \"${wheel_group}\"\n      fi\n    fi\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      if [ \"${os_vendor}\" = \"Ubuntu\" ] && [ \"${os_version}\" -ge 22 ]; then\n        check_linux_package \"install\" \"systemd-journal-remote\"\n        if [ \"${syslog_server}\" != \"\" ]; then\n          check_file_value  \"is\" \"/etc/systemd/journal-upload.conf\" \"URL\"                     \"eq\" \"${syslog_server}\"                    \"hash\"\n        fi\n        check_file_value    \"is\" \"/etc/systemd/journal-upload.conf\" \"ServerKeyFile\"           \"eq\" \"/etc/ssl/private/journal-upload.pem\" \"hash\"\n        check_file_value    \"is\" \"/etc/systemd/journal-upload.conf\" \"ServerCertificateFile\"   \"eq\" \"/etc/ssl/certs/journal-upload.pem\"   \"hash\"\n        check_file_value    \"is\" \"/etc/systemd/journal-upload.conf\" \"TrustedCertificateFile\"  \"eq\" \"/etc/ssl/ca/trusted.pem\"             \"hash\"\n        check_file_value    \"is\" \"/etc/systemd/journald.conf\"       \"Compress\"                \"eq\" \"yes\"                                 \"hash\"\n        check_file_value    \"is\" \"/etc/systemd/journald.conf\"       \"Storage\"                 \"eq\" \"persistent\"                          \"hash\"\n        check_file_value    \"is\" \"/etc/systemd/journald.conf\"       \"ForwardToSyslog\"         \"eq\" \"yes\"                                 \"hash\"\n        check_file_value    \"is\" \"/etc/systemd/journald.conf\"       \"SystemMaxUse\"            \"eq\" \"1G\"                                  \"hash\"\n        check_file_value    \"is\" \"/etc/systemd/journald.conf\"       \"SystemKeepFree\"          \"eq\" \"500M\"                                \"hash\"\n        check_file_value    \"is\" \"/etc/systemd/journald.conf\"       \"RuntimeMaxUse\"           \"eq\" \"200M\"                                \"hash\"\n        check_file_value    \"is\" \"/etc/systemd/journald.conf\"       \"RuntimeKeepFree\"         \"eq\" \"50M\"                                 \"hash\"\n        check_file_value    \"is\" \"/etc/systemd/journald.conf\"       \"MaxFileSec\"              \"eq\" \"1month\"                              \"hash\"\n        check_linux_service      \"systemd-journal-upload.service\"   \"on\"\n        check_linux_service      \"systemd-journal-remote.socket\"    \"off\"\n        check_linux_service      \"systemd-journald.service\"         \"on\"\n        conf_file=\"/usr/lib/tmpfiles.d/systemd.conf\"\n        if [ -f \"/usr/lib/tmpfiles.d/systemd.conf\" ]; then\n          conf_file=\"/usr/lib/tmpfiles.d/systemd.conf\"\n        else\n          if [ -f \"/etc/tmpfiles.d/systemd.conf\" ]; then\n            conf_file=\"/etc/tmpfiles.d/systemd.conf\"\n          fi\n        fi\n        if [ -f \"${conf_file}\" ]; then\n          check_file_perms      \"${conf_file}\" \"0640\" \"root\" \"root\"\n          check_file_value \"is\" \"${conf_file}\" \"d /var/lib/private\"    \"space\" \"root root -\" \"hash\"\n          check_file_value \"is\" \"${conf_file}\" \"d /var/log/private\"    \"space\" \"root root -\" \"hash\"\n          check_file_value \"is\" \"${conf_file}\" \"d /var/cache/private\"  \"space\" \"root root -\" \"hash\"\n        fi\n      fi\n      conf_file=\"/etc/rsyslog.conf\"\n      if [ ! -f \"${conf_file}\" ]; then\n        if [ \"${install_rsyslog}\" = \"yes\" ]; then\n          check_linux_service \"syslog\"  \"off\"\n          check_linux_package \"install\" \"rsyslog\"\n          check_linux_service \"rsyslog\" \"on\"\n        fi\n      fi \n      if [ -f \"/etc/rsyslog.d/60-rsyslog.conf\" ]; then\n        conf_file=\"/etc/rsyslog.d/60-rsyslog.conf\"\n        check_file_value  \"is\" \"${conf_file}\" \"auth,authpriv.*\"         \"tab\" \"/var/log/secure\"         \"hash\"\n        check_file_value  \"is\" \"${conf_file}\" \"mail.*\"                  \"tab\" \"/var/log/mail\"           \"hash\"\n        check_file_value  \"is\" \"${conf_file}\" \"cron.*\"                  \"tab\" \"/var/log/cron\"           \"hash\"\n        check_file_value  \"is\" \"${conf_file}\" \"*.=warning;*.=err\"       \"tab\" \"/var/log/warn\"           \"hash\"\n        check_file_value  \"is\" \"${conf_file}\" \"*.crit\"                  \"tab\" \"/var/log/warn\"           \"hash\"\n        check_file_value  \"is\" \"${conf_file}\" \"*.*;mail.none;news.none\" \"tab\" \"/var/log/messages\"       \"hash\"\n        check_file_value  \"is\" \"${conf_file}\" \"local0,local1.*\"         \"tab\" \"/var/log/localmessages\"  \"hash\"\n        check_file_value  \"is\" \"${conf_file}\" \"local2,local3.*\"         \"tab\" \"/var/log/localmessages\"  \"hash\"\n        check_file_value  \"is\" \"${conf_file}\" \"local4,local5.*\"         \"tab\" \"/var/log/localmessages\"  \"hash\"\n        check_file_value  \"is\" \"${conf_file}\" \"local6,local1.*\"         \"tab\" \"/var/log/localmessages\"  \"hash\"\n        conf_file=\"/etc/rsyslog.d/50-default.conf\"\n        check_file_value  \"is\" \"${conf_file}\" \"auth,authpriv.*\"         \"tab\" \"/var/log/auth.log\"       \"hash\"\n        check_file_value  \"is\" \"${conf_file}\" \"*.*;auth,authpriv.*\"     \"tab\" \"/var/log/syslog\"         \"hash\"\n        check_file_value  \"is\" \"${conf_file}\" \"kern.*\"                  \"tab\" \"/var/log/kern.log\"       \"hash\"\n        check_file_value  \"is\" \"${conf_file}\" \"mail.*\"                  \"tab\" \"/var/log/mail\"           \"hash\"\n      else\n        if [ \"${os_vendor}\" = \"CentOS\" ] || [ \"${os_vendor}\" = \"Red\" ] || [ \"${os_vendor}\" = \"SuSE\" ] || [ \"${os_vendor}\" = \"Amazon\" ]; then\n          if [ \"${os_version}\" -lt 4 ]; then\n            check_file_value   \"is\" \"${conf_file}\" \"*.emerg\"                 \"tab\" \":omusrmsg:*\"         \"hash\"\n            check_file_value   \"is\" \"${conf_file}\" \"mail.*\"                  \"tab\" \"/var/log/mail\"       \"hash\"\n            check_file_value   \"is\" \"${conf_file}\" \"cron.*\"                  \"tab\" \"/var/log/cron\"       \"hash\"\n            check_file_value   \"is\" \"${conf_file}\" \"*.crit\"                  \"tab\" \"/var/log/warn\"       \"hash\"\n            check_file_value   \"is\" \"${conf_file}\" \"kern.*\"                  \"tab\" \"/var/log/kern.log\"   \"hash\"\n            check_file_value   \"is\" \"${conf_file}\" \"daemon.*\"                \"tab\" \"/var/log/daemon.log\" \"hash\"\n            check_file_value   \"is\" \"${conf_file}\" \"syslog.*\"                \"tab\" \"/var/log/syslog\"     \"hash\"\n            check_file_value   \"is\" \"${conf_file}\" \"auth,user.*\"             \"tab\" \"/var/log/auth.log\"   \"hash\"\n            check_file_value   \"is\" \"${conf_file}\" \"auth,authpriv.*\"         \"tab\" \"/var/log/secure\"     \"hash\"\n            check_file_value   \"is\" \"${conf_file}\" \"*.=warning;*.=err\"       \"tab\" \"/var/log/warn\"       \"hash\"\n            check_file_value   \"is\" \"${conf_file}\" \"*.*;mail.none;news.none\" \"tab\" \"/var/log/messages\"   \"hash\"\n            check_file_value   \"is\" \"${conf_file}\" \"lpr,news,uucp,local0,local1,local2,local3,local4,local5,local6.*\" \"tab\" \"/var/log/localmessages\" \"hash\"\n            funct_file_perms        \"${conf_file}\" \"0600\" \"root\" \"root\"\n            if [ \"${audit_mode}\" != 2 ]; then\n              command=\"grep -v '#' \\\"${check_file}\\\" | grep \\\"*.* @@\\\" | grep -v localhost | grep -c \\\"[A-Z]|[a-z]\\\"\"\n              command_message \"${command}\"\n              remote_check=$( eval \"${command}\" )\n              if [ \"${remote_check}\" != \"1\" ]; then\n                if [ \"${audit_mode}\" = 1 ] || [ \"${audit_mode}\" = 0 ]; then\n                  inc_insecure \"Rsyslog is not sending messages to a remote server\"\n                  fix_message  \"Add a server entry to ${check_file}, eg:\"\n                  fix_message  \"*.* @@loghost.example.com\"\n                fi\n              else\n                inc_secure \"Rsyslog is sending messages to a remote server\"\n              fi\n            fi\n          fi\n        fi\n      fi\n      conf_file=\"/etc/rsyslog.conf\"\n      if [ -f \"${conf_file}\" ]; then\n        command=\"grep -E \\\"imtcp|imudp\\\" < \\\"${conf_file}\\\" | grep -cv \\\"^#\\\" | sed \\\"s/ //g\\\"\"\n        command_message      \"${command}\"\n        server_check=$( eval \"${command}\" )\n        if [ \"${server_check}\" = \"0\" ]; then\n          inc_secure     \"Rsyslog is not running in server mode\"\n        else\n          inc_insecure   \"Rsyslog is running in server mode\"\n        fi\n        check_file_value \"is\" \"${conf_file}\" \"\\$FileCreateMode\" \"space\" \"0640\" \"hash\"\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/talk/audit_talk_client.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_talk_client\n#\n# Uninstall talk client\n#\n# Refer to Section(s) 2.1.9 Page(s) 53    CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 2.1.9 Page(s) 61    CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 2.1.9 Page(s) 55-6  CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 2.3.3 Page(s) 126   CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 5.2.6 Page(s) 43-4  CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 2.3.3 Page(s) 113   CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 2.3.3 Page(s) 122   CIS Ubuntu 16.04 Benchmark v1.0.0\n# Refer to Section(s) 2.2.3 Page(s) 296-7 CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_talk_client () {\n  print_function \"audit_talk_client\"\n  string=\"Talk Client\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    check_linux_package \"uninstall\" \"talk\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/talk/audit_talk_server.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_talk_server\n#\n# Turn off talk server\n#\n# Refer to Section(s) 2.1.10 Page(s) 53-54 CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 2.1.10 Page(s) 61-2  CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 2.1.10 Page(s) 56    CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 2.1.18 Page(s) 119   CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 5.1.5  Page(s) 43    CIS SLES 11 Benchmark v1.0.0\n#.\n\naudit_talk_server () {\n  print_function \"audit_talk_server\"\n  string=\"Talk Server\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${os_vendor}\" = \"CentOS\" ] || [ \"${os_vendor}\" = \"Red\" ] || [ \"${os_vendor}\" = \"Amazon\" ]; then\n      check_linux_service \"ntalk\"     \"off\"\n      check_linux_package \"uninstall\" \"talk-server\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/tcp/audit_tcp_strong_iss.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_tcp_strong_iss\n#\n# Strong TCP Sequence Number Generation\n#\n# Checks for the following values in /etc/default/inetinit:\n#\n# TCP_STRONG_ISS=2\n#\n# 0 = Old-fashioned sequential initial sequence number generation.\n# 1 = Improved sequential generation, with random variance in increment.\n# 2 = RFC 1948 sequence number generation, unique-per-connection-ID.\n#\n# Refer to Section(s) 3.3 Page(s) 27-8 CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 3.4 Page(s) 63-4 CIS Solaris 10 Benchmark v5.1.0\n#.\n\naudit_tcp_strong_iss () {\n  print_function \"audit_tcp_strong_iss\"\n  string=\"TCP Sequence Number Generation\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    check_file_value \"is\" \"/etc/default/inetinit\" \"TCP_STRONG_ISS\" \"eq\" \"2\" \"hash\"\n    if [ \"${os_version}\" != \"11\" ]; then\n      audit_ndd_value   \"/dev/tcp\"    \"tcp_strong_iss\" \"2\"\n    fi\n    if [ \"${os_version}\" = \"11\" ]; then\n      audit_ipadm_value \"_strong_iss\" \"tcp\" \"2\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/tcp/audit_tcp_syn_cookie.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_tcpsyn_cookie\n#\n# TCP SYN Cookie Protection\n#\n# Refer to Section(s) 4.2.8 Page(s) 90-1 CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 4.2.8 Page(s) 82-3 CIS RHEL 6 Benchmark v1.2.0\n#.\n\naudit_tcp_syn_cookie () {\n  print_function \"audit_tcp_syn_cookie\"\n  string=\"TCP SYN Cookie Protection\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    check_append_file \"/etc/rc.d/local\" \"echo 1 > /proc/sys/net/ipv4/tcp_syncookies\" \"hash\"\n    check_file_perms  \"/etc/rc.d/local\" \"0600\" \"root\" \"root\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/tcp/audit_tcp_wrappers.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2046\n# shellcheck disable=SC2154\n\n# audit_tcp_wrappers\n#\n# Check TCP wrappers\n#\n# Refer to Section(s) 5.5.1-5  Page(s) 110-114 CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 4.5.1-5  Page(s) 95-8    CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 4.5.1-5  Page(s) 86-9    CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 3.4.1-5  Page(s) 143-8   CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 7.4.1-5  Page(s) 77-80   CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 1.3      Page(s) 3-4     CIS FreeBSD Benchmark v1.0.5\n# Refer to Section(s) 2.10.1-4 Page(s) 188-192 CIS AIX Benchmark v1.1.0\n# Refer to Section(s) 2.11     Page(s) 22-3    CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 2.4      Page(s) 36-7    CIS Solaris 10 Benchmark v5.1.0\n# Refer to Section(s) 3.4.1-5  Page(s) 1verbose_message \"-4   CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 3.4.1-5  Page(s) 139-43  CIS Ubuntu 16.04 Benchmark v2.0.0\n#.\n\naudit_tcp_wrappers () {\n  print_function \"audit_tcp_wrappers\"\n  string=\"TCP Wrappers\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"FreeBSD\" ] || [ \"${os_name}\" = \"Darwin\" ] || [ \"${os_name}\" = \"AIX\" ]; then\n    if [ \"${os_name}\" = \"AIX\" ]; then\n      package_name=\"netsec.options.tcpwrapper.base\"\n      check_lslpp \"${package_name}\"\n      if [ \"${audit_mode}\" != 2 ]; then\n        if [ \"${lslpp_check}\" != \"${package_name}\" ]; then\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_insecure \"TCP Wrappers not installed\"\n            fix_message  \"TCP Wrappers not installed\"\n            fix_message  \"Install TCP Wrappers\"\n          fi\n        else\n          inc_secure     \"TCP Wrappers installed\"\n        fi\n      fi\n    fi\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      if [ \"${os_version}\" = \"10\" ] || [ \"${os_version}\" = \"11\" ]; then\n        audit_rpc_bind\n        for service_name in $( inetadm | awk '{print $3}' | grep \"^svc\" ); do\n          check_command_value \"inetadm\" \"tcp_wrappers\" \"TRUE\" \"${service_name}\"\n        done\n      fi\n    fi\n    if [ \"${os_name}\" = \"FreeBSD\" ]; then\n      check_file_value \"is\" \"/etc/rc.conf\"     \"inetd_enable\" \"eq\"     \"YES\"           \"hash\"\n      check_file_value \"is\" \"/etc/rc.conf\"     \"inetd_flags\"  \"eq\"     \"-Wwl -C60\"     \"hash\"\n    fi\n    check_file_value   \"is\" \"/etc/hosts.deny\"  \"ALL\"          \"colon\" \" ALL\"           \"hash\"\n    check_file_value   \"is\" \"/etc/hosts.allow\" \"ALL\"          \"colon\" \" localhost\"     \"hash\"\n    check_file_value   \"is\" \"/etc/hosts.allow\" \"ALL\"          \"colon\" \" 127.0.0.1\"     \"hash\"\n    ip_list=$( who | cut -d\"(\" -f2 | cut -d\")\" -f1 | sort -u )\n    for ip_address in ${ip_list}; do\n      check_file_value \"is\" \"/etc/hosts.allow\" \"ALL\"          \"colon\" \" ${ip_address}\" \"hash\"\n    done\n    if [ ! -f \"${check_file}\" ]; then\n      check=$( command -v ifconfig 2> /dev/null )\n      if [ \"${check}\" ]; then\n        command=\"ifconfig -a | grep 'inet [0-9]' | grep -v ' 127.' | awk '{print \\$2}' | cut -f2 -d':'\"\n        command_message \"${command}\"\n        ip_list=$( eval \"${command}\" )\n        for ip_address in ${ip_list}; do\n          netmask=$( ifconfig -a | grep \"${ip_address}\" | awk '{print $3}' | cut -f2 -d:)\n          for daemon in ${tcpd_allow}; do\n            check_file_value \"is\" \"${check_file}\" \"${daemon}\" \"colon\" \" ${ip_address}/${netmask}\" \"hash\"\n          done\n        done\n      else\n        check=$( command -v ip 2> /dev/null )\n        if [ \"${check}\" ]; then\n          command=\"ip addr | grep 'inet [0-9]' | grep -v ' 127.' | awk '{print \\$2}'\"\n          command_message   \"${command}\"\n          ip_values=$( eval \"${command}\" )\n          for ip_value in $ip_values; do\n            set -- $( echo \"$ip_value\" | awk -F\"/\" '{print $1\" \"$2 }' )\n            ip_address=\"${1}\"\n            cidr=\"${2}\"\n            netmask=$( cidr_to_mask \"$cidr\" )\n            for daemon in ${tcpd_allow}; do\n              check_file_value \"is\" \"${check_file}\" \"${daemon}\" \"colon\" \" ${ip_address}/${netmask}\" \"hash\"\n            done\n          done\n        fi\n      fi\n    fi\n    if [ \"${os_name}\" = \"AIX\" ]; then\n      group_name=\"system\"\n    else\n      group_name=\"root\"\n    fi\n    check_file_perms \"/etc/hosts.deny\"  \"0644\" \"root\" \"${group_name}\"\n    check_file_perms \"/etc/hosts.allow\" \"0644\" \"root\" \"${group_name}\"\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      if [ \"${os_vendor}\" = \"Red\" ] || [ \"${os_vendor}\" = \"SuSE\" ] || [ \"${os_vendor}\" = \"CentOS\" ] || [ \"${os_vendor}\" = \"Amazon\" ] ; then\n        check_linux_package \"install\" \"tcp_wrappers\"\n      else\n        check_linux_package \"install\" \"tcpd\"\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/telnet/audit_telnet_banner.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_telnet_banner\n#\n# Set telnet banner\n#\n# Refer to Section(s) 8.5 Page(s) 71    CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 8.5 Page(s) 114-5 CIS Solaris 10 Benchmark v5.1.0\n#.\n\naudit_telnet_banner () {\n  print_function \"audit_telnet_banner\"\n  string=\"Telnet Banner\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    check_file_value \"is\" \"/etc/default/telnetd\" \"BANNER\" \"eq\" \"/etc/issue\" \"hash\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/telnet/audit_telnet_client.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_telnet_client\n#\n# If telnet is not installed\n#\n# Refer to Section(s) 2.1.2 Page(s) 49    CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 2.1.2 Page(s) 56    CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 2.1.2 Page(s) 51    CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 2.3.4 Page(s) 127   CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 2.3.4 Page(s) 114   CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 2.3.4 Page(s) 123   CIS Ubuntu 16.04 Benchmark v1.0.0\n# Refer to Section(s) 2.2.4 Page(s) 298-9 CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_telnet_client () {\n  print_function \"audit_telnet_client\"\n  string=\"Telnet Client\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    check_linux_package \"uninstall\" \"telnet\"\n    check_linux_package \"uninstall\" \"inetutils-telnet\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/telnet/audit_telnet_server.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_telnet_server\n#\n# Turn off telner server\n#\n# Refer to Section(s) 2.1.1 Page(s) 47-48 CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 2.1.1 Page(s) 55    CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 2.1.1 Page(s) 50-1  CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 2.1.1 Page(s) 55    CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 5.1.7 Page(s) 44    CIS SLES 11 Benchmark v1.0.0\n#.\n\naudit_telnet_server () {\n  print_function \"audit_telnet_server\"\n  string=\"Telnet Server\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${os_vendor}\" = \"CentOS\" ] || [ \"${os_vendor}\" = \"Red\" ] || [ \"${os_name}\" = \"Amazon\" ]; then\n      check_linux_service \"telnet.socket\" \"off\"\n      check_linux_package \"uninstall\"     \"telnet-server\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/users/audit_daemon_umask.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_daemon_umask\n#\n# Check daemon umask\n#\n# Refer to Section(s) 3.1 Page(s) 58-9 CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 3.2 Page(s) 72   CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 3.1 Page(s) 61-2 CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 3.3 Page(s) 9-10 CIS FreeBSD Benchmark v1.0.5\n# Refer to Section(s) 5.1 Page(s) 75-6 CIS Solaris 10 Benchmark v5.1.0\n#.\n\naudit_daemon_umask () {\n  print_function \"audit_daemon_umask\"\n  string=\"Daemon Umask\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"FreeBSD\" ]; then\n    if [ \"${my_id}\" != \"0\" ] && [ \"${use_sudo}\" = \"0\" ]; then\n      verbose_message \"Requires sudo to check\" \"notice\"\n      return\n    fi\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      if [ \"${os_version}\" = \"11\" ]; then\n        command=\"svcprop -p umask/umask svc:/system/environment:init\"\n        command_message      \"${command}\"\n        umask_check=$( eval  \"${command}\" )\n        umask_value=\"022\"\n        log_file=\"umask.log\"\n        if [ \"${umask_check}\" != \"${umask_value}\" ]; then\n          log_file=\"${work_dir}/${log_file}\"\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_insecure     \"Default service file creation mask not set to ${umask_value}\"\n            verbose_message  \"svccfg -s svc:/system/environment:init setprop umask/umask = astring:  \\\"${umask_value}\\\"\" \"fix\"\n          fi\n          if [ \"${audit_mode}\" = 0 ]; then\n            verbose_message  \"Setting:   Default service file creation mask to ${umask_value}\"\n            if [ ! -f \"${log_file}\" ]; then\n              echo \"${umask_check}\" >> \"${log_file}\"\n            fi\n            svccfg -s svc:/system/environment:init setprop umask/umask = astring:  \"${umask_value}\"\n          fi\n        else\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_secure \"Default service file creation mask set to ${umask_value}\"\n          fi\n          if [ \"${audit_mode}\" = 2 ]; then\n            restore_file=\"${restore_dir}/${log_file}\"\n            if [ -f \"${restore_file}\" ]; then\n              restore_value=$( cat \"${restore_file}\" )\n              if [ \"${restore_value}\" != \"${umask_check}\" ]; then\n                verbose_message \"Restoring:  Default service file creation mask to ${restore_value}\"\n                svccfg -s svc:/system/environment:init setprop umask/umask = astring:  \"${restore_value}\"\n              fi\n            fi\n          fi\n        fi\n      else\n        if [ \"${os_version}\" = \"7\" ] || [ \"${os_version}\" = \"6\" ]; then\n          check_file=\"/etc/init.d/umask.sh\"\n          check_file_value \"is\" \"${check_file}\" \"umask\" \"space\" \"022\" \"hash\"\n          if [ \"${audit_mode}\" = \"0\" ]; then\n            if [ -f \"${check_file}\" ]; then\n              check_file_perms  \"${check_file}\" \"0744\"  \"root\"  \"sys\"\n              for dir_name in /etc/rc?.d; do\n                link_file=\"${dir_name}/S00umask\"\n                if [ ! -f \"$link_file\" ]; then\n                  ln -s \"${check_file}\" \"$link_file\"\n                fi\n              done\n            fi\n          fi\n        else\n          check_file=\"/etc/default/init\"\n          check_file_value \"is\" \"${check_file}\" \"CMASK\" \"eq\" \"022\" \"hash\"\n        fi\n      fi\n    fi\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      check_file=\"/etc/sysconfig/init\"\n      check_file_value \"is\" \"${check_file}\" \"umask\" \"space\" \"027\" \"hash\"\n      if [ \"${audit_mode}\" = \"0\" ]; then\n        if [ -f \"${check_file}\" ]; then\n          check_file_perms  \"${check_file}\" \"0755\"  \"root\"  \"root\"\n        fi\n      fi\n    fi\n    # Check relevant /etc/* directoris for files with a potential umasks\n    for dir_name in /etc /etc/rc0.d /etc/rc1.d /etc/rc2.d /etc/rc4.d /etc/rc5.d /etc/rcS.d /usr/local/etc; do\n      if [ -e \"${dir_name}\" ]; then\n        file_list=$( find /etc/ -maxdepth 1 -type f )\n        for check_file in ${file_list}; do\n          umask_test=$( grep -c \"umask\" \"${check_file}\" | sed \"s/ //g\" )\n          if [ ! \"$umask_test\" = \"0\" ]; then\n            check_file_value \"is\" \"${check_file}\" \"umask\" \"space\" \"077\" \"hash\"\n          fi\n        done\n      fi\n    done \n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/users/audit_default_umask.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_default_umask\n#\n# Check default umask\n#\n# Refer to Section(s) 7.4             Page(s) 147-8         CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 7.4             Page(s) 170-1         CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 7.4             Page(s) 150-1         CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 5.4.4           Page(s) 254-5         CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 10.4            Page(s) 140           CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 8.8             Page(s) 29            CIS FreeBSD Benchmark v1.0.5\n# Refer to Section(s) 7.3             Page(s) 64-5          CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 7.6             Page(s) 106-7         CIS Solaris 10 Benchmark v5.1.0\n# Refer to Section(s) 5.4.4           Page(s) 233-4         CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 5.4.4           Page(s) 246-7         CIS Ubuntu 16.04 Benchmark v1.0.0\n# Refer to Section(s) 5.4.2.6,5.4.3.3 Page(s) 705-7,719-25  CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_default_umask () {\n  print_function \"audit_default_umask\"\n  string=\"Default umask for Users\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"FreeBSD\" ]; then\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      check_file_value    \"is\" \"/etc/default/login\" \"UMASK\" \"eq\"    \"077\" \"hash\"\n    fi\n    if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"FreeBSD\" ]; then\n      for check_file in /etc/.login /etc/profile /etc/skel/.bash_profile /etc/csh.login \\\n        /etc/csh.cshrc /etc/zprofile /etc/skel/.zshrc /etc/skel/.bashrc; do\n        check_file_value  \"is\" \"${check_file}\"      \"umask\" \"space\" \"077\" \"hash\"\n      done\n      for check_file in /etc/bashrc /etc/skel/.bashrc /etc/login.defs; do\n        check_file_value  \"is\" \"${check_file}\"      \"UMASK\" \"eq\"    \"077\" \"hash\"\n      done\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/users/audit_dot_files.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_dot_files\n#\n# Check for a dot file and copy it to backup directory\n#.\n\naudit_dot_files () {\n  print_function \"audit_dot_files\"\n  string=\"Dot Files\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ]; then\n    check_file=\"${1}\"\n    if [ \"${audit_mode}\" != 2 ]; then\n      dir_list=$( cut -f6 -d':' /etc/passwd )\n      for dir_name in ${dir_list}; do\n        if [ \"${dir_name}\" = \"/\" ]; then\n          dot_file=\"/${check_file}\"\n        else\n          dot_file=\"${dir_name}/${check_file}\"\n        fi\n        if [ -f \"${dot_file}\" ]; then\n          if [ \"${audit_mode}\" = 1 ];then\n            inc_insecure \"File \\\"${dot_file}\\\" ${exists}\"\n            fix_message  \"mv ${dot_file} ${dot_file}.disabled\"\n          fi\n          if [ \"${audit_mode}\" = 0 ];then\n            backup_file \"${dot_file}\"\n          fi\n        else\n          if [ \"${audit_mode}\" = 1 ];then\n            inc_secure \"File \\\"${dot_file}\\\" does not exist\"\n          fi\n        fi\n      done\n    else\n      file_list=$( find \"${restore_dir}\" -name \"${check_file}\" )\n      for check_file in ${file_list}; do\n        restore_file \"${check_file}\" \"${restore_dir}\"\n      done\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/users/audit_duplicate_ids.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_duplicate_ids\n#\n# Code to check for duplicate IDs\n# Routine to check a file for duplicates\n# Takes:\n# field:      Field number\n# function:   String describing action, eg users\n# term:       String describing term, eg name\n# check_file: File to parse\n#\n# Although the useradd program will not let you create a duplicate User ID\n# (UID), it is possible for an administrator to manually edit the /etc/passwd\n# file and change the UID field.\n#\n#.\n\naudit_duplicate_ids () {\n  print_function \"audit_duplicate_ids\"\n  string=\"Duplicate IDs\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ]; then\n    field_no=\"${1}\"\n    function=\"${2}\"\n    term=\"${3}\"\n    check_file=\"${4}\"\n    duplicate=0\n    if [ \"${audit_mode}\" != 2 ]; then\n      file_list=$( cut -f\"${field_no}\" -d: < \"${check_file}\" | sort -n | uniq -c | awk '{ print $1\":\"$2 }' )\n      for file_info in ${file_list}; do\n        file_check=$( expr \"${file_info}\" : \"[A-z,0-9]\" )\n        if [ \"${file_check}\" = 1 ]; then\n          file_check=$( expr \"${file_info}\" : \"2\" )\n          if [ \"${file_check}\" = 1 ]; then\n            file_id=$( echo \"${file_info}\" |cut -f2 -d:)\n            if [ \"${audit_mode}\" = 1 ];then\n              inc_insecure \"There are multiple \\\"${function}\\\" with \\\"${term}\\\" \\\"${file_id}\\\"\"\n              duplicate=1\n            fi\n          fi\n        fi\n      done\n      if [ \"${audit_mode}\" = 1 ]; then\n        if [ \"${duplicate}\" = 0 ];then\n          inc_secure \"No \\\"${function}\\\" with duplicate \\\"${term}\\\"\"\n        fi\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/users/audit_duplicate_users.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_duplicate_users\n#\n# Check duplicate users\n#\n# Refer to Section(s) 9.2.16,17 Page(s) 174-5       CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 9.2.15,18 Page(s) 201,203-4   CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 9.2.16,17 Page(s) 177-8       CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 6.2.16,18 Page(s) 291,3       CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 13.14,16  Page(s) 164-5       CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 2.12.16   Page(s) 219         CIS AIX Benchmark v1.1.0\n# Refer to Section(s) 9.15,18   Page(s) 82-3,5      CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 9.15,18   Page(s) 128-9,131   CIS Solaris 10 Benchmark v1.1.0\n# Refer to Section(s) 6.2.16,18 Page(s) 269,71      CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 6.2.16,18 Page(s) 283,5       CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 7.2.5,7   Page(s) 977-8,974-5 CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_duplicate_users () {\n  print_function \"audit_duplicate_users\"\n  string=\"Duplicate Users\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"AIX\" ]; then\n    audit_duplicate_ids \"1\" \"users\" \"name\" \"/etc/passwd\"\n    audit_duplicate_ids \"3\" \"users\" \"id\"   \"/etc/passwd\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/users/audit_forward_files.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154 \n\n# audit_forward_files\n#\n# Check dot forward files\n#\n# Refer to Section(s) 9.2.19 Page(s) 176-7 CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 9.2.21 Page(s) 206-7 CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 9.2.20 Page(s) 180-1 CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 6.2.11 Page(s) 2815  CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 13.19  Page(s) 167-8 CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 9.21   Page(s) 87    CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 9.21   Page(s) 133-4 CIS Solaris 10 Benchmark v1.1.0\n# Refer to Section(s) 6.2.11 Page(s) 263   CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 6.2.11 Page(s) 277   CIS Ubuntu 16.04 Benchmark v1.0.0\n#.\n\naudit_forward_files () {\n  print_function \"audit_forward_files\"\n  string=\"User Forward Files\"\n  check_message  \"${string}\" \n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ]; then\n    audit_dot_files \".forward\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/users/audit_home_ownership.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2012\n# shellcheck disable=SC2030\n# shellcheck disable=SC2031\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_home_ownership\n#\n# Check home ownership\n#\n# Bug: insecure_count is being reset to 0\n#\n# Refer to Section(s) 9.2.7,12,3 Page(s) 166-7,171-2   CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 9.2.7,12-4 Page(s) 192-3,197-200 CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 9.2.7,12-4 Page(s) 170,174-6     CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 6.2.7,9    Page(s) 281,3         CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 13.12-3    Page(s) 162-3         CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 2.11.18-20 Page(s) 202-6         CIS AIX Benchmark v1.1.0\n# Refer to Section(s) 9.12-4     Page(s) 80-1          CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 9.12-4     Page(s) 126-8         CIS Solaris 10 Benchmark v1.1.0\n# Refer to Section(s) 6.2.7,9    Page(s) 259,61        CIS Amazon Linux Benchmark v1.0.0\n# Refer to Section(s) 6.2.7,9    Page(s) 273,5         CIS Ubuntu 16.04 Benchmark v1.0.0\n# Refer to Section(s) 7.2.9      Page(s) 981-5         CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_home_ownership () {\n  print_function \"audit_home_ownership\"\n  string=\"Ownership of Home Directories\"\n  check_message  \"${string}\"\n  found=0\n  if [ \"${os_name}\" = \"SunOS\" ] || [  \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"AIX\" ]; then\n    if [ \"${os_name}\" = \"AIX\" ]; then\n      if [ \"${audit_mode}\" != 2 ]; then\n        command=\"lsuser -c ALL | grep -v \\\"^#name\\\" | cut -f1 -d:\"\n        command_message \"${command}\"\n        lsuser -c ALL | grep -v \"^#name\" | cut -f1 -d: | while read -r check_user; do\n          user_check=$( lsuser -f \"${check_user}\" | grep id | cut -f2 -d= )\n          if [ \"${user_check}\" -ge 200 ]; then\n            found=0\n            command=\"lsuser -a home \\\"${check_user}\\\" | cut -f2 -d=\"\n            command_message  \"${command}\"\n            home_dir=$( eval \"${command}\" )\n          else\n            found=1\n          fi\n          if [ \"${found}\" = 0 ]; then\n            if [ -z \"${home_dir}\" ] || [ \"${home_dir}\" = \"/\" ]; then\n              if [ \"${audit_mode}\" = 1 ];then\n                inc_insecure \"User \\\"${check_user}\\\" has no home directory defined\"\n              fi\n            else\n              if [ -d \"${home_dir}\" ]; then\n                command=\"ls -ld \\\"${home_dir}/.\\\" | awk '{ print \\$3 }'\"\n                command_message   \"${command}\"\n                dir_owner=$( eval \"${command}\" )\n                if [ \"${dir_owner}\" != \"${check_user}\" ]; then\n                  if [ \"${audit_mode}\" = 1 ];then\n                    inc_insecure \"Home Directory for \\\"${check_user}\\\" is owned by \\\"${dir_owner}\\\"\"\n                  fi\n                else\n                  if [ -z \"${home_dir}\" ] || [ \"${home_dir}\" = \"/\" ]; then\n                    if [ \"${audit_mode}\" = 1 ];then\n                      inc_insecure \"User \\\"${check_user}\\\" has no home directory\"\n                    fi\n                  fi\n                fi\n              fi\n            fi\n          fi\n        done\n      fi\n    fi\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      if [ \"${audit_mode}\" != 2 ]; then\n        getent passwd | awk -F: '{ print $1\" \"$6 }' | while read -r check_user home_dir; do\n          found=0\n          for test_user in root daemon bin sys adm lp uucp nuucp smmsp listen \\\n            gdm webservd postgres svctag nobody noaccess nobody4 unknown; do\n            if [ \"${check_user}\" = \"${test_user}\" ]; then\n              found=1\n            fi\n          done\n          if [ \"${found}\" = 0 ]; then\n            if [ -z \"${home_dir}\" ] || [ \"${home_dir}\" = \"/\" ]; then\n              if [ \"${audit_mode}\" = 1 ];then\n                inc_insecure \"User \\\"${check_user}\\\" has no home directory defined\"\n              fi\n            else\n              if [ -d \"${home_dir}\" ]; then\n                command=\"ls -ld \\\"${home_dir}/.\\\" | awk '{ print \\$3 }'\"\n                command_message \"${command}\"\n                dir_owner=$( eval \"${command}\" )\n                if [ \"${dir_owner}\" != \"${check_user}\" ]; then\n                  if [ \"${audit_mode}\" = 1 ];then\n                    inc_insecure \"Home Directory for \\\"${check_user}\\\" is owned by \\\"${dir_owner}\\\"\"\n                  fi\n                else\n                  if [ -z \"${home_dir}\" ] || [ \"${home_dir}\" = \"/\" ]; then\n                    if [ \"${audit_mode}\" = 1 ];then\n                      inc_insecure \"User \\\"${check_user}\\\" has no home directory\"\n                    fi\n                  fi\n                fi\n              fi\n            fi\n          fi\n        done\n      fi\n    fi\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      if [ \"${audit_mode}\" != 2 ]; then\n        getent passwd | awk -F: '{ print $1\" \"$6 }' | while read -r check_user home_dir; do\n          found=0\n          for test_user in root bin daemon adm lp sync shutdown halt mail news uucp \\\n            operator games gopher ftp nobody nscd vcsa rpc mailnull smmsp pcap \\\n            dbus sshd rpcuser nfsnobody haldaemon distcache apache \\\n            oprofile webalizer dovecot squid named xfs gdm sabayon; do\n            if [ \"${check_user}\" = \"${test_user}\" ]; then\n              found=1\n            fi\n          done\n          if [ \"${found}\" = 0 ]; then\n            if test -r \"${home_dir}\"; then\n              if [ -z \"${home_dir}\" ] || [ \"${home_dir}\" = \"/\" ]; then\n                if [ \"${audit_mode}\" = 1 ];then\n                  inc_insecure \"User \\\"${check_user}\\\" has no home directory defined\"\n                fi\n              else\n                if [ -d \"${home_dir}\" ]; then\n                  command=\"ls -ld \\\"${home_dir}/.\\\" | awk '{ print \\$3 }'\"\n                  command_message   \"${command}\"\n                  dir_owner=$( eval \"${command}\" )\n                  if [ \"${dir_owner}\" != \"${check_user}\" ]; then\n                    if [ \"${audit_mode}\" = 1 ];then\n                      inc_insecure \"Home Directory for \\\"${check_user}\\\" is owned by \\\"${dir_owner}\\\"\"\n                    fi\n                  else\n                    if [ -z \"${home_dir}\" ] || [ \"${home_dir}\" = \"/\" ]; then\n                      if [ \"${audit_mode}\" = 1 ];then\n                        inc_insecure \"User \\\"${check_user}\\\" has no home directory\"\n                      fi\n                    fi\n                  fi\n                fi\n              fi\n            fi\n          fi\n        done\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/users/audit_home_perms.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_home_perms\n#\n# Check home permissions\n#\n# Refer to Section(s) 5.4   Page(s) 51-52 CIS Apple OS X 10.8 Benchmark v1.0.0\n# Refer to Section(s) 6.6   Page(s) 22    CIS FreeBSD Benchmark v1.0.5\n# Refer to Section(s) 13.7  Page(s) 158-9 CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 9.7   Page(s) 77    CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 9.7   Page(s) 121   CIS Solaris 10 Benchmark v1.1.0\n# Refer to Section(s) 6.2.8 Page(s) 282   CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 6.2.8 Page(s) 260   CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 6.2.8 Page(s) 274   CIS Ubuntu 16.04 Benchmark v1.0.0\n# Refer to Section(s) 5.1.1 Page(s) 107-8 CIS Apple OS X 10.12 Benchmark v1.0.0\n# Refer to Section(s) 5.1.1 Page(s) 298-9 CIS Apple macOS 14 Sonoma Benchmark v1.0.0\n#.\n\naudit_home_perms () {\n  print_function \"audit_home_perms\"\n  string=\"Home Directory Permissions\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"Darwin\" ] || [ \"${os_name}\" = \"FreeBSD\" ]; then\n    if [ \"${do_fs}\" = \"1\" ]; then\n      command=\"cut -f6 -d: < /etc/passwd | grep -v \\\"^#\\\" | grep -v \\\"^/\\$\\\" | egrep -iE \\\"home|users\\\"\"\n      command_message  \"${command}\"\n      dir_list=$( eval \"${command}\" )\n      for home_dir in ${dir_list}; do\n        if [ -d \"${home_dir}\" ]; then\n          check_file_perms \"${home_dir}\" \"0700\"\n        fi\n      done\n      if [ \"${os_name}\" = \"Darwin\" ]; then\n        command=\"find /Users -maxdepth 1 | grep -vE \\\"localized|Shared\\\" | cut -f3 -d/\"\n        command_message  \"${command}\"\n        dir_list=$( eval \"${command}\" )\n        for home_dir in ${dir_list}; do\n          check_file_perms \"/Users/${home_dir}\" \"0700\"\n        done\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/users/audit_inactive_users.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_inactive_users\n#\n# Check inactive users\n#\n# Refer to Section(s) 7.5  Page(s) 171-2   CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 7.5  Page(s) 151-2   CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 10.5 Page(s) 141     CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 7.6  Page(s) 66-7    CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 7.9  Page(s) 109-110 CIS Solaris 10 Benchmark v5.1.0\n#.\n\naudit_inactive_users () {\n  print_function \"audit_inactive_users\"\n  string=\"Inactive User Accounts\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${my_id}\" != \"0\" ] && [ \"${use_sudo}\" = \"0\" ]; then\n      verbose_message \"Requires sudo to check\" \"notice\"\n      return\n    fi\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      check_file_value \"is\" \"/usr/sadm/defadduser\" \"definact\" \"eq\" \"35\" \"hash\"\n    fi\n    check_file=\"/etc/shadow\"\n    if test -r \"${check_file}\"; then\n      if [ \"${audit_mode}\" != 2 ]; then\n        command=\"grep -v nobody4 < ${check_file} | grep -v root\"\n        command_message   \"${command}\"\n        user_list=$( eval \"${command}\" )\n        for user_check in ${user_list}; do\n          command=\"echo \\\"${user_check}\\\" | cut -f 7 -d:\"\n          command_message   \"${command}\"\n          inactive=$( eval  \"${command}\" )\n          command=\"echo \\\"${user_check}\\\" | cut -f 1 -d:\"\n          command_message   \"${command}\"\n          user_name=$( eval \"${command}\" )\n          if [ \"$inactive\" = \"\" ]; then\n            if [ \"${audit_mode}\" = 1 ]; then\n              inc_insecure \"Inactive lockout not set for \\\"${user_name}\\\"\"\n              fix_message  \"usermod -f 35 ${user_name}\"\n            fi\n            if [ \"${audit_mode}\" = 0 ]; then\n              verbose_message \"File \\\"${check_file}\\\" to \\\"${work_dir}${check_file}\\\"\" \"save\"\n              command=\"find \\\"${check_file}\\\" | cpio -pdm \\\"${work_dir}\\\" 2> /dev/null\"\n              command_message \"${command}\"\n              eval \"${command}\"\n              set_message \"Inactive lockout for \\\"${user_name}\\\"\"\n              command=\"usermod -f 35 \\\"${user_name}\\\"\"\n              command_message \"${command}\"\n              eval \"${command}\"\n            fi\n          else\n            if [ \"${audit_mode}\" = 1 ]; then\n              inc_secure \"Inactive lockout set for user \\\"${user_name}\\\"\"\n            fi\n          fi\n        done\n      else\n        restore_file \"${check_file}\" \"${restore_dir}\"\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/users/audit_mesgn.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_mesgn\n#\n# Check mesgn set in profiles\n#\n# Refer to Section(s) 8.9    Page(s) 29    CIS FreeBSD Benchmark v1.0.5\n# Refer to Section(s) 2.12.7 Page(s) 211-2 CIS AIX Benchmark v1.1.0\n# Refer to Section(s) 7.5    Page(s) 66    CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 7.8    Page(s) 108-9 CIS Solaris 10 Benchmark v5.1.0\n#.\n\naudit_mesgn () {\n  print_function \"audit_mesgn\"\n  string=\"Messages are disabled by default\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"FreeBSD\" ] || [ \"${os_name}\" = \"AIX\" ]; then\n    for check_file in /etc/.login /etc/profile /etc/skel/.bash_profile /etc/skel/.bashrc \\\n      /etc/csh.login /etc/csh.cshrc /etc/zprofile /etc/skel/.zshrc /etc/skel/.bashrc; do\n      check_file_value \"is\" \"${check_file}\" \"mesg\" \"space\" \"n\" \"hash\"\n    done\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/users/audit_netrc_files.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_netrc_files\n#\n# Check netrc files\n#\n# Refer to Section(s) 6.2.12-3 Page(s) 264-6  CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 6.2.12-3 Page(s) 278-80 CIS Ubuntu 16.04 Benchmark v1.0.0\n#.\n\naudit_netrc_files () {\n  print_function \"audit_netrc_files\"\n  string=\"Netrc Files\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ]; then\n    audit_dot_files \".netrc\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/users/audit_old_users.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_old_users\n#\n# Audit users to check for accounts that have not been logged into etc\n#.\n\naudit_old_users () {\n  print_function \"audit_old_users\"\n  string=\"Old Users\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${my_id}\" != \"0\" ] && [ \"${use_sudo}\" = \"0\" ]; then\n      verbose_message \"Requires sudo to check\" \"notice\"\n      return\n    fi\n    last_test=$( command -v last)\n    if [ \"${last_test}\" = \"\" ]; then\n      inc_insecure \"last command not found\"\n      fix_message  \"Install wtmpdb package\"\n      return\n    fi\n    never_count=0\n    if [ \"${audit_mode}\" = 2 ]; then\n      restore_file \"/etc/shadow\" \"${restore_dir}\"\n    else\n      command=\"grep -v \\\"/usr/bin/false\\\" \\\"/etc/passwd\\\" | grep -Ev \\\"^halt|^shutdown|^root|^sync|/sbin/nologin\\\" | cut -f1 -d:\"\n      command_message   \"${command}\"\n      user_list=$( eval \"${command}\" )\n      for user_name in ${user_list}; do\n        if test -r \"/etc/shadow\"; then\n          command=\"grep \\\"^${user_name}:\\\" \\\"/etc/shadow\\\" | cut -f2 -d: | grep -cEv \\\"\\*|\\!\\!|NP|LK|UP\\\" | sed \\\"s/ //g\\\"\"\n          command_message      \"${command}\"\n          shadow_check=$( eval \"${command}\" )\n          if [ \"$shadow_check\" = \"1\" ]; then\n            command=\"last \\\"${user_name}\\\" | awk '{print \\$1}' | grep -c \\\"${user_name}\\\" | sed \\\"s/ //g\\\"\"\n            command_message     \"${command}\"\n            login_check=$( eval \"${command}\" )\n            if [ \"$login_check\" = \"1\" ]; then\n              if [ \"${audit_mode}\" = 1 ]; then\n                never_count=$((never_count+1))\n                inc_insecure \"User \\\"${user_name}\\\" has not logged in recently and their account is not locked\"\n                fix_message        \"passwd -l ${user_name}\"\n              fi\n              if [ \"${audit_mode}\" = 0 ]; then\n                backup_file \"/etc/shadow\"\n                set_message \"User \\\"${user_name}\\\" to locked\"\n                passwd -l \"${user_name}\"\n              fi\n            fi\n          fi\n        fi\n      done\n      if [ \"${never_count}\" = 0 ]; then\n        if [ \"${audit_mode}\" = 1 ]; then\n          inc_secure \"There are no users who have never logged that do not have their account locked\"\n        fi\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/users/audit_reserved_ids.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_reserved_ids\n#\n# Check reserved IDs\n#\n# Bug: sets insecure_count to 0 for some reason\n#\n# Refer to Section(s) 9.2.17 Page(s) 202-3 CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 9.17   Page(s) 84-5  CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 9.17   Page(s) 130-1 CIS Solaris 10 Benchmark v1.1.0\n#.\n\naudit_reserved_ids () {\n  print_function \"audit_reserved_ids\"\n  string=\"Reserved IDs\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${audit_mode}\" != 2 ]; then\n      command=\"getent passwd | awk -F: '(\\$3 < 500) { print \\\"\\$1\\\" \\\"\\$3\\\" }'\"\n      command_message \"${command}\"\n      getent passwd | awk -F: '($3 < 100) { print $1\" \"$3 }' | while read -r check_user check_uid; do\n        found=0\n        for test_user in root daemon bin sys adm lp uucp nuucp smmsp listen \\\n          gdm webservd postgres svctag nobody noaccess nobody4 unknown; do\n          if [ \"${check_user}\" = \"${test_user}\" ]; then\n            found=1\n          fi\n        done\n        if [ \"${found}\" = 0 ]; then\n          if [ \"${audit_mode}\" = 1 ];then\n            inc_insecure \"User \\\"${check_user}\\\" has a reserved UID \\\"${check_uid}\\\"\"\n          fi\n        fi\n      done\n    fi\n  else\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      if [ \"${audit_mode}\" != 2 ]; then\n        check_message \"Reserved UUIDs are assigned to system accounts\"\n      fi\n      if [ \"${audit_mode}\" != 2 ]; then\n        command=\"getent passwd | awk -F: '(\\$3 < 500) { print \\\"\\$1\\\" \\\"\\$3\\\" }'\"\n        command_message \"${command}\"\n        getent passwd | awk -F: '($3 < 500) { print $1\" \"$3 }' | while read -r check_user check_uid; do\n          found=0\n          for test_user in root bin daemon adm lp sync shutdown halt mail news uucp \\\n          operator games gopher ftp nobody nscd vcsa rpc mailnull smmsp pcap \\\n          dbus sshd rpcuser nfsnobody haldaemon distcache apache \\\n          oprofile webalizer dovecot squid named xfs gdm sabayon; do\n            if [ \"${check_user}\" = \"${test_user}\" ]; then\n              found=1\n            fi\n          done\n          if [ \"${found}\" = 0 ]; then\n            if [ \"${audit_mode}\" = 1 ];then\n              inc_insecure \"User \\\"${check_user}\\\" has a reserved UID \\\"${check_uid}\\\"\"\n            fi\n          fi\n        done\n      fi\n    else\n      na_message \"${string}\"\n    fi\n  fi\n}\n"
  },
  {
    "path": "modules/users/audit_rhosts_files.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_rhosts_files\n#\n# Check rhosts files\n#\n# Refer to Section(s) 1.5.2 Page(s) 102-3 CIS AIX Benchmark v1.1.0\n#.\n\naudit_rhosts_files () {\n  print_function \"audit_rhosts_files\"\n  string=\"Rhosts Files\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"AIX\" ] || [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${my_id}\" != \"0\" ] && [ \"${use_sudo}\" = \"0\" ]; then\n      notice_message \"Requires sudo to check\"\n      return\n    fi\n    for check_file in /.rhosts /.shosts /root/.rhosts /root/.shosts /etc/hosts.equiv; do\n      check_file_exists \"${check_file}\" \"no\"\n    done\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/users/audit_root_access.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_root_access\n#\n# Check root access \n#\n# Refer to Section(s) 7.5     Page(s) 105-6 CIS Solaris 10 Benchmark v5.1.0\n# Refer to Section(s) 5.4.2.4 Page(s) 700-1 CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_root_access () {\n  print_function \"audit_root_access\"\n  string=\"Root Access\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    if [ \"${my_id}\" != \"0\" ] && [ \"${use_sudo}\" = \"0\" ]; then\n      verbose_message \"Requires sudo to check\" \"notice\"\n      return\n    fi\n    access_test=$( passwd -S root | awk '{ print $2}' | grep -cE \"L\"  )\n    if [ \"${access_test}\" = \"0\" ]; then\n      inc_insecure \"Root account is not locked\"\n    else\n      inc_secure   \"Root account is locked\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/users/audit_root_home.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_root_home\n#\n# Check root home\n#\n# Refer to Section(s) 7.5 Page(s) 105-6 CIS Solaris 10 Benchmark v5.1.0\n#.\n\naudit_root_home () {\n  print_function \"audit_root_home\"\n  string=\"Root Home\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ]; then\n    if [ \"${os_name}\" = \"SunOS\" ]; then\n      if [ \"${os_version}\" = \"10\" ]; then\n        command=\"grep root /etc/passwd | cut -f6 -d:\"\n        command_message    \"${command}\"\n        home_check=$( eval \"${command}\" )\n        log_file=\"${work_dir}/roothome.log\"\n        if [ \"${home_check}\" != \"/root\" ]; then\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_insecure \"Root home directory incorrectly set\"\n            fix_message  \"mkdir -m 700 /root\"\n            fix_message  \"mv -i /.?* /root/\"\n            fix_message  \"passmgmt -m -h /root root\"\n          fi\n          if [ \"${audit_mode}\" = 0 ]; then\n            echo \"${home_check}\" >> \"${log_file}\"\n            set_message \"Root home directory correctly\"\n            mkdir -m 700 /root\n            mv -i /.?* /root/\n            passmgmt -m -h /root root\n          fi\n        else\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_secure \"Root home directory correctly set\"\n          fi\n        fi\n        if [ \"${audit_mode}\" = 2 ]; then\n          restore_file=\"${restore_dir}/rootgroup.log\"\n          if [ -f \"${restore_file}\" ]; then\n            home_check=$( cat \"${restore_file}\" )\n            restore_message \"Root home directory \\\"${home_check}\\\"\"\n            eval \"mv -i ${home_check}/.?* /\"\n            passmgmt -m -h \"${group_check}\" root\n          fi\n        fi\n      fi\n    fi\n  else\n    if [ \"${os_name}\" = \"Linux\" ]; then\n      check_file_perms \"/root\" \"0700\" \"root\" \"root\"\n    else\n      na_message \"${string}\"\n    fi\n  fi\n}\n"
  },
  {
    "path": "modules/users/audit_root_path.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_root_path\n#\n# Check root path\n#\n# Refer to Section(s) 9.2.6         Page(s) 165-166       CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 9.2.6         Page(s) 191-2         CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 9.2.6         Page(s) 167           CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 6.2.6         Page(s) 279-80        CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 13.6          Page(s) 157-8         CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 2.12.20       Page(s) 223           CIS AIX Benchmark v1.1.0\n# Refer to Section(s) 9.6           Page(s) 76-7          CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 9.6           Page(s) 120-1         CIS Solaris 10 Benchmark v1.1.0\n# Refer to Section(s) 6.2.6         Page(s) 257-8         CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 6.2.6         Page(s) 271-2         CIS Ubuntu 16.04 Benchmark v1.0.0\n# Refer to Section(s) 5.4.2.5,6.2.6 Page(s) 702-4,271-2   CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_root_path () {\n  print_function \"audit_root_path\"\n  string=\"Root PATH Environment Integrity\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"AIX\" ]; then\n    if [ \"${audit_mode}\" != 2 ]; then\n      if [ \"${audit_mode}\" = 1 ]; then\n        command=\"echo \\\"$PATH\\\" | grep \\\"::\\\"\"\n        command_message    \"${command}\"\n        path_check=$( eval \"${command}\" )\n        if [ \"${path_check}\" != \"\" ]; then\n          inc_insecure \"Empty directory in PATH\"\n        else\n          inc_secure   \"No empty directory in PATH\"\n        fi\n        command=\"echo \\\"$PATH\\\" | grep \\\":$\\\"\"\n        command_message    \"${command}\"\n        path_check=$( eval \"${command}\" )\n        if [ \"${path_check}\"  != \"\" ]; then\n          inc_insecure \"Trailing : in PATH\"\n        else\n          inc_secure   \"No trailing : in PATH\"\n        fi\n        command=\"echo \\\"$PATH\\\" | sed -e 's/::/:/' -e 's/:$//' -e 's/:/ /g'\"\n        command_message  \"${command}\"\n        dir_list=$( eval \"${command}\" )\n        for dir_name in ${dir_list}$; do\n          if [ \"${dir_name}\" = \".\" ]; then\n            inc_insecure \"PATH contains .\"\n          fi\n          if [ -d \"${dir_name}\" ]; then\n            command=\"find \\\"${dir_name}\\\" -maxdepth 1 -type f -writable \\( -perm -g+w \\)\"\n            command_message    \"${command}\"\n            group_test=$( eval \"${command}\" )\n            if [ -n \"${group_test}\" ]; then\n              inc_insecure \"Group write permissions set on directory \\\"${dir_name}\\\"\"\n            else\n              inc_secure   \"Group write permission not set on directory \\\"${dir_name}\\\"\"\n            fi\n            command=\"find \\\"${dir_name}\\\" -maxdepth 1 -type f -writable \\( -perm -o+w \\)\"\n            command_message    \"${command}\"\n            other_test=$( eval \"${command}\" )  \n            if [ -n \"${other_test}\" ]; then\n              inc_insecure \"Other write permissions set on directory \\\"${dir_name}\\\"\"\n            else\n              inc_secure   \"Other write permission not set on directory \\\"${dir_name}\\\"\"\n            fi\n          fi\n        done\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/users/audit_shell_timeout.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_shell_timeout\n#\n# Check Shell Timeout settings\n#\n# Refer to Section(s) 5.4.3.2 Page(s) 714-8 CIS Ubuntu 24.04 Benchmark v1.0.0\n#\n# Refer to: http://pubs.vmware.com/vsphere-55/topic/com.vmware.wssdk.apiref.doc/vim.option.OptionManager.html\n#.\n\naudit_shell_timeout () {\n  print_function \"audit_shell_timeout\"\n  string=\"Shell Timeout\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"VMkernel\" ]; then\n    for test in ESXiShellInteractiveTimeOut ESXiShellTimeOut; do\n      timeout=\"3600\"\n      check_message \"Timeout value for \\\"${test}\\\"\"\n      backup_file=\"${work_dir}/${test}\"\n      command=\"esxcli --formatter=csv --format-param=fields=\\\"Path,Int Value\\\" system settings advanced list | grep \\\"/UserVars/${test}\\\" | cut -f2 -d,\"\n      command_message       \"${command}\"\n      current_value=$( eval \"${command}\" )\n      if [ \"${audit_mode}\" != \"2\" ]; then\n        if [ \"${current_value}\" != \"${timeout}\" ]; then\n          if [ \"${audit_mode}\" = \"0\" ]; then\n            echo \"${current_value}\" > \"${backup_file}\"\n            set_message  \"Timeout value for ${test} to ${timeout}\"\n            esxcli system settings advanced set -o \"/UserVars/${test}\" -i \"${timeout}\"\n          fi\n          if [ \"${audit_mode}\" = \"1\" ]; then\n            inc_insecure \"Timeout value for ${test} not set to ${timeout}\"\n            fix_message  \"esxcli system settings advanced set -o /UserVars/${test} -i ${timeout}\"\n          fi\n        else\n          if [ \"${audit_mode}\" = \"1\" ]; then\n            inc_secure   \"Timeout value for ${test} is set to ${timeout}\"\n          fi\n        fi\n      else\n        restore_file=\"${restore_dir}/${test}\"\n        if [ -f \"${restore_file}\" ]; then\n          previous_value=$( cat \"${restore_file}\" )\n          if [ \"${previous_value}\" != \"${current_value}\" ]; then\n            verbose_message \"Restoring: Shell timeout to ${previous_value}\"\n            esxcli system settings advanced set -o \"/UserVars/${test}\" -i \"${previous_value}\"\n          fi\n        fi\n      fi\n    done\n  else\n    if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"FreeBSD\" ]; then\n      for check_file in /etc/.login /etc/profile /etc/skel/.bash_profile /etc/csh.login /etc/csh.cshrc \\\n        /etc/zprofile /etc/skel/.zshrc /etc/skel/.bashrc /etc/bashrc /etc/skel/.bashrc /etc/login.defs; do\n        check_file_value \"is\" \"${check_file}\" \"TMOUT\" \"eq\" \"900\" \"hash\"\n      done\n    else\n      na_message \"${string}\"\n    fi \n  fi\n}\n"
  },
  {
    "path": "modules/users/audit_shells.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_shells\n#\n# Check that shells in /etc/shells exist\n#\n# Refer to Section(s) 5.4.2.8-5.4.3.1,7.1.9   Page(s) 711-5,950-1   CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_shells () {\n  print_function \"audit_shells\"\n  string=\"Shells\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ]; then\n    check_file=\"/etc/shells\"\n    if [ -f \"${check_file}\" ]; then\n      if [ \"${audit_mode}\" = 2 ]; then\n        restore_file \"${check_file}\" \"${restore_dir}\"\n      else\n        check_shell=\"nologin\" \n        command=\"grep \\\"${check_shell}\\\" < \\\"${check_file}\\\" | grep -cv \\\"^#\\\"\"\n        command_message       \"${command}\"\n        nologin_check=$( eval \"${command}\" )\n        if [ \"${nologin_check}\" = \"0\" ]; then\n          inc_secure   \"Shell \\\"${check_shell}\\\" is not in \\\"${check_file}\\\"\"\n        else\n          inc_insecure \"Shell \\\"${check_shell}\\\" is in \\\"${check_file}\\\"\"\n        fi\n        check_file_comment \"${check_file}\" \"nologin\" \"hash\"\n        command=\"grep -v '^#' \\\"${check_file}\\\"\"\n        command_message      \"${command}\"\n        check_shells=$( eval \"${command}\" )\n        for check_shell in ${check_shells}; do\n          if [ ! -f \"${check_shell}\" ]; then\n            if [ \"${audit_mode}\" = 1 ]; then\n              inc_insecure \"Shell \\\"${check_shell}\\\" in \\\"${check_file}\\\" does not exit\"\n            fi\n            if [ \"${audit_mode}\" = 0 ]; then\n              temp_file=\"${temp_dir}/shells\"\n              backup_file \"${check_file}\"\n              grep -v \"^${check_shell}\" ${check_file} > \"${temp_file}\"\n              cat  \"${temp_file}\" > \"${check_file}\"\n            fi\n          fi\n        done\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/users/audit_super_users.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_super_users\n#\n# Check Super Users\n#\n# Refer to Section(s) 9.2.5 Page(s) 190-1  CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 9.2.5 Page(s) 165    CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 9.2.5 Page(s) 168    CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 6.2.5 Page(s) 278    CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 13.5  Page(s) 156-7  CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 8.6   Page(s) 28     CIS FreeBSD Benchmark v1.0.5\n# Refer to Section(s) 1.2.8 Page(s) 32     CIS AIX Benchmark v1.1.0\n# Refer to Section(s) 9-5   Page(s) 75-6   CIS Solaris 11.1 Benchmark v1.0.0\n# Refer to Section(s) 9.5   Page(s) 119-20 CIS Solaris 10 Benchmark v1.1.0\n# Refer to Section(s) 6.2.5 Page(s) 256    CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 6.2.5 Page(s) 270    CIS Ubuntu 16.04 Benchmark v1.0.0\n#.\n\naudit_super_users () {\n  print_function \"audit_super_users\"\n  string=\"Accounts with UID 0\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"FreeBSD\" ] || [ \"${os_name}\" = \"AIX\" ]; then\n    if [ \"${os_name}\" = \"AIX\" ]; then\n      check_chuser \"su\" \"true\" \"sugroups\" \"system\" \"root\"\n    else\n      if [ \"${audit_mode}\" != 2 ]; then\n        lock_command=\"userdel ${user_name}\"\n        command=\"awk -F: '\\$3 == \\\"0\\\" { print \\$1 }' /etc/passwd | grep -v root\"\n        command_message   \"${command}\"\n        user_list=$( eval \"${command}\" )\n        for user_name in ${user_list}; do\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_insecure \"UID 0 for User \\\"${user_name}\\\"\"\n            fix_message  \"${lock_command}\"\n          fi\n          if [ \"${audit_mode}\" = 0 ]; then\n            backup_file  \"/etc/shadow\"\n            backup_file  \"/etc/passwd\"\n            lock_message=\"Removing Account ${user_name} as it is UID 0\"\n            lock_command=\"userdel ${user_name}\"\n            run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n          fi\n        done\n        if [ \"${user_name}\" = \"\" ]; then\n          if [ \"${audit_mode}\" = 1 ]; then\n            inc_secure \"No accounts other than root have UID 0\"\n          fi\n        fi\n      else\n        restore_file \"/etc/shadow\" \"${restore_dir}\"\n        restore_file \"/etc/passwd\" \"${restore_dir}\"\n      fi\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/wheel/audit_pam_wheel.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_pam_wheel\n#\n# PAM Wheel group membership. Make sure wheel group membership is required to su.\n#\n# Refer to Section(s) 6.5   Page(s) 142-3 CIS CentOS Linux 6 Benchmark v1.0.0\n# Refer to Section(s) 6.5   Page(s) 165-6 CIS RHEL 5 Benchmark v2.1.0\n# Refer to Section(s) 6.5   Page(s) 145-6 CIS RHEL 6 Benchmark v1.2.0\n# Refer to Section(s) 5.6   Page(s) 257-8 CIS RHEL 7 Benchmark v2.1.0\n# Refer to Section(s) 9.5   Page(s) 135-6 CIS SLES 11 Benchmark v1.0.0\n# Refer to Section(s) 5.5   Page(s) 235-6 CIS Amazon Linux Benchmark v2.0.0\n# Refer to Section(s) 5.6   Page(s) 249   CIS Ubuntu 16.04 Benchmark v1.0.0\n# Refer to Section(s) 5.2.7 Page(s) 594-5 CIS Ubuntu 24.04 Benchmark v1.0.0\n#.\n\naudit_pam_wheel () {\n  print_function \"audit_pam_wheel\"\n  pam_module=\"pam_wheel\"\n  check_string=\"PAM ${pam_module} Configuration\"\n  check_message  \"${check_string}\"\n  if [ \"${os_name}\" = \"Linux\" ]; then\n    check_file=\"/etc/pam.d/su\"\n    if [ -f \"${check_file}\" ]; then\n      search_string=\"use_uid\"\n      if [ \"${audit_mode}\" != 2 ]; then\n        command=\"grep \\\"^auth\\\" \\\"${check_file}\\\" | grep \\\"${search_string}$\\\" | awk '{print \\$8}'\"\n        command_message     \"${command}\"\n        check_value=$( eval \"${command}\" )\n        if [ \"${ansible_mode}\" = 1 ]; then\n          ansible_counter=$((ansible_counter+1))\n          ansible_value=\"audit_pam_wheel_${ansible_counter}\"\n          echo \"\"\n          echo \"- name: Checking ${check_string}\"\n          echo \"  command:  sh -c \\\"cat ${check_file} | grep -v '^#' |grep '${search_string}$' |head -1 |wc -l\\\"\"\n          echo \"  register: ${ansible_value}\"\n          echo \"  failed_when: ${ansible_value} == 1\"\n          echo \"  changed_when: false\"\n          echo \"  ignore_errors: true\"\n          echo \"  when: ansible_facts['ansible_system'] == '${os_name}'\"\n          echo \"\"\n          echo \"- name: Fixing ${check_string}\"\n          echo \"  command: sh -c \\\"sed -i 's/^.*${search_string}$/#&/' ${check_file}\\\"\"\n          echo \"  when: ${ansible_value}.rc == 1 and ansible_facts['ansible_system'] == '${os_name}'\"\n          echo \"\"\n        fi\n        if [ \"${check_value}\" != \"${search_string}\" ]; then\n          if [ \"${audit_mode}\" = \"1\" ]; then\n            inc_insecure    \"Wheel group membership not required for su in \\\"${check_file}\\\"\"\n            verbose_message \"cp ${check_file} ${temp_file}\" \"fix\"\n            verbose_message \"cat ${temp_file} |awk '( \\$1==\\\"#auth\\\" && \\$2==\\\"required\\\" && \\$3~\\\"${pam_module}.so\\\" ) { print \\\"auth\\t\\trequired\\t\\\",\\$3,\\\"\\tuse_uid\\\"; next }; { print }' > ${check_file}\" \"fix\"\n            verbose_message \"rm ${temp_file}\" \"fix\"\n          fi\n          if [ \"${audit_mode}\" = 0 ]; then\n            backup_file     \"${check_file}\"\n            verbose_message \"Setting:   Su to require wheel group membership in PAM in \\\"${check_file}\\\"\"\n            cp \"${check_file}\" \"${temp_file}\"\n            awk '( $1==\"#auth\" && $2==\"required\" && $3~\"${pam_module}.so\" ) { print \"auth\\t\\trequired\\t\",$3,\"\\tuse_uid\"; next }; { print }' < \"${temp_file}\" > ${check_file}\n            if [ -f \"$tuse_file\" ]; then\n              rm \"${temp_file}\"\n            fi\n          fi\n        else\n          if [ \"${audit_mode}\" = \"1\" ]; then\n            inc_secure \"Wheel group membership required for su in \\\"${check_file}\\\"\"\n          fi\n        fi\n      else\n        restore_file \"${check_file}\" \"${restore_dir}\"\n      fi\n    fi\n  else\n    na_message \"${check_string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/wheel/audit_wheel_group.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_wheel_group\n#\n# Make sure there is a wheel group so privileged account access is limited.\n#.\n\naudit_wheel_group () {\n  print_function \"audit_wheel_group\"\n  string=\"Wheel Group\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ]; then\n    check_file=\"/etc/group\"\n    if [ \"${audit_mode}\" != 2 ]; then\n      command=\"grep \\\"^${wheel_group}:\\\" \\\"${check_file}\\\" |wc -c\"\n      command_message     \"${command}\"\n      check_value=$( eval \"${command}\" )\n      if [ \"${check_value}\" = \"0\" ]; then\n        if [ \"${audit_mode}\" = \"1\" ]; then\n          inc_insecure \"Wheel group \\\"${wheel_group}\\\" does not exist in \\\"${check_file}\\\"\"\n        fi\n        if [ \"${ansible_mode}\" = 1 ]; then\n          echo \"\"\n          echo \"- name: Checking ${string}\"\n          echo \"  group:\"\n          echo \"    name: ${wheel_group}\"\n          echo \"  when: ansible_facts['ansible_system'] == '${os_name}' or ansible_facts['ansible_system'] == '${os_name}'\"\n        fi\n        if [ \"${audit_mode}\" = 0 ]; then\n          backup_file  \"${check_file}\"\n          lock_message=\"Adding wheel group \\\"${wheel_group}\\\" to \\\"${check_file}\\\"\"\n          lock_command=\"groupadd ${wheel_group} ; usermod -G ${wheel_group} root\"\n          run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n        fi\n      else\n        if [ \"${audit_mode}\" = \"1\" ]; then\n          inc_secure   \"Wheel group \\\"${wheel_group}\\\" ${exists} in \\\"${check_file}\\\"\"\n        fi\n      fi\n    else\n      restore_file \"${check_file}\" \"${restore_dir}\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/wheel/audit_wheel_su.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_wheel_su\n#\n# Make sure su has a wheel group ownership\n#.\n\naudit_wheel_su () {\n  print_function \"audit_wheel_su\"\n  string=\"Wheel group ownership\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"Darwin\" ]; then\n    command=\"command -v su 2> /dev/null\"\n    command_message    \"${command}\"\n    check_file=$( eval \"${command}\" )\n    check_file_perms   \"${check_file}\" \"4750\" \"root\" \"${wheel_group}\"\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  },
  {
    "path": "modules/wheel/audit_wheel_users.sh",
    "content": "#!/bin/sh\n\n# shellcheck disable=SC1090\n# shellcheck disable=SC2034\n# shellcheck disable=SC2154\n\n# audit_wheel_users\n#\n# Check users in wheel group have recently logged in, if not lock them\n#\n\naudit_wheel_users () {\n  print_function \"audit_wheel_users\"\n  string=\"Wheel Users\"\n  check_message  \"${string}\"\n  if [ \"${os_name}\" = \"SunOS\" ] || [ \"${os_name}\" = \"Linux\" ] || [ \"${os_name}\" = \"Darwin\" ]; then\n    check_file=\"/etc/group\"\n    if [ \"${audit_mode}\" != 2 ]; then\n      command=\"grep \\\"^${wheel_group}:\\\" \\\"${check_file}\\\" | cut -f4 -d: | sed 's/,/ /g'\"\n      command_message   \"${command}\"\n      user_list=$( eval \"${command}\" )\n      if [ \"${user_list}\" = \"\" ]; then\n        inc_insecure \"No users in wheel group\"\n      fi\n      for user_name in ${user_list}; do\n        command=\"last -1 \\\"${user_name}\\\" | grep '[a-z]' | awk '{print \\$1}'\"\n        command_message    \"${command}\"\n        last_login=$( eval \"${command}\" )\n        if [ \"${last_login}\" = \"wtmp\" ]; then\n          command=\"read -r \\\"/etc/shadow\\\"\"\n          command_message \"${command}\"\n          if eval \"${command}\"; then\n            command=\"grep \\\"^${user_name}:\\\" /etc/shadow | grep -v 'LK' | cut -f1 -d:\"\n            command_message   \"${command}\"\n            lock_test=$( eval \"${command}\" )\n            if [ \"${lock_test}\" = \"${user_name}\" ]; then\n              if [ \"${ansible_mode}\" = 1 ]; then\n                echo \"\"\n                echo \"- name: Checking password lock for ${user_name}\"\n                echo \"  user:\"\n                echo \"    name: ${user_name}\"\n                echo \"    password_lock: yes\"\n                echo \"\"\n              fi\n              if [ \"${audit_mode}\" = 1 ]; then\n                inc_insecure \"User ${user_name} has not logged in recently and their account is not locked\"\n              fi\n              if [ \"${audit_mode}\" = 0 ]; then\n                backup_file  \"${check_file}\"\n                lock_message \"User \\\"${user_name}\\\" to locked\"\n                lock_command=\"passwd -l ${user_name}\"\n                run_lockdown \"${lock_command}\" \"${lock_message}\" \"sudo\"\n              fi\n            fi\n          fi\n        fi\n      done\n    else\n      restore_file \"${check_file}\" \"${restore_dir}\"\n    fi\n  else\n    na_message \"${string}\"\n  fi\n}\n"
  }
]