Coverage for veracode/check_compliance.py : 100%
Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1#!/usr/bin/env python3
2"""
3A python module to check the compliance status of an app in Veracode via their XML Results API
4"""
6# built-ins
7import logging
8from typing import Union, Optional
9from xml.etree import ( # nosec (Used only when TYPE_CHECKING) # nosem: python.lang.security.use-defused-xml.use-defused-xml
10 ElementTree as InsecureElementTree,
11)
13# third party
14from requests.exceptions import HTTPError, Timeout, RequestException, TooManyRedirects
16# custom
17from veracode.api import ResultsAPI
18from veracode.utils import validate, element_contains_error
19from veracode import __project_name__
21LOG = logging.getLogger(__project_name__ + "." + __name__)
24@validate
25def get_latest_completed_build(
26 *, results_api: ResultsAPI, only_latest: Optional[bool] = True
27) -> Union[InsecureElementTree.Element, bool]:
28 """
29 Get the latest completed build build_id for a given app_id
30 https://help.veracode.com/reader/LMv_dtSHyb7iIxAQznC~9w/Q8E6r4JDAN1lykB08oGDSA
31 """
32 endpoint = "getappbuilds.do"
33 params = {"only_latest": only_latest}
34 try:
35 appbuilds = results_api.http_get(endpoint=endpoint, params=params)
36 if element_contains_error(parsed_xml=appbuilds):
37 LOG.error("Veracode returned an error when attempting to call %s", endpoint)
38 return False
39 except (
40 HTTPError,
41 ConnectionError,
42 Timeout,
43 TooManyRedirects,
44 RequestException,
45 ):
46 LOG.error("Exception encountered when calling the Veracode API")
47 return False
49 # Filter on the provided app_id
50 for app in appbuilds:
51 if app.get("app_id") == results_api.app_id:
52 LOG.debug("Found app_id %s, returning %s", results_api.app_id, app)
53 return app
55 LOG.error(
56 "Unable to find a completed build for app_id %s",
57 results_api.app_id,
58 )
59 return False
62@validate
63def get_policy_compliance_status(*, results_api: ResultsAPI) -> Union[str, None]:
64 """
65 Retrieve the policy compliance status
66 """
67 tag = "{https://analysiscenter.veracode.com/schema/2.0/applicationbuilds}build"
68 # See https://analysiscenter.veracode.com/resource/2.0/applicationbuilds.xsd
69 policy_compliance_status = "Unknown"
71 LOG.debug("Calling get_latest_completed_scan")
72 latest_completed_build = get_latest_completed_build(results_api=results_api)
73 if latest_completed_build:
74 for build in latest_completed_build.iter(tag=tag):
75 policy_compliance_status = build.get("policy_compliance_status")
76 else:
77 LOG.warning("No builds detected for app_id %s", results_api.app_id)
79 return policy_compliance_status
82@validate
83def in_compliance(*, results_api: ResultsAPI) -> bool:
84 """
85 Identify if a policy compliance status is sufficient
86 """
87 LOG.debug("Calling get_policy_compliance_status")
88 compliance_status = get_policy_compliance_status(results_api=results_api)
89 if compliance_status != "Unknown":
90 LOG.debug(
91 "app_id %s has a compliance status of %s",
92 results_api.app_id,
93 compliance_status,
94 )
95 else:
96 raise ValueError
98 return bool(compliance_status == "Pass")
101@validate
102def check_compliance(*, results_api: ResultsAPI) -> bool:
103 """
104 Check the compliance status of an app in Veracode
105 """
106 LOG.debug(
107 "Checking to see if the latest build for app_id %s is in compliance",
108 results_api.app_id,
109 )
110 try:
111 if not in_compliance(results_api=results_api):
112 LOG.warning(
113 "The latest build for app %s was not in compliance", results_api.app_id
114 )
115 if results_api.ignore_compliance_status:
116 return True
118 return False
119 except ValueError:
120 LOG.error(
121 "Unable to determine the compliance status of app_id %s", results_api.app_id
122 )
123 return False
125 # App was in compliance
126 LOG.info("App ID %s is in compliance", results_api.app_id)
127 return True