def test_deny_change_requires_feedback(): vuln = Vulnerability(state=VulnerabilityState.IN_REVIEW) with pytest.raises(TransitionDenied): vuln.update_state(VulnerabilityState.NEEDS_IMPROVEMENT) assert vuln.state == VulnerabilityState.IN_REVIEW
def test_mark_new_as_reviewable(): cr1 = creator1() vuln = Vulnerability(state=VulnerabilityState.NEW, creator=cr1) vuln.make_reviewable() assert vuln.state == VulnerabilityState.READY assert vuln.is_reviewable()
def test_publish_requires_version(): vuln = Vulnerability(state=VulnerabilityState.REVIEWED) with pytest.raises(TransitionDenied): vuln.update_state(VulnerabilityState.PUBLISHED) assert vuln.state == VulnerabilityState.REVIEWED
def test_mark_needs_improvement_as_reviewable(): cr1 = creator1() vuln = Vulnerability(state=VulnerabilityState.NEEDS_IMPROVEMENT, creator=cr1) vuln.make_reviewable() assert vuln.state == VulnerabilityState.READY assert vuln.is_reviewable
def test_take_review_requires_reviewer(): cr1 = creator1() vuln = Vulnerability(state=VulnerabilityState.READY, creator=cr1) with pytest.raises(TransitionDenied): vuln.update_state(VulnerabilityState.IN_REVIEW) assert vuln.state == VulnerabilityState.READY
def test_state_matrix(src_state, dst_state, exc): cr1 = creator1() vuln = Vulnerability(state=src_state, creator=cr1) if exc: with pytest.raises(exc): vuln.update_state(dst_state) else: vuln.update_state(dst_state)
def test_return_review_requires_reviewer_reset(): rev = reviewer() vuln = Vulnerability(state=VulnerabilityState.IN_REVIEW, reviewer=rev) with pytest.raises(TransitionDenied): vuln.update_state(VulnerabilityState.READY) assert vuln.state == VulnerabilityState.IN_REVIEW
def test_deny_reviewed(): vuln = Vulnerability(state=VulnerabilityState.REVIEWED) vuln.deny_change('merge conflict') assert vuln.state == VulnerabilityState.NEW assert vuln.review_feedback == 'merge conflict' assert not vuln.is_publishable() assert not vuln.is_reviewable()
def test_take_review(): cr1 = creator1() rev = reviewer() vuln = Vulnerability(state=VulnerabilityState.READY, creator=cr1) vuln.accept_review(rev) assert vuln.reviewer == rev assert vuln.state == VulnerabilityState.IN_REVIEW assert vuln.is_reviewer(rev)
def test_return_review(): rev = reviewer() vuln = Vulnerability(state=VulnerabilityState.IN_REVIEW, reviewer=rev) vuln.return_to_review_pool() assert vuln.state == VulnerabilityState.READY assert vuln.reviewer is None assert not vuln.is_publishable() assert vuln.is_reviewable()
def test_deny_reviewed(): vuln = Vulnerability(state=VulnerabilityState.REVIEWED) rev = reviewer() vuln.deny_change(rev, 'merge conflict') assert vuln.state == VulnerabilityState.NEEDS_IMPROVEMENT assert vuln.review_feedback == 'merge conflict' assert not vuln.is_publishable() assert not vuln.is_reviewable()
def test_publish_reviewed(mocker): mocker.patch.object(Vulnerability, "next_version_number").return_value = 123 vuln = Vulnerability(state=VulnerabilityState.REVIEWED, version=1) vuln.publish_change() assert vuln.state == VulnerabilityState.PUBLISHED assert vuln.version == 123 assert not vuln.is_publishable assert not vuln.is_in_review
def test_archive_published(mocker): # !! mocks all .query getters on all models. Save here as we only use one mock_query = mocker.patch("flask_sqlalchemy._QueryProperty.__get__").return_value mock_query.filter.return_value.exists.return_value = True vuln = Vulnerability(state=VulnerabilityState.PUBLISHED) vuln.archive_entry() assert vuln.state == VulnerabilityState.ARCHIVED assert not vuln.is_publishable assert not vuln.is_in_review
def test_archive_requires_published(mocker): # !! mocks all .query getters on all models. Save here as we only use one mock_query = mocker.patch("flask_sqlalchemy._QueryProperty.__get__").return_value mock_query.filter.return_value.first.return_value = False vuln = Vulnerability(state=VulnerabilityState.PUBLISHED) with pytest.raises(TransitionDenied): vuln.archive_entry() assert vuln.state == VulnerabilityState.PUBLISHED assert not vuln.is_publishable assert not vuln.is_in_review
def test_accept_change_after_review(): vuln = Vulnerability(state=VulnerabilityState.IN_REVIEW) vuln.accept_change() assert vuln.state == VulnerabilityState.REVIEWED assert vuln.is_publishable()
def _db(app): """Returns session-wide initialised database.""" db = DEFAULT_DATABASE.db # setup databases and tables with open(os.path.join(cfg.BASE_DIR, 'docker/db_schema.sql'), 'rb') as f: create_schemas_sql = f.read().decode('utf8') with app.app_context(): # clear database db.drop_all() db.engine.execute('DROP TABLE IF EXISTS alembic_version') # build database db.engine.execute(create_schemas_sql) alembic_upgrade() # create data vuln_cves = list('CVE-1970-{}'.format(1000 + i) for i in range(10)) new_cves = list('CVE-1970-{}'.format(2000 + i) for i in range(10)) cves = vuln_cves + new_cves session = db.session nvds = [] for i, cve in enumerate(cves, 1): nvds.append( Nvd(cve_id=cve, descriptions=[ Description(value='Description {}'.format(i), ), ], references=[ Reference( link= 'https://cve.mitre.org/cgi-bin/cvename.cgi?name={}' .format(cve), source='cve.mitre.org', ), ], published_date=datetime.date.today(), cpes=[ Cpe( vendor='Vendor {}'.format(i), product='Product {}'.format(j), ) for j in range(1, 4) ])) session.add_all(nvds) vulns = [] for i, cve in enumerate(vuln_cves, 1): repo_owner = 'OWNER' repo_name = 'REPO{i}'.format(i=i) repo_url = 'https://github.com/{owner}/{repo}/'.format( owner=repo_owner, repo=repo_name, ) commit = '{:07x}'.format(0x1234567 + i) vulns.append( Vulnerability( cve_id=cve, date_created=datetime.date.today(), comment='Vulnerability {} comment'.format(i), commits=[ VulnerabilityGitCommits( commit_link='{repo_url}commit/{commit}'.format( repo_url=repo_url, commit=commit, ), repo_owner=repo_owner, repo_name=repo_name, # repo_url=repo_url, commit_hash=commit) ])) vulns.append( Vulnerability( cve_id='CVE-1970-1500', date_created=datetime.date.today(), comment='Vulnerability {} comment'.format(len(vuln_cves) + 1), commits=[])) session.add_all(vulns) users = [ User( email='*****@*****.**', full_name='Admin McAdmin', ), User( email='*****@*****.**', full_name='User McUser', ) ] session.add_all(users) session.commit() return db
def setup_test_database(): """Returns session-wide initialised database.""" # Create a temporary flask app for the database setup. # We don't use the app or db fixtures here as they should be # executed in the function scope, not in the session scope like # this function is. app = create_app(TEST_CONFIG) with app.app_context(): db: SQLAlchemy = app.extensions["sqlalchemy"].db # setup databases and tables with open(os.path.join(cfg.BASE_DIR, "docker/db_schema.sql"), "rb") as f: create_schemas_sql = f.read().decode("utf8") # with app.app_context(): # clear database db.drop_all() db.engine.execute("DROP TABLE IF EXISTS alembic_version") # build database db.engine.execute(create_schemas_sql) alembic_upgrade() # create data session = db.session roles = [ Role(name=role) for role in (PredefinedRoles.ADMIN, PredefinedRoles.USER) ] session.add_all(roles) users = [ User( login="******", full_name="Admin McAdmin", roles=roles, state=UserState.ACTIVE, login_type=LoginType.LOCAL, ), User( login="******", full_name="User McUser", roles=[roles[1]], state=UserState.ACTIVE, login_type=LoginType.LOCAL, ), User( login="******", full_name="Blocked User", roles=[roles[1]], state=UserState.BLOCKED, login_type=LoginType.LOCAL, ), ] session.add_all(users) vuln_cves = list("CVE-1970-{}".format(1000 + i) for i in range(10)) new_cves = list("CVE-1970-{}".format(2000 + i) for i in range(10)) cves = vuln_cves + new_cves nvds = [] for i, cve in enumerate(cves, 1): nvds.append( Nvd( cve_id=cve, descriptions=[ Description( value="Description {}".format(i), ), ], references=[ Reference( link="https://cve.mitre.org/cgi-bin/cvename.cgi?name={}".format( cve ), source="cve.mitre.org", ), ], published_date=datetime.date.today(), cpes=[ Cpe( vendor="Vendor {}".format(i), product="Product {}".format(j), ) for j in range(1, 4) ], ) ) session.add_all(nvds) vulns = [] for i, cve in enumerate(vuln_cves, 1): repo_owner = "OWNER" repo_name = "REPO{i}".format(i=i) repo_url = "https://github.com/{owner}/{repo}/".format( owner=repo_owner, repo=repo_name, ) commit = "{:07x}".format(0x1234567 + i) vulns.append( Vulnerability( vcdb_id=i, cve_id=cve, date_created=datetime.date.today(), creator=users[1], state=VulnerabilityState.PUBLISHED, version=0, comment="Vulnerability {} comment".format(i), commits=[ VulnerabilityGitCommits( commit_link="{repo_url}commit/{commit}".format( repo_url=repo_url, commit=commit, ), repo_owner=repo_owner, repo_name=repo_name, # TODO: test conflicting data? repo_url=repo_url, commit_hash=commit, ) ], ) ) vulns.append( Vulnerability( state=VulnerabilityState.PUBLISHED, version=0, vcdb_id=len(vulns) + 1, cve_id="CVE-1970-1500", date_created=datetime.date.today(), comment="Vulnerability {} comment".format(len(vuln_cves) + 1), commits=[], ) ) session.add_all(vulns) session.commit()