def test_policy_states_summarize_for_subscription_sdk(self):
        """
        Testing the policy_states_summarize_for_subscription methods on the class PolicyStates
        :return:
        """
        subscriptionId = self.config["DEFAULT"]["subscription_id"]
        scour_policy = PolicyStates()
        response = scour_policy.policy_states_summarize_for_subscription(
            subscriptionId)

        self.assertIsNotNone(response)

        result2 = response.json()
        self.assertIsNotNone(result2)

        if os.path.isfile("states_summarized_subscription.json"):
            os.remove("states_summarized_subscription.json")

        states_summarized_subscription = json.dumps(response.json(),
                                                    indent=4,
                                                    ensure_ascii=False)
        with open("states_summarized_subscription.json", "w") as json_results:
            json_results.write(states_summarized_subscription)

        self.assertIsInstance(response.json(), dict)

        values = result2["value"]
        self.assertIs(type(values), list)
    def test_policy_states_list_query_results_for_management_group(self):
        scour_policy = PolicyStates()

        execute = scour_policy.policy_states_list_query_results_for_management_group(
            'global-legacy001-mg')
        results = execute()
        print(results)
    def test_policy_states_summarize_for_subscription_query(self):

        scour_policy = PolicyStates()
        execute = scour_policy.policy_states_summarize_for_subscription_query()
        results = execute()

        self.assertFalse('error' in results)
        self.assertIsNotNone(results)
    def test_policy_states_list_query_results_for_policy_definition(self):
        scour_policy = PolicyStates()

        subscription_id = self.config["DEFAULT"]["subscription_id"]

        execute = scour_policy.policy_states_list_query_results_for_policy_definitions(
            subscription_id, 'glbl-pr-sec-sqldb-threatdetection-pol')
        results = execute()
        print(results)
    def summarize_fact_compliance_for_definition(self, category,
                                                 policy_definition_name,
                                                 tenant_id, subscription_id,
                                                 batch_uuid):
        """
        This method captures the results for a policy compliance within a single subscription
        publishes results to non-SQL Cosmos DB
        :param category:
        :param policy_definition_name:
        :param subscription_id:
        """
        policy_states = PolicyStates()

        created = datetime.datetime.utcnow()

        # create a configured "Session" class
        print("Subscription: {}, Policy Name {}".format(
            subscription_id, policy_definition_name))
        '''
        Retreive the states for a policy and subscription
        '''
        policy_states_of_definition_response = policy_states.policy_states_summarize_for_policy_definition(
            subscriptionId=subscription_id,
            policyDefinitionName=policy_definition_name)
        '''
        The Rest API may fail to pull back states for many reasons.
        Failed states are skipped for various reasons but mostly, some results are better than none
        You are free to act differently.
        '''
        if not policy_states_of_definition_response.status_code in range(
                200, 299):
            print("Skipping with Error {} Subscription: {}, Policy Name {}".
                  format(policy_states_of_definition_response.status_code,
                         subscription_id, policy_definition_name))
            return

        policy_states_of_definitions_json = policy_states_of_definition_response.json(
        )

        if 'value' in policy_states_of_definitions_json:
            policy_states_of_definitions = policy_states_of_definitions_json[
                'value']
            for policy_states_of_definition in policy_states_of_definitions:
                policy_states_of_definition['category'] = category
                policy_states_of_definition[
                    'policy_definition_name'] = policy_definition_name
                policy_states_of_definition['tenant_id'] = tenant_id
                policy_states_of_definition[
                    'subscription_id'] = subscription_id
                policy_states_of_definition['batch_uuid'] = str(batch_uuid)

                self.cosmos_container_client.upsert_item(
                    policy_states_of_definition)
        else:
            return 0
    def test_policy_states_summarize_for_policy_definition(self):
        subscriptionId = self.config["DEFAULT"]["subscription_id"]
        policy_definition_name = self.config["FILTERS"][
            "policy_definition_name_01"]

        policy_states = PolicyStates()
        policy_states_list = policy_states.policy_states_summarize_for_policy_definition(
            subscriptionId=subscriptionId,
            policyDefinitionName=policy_definition_name)
        results = policy_states_list.json()
        self.assertEqual(policy_states_list.status_code, 200)
    def test_generic_function(self):
        """
            Demonstration the composability of the framework. Returns a method can be called at any time
        :return:
        """
        subscriptionId = os.environ["SUB"]
        polic_states = PolicyStates()
        api_config_key = "https://management.azure.com/subscriptions/{subscriptionId}/providers/Microsoft.PolicyInsights/policyStates/latest/summarize?api-version=2019-10-01"
        # The policystates_genericfunc has no way of learning the named string format parameters
        # a simple replace makes the URL a workable generic call to the API
        api_config_key = api_config_key.replace("{subscriptionId}", "{}")

        execute = polic_states.policystates_genericfunc(
            api_config_key,
            subscriptionId,
        )
        result = execute()

        self.assertIsNotNone(result)
    def test_policy_states_summarize_for_subscription(self):
        """
        Testing the policy_states_summarize_for_subscription methods on the class PolicyStates
        :return:
        """
        subscription = self.config["DEFAULT"]["subscription_id"]
        scour_policy = PolicyStates()
        execute = scour_policy.policy_states_summarize_for_subscription(
            subscription)
        # Execute returns a method the can be executed anywhere more than once
        result = execute()

        summarize_results = result["value"]
        for summary in summarize_results:
            policyAssignments = summary["policyAssignments"]
            for policy_assignment in policyAssignments:
                policyAssignmentId = policy_assignment["policyAssignmentId"]
                policySetDefinitionId = policy_assignment[
                    "policySetDefinitionId"]

                self.assertIsNotNone(policyAssignmentId)
                self.assertIsNotNone(policySetDefinitionId)

                complianceState = policy_assignment["results"][
                    "resourceDetails"][0]
                com_state = complianceState["complianceState"]
                com_state_cnt = complianceState["count"]

                self.assertIsNotNone(com_state)
                self.assertEqual(type(com_state_cnt), type(1))

                non_complianceState = policy_assignment["results"][
                    "resourceDetails"][1]
                non_comp_state = non_complianceState["complianceState"]
                non_comp_state_cnt = non_complianceState["count"]

                self.assertIsNotNone(non_comp_state)
                self.assertEqual(type(non_comp_state_cnt), type(1))

                break
    def Summarize_For_Subscription(self):
        policy_states = PolicyStates()
        batch_uuid = uuid.uuid4()
        created = datetime.datetime.utcnow()

        # create a configured "Session" class

        # create a Session
        # Execute returns a method the can be executed anywhere more than once
        models = self.get_db_model(self.engine)
        subscriptions_model = models.classes.subscriptions

        session = self.Session()
        subscriptions = session.query(subscriptions_model).all()
        policy_insights = PolicyInsights2()

        for subscription in subscriptions:
            policy_insight_response = policy_insights.policy_states_summarize_for_subscription(subscriptionId=subscription.subscription_id)
            if policy_insight_response.status_code in range(200, 299):
                policy_states_summarize_for_subscription = policy_insight_response.json()
                print(subscription.subscription_id)
    def summarize_fact_compliance_for_definition(self, subscription_id,
                                                 policy_definition_name):

        jmespath_expression = jmespath.compile(
            "value[*].policyAssignments[*].policyDefinitions[*]")
        policy_states = PolicyStates()
        batch_uuid = uuid.uuid4()
        created = datetime.datetime.utcnow()

        # create a configured "Session" class

        # create a Session
        # Execute returns a method the can be executed anywhere more than once
        models = self.get_db_model(self.engine)
        FactCompliance = models.classes.factcompliance
        subscriptions = models.classes.subscriptions

        session = self.Session()
        if subscription_id is not None:
            subscriptions_list = session.query(subscriptions).filter_by(
                subscription_id=subscription_id)
        else:
            subscriptions_list = session.query(subscriptions).all()

        for subscription in subscriptions_list:
            tenant_id = subscription.tenant_id
            print("Subscription: {}, Policy Name {}".format(
                subscription.subscription_id, policy_definition_name))
            policy_states_of_definition = policy_states.policy_states_summarize_for_policy_definition(
                subscriptionId=subscription.subscription_id,
                policyDefinitionName=policy_definition_name).json()

            jmes_result = jmespath_expression.search(
                policy_states_of_definition)

            if jmespath_expression is None or jmes_result is None or jmes_result[
                    0] is None or len(jmes_result[0]) == 0:
                continue
            else:
                # flatten results
                policyresults = jmes_result[0][0]
                bulk_insert = list()
                for policyresult in policyresults:
                    policy_definition_name = str(
                        policyresult['policyDefinitionId']).split('/')[-1]
                    resourceDetails = jmespath.search(
                        'results.resourceDetails[*]', policyresult)

                    compliance_ratio = self.determine_compliance_ratio(
                        resourceDetails)

                    fact = FactCompliance(
                        tenant_id=tenant_id,
                        subscription_id=subscription.subscription_id,
                        policy_definition_name=policy_definition_name,
                        compliant=compliance_ratio['compliant'],
                        noncompliant=compliance_ratio['noncompliant'],
                        total_resources_measured=compliance_ratio[
                            'total_resources_measured'],
                        percent_compliant=compliance_ratio[
                            'percent_compliant'],
                        batch_uuid=batch_uuid,
                        created=created,
                        modified=created)
                    bulk_insert.append(fact)

                session.bulk_save_objects(bulk_insert)
                session.commit()
def subscription_policy_compliance(subscriptionId):
    with change_dir(OPERATIONSPATH):
        config = ConfigParser()
        config.read(CONFVARIABLES)

    jmespath_expression = jmespath.compile(
        "value[*].policyAssignments[*].policyDefinitions[*]")
    jmespath_results = jmespath.compile("[0].results.resourceDetails")
    scour_policy = PolicyStates()
    response = scour_policy.policy_states_summarize_for_subscription(
        subscriptionId)
    if response is None:
        response = scour_policy.policy_states_summarize_for_subscription(
            subscriptionId)

    # Execute returns a method the can be executed anywhere more than once
    result = response.json()
    df = pd.DataFrame(columns=[
        'subscription_id', 'policy_definition_name', 'policy_definition_id',
        'compliant', 'noncompliant', 'total_resources_measured',
        'percent_compliant'
    ])
    jmes_result = jmespath_expression.search(result)

    if jmespath_expression is None or jmes_result is None or jmes_result[
            0] is None:
        return
    else:
        # flatten results
        try:

            policyresults = jmes_result[0][0]
            for policyresult in policyresults:
                policy_definition_name = str(
                    policyresult['policyDefinitionId']).split('/')[-1]
                resourceDetails = jmespath.search('results.resourceDetails[*]',
                                                  policyresult)

                compliance_ratio = determine_compliance_ratio(resourceDetails)
                new_row = {
                    'subscription_id':
                    subscriptionId,
                    'policy_definition_name':
                    policy_definition_name,
                    'policy_definition_id':
                    policyresult['policyDefinitionId'],
                    'compliant':
                    compliance_ratio['compliant'],
                    'noncompliant':
                    compliance_ratio['noncompliant'],
                    'total_resources_measured':
                    compliance_ratio['total_resources_measured'],
                    'percent_compliant':
                    compliance_ratio['percent_compliant'],
                }

                df = df.append(new_row, ignore_index=True)

        except IndexError:
            return None

    return df