added references

This commit is contained in:
Bob Gendler
2021-10-13 16:07:38 -04:00
parent 67e6278bbd
commit f3b783cc14
14 changed files with 179 additions and 122 deletions

View File

@@ -31,7 +31,12 @@ references:
disa_stig:
- N/A
800-171r2:
- N/A
- 3.1.20
- 3.4.6
cisv8:
- 4.1
- 4.8
- 15.3
macOS:
- "12.0"
tags:

View File

@@ -27,7 +27,7 @@ references:
disa_stig:
- N/A
800-171r2:
- N/A
- 3.4.6
cisv8:
- 4.1
- 4.8

View File

@@ -247,15 +247,9 @@ def output_baseline(rules, os, keyword):
output_text = f'title: "macOS {os}: Security Configuration - {keyword}"\n'
output_text += f'description: |\n This guide describes the actions to take when securing a macOS {os} system against the {keyword} baseline.\n'
output_text += f'authors: |\n |===\n |Name|Organization\n |===\n'
output_text += 'profile:\n'
# sort the rules
other_rules.sort()
inherent_rules.sort()
permanent_rules.sort()
na_rules.sort()
supplemental_rules.sort()
if len(other_rules) > 0:
for section in sections:
output_text += (' - section: "{}"\n'.format(section_title(section)))

View File

@@ -23,7 +23,7 @@ from collections import namedtuple
class MacSecurityRule():
def __init__(self, title, rule_id, severity, discussion, check, fix, cci, cce, nist_controls, nist_171, disa_stig, srg, custom_refs, tags, result_value, mobileconfig, mobileconfig_info, customized):
def __init__(self, title, rule_id, severity, discussion, check, fix, cci, cce, nist_controls, nist_171, disa_stig, srg, cisv8, custom_refs, tags, result_value, mobileconfig, mobileconfig_info, customized):
self.rule_title = title
self.rule_id = rule_id
self.rule_severity = severity
@@ -36,6 +36,7 @@ class MacSecurityRule():
self.rule_800171 = nist_171
self.rule_disa_stig = disa_stig
self.rule_srg = srg
self.rule_cisv8 = cisv8
self.rule_custom_refs = custom_refs
self.rule_result_value = result_value
self.rule_tags = tags
@@ -56,6 +57,7 @@ class MacSecurityRule():
rule_cci=self.rule_cci,
rule_80053r5=self.rule_80053r5,
rule_disa_stig=self.rule_disa_stig,
rule_cisv8=self.rule_cisv8,
rule_srg=self.rule_srg,
rule_result=self.rule_result_value
)
@@ -389,56 +391,46 @@ def generate_profiles(baseline_name, build_path, parent_dir, baseline_yaml, sign
for sections in baseline_yaml['profile']:
for profile_rule in sections['rules']:
logging.debug(f"checking for rule file for {profile_rule}")
if glob.glob('../custom/rules/**/{}.yaml'.format(profile_rule),recursive=True):
rule = glob.glob('../custom/rules/**/{}.yaml'.format(profile_rule),recursive=True)[0]
custom=True
logging.debug(f"{rule}")
elif glob.glob('../rules/*/{}.yaml'.format(profile_rule)):
rule = glob.glob('../rules/*/{}.yaml'.format(profile_rule))[0]
custom=False
logging.debug(f"{rule}")
for rule in glob.glob('../rules/*/{}.yaml'.format(profile_rule)) + glob.glob('../custom/rules/**/{}.yaml'.format(profile_rule),recursive=True):
rule_yaml = get_rule_yaml(rule, False)
#for rule in glob.glob('../rules/*/{}.yaml'.format(profile_rule)) + glob.glob('../custom/rules/**/{}.yaml'.format(profile_rule),recursive=True):
rule_yaml = get_rule_yaml(rule, custom)
if rule_yaml['mobileconfig']:
for payload_type, info in rule_yaml['mobileconfig_info'].items():
try:
if payload_type not in manifests['payloads_types']:
if rule_yaml['mobileconfig']:
for payload_type, info in rule_yaml['mobileconfig_info'].items():
try:
if payload_type not in manifests['payloads_types']:
profile_errors.append(rule)
raise ValueError(
"{}: Payload Type is not supported".format(payload_type))
else:
pass
except (KeyError, ValueError) as e:
profile_errors.append(rule)
raise ValueError(
"{}: Payload Type is not supported".format(payload_type))
else:
#print(e)
pass
except (KeyError, ValueError) as e:
profile_errors.append(rule)
#print(e)
pass
try:
if isinstance(info, list):
raise ValueError(
"Payload key is non-conforming")
else:
try:
if isinstance(info, list):
raise ValueError(
"Payload key is non-conforming")
else:
pass
except (KeyError, ValueError) as e:
profile_errors.append(rule)
#print(e)
pass
except (KeyError, ValueError) as e:
profile_errors.append(rule)
#print(e)
pass
if payload_type == "com.apple.ManagedClient.preferences":
for payload_domain, settings in info.items():
for key, value in settings.items():
payload_settings = (
payload_domain, key, value)
if payload_type == "com.apple.ManagedClient.preferences":
for payload_domain, settings in info.items():
for key, value in settings.items():
payload_settings = (
payload_domain, key, value)
profile_types.setdefault(
payload_type, []).append(payload_settings)
else:
for profile_key, key_value in info.items():
payload_settings = {profile_key: key_value}
profile_types.setdefault(
payload_type, []).append(payload_settings)
else:
for profile_key, key_value in info.items():
payload_settings = {profile_key: key_value}
profile_types.setdefault(
payload_type, []).append(payload_settings)
if len(profile_errors) > 0:
print("There are errors in the following files, please correct the .yaml file(s)!")
@@ -579,9 +571,6 @@ plb="/usr/libexec/PlistBuddy"
CURRENT_USER=$(scutil <<< "show State:/Users/ConsoleUser" | awk '/Name :/ && ! /loginwindow/ {{ print $3 }}')
CURR_USER_UID=$(/usr/bin/id -u $CURR_USER)
# get system architecture
arch=$(/usr/bin/arch)
# configure colors for text
RED='\e[31m'
STD='\e[39m'
@@ -755,6 +744,8 @@ fi
defaults write "$audit_plist" lastComplianceCheck "$(date)"
"""
#compliance_script_file.write(check_zsh_header)
# Read all rules in the section and output the check functions
for sections in baseline_yaml['profile']:
for profile_rule in sections['rules']:
@@ -768,20 +759,13 @@ defaults write "$audit_plist" lastComplianceCheck "$(date)"
custom=False
logging.debug(f"{rule}")
#for rule in glob.glob('../rules/*/{}.yaml'.format(profile_rule)) + glob.glob('../custom/rules/**/{}.yaml'.format(profile_rule),recursive=True):
rule_yaml = get_rule_yaml(rule, custom)
if rule_yaml['id'].startswith("supplemental"):
continue
if "manual" in rule_yaml['tags']:
continue
if "arm64" in rule_yaml['tags']:
arch="arm64"
elif "intel" in rule_yaml['tags']:
arch="i386"
else:
arch=""
# grab the 800-53 controls
try:
rule_yaml['references']['800-53r5']
@@ -790,6 +774,21 @@ defaults write "$audit_plist" lastComplianceCheck "$(date)"
else:
nist_80053r5 = rule_yaml['references']['800-53r5']
#try:
# rule_yaml['references']['disa_stig']
#except KeyError:
# stig_ref = rule_yaml['id']
#else:
# if rule_yaml['references']['disa_stig'][0] == "N/A":
# stig_ref = [rule_yaml['id']]
# else:
# stig_ref = rule_yaml['references']['disa_stig']
#
#if "STIG" in baseline_yaml['title']:
# logging.debug(f'Setting STIG reference for logging: {stig_ref}')
# log_reference_id = stig_ref
#else:
# log_reference_id = [rule_yaml['id']]
if reference == "default":
log_reference_id = [rule_yaml['id']]
else:
@@ -848,40 +847,31 @@ defaults write "$audit_plist" lastComplianceCheck "$(date)"
zsh_check_text = """
#####----- Rule: {0} -----#####
## Addresses the following NIST 800-53 controls: {1}
rule_arch="{6}"
if [[ "$arch" == "$rule_arch" ]] || [[ -z "$rule_arch" ]]; then
#echo 'Running the command to check the settings for: {0} ...' | tee -a "$audit_log"
unset result_value
result_value=$({2})
# expected result {3}
#echo 'Running the command to check the settings for: {0} ...' | tee -a "$audit_log"
unset result_value
result_value=$({2})
# expected result {3}
# check to see if rule is exempt
unset exempt
unset exempt_reason
exempt=$($plb -c "print {0}:exempt" "$audit_plist_managed" 2>/dev/null)
exempt_reason=$($plb -c "print {0}:exempt_reason" "$audit_plist_managed" 2>/dev/null)
# check to see if rule is exempt
unset exempt
unset exempt_reason
exempt=$($plb -c "print {0}:exempt" "$audit_plist_managed" 2>/dev/null)
exempt_reason=$($plb -c "print {0}:exempt_reason" "$audit_plist_managed" 2>/dev/null)
if [[ ! $exempt == "true" ]] || [[ -z $exempt ]];then
if [[ $result_value == "{4}" ]]; then
echo "$(date -u) {5} passed (Result: $result_value, Expected: "{3}")" | tee -a "$audit_log"
defaults write "$audit_plist" {0} -dict-add finding -bool NO
else
echo "$(date -u) {5} failed (Result: $result_value, Expected: "{3}")" | tee -a "$audit_log"
defaults write "$audit_plist" {0} -dict-add finding -bool YES
fi
elif [[ ! -z "$exempt_reason" ]];then
echo "$(date -u) {5} has an exemption (Reason: "$exempt_reason")" | tee -a "$audit_log"
if [[ ! $exempt == "true" ]] || [[ -z $exempt ]];then
if [[ $result_value == "{4}" ]]; then
echo "$(date -u) {5} passed (Result: $result_value, Expected: "{3}")" | tee -a "$audit_log"
defaults write "$audit_plist" {0} -dict-add finding -bool NO
/bin/sleep 1
else
echo "$(date -u) {5} failed (Result: $result_value, Expected: "{3}")" | tee -a "$audit_log"
defaults write "$audit_plist" {0} -dict-add finding -bool YES
fi
else
echo "$(date -u) {5} does not apply to this architechture" | tee -a "$audit_log"
elif [[ ! -z "$exempt_reason" ]];then
echo "$(date -u) {5} has an exemption (Reason: "$exempt_reason")" | tee -a "$audit_log"
defaults write "$audit_plist" {0} -dict-add finding -bool NO
/bin/sleep 1
fi
""".format(rule_yaml['id'], nist_controls.replace("\n", "\n#"), check.strip(), result, result_value, ' '.join(log_reference_id), arch)
""".format(rule_yaml['id'], nist_controls.replace("\n", "\n#"), check.strip(), result, result_value, ' '.join(log_reference_id))
check_function_string = check_function_string + zsh_check_text
@@ -1124,7 +1114,7 @@ def generate_xls(baseline_name, build_path, baseline_yaml):
top = xlwt.easyxf("align: vert top")
headers = xlwt.easyxf("font: bold on")
counter = 1
column_counter = 14
column_counter = 15
custom_ref_column = {}
sheet1.write(0, 0, "CCE", headers)
sheet1.write(0, 1, "Rule ID", headers)
@@ -1138,8 +1128,9 @@ def generate_xls(baseline_name, build_path, baseline_yaml):
sheet1.write(0, 9, "800-171", headers)
sheet1.write(0, 10, "SRG", headers)
sheet1.write(0, 11, "DISA STIG", headers)
sheet1.write(0, 12, "CCI", headers)
sheet1.write(0, 13, "Modifed Rule", headers)
sheet1.write(0, 12, "CIS Controls v8", headers)
sheet1.write(0, 13, "CCI", headers)
sheet1.write(0, 14, "Modifed Rule", headers)
sheet1.set_panes_frozen(True)
sheet1.set_horz_split_pos(1)
sheet1.set_vert_split_pos(2)
@@ -1219,14 +1210,20 @@ def generate_xls(baseline_name, build_path, baseline_yaml):
cci = (str(rule.rule_cci)).strip('[]\'')
cci = cci.replace(", ", "\n").replace("\'", "")
sheet1.write(counter, 12, cci, topWrap)
sheet1.col(12).width = 400 * 15
cisv8_refs = (str(rule.rule_cisv8)).strip('[]\'')
cisv8_refs = cisv8_refs.replace(", ", "\n").replace("\'", "")
sheet1.write(counter, 12, cisv8_refs, topWrap)
sheet1.col(12).width = 500 * 15
sheet1.write(counter, 13, cci, topWrap)
sheet1.col(13).width = 400 * 15
customized = (str(rule.rule_customized)).strip('[]\'')
customized = customized.replace(", ", "\n").replace("\'", "")
sheet1.write(counter, 13, customized, topWrap)
sheet1.col(13).width = 400 * 15
sheet1.write(counter, 14, customized, topWrap)
sheet1.col(14).width = 400 * 15
if rule.rule_custom_refs != ['None']:
for title, ref in rule.rule_custom_refs.items():
@@ -1270,6 +1267,7 @@ def create_rules(baseline_yaml):
'cce',
'800-53r5',
'800-171r2',
'cisv8',
'srg',
'custom']
@@ -1312,6 +1310,7 @@ def create_rules(baseline_yaml):
rule_yaml['references']['800-171r2'],
rule_yaml['references']['disa_stig'],
rule_yaml['references']['srg'],
rule_yaml['references']['cisv8'],
rule_yaml['references']['custom'],
rule_yaml['tags'],
rule_yaml['result'],
@@ -1476,6 +1475,7 @@ def main():
"adoc_header",
"adoc_footer",
"adoc_foreword",
"adoc_scope",
"adoc_authors",
"adoc_acronyms",
"adoc_additional_docs"
@@ -1515,8 +1515,11 @@ def main():
with open(adoc_templates_dict['adoc_foreword']) as adoc_foreword_file:
adoc_foreword_template = adoc_foreword_file.read() + "\n"
with open(adoc_templates_dict['adoc_scope']) as adoc_scope_file:
adoc_scope_template = Template(adoc_scope_file.read() +"\n")
with open(adoc_templates_dict['adoc_authors']) as adoc_authors_file:
adoc_authors_template = adoc_authors_file.read() + "\n"
adoc_authors_template = Template(adoc_authors_file.read() + "\n")
with open(adoc_templates_dict['adoc_acronyms']) as adoc_acronyms_file:
adoc_acronyms_template = adoc_acronyms_file.read() + "\n"
@@ -1535,6 +1538,11 @@ def main():
else:
adoc_STIG_show=":show_STIG!:"
if "CIS" in baseline_yaml['title'].upper():
adoc_cisv8_show=":show_cisv8:"
else:
adoc_cisv8_show=":show_cisv8!:"
if "800" in baseline_yaml['title']:
adoc_171_show=":show_171:"
else:
@@ -1551,17 +1559,29 @@ def main():
tag_attribute=adoc_tag_show,
nist171_attribute=adoc_171_show,
stig_attribute=adoc_STIG_show,
cisv8_attribute=adoc_cisv8_show,
version=version_yaml['version'],
os_version=version_yaml['os'],
release_date=version_yaml['date']
)
# Create scope
scope_adoc = adoc_scope_template.substitute(
scope_description=baseline_yaml['description']
)
# Create author
authors_adoc = adoc_authors_template.substitute(
authors_list=baseline_yaml['authors']
)
# Output header
adoc_output_file.write(header_adoc)
# write foreword, authors, acronyms, supporting docs
adoc_output_file.write(adoc_foreword_template)
adoc_output_file.write(adoc_authors_template)
adoc_output_file.write(scope_adoc)
adoc_output_file.write(authors_adoc)
adoc_output_file.write(adoc_acronyms_template)
adoc_output_file.write(adoc_additional_docs_template)
@@ -1653,6 +1673,13 @@ def main():
else:
disa_stig = ulify(rule_yaml['references']['disa_stig'])
try:
rule_yaml['references']['cisv8']
except KeyError:
cisv8 = '- N/A'
else:
cisv8 = ulify(rule_yaml['references']['cisv8'])
try:
rule_yaml['references']['srg']
except KeyError:
@@ -1735,6 +1762,7 @@ def main():
rule_80053r5=nist_controls,
rule_800171=nist_800171,
rule_disa_stig=disa_stig,
rule_cisv8=cisv8,
rule_cce=cce,
rule_tags=tags,
rule_srg=srg
@@ -1750,6 +1778,7 @@ def main():
rule_80053r5=nist_controls,
rule_800171=nist_800171,
rule_disa_stig=disa_stig,
rule_cisv8=cisv8,
rule_cce=cce,
rule_custom_refs=custom_refs,
rule_tags=tags,
@@ -1767,6 +1796,7 @@ def main():
rule_80053r5=nist_controls,
rule_800171=nist_800171,
rule_disa_stig=disa_stig,
rule_cisv8=cisv8,
rule_cce=cce,
rule_tags=tags,
rule_srg=srg,
@@ -1805,16 +1835,14 @@ def main():
else:
print("If you would like to generate the HTML file from the AsciiDoc file, install the ruby gem for asciidoctor")
# Don't create PDF if we are generating SCAP
if not args.gary:
asciidoctorPDF_path = is_asciidoctor_pdf_installed()
if asciidoctorPDF_path != "":
print('Generating PDF file from AsciiDoc...')
cmd = f"{asciidoctorPDF_path} \'{adoc_output_file.name}\'"
process = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
process.communicate()
else:
print("If you would like to generate the PDF file from the AsciiDoc file, install the ruby gem for asciidoctor-pdf")
asciidoctorPDF_path = is_asciidoctor_pdf_installed()
if asciidoctorPDF_path != "":
print('Generating PDF file from AsciiDoc...')
cmd = f"{asciidoctorPDF_path} \'{adoc_output_file.name}\'"
process = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
process.communicate()
else:
print("If you would like to generate the PDF file from the AsciiDoc file, install the ruby gem for asciidoctor-pdf")
# finally revert back to the prior directory
os.chdir(original_working_directory)

View File

@@ -349,13 +349,6 @@ def main():
</plist510_object>
'''.format(rule_yaml['id'],x,key,payload_type)
state_kind = ""
if type(value) == bool:
state_kind = "boolean"
elif type(value) == int:
state_kind = "int"
elif type(value) == str:
state_kind = "string"
oval_state = oval_state + '''
<plist510_state xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5#macos" comment="{}_state" id="oval:mscp:ste:{}" version="1">
@@ -1130,7 +1123,7 @@ def main():
</file_test>'''.format(x,rule_yaml['id'],x,x)
if "-" in fix_command and "R" in fix_command or rule_yaml['fix'].split("\n")[2][-1] == "*":
behavior = '<behaviors recurse="symlinks and directories" recurse_direction="down" max_depth="-1" recurse_file_system="local"></behaviors>'
behavior = '<behaviors recurse="directories" recurse_direction="down" max_depth="-1" recurse_file_system="local"></behaviors>'
if "audit" in rule_file:
filename = '<filename datatype="string" operation="not equal">current</filename>'
else:

View File

@@ -6,9 +6,11 @@
|ABM|Apple Business Manager
|AFP|Apple Filing Protocol
|ALF|Application Layer Firewall
|AO|Authorizing Official
|API|Application Programming Interface
|ARD|Apple Remote Desktop
|CA|Certificate Authority
|CIS|Center for Internet Security
|CRL|Certificate Revocation List
|DISA|Defense Information Systems Agency
|DMA|Direct Memory Access
@@ -31,6 +33,7 @@
|SIP|System Integrity Protection
|SMB|Server Message Block
|SSH|Secure Shell
|SSP|System Security Plan
|STIG|Security Technical Implementation Guide
|UAMDM|User Approved MDM
|UUCP|Unix-to-Unix Copy Protocol

View File

@@ -51,3 +51,11 @@ ASSOCIATED DOCUMENTS
|link:https://developer.apple.com/documentation/devicemanagement/profile-specific_payload_keys[Profile-Specific Payload Keys]|_Profile-Specific Payload Keys_
|link:https://support.apple.com/guide/sccc/welcome/web[Security Certifications and Compliance Center]|_Security Certifications and Compliance Center_
|===
[%header, cols=2*a]
.Center for Internet Security
|===
|Document Number or Descriptor
|Document Title
|link:https://www.cisecurity.org/benchmark/apple_os/[Apple macOS 11.0]|_CIS Apple macOS 11.0 Benchmark version 1.2.0_
|===

View File

@@ -1,5 +1,9 @@
== Authors
[width="100%",cols="1,3"]
$authors_list
////
|===
|Bob Gendler|National Institute of Standards and Technology
|Allen Golbig|National Aeronautics and Space Administration
@@ -10,3 +14,4 @@
|Elyse Anderson|National Aeronautics and Space Administration
|Gary Gapinski|National Aeronautics and Space Administration
|===
////

View File

@@ -5,3 +5,5 @@ The macOS Security Compliance Project is an open source effort to provide a prog
This project can be used as a resource to easily create customized security baselines of technical security controls by leveraging a library of atomic actions which are mapped to the compliance requirements defined in NIST SP 800-53 (Rev. 5). It can also be used to develop customized guidance to meet the particular cybersecurity needs of any organization.
The objective of this effort was to simplify and radically accelerate the process of producing up-to-date macOS security guidance that is also accessible to any organization and tailorable to meet each organizations specific security needs.
Any and all risk based decisions to tailor the content produced by this project in order to meet the needs of a specific organization shall be approved by the responsible Information System Owner (ISO) and Authorizing Official (AO) and formally documented in their System Security Plan (SSP). While the project attempts to provide settings to meet compliance requirements, it is recommended that each rule be reviewed by your organization's Information System Security Officer (ISSO) prior to implementation.

View File

@@ -14,6 +14,7 @@
:nofooter:
$nist171_attribute
$stig_attribute
$cisv8_attribute
ifdef::backend-pdf[]
= $profile_title
$version ($release_date)

View File

@@ -45,6 +45,11 @@ ifdef::show_STIG[]
!$rule_disa_stig
endif::[]
ifdef::show_CISv8[]
!CIS Controls V8
!$rule_cisv8
endif::[]
!CCE
!$rule_cce

View File

@@ -45,6 +45,11 @@ ifdef::show_STIG[]
!$rule_disa_stig
endif::[]
ifdef::show_CISv8[]
!CIS Controls V8
!$rule_cisv8
endif::[]
!CCE
!$rule_cce

View File

@@ -31,6 +31,11 @@ ifdef::show_STIG[]
!$rule_disa_stig
endif::[]
ifdef::show_CISv8[]
!CIS Controls V8
!$rule_cisv8
endif::[]
ifdef::show_tags[]
!CCE
!$rule_cce

View File

@@ -0,0 +1,3 @@
== Scope
$scope_description