cleanup http client a bit and add new functions

This commit is contained in:
Izalia Mae 2020-06-06 06:34:27 -04:00
parent a731490af4
commit 4c19e55f1a
3 changed files with 78 additions and 37 deletions

View file

@ -48,12 +48,6 @@ class httpClient:
if isinstance(data, dict): if isinstance(data, dict):
data = json.dumps(data) data = json.dumps(data)
elif not isinstance(data, bytes):
try:
data = bytes(data)
except:
raise TypeError('Post data cannot be turned into bytes')
resp = self.client.request(method, url, headers=headers, body=data) resp = self.client.request(method, url, headers=headers, body=data)
else: else:
@ -83,7 +77,7 @@ class httpClient:
''' '''
resp = self._fetch(*args, **kwargs) resp = self._fetch(*args, **kwargs)
return resp.data.decode() return resp.data.decode() if resp else None
def json(self, *args, **kwargs): def json(self, *args, **kwargs):
@ -109,6 +103,29 @@ class httpClient:
return data return data
def ParseSig(headers):
sig_header = headers.get('signature')
if not sig_header:
logging.verbose('Missing signature header')
return
split_sig = sig_header.split(',')
signature = {}
for part in split_sig:
key, value = part.split('=', 1)
signature[key.lower()] = value.replace('"', '')
if not signature.get('headers'):
logging.verbose('Missing headers section in signature')
return
signature['headers'] = signature['headers'].split()
return signature
def SignHeaders(headers, keyid, privkey, url, method='GET'): def SignHeaders(headers, keyid, privkey, url, method='GET'):
''' '''
Signs headers and returns them with a signature header Signs headers and returns them with a signature header
@ -140,7 +157,6 @@ def SignHeaders(headers, keyid, privkey, url, method='GET'):
return new_headers return new_headers
def ValidateSignature(headers, method, path, client=None, agent=None): def ValidateSignature(headers, method, path, client=None, agent=None):
''' '''
Validates the signature header. Validates the signature header.
@ -155,29 +171,7 @@ def ValidateSignature(headers, method, path, client=None, agent=None):
client = httpClient(agent=agent) if not client else client client = httpClient(agent=agent) if not client else client
headers = {k.lower(): v for k,v in headers.items()} headers = {k.lower(): v for k,v in headers.items()}
try: signature = ParseSig(headers)
sig_header = headers.get('signature')
except Exception as e:
logging.error(e)
return
if not sig_header:
logging.error('Missing signature header')
return
split_sig = sig_header.split(',')
signature = {}
for part in split_sig:
key, value = part.split('=', 1)
signature[key.lower()] = value.replace('"', '')
if not signature.get('headers'):
logging.verbose('Missing headers section in signature')
return
signature['headers'] = signature['headers'].split()
actor_data = client.json(signature['keyid']) actor_data = client.json(signature['keyid'])
logging.debug(actor_data) logging.debug(actor_data)
@ -194,11 +188,12 @@ def ValidateSignature(headers, method, path, client=None, agent=None):
if not valid: if not valid:
if not isinstance(valid, tuple): if not isinstance(valid, tuple):
logging.verbose('Signature validation failed for unknown actor') logging.verbose('Signature validation failed for unknown actor')
logging.verbose(valid)
else: else:
logging.verbose(f'Signature validation failed for actor: {valid[1]}') logging.verbose(f'Signature validation failed for actor: {valid[1]}')
return json_error(401, 'signature check failed') return
else: else:
return True return True

View file

@ -1,9 +1,10 @@
'''Miscellaneous functions''' '''Miscellaneous functions'''
import random, string, sys, os, shlex, subprocess import random, string, sys, os, shlex, subprocess, socket, traceback
from os.path import abspath, dirname, basename, isdir, isfile from os.path import abspath, dirname, basename, isdir, isfile
from os import environ as env from os import environ as env
from datetime import datetime from datetime import datetime
from collections import namedtuple
from . import logging from . import logging
@ -68,6 +69,31 @@ def config_dir(modpath=None):
return stor_path return stor_path
def getBin(filename):
for pathdir in env['PATH'].split(':'):
fullpath = os.path.join(pathdir, filename)
if os.path.isfile(fullpath):
return fullpath
raise FileNotFoundError(f'Cannot find {filename} in path.')
def Try(funct, *args, **kwargs):
Result = namedtuple('Result', 'result exception')
out = None
exc = None
try:
out = funct(*args, **kwargs)
except Exception as e:
traceback.print_exc()
exc = e
return Result(out, exc)
def sudo(cmd, password, user=None): def sudo(cmd, password, user=None):
### Please don't pur your password in plain text in a script ### Please don't pur your password in plain text in a script
### Use a module like 'getpass' to get the password instead ### Use a module like 'getpass' to get the password instead
@ -87,6 +113,24 @@ def sudo(cmd, password, user=None):
return proc return proc
def getip():
# Get the main IP address of the machine
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
s.connect(('10.255.255.255', 1))
data = s.getsockname()
ip = data[0]
except Exception:
ip = '127.0.0.1'
finally:
s.close()
return ip
def merp(): def merp():
log = logging.getLogger('merp-heck', {'level': 'merp', 'date': False}) log = logging.getLogger('merp-heck', {'level': 'merp', 'date': False})
log.merp('heck') log.merp('heck')

View file

@ -44,6 +44,9 @@ build_path_pairs = dict()
def addSearchPath(path): def addSearchPath(path):
tplPath = abspath(path) tplPath = abspath(path)
if not isdir(tplPath):
raise FileNotFoundError(f'Cannot find template directory: {tplPath}')
if tplPath not in search_path: if tplPath not in search_path:
search_path.append(tplPath) search_path.append(tplPath)
@ -60,7 +63,7 @@ def addBuildPath(name, source, destination):
dest = abspath(destination) dest = abspath(destination)
if not isdir(src): if not isdir(src):
raise FileNotFoundError('Source path doesn\'t exist: {src}') raise FileNotFoundError(f'Source path doesn\'t exist: {src}')
build_path_pairs.update({ build_path_pairs.update({
name: { name: {
@ -132,7 +135,7 @@ def renderTemplate(tplfile, context, request=None, headers=dict(), cookies=dict(
def sendResponse(template, request, context=dict(), status=200, ctype='text/html', headers=dict(), **kwargs): def sendResponse(template, request, context=dict(), status=200, ctype='text/html', headers=dict(), **kwargs):
context['request'] = request context['request'] = request
html = renderTemplate(template, context=context, **kwargs) html = renderTemplate(template, context, **kwargs)
if framework == 'sanic': if framework == 'sanic':
return sanic.response.text(html, status=status, headers=headers, content_type=ctype) return sanic.response.text(html, status=status, headers=headers, content_type=ctype)
@ -213,9 +216,8 @@ def templateWatcher():
for tplpath in watchPaths: for tplpath in watchPaths:
logging.debug(f'Watching template dir for changes: {tplpath}') logging.debug(f'Watching template dir for changes: {tplpath}')
observer.schedule(templateWatchHandler(), tplpath, recursive=False) observer.schedule(templateWatchHandler(), tplpath, recursive=True)
observer.start()
return observer return observer