chg: Initial commit

This commit is contained in:
Raphaël Vinot 2023-05-19 15:21:11 +02:00
commit 3943daf914
26 changed files with 1978 additions and 0 deletions

17
.github/dependabot.yml vendored Normal file
View file

@ -0,0 +1,17 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "pip"
directory: "/"
schedule:
interval: "daily"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
# Check for updates to GitHub Actions every weekday
interval: "daily"

33
.github/workflows/mypy.yml vendored Normal file
View file

@ -0,0 +1,33 @@
name: Python application - MyPy
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.8', '3.9', '3.10', '3.11']
name: Python ${{ matrix.python-version }} sample
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: ${{matrix.python-version}}
- name: Install poetry
run: |
python -m pip install --upgrade pip poetry
poetry install
- name: Test with MyPy
run: |
poetry run mypy .

131
.gitignore vendored Normal file
View file

@ -0,0 +1,131 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
.python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
*.swp

14
.readthedocs.yml Normal file
View file

@ -0,0 +1,14 @@
version: 2
python:
version: 3.8
install:
- method: pip
path: .
extra_requirements:
- docs
build:
image: latest
formats: all

29
LICENSE Normal file
View file

@ -0,0 +1,29 @@
BSD 3-Clause License
Copyright (c) 2020, Lookyloo
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

20
README.md Normal file
View file

@ -0,0 +1,20 @@
# Python client and module for Vulnerability Lookup
## Installation
```bash
pip install pyvulnerabilitylookup
```
## Usage
### Command line
You can use the `vulnerability_lookup` command:
```bash
```
### Library
See [API Reference]()

20
docs/Makefile Normal file
View file

@ -0,0 +1,20 @@
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = source
BUILDDIR = build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

0
docs/__init__.py Normal file
View file

35
docs/make.bat Normal file
View file

@ -0,0 +1,35 @@
@ECHO OFF
pushd %~dp0
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=source
set BUILDDIR=build
if "%1" == "" goto help
%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
goto end
:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
:end
popd

0
docs/source/__init__.py Normal file
View file

View file

@ -0,0 +1,14 @@
API reference
=============
.. toctree::
:maxdepth: 2
.. automodule:: pyvulnerabilitylookup
:members:
PyVulnerabilityLookup
---------
.. autoclass:: PyVulnerabilityLookup
:members:

61
docs/source/conf.py Normal file
View file

@ -0,0 +1,61 @@
# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
# -- Path setup --------------------------------------------------------------
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
# import os
# import sys
# sys.path.insert(0, os.path.abspath('.'))
# -- Project information -----------------------------------------------------
project = 'PyVulnerabilityLookup'
copyright = '2023, CVE Search team'
author = 'CVE Search team'
# The full version, including alpha/beta/rc tags
release = 'v0.0.1'
# -- General configuration ---------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.autodoc'
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = []
# -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'alabaster'
html_theme_options = {
'page_width': '1200',
'body_min_width': '1200',
}
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']

37
docs/source/index.rst Normal file
View file

@ -0,0 +1,37 @@
Welcome to PyVulnerabilityLookup's documentation!
=============================================
This is the client API for `PyVulnerabilityLookup <https://github.com/cve-search/PyVulnerabilityLookup>`_:
foo
Installation
------------
The package is available on PyPi, so you can install it with::
pip install pyvulnerabilitylookup
Usage
-----
You can use `client` as a python script::
$ vulnerability_lookup -h
Or as a library:
.. toctree::
:glob:
api_reference
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

4
mypy.ini Normal file
View file

@ -0,0 +1,4 @@
[mypy]
[mypy-docs.source.*]
ignore_errors = True

1182
poetry.lock generated Normal file

File diff suppressed because it is too large Load diff

47
pyproject.toml Normal file
View file

@ -0,0 +1,47 @@
[tool.poetry]
name = "pyvulnerabilitylookup"
version = "0.0.1"
description = "Python CLI and module for Vulnerability Lookup"
authors = ["Raphaël Vinot <raphael.vinot@circl.lu>"]
license = "BSD-3-Clause"
readme = "README.md"
classifiers = [
'License :: OSI Approved :: BSD License',
'Development Status :: 5 - Production/Stable',
'Environment :: Console',
'Operating System :: POSIX :: Linux',
'Intended Audience :: Science/Research',
'Intended Audience :: Telecommunications Industry',
'Intended Audience :: Information Technology',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
'Topic :: Security',
'Topic :: Internet',
]
include = ['README.md']
[tool.poetry.scripts]
vulnerability_lookup = 'pyvulnerabilitylookup:main'
[tool.poetry.dependencies]
python = "^3.10"
requests = "^2.30.0"
Sphinx = { version = "^7.0.1", optional = true }
[tool.poetry.extras]
docs = ["Sphinx"]
[tool.poetry.group.dev.dependencies]
pylint = "^2.17.4"
mypy = "^1.3.0"
types-requests = "^2.30.0.0"
ipython = "^8.13.2"
pytest = "^7.3.1"
[build-system]
requires = ["poetry_core"]
build-backend = "poetry.core.masonry.api"

View file

@ -0,0 +1,25 @@
import argparse
import json
import sys
from .api import PyVulnerabilityLookup
def main():
parser = argparse.ArgumentParser(description='Query a thing.')
parser.add_argument('--url', type=str, required=True, help='URL of the instance.')
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument('--redis_up', action='store_true', help='Check if redis is up.')
group.add_argument('--vulnerability', type=str, help='Get a vulnerability.')
args = parser.parse_args()
client = PyVulnerabilityLookup(args.url)
if not client.is_up:
print(f'Unable to reach {client.root_url}. Is the server up?')
sys.exit(1)
if args.redis_up:
response = client.redis_up()
elif args.vulnerability:
response = client.get_vulnerability(args.vulnerability)
print(json.dumps(response, indent=2))

View file

@ -0,0 +1,44 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from importlib.metadata import version
from pathlib import Path
from typing import Dict, Optional, Any
from urllib.parse import urljoin, urlparse
import requests
class PyVulnerabilityLookup():
def __init__(self, root_url: str, useragent: Optional[str]=None):
'''Query a specific instance.
:param root_url: URL of the instance to query.
'''
self.root_url = root_url
if not urlparse(self.root_url).scheme:
self.root_url = 'http://' + self.root_url
if not self.root_url.endswith('/'):
self.root_url += '/'
self.session = requests.session()
self.session.headers['user-agent'] = useragent if useragent else f'PyProject / {version("pyvulnerabilitylookup")}'
@property
def is_up(self) -> bool:
'''Test if the given instance is accessible'''
try:
r = self.session.head(self.root_url)
except requests.exceptions.ConnectionError:
return False
return r.status_code == 200
def redis_up(self) -> Dict:
'''Check if redis is up and running'''
r = self.session.get(urljoin(self.root_url, 'redis_up'))
return r.json()
def get_vulnerability(self, vulnerability_id: str) -> Dict[str, Any]:
r = self.session.get(urljoin(self.root_url, str(Path('vulnerability', vulnerability_id))))
return r.json()

View file

131
tests/.gitignore vendored Normal file
View file

@ -0,0 +1,131 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
.python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
*.swp

14
tests/.readthedocs.yml Normal file
View file

@ -0,0 +1,14 @@
version: 2
python:
version: 3.8
install:
- method: pip
path: .
extra_requirements:
- docs
build:
image: latest
formats: all

29
tests/LICENSE Normal file
View file

@ -0,0 +1,29 @@
BSD 3-Clause License
Copyright (c) 2020, Lookyloo
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

20
tests/README.md Normal file
View file

@ -0,0 +1,20 @@
# Python client and module for Vulnerability Lookup
## Installation
```bash
pip install pyvulnerabilitylookup
```
## Usage
### Command line
You can use the `vulnerability_lookup` command:
```bash
```
### Library
See [API Reference]()

4
tests/mypy.ini Normal file
View file

@ -0,0 +1,4 @@
[mypy]
[mypy-docs.source.*]
ignore_errors = True

47
tests/pyproject.toml Normal file
View file

@ -0,0 +1,47 @@
[tool.poetry]
name = "pyvulnerabilitylookup"
version = "0.0.1"
description = "Python CLI and module for Vulnerability Lookup"
authors = ["Raphaël Vinot <raphael.vinot@circl.lu>"]
license = "BSD-3-Clause"
readme = "README.md"
classifiers = [
'License :: OSI Approved :: BSD License',
'Development Status :: 5 - Production/Stable',
'Environment :: Console',
'Operating System :: POSIX :: Linux',
'Intended Audience :: Science/Research',
'Intended Audience :: Telecommunications Industry',
'Intended Audience :: Information Technology',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
'Topic :: Security',
'Topic :: Internet',
]
include = ['README.md']
[tool.poetry.scripts]
vulnerability_lookup = 'pyvulnerabilitylookup:main'
[tool.poetry.dependencies]
python = "^3.10"
requests = "^2.30.0"
Sphinx = { version = "^7.0.1", optional = true }
[tool.poetry.extras]
docs = ["Sphinx"]
[tool.poetry.group.dev.dependencies]
pylint = "^2.17.4"
mypy = "^1.3.0"
types-requests = "^2.30.0.0"
ipython = "^8.13.2"
pytest = "^7.3.1"
[build-system]
requires = ["poetry_core"]
build-backend = "poetry.core.masonry.api"

20
tests/test_web.py Normal file
View file

@ -0,0 +1,20 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import unittest
from pyvulnerabilitylookup import PyVulnerabilityLookup
class TestBasic(unittest.TestCase):
def setUp(self):
self.client = PyVulnerabilityLookup(root_url="http://127.0.0.1:10001")
def test_up(self):
self.assertTrue(self.client.is_up)
self.assertTrue(self.client.redis_up())
def test_get_vulnerability(self):
vuln = self.client.get_vulnerability('CVE-2023-23059')
self.assertEqual(vuln['cve']['id'], 'CVE-2023-23059')