| Conditions | 48 |
| Total Lines | 169 |
| Code Lines | 112 |
| Lines | 0 |
| Ratio | 0 % |
| Tests | 0 |
| CRAP Score | 2352 |
| Changes | 0 | ||
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
Complex classes like verify_references.main() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
| 1 | #!/usr/bin/python3 |
||
| 142 | def main(): |
||
| 143 | global exit_value |
||
| 144 | (options, args) = parse_options() |
||
| 145 | xccdffilename = args[0] |
||
| 146 | |||
| 147 | # extract all of the rules within the xccdf |
||
| 148 | xccdftree = ssg.xml.ElementTree.parse(xccdffilename) |
||
| 149 | rules = xccdftree.findall(".//{%s}Rule" % xccdf_ns) |
||
| 150 | |||
| 151 | # if a profile was specified, get rid of any Rules that aren't in it |
||
| 152 | if options.profile_name: |
||
| 153 | profile_ruleids = get_profileruleids(xccdftree, options.profile_name) |
||
| 154 | prunedrules = rules[:] |
||
| 155 | for rule in rules: |
||
| 156 | if rule.get("id") not in profile_ruleids: |
||
| 157 | prunedrules.remove(rule) |
||
| 158 | rules = prunedrules |
||
| 159 | |||
| 160 | # step over xccdf file, and find referenced oval files |
||
| 161 | checks = xccdftree.findall(".//{%s}check" % xccdf_ns) |
||
| 162 | ovalfiles = get_ovalfiles(checks) |
||
| 163 | |||
| 164 | # this script only supports the inclusion of one OVAL file |
||
| 165 | if len(ovalfiles) > 1: |
||
| 166 | sys.exit("Referencing more than one OVAL file is not yet " + |
||
| 167 | "supported by this script.") |
||
| 168 | |||
| 169 | # find important elements within the XCCDF and the OVAL |
||
| 170 | ovalfile = os.path.join(os.path.dirname(xccdffilename), ovalfiles.pop()) |
||
| 171 | ovaltree = ssg.xml.ElementTree.parse(ovalfile) |
||
| 172 | # collect all compliance checks (not inventory checks, which are |
||
| 173 | # needed by CPE) |
||
| 174 | ovaldefs = [] |
||
| 175 | for el in ovaltree.findall(".//{%s}definition" % oval_ns): |
||
| 176 | if el.get("class") != "compliance": |
||
| 177 | continue |
||
| 178 | |||
| 179 | ovaldefs.append(el) |
||
| 180 | |||
| 181 | ovaldef_ids = [ovaldef.get("id") for ovaldef in ovaldefs] |
||
| 182 | |||
| 183 | oval_extenddefs = ovaltree.findall(".//{%s}extend_definition" % oval_ns) |
||
| 184 | ovaldef_ids_extended = [oval_extenddef.get("definition_ref") for oval_extenddef in oval_extenddefs] |
||
| 185 | ovaldef_ids_extended = list(set(ovaldef_ids_extended)) |
||
| 186 | |||
| 187 | check_content_refs = xccdftree.findall(".//{%s}check-content-ref" |
||
| 188 | % xccdf_ns) |
||
| 189 | xccdf_parent_map = dict((c, p) for p in xccdftree.iter() for c in p) |
||
| 190 | # now we can actually do the verification work here |
||
| 191 | if options.rules_with_invalid_checks or options.all_checks: |
||
| 192 | for check_content_ref in check_content_refs: |
||
| 193 | parent = xccdf_parent_map[check_content_ref] |
||
| 194 | rule = xccdf_parent_map[parent] |
||
| 195 | check_system = parent.get("system") |
||
| 196 | # Skip those <check-content-ref> elements using OCIL as the checksystem |
||
| 197 | # (since we are checking just referenced OVAL definitions) |
||
| 198 | if check_system == ocil_cs: |
||
| 199 | continue |
||
| 200 | |||
| 201 | # Obtain the value of the 'href' attribute of particular |
||
| 202 | # <check-content-ref> element |
||
| 203 | href = check_content_ref.get("href") |
||
| 204 | |||
| 205 | # Don't attempt to obtain refname on <check-content-ref> element |
||
| 206 | # having its "href" attribute set either to "http://" or to |
||
| 207 | # "https://" values (since the "name" attribute will be empty for |
||
| 208 | # these two cases) |
||
| 209 | # Also, skip known remote data files with CVE feeds. |
||
| 210 | if is_remote_feed(href): |
||
| 211 | continue |
||
| 212 | |||
| 213 | if check_system == sce_cs: |
||
| 214 | check_path = os.path.join(options.base_dir, href) |
||
| 215 | if not os.path.exists(check_path): |
||
| 216 | msg = "ERROR: Invalid or missing SCE definition (%s) " |
||
| 217 | msg += "referenced by XCCDF Rule: %s" |
||
| 218 | msg = msg % (check_path, rule.get("id")) |
||
| 219 | print(msg) |
||
| 220 | exit_value = 1 |
||
| 221 | else: |
||
| 222 | refname = check_content_ref.get("name") |
||
| 223 | if refname not in ovaldef_ids: |
||
| 224 | print("ERROR: Invalid OVAL definition referenced by XCCDF Rule: %s" |
||
| 225 | % (rule.get("id"))) |
||
| 226 | exit_value = 1 |
||
| 227 | |||
| 228 | if options.rules_without_checks or options.all_checks: |
||
| 229 | for rule in rules: |
||
| 230 | check = rule.find("./{%s}check" % xccdf_ns) |
||
| 231 | if check is None: |
||
| 232 | print("ERROR: No reference to OVAL definition in XCCDF Rule: %s" |
||
| 233 | % (rule.get("id"))) |
||
| 234 | exit_value = 1 |
||
| 235 | |||
| 236 | if options.rules_without_severity or options.all_checks: |
||
| 237 | for rule in rules: |
||
| 238 | if rule.get("severity") is None: |
||
| 239 | print("ERROR: No severity assigned to XCCDF Rule: %s" |
||
| 240 | % (rule.get("id"))) |
||
| 241 | exit_value = 1 |
||
| 242 | |||
| 243 | if options.rules_without_nistrefs or options.rules_without_disarefs or options.all_checks: |
||
| 244 | for rule in rules: |
||
| 245 | # find all references in the current rule |
||
| 246 | refs = rule.findall(".//{%s}reference" % xccdf_ns) |
||
| 247 | if refs is None: |
||
| 248 | print("ERROR: No reference assigned to XCCDF Rule: %s" |
||
| 249 | % (rule.get("id"))) |
||
| 250 | exit_value = 1 |
||
| 251 | else: |
||
| 252 | # loop through the Rule's references and put their hrefs |
||
| 253 | # in a list |
||
| 254 | ref_href_list = [ref.get("href") for ref in refs] |
||
| 255 | # print warning if rule does not have a NIST reference |
||
| 256 | if (nist_ref_href not in ref_href_list) and options.rules_without_nistrefs: |
||
| 257 | print("ERROR: No valid NIST reference in XCCDF Rule: " + |
||
| 258 | rule.get("id")) |
||
| 259 | exit_value = 1 |
||
| 260 | # print warning if rule does not have a DISA reference |
||
| 261 | if (disa_ref_href not in ref_href_list) and options.rules_without_disarefs: |
||
| 262 | print("ERROR: No valid DISA CCI reference in XCCDF Rule: " + |
||
| 263 | rule.get("id")) |
||
| 264 | exit_value = 1 |
||
| 265 | |||
| 266 | if options.disarefs_not_in_profile or options.nistrefs_not_in_profile: |
||
| 267 | if options.profile_name is None: |
||
| 268 | sys.exit("The options for finding Rules with a reference, " |
||
| 269 | "but which are not in a Profile, requires specifying a Profile.") |
||
| 270 | allrules = xccdftree.findall(".//{%s}Rule" % xccdf_ns) |
||
| 271 | for rule in allrules: |
||
| 272 | # find all references in the current rule |
||
| 273 | refs = rule.findall(".//{%s}reference" % xccdf_ns) |
||
| 274 | ref_href_list = [ref.get("href") for ref in refs] |
||
| 275 | # print warning if Rule is outside Profile and has a NIST reference |
||
| 276 | if options.nistrefs_not_in_profile: |
||
| 277 | if (nist_ref_href in ref_href_list) and (rule.get("id") not in profile_ruleids): |
||
|
|
|||
| 278 | print("ERROR: XCCDF Rule found with NIST reference outside Profile %s: " |
||
| 279 | % options.profile_name + rule.get("id")) |
||
| 280 | exit_value = 1 |
||
| 281 | # print warning if Rule is outside Profile and has a DISA reference |
||
| 282 | if options.disarefs_not_in_profile: |
||
| 283 | if (disa_ref_href in ref_href_list) and (rule.get("id") not in profile_ruleids): |
||
| 284 | print("ERROR: XCCDF Rule found with DISA CCI reference outside Profile %s: " |
||
| 285 | % options.profile_name + rule.get("id")) |
||
| 286 | exit_value = 1 |
||
| 287 | |||
| 288 | if options.ovaldefs_unused or options.all_checks: |
||
| 289 | # create a list of all of the OVAL compliance check ids that are |
||
| 290 | # defined in the oval file |
||
| 291 | oval_checks_list = [ovaldef.get("id") for ovaldef in ovaldefs] |
||
| 292 | # now loop through the xccdf rules; if a rule references an oval check |
||
| 293 | # we remove the oval check from our list |
||
| 294 | for check_content in check_content_refs: |
||
| 295 | # remove from the list |
||
| 296 | if check_content.get("name") in oval_checks_list: |
||
| 297 | oval_checks_list.remove(check_content.get("name")) |
||
| 298 | # the list should now contain the OVAL checks that are not referenced |
||
| 299 | # by any XCCDF rule |
||
| 300 | oval_checks_list.sort() |
||
| 301 | for oval_id in oval_checks_list: |
||
| 302 | # don't print out the OVAL defs that are extended by others, |
||
| 303 | # as they're not unused |
||
| 304 | if oval_id not in ovaldef_ids_extended: |
||
| 305 | print("WARNING: OVAL Check is not referenced by XCCDF: %s" |
||
| 306 | % (oval_id)) |
||
| 307 | # Do not treat this as error but only as a warning |
||
| 308 | #exit_value = 1 |
||
| 309 | |||
| 310 | sys.exit(exit_value) |
||
| 311 | |||
| 314 |