summaryrefslogtreecommitdiff
path: root/src/merchant-tools/mitm
diff options
context:
space:
mode:
Diffstat (limited to 'src/merchant-tools/mitm')
-rw-r--r--src/merchant-tools/mitm/Makefile.in21
-rw-r--r--src/merchant-tools/mitm/README25
-rw-r--r--src/merchant-tools/mitm/merchant-mitm.wsgi.in21
-rw-r--r--src/merchant-tools/mitm/setup.py11
-rw-r--r--src/merchant-tools/mitm/taler-merchant-mitm.in45
-rw-r--r--src/merchant-tools/mitm/talermerchantmitm/__init__.py0
-rw-r--r--src/merchant-tools/mitm/talermerchantmitm/mitm.py78
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