103 lines
4.1 KiB
Python
103 lines
4.1 KiB
Python
#!/usr/bin/env python3
|
|
import os
|
|
import base64
|
|
from cryptography.hazmat.primitives.asymmetric import ec
|
|
from cryptography.hazmat.primitives import serialization
|
|
|
|
def generate_vapid_keys():
|
|
"""
|
|
Generate VAPID keys and update .env file, preserving existing variables.
|
|
Only regenerates keys if they are missing or empty.
|
|
"""
|
|
# Read existing .env file if it exists
|
|
env_vars = {}
|
|
if os.path.exists('.env'):
|
|
with open('.env', 'r') as f:
|
|
for line in f:
|
|
line = line.strip()
|
|
if line and not line.startswith('#') and '=' in line:
|
|
key, value = line.split('=', 1)
|
|
env_vars[key.strip()] = value.strip()
|
|
|
|
# Check if we need to generate new keys
|
|
need_new_keys = (
|
|
'VAPID_PRIVATE_KEY' not in env_vars or
|
|
'VAPID_PUBLIC_KEY' not in env_vars or
|
|
not env_vars.get('VAPID_PRIVATE_KEY') or
|
|
not env_vars.get('VAPID_PUBLIC_KEY')
|
|
)
|
|
|
|
if need_new_keys:
|
|
# Generate EC private key
|
|
private_key = ec.generate_private_key(ec.SECP256R1())
|
|
|
|
# Serialize private key to PEM format
|
|
private_pem = private_key.private_bytes(
|
|
encoding=serialization.Encoding.PEM,
|
|
format=serialization.PrivateFormat.PKCS8,
|
|
encryption_algorithm=serialization.NoEncryption()
|
|
).decode('utf-8')
|
|
|
|
# Format for .env file (replace newlines with \n)
|
|
env_private_key = private_pem.strip().replace('\n', '\\n')
|
|
|
|
# Get public key
|
|
public_key = private_key.public_key()
|
|
public_key_bytes = public_key.public_bytes(
|
|
encoding=serialization.Encoding.X962,
|
|
format=serialization.PublicFormat.UncompressedPoint
|
|
)
|
|
|
|
# Store keys
|
|
env_vars['VAPID_PRIVATE_KEY'] = env_private_key # Single-line format
|
|
env_vars['VAPID_PUBLIC_KEY'] = base64.urlsafe_b64encode(public_key_bytes).decode('utf-8')
|
|
|
|
print("New VAPID keys generated in .env-compatible format.")
|
|
else:
|
|
print("Existing VAPID keys found - no changes made.")
|
|
# Verify existing key format
|
|
if '-----BEGIN PRIVATE KEY-----' not in env_vars['VAPID_PRIVATE_KEY']:
|
|
print("Warning: Existing private key doesn't appear to be in PEM format!")
|
|
|
|
# Ensure we have all required configuration variables with defaults if missing
|
|
defaults = {
|
|
# Flic Button Configuration
|
|
'FLIC_BUTTON1_SERIAL': env_vars.get('FLIC_BUTTON1_SERIAL', 'your_button1_serial'),
|
|
'FLIC_BUTTON2_SERIAL': env_vars.get('FLIC_BUTTON2_SERIAL', 'your_button2_serial'),
|
|
'FLIC_BUTTON3_SERIAL': env_vars.get('FLIC_BUTTON3_SERIAL', 'your_button3_serial'),
|
|
|
|
# Subscription Storage
|
|
'SUBSCRIPTIONS_FILE': env_vars.get('SUBSCRIPTIONS_FILE', 'data/subscriptions.json'),
|
|
|
|
# Logging Configuration
|
|
'LOG_LEVEL': env_vars.get('LOG_LEVEL', 'INFO'),
|
|
|
|
# VAPID Claim (email)
|
|
'VAPID_CLAIM_EMAIL': env_vars.get('VAPID_CLAIM_EMAIL', 'mailto:your-email@example.com')
|
|
}
|
|
|
|
# Update env_vars with defaults for any missing keys
|
|
env_vars.update({k: v for k, v in defaults.items() if k not in env_vars})
|
|
|
|
# Write back to .env file
|
|
with open('.env', 'w') as f:
|
|
f.write("# VAPID Keys for Web Push\n")
|
|
f.write(f"VAPID_PRIVATE_KEY={env_vars['VAPID_PRIVATE_KEY']}\n")
|
|
f.write(f"VAPID_PUBLIC_KEY={env_vars['VAPID_PUBLIC_KEY']}\n\n")
|
|
|
|
f.write("# Flic Button Configuration\n")
|
|
f.write(f"FLIC_BUTTON1_SERIAL={env_vars['FLIC_BUTTON1_SERIAL']}\n")
|
|
f.write(f"FLIC_BUTTON2_SERIAL={env_vars['FLIC_BUTTON2_SERIAL']}\n")
|
|
f.write(f"FLIC_BUTTON3_SERIAL={env_vars['FLIC_BUTTON3_SERIAL']}\n\n")
|
|
|
|
f.write("# Subscription Storage\n")
|
|
f.write(f"SUBSCRIPTIONS_FILE={env_vars['SUBSCRIPTIONS_FILE']}\n\n")
|
|
|
|
f.write("# Logging Configuration\n")
|
|
f.write(f"LOG_LEVEL={env_vars['LOG_LEVEL']}\n\n")
|
|
|
|
f.write("# VAPID Claim Email\n")
|
|
f.write(f"VAPID_CLAIM_EMAIL={env_vars['VAPID_CLAIM_EMAIL']}\n")
|
|
|
|
if __name__ == '__main__':
|
|
generate_vapid_keys() |