From 25ce52f36ff2545a9a96d271df12bd35c2cd9b5d Mon Sep 17 00:00:00 2001 From: nad Date: Tue, 29 Jun 2021 13:16:54 +0200 Subject: [PATCH 1/7] first iteration adding JWT on snapshot --- ereuse_workbench/config.py | 2 -- ereuse_workbench/erwb.py | 7 +++++-- ereuse_workbench/install.py | 1 + ereuse_workbench/workbench.py | 13 +++++++++---- requirements.txt | 3 ++- 5 files changed, 17 insertions(+), 9 deletions(-) diff --git a/ereuse_workbench/config.py b/ereuse_workbench/config.py index f79f7d7..c675d48 100644 --- a/ereuse_workbench/config.py +++ b/ereuse_workbench/config.py @@ -1,7 +1,5 @@ from decouple import AutoConfig -from ereuse_workbench.test import TestDataStorageLength - class WorkbenchConfig: # Path where find settings.ini file diff --git a/ereuse_workbench/erwb.py b/ereuse_workbench/erwb.py index 8eefd97..09ac1a4 100755 --- a/ereuse_workbench/erwb.py +++ b/ereuse_workbench/erwb.py @@ -1,10 +1,11 @@ -import json import logging.config import subprocess import time from datetime import datetime, timezone import click +import ereuse_utils +import jwt import ntplib import requests from boltons import urlutils @@ -115,8 +116,10 @@ def _submit(url: urlutils.URL, snapshot: Snapshot): r = session.post('/users/login/', json={'email': username, 'password': password}) token = r.json()['token'] t = token or WorkbenchConfig.DH_TOKEN + # TODO Get the user's key on the server + key = '' r = session.post('{}actions/'.format(url.to_text()), - data=snapshot.to_json(), + data=jwt.encode(snapshot.dump(), key, algorithm="HS256", json_encoder=ereuse_utils.JSONEncoder), headers={ 'Authorization': 'Basic {}'.format(t), 'Content-Type': 'application/json' diff --git a/ereuse_workbench/install.py b/ereuse_workbench/install.py index 2b662e6..b854374 100644 --- a/ereuse_workbench/install.py +++ b/ereuse_workbench/install.py @@ -14,6 +14,7 @@ class Install(Measurable): Important: GPT partition scheme and UEFI-based boot not yet supported. All relevant code is just placeholder. """ + def __init__(self, image_path: Path, logical_name: str = '/dev/sda', diff --git a/ereuse_workbench/workbench.py b/ereuse_workbench/workbench.py index 9c4073a..4712432 100644 --- a/ereuse_workbench/workbench.py +++ b/ereuse_workbench/workbench.py @@ -9,16 +9,17 @@ from subprocess import CalledProcessError import ereuse_utils +import jwt from boltons import urlutils from colorama import Fore, init from ereuse_utils import cmd from ereuse_utils.session import DevicehubClient, retry +from ereuse_workbench.config import WorkbenchConfig from ereuse_workbench.erase import EraseType from ereuse_workbench.snapshot import Snapshot, SnapshotSoftware from ereuse_workbench.test import TestDataStorageLength from ereuse_workbench.usb_sneaky import USBSneaky -from ereuse_workbench.config import WorkbenchConfig class Workbench: @@ -136,9 +137,11 @@ def erase(self, value): self._erase = EraseType(value) if value else None def config_environment(self): - """Configures snapshots folder and and save json name""" + """Configures snapshots folder and save json name""" self.snapshots_path.mkdir(parents=True, exist_ok=True) - self.json = Path('{snapshots_path}/{date}_{uuid}_computer.json'.format(snapshots_path=self.snapshots_path, date=date.today().strftime("%Y-%m-%d"), uuid=self.uuid)) + self.json = Path('{snapshots_path}/{date}_{uuid}_computer.json'.format(snapshots_path=self.snapshots_path, + date=date.today().strftime("%Y-%m-%d"), + uuid=self.uuid)) def config_from_server(self): """Configures the Workbench from a config endpoint in the server.""" @@ -242,7 +245,9 @@ def _run(self) -> Snapshot: (self.install_path / self.install) if self.install else None) snapshot.close() - self.json.write_text(snapshot.to_json()) + ## Convert snapshot to dict object and encoded using PyJWT + snapshot_encoded = jwt.encode(snapshot.dump(), '', algorithm="HS256", json_encoder=ereuse_utils.JSONEncoder) + self.json.write_text(snapshot_encoded) return snapshot @property diff --git a/requirements.txt b/requirements.txt index 5495d56..29e27a0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,4 +10,5 @@ pySMART.smartx==0.3.9 requests==2.21.0 requests-toolbelt==0.9.1 tqdm==4.32.2 -python-decouple==3.3 \ No newline at end of file +python-decouple==3.3 +pyjwt==2.1.0 \ No newline at end of file From 07ac46a224149940037483425b81ce077efc7cfd Mon Sep 17 00:00:00 2001 From: nad Date: Tue, 29 Jun 2021 15:58:00 +0200 Subject: [PATCH 2/7] adding default values on config file --- ereuse_workbench/config.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ereuse_workbench/config.py b/ereuse_workbench/config.py index c675d48..bfa8464 100644 --- a/ereuse_workbench/config.py +++ b/ereuse_workbench/config.py @@ -6,9 +6,9 @@ class WorkbenchConfig: config = AutoConfig(search_path='/home/user/') # Env variables for DH parameters - DH_TOKEN = config('DH_TOKEN') - DH_HOST = config('DH_HOST') - DH_DATABASE = config('DH_DATABASE') + DH_TOKEN = config('DH_TOKEN', default='') + DH_HOST = config('DH_HOST', default='') + DH_DATABASE = config('DH_DATABASE', default='') DEVICEHUB_URL = 'https://{host}/{db}/'.format( host=DH_HOST, db=DH_DATABASE From 3bde7705109e4a01095bae342aa7af4c321f6cbc Mon Sep 17 00:00:00 2001 From: nad Date: Thu, 1 Jul 2021 13:08:00 +0200 Subject: [PATCH 3/7] add hashlib to prevent snapshot modification --- ereuse_workbench/snapshot.py | 11 +++++++++++ ereuse_workbench/workbench.py | 5 ++--- tests/conftest.py | 4 +++- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/ereuse_workbench/snapshot.py b/ereuse_workbench/snapshot.py index 3e54851..9e78bd2 100644 --- a/ereuse_workbench/snapshot.py +++ b/ereuse_workbench/snapshot.py @@ -1,3 +1,4 @@ +import hashlib import logging from concurrent.futures import ThreadPoolExecutor from datetime import datetime, timedelta, timezone @@ -214,6 +215,16 @@ def close(self): if self._session: self._session.patch('/snapshots/', self, self.uuid, status=204) + def hash(self): + """Create snapshot hash to prevent manual modifications + on json file. + """ + snapshot_without_debug = self.dump() + snapshot_without_debug.pop('debug') + bfile = str(snapshot_without_debug).encode('utf-8') + hash3 = hashlib.sha3_256(bfile).hexdigest() + self.debug['hwinfo'] += hash3 + class Progress: """Manages updating progress percentage to a Line and a Workbench diff --git a/ereuse_workbench/workbench.py b/ereuse_workbench/workbench.py index 4712432..2f3b887 100644 --- a/ereuse_workbench/workbench.py +++ b/ereuse_workbench/workbench.py @@ -245,9 +245,8 @@ def _run(self) -> Snapshot: (self.install_path / self.install) if self.install else None) snapshot.close() - ## Convert snapshot to dict object and encoded using PyJWT - snapshot_encoded = jwt.encode(snapshot.dump(), '', algorithm="HS256", json_encoder=ereuse_utils.JSONEncoder) - self.json.write_text(snapshot_encoded) + snapshot.hash() + self.json.write_text(snapshot.to_json()) return snapshot @property diff --git a/tests/conftest.py b/tests/conftest.py index 4471513..221aa9b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -81,9 +81,11 @@ def computer(run, model: str) -> Tuple[Computer, List[Component]]: run.set(model) s = Snapshot(UUID(int=000000), SnapshotSoftware.Workbench, - StrictVersion('11.0a1')) + StrictVersion('11.0a1'), + debug=True) s.computer() s.close() + s.hash() s.elapsed = 0 # So cpu time does not impact assert s.closed pc, components = s.device, s.components From 0615b4bfaa2285b3181718dff8aba826d5338bbd Mon Sep 17 00:00:00 2001 From: nad Date: Fri, 2 Jul 2021 09:25:22 +0200 Subject: [PATCH 4/7] adding jwt encode on snapshot data --- ereuse_workbench/erwb.py | 4 ++-- ereuse_workbench/snapshot.py | 14 ++++---------- ereuse_workbench/workbench.py | 4 +--- 3 files changed, 7 insertions(+), 15 deletions(-) diff --git a/ereuse_workbench/erwb.py b/ereuse_workbench/erwb.py index 09ac1a4..fd47f12 100755 --- a/ereuse_workbench/erwb.py +++ b/ereuse_workbench/erwb.py @@ -117,9 +117,9 @@ def _submit(url: urlutils.URL, snapshot: Snapshot): token = r.json()['token'] t = token or WorkbenchConfig.DH_TOKEN # TODO Get the user's key on the server - key = '' + s = '7KU4ZzsEfe' r = session.post('{}actions/'.format(url.to_text()), - data=jwt.encode(snapshot.dump(), key, algorithm="HS256", json_encoder=ereuse_utils.JSONEncoder), + data=jwt.encode(snapshot.dump(), s, algorithm="HS256", json_encoder=ereuse_utils.JSONEncoder), headers={ 'Authorization': 'Basic {}'.format(t), 'Content-Type': 'application/json' diff --git a/ereuse_workbench/snapshot.py b/ereuse_workbench/snapshot.py index 9e78bd2..526c8cb 100644 --- a/ereuse_workbench/snapshot.py +++ b/ereuse_workbench/snapshot.py @@ -1,4 +1,3 @@ -import hashlib import logging from concurrent.futures import ThreadPoolExecutor from datetime import datetime, timedelta, timezone @@ -9,6 +8,7 @@ from uuid import UUID import inflection +import jwt from ereuse_utils import cli from ereuse_utils.cli import Line from ereuse_utils.session import DevicehubClient @@ -215,15 +215,9 @@ def close(self): if self._session: self._session.patch('/snapshots/', self, self.uuid, status=204) - def hash(self): - """Create snapshot hash to prevent manual modifications - on json file. - """ - snapshot_without_debug = self.dump() - snapshot_without_debug.pop('debug') - bfile = str(snapshot_without_debug).encode('utf-8') - hash3 = hashlib.sha3_256(bfile).hexdigest() - self.debug['hwinfo'] += hash3 + def encode(self, s): + """Convert snapshot to dict object and encoded using PyJWT""" + return jwt.encode(self.dump(), s, algorithm="HS256", json_encoder=self.ENCODER) class Progress: diff --git a/ereuse_workbench/workbench.py b/ereuse_workbench/workbench.py index 2f3b887..35b0b17 100644 --- a/ereuse_workbench/workbench.py +++ b/ereuse_workbench/workbench.py @@ -9,7 +9,6 @@ from subprocess import CalledProcessError import ereuse_utils -import jwt from boltons import urlutils from colorama import Fore, init from ereuse_utils import cmd @@ -245,8 +244,7 @@ def _run(self) -> Snapshot: (self.install_path / self.install) if self.install else None) snapshot.close() - snapshot.hash() - self.json.write_text(snapshot.to_json()) + self.json.write_text(snapshot.encode('7KU4ZzsEfe')) return snapshot @property From 8a2a75edfeeea377f72c9fd71d5bce68f55d37b3 Mon Sep 17 00:00:00 2001 From: nad Date: Fri, 2 Jul 2021 09:25:47 +0200 Subject: [PATCH 5/7] fixing conftest --- tests/conftest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/conftest.py b/tests/conftest.py index 221aa9b..eca7e14 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -85,7 +85,7 @@ def computer(run, model: str) -> Tuple[Computer, List[Component]]: debug=True) s.computer() s.close() - s.hash() + s.encode('foo') s.elapsed = 0 # So cpu time does not impact assert s.closed pc, components = s.device, s.components From 487fe9624286986d94b109aa50a23eb4913eb717 Mon Sep 17 00:00:00 2001 From: nad Date: Fri, 2 Jul 2021 10:31:12 +0200 Subject: [PATCH 6/7] update WB version to 12.1.0-beta --- CHANGELOG.md | 3 +++ setup.py | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f582f68..f1665e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,9 @@ ml). ## testing [12.0.0-beta] +## [12.1.0-beta] - 2021/07/01 +- [added] JWT on snapshot data + ## [12.0.0-beta] - 2021/05/25 - [added] first version with decoupled configuration diff --git a/setup.py b/setup.py index 15d3acc..04d9eb6 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ setup( name='ereuse-workbench', - version='12.0.0-beta', + version='12.1.0-beta', url='https://github.com/ereuse/workbench', license='Affero', packages=find_packages(), From a2010616df7047d5779dc8337cd5c5a79873a2b7 Mon Sep 17 00:00:00 2001 From: nad Date: Mon, 5 Jul 2021 13:05:29 +0200 Subject: [PATCH 7/7] second iteration adding JWT on snapshot --- ereuse_workbench/erwb.py | 5 ++++- ereuse_workbench/snapshot.py | 5 ++++- requirements.txt | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/ereuse_workbench/erwb.py b/ereuse_workbench/erwb.py index fd47f12..8ed060f 100755 --- a/ereuse_workbench/erwb.py +++ b/ereuse_workbench/erwb.py @@ -1,3 +1,4 @@ +import json import logging.config import subprocess import time @@ -118,8 +119,10 @@ def _submit(url: urlutils.URL, snapshot: Snapshot): t = token or WorkbenchConfig.DH_TOKEN # TODO Get the user's key on the server s = '7KU4ZzsEfe' + snapshot_data = {"type": "Snapshot", + "data": jwt.encode(snapshot.dump(), s, algorithm="HS256", json_encoder=ereuse_utils.JSONEncoder)} r = session.post('{}actions/'.format(url.to_text()), - data=jwt.encode(snapshot.dump(), s, algorithm="HS256", json_encoder=ereuse_utils.JSONEncoder), + data=json.dumps(snapshot_data), headers={ 'Authorization': 'Basic {}'.format(t), 'Content-Type': 'application/json' diff --git a/ereuse_workbench/snapshot.py b/ereuse_workbench/snapshot.py index 526c8cb..df24bc5 100644 --- a/ereuse_workbench/snapshot.py +++ b/ereuse_workbench/snapshot.py @@ -1,3 +1,4 @@ +import json import logging from concurrent.futures import ThreadPoolExecutor from datetime import datetime, timedelta, timezone @@ -217,7 +218,9 @@ def close(self): def encode(self, s): """Convert snapshot to dict object and encoded using PyJWT""" - return jwt.encode(self.dump(), s, algorithm="HS256", json_encoder=self.ENCODER) + snapshot = {"type": "Snapshot", + "data": jwt.encode(self.dump(), s, algorithm="HS256", json_encoder=self.ENCODER)} + return json.dumps(snapshot) class Progress: diff --git a/requirements.txt b/requirements.txt index 29e27a0..3322eba 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,4 +11,4 @@ requests==2.21.0 requests-toolbelt==0.9.1 tqdm==4.32.2 python-decouple==3.3 -pyjwt==2.1.0 \ No newline at end of file +pyjwt>=2.0.0a1 \ No newline at end of file