Example #1
0
    def test_element_create(self):
        # Create a root_element and system
        e = Element.objects.create(name="New Element 2",
                                   full_name="New Element 2 Full Name",
                                   element_type="system")
        self.assertTrue(e.id is not None)
        self.assertTrue(e.name == "New Element 2")
        self.assertTrue(e.full_name == "New Element 2 Full Name")
        self.assertTrue(e.element_type == "system")

        e.save()
        s = System(root_element=e)
        s.save()
        self.assertEqual(s.root_element.name, e.name)

        # Create a Poam for the system
        smt = Statement.objects.create(sid=None,
                                       sid_class=None,
                                       pid=None,
                                       body="This is a test Poam statement.",
                                       statement_type="Poam",
                                       status="New",
                                       consumer_element=e)
        smt.save()
        poam = Poam.objects.create(statement=smt, poam_group="New POA&M Group")
        self.assertTrue(poam.poam_group == "New POA&M Group")
        # self.assertTrue(poam.name == "New Element")
        # self.assertTrue(poam.full_name == "New Element Full Name")
        # self.assertTrue(poam.element_type == "system")
        poam.save()
    def test_security_objectives(self):
        """
        Test set/get of Security Objective levels
        """
        # Log in, create a new project.
        self._login()
        self._new_project()

        project = Project.objects.first()
        element = Element()
        element.name = project.title
        element.element_type = "system"
        element.save()
        # Create system
        system = System(root_element=element)
        system.save()
        # Link system to project
        project.system = system

        # security objectives
        new_security_objectives = {
            "security_objective_confidentiality": "low",
            "security_objective_integrity": "high",
            "security_objective_availability": "moderate"
        }
        # Setting security objectives for project's statement
        security_objective_smt, smt = project.system.set_security_impact_level(
            new_security_objectives)

        # Check value changed worked
        self.assertEqual(project.system.get_security_impact_level,
                         new_security_objectives)
Example #3
0
    def test_assign_baseline(self):

        # Create root_element - no relayed controls should exist
        element = Element(name="sys_root_element")
        element.save()
        self.assertEqual(0, len(element.controls.all()))
        # Create system
        system = System(root_element=element)
        system.save()

        # Create a user because method expect user with correct permission
        user = User(email='*****@*****.**', username="******")
        user.save()
        # Assign owner permissions
        element.assign_edit_permissions(user)

        # Assign low baseline and some controls should exist
        result = element.assign_baseline_controls(user, 'NIST_SP-800-53_rev4',
                                                  'low')
        self.assertLess(110, len(element.controls.all()))
        self.assertGreater(135, len(element.controls.all()))

        # Assign moderate baseline and more controls should exist
        element.assign_baseline_controls(user, 'NIST_SP-800-53_rev4',
                                         'moderate')
        self.assertLess(210, len(element.controls.all()))
        self.assertGreater(280, len(element.controls.all()))

        # Assign low baseline and controls should be removed
        element.assign_baseline_controls(user, 'NIST_SP-800-53_rev4', 'low')
        self.assertLess(110, len(element.controls.all()))
        self.assertGreater(135, len(element.controls.all()))
Example #4
0
    def setUp(self):
        super().setUp()

        self.json_download = \
            self.download_path / PurePath(slugify(self.component_name)).with_suffix(".json")
        # print("********* self.json_download", self.json_download)

        # we need a system and a component
        root_element = Element(name="My Root Element",
                               description="Description of my root element")
        root_element.save()
        self.system = System()
        self.system.root_element = root_element
        self.system.save()

        project = self.org.get_organization_project()
        project.system = self.system
        project.save()
        self.system.assign_owner_permissions(self.user)
        statement = Statement(sid='ac-1',
                              sid_class=Catalogs.NIST_SP_800_53_rev4,
                              body='My statement body',
                              status='Not Implmented')
        statement.save()
        producer_element, created = Element.objects.get_or_create(name=self.component_name)
        statement.producer_element = producer_element
        statement.consumer_element = root_element
        statement.save()

        self.component = producer_element

        # enable experimental OpenControl support
        enable_experimental_opencontrol, _  = SystemSettings.objects.get_or_create(setting='enable_experimental_opencontrol')
        enable_experimental_opencontrol.active = True
        enable_experimental_opencontrol.save()
Example #5
0
    def test_export_csv(self, mockcsvexport):
        """
        Mock post request of SSP CSV export
        Check if the mock can create valid ExportCSVTemplateSSPForm data.
        export_ssp_csv
        """

        mockresponse = Mock()
        mockcsvexport.return_value = mockresponse
        mockresponse.POST = dict(info_system="Information System",
                                 control_id="Control ID",
                                 catalog="Control Set Version Number",
                                 shared_imps="Shared Implementation Details",
                                 private_imps="Private Implementation Details")

        export_csv_form = ExportCSVTemplateSSPForm(mockresponse.POST)
        # we need a system and a component
        root_element = Element(name="My Root Element",
                               description="Description of my root element")
        root_element.save()
        self.system = System()
        self.system.root_element = root_element
        if export_csv_form.is_valid():
            response = export_ssp_csv(export_csv_form.data, self.system)
            assert response.status_code == 200
Example #6
0
    def test_system_create(self):
        e = Element.objects.create(name="New Element",
                                   full_name="New Element Full Name",
                                   element_type="system")
        self.assertTrue(e.id is not None)
        self.assertTrue(e.name == "New Element")
        self.assertTrue(e.full_name == "New Element Full Name")
        self.assertTrue(e.element_type == "system")
        s = System(root_element=e)
        s.save()
        self.assertEqual(s.root_element.name, e.name)

        u2 = User.objects.create(username="******", email="*****@*****.**")
        # Test no permissions for user
        perms = get_user_perms(u2, s)
        self.assertTrue(len(perms) == 0)

        # Assign owner permissions
        s.assign_owner_permissions(u2)
        perms = get_user_perms(u2, s)
        self.assertTrue(len(perms) == 4)
        self.assertIn('add_system', perms)
        self.assertIn('change_system', perms)
        self.assertIn('delete_system', perms)
        self.assertIn('view_system', perms)
Example #7
0
class ComponentUITests(OrganizationSiteFunctionalTests):

    component_name = "XYZZY"

    def setUp(self):
        super().setUp()

        self.json_download = \
            self.download_path / PurePath(slugify(self.component_name)).with_suffix(".json")
        print("********* self.json_download", self.json_download)

        # we need a system and a component
        root_element = Element(name="My Root Element",
                               description="Description of my root element")
        root_element.save()
        self.system = System()
        self.system.root_element = root_element
        self.system.save()
        project = self.org.get_organization_project()
        project.system = self.system
        project.save()
        self.system.assign_owner_permissions(self.user)
        statement = Statement(sid='ac-1',
                              sid_class=Catalogs.NIST_SP_800_53_rev4,
                              body='My statement body',
                              status='Not Implmented')
        statement.save()
        producer_element, created = Element.objects.get_or_create(
            name=self.component_name)
        statement.producer_element = producer_element
        statement.consumer_element = root_element
        statement.save()

        self.component = producer_element

        # enable experimental OSCAL -and- OpenControl support
        enable_experimental_oscal, _ = SystemSettings.objects.get_or_create(
            setting='enable_experimental_oscal')
        enable_experimental_oscal.active = True
        enable_experimental_oscal.save()

        enable_experimental_opencontrol, _ = SystemSettings.objects.get_or_create(
            setting='enable_experimental_opencontrol')
        enable_experimental_opencontrol.active = True
        enable_experimental_opencontrol.save()

    def tearDown(self):
        # clean up downloaded file if linux elif dos
        if self.json_download.is_file():
            self.json_download.unlink()
        elif os.path.isfile(self.json_download.name):
            os.remove(self.json_download.name)
        super().tearDown()

    def test_component_download_oscal_json(self):
        self._login()
        url = self.url(
            f"/systems/{self.system.id}/component/{self.component.id}")
        self.browser.get(url)
        self.click_element('a[href="#oscal"]')

        # sigh; selenium doesn't really let us find out the name of the
        # downloaded file, so let's make sure it doesn't exist before we
        # download
        # definite race condition possibility

        if self.json_download.is_file():
            self.json_download.unlink()
        elif os.path.isfile(self.json_download.name):
            os.remove(self.json_download.name)
        self.click_element("a#oscal_download_json_link")
        var_sleep(2)  # need to wait for download, alas
        # assert download exists!
        try:
            self.assertTrue(self.json_download.is_file())
            filetoopen = self.json_download
        except:
            self.assertTrue(os.path.isfile(self.json_download.name))
            # assert that it is valid JSON by trying to load it
            filetoopen = self.json_download.name
        with open(filetoopen, 'r') as f:
            json_data = json.load(f)
            self.assertIsNotNone(json_data)

        if self.json_download.is_file():
            self.json_download.unlink()
        elif os.path.isfile(self.json_download.name):
            os.remove(self.json_download.name)

    def test_component_import_invalid_oscal(self):
        self._login()
        url = self.url(f"/controls/components")
        self.browser.get(url)
        self.click_element('a#component-import-oscal')
        app_root = os.path.dirname(os.path.realpath(__file__))
        oscal_json_path = os.path.join(app_root, "data/test_data",
                                       "test_invalid_oscal.json")
        file_input = self.find_selected_option('input#id_file')
        self.filepath_conversion(file_input, oscal_json_path, "sendkeys")

        # Verify that the contents got copied correctly from the file to the textfield
        try:
            # Load contents from file
            with open(oscal_json_path, 'r') as f:
                loaded_oscal_file_json = json.load(f)

            # Load contents from textarea
            file_contents = self.find_selected_option(
                'textarea#id_json_content').get_attribute("value")
            oscal_json_contents = json.loads(file_contents)

            self.assertEqual(loaded_oscal_file_json, oscal_json_contents)

        except ValueError:
            pass

        self.click_element('input#import_component_submit')

        element_count = Element.objects.filter(
            uuid='123456a7-b890-1234-cd56-e789fa012bcd').count()
        self.assertEqual(element_count, 0)

        statement1_count = Statement.objects.filter(
            uuid='1ab2c345-67d8-9e0f-1234-5a6bcd789efa').count()
        self.assertEqual(statement1_count, 0)

        statement2_count = Statement.objects.filter(
            uuid='2bc3d456-78e9-0f1a-2345-6b7cde890fab').count()
        self.assertEqual(statement2_count, 0)

    def test_component_import_oscal_json(self):
        self._login()
        url = self.url(f"/controls/components")
        self.browser.get(url)

        # Test initial import of Component(s) and Statement(s)
        self.click_element('a#component-import-oscal')
        app_root = os.path.dirname(os.path.realpath(__file__))
        oscal_json_path = os.path.join(app_root, "data/test_data",
                                       "test_oscal_component.json")
        file_input = self.find_selected_option('input#id_file')
        oscal_json_path = self.filepath_conversion(file_input, oscal_json_path,
                                                   "sendkeys")

        self.click_element('input#import_component_submit')

        element_count = Element.objects.filter(
            name='Test OSCAL Component').count()
        self.assertEqual(element_count, 1)

        statement1_count = Statement.objects.filter(
            uuid='1ab0b252-90d3-4d2c-9785-0c4efb254dfc').count()
        self.assertEqual(statement1_count, 1)

        statement2_count = Statement.objects.filter(
            uuid='2ab0b252-90d3-4d2c-9785-0c4efb254dfc').count()
        self.assertEqual(statement2_count, 1)

        # Verify that statements without a proper Catalog don't get entered
        statement3_count = Statement.objects.filter(
            uuid='4ab0b252-90d3-4d2c-9785-0c4efb254dfc').count()
        self.assertEqual(statement3_count, 0)

        # Verify that statements without a proper Control don't get entered
        statement4_count = Statement.objects.filter(
            uuid='6ab0b252-90d3-4d2c-9785-0c4efb254dfc').count()
        self.assertEqual(statement4_count, 0)

        var_sleep(1)  # Needed to allow page to refresh and messages to render

        # Test that duplicate Components and Statements are not re-imported
        self.click_element('a#component-import-oscal')
        file_input = self.find_selected_option('input#id_file')
        # Using converted keys from above
        file_input.send_keys(oscal_json_path)

        self.click_element('input#import_component_submit')

        element_count = Element.objects.filter(
            name='Test OSCAL Component').count()
        self.assertEqual(element_count, 1)

        statement1_count = Statement.objects.filter(
            uuid='1ab0b252-90d3-4d2c-9785-0c4efb254dfc').count()
        self.assertEqual(statement1_count, 1)
Example #8
0
def start_app(appver, organization, user, folder, task, q, portfolio):
    # Begin a transaction to create the Module and Task instances for the app.
    with transaction.atomic():
        # Create project.
        project = Project()
        project.organization = organization
        project.portfolio = portfolio

        # Save and add to folder
        project.save()
        project.set_root_task(appver.modules.get(module_name="app"), user)
        # Update default name to be unique by using project.id
        project.root_task.title_override = project.title + " " + str(
            project.id)
        project.root_task.save()
        if folder:
            folder.projects.add(project)

        # Log start app / new project
        logger.info(event="start_app",
                    object={
                        "task": "project",
                        "id": project.root_task.id,
                        "title": project.root_task.title_override
                    },
                    user={
                        "id": user.id,
                        "username": user.username
                    })
        logger.info(event="new_project",
                    object={
                        "object": "project",
                        "id": project.id,
                        "title": project.title
                    },
                    user={
                        "id": user.id,
                        "username": user.username
                    })

        # Create a new System element and link to project?
        # Top level apps should be linked to a system
        # Create element to serve as system's root_element
        # Element names must be unique. Use unique project title set above.
        element = Element()
        element.name = project.title
        element.element_type = "system"
        element.save()
        # Create system
        system = System(root_element=element)
        system.save()
        system.add_event(
            "SYS",
            f"Created new System in GovReady based on template '{appver.catalog_metadata['title']}'."
        )
        system.info == {
            "created_from_template": project.title,
            "system_description": "New system",
            "id": system.id,
            "other_id": "~",
            "name": project.root_task.title_override,
            "organization_name": "~",
            "aka": "~",
            "impact": "~",
            "status": "Planned",
            "type": "~",
            "created": "~",
            "hosting_facility": "~",
            "next_audit": "~",
            "next_scan": "~",  #"05/01/22",
            "security_scan": "~",
            "pen_test": "~",  #"Scheduled for 05/05/22",
            "config_scan": "~",
            "purpose": "~",
            "vuln_new_30days": "~",
            "vuln_new_rslvd_30days": "~",
            "vuln_90days": "~",
            "risk_score": "~",
            "score_1": "~",
            "score_2": "~",
            "score_3": "~",
            "score_4": "~",
            "score_5": "~",
        }
        system.save()
        # Link system to project
        project.system = system
        project.save()
        # Log start app / new project
        logger.info(event="new_element new_system",
                    object={
                        "object": "element",
                        "id": element.id,
                        "name": element.name
                    },
                    user={
                        "id": user.id,
                        "username": user.username
                    })

        # Add user as the first admin of project.
        ProjectMembership.objects.create(project=project,
                                         user=user,
                                         is_admin=True)
        # Grant owner permissions on root_element to user
        element.assign_owner_permissions(user)
        # Log ownership assignment
        logger.info(event="new_element new_system assign_owner_permissions",
                    object={
                        "object": "element",
                        "id": element.id,
                        "name": element.name
                    },
                    user={
                        "id": user.id,
                        "username": user.username
                    })
        system.assign_owner_permissions(user)
        # Log ownership assignment
        logger.info(event="new_system assign_owner_permissions",
                    object={
                        "object": "system",
                        "id": system.root_element.id,
                        "name": system.root_element.name
                    },
                    user={
                        "id": user.id,
                        "username": user.username
                    })

        # Add default deployments to system
        deployment = Deployment(
            name="Blueprint",
            description="Reference system archictecture design",
            system=system)
        deployment.save()
        deployment = Deployment(
            name="Dev",
            description="Development environment deployment",
            system=system)
        deployment.save()
        deployment = Deployment(
            name="Stage",
            description="Stage/Test environment deployment",
            system=system)
        deployment.save()
        deployment = Deployment(
            name="Prod",
            description="Production environment deployment",
            system=system)
        deployment.save()

        # Assign default control catalog and control profile
        # Use from App catalog settings
        try:
            # Get default catalog key
            parameters = project.root_task.module.app.catalog_metadata[
                'parameters']
            catalog_key = [p for p in parameters
                           if p['id'] == 'catalog_key'][0]['value']
            # Get default profile/baseline
            baseline_name = [p for p in parameters
                             if p['id'] == 'baseline'][0]['value']
            # Assign profile/baseline
            assign_results = system.root_element.assign_baseline_controls(
                user, catalog_key, baseline_name)
            # Log result if successful
            if assign_results:
                # Log start app / new project
                logger.info(event="assign_baseline",
                            object={
                                "object": "system",
                                "id": system.root_element.id,
                                "title": system.root_element.name
                            },
                            baseline={
                                "catalog_key": catalog_key,
                                "baseline_name": baseline_name
                            },
                            user={
                                "id": user.id,
                                "username": user.username
                            })
        except:
            # TODO catch error and return error message
            print(
                "[INFO] App could not assign catalog_key or profile/baseline.\n"
            )

        # Assign default organization components for a system
        if user.has_perm('change_system', system):
            # Get the components from the import records of the app version
            import_records = appver.input_artifacts.all()
            for import_record in import_records:
                add_selected_components(system, import_record)

        else:
            # User does not have write permissions
            logger.info(event="change_system permission_denied",
                        user={
                            "id": user.id,
                            "username": user.username
                        })

        # TODO: Assign default org parameters

        if task and q:
            # It will also answer a task's question.
            ans, is_new = task.answers.get_or_create(question=q)
            ansh = ans.get_current_answer()
            if q.spec[
                    "type"] == "module" and ansh and ansh.answered_by_task.count(
                    ):
                raise ValueError(
                    'The question %s already has an app associated with it.' %
                    q.spec["title"])
            ans.save_answer(
                None,  # not used for module-type questions
                list([] if not ansh else ansh.answered_by_task.all()) +
                [project.root_task],
                None,
                user,
                "web")

        return project
Example #9
0
    def test_organizational_parameters_via_project(self):

        # for this test, we need a Project, System, and Organization

        # REMIND: it would be nice to refactor all this setup code so
        # it could be easily reused ...
        
        from guidedmodules.models import AppSource
        from guidedmodules.management.commands.load_modules import Command as load_modules
        
        AppSource.objects.all().delete()
        AppSource.objects.get_or_create(
            slug="system",
            is_system_source=True,
            defaults={
                "spec": { # required system projects
                    "type": "local",
                    "path": "fixtures/modules/system",
                }
            }
        )
        load_modules().handle() # load system modules

        AppSource.objects.create(
            slug="project",
            spec={ # contains a test project
                "type": "local",
                "path": "fixtures/modules/other",
            },
            trust_assets=True
        )\
            .add_app_to_catalog("simple_project")

        user = User.objects.create(
            username="******",
            email="*****@*****.**",
            is_staff=True
        )
        org = Organization.create(name="Our Organization", slug="testorg",
                                  admin_user=user)

        root_element = Element(name="My Root Element",
                               description="Description of my root element")
        root_element.save()

        system = System()
        system.root_element = root_element
        system.save()

        project = org.get_organization_project()
        project.system = system
        project.save()

        parameter_values = project.get_parameter_values(Catalogs.NIST_SP_800_53_rev4)
        self.assertEquals(parameter_values["ac-1_prm_2"], "at least every 3 years")

        # now, add an organizational setting and try again
        OrganizationalSetting.objects.create(organization=org, 
                                             catalog_key=Catalogs.NIST_SP_800_53_rev4,
                                             parameter_key="ac-1_prm_2", 
                                             value="at least every 100 years")
        
        # we should now see the organizational setting override
        parameter_values = project.get_parameter_values(Catalogs.NIST_SP_800_53_rev4)
        self.assertEquals(parameter_values["ac-1_prm_2"], "at least every 100 years")
Example #10
0
class ComponentUITests(OrganizationSiteFunctionalTests):

    component_name = "XYZZY"

    def setUp(self):
        super().setUp()

        self.json_download = \
            self.download_path / PurePath(slugify(self.component_name)).with_suffix(".json")
        print("********* self.json_download", self.json_download)

        # we need a system and a component
        root_element = Element(name="My Root Element",
                               description="Description of my root element")
        root_element.save()
        self.system = System()
        self.system.root_element = root_element
        self.system.save()

        project = self.org.get_organization_project()
        project.system = self.system
        project.save()
        self.system.assign_owner_permissions(self.user)
        statement = Statement(sid='ac-1',
                              sid_class=Catalogs.NIST_SP_800_53_rev4,
                              body='My statement body',
                              status='Not Implmented')
        statement.save()
        producer_element, created = Element.objects.get_or_create(name=self.component_name)
        statement.producer_element = producer_element
        statement.consumer_element = root_element
        statement.save()

        self.component = producer_element

        # enable experimental OSCAL -and- OpenControl support
        enable_experimental_oscal, _ = SystemSettings.objects.get_or_create(setting='enable_experimental_oscal')
        enable_experimental_oscal.active = True
        enable_experimental_oscal.save()

        enable_experimental_opencontrol, _  = SystemSettings.objects.get_or_create(setting='enable_experimental_opencontrol')
        enable_experimental_opencontrol.active = True
        enable_experimental_opencontrol.save()

    def tearDown(self):
        # clean up downloaded file if linux elif dos
        if self.json_download.is_file():
            self.json_download.unlink()
        elif os.path.isfile(self.json_download.name):
            os.remove(self.json_download.name)
        super().tearDown()

    def test_component_download_oscal_json(self):
        self._login()
        url = self.url(f"/systems/{self.system.id}/component/{self.component.id}")
        self.browser.get(url)
        self.click_element('a[href="#oscal"]')

        # sigh; selenium doesn't really let us find out the name of the
        # downloaded file, so let's make sure it doesn't exist before we
        # download
        # definite race condition possibility

        if self.json_download.is_file():
            self.json_download.unlink()
        elif os.path.isfile(self.json_download.name):
            os.remove(self.json_download.name)
        self.click_element("a#oscal_download_json_link")
        var_sleep(2)            # need to wait for download, alas
        # assert download exists!
        try:
            self.assertTrue(self.json_download.is_file())
            filetoopen = self.json_download
        except:
            self.assertTrue(os.path.isfile(self.json_download.name))
            # assert that it is valid JSON by trying to load it
            filetoopen = self.json_download.name
        with open(filetoopen, 'r') as f:
            json_data = json.load(f)
            self.assertIsNotNone(json_data)

        if self.json_download.is_file():
            self.json_download.unlink()
        elif os.path.isfile(self.json_download.name):
            os.remove(self.json_download.name)

    def test_component_import_invalid_oscal(self):
        self._login()
        url = self.url(f"/controls/components")
        self.browser.get(url)
        self.click_element('a#component-import-oscal')
        app_root = os.path.dirname(os.path.realpath(__file__))
        oscal_json_path = os.path.join(app_root, "data/test_data", "test_invalid_oscal.json")
        file_input = self.find_selected_option('input#id_file')
        self.filepath_conversion(file_input, oscal_json_path, "sendkeys")

        element_count_before_import = Element.objects.filter(element_type="system_element").count()
        statement_count_before_import = Statement.objects.filter(
            statement_type="control_implementation_prototype").count()

        # Verify that the contents got copied correctly from the file to the textfield
        try:
            # Load contents from file
            with open(oscal_json_path, 'r') as f:
                loaded_oscal_file_json = json.load(f)

            # Load contents from textarea
            file_contents = self.find_selected_option('textarea#id_json_content').get_attribute("value")
            oscal_json_contents = json.loads(file_contents)

            self.assertEqual(loaded_oscal_file_json, oscal_json_contents)

        except ValueError:
            pass

        self.click_element('input#import_component_submit')

        element_count_after_import = Element.objects.filter(element_type="system_element").count()
        self.assertEqual(element_count_before_import, element_count_after_import)

        statement_count_after_import = Statement.objects.filter(statement_type="control_implementation_prototype").count()
        self.assertEqual(statement_count_before_import, statement_count_after_import)

    def test_component_import_oscal_json(self):
        self._login()
        url = self.url(f"/controls/components")
        self.browser.get(url)

        element_count_before_import = Element.objects.filter(element_type="system_element").count()
        statement_count_before_import = Statement.objects.filter(statement_type="control_implementation_prototype").count()

        # Test initial import of Component(s) and Statement(s)
        self.click_element('a#component-import-oscal')
        app_root = os.path.dirname(os.path.realpath(__file__))
        oscal_json_path = os.path.join(app_root, "data/test_data", "test_oscal_component.json")
        file_input = self.find_selected_option('input#id_file')
        oscal_json_path = self.filepath_conversion(file_input, oscal_json_path, "sendkeys")

        self.click_element('input#import_component_submit')

        var_sleep(3) # Wait for OSCAL to be imported

        element_count_after_import = Element.objects.filter(element_type="system_element").count()
        self.assertEqual(element_count_before_import + 2, element_count_after_import)

        statement_count_after_import = Statement.objects.filter(statement_type="control_implementation_prototype").count()
        self.assertEqual(statement_count_before_import + 4, statement_count_after_import)
        # Test file contains 6 Statements, but only 4 get imported
        # because one has an improper Catalog
        # and another has an improper Control
        # but we can't test individual statements because the UUIDs are randomly generated and not consistent
        # with the OSCAL JSON file. So we simply do a count.

        var_sleep(3) # Needed to allow page to refresh and messages to render

        # Test that duplicate Components are re-imported with a different name and that Statements get reimported
        self.click_element('a#component-import-oscal')
        file_input = self.find_selected_option('input#id_file')
        # Using converted keys from above
        file_input.send_keys(oscal_json_path)

        self.click_element('input#import_component_submit')

        var_sleep(3) # Wait for OSCAL to be imported

        element_count_after_duplicate_import = Element.objects.filter(element_type="system_element").count()
        self.assertEqual(element_count_after_import + 2, element_count_after_duplicate_import)

        original_import_element_count = Element.objects.filter(name='Test OSCAL Component1').count()
        self.assertEqual(original_import_element_count, 1)

        duplicate_import_element_count = Element.objects.filter(name='Test OSCAL Component1 (1)').count()
        self.assertEqual(duplicate_import_element_count, 1)

        statement_count_after_duplicate_import = Statement.objects.filter(
            statement_type="control_implementation_prototype").count()
        self.assertEqual(statement_count_after_import + 4, statement_count_after_duplicate_import)


    def test_import_tracker(self):
        """Tests that imports are tracked correctly."""

        self._login()
        url = self.url(f"/controls/components")
        self.browser.get(url)

        # Test initial import of Component(s) and Statement(s)
        self.click_element('a#import_records_link')

        current_path = urlparse(self.browser.current_url).path
        self.assertEqual('/controls/import_records', current_path)

        import_record_links = self.browser.find_elements_by_class_name('import_record_detail_link')
        self.assertEqual(len(import_record_links), 0)

        # Create an Import Record with a component and statement
        helper = ControlTestHelper()
        helper.create_simple_import_record()

        self.browser.refresh()
        var_sleep(1)

        import_record_links = self.browser.find_elements_by_class_name('import_record_detail_link')
        self.assertEqual(len(import_record_links), 1)

    def test_import_delete(self):
        """Tests that import deletions remove child components and statements."""

        # Create an Import Record with a component and statement
        helper = ControlTestHelper()
        import_record = helper.create_simple_import_record()

        self._login()
        url = self.url(f"/controls/import_records")
        self.browser.get(url)

        self.click_element(f"a.import_record_detail_link")
        self.click_element(f"a#delete-import")

        # Test that cancel doesn't delete the import, and redirects to the component library
        self.click_element(f"a#cancel-import-delete")

        current_path = urlparse(self.browser.current_url).path
        self.assertEqual('/controls/components', current_path)

        import_records_count = ImportRecord.objects.all().count()
        self.assertEqual(import_records_count, 1)
        component_count = Element.objects.filter(import_record=import_record).count()
        self.assertEqual(component_count, 1)
        statement_count = Statement.objects.filter(import_record=import_record).count()
        self.assertEqual(statement_count, 1)

        # Test that confirming the deletion deletes the import, component, and statement
        url = self.url(f"/controls/import_records")
        self.browser.get(url)
        self.click_element(f"a.import_record_detail_link")
        self.click_element(f"a#delete-import")

        self.click_element(f"a#confirm-import-delete")

        var_sleep(1)
        current_path = urlparse(self.browser.current_url).path
        self.assertEqual('/controls/components', current_path)

        import_records_count = ImportRecord.objects.all().count()
        self.assertEqual(import_records_count, 0)
        component_count = Element.objects.filter(import_record=import_record).count()
        self.assertEqual(component_count, 0)
        statement_count = Statement.objects.filter(import_record=import_record).count()
        self.assertEqual(statement_count, 0)


    def test_element_rename(self):
        # Ensures that the edit button doesnt appear for non-superusers
        # Logs into a non-superuser account and goes to a components page
        self._login()
        url = self.url(f"controls/components/{self.component.id}")
        self.browser.get(url)
        # Asserts that the edit button element is not found on the page
        self.assertTrue(len(self.browser.find_elements_by_css_selector('#edit-button'))<1)