make the script compatible with Python 2.7 and 3.18

This commit is contained in:
Jamesits 2024-10-25 15:53:01 +08:00
parent 2414d822ee
commit b4dd87c236
No known key found for this signature in database
5 changed files with 95 additions and 36 deletions

View File

@ -22,7 +22,9 @@ Highlights:
- Comes with standard Debian package, easy to manage and automate - 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 - **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. [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 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 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) - [Proxmox Backup Server (PBS)](https://pbs.proxmox.com/docs/installation.html#proxmox-backup-no-subscription-repository)
## Uninstallation ### Uninstallation
Run as root: Run as root:
@ -48,10 +50,45 @@ apt purge pve-fake-subscription
This will revert your system to a "no subscription key" status. 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: Install [nFPM](https://nfpm.goreleaser.com/install/), then:
```shell ```shell
./package.sh ./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
```

View File

@ -1,7 +1,7 @@
name: "pve-fake-subscription" name: "pve-fake-subscription"
arch: "all" arch: "all"
platform: "linux" platform: "linux"
version: "0.0.9" version: "0.0.10"
version_schema: "semver" version_schema: "semver"
version_metadata: "git" version_metadata: "git"

View File

@ -3,15 +3,19 @@
after_upgrade() { after_upgrade() {
: :
systemctl --system daemon-reload >/dev/null || true if command -v systemctl >/dev/null; then
debsystemctl=$(command -v deb-systemd-invoke || echo systemctl) systemctl --system daemon-reload >/dev/null || true
if ! systemctl is-enabled pve-fake-subscription.timer >/dev/null debsystemctl=$(command -v deb-systemd-invoke || echo systemctl)
then if ! systemctl is-enabled pve-fake-subscription.timer >/dev/null
: # Ensure this if-clause is not empty. If it were empty, and we had an 'else', then it is an error in shell syntax then
systemctl preset pve-fake-subscription.timer >/dev/null || true : # Ensure this if-clause is not empty. If it were empty, and we had an 'else', then it is an error in shell syntax
$debsystemctl start pve-fake-subscription.timer >/dev/null || true 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 else
$debsystemctl restart pve-fake-subscription.timer >/dev/null || true ln -sf /usr/bin/pve-fake-subscription /etc/cron.hourly/pve-fake-subscription
fi fi
pve-fake-subscription pve-fake-subscription
@ -20,10 +24,14 @@ after_upgrade() {
after_install() { after_install() {
: :
systemctl --system daemon-reload >/dev/null || true if command -v systemctl >/dev/null; then
debsystemctl=$(command -v deb-systemd-invoke || echo systemctl) systemctl --system daemon-reload >/dev/null || true
systemctl preset pve-fake-subscription.timer >/dev/null || true debsystemctl=$(command -v deb-systemd-invoke || echo systemctl)
$debsystemctl start pve-fake-subscription.timer >/dev/null || true 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 pve-fake-subscription
} }

View File

@ -6,6 +6,8 @@ after_remove() {
rm -f /etc/subscription rm -f /etc/subscription
rm -f /etc/pmg/subscription rm -f /etc/pmg/subscription
rm -f /etc/proxmox-backup/subscription rm -f /etc/proxmox-backup/subscription
rm -f /etc/cron.hourly/pve-fake-subscription
} }
after_purge() { after_purge() {

View File

@ -3,6 +3,8 @@
# Pollute Proxmox software subscription cache so it won't alert you on dashboard login # 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 # 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 # 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 hashlib
import base64 import base64
import json import json
@ -10,7 +12,6 @@ import time
import re import re
import sys import sys
import os import os
from typing import List
from datetime import datetime, timedelta from datetime import datetime, timedelta
# PVE & PMG: /usr/share/perl5/PVE/Subscription.pm # PVE & PMG: /usr/share/perl5/PVE/Subscription.pm
@ -18,30 +19,40 @@ from datetime import datetime, timedelta
shared_key_data = "kjfdlskfhiuewhfk947368" shared_key_data = "kjfdlskfhiuewhfk947368"
server_key_file = "/etc/ssh/ssh_host_rsa_key.pub" 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()) return int(time.time())
# Perl's md5_base64 implementation # 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() return base64.b64encode(hashlib.md5(x.encode()).digest()).strip(b'=').decode()
# Rust's `base64::encode(tools::md5sum("something")?);` # 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() 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() 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) 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 = { localinfo = {
"checktime": get_timestamp(), "checktime": get_timestamp(),
"status": "Active", "status": "Active",
"key": key, "key": key,
"validdirectory": ",".join(server_ids), "validdirectory": ",".join(server_ids),
"productname": "YajuuSenpai", "productname": product_name,
"regdate": dt_string("%Y-%m-%d %H:%M:%S"), "regdate": dt_string("%Y-%m-%d %H:%M:%S"),
"nextduedate": dt_string("%Y-%m-%d", 1296000), "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" return key + "\n" + csum + "\n" + data + "\n"
# key_pattern can be find in /usr/share/perl5/{PVE,PMG}/API2/Subscription.pm # 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}' # 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 # check if the key format is correct
# pattern = re.compile(key_pattern) # pattern = re.compile(key_pattern)
# if not pattern.match(key): # 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()) server_id = generate_server_id(f.read())
# generate a license file # 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 # write license file
with open(subscription_file, "w") as f: with open(subscription_file, "w") as f:
f.write(subscription) 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 = { localinfo = {
"status": "active", # PBS: `new`, `notfound`, `active`, `invalid` "status": "active", # PBS: `new`, `notfound`, `active`, `invalid`
"serverid": ",".join(server_ids), "serverid": ",".join(server_ids),
"checktime": get_timestamp(), "checktime": get_timestamp(),
"key": key, "key": key,
"message": "Yajuu Senpai has got your back", "message": message,
"productname": "YajuuSenpai", "productname": product_name,
"regdate": dt_string("%Y-%m-%d %H:%M:%S"), "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 "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() 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" return key + "\n" + csum + "\n" + data + "\n"
# Key pattern: pbst-xxxxxxxxxx # Key pattern: pbst-xxxxxxxxxx
def activate_pbs(key: str, subscription_file: str) -> None: def activate_pbs(key, subscription_file, *args, **kwargs):
# get machine ID # get machine ID
server_id = "" server_id = ""
with open(server_key_file, "r") as f: with open(server_key_file, "r") as f:
server_id = generate_server_id(f.read()) server_id = generate_server_id(f.read())
# generate a license file # generate a license file
subscription = generate_subscription_pbs(key, [server_id]) subscription = generate_subscription_pbs(key, [server_id], *args, **kwargs)
# write license file # write license file
with open(subscription_file, "w") as f: with open(subscription_file, "w") as f:
@ -111,14 +123,14 @@ if __name__ == "__main__":
# Proxmox VE # Proxmox VE
if os.path.exists("/etc/pve"): if os.path.exists("/etc/pve"):
print("Activating Proxmox VE...") print("Activating Proxmox VE...")
activate_pve_pmg("pve8p-1145141919", "/etc/subscription") activate_pve_pmg(lic_pve, "/etc/subscription")
# Proxmox Mail Gateway # Proxmox Mail Gateway
if os.path.exists("/etc/pmg"): if os.path.exists("/etc/pmg"):
print("Activating Proxmox Mail Gateway...") print("Activating Proxmox Mail Gateway...")
activate_pve_pmg("pmgp-1145141919", "/etc/pmg/subscription") activate_pve_pmg(lic_pmg, "/etc/pmg/subscription")
# Proxmox Backup Server # Proxmox Backup Server
if os.path.exists("/etc/proxmox-backup"): if os.path.exists("/etc/proxmox-backup"):
print("Activating Proxmox Backup Server...") print("Activating Proxmox Backup Server...")
activate_pbs("pbst-1145141919", "/etc/proxmox-backup/subscription") activate_pbs(lic_pbs, "/etc/proxmox-backup/subscription")