Compare commits

..

No commits in common. "master" and "v0.0.5" have entirely different histories.

5 changed files with 30 additions and 96 deletions

View File

@ -1,37 +1,18 @@
Disables the "No valid subscription" dialog on all Proxmox products. I am really poor and I really can't afford a license. I just want to get rid of the annoying dialog on every login.
> I am really poor and I can't afford a license. I just want to get rid of the annoying dialog.
## Features ## Features
Works for: * Works for any version >=5 (we've tested this from 5.3 to 6.0 without any changes in the code)
- Proxmox VE (5.x or later, tested up to 7.0) * Supports Proxmox VE and Proxmox Mail Gateway
- Proxmox Mail Gateway (5.x or later) * Non-intrusive, no changes to any system file, persists between system updates
- Proxmox Backup Server (1.x) * Comes with standard Debian package, easy to manage and automate
* You can uninstall at any time, hassle-free
Highlights: * **No JavaScript**
- Non-intrusive: zero modification of any system file
- Future-proof: persists between system updates & major upgrades
- Hassle-free: you can uninstall at any time
- 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 ## Installation
1. [Download the latest release](https://github.com/Jamesits/pve-fake-subscription/releases/latest) * Go to [release](https://github.com/Jamesits/pve-fake-subscription/releases/latest) to download the latest release
1. Install: run `dpkg -i pve-fake-subscription_*.deb` as root on every node * Run `dpkg -i pve-fake-subscription_*.deb` as root on every Proxmox VE node
1. (Optional) `echo "127.0.0.1 shop.maurer-it.com" | sudo tee -a /etc/hosts` to prevent fake keys from being checked against the Proxmox servers
Notes:
The initial run will be scheduled within 1 minute of the installation. If you don't want to wait, you can invoke it immediately by executing `pve-fake-subscription`.
After installation, please refrain yourself from clicking the "check" button on the "Subscription" page. It will invalidate the cache and temporary revert your instance into an unlicensed status.
The fake subscription status doesn't grant you free access to the enterprise repository. You should switch to the no-subscription repository if not already done. Use the following method:
- [Proxmox VE (PVE)](https://pve.proxmox.com/wiki/Package_Repositories#sysadmin_no_subscription_repo)
- [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

View File

@ -4,16 +4,16 @@ cd "$( dirname "${BASH_SOURCE[0]}" )"
fpm -s dir -t deb --force \ fpm -s dir -t deb --force \
-n pve-fake-subscription \ -n pve-fake-subscription \
--description "Pollute the subscription cache of Proxmox VE (>=5.0), Proxmox Mail Gateway (>=5.0) & Proxmox Backup Server (>=1.0) so it won't alert you on dashboard login" \ --description "Pollute Proxmox VE (>=5.0) and Proxmox Mail Gateway (>=5.0) subscription cache so it won't alert you on dashboard login" \
--url "https://github.com/Jamesits/pve-fake-subscription" \ --url "https://github.com/Jamesits/pve-fake-subscription" \
-v 0.0.7 \ -v 0.0.5 \
--license "GLWTS(Good Luck With That Shit) Public License" \ --license "GLWTS(Good Luck With That Shit) Public License" \
--depends "python3" \ --depends "python3" \
--depends "libpve-common-perl" \
--architecture all \ --architecture all \
--deb-dist "unstable" \ --deb-dist "unstable" \
--deb-priority "optional" \ --deb-priority "optional" \
--deb-systemd "usr/lib/systemd/system/pve-fake-subscription.timer" \ --deb-systemd "usr/lib/systemd/system/pve-fake-subscription.timer" \
--deb-systemd-enable --deb-systemd-auto-start --deb-systemd-restart-after-upgrade \
--after-remove "scripts/purge" \ --after-remove "scripts/purge" \
./usr ./usr

View File

@ -1,3 +1,2 @@
rm -f /etc/subscription rm -f /etc/subscription
rm -f /etc/pmg/subscription rm -f /etc/pmg/subscription
rm -f /etc/proxmox-backup/subscription

View File

@ -1,8 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# Pollute Proxmox software subscription cache so it won't alert you on dashboard login # Pollute Proxmox VE 5.x 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"
# If you need to prevent it checking keys against a server, please block "shop.maurer-it.com" in your hosts file
import hashlib import hashlib
import base64 import base64
import json import json
@ -11,28 +10,22 @@ import re
import sys import sys
import os import os
from typing import List from typing import List
from datetime import datetime, timedelta
# PVE & PMG: /usr/share/perl5/PVE/Subscription.pm # /usr/share/perl5/PVE/Subscription.pm
# PBS: /usr/lib/x86_64-linux-gnu/proxmox-backup/* (source code at `https://git.proxmox.com/git/proxmox-backup.git`)
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: def get_timestamp() -> int:
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(x: str) -> str:
return base64.b64encode(hashlib.md5(x.encode()).digest()).strip(b'=').decode() return base64.b64encode(hashlib.md5(x.encode()).digest()).strip(b'=')
# Rust's `base64::encode(tools::md5sum("something")?);`
def md5_base64_rs(x: str) -> str:
return base64.b64encode(hashlib.md5(x.encode()).digest()).decode()
def generate_server_id(key: str) -> str: def generate_server_id(key: str) -> str:
return hashlib.md5(key.encode()).hexdigest().upper() return hashlib.md5(key.encode()).hexdigest().upper()
def generate_subscription_pve_pmg(key: str, server_ids: List[str]) -> str: def generate_subscription(key: str, server_ids: List[str]) -> str:
localinfo = { localinfo = {
"checktime": get_timestamp(), "checktime": get_timestamp(),
"status": "Active", "status": "Active",
@ -45,19 +38,17 @@ def generate_subscription_pve_pmg(key: str, server_ids: List[str]) -> str:
data = base64.standard_b64encode(json.dumps(localinfo).encode()).decode() data = base64.standard_b64encode(json.dumps(localinfo).encode()).decode()
cat = str(localinfo["checktime"]) + data + "\n" + shared_key_data cat = str(localinfo["checktime"]) + data + "\n" + shared_key_data
csum = md5_base64_perl(cat) csum = md5_base64(cat).decode()
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}' def activate(key: str, key_pattern: str, subscription_file: str) -> None:
# PMG: r'pmg([cbsp])-[0-9a-f]{10}'
def activate_pve_pmg(key: str, subscription_file: str) -> None:
# 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):
# print("key format error", file=sys.stderr) print("key format error", file=sys.stderr)
# sys.exit(1) sys.exit(1)
# get machine ID # get machine ID
server_id = "" server_id = ""
@ -65,40 +56,7 @@ 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(key, [server_id])
# write license file
with open(subscription_file, "w") as f:
f.write(subscription)
def generate_subscription_pbs(key: str, server_ids: List[str]) -> str:
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",
"regdate": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
"nextduedate": (datetime.now() + timedelta(seconds=1296000)).strftime("%Y-%m-%d"), # 1296000: MAX_LOCAL_KEY_AGE in src/tools/subscription.rs
"url": "https://github.com/Jamesits/pve-fake-subscription",
}
data = base64.standard_b64encode(json.dumps(localinfo).encode()).decode()
cat = str(localinfo["checktime"]) + data + shared_key_data
csum = md5_base64_rs(cat)
return key + "\n" + csum + "\n" + data + "\n"
# Key pattern: pbst-xxxxxxxxxx
def activate_pbs(key: str, subscription_file: str) -> None:
# 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])
# write license file # write license file
with open(subscription_file, "w") as f: with open(subscription_file, "w") as f:
@ -108,14 +66,9 @@ 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("pve8p-1145141919", r'pve([1248])([cbsp])-[0-9a-f]{10}', "/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("pmgp-1145141919", r'pmg([cbsp])-[0-9a-f]{10}', "/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")

View File

@ -10,3 +10,4 @@ Persistent=true
[Install] [Install]
WantedBy=timers.target WantedBy=timers.target