diff --git a/README.md b/README.md index 69da535..35c3272 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,9 @@ Highlights: - Comes with standard Debian package, easy to manage and automate - **No JavaScript is involved** in the whole process, as I believe JavaScript is harmful to developers -## Installation / Usage +## Usage + +### Installation 1. [Download the latest release](https://github.com/Jamesits/pve-fake-subscription/releases/latest) 1. Install: run `dpkg -i pve-fake-subscription_*.deb` as root on every node @@ -38,7 +40,7 @@ The fake subscription status doesn't grant you free access to the enterprise rep - [Proxmox Mail Gateway (PMG)](https://pmg.proxmox.com/pmg-docs/pmg-admin-guide.html#pmg_package_repositories) - [Proxmox Backup Server (PBS)](https://pbs.proxmox.com/docs/installation.html#proxmox-backup-no-subscription-repository) -## Uninstallation +### Uninstallation Run as root: @@ -48,10 +50,45 @@ apt purge pve-fake-subscription This will revert your system to a "no subscription key" status. -## Building the Package +## Development Notes + +### Building the Package Install [nFPM](https://nfpm.goreleaser.com/install/), then: ```shell ./package.sh ``` + +### Compatibility for Old Proxmox VE Versions + +#### PVE 4.x + +PVE 4.x is supported with minor changes to the script. + +Changes needed: +- License key needs to be changed from `pve8p` to `pve4p` + +#### PVE 3.x + +PVE 3.x is supported with minor changes to the script. + +Changes needed: +- The script's hashbang need to be changed from `#!/usr/bin/env python3` to `#!/usr/bin/env python` +- License key needs to be changed from `pve8p` to `pve4p` + +Installation with `dpkg -i` will not work. Use the following script to install manually: +```shell +mkdir -p /tmp/pve-fake-subscription +dpkg-deb -x pve-fake-subscription_*.deb /tmp/pve-fake-subscription +sed -i'' -e's/python3/python/g' -e's/pve8p/pve4p/g' /tmp/pve-fake-subscription/usr/bin/pve-fake-subscription +mv /tmp/pve-fake-subscription/usr/bin/pve-fake-subscription /usr/local/bin/ +rm -rf /tmp/pve-fake-subscription +ln -sf /usr/local/bin/pve-fake-subscription /etc/cron.hourly/pve-fake-subscription +/usr/local/bin/pve-fake-subscription +``` + +Removal: +```shell +rm -f /usr/local/bin/pve-fake-subscription /etc/cron.hourly/pve-fake-subscription +``` diff --git a/nfpm.yaml b/nfpm.yaml index 1f333a2..427ed53 100644 --- a/nfpm.yaml +++ b/nfpm.yaml @@ -1,7 +1,7 @@ name: "pve-fake-subscription" arch: "all" platform: "linux" -version: "0.0.9" +version: "0.0.10" version_schema: "semver" version_metadata: "git" diff --git a/scripts/postinst b/scripts/postinst index a39394a..da7c9c6 100755 --- a/scripts/postinst +++ b/scripts/postinst @@ -3,15 +3,19 @@ after_upgrade() { : - systemctl --system daemon-reload >/dev/null || true - debsystemctl=$(command -v deb-systemd-invoke || echo systemctl) - if ! systemctl is-enabled pve-fake-subscription.timer >/dev/null - then - : # Ensure this if-clause is not empty. If it were empty, and we had an 'else', then it is an error in shell syntax - systemctl preset pve-fake-subscription.timer >/dev/null || true - $debsystemctl start pve-fake-subscription.timer >/dev/null || true + if command -v systemctl >/dev/null; then + systemctl --system daemon-reload >/dev/null || true + debsystemctl=$(command -v deb-systemd-invoke || echo systemctl) + if ! systemctl is-enabled pve-fake-subscription.timer >/dev/null + then + : # Ensure this if-clause is not empty. If it were empty, and we had an 'else', then it is an error in shell syntax + systemctl preset pve-fake-subscription.timer >/dev/null || true + $debsystemctl start pve-fake-subscription.timer >/dev/null || true + else + $debsystemctl restart pve-fake-subscription.timer >/dev/null || true + fi else - $debsystemctl restart pve-fake-subscription.timer >/dev/null || true + ln -sf /usr/bin/pve-fake-subscription /etc/cron.hourly/pve-fake-subscription fi pve-fake-subscription @@ -20,10 +24,14 @@ after_upgrade() { after_install() { : - systemctl --system daemon-reload >/dev/null || true - debsystemctl=$(command -v deb-systemd-invoke || echo systemctl) - systemctl preset pve-fake-subscription.timer >/dev/null || true - $debsystemctl start pve-fake-subscription.timer >/dev/null || true + if command -v systemctl >/dev/null; then + systemctl --system daemon-reload >/dev/null || true + debsystemctl=$(command -v deb-systemd-invoke || echo systemctl) + systemctl preset pve-fake-subscription.timer >/dev/null || true + $debsystemctl start pve-fake-subscription.timer >/dev/null || true + else + ln -sf /usr/bin/pve-fake-subscription /etc/cron.hourly/pve-fake-subscription + fi pve-fake-subscription } diff --git a/scripts/postrm b/scripts/postrm index eab36b4..77de063 100755 --- a/scripts/postrm +++ b/scripts/postrm @@ -6,6 +6,8 @@ after_remove() { rm -f /etc/subscription rm -f /etc/pmg/subscription rm -f /etc/proxmox-backup/subscription + + rm -f /etc/cron.hourly/pve-fake-subscription } after_purge() { diff --git a/usr/bin/pve-fake-subscription b/usr/bin/pve-fake-subscription index 8deeaa3..f94a437 100755 --- a/usr/bin/pve-fake-subscription +++ b/usr/bin/pve-fake-subscription @@ -3,6 +3,8 @@ # Pollute Proxmox software subscription cache so it won't alert you on dashboard login # Should be scheduled to run every few hours with a timer to prevent cache from expiring # If you need to prevent it checking keys against a server, please block "shop.maurer-it.com" in your hosts file + +from __future__ import print_function import hashlib import base64 import json @@ -10,7 +12,6 @@ import time import re import sys import os -from typing import List from datetime import datetime, timedelta # PVE & PMG: /usr/share/perl5/PVE/Subscription.pm @@ -18,30 +19,40 @@ from datetime import datetime, timedelta shared_key_data = "kjfdlskfhiuewhfk947368" server_key_file = "/etc/ssh/ssh_host_rsa_key.pub" -def get_timestamp() -> int: +# Default license keys +lic_pve = "pve8p-1145141919" +lic_pmg = "pmgp-1145141919" +lic_pbs = "pbst-1145141919" + +# UI customization +ui_product_name = "YajuuSenpai" +ui_message = "Yajuu Senpai has got your back" +ui_url = "https://github.com/Jamesits/pve-fake-subscription" + +def get_timestamp(): return int(time.time()) # Perl's md5_base64 implementation -def md5_base64_perl(x: str) -> str: +def md5_base64_perl(x): return base64.b64encode(hashlib.md5(x.encode()).digest()).strip(b'=').decode() # Rust's `base64::encode(tools::md5sum("something")?);` -def md5_base64_rs(x: str) -> str: +def md5_base64_rs(x): return base64.b64encode(hashlib.md5(x.encode()).digest()).decode() -def generate_server_id(key: str) -> str: +def generate_server_id(key): return hashlib.md5(key.encode()).hexdigest().upper() -def dt_string(format: str, offset_secs: int = 0) -> str: +def dt_string(format, offset_secs=0): return (datetime.now() + timedelta(seconds=offset_secs)).strftime(format) -def generate_subscription_pve_pmg(key: str, server_ids: List[str]) -> str: +def generate_subscription_pve_pmg(key, server_ids, product_name=ui_product_name): localinfo = { "checktime": get_timestamp(), "status": "Active", "key": key, "validdirectory": ",".join(server_ids), - "productname": "YajuuSenpai", + "productname": product_name, "regdate": dt_string("%Y-%m-%d %H:%M:%S"), "nextduedate": dt_string("%Y-%m-%d", 1296000), } @@ -53,9 +64,10 @@ def generate_subscription_pve_pmg(key: str, server_ids: List[str]) -> str: return key + "\n" + csum + "\n" + data + "\n" # key_pattern can be find in /usr/share/perl5/{PVE,PMG}/API2/Subscription.pm -# PVE: r'pve([1248])([cbsp])-[0-9a-f]{10}' +# PVE5+: r'pve([1248])([cbsp])-[0-9a-f]{10}' +# PVE3/4: r'pve([124])([cbsp])-[0-9a-f]{10}' # PMG: r'pmg([cbsp])-[0-9a-f]{10}' -def activate_pve_pmg(key: str, subscription_file: str) -> None: +def activate_pve_pmg(key, subscription_file, *args, **kwargs): # check if the key format is correct # pattern = re.compile(key_pattern) # if not pattern.match(key): @@ -68,23 +80,23 @@ def activate_pve_pmg(key: str, subscription_file: str) -> None: server_id = generate_server_id(f.read()) # generate a license file - subscription = generate_subscription_pve_pmg(key, [server_id]) + subscription = generate_subscription_pve_pmg(key, [server_id], *args, **kwargs) # write license file with open(subscription_file, "w") as f: f.write(subscription) -def generate_subscription_pbs(key: str, server_ids: List[str]) -> str: +def generate_subscription_pbs(key, server_ids, product_name=ui_product_name, message=ui_message): localinfo = { "status": "active", # PBS: `new`, `notfound`, `active`, `invalid` "serverid": ",".join(server_ids), "checktime": get_timestamp(), "key": key, - "message": "Yajuu Senpai has got your back", - "productname": "YajuuSenpai", + "message": message, + "productname": product_name, "regdate": dt_string("%Y-%m-%d %H:%M:%S"), "nextduedate": dt_string("%Y-%m-%d", 1296000), # 1296000: MAX_LOCAL_KEY_AGE in src/tools/subscription.rs - "url": "https://github.com/Jamesits/pve-fake-subscription", + "url": url, } data = base64.standard_b64encode(json.dumps(localinfo).encode()).decode() @@ -94,14 +106,14 @@ def generate_subscription_pbs(key: str, server_ids: List[str]) -> str: return key + "\n" + csum + "\n" + data + "\n" # Key pattern: pbst-xxxxxxxxxx -def activate_pbs(key: str, subscription_file: str) -> None: +def activate_pbs(key, subscription_file, *args, **kwargs): # get machine ID server_id = "" with open(server_key_file, "r") as f: server_id = generate_server_id(f.read()) # generate a license file - subscription = generate_subscription_pbs(key, [server_id]) + subscription = generate_subscription_pbs(key, [server_id], *args, **kwargs) # write license file with open(subscription_file, "w") as f: @@ -111,14 +123,14 @@ if __name__ == "__main__": # Proxmox VE if os.path.exists("/etc/pve"): print("Activating Proxmox VE...") - activate_pve_pmg("pve8p-1145141919", "/etc/subscription") + activate_pve_pmg(lic_pve, "/etc/subscription") # Proxmox Mail Gateway if os.path.exists("/etc/pmg"): print("Activating Proxmox Mail Gateway...") - activate_pve_pmg("pmgp-1145141919", "/etc/pmg/subscription") + activate_pve_pmg(lic_pmg, "/etc/pmg/subscription") # Proxmox Backup Server if os.path.exists("/etc/proxmox-backup"): print("Activating Proxmox Backup Server...") - activate_pbs("pbst-1145141919", "/etc/proxmox-backup/subscription") + activate_pbs(lic_pbs, "/etc/proxmox-backup/subscription")