def test_send_invite_with_groups_and_sites(self):
        sender = User(self.email, name="Bob")
        sender.create()
        recipient = User(self.random_email(), name="Alice")
        recipient.invite()

        # create the invitation
        invite = Invite(sender.email, recipient.email)
        res = invite.create() 
        invite_id = res.json()['invite']['id']

        # create a site in minion
        site = Site(self.target_url)
        res2 = site.create()
        site_id = res2.json()["site"]["id"]

        # Uncomment the following checks when #297 is resolved.
        # create a group in minion
        group = Group(self.group_name, sites=[site.url], users=[recipient.email])
        res3 = group.create()

        # site should exists in group and recipient should also be in the same group
        res4 = group.get()
        self.assertEqual(res4.json()['group']['users'], [recipient.email,])

        res5 = site.get(site_id)
        self.assertEqual(res5.json()["site"]["groups"], [group.group_name])

        # finally, if we query recipient's user object, user should be in
        # the group and have access to a site.
        res6 = recipient.get()
        self.assertEqual(res6.json()["user"]["sites"], [site.url])
        self.assertEqual(res6.json()["user"]["groups"], [group.group_name])
Example #2
0
    def test_create_site_with_verifying(self):
        group = Group(self.group_name)
        group.create()
        site = Site(self.target_url, groups=[group.group_name])

        res = site.create(verify=True)
        self.assertEqual(res.json()['site']['verification']['enabled'], True)
        self.assertTrue(res.json()['site']['verification']['value'])
Example #3
0
 def test_create_duplicate_site(self):
     group = Group(self.group_name)
     group.create()
     site = Site(self.target_url, groups=[group.group_name])
     res1 = site.create()
     res2 = site.create()
     self.assertEqual(res2.json()['success'], False)
     self.assertEqual(res2.json()['reason'], 'site-already-exists')
Example #4
0
    def test_create_site_with_bad_format(self):
        group = Group(self.group_name)
        group.create()

        site = Site(self.target_badurl, groups=[group.group_name])
        res = site.create()
        self.assertEqual(res.status_code, 200)
        self.assertEqual(res.json()['reason'], 'invalid-url')
Example #5
0
    def test_get_specific_site_by_url(self):
        group = Group(self.group_name)
        group.create()

        site = Site(self.target_url, groups=[group.group_name])
        res1 = site.create()
        res2 = Sites().get(url=site.url)
        self.assertEqual(len(res2.json()["sites"]), 1)
        self.assertEqual(res2.json()["sites"][0], res1.json()["site"])
Example #6
0
    def test_create_site_with_cidr_network(self):
        group = Group(self.group_name)
        group.create()

        site = Site(self.target_cidr, groups=[group.group_name])
        res = site.create()
        self.assertEqual(set(res.json()['site'].keys()),
            set(self.expected_inner_keys))
        self.assertEqual(res.json()['site']['url'], site.url)
        self.assertEqual(res.json()['site']['plans'], [])
Example #7
0
    def test_create_site_without_verifying(self):
        group = Group(self.group_name)
        group.create()

        site = Site(self.target_url, groups=[group.group_name])
        res = site.create(verify=False)
        self.assertEqual(set(res.json()["site"].keys()), set(self.expected_inner_keys))
        self.assertEqual(res.json()["site"]["url"], site.url)
        self.assertEqual(res.json()["site"]["plans"], [])
        self.assertEqual(res.json()["site"]["verification"]["enabled"], False)
        self.assertEqual(res.json()["site"]["verification"]["value"], None)
Example #8
0
    def test_get_site(self):
        group = Group(self.group_name)
        group.create()

        site = Site(self.target_url, groups=[group.group_name])
        res1 = site.create()
        site_id = res1.json()["site"]["id"]

        res2 = site.get(site_id)
        self.assertEqual(res2.json()["success"], True)
        self.assertEqual(res2.json()['site'], res1.json()['site'])
    def test_accept_invite_with_a_different_login_email(self):
        # we allow recipient to login with a different email address.
        recipient = User(self.random_email())
        recipient.invite()
        sender = User(self.random_email())
        sender.create()

        invite = Invite(sender.email, recipient.email)
        res1 = invite.create()
        invite_id = res1.json()["invite"]["id"]

        # create a group and a site and add the recipient to the group
        site = Site(self.target_url)
        res2 = site.create()

        # create a group in minion
        group = Group(self.group_name,
                      sites=[site.url],
                      users=[recipient.email])
        group.create()

        # ensure user and site are in this new group
        res3 = group.get()
        self.assertEqual(res3.json()["group"]["sites"], [site.url])
        self.assertEqual(res3.json()["group"]["users"], [recipient.email])

        # user should have access to the group and the site
        res4 = recipient.get()
        self.assertEqual(res4.json()["user"]["sites"], [site.url])
        self.assertEqual(res4.json()["user"]["groups"], [group.group_name])

        # recipient accepts the invitation with a different login email address
        actual_login = self.random_email()
        recipient_2 = User(actual_login)
        res5 = invite.update(invite_id, "accept", login=recipient_2.email)
        self.assertEqual(res5.json()["success"], True)

        # upon invitation acceptance, user status changed to active
        res6 = recipient_2.get()
        self.assertEqual(res6.json()['user']['email'], recipient_2.email)
        self.assertEqual(res6.json()['user']['status'], 'active')
        # the new email address has access to the group and site
        self.assertEqual(res6.json()["user"]["groups"], [group.group_name])
        self.assertEqual(res6.json()["user"]["sites"], [site.url])

        # if we query the old recipient email, it should not be found
        res7 = recipient.get()
        self.assertEqual(res7.json()["success"], False)
        self.assertEqual(res7.json()["reason"], "no-such-user")

        # group should agree that user and site are still member of the group
        res8 = group.get()
        self.assertEqual(res8.json()["group"]["sites"], [site.url])
        self.assertEqual(res8.json()["group"]["users"], [recipient_2.email])
Example #10
0
    def test_get_all_sites(self):
        group = Group(self.group_name)
        group.create()
        site = Site(self.target_url, groups=[group.group_name])
        site.create()

        res = Sites().get()
        self.assertEqual(res.json()["success"], True)
        self.assertEqual(set(res.json()["sites"][0].keys()), set(self.expected_inner_keys))
        self.assertEqual(res.json()["sites"][0]["url"], site.url)
        self.assertEqual(res.json()["sites"][0]["groups"], site.groups)
        self.assertEqual(res.json()["sites"][0]["plans"], site.plans)
Example #11
0
 def create_plan(self):
     self.plan = Plan(self.TEST_PLAN)
     res = self.plan.create()
     self.assertEqual(res.json()["success"], True)
     self.user = User(self.email)
     self.user.create()
     self.site = Site(self.target_url, plans=[self.plan.plan["name"]])
     self.site.create()
     self.group = Group("testgroup",
                        sites=[self.site.url],
                        users=[self.user.email])
     self.group.create()
Example #12
0
 def test_create_site_without_verifying(self):
     group = Group(self.group_name)
     group.create()
     
     site = Site(self.target_url, groups=[group.group_name])
     res = site.create(verify=False)
     self.assertEqual(set(res.json()['site'].keys()),
         set(self.expected_inner_keys))
     self.assertEqual(res.json()['site']['url'], site.url)
     self.assertEqual(res.json()['site']['plans'], [])
     self.assertEqual(res.json()['site']['verification']['enabled'], False)
     self.assertEqual(res.json()['site']['verification']['value'], None)
    def test_accept_invite_with_a_different_login_email(self):
        # we allow recipient to login with a different email address.
        recipient = User(self.random_email())
        recipient.invite()
        sender = User(self.random_email())
        sender.create()

        invite = Invite(sender.email, recipient.email)
        res1 = invite.create()
        invite_id = res1.json()["invite"]["id"]

        # create a group and a site and add the recipient to the group
        site = Site(self.target_url)
        res2 = site.create()

        # create a group in minion
        group = Group(self.group_name, sites=[site.url], users=[recipient.email])
        group.create()

        # ensure user and site are in this new group
        res3 = group.get()
        self.assertEqual(res3.json()["group"]["sites"], [site.url])
        self.assertEqual(res3.json()["group"]["users"], [recipient.email])

        # user should have access to the group and the site
        res4 = recipient.get()
        self.assertEqual(res4.json()["user"]["sites"], [site.url])
        self.assertEqual(res4.json()["user"]["groups"], [group.group_name])

        # recipient accepts the invitation with a different login email address
        actual_login = self.random_email()
        recipient_2 = User(actual_login)
        res5 = invite.update(invite_id, "accept", login=recipient_2.email)
        self.assertEqual(res5.json()["success"], True)

        # upon invitation acceptance, user status changed to active
        res6 = recipient_2.get()
        self.assertEqual(res6.json()['user']['email'], recipient_2.email)
        self.assertEqual(res6.json()['user']['status'], 'active')
        # the new email address has access to the group and site
        self.assertEqual(res6.json()["user"]["groups"], [group.group_name])
        self.assertEqual(res6.json()["user"]["sites"], [site.url])

        # if we query the old recipient email, it should not be found
        res7 = recipient.get()
        self.assertEqual(res7.json()["success"], False)
        self.assertEqual(res7.json()["reason"], "no-such-user")

        # group should agree that user and site are still member of the group
        res8 = group.get()
        self.assertEqual(res8.json()["group"]["sites"], [site.url])
        self.assertEqual(res8.json()["group"]["users"], [recipient_2.email])
Example #14
0
    def test_update_only_change_plans(self):
        group = Group(self.group_name)
        group.create()
        site = Site(self.target_url, groups=[group.group_name], plans=[self.TEST_PLAN["name"]])
        res1 = site.create()
        site_id = res1.json()["site"]["id"]
        self.assertEqual(res1.json()["success"], True)
        self.assertEqual(res1.json()["site"]["plans"], [self.TEST_PLAN["name"]])
        self.assertEqual(res1.json()["site"]["groups"], [group.group_name])

        res2 = site.update(site_id, plans=[self.TEST_PLAN["name"]])
        self.assertEqual(res2.json()["success"], True)
        self.assertEqual(set(res2.json()["site"]["plans"]), set([self.TEST_PLAN["name"], self.TEST_PLAN["name"]]))
        self.assertEqual(res2.json()["site"]["groups"], [group.group_name])
Example #15
0
    def test_update_only_change_groups(self):
        group1 = Group("group1")
        group1.create()
        group2 = Group("group2")
        group2.create()

        site = Site(self.target_url, groups=[group1.group_name], plans=[self.TEST_PLAN["name"]])
        res1 = site.create()
        site_id = res1.json()["site"]["id"]
        self.assertEqual(res1.json()["success"], True)
        self.assertEqual(res1.json()["site"]["plans"], [self.TEST_PLAN["name"]])
        self.assertEqual(res1.json()["site"]["groups"], [group1.group_name])

        """
Example #16
0
 def create_plan(self):
     self.plan = Plan(self.TEST_PLAN)
     res = self.plan.create()
     self.assertEqual(res.json()["success"], True)
     self.user = User(self.email)
     self.user.create()
     self.site = Site(self.target_url, plans=[self.plan.plan["name"]])
     self.site.create()
     self.group = Group("testgroup", sites=[self.site.url], users=[self.user.email])
     self.group.create()
Example #17
0
    def _create_plan(self, plan=None):
        """ Create a plan in Minion and assign
        a site to a group and a user.

        Use Plan(self.TEST_PLAN) to test plan only.
        """

        _plan = plan or self.TEST_PLAN
        self.plan = Plan(_plan)
        resp = self.plan.create()

        self.user = User(self.email)
        self.user.create()
        self.site = Site(self.target_url, plans=[self.plan.plan["name"]])
        self.site.create()
        self.group = Group("testgroup",
                           sites=[self.site.url],
                           users=[self.user.email])
        self.group.create()
        self.plan = Plan(_plan)
        return resp
Example #18
0
    def test_update_site(self):
        group1 = Group("group1")
        group2 = Group("group2")
        group3 = Group("group3")
        group1.create()
        group2.create()
        group3.create()

        site = Site(self.target_url)
        res1 = site.create()
        site_id = res1.json()["site"]["id"]
        # Verify that the new site has no plans and no groups
        self.assertEqual(res1.json()["site"]['plans'], site.plans)
        self.assertEqual(res1.json()["site"]['groups'], site.groups)

        # Update the site, add a plan and group
        res2 = site.update(site_id, groups=[group1.group_name],
            plans=[self.TEST_PLAN["name"]])
        # Verify that the site has these new settings
        res3 = site.get(site_id)
        self.assertEqual(res3.json()["site"]['plans'], [self.TEST_PLAN["name"]])
        self.assertEqual(res3.json()["site"]["groups"], [group1.group_name])
        self.assertEqual(res3.json()["site"]['url'], site.url)

        # Update the site, replace plans and groups
        res4 = site.update(site_id, groups=[group2.group_name, group3.group_name]) # bug #144
        res5 = site.get(site_id)
        self.assertEqual(res5.json()["site"]['plans'], [self.TEST_PLAN["name"]])
        self.assertEqual(set(res5.json()["site"]['groups']), set([group2.group_name, group3.group_name]))
        self.assertEqual(res5.json()["site"]['url'], site.url)
    def test_send_invite_with_groups_and_sites(self):
        sender = User(self.email, name="Bob")
        sender.create()
        recipient = User(self.random_email(), name="Alice")
        recipient.invite()

        # create the invitation
        invite = Invite(sender.email, recipient.email)
        res = invite.create()
        invite_id = res.json()['invite']['id']

        # create a site in minion
        site = Site(self.target_url)
        res2 = site.create()
        site_id = res2.json()["site"]["id"]

        # Uncomment the following checks when #297 is resolved.
        # create a group in minion
        group = Group(self.group_name,
                      sites=[site.url],
                      users=[recipient.email])
        res3 = group.create()

        # site should exists in group and recipient should also be in the same group
        res4 = group.get()
        self.assertEqual(res4.json()['group']['users'], [
            recipient.email,
        ])

        res5 = site.get(site_id)
        self.assertEqual(res5.json()["site"]["groups"], [group.group_name])

        # finally, if we query recipient's user object, user should be in
        # the group and have access to a site.
        res6 = recipient.get()
        self.assertEqual(res6.json()["user"]["sites"], [site.url])
        self.assertEqual(res6.json()["user"]["groups"], [group.group_name])
Example #20
0
    def _create_plan(self, plan=None):
        """ Create a plan in Minion and assign
        a site to a group and a user.

        Use Plan(self.TEST_PLAN) to test plan only.
        """

        _plan = plan or self.TEST_PLAN
        self.plan = Plan(_plan)
        resp = self.plan.create()

        self.user = User(self.email)
        self.user.create()
        self.site = Site(self.target_url, plans=[self.plan.plan["name"]])
        self.site.create()
        self.group = Group("testgroup", sites=[self.site.url], users=[self.user.email])
        self.group.create()
        self.plan = Plan(_plan)
        return resp
    def test_retrieve_issue_status_and_issues_by_group(self):
        # Don't be shock. This test fits here; by querying
        # user and group, we should only be given the latest
        # issue status.

        bob = User(self.email)
        bob.create()

        group1 = Group("group1", users=[bob.email])
        group2 = Group("group2", users=[bob.email])
        res1 = group1.create()
        res2 = group2.create()

        plan = Plan(self.TEST_PLAN)
        plan.create()

        site1 = Site(self.target_url,
                     groups=[group1.group_name],
                     plans=[self.TEST_PLAN["name"]])
        site1.create()
        site2 = Site(self.target_url,
                     groups=[group2.group_name],
                     plans=[self.TEST_PLAN["name"]])
        site2.create()

        # if we query just test1, should get back only foo.com
        report = Reports()
        res5 = report.get_status(user=bob.email, group_name=group1.group_name)
        r = res5.json()['report']
        self.assertEqual(
            len(r), 1)  # there should just be one dict returned in the list
        self.assertEqual(r[0]['target'], site1.url)

        # if we try it on get_report_issues we should see similar result
        res6 = report.get_issues(user=bob.email, group_name=group1.group_name)
        r = res6.json()['report']
        self.assertEqual(
            len(r), 1)  # there should just be one dict returned in the list
        self.assertEqual(r[0]['target'], site1.url)
Example #22
0
class TestScanAPIs(TestAPIBaseClass):
    TEST_PLAN = {
        "name":
        "test-plan",
        "description":
        "Plan that runs HelloWorldPlugin",
        "workflow": [{
            "plugin_name": "minion.plugins.test.HelloWorldPlugin",
            "description": "",
            "configuration": {}
        }]
    }

    def create_plan(self):
        self.plan = Plan(self.TEST_PLAN)
        res = self.plan.create()
        self.assertEqual(res.json()["success"], True)
        self.user = User(self.email)
        self.user.create()
        self.site = Site(self.target_url, plans=[self.plan.plan["name"]])
        self.site.create()
        self.group = Group("testgroup",
                           sites=[self.site.url],
                           users=[self.user.email])
        self.group.create()

    def setUp(self):
        super(TestScanAPIs, self).setUp()
        self.create_plan()

    def test_create_scan_with_credential(self):
        scan = Scan(self.user.email, self.TEST_PLAN["name"],
                    {"target": self.target_url})
        res = scan.create()
        expected_top_keys = (
            'success',
            'scan',
        )
        self.assertEqual(res.json()["success"], True)
        expected_scan_keys = set(['id', 'state', 'created', 'queued', 'started', \
                'finished', 'plan', 'configuration', 'sessions', 'meta'])
        self.assertEqual(set(res.json()["scan"].keys()), expected_scan_keys)

        meta = res.json()['scan']['meta']
        # this scan is not tagged
        self.assertEqual(meta['tags'], [])
        # bug #106 add owner of the scan
        self.assertEqual(meta['user'], self.user.email)
        self.assertEqual(res.json()['scan']['configuration']['target'],
                         self.target_url)

        scan = res.json()['scan']
        expected_session_keys = ['id', 'state', 'plugin', 'configuration', \
                'description', 'artifacts', 'issues', 'created', 'started', \
                'queued', 'finished', 'progress']
        for session in scan['sessions']:
            self.assertEqual(set(session.keys()), set(expected_session_keys))
            self.assertEqual(session['configuration']['target'],
                             self.target_url)

            self.assertEqual(session['state'], 'CREATED')
            self.assertEqual(session['artifacts'], {})
            self.assertEqual(session['issues'], [])
            for name in ('queued', 'started', 'finished', 'progress'):
                self.assertEqual(session[name], None)

    def test_get_scan_details(self):
        scan = Scan(self.user.email, self.TEST_PLAN["name"],
                    {"target": self.target_url})
        res1 = scan.create()
        scan_id = res1.json()['scan']['id']

        res2 = scan.get_scan_details(scan_id)
        # since scan hasn't started, should == res1
        self.assertEqual(res2.json(), res1.json())

        # bug #140 and bug #146
        res3 = scan.get_scan_details(scan_id, email=self.user.email)
        self.assertEqual(res3.json(), res2.json())

    # bug #140 and bug #146
    def test_get_scan_details_filter_with_nonexistent_user(self):
        # If we give a non-existent user in the request argument, it will return user not found
        scan = Scan(self.user.email, self.TEST_PLAN["name"],
                    {"target": self.target_url})
        res1 = scan.create()
        scan_id = res1.json()['scan']['id']

        res2 = scan.get_scan_details(scan_id,
                                     email="*****@*****.**")
        self.assertEqual(res2.json()["success"], False)
        self.assertEqual(res2.json()["reason"], "user-does-not-exist")

    # bug #140 and bug #146
    def test_get_scan_details_filter_with_incorrect_user(self):
        # Scan is started by Bob and only Bob's group has access to target_url.
        # Alice does not belong to Bob's group so she has no permission to the scan
        scan = Scan(self.user.email, self.TEST_PLAN["name"],
                    {"target": self.target_url})
        res1 = scan.create()
        scan_id = res1.json()['scan']['id']

        alice = User("*****@*****.**")
        res2 = alice.create()
        self.assertEqual(res2.json()["success"], True)

        res2 = scan.get_scan_details(scan_id, email=alice.email)
        self.assertEqual(res2.json()["success"], False)
        self.assertEqual(res2.json()["reason"], "not-found")

    def test_scan(self):
        """
        This is a comprehensive test that runs through the following
        endpoints:

        1. POST /scans
        2. GET /scans/<scan_id>
        3. PUT /scans/<scan_id>/control
        4. GET /scans/<scan_id>/summary
        5. GET /reports/history
        6. GET /reports/status
        7. GET /reports/issues

        """

        # Create user, site, group, plan and site
        # This is already handled in setUp call.

        # POST /scans
        # create a scan on target_url based on our
        # test plan (which runs HelloWorldPlugin)
        scan = Scan(self.user.email, self.TEST_PLAN["name"],
                    {"target": self.target_url})
        res1 = scan.create()
        scan_id = res1.json()['scan']['id']

        # PUT /scans/<scan_id>/control
        # Start the scan now.
        res2 = scan.start(scan_id)
        self.assertEqual(res2.json()['success'], True)

        # GET /scans/<scan_id>
        # Check the status. It should be in QUEUED (hopefully it doesn't go too fast)
        res3 = scan.get_scan_details(scan_id)
        self.assertEqual(res3.json()["scan"]["state"], "QUEUED")
        # POST and GET scan details should have the same set of keys at the top-level
        # and at the "scan" level
        self.assertEqual(set(res3.json().keys()), set(res1.json().keys()))
        self.assertEqual(set(res3.json()["scan"].keys()),
                         set(res1.json()["scan"].keys()))

        # give scanner a few seconds
        time.sleep(6)

        # GET /scans/<scan_id>
        # now check if the scan has completed or not
        res4 = scan.get_scan_details(scan_id)
        self.assertEqual(res4.json()['scan']['state'], 'FINISHED')

        # GET /scans/<scan_id>/summary
        res5 = scan.get_summary(scan_id)
        # bug #106 include scan creator in the output
        self.assertEqual(res5.json()['summary']['meta'], {
            'user': self.email,
            'tags': []
        })

        # GET /reports/history
        res6 = Reports().get_history()
        self.assertEqual(res6.json()["success"], True)
        expected_inner_keys = set([
            'configuration', 'created', 'finished', 'id', 'issues', "meta",
            'plan', 'queued', 'sessions', 'state'
        ])
        self.assertEqual(set(res6.json()['report'][0].keys()),
                         expected_inner_keys)
        self.assertEqual(res6.json()['report'][0]['id'], scan_id)

        # GET /reports/status
        res7 = Reports().get_status(user=self.user.email)
        self.assertEqual(res7.json()["success"], True)
        expected_inner_keys = set(['plan', 'scan', 'target'])
        self.assertEqual(set(res7.json()['report'][0].keys()),
                         expected_inner_keys)
        self.assertEqual(res7.json()['report'][0]['plan'],
                         self.plan.plan["name"])
        self.assertEqual(res7.json()['report'][0]['target'], self.target_url)

        # GET /reports/issues
        res8 = Reports().get_issues(user=self.user.email)
        self.assertEqual(res8.json()["success"], True)
        expected_inner_keys = (
            'issues',
            'target',
        )
        self.assertEqual(set(res8.json()['report'][0].keys()),
                         set(["issues", "target"]))

        issues = res8.json()['report'][0]['issues']
        # DelayPlugin emits only one issue
        self.assertEqual(len(issues), 1)
        self.assertEqual(issues[0]["summary"], "Hello World")
        self.assertEqual('Info', issues[0]['severity'])
        self.assertEqual(issues[0]["severity"], "Info")
        self.assertEqual(res8.json()['report'][0]['target'], self.target_url)
Example #23
0
class TestPlanAPIs(TestAPIBaseClass):

    TEST_PLAN = {
        "name":
        "test",
        "description":
        "Test",
        "workflow": [{
            "plugin_name": "minion.plugins.basic.AlivePlugin",
            "description": "Test if the site is alive",
            "configuration": {
                "foo": "bar"
            }
        }]
    }

    def _create_plan(self, plan=None):
        """ Create a plan in Minion and assign
        a site to a group and a user.

        Use Plan(self.TEST_PLAN) to test plan only.
        """

        _plan = plan or self.TEST_PLAN
        self.plan = Plan(_plan)
        resp = self.plan.create()

        self.user = User(self.email)
        self.user.create()
        self.site = Site(self.target_url, plans=[self.plan.plan["name"]])
        self.site.create()
        self.group = Group("testgroup",
                           sites=[self.site.url],
                           users=[self.user.email])
        self.group.create()
        self.plan = Plan(_plan)
        return resp

    def _assert_test_plan(self, plan):
        self.assertEqual("test", plan["name"])
        self.assertEqual("Test", plan["description"])
        self.assertEqual(1, len(plan["workflow"]))
        self.assertEqual("Test if the site is alive",
                         plan["workflow"][0]["description"])
        self.assertEqual({"foo": "bar"}, plan["workflow"][0]["configuration"])
        self.assertEqual("minion.plugins.basic.AlivePlugin",
                         plan["workflow"][0]["plugin_name"])

    def test_create_plan_and_get_plan(self):
        plan = Plan(self.TEST_PLAN)
        res = plan.create()
        self.assertEqual(res.json()["success"], True)
        self._assert_test_plan(res.json()["plan"])

        # Check if we can retrieve the plan we just created
        # retrieve the newly created plan
        res2 = plan.get(plan.plan["name"])
        self.assertEqual(res2.json()["success"], True)
        self._assert_test_plan(res2.json()["plan"])

    def test_get_plan_without_email(self):
        self._create_plan()
        resp = Plans().get(name=self.TEST_PLAN["name"])
        self.assertEqual(len(resp.json()["plans"]), 1)
        self._assert_test_plan(resp.json()["plans"][0])

    def test_find_all_plans_registered_under_an_email(self):
        self._create_plan()
        resp = Plans().get(email=self.user.email)
        self.assertEqual(len(resp.json()["plans"]), 1)
        self._assert_test_plan(resp.json()["plans"][0])

    def test_create_invalid_plugin_plan(self):
        # Check /plans return invalid-plan-exists when plugin is not
        # importable.
        bad_plan = {
            "name":
            "test",
            "description":
            "Test",
            "workflow": [{
                "plugin_name": "minion.plugins.basic.Cheeseburger",
                "description": "Test if the site is cheeseburger",
                "configuration": {
                    "foo": "bar"
                }
            }]
        }
        plan = Plan(bad_plan)
        resp = plan.create()
        self.assertEqual(resp.status_code, 200)
        self.assertEqual(resp.json()['reason'], 'invalid-plan-exists')

    def test_create_plan_fail_because_plugin_name_is_missing(self):
        # this plan does not contain plugin_name which is invalid
        bad_plan = {
            "name":
            "test",
            "description":
            "Test",
            "workflow": [{
                "description": "Test if the site is cheeseburger",
                "configuration": {
                    "foo": "bar"
                }
            }]
        }
        plan = Plan(bad_plan)
        resp = plan.create()
        self.assertEqual(resp.status_code, 200)
        self.assertEqual(resp.json()['reason'], 'invalid-plan-exists')

    def test_create_plan_fail_because_workflow_is_empty(self):
        # workflow is entirely missing
        bad_plan = {"name": "test", "description": "Test", "workflow": []}
        plan = Plan(bad_plan)
        resp = plan.create()
        self.assertEqual(resp.status_code, 200)
        self.assertEqual(resp.json()['reason'], 'invalid-plan-exists')

    def test_delete_plan(self):
        plan = Plan(self.TEST_PLAN)
        res1 = plan.create()
        self.assertEqual(res1.json()["success"], True)

        # Delete the plan
        res2 = plan.delete(self.TEST_PLAN["name"])
        self.assertEqual(res2.json()["success"], True)

        # Make sure the plan is gone
        res3 = plan.get(self.TEST_PLAN["name"])
        self.assertEqual(res3.json()["success"], False)
        self.assertEqual(res3.json()["reason"], "Plan does not exist")

    def test_delete_nonexistent_plan(self):
        plan = Plan(None)
        resp = plan.delete("nonexistentplan")
        self.assertEqual(resp.json()["success"], False)
        self.assertEqual(resp.json()["reason"], "Plan does not exist.")

    def test_update_plan(self):
        plan = Plan(self.TEST_PLAN)
        resp = plan.create()

        # Update the plan
        new_plan = {
            "description":
            "Changed Test",
            "workflow": [{
                "plugin_name": "minion.plugins.basic.XFrameOptionsPlugin",
                "description":
                "Test if the site has an X-Frame-Options header",
                "configuration": {
                    "require": "DENY"
                }
            }]
        }

        res = plan.update(plan.plan["name"], new_plan)
        self.assertEqual(res.json()["success"], True)

        # make a copy of the new plan because we need to fill in the plan name
        _new_plan = dict(new_plan)
        _new_plan["name"] = self.TEST_PLAN["name"]
        # the response contains some unncessary fields, only extract the good one
        _res_plan = {
            key: value
            for key, value in res.json()["plan"].items()
            if key in ("name", "description", "workflow")
        }
        # the new plan we feed into minion and the one we return from response shoudl match
        self.assertEqual(_res_plan, _new_plan)

        # make sure get gives the same result as well
        res2 = plan.get(self.TEST_PLAN["name"])
        _res2_plan = {
            key: value
            for key, value in res2.json()["plan"].items()
            if key in ("name", "description", "workflow")
        }
        self.assertEqual(_res2_plan, _new_plan)
Example #24
0
 def test_update_site_with_unknown_group(self):
     site = Site(self.target_url)
     res1 = site.create()
     site_id = res1.json()["site"]["id"]
     res2 = site.update(site_id, groups=["non-existing-group"])
     self.assertEqual(res2.json(), {"success": False, "reason": "unknown-group"})
Example #25
0
class TestPlanAPIs(TestAPIBaseClass):

    TEST_PLAN = { "name": "test",
                      "description": "Test",
                      "workflow": [ { "plugin_name": "minion.plugins.basic.AlivePlugin",
                                      "description": "Test if the site is alive",
                                      "configuration": { "foo": "bar" }
                                      } ] }
    def _create_plan(self, plan=None):
        """ Create a plan in Minion and assign
        a site to a group and a user.

        Use Plan(self.TEST_PLAN) to test plan only.
        """

        _plan = plan or self.TEST_PLAN
        self.plan = Plan(_plan)
        resp = self.plan.create()

        self.user = User(self.email)
        self.user.create()
        self.site = Site(self.target_url, plans=[self.plan.plan["name"]])
        self.site.create()
        self.group = Group("testgroup", sites=[self.site.url], users=[self.user.email])
        self.group.create()
        self.plan = Plan(_plan)
        return resp

    def _assert_test_plan(self, plan):
        self.assertEqual("test", plan["name"])
        self.assertEqual("Test", plan["description"])
        self.assertEqual(1, len(plan["workflow"]))
        self.assertEqual("Test if the site is alive", plan["workflow"][0]["description"])
        self.assertEqual({"foo": "bar"}, plan["workflow"][0]["configuration"])
        self.assertEqual("minion.plugins.basic.AlivePlugin", plan["workflow"][0]["plugin_name"])

    def test_create_plan_and_get_plan(self):
        plan = Plan(self.TEST_PLAN)
        res = plan.create()
        self.assertEqual(res.json()["success"], True)
        self._assert_test_plan(res.json()["plan"])

        # Check if we can retrieve the plan we just created
        # retrieve the newly created plan
        res2 = plan.get(plan.plan["name"])
        self.assertEqual(res2.json()["success"], True)
        self._assert_test_plan(res2.json()["plan"])

    def test_get_plan_without_email(self):
        self._create_plan()
        resp = Plans().get(name=self.TEST_PLAN["name"])
        self.assertEqual(len(resp.json()["plans"]), 1)
        self._assert_test_plan(resp.json()["plans"][0])

    def test_find_all_plans_registered_under_an_email(self):
        self._create_plan()
        resp = Plans().get(email=self.user.email)
        self.assertEqual(len(resp.json()["plans"]), 1)
        self._assert_test_plan(resp.json()["plans"][0])

    def test_create_invalid_plugin_plan(self):
        # Check /plans return invalid-plan-exists when plugin is not
        # importable.
        bad_plan = { "name": "test",
                     "description": "Test",
                     "workflow": [ { "plugin_name": "minion.plugins.basic.Cheeseburger",
                                     "description": "Test if the site is cheeseburger",
                                     "configuration": { "foo": "bar" }
                      } ] }
        plan = Plan(bad_plan)
        resp = plan.create()
        self.assertEqual(resp.status_code, 200)
        self.assertEqual(resp.json()['reason'], 'invalid-plan-exists')

    def test_create_plan_fail_because_plugin_name_is_missing(self):
        # this plan does not contain plugin_name which is invalid
        bad_plan = { "name": "test",
                     "description": "Test",
                     "workflow": [ {"description": "Test if the site is cheeseburger",
                                    "configuration": { "foo": "bar" }
                    } ] }
        plan = Plan(bad_plan)
        resp = plan.create()
        self.assertEqual(resp.status_code, 200)
        self.assertEqual(resp.json()['reason'], 'invalid-plan-exists')

    def test_create_plan_fail_because_workflow_is_empty(self):
        # workflow is entirely missing
        bad_plan = { "name": "test",
                     "description": "Test",
                     "workflow": []}
        plan = Plan(bad_plan)
        resp = plan.create()
        self.assertEqual(resp.status_code, 200)
        self.assertEqual(resp.json()['reason'], 'invalid-plan-exists')

    def test_delete_plan(self):
        plan = Plan(self.TEST_PLAN)
        res1 = plan.create()
        self.assertEqual(res1.json()["success"], True)

        # Delete the plan
        res2 = plan.delete(self.TEST_PLAN["name"])
        self.assertEqual(res2.json()["success"], True)

        # Make sure the plan is gone
        res3 = plan.get(self.TEST_PLAN["name"])
        self.assertEqual(res3.json()["success"], False)
        self.assertEqual(res3.json()["reason"], "Plan does not exist")

    def test_delete_nonexistent_plan(self):
        plan = Plan(None)
        resp = plan.delete("nonexistentplan")
        self.assertEqual(resp.json()["success"], False)
        self.assertEqual(resp.json()["reason"], "Plan does not exist.")

    def test_update_plan(self):
        plan = Plan(self.TEST_PLAN)
        resp = plan.create()

        # Update the plan
        new_plan = { "description": "Changed Test",
                     "workflow": [ { "plugin_name": "minion.plugins.basic.XFrameOptionsPlugin",
                                     "description": "Test if the site has an X-Frame-Options header",
                                     "configuration": { "require": "DENY" } } ] }

        res = plan.update(plan.plan["name"], new_plan)
        self.assertEqual(res.json()["success"], True)

        # make a copy of the new plan because we need to fill in the plan name
        _new_plan = dict(new_plan)
        _new_plan["name"] = self.TEST_PLAN["name"]
        # the response contains some unncessary fields, only extract the good one
        _res_plan = {key:value for key,value in res.json()["plan"].items() 
                if key in ("name", "description", "workflow")}
        # the new plan we feed into minion and the one we return from response shoudl match
        self.assertEqual(_res_plan, _new_plan)

        # make sure get gives the same result as well
        res2 = plan.get(self.TEST_PLAN["name"])
        _res2_plan = {key:value for key,value in res2.json()["plan"].items() 
                if key in ("name", "description", "workflow")}
        self.assertEqual(_res2_plan, _new_plan)
Example #26
0
 def test_update_unknown_site(self):
     site = Site(self.target_url)
     res = site.update("e22dbe0c-b958-4050-a339-b9a88fa7cd01",
         plans=["nmap", "zap"], groups=["foo", "bar"])
     self.assertEqual(res.json(), {'success': False, 'reason': 'no-such-site'})
Example #27
0
class TestScanAPIs(TestAPIBaseClass):
    TEST_PLAN = {
        "name": "test-plan",
        "description": "Plan that runs HelloWorldPlugin",
        "workflow": [
            {
                "plugin_name": "minion.plugins.test.HelloWorldPlugin",
                "description": "",
                "configuration": {}
            }
        ]
    }

    def create_plan(self):
        self.plan = Plan(self.TEST_PLAN)
        res = self.plan.create()
        self.assertEqual(res.json()["success"], True)
        self.user = User(self.email)
        self.user.create()
        self.site = Site(self.target_url, plans=[self.plan.plan["name"]])
        self.site.create()
        self.group = Group("testgroup", sites=[self.site.url], users=[self.user.email])
        self.group.create()

    def setUp(self):
        super(TestScanAPIs, self).setUp()
        self.create_plan()

    def test_create_scan_with_credential(self):
        scan = Scan(self.user.email, self.TEST_PLAN["name"], {"target": self.target_url})
        res = scan.create()
        expected_top_keys = ('success', 'scan',)
        self.assertEqual(res.json()["success"], True)
        expected_scan_keys = set(['id', 'state', 'created', 'queued', 'started', \
                'finished', 'plan', 'configuration', 'sessions', 'meta'])
        self.assertEqual(set(res.json()["scan"].keys()), expected_scan_keys)

        meta = res.json()['scan']['meta']
        # this scan is not tagged
        self.assertEqual(meta['tags'], [])
        # bug #106 add owner of the scan
        self.assertEqual(meta['user'], self.user.email)
        self.assertEqual(res.json()['scan']['configuration']['target'],
            self.target_url)

        scan = res.json()['scan']
        expected_session_keys = ['id', 'state', 'plugin', 'configuration', \
                'description', 'artifacts', 'issues', 'created', 'started', \
                'queued', 'finished', 'progress']
        for session in scan['sessions']:
            self.assertEqual(set(session.keys()), set(expected_session_keys))
            self.assertEqual(session['configuration']['target'], self.target_url)

            self.assertEqual(session['state'], 'CREATED')
            self.assertEqual(session['artifacts'], {})
            self.assertEqual(session['issues'], [])
            for name in ('queued', 'started', 'finished', 'progress'):
                self.assertEqual(session[name], None)

    def test_get_scan_details(self):
        scan = Scan(self.user.email, self.TEST_PLAN["name"], {"target": self.target_url})
        res1 = scan.create()
        scan_id = res1.json()['scan']['id']

        res2 = scan.get_scan_details(scan_id)
        # since scan hasn't started, should == res1
        self.assertEqual(res2.json(), res1.json())

        # bug #140 and bug #146
        res3 = scan.get_scan_details(scan_id, email=self.user.email)
        self.assertEqual(res3.json(), res2.json())

    # bug #140 and bug #146
    def test_get_scan_details_filter_with_nonexistent_user(self):
        # If we give a non-existent user in the request argument, it will return user not found
        scan = Scan(self.user.email, self.TEST_PLAN["name"], {"target": self.target_url})
        res1 = scan.create()
        scan_id = res1.json()['scan']['id']

        res2 = scan.get_scan_details(scan_id, email="*****@*****.**")
        self.assertEqual(res2.json()["success"], False)
        self.assertEqual(res2.json()["reason"], "user-does-not-exist")

    # bug #140 and bug #146
    def test_get_scan_details_filter_with_incorrect_user(self):
        # Scan is started by Bob and only Bob's group has access to target_url.
        # Alice does not belong to Bob's group so she has no permission to the scan
        scan = Scan(self.user.email, self.TEST_PLAN["name"], {"target": self.target_url})
        res1 = scan.create()
        scan_id = res1.json()['scan']['id']

        alice = User("*****@*****.**")
        res2 = alice.create()
        self.assertEqual(res2.json()["success"], True)

        res2 = scan.get_scan_details(scan_id, email=alice.email)
        self.assertEqual(res2.json()["success"], False)
        self.assertEqual(res2.json()["reason"], "not-found")

    def test_scan(self):
        """
        This is a comprehensive test that runs through the following
        endpoints:

        1. POST /scans
        2. GET /scans/<scan_id>
        3. PUT /scans/<scan_id>/control
        4. GET /scans/<scan_id>/summary
        5. GET /reports/history
        6. GET /reports/status
        7. GET /reports/issues

        """

        # Create user, site, group, plan and site
        # This is already handled in setUp call.

        # POST /scans
        # create a scan on target_url based on our 
        # test plan (which runs HelloWorldPlugin)
        scan = Scan(self.user.email, self.TEST_PLAN["name"], {"target": self.target_url})
        res1 = scan.create()
        scan_id = res1.json()['scan']['id']

        # PUT /scans/<scan_id>/control
        # Start the scan now.
        res2 = scan.start(scan_id)
        self.assertEqual(res2.json()['success'], True)

        # GET /scans/<scan_id>
        # Check the status. It should be in QUEUED (hopefully it doesn't go too fast)
        res3 = scan.get_scan_details(scan_id)
        self.assertEqual(res3.json()["scan"]["state"], "QUEUED")
        # POST and GET scan details should have the same set of keys at the top-level
        # and at the "scan" level
        self.assertEqual(set(res3.json().keys()), set(res1.json().keys()))
        self.assertEqual(set(res3.json()["scan"].keys()), set(res1.json()["scan"].keys()))

        # give scanner a few seconds
        time.sleep(6)

        # GET /scans/<scan_id>
        # now check if the scan has completed or not
        res4 = scan.get_scan_details(scan_id)
        self.assertEqual(res4.json()['scan']['state'], 'FINISHED')
        
        # GET /scans/<scan_id>/summary
        res5 = scan.get_summary(scan_id)
        # bug #106 include scan creator in the output
        self.assertEqual(res5.json()['summary']['meta'], 
            {'user': self.email, 'tags': []})

        # GET /reports/history
        res6 = Reports().get_history()
        self.assertEqual(res6.json()["success"], True)
        expected_inner_keys = set(['configuration', 'created', 'finished', 'id',
                'issues', "meta", 'plan', 'queued', 'sessions', 'state'])
        self.assertEqual(set(res6.json()['report'][0].keys()), expected_inner_keys)
        self.assertEqual(res6.json()['report'][0]['id'], scan_id)

        # GET /reports/status
        res7 = Reports().get_status(user=self.user.email)
        self.assertEqual(res7.json()["success"], True)
        expected_inner_keys = set(['plan', 'scan', 'target'])
        self.assertEqual(set(res7.json()['report'][0].keys()), expected_inner_keys)
        self.assertEqual(res7.json()['report'][0]['plan'], self.plan.plan["name"])
        self.assertEqual(res7.json()['report'][0]['target'], self.target_url)

        # GET /reports/issues
        res8 = Reports().get_issues(user=self.user.email)
        self.assertEqual(res8.json()["success"], True)
        expected_inner_keys = ('issues', 'target',)
        self.assertEqual(set(res8.json()['report'][0].keys()), set(["issues", "target"]))

        issues = res8.json()['report'][0]['issues']
        # DelayPlugin emits only one issue
        self.assertEqual(len(issues), 1)
        self.assertEqual(issues[0]["summary"], "Hello World")
        self.assertEqual('Info', issues[0]['severity'])
        self.assertEqual(issues[0]["severity"], "Info")
        self.assertEqual(res8.json()['report'][0]['target'], self.target_url)
Example #28
0
 def test_update_site_with_unknown_plan(self):
     site = Site(self.target_url)
     res1 = site.create()
     site_id = res1.json()["site"]["id"]
     res2 = site.update(site_id, plans=["non-existing-plan"])
     self.assertEqual(res2.json(), {'success': False, 'reason': 'unknown-plan'})