Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f02db4c6b5 | ||
|
|
c7ad0d3d49 |
+1
-1
@@ -134,7 +134,7 @@ sudo chmod 755 /var/log/tesm
|
||||
step "Deploying application to /srv/tesm"
|
||||
sudo mkdir -p /srv/tesm
|
||||
sudo rsync -a --delete --exclude 'venv' --exclude 'sqlite.db' --exclude 'fernet.key' --exclude 'secret.key' \
|
||||
--exclude 'known_hosts' \
|
||||
--exclude 'known_hosts' --exclude 'license.json' \
|
||||
"$REPO_DIR/srv/tesm/" /srv/tesm/ >>/var/log/tesm-install.log 2>&1
|
||||
print_status "Application files copied"
|
||||
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
1.2.2
|
||||
1.2.4
|
||||
|
||||
+25
-2
@@ -103,14 +103,30 @@ def _parse_iso(s: str) -> float:
|
||||
return datetime.datetime.strptime(s, "%Y-%m-%dT%H:%M:%SZ").replace(tzinfo=datetime.timezone.utc).timestamp()
|
||||
|
||||
|
||||
# Sentinel-Ablaufdatum fuer "Lifetime"-Lizenzen. Bewusst ein fixes, weit in
|
||||
# der Zukunft liegendes Datum statt eines Sonderwerts wie None/0 fuer
|
||||
# expires_at -- dadurch bleibt JEDE bestehende Datumsvergleichs-/
|
||||
# Differenzrechnung (hier, im Master-Dashboard, UND im TESM-Client) ohne
|
||||
# jede Sonderbehandlung korrekt: "in > 90 Tagen faellig" o.ae. ist fuer ein
|
||||
# Datum im Jahr 2099 schlicht immer wahr. Ob eine Lizenz als "Lifetime"
|
||||
# geflaggt ist, wird zusaetzlich explizit in der Master-DB gespeichert
|
||||
# (licenses.lifetime) -- dieses Sentinel-Datum ist nur die tatsaechlich in
|
||||
# die signierte Lizenzdatei eingebettete, fuer den Client sichtbare Reprae-
|
||||
# sentation davon.
|
||||
LIFETIME_EXPIRES_AT = "2099-12-31T00:00:00Z"
|
||||
|
||||
|
||||
# ================================================================ Lizenz ==
|
||||
|
||||
def issue_license(*, customer, license_type, modules, valid_days,
|
||||
master_private_key_b64, master_public_key_b64,
|
||||
master_endpoint, vendor, license_id=None, now=None):
|
||||
master_endpoint, vendor, license_id=None, now=None, lifetime=False):
|
||||
"""Vom MASTER aufgerufen: erzeugt eine neue, signierte Lizenz samt
|
||||
frischem Pro-Lizenz-Schlüsselpaar.
|
||||
|
||||
lifetime=True ignoriert valid_days komplett und setzt stattdessen das
|
||||
feste Sentinel-Datum LIFETIME_EXPIRES_AT -- siehe dortigen Kommentar.
|
||||
|
||||
Rückgabe: (license_file, license_pubkey) -- license_file ist die
|
||||
komplette, an den Kunden auszuhändigende Datei (inkl. dem PRIVATEN
|
||||
Lizenzschlüssel); license_pubkey ist NUR für die Master-Datenbank
|
||||
@@ -130,7 +146,7 @@ def issue_license(*, customer, license_type, modules, valid_days,
|
||||
"type": license_type,
|
||||
"modules": sorted(modules),
|
||||
"issued_at": _iso(now),
|
||||
"expires_at": _iso(now + valid_days * 86400),
|
||||
"expires_at": LIFETIME_EXPIRES_AT if lifetime else _iso(now + valid_days * 86400),
|
||||
"license_pubkey": license_pub,
|
||||
"master_pubkey": master_public_key_b64,
|
||||
"master_endpoint": master_endpoint,
|
||||
@@ -225,6 +241,13 @@ def build_client_request(action, license_file, nonce=None) -> dict:
|
||||
payload = {
|
||||
"license_id": license_file["license_id"],
|
||||
"fingerprint": system_fingerprint(),
|
||||
# Rein informativ fuer die Dashboard-Kacheln des Masters (siehe
|
||||
# dortiges index()) -- fliesst NICHT in irgendeine Sicherheits-
|
||||
# entscheidung ein (die bleibt allein Sache des Fingerprints), wird
|
||||
# aber wie alle anderen Felder mitsigniert, damit ein Angreifer
|
||||
# ohne den privaten Lizenzschluessel keinen falschen Hostnamen
|
||||
# unterschieben kann.
|
||||
"hostname": socket.gethostname(),
|
||||
"action": action,
|
||||
"nonce": nonce or uuid.uuid4().hex,
|
||||
"timestamp": _iso(time.time()),
|
||||
|
||||
Reference in New Issue
Block a user