From a339fe2df2118984daa8152c734ed2dc5e8815ec Mon Sep 17 00:00:00 2001 From: jmbott Date: Fri, 15 Nov 2019 17:09:53 -0500 Subject: [PATCH 1/4] erase cards --- minigrid/device_interface.py | 39 +++++++++++++++++++++++++++++++++++ minigrid/handlers.py | 17 ++++++++++----- minigrid/templates/cards.html | 15 +++++++++++++- 3 files changed, 65 insertions(+), 6 deletions(-) diff --git a/minigrid/device_interface.py b/minigrid/device_interface.py index d938fa8..bed173e 100644 --- a/minigrid/device_interface.py +++ b/minigrid/device_interface.py @@ -20,6 +20,45 @@ def _wrap_binary(binary): """Add a signifier to the beginning and end of a binary block.""" return b'qS' + binary.hex().encode('ascii') + b'EL' +def erase_card(session, cache): + """Erase card.""" + sector_1 = b''.join(( + bytes(45), + )) + sector_2 = b''.join(( + bytes(32), + )) + naive_payload = sector_1 + sector_2 + actual_payload = b''.join(( + naive_payload[:15], + (sum(naive_payload[:15]) & 0xFF).to_bytes(1, 'big'), + naive_payload[15:30], + (sum(naive_payload[15:30]) & 0xFF).to_bytes(1, 'big'), + naive_payload[30:45], + (sum(naive_payload[30:45]) & 0xFF).to_bytes(1, 'big'), + naive_payload[45:60], + (sum(naive_payload[45:60]) & 0xFF).to_bytes(1, 'big'), + naive_payload[60:75], + (sum(naive_payload[60:75]) & 0xFF).to_bytes(1, 'big'), + naive_payload[75:77], + bytes(13), + (sum(naive_payload[75:77]) & 0xFF).to_bytes(1, 'big'), + )) + cache.set('device_info', _wrap_binary(actual_payload), 30) + # write_result = OrderedDict() + # write_result['card_type'] = 'Vendor ID Card' + # write_result['user_id'] = str(vendor_id) + # write_result['creation_time'] = \ + # datetime.fromtimestamp(card_produce_time).isoformat() + # write_result['minigrid_id'] = str(minigrid_id) + # write_result['vendor_id'] = vendor.vendor_id + # cache.set('write_info', json_encode(write_result), 30) + notify = OrderedDict() + notify['notification'] = 'Erasing Card...' + notify['type'] = 'alert-warning' + cache.set('notification', json_encode(notify), 30) + cache.delete('received_info') + def write_vendor_card(session, cache, key, minigrid_id, payment_id, vendor): """Write information to a vendor ID card.""" diff --git a/minigrid/handlers.py b/minigrid/handlers.py index 15f4db1..e3e5e19 100644 --- a/minigrid/handlers.py +++ b/minigrid/handlers.py @@ -26,7 +26,7 @@ import tornado.ioloop from minigrid.device_interface import ( - write_maintenance_card_card, + write_maintenance_card_card, erase_card, write_vendor_card, write_customer_card, write_credit_card) import minigrid.error import minigrid.models as models @@ -321,6 +321,12 @@ def get(self): http_protocol = 'https' if options.minigrid_https else 'http' self.render('cards.html', http_protocol=http_protocol) + @tornado.web.authenticated + def post(self): + """Erase card.""" + erase_card(self.session, cache) + self.redirect(f'/cards') + class MinigridHandler(BaseHandler): """Handlers for a minigrid view.""" @@ -807,6 +813,9 @@ def _pack_into_dict(session, binary): if system_id == 'up': logging.info(f'Operator Box is {system_id}') return json_encode(result) + else: + cache.set('device_active', 1, 10) + cache.set('received_info', json_encode(result), 10) card_type = sector_1[4:5].decode('ascii') logging.info(f'Card Type: {card_type}') try: @@ -1140,8 +1149,7 @@ class ImageHandler(BaseHandler): def genImage(self, minigrid_id): """Return the plot png.""" - x = [] - y = [] + x = []; y = [] with models.transaction(self.session) as session: minigrid = models.get_minigrid(session, minigrid_id) for credit_card_history \ @@ -1151,8 +1159,7 @@ def genImage(self, minigrid_id): # fig = plt.figure() memdata = io.BytesIO() if x: - min = x[0] - max = x[-1] + min = x[0]; max = x[-1] # plt.plot(x, y) # plt.bar(x, y, align='center', alpha=0.5) plt.scatter(x, y, alpha=0.5) diff --git a/minigrid/templates/cards.html b/minigrid/templates/cards.html index a9fb7d7..16a5205 100644 --- a/minigrid/templates/cards.html +++ b/minigrid/templates/cards.html @@ -1,6 +1,8 @@ {% extends 'base.html' %} {% block body %} +
+
{% if message is not None %} @@ -12,6 +14,17 @@

Read and validate cards:

Card Info
+
+
+ {% module xsrf_form_html() %} + + {% if device_active %} + + {% else %} + + {% end %} +
+
@@ -19,6 +32,6 @@

Read and validate cards:

- + {% end %} From 1629c4f4ccc3736e5fceb1f43678c0cb54b73e4b Mon Sep 17 00:00:00 2001 From: jmbott Date: Wed, 20 Nov 2019 15:39:08 -0500 Subject: [PATCH 2/4] blank cards confirm --- minigrid/device_interface.py | 12 ++++-------- minigrid/handlers.py | 16 ++++++++++++++++ minigrid/templates/cards.html | 6 ++++++ 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/minigrid/device_interface.py b/minigrid/device_interface.py index bed173e..436e6e2 100644 --- a/minigrid/device_interface.py +++ b/minigrid/device_interface.py @@ -45,14 +45,10 @@ def erase_card(session, cache): (sum(naive_payload[75:77]) & 0xFF).to_bytes(1, 'big'), )) cache.set('device_info', _wrap_binary(actual_payload), 30) - # write_result = OrderedDict() - # write_result['card_type'] = 'Vendor ID Card' - # write_result['user_id'] = str(vendor_id) - # write_result['creation_time'] = \ - # datetime.fromtimestamp(card_produce_time).isoformat() - # write_result['minigrid_id'] = str(minigrid_id) - # write_result['vendor_id'] = vendor.vendor_id - # cache.set('write_info', json_encode(write_result), 30) + write_result = OrderedDict() + write_result['card_type'] = 'Blank Card' + write_result['future_time'] = str(int(time.time())+30) + cache.set('write_info', json_encode(write_result), 30) notify = OrderedDict() notify['notification'] = 'Erasing Card...' notify['type'] = 'alert-warning' diff --git a/minigrid/handlers.py b/minigrid/handlers.py index e3e5e19..cac98f7 100644 --- a/minigrid/handlers.py +++ b/minigrid/handlers.py @@ -1,4 +1,5 @@ """Handlers for the URL endpoints.""" +import time from binascii import unhexlify from collections import OrderedDict from datetime import datetime, timedelta @@ -52,6 +53,7 @@ 'B': 'Customer ID Card', 'C': 'Credit Card', 'D': 'Maintenance Card', + 'E': 'Blank Card', } @@ -60,6 +62,7 @@ 'B': 'Customer User ID', 'C': 'Credit Amount', 'D': 'Maintenance Card ID', + 'E': 'Card Type', } @@ -822,6 +825,10 @@ def _pack_into_dict(session, binary): result['Card Type'] = _card_type_dict[card_type] except KeyError: if card_type == '\x00': + found = OrderedDict() + found['Card Type'] = 'Blank Card' + found['Connected Device'] = device_address.hex() + cache.set('received_info', json_encode(found), 10) raise minigrid.error.CardReadError('This card appears blank') raise minigrid.error.CardReadError( f'This card appears to have the invalid card type {card_type}') @@ -1042,6 +1049,15 @@ def _verify_written_card(session): mc_maintenance_card_card_id=mcid, )) cache.delete('write_info') + elif type == 'E': # Blank card + future = write_result['future_time'] + logging.info(f'future: {future}') + if int(future) > int(time.time()): + notify['notification'] = 'Card Blank' + notify['type'] = 'alert-success' + cache.set('notification', json_encode(notify), 10) + logging.info('Card Erased') + cache.delete('write_info') else: # Error case for card type notify['notification'] = 'Invalid Card Type' diff --git a/minigrid/templates/cards.html b/minigrid/templates/cards.html index 16a5205..0510ecd 100644 --- a/minigrid/templates/cards.html +++ b/minigrid/templates/cards.html @@ -9,6 +9,12 @@

{{ message }}

{% end %}

Read and validate cards:

+
+
+ Device Info +
+
+
Card Info From 3a7c35ff78e8f54dd76f4ef8b2a496e1aaa94bd9 Mon Sep 17 00:00:00 2001 From: jmbott Date: Wed, 20 Nov 2019 17:58:25 -0500 Subject: [PATCH 3/4] flake backup cronjob --- minigrid/device_interface.py | 1 + minigrid/handlers.py | 8 +++++--- prod/install.sh | 12 +++++++++--- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/minigrid/device_interface.py b/minigrid/device_interface.py index 436e6e2..7c46c6e 100644 --- a/minigrid/device_interface.py +++ b/minigrid/device_interface.py @@ -20,6 +20,7 @@ def _wrap_binary(binary): """Add a signifier to the beginning and end of a binary block.""" return b'qS' + binary.hex().encode('ascii') + b'EL' + def erase_card(session, cache): """Erase card.""" sector_1 = b''.join(( diff --git a/minigrid/handlers.py b/minigrid/handlers.py index cac98f7..34d6a7f 100644 --- a/minigrid/handlers.py +++ b/minigrid/handlers.py @@ -1049,7 +1049,7 @@ def _verify_written_card(session): mc_maintenance_card_card_id=mcid, )) cache.delete('write_info') - elif type == 'E': # Blank card + elif type == 'E': # Blank card future = write_result['future_time'] logging.info(f'future: {future}') if int(future) > int(time.time()): @@ -1165,7 +1165,8 @@ class ImageHandler(BaseHandler): def genImage(self, minigrid_id): """Return the plot png.""" - x = []; y = [] + x = [] + y = [] with models.transaction(self.session) as session: minigrid = models.get_minigrid(session, minigrid_id) for credit_card_history \ @@ -1175,7 +1176,8 @@ def genImage(self, minigrid_id): # fig = plt.figure() memdata = io.BytesIO() if x: - min = x[0]; max = x[-1] + min = x[0] + max = x[-1] # plt.plot(x, y) # plt.bar(x, y, align='center', alpha=0.5) plt.scatter(x, y, alpha=0.5) diff --git a/prod/install.sh b/prod/install.sh index 85e8281..fd39c0d 100755 --- a/prod/install.sh +++ b/prod/install.sh @@ -147,7 +147,7 @@ printf "========================================\n" # The --post-hook should just be docker restart $NGINX_CONTAINER_NAME... but # the container can't run the docker command properly. # So /tmp/renewed serves as a sentinel -CRON_CMD="mkdir -p /tmp/letsencrypt && "\ +CRON_CMD_1="mkdir -p /tmp/letsencrypt && "\ "docker run -i --rm --name certbot"\ " -v /etc/letsencrypt:/etc/letsencrypt:Z"\ " -v /var/lib/letsencrypt:/var/lib/letsencrypt:Z"\ @@ -155,7 +155,13 @@ CRON_CMD="mkdir -p /tmp/letsencrypt && "\ " -v /var/log/letsencrypt:/var/log/letsencrypt:Z"\ " quay.io/letsencrypt/letsencrypt renew --quiet --webroot --webroot-path /tmp/letsencrypt;"\ " docker restart $NGINX_CONTAINER_NAME" +# Backup database every week at 2:15 +DB_CONTAINER_NAME=$($DOCKER_COMPOSE ps | grep _db_ | cut -d' ' -f1) +CRON_CMD_2="mkdir -p /db-bak && "\ +"docker exec $DB_CONTAINER_NAME pg_dump -U postgres minigrid > /db-bak/$LETSENCRYPT_DIR-db-$(date +%d-%m-%y).pg" # https://certbot.eff.org/#ubuntuxenial-nginx recommends running this twice a day on random minute within the hour -CRON_JOB="00 01,13 * * * sleep \$(expr \$RANDOM \% 59 \* 60); $CRON_CMD" -crontab -l | fgrep -i -v "$CRON_CMD" | { cat; echo "$CRON_JOB"; } | crontab - +CRON_JOB_1="00 01,13 * * * sleep \$(expr \$RANDOM \% 59 \* 60); $CRON_CMD_1" +CRON_JOB_2="15 2 * * 0 $CRON_CMD_2" +crontab -l | fgrep -i -v "$CRON_CMD_1" | { cat; echo "$CRON_JOB_1"; } | crontab - +crontab -l | fgrep -i -v "$CRON_CMD_2" | { cat; echo "$CRON_JOB_2"; } | crontab - crontab -l From f588dfe43954eb386f299c2ee690fc5ac52e2ab5 Mon Sep 17 00:00:00 2001 From: jmbott Date: Wed, 20 Nov 2019 18:08:20 -0500 Subject: [PATCH 4/4] bump --- .travis.yml | 4 ++-- Dockerfile | 2 +- dev/docker-compose.yml | 2 +- prod/docker-compose.yml | 8 ++++---- prod/install.sh | 10 +++++----- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.travis.yml b/.travis.yml index 370568d..d58822a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,8 +4,8 @@ python: - "3.7" cache: pip addons: - postgresql: "9.5" - firefox: "49.0" + postgresql: "9.6" + firefox: latest dist: bionic sudo: false diff --git a/Dockerfile b/Dockerfile index 1863bb7..3c5ca9e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ FROM python:3.7 COPY . /minigrid-server WORKDIR /minigrid-server RUN set -x \ - && curl -sL https://deb.nodesource.com/setup_7.x | bash \ + && curl -sL https://deb.nodesource.com/setup_10.x | bash \ && apt-get install -y nodejs \ && rm -rf /var/lib/apt/lists/* \ && npm install \ diff --git a/dev/docker-compose.yml b/dev/docker-compose.yml index 6c3b17d..9140b16 100644 --- a/dev/docker-compose.yml +++ b/dev/docker-compose.yml @@ -17,4 +17,4 @@ services: environment: POSTGRES_DB: minigrid redis: - image: redis:3.2 + image: redis:5.0 diff --git a/prod/docker-compose.yml b/prod/docker-compose.yml index c1c76a3..4668daa 100644 --- a/prod/docker-compose.yml +++ b/prod/docker-compose.yml @@ -1,20 +1,20 @@ version: '2' services: minigrid: - image: selcolumbia/minigrid-server:0.2.9 + image: selcolumbia/minigrid-server:0.3.3 command: ./prod/run.sh --db_host=db --redis_url=redis://redis:6379/0 --minigrid-website-url=https://www.example.com depends_on: - redis - db db: - image: postgres:9.6.1 + image: postgres:9.6 environment: POSTGRES_DB: minigrid redis: - image: redis:3.2.5 + image: redis:5.0 command: redis-server --notify-keyspace-events "Ex" nginx: - image: nginx:1.11.6 + image: nginx:1.16.1 ports: - "80:80" - "443:443" diff --git a/prod/install.sh b/prod/install.sh index fd39c0d..4fb9775 100755 --- a/prod/install.sh +++ b/prod/install.sh @@ -1,5 +1,5 @@ #!/usr/bin/env sh -# Minigrid Server installer for version 0.2.9 +# Minigrid Server installer for version 0.3.3 set -e # Do you have docker installed? @@ -37,7 +37,7 @@ else printf " Installing docker-compose in this \n" printf " directory \n" printf "========================================\n" - $CURL -L https://github.com/docker/compose/releases/download/1.9.0/run.sh > docker-compose \ + $CURL -L https://github.com/docker/compose/releases/download/1.24.1/run.sh > docker-compose \ && chmod +x docker-compose ./docker-compose -v fi @@ -108,8 +108,8 @@ $SUDO openssl dhparam -out /etc/letsencrypt/live/$LETSENCRYPT_DIR/dhparam.pem 20 printf "========================================\n" printf " Generating configuration \n" printf "========================================\n" -$CURL -L https://raw.githubusercontent.com/SEL-Columbia/minigrid-server/0.2.9/prod/docker-compose.yml > docker-compose.yml -$CURL -L https://raw.githubusercontent.com/SEL-Columbia/minigrid-server/0.2.9/prod/nginx.conf > nginx.conf +$CURL -L https://raw.githubusercontent.com/SEL-Columbia/minigrid-server/0.3.3/prod/docker-compose.yml > docker-compose.yml +$CURL -L https://raw.githubusercontent.com/SEL-Columbia/minigrid-server/0.3.3/prod/nginx.conf > nginx.conf sed -i s/www.example.com/$LETSENCRYPT_DIR/g docker-compose.yml sed -i s/www.example.com/$LETSENCRYPT_DIR/g nginx.conf @@ -134,7 +134,7 @@ if [ -f /etc/redhat-release ] ; then fi $DOCKER_COMPOSE up -d MINIGRID_CONTAINER_NAME=$($DOCKER_COMPOSE ps | grep _minigrid_ | cut -d' ' -f1) -sleep 1 +sleep 4 docker exec $MINIGRID_CONTAINER_NAME ""prod/create_initial_user.py --db-host=db $ADMIN_EMAIL"" docker exec $MINIGRID_CONTAINER_NAME ""prod/create_payment_ids.py --db-host=db"" NGINX_CONTAINER_NAME=$($DOCKER_COMPOSE ps | grep _nginx_ | cut -d' ' -f1)