Merge pull request #5 from Rafiot/master

Client API 2.0
This commit is contained in:
Alexandre Dulaunoy 2015-08-27 18:02:52 +02:00
commit 70874bc8a3
3 changed files with 71 additions and 11 deletions

30
client/bin/pypssl Executable file
View file

@ -0,0 +1,30 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import argparse
import pypssl
import json
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Query a Passive SSL instance.')
parser.add_argument("--url", default='https://www.circl.lu/', help='URL where the passive SSL is running (no path).')
parser.add_argument("-v", "--version", type=int, default=2, help='URL where the passive SSL is running (no path).')
parser.add_argument("-u", "--username", help='Username to login on the platform.')
parser.add_argument("-p", "--password", help='Password to login on the platform.')
parser.add_argument("-t", "--token", help='Token to login on the platform.')
parser.add_argument("-i", "--ip", help='IP to query (can be a block, max /23).')
parser.add_argument("-c", "--cert", help='SHA1 of the certificate to search.')
parser.add_argument("-f", "--fetch", help='SHA1 of the certificate to fetch.')
args = parser.parse_args()
p = pypssl.PyPSSL(args.url, args.version, (args.username, args.password), args.token)
if args.ip is not None:
print(json.dumps(p.query(args.ip)))
elif args.cert is not None:
print(json.dumps(p.query_cert(args.cert)))
elif args.fetch is not None:
print(json.dumps(p.fetch_cert(args.fetch, make_datetime=False)))
else:
print('You didn\'t query anything...')

View file

@ -3,13 +3,18 @@
import requests import requests
import socket import socket
try:
from urllib.parse import urljoin
except ImportError:
from urlparse import urljoin
import dateutil.parser
class PyPSSL(object): class PyPSSL(object):
def __init__(self, url='https://www.circl.lu/pssl/query', basic_auth=None, def __init__(self, base_url='https://www.circl.lu/', api_version=2, basic_auth=None, auth_token=None):
auth_token=None): self.base_url = base_url
self.url = url self.api_version = api_version
self.session = requests.Session() self.session = requests.Session()
if basic_auth is not None: if basic_auth is not None:
@ -21,6 +26,13 @@ class PyPSSL(object):
# No authentication defined. # No authentication defined.
pass pass
def _query(self, url):
response = self.session.get(url)
try:
return response.json()
except:
raise Exception('Unable to decode JSON object: ' + response.text)
def _check_IP(self, ip): def _check_IP(self, ip):
if ':' in ip: if ':' in ip:
return {'error': 'IPv6 is not (yet) supported'} return {'error': 'IPv6 is not (yet) supported'}
@ -39,9 +51,26 @@ class PyPSSL(object):
check = self._check_IP(q) check = self._check_IP(q)
if check is not None: if check is not None:
return check return check
response = self.session.get('{}/{}' .format(self.url, q)) if self.api_version == 1:
try: path = 'pssl/query/{}'.format(q)
return response.json() else:
except: path = 'v2pssl/query/{}'.format(q)
raise Exception('Unable to decode JSON object: ' + response.text) return self._query(urljoin(self.base_url, path))
return {}
def query_cert(self, q):
if self.api_version != 2:
return {'error': 'Only available in API v2'}
path = 'v2pssl/cquery/{}'.format(q)
return self._query(urljoin(self.base_url, path))
def fetch_cert(self, q, make_datetime=True):
if self.api_version != 2:
return {'error': 'Only available in API v2'}
path = 'v2pssl/cfetch/{}'.format(q)
response = self._query(urljoin(self.base_url, path))
if response.get('error') or not make_datetime:
return response
# create python datetime, doesn't return a json object
response['info']['not_before'] = dateutil.parser.parse(response['info']['not_before'])
response['info']['not_after'] = dateutil.parser.parse(response['info']['not_after'])
return response

View file

@ -4,7 +4,7 @@ from setuptools import setup
setup( setup(
name='pypssl', name='pypssl',
version='1.1', version='2.1',
author='Raphaël Vinot', author='Raphaël Vinot',
author_email='raphael.vinot@circl.lu', author_email='raphael.vinot@circl.lu',
maintainer='Raphaël Vinot', maintainer='Raphaël Vinot',
@ -12,6 +12,7 @@ setup(
description='Python API for PSSL.', description='Python API for PSSL.',
long_description=open('README.md').read(), long_description=open('README.md').read(),
packages=['pypssl'], packages=['pypssl'],
scripts=['bin/pypssl'],
classifiers=[ classifiers=[
'License :: OSI Approved :: GNU General Public License v3 (GPLv3)', 'License :: OSI Approved :: GNU General Public License v3 (GPLv3)',
'Development Status :: 5 - Production/Stable', 'Development Status :: 5 - Production/Stable',
@ -23,6 +24,6 @@ setup(
'Topic :: Security', 'Topic :: Security',
'Topic :: Internet', 'Topic :: Internet',
], ],
install_requires=['requests'], install_requires=['requests', 'python-dateutil'],
package_data={'': ['*.md', '*.rst', 'LICENSE']}, package_data={'': ['*.md', '*.rst', 'LICENSE']},
) )