示例#1
0
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
示例#3
0
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
示例#4
0
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()
示例#5
0
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
示例#6
0
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)
    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
示例#8
0
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
示例#10
0
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
示例#11
0
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
示例#12
0
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
示例#13
0
def test_delete_vulnerability_entry(client):
    vuln = Vulnerability.get_by_cve_id('CVE-1970-1000')
    assert vuln is not None

    resp = client.post('/CVE-1970-1000/create',
                       data={
                           'delete_entry': vuln.id,
                       })
    assert resp.status_code == 401

    vuln = Vulnerability.get_by_cve_id('CVE-1970-1000')
    assert vuln is not None
示例#14
0
def test_update_vulnerability(client, db_session, use_group, expected_status):
    if use_group:
        use_group(client)
    data = {
        'cve_id': 'CVE-1970-1000',
        'comment': 'This is the new comment',
        'commits-0-commit_link':
        'https://github.com/OWNER/REPO/commit/12345678',
        'commits-0-repo_name': 'REPO',
        'commits-0-repo_url': 'https://github.com/OWNER/REPO',
        'commits-0-commit_hash': '12345678',
    }

    resp = client.post('/CVE-1970-1000/create', data=data)
    assert resp.status_code == expected_status
    if use_group == as_admin:
        assert resp.headers.get('Location', '<empty>').endswith(f'/1')

    vuln = Vulnerability.get_by_id(1)
    assert vuln.cve_id == data['cve_id']
    assert len(vuln.commits) == 1

    if use_group == as_admin:
        assert vuln.comment == data['comment']
        assert vuln.commits[0].commit_link == data['commits-0-commit_link']
        assert vuln.commits[0].repo_name == data['commits-0-repo_name']
        assert vuln.commits[0].repo_url == data['commits-0-repo_url']
        assert vuln.commits[0].commit_hash == data['commits-0-commit_hash']
    else:
        assert vuln.comment == 'Vulnerability 1 comment'
        assert vuln.commits[
            0].commit_link == 'https://github.com/OWNER/REPO1/commit/1234568'
        assert vuln.commits[0].repo_name == 'REPO1'
        assert vuln.commits[0].repo_url == 'https://github.com/OWNER/REPO1'
        assert vuln.commits[0].commit_hash == '1234568'
示例#15
0
def test_update_vulnerability(client, db_session, use_group, expected_status):
    if use_group:
        use_group(client)
    data = {
        "cve_id": "CVE-1970-1000",
        "comment": "This is the new comment",
        "commits-0-commit_link":
        "https://github.com/OWNER/REPO/commit/12345678",
        "commits-0-repo_name": "REPO",
        "commits-0-repo_url": "https://github.com/OWNER/REPO",
        "commits-0-commit_hash": "12345678",
    }

    resp = client.post("/CVE-1970-1000/create", data=data)
    assert resp.status_code == expected_status
    if use_group == as_admin:
        assert resp.headers.get("Location", "<empty>").endswith(f"/1")

    vuln = Vulnerability.get_by_id(1)
    assert vuln.cve_id == data["cve_id"]
    assert len(vuln.commits) == 1

    if use_group == as_admin:
        assert vuln.comment == data["comment"]
        assert vuln.commits[0].commit_link == data["commits-0-commit_link"]
        assert vuln.commits[0].repo_name == data["commits-0-repo_name"]
        assert vuln.commits[0].repo_url == data["commits-0-repo_url"]
        assert vuln.commits[0].commit_hash == data["commits-0-commit_hash"]
    else:
        assert vuln.comment == "Vulnerability 1 comment"
        assert (vuln.commits[0].commit_link ==
                "https://github.com/OWNER/REPO1/commit/1234568")
        assert vuln.commits[0].repo_name == "REPO1"
        assert vuln.commits[0].repo_url == "https://github.com/OWNER/REPO1"
        assert vuln.commits[0].commit_hash == "1234568"
示例#16
0
def test_delete_vulnerability_entry(client, use_group, expected_status,
                                    expected_deletion):
    if use_group:
        use_group(client)
    vuln = Vulnerability.get_by_cve_id('CVE-1970-1000')
    assert vuln is not None

    resp = client.post('/CVE-1970-1000/create',
                       data={
                           'delete_entry': vuln.id,
                       })
    assert resp.status_code == expected_status

    vuln = Vulnerability.get_by_cve_id('CVE-1970-1000')
    if expected_deletion:
        assert vuln is None
    else:
        assert vuln is not None
示例#17
0
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)
示例#18
0
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()
示例#19
0
def test_update_vulnerabilty(client, db_session):
    data = {
        'cve_id': 'CVE-1970-1000',
        'comment': 'This is the new comment',
        'commits-0-commit_link':
        'https://github.com/OWNER/REPO/commit/12345678',
        'commits-0-repo_name': 'REPO',
        'commits-0-repo_url': 'https://github.com/OWNER/REPO',
        'commits-0-commit_hash': '12345678',
    }

    resp = client.post('/CVE-1970-1000/create', data=data)
    assert resp.status_code == 401

    vuln = Vulnerability.get_by_id(1)
    assert vuln.comment == 'Vulnerability 1 comment'
    assert vuln.cve_id == data['cve_id']
    assert len(vuln.commits) == 1
    assert vuln.commits[
        0].commit_link == 'https://github.com/OWNER/REPO1/commit/1234568'
    assert vuln.commits[0].repo_name == 'REPO1'
    assert vuln.commits[0].repo_url == 'https://github.com/OWNER/REPO1'
    assert vuln.commits[0].commit_hash == '1234568'
示例#20
0
def test_update_vulnerabilty_as_admin(client, db_session):
    data = {
        'cve_id': 'CVE-1970-1000',
        'comment': 'This is the new comment',
        'commits-0-commit_link':
        'https://github.com/OWNER/REPO/commit/12345678',
        'commits-0-repo_name': 'REPO',
        'commits-0-repo_url': 'https://github.com/OWNER/REPO',
        'commits-0-commit_hash': '12345678',
    }

    as_admin(client)
    resp = client.post('/CVE-1970-1000/create', data=data)
    assert resp.status_code == 302
    assert resp.headers.get('Location', '<empty>').endswith(f'/1')

    vuln = Vulnerability.get_by_id(1)
    assert vuln.comment == data['comment']
    assert vuln.cve_id == data['cve_id']
    assert len(vuln.commits) == 1
    assert vuln.commits[0].commit_link == data['commits-0-commit_link']
    assert vuln.commits[0].repo_name == data['commits-0-repo_name']
    assert vuln.commits[0].repo_url == data['commits-0-repo_url']
    assert vuln.commits[0].commit_hash == data['commits-0-commit_hash']
示例#21
0
 def has_vcdb_entry(self):
     return Vulnerability.get_by_cve_id(self.cve_id)
示例#22
0
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()
示例#23
0
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
示例#24
0
def test_accept_change_after_review():
    vuln = Vulnerability(state=VulnerabilityState.IN_REVIEW)
    vuln.accept_change()

    assert vuln.state == VulnerabilityState.REVIEWED
    assert vuln.is_publishable()