Added json validation of formats to check IPv4

refactored files and calls to be api_server
worked down satisfying review comments of last commit
This commit is contained in:
creslinux 2018-06-14 20:19:15 +00:00
parent b101a2608a
commit 9aa08ec3c1
3 changed files with 33 additions and 23 deletions

View File

@ -6,7 +6,7 @@ import json
import logging import logging
from argparse import Namespace from argparse import Namespace
from typing import Optional, Dict, Any from typing import Optional, Dict, Any
from jsonschema import Draft4Validator, validate from jsonschema import Draft4Validator, validate, draft4_format_checker
from jsonschema.exceptions import ValidationError, best_match from jsonschema.exceptions import ValidationError, best_match
import ccxt import ccxt
@ -202,7 +202,7 @@ class Configuration(object):
:return: Returns the config if valid, otherwise throw an exception :return: Returns the config if valid, otherwise throw an exception
""" """
try: try:
validate(conf, constants.CONF_SCHEMA) validate(conf, constants.CONF_SCHEMA, format_checker=draft4_format_checker)
return conf return conf
except ValidationError as exception: except ValidationError as exception:
logger.critical( logger.critical(
@ -210,7 +210,9 @@ class Configuration(object):
exception exception
) )
raise ValidationError( raise ValidationError(
best_match(Draft4Validator(constants.CONF_SCHEMA).iter_errors(conf)).message best_match(Draft4Validator(constants.CONF_SCHEMA,
format_checker=draft4_format_checker)
.iter_errors(conf)).message
) )
def get_config(self) -> Dict[str, Any]: def get_config(self) -> Dict[str, Any]:

View File

@ -92,6 +92,19 @@ CONF_SCHEMA = {
}, },
'required': ['enabled', 'token', 'chat_id'] 'required': ['enabled', 'token', 'chat_id']
}, },
'api_server': {
'type': 'object',
'properties': {
'enabled': {'type': 'boolean'},
'listen_ip_address': { "format": "ipv4"},
'listen_port': {
'type': 'integer',
"minimum": 1024,
"maximum": 65535
},
},
'required': ['enabled', 'listen_ip_address', 'listen_port']
},
'db_url': {'type': 'string'}, 'db_url': {'type': 'string'},
'initial_state': {'type': 'string', 'enum': ['running', 'stopped']}, 'initial_state': {'type': 'string', 'enum': ['running', 'stopped']},
'internals': { 'internals': {

View File

@ -6,26 +6,25 @@ from flask import Flask, request
from flask_restful import Resource, Api from flask_restful import Resource, Api
from json import dumps from json import dumps
from freqtrade.rpc.rpc import RPC, RPCException from freqtrade.rpc.rpc import RPC, RPCException
from ipaddress import IPv4Address
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
app = Flask(__name__)
class LocalRestSuperWrap(RPC): class ApiServerSuperWrap(RPC):
""" """
This class is for REST cmd line client This class is for REST calls across api server
""" """
def __init__(self, freqtrade) -> None: def __init__(self, freqtrade) -> None:
""" """
Init the LocalRestServer call, and init the super class RPC Init the api server, and init the super class RPC
:param freqtrade: Instance of a freqtrade bot :param freqtrade: Instance of a freqtrade bot
:return: None :return: None
""" """
super().__init__(freqtrade) super().__init__(freqtrade)
""" Constructor
:type interval: int self.interval = 1
:param interval: Check interval, in seconds
"""
self.interval = int(1)
thread = threading.Thread(target=self.run, args=(freqtrade,)) # extra comma as ref ! Tuple thread = threading.Thread(target=self.run, args=(freqtrade,)) # extra comma as ref ! Tuple
thread.daemon = True # Daemonize thread thread.daemon = True # Daemonize thread
@ -35,7 +34,6 @@ class LocalRestSuperWrap(RPC):
def run(self, freqtrade): def run(self, freqtrade):
""" Method that runs forever """ """ Method that runs forever """
self._config = freqtrade.config self._config = freqtrade.config
app = Flask(__name__)
""" """
Define the application routes here Define the application routes here
@ -97,17 +95,14 @@ class LocalRestSuperWrap(RPC):
Section to handle configuration and running of the Rest serve Section to handle configuration and running of the Rest serve
also to check and warn if not bound to 127.0.0.1 as a security risk. also to check and warn if not bound to 127.0.0.1 as a security risk.
""" """
rest_ip = self._config['api_server']['listen_ip_address']
rest_port = self._config['api_server']['listen_port']
rest_ip = self._config['rest_cmd_line']['listen_ip_address'] if not IPv4Address(rest_ip).is_loopback :
rest_port = self._config['rest_cmd_line']['listen_port'] logger.info("SECURITY WARNING - Local Rest Server listening to external connections")
logger.info("SECURITY WARNING - This is insecure please set to your loopback, e.g 127.0.0.1 in config.json")
if rest_ip != "127.0.0.1":
i=0
while i < 10:
logger.info("SECURITY WARNING - Local Rest Server listening to external connections")
logger.info("SECURITY WARNING - This is insecure please set to 127.0.0.1 in config.json")
i += 1
# Run the Server # Run the Server
logger.info('Starting Local Rest Server') logger.info('Starting Local Rest Server')
app.run(host=rest_ip, port=rest_port) app.run(host=rest_ip, port=rest_port)