diff options
Diffstat (limited to 'src/merchant-tools/mitm')
-rw-r--r-- | src/merchant-tools/mitm/Makefile.in | 21 | ||||
-rw-r--r-- | src/merchant-tools/mitm/README | 25 | ||||
-rw-r--r-- | src/merchant-tools/mitm/merchant-mitm.wsgi.in | 21 | ||||
-rw-r--r-- | src/merchant-tools/mitm/setup.py | 11 | ||||
-rw-r--r-- | src/merchant-tools/mitm/taler-merchant-mitm.in | 45 | ||||
-rw-r--r-- | src/merchant-tools/mitm/talermerchantmitm/__init__.py | 0 | ||||
-rw-r--r-- | src/merchant-tools/mitm/talermerchantmitm/mitm.py | 78 |
7 files changed, 201 insertions, 0 deletions
diff --git a/src/merchant-tools/mitm/Makefile.in b/src/merchant-tools/mitm/Makefile.in new file mode 100644 index 00000000..4a9f33a2 --- /dev/null +++ b/src/merchant-tools/mitm/Makefile.in @@ -0,0 +1,21 @@ + +.PHONY: all +all: + true + +.PHONY: install-data +install-data: + install -m 444 -Dt @prefix@/share/taler/ merchant-mitm.wsgi + +.PHONY: install +install: install-data + pip3 install . --install-option="--prefix=@prefix@" --upgrade --no-deps + install -m 544 -Dt @prefix@/bin taler-merchant-mitm + +# need a way to make 'make check' happy in this subdir. +# This component is still too young to be tested. +.PHONY: check +check: + true +clean: + true diff --git a/src/merchant-tools/mitm/README b/src/merchant-tools/mitm/README new file mode 100644 index 00000000..662cbe39 --- /dev/null +++ b/src/merchant-tools/mitm/README @@ -0,0 +1,25 @@ + +=== INTRODUCTION === + +This directory contain a Web server that listens for +requests addressed to the exchange, relays them to the +exchange, and returns a modified response to the caller. + +The modifications are made to test error management in the +merchant, and are driven by a HTTP header that instructs the +proxy about the modifications to be made. + +=== INVOCATION === + +After a successful 'make install', a command called 'taler-merchant-mitm' +is placed under <prefix>/bin - make sure PATH points at it. + +To run the mitm, give the following commands: + +$ taler-merchant-mitm --exchange URL [--port PORT] + +The '--exchange' option is mandatory, telling the mitm where to +forward the requests addressed to the exchange. + +The second option just sets the port number where the mitm +listens, defaulting to 5000. diff --git a/src/merchant-tools/mitm/merchant-mitm.wsgi.in b/src/merchant-tools/mitm/merchant-mitm.wsgi.in new file mode 100644 index 00000000..3fb4cfbf --- /dev/null +++ b/src/merchant-tools/mitm/merchant-mitm.wsgi.in @@ -0,0 +1,21 @@ + +import sys + +if sys.version_info.major < 3: + print("The merchant mitm needs to run with Python>=3.4") + sys.exit(1) + +import os +import site +import logging + +logging.basicConfig(level=logging.INFO) + +site.addsitedir("%s/lib/python%d.%d/site-packages" % ( + "@prefix@", + sys.version_info.major, + sys.version_info.minor)) + +import talermerchantmitm.mitm + +application = talermerchantmitm.mitm.app diff --git a/src/merchant-tools/mitm/setup.py b/src/merchant-tools/mitm/setup.py new file mode 100644 index 00000000..f5eedeaa --- /dev/null +++ b/src/merchant-tools/mitm/setup.py @@ -0,0 +1,11 @@ +from setuptools import setup, find_packages +setup(name='talermerchantmitm', + version='0.0', + description='Layer generating errors for testing', + url='git://taler.net/merchant', + author='Marcello Stanisci', + author_email='marcello.stanisci@inria.fr', + license='GPL', + packages=find_packages(), + install_requires=["Flask>=0.10"], + zip_safe=False) diff --git a/src/merchant-tools/mitm/taler-merchant-mitm.in b/src/merchant-tools/mitm/taler-merchant-mitm.in new file mode 100644 index 00000000..39a7275e --- /dev/null +++ b/src/merchant-tools/mitm/taler-merchant-mitm.in @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 + +""" +Stand-alone script to manage the merchant's MITM +error generator. +""" + +import argparse +import sys +import os + +parser = argparse.ArgumentParser() + +parser.add_argument('--exchange', + '-e', + help="Exchange URL", + metavar="URL", + type=str, + dest="exchange_url", + default=None) + + +parser.add_argument("--port", + "-p", + help="Port where the MITM listens", + dest="port", + type=int, + default=5000, + metavar="PORT") + +args = parser.parse_args() + +if getattr(args, 'exchange_url', None) is None: + parser.print_help() + sys.exit(1) + +uwsgi_logfmt = "%(ltime) %(proto) %(method) %(uri) %(proto) => %(status)" + +os.environ["TALER_EXCHANGE_URL"] = args.exchange_url +os.execlp("uwsgi", "uwsgi", + "--master", + "--die-on-term", + "--log-format", uwsgi_logfmt, + "--http", ":%d" % args.port, + "--wsgi-file", "@prefix@/share/taler/merchant-mitm.wsgi") diff --git a/src/merchant-tools/mitm/talermerchantmitm/__init__.py b/src/merchant-tools/mitm/talermerchantmitm/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/src/merchant-tools/mitm/talermerchantmitm/__init__.py diff --git a/src/merchant-tools/mitm/talermerchantmitm/mitm.py b/src/merchant-tools/mitm/talermerchantmitm/mitm.py new file mode 100644 index 00000000..c998a1c5 --- /dev/null +++ b/src/merchant-tools/mitm/talermerchantmitm/mitm.py @@ -0,0 +1,78 @@ +#This file is part of TALER +#Copyright (C) 2014, 2015, 2016, 2017 GNUnet e.V. and INRIA +# +#TALER is free software; you can redistribute it and/or modify it under the +#terms of the GNU Lesser General Public License as published by the Free Software +#Foundation; either version 2.1, or (at your option) any later version. +# +#TALER is distributed in the hope that it will be useful, but WITHOUT ANY +#WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +#A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. +# +#You should have received a copy of the GNU Lesser General Public License along with +#TALER; see the file COPYING.LGPL. If not, see <http://www.gnu.org/licenses/> + +# @author Marcello Stanisci +# @brief Error generator for responses coming from the exchange + +from flask import (request, + Flask, + make_response) +import requests +from urllib.parse import (urljoin, + urlencode, + urlparse, + urlunparse) +from pytaler import amount +import base64 +import os +import logging +import json +from random import randint +from datetime import datetime + +app = Flask(__name__) +app.secret_key = base64.b64encode(os.urandom(64)).decode('utf-8') +logger = logging.getLogger(__name__) +exchange_url = os.environ.get("TALER_EXCHANGE_URL") +assert(None != exchange_url) + +def track_transaction(resp): + return resp.text + +def track_transfer(resp): + return resp.text + +def keys(resp): + try: + keys = resp.json() + # Put here data perturbation logic + return json.dumps(keys) + except Exception: + return resp.text + +@app.route('/', defaults={'path': ''}) +@app.route('/<path:path>', methods=["GET", "POST"]) +def all(path): + body = request.get_json() + url = list(urlparse(request.url)) + xurl = urlparse(exchange_url) + url[0] = xurl[0] + url[1] = xurl[1] + url = urlunparse(url) + if "POST" == request.method: + r = requests.post(urljoin(url, path), json=body) + else: + r = requests.get(urljoin(url, path), json=body) + dispatcher = { + "track_transaction": track_transaction, + "track_transfer": track_transfer, + "keys": keys + } + func = dispatcher.get(request.headers.get("X-Taler-Mitm"), + lambda x: x.text) + response = make_response(func(r)) + for key, value in r.headers.items(): + if key not in ("Server", "Content-Length"): + response.headers[key] = value + return response, r.status_code |