44 lines
3.4 KiB
Python
44 lines
3.4 KiB
Python
"""Generate private local configuration and a CA for the device HTTPS channel."""
|
|
import argparse
|
|
import datetime
|
|
import ipaddress
|
|
import json
|
|
import pathlib
|
|
import secrets
|
|
import os
|
|
from cryptography import x509
|
|
from cryptography.hazmat.primitives import hashes, serialization
|
|
from cryptography.hazmat.primitives.asymmetric import rsa
|
|
from cryptography.x509.oid import NameOID
|
|
|
|
p = argparse.ArgumentParser()
|
|
p.add_argument('--ip', required=True)
|
|
p.add_argument('--pve-hostname', required=True, help='DNS name present in the PVE certificate')
|
|
p.add_argument('--pve-ip', required=True)
|
|
args = p.parse_args()
|
|
ip = ipaddress.ip_address(args.ip)
|
|
root = pathlib.Path(__file__).resolve().parent.parent
|
|
target = root / '.local/live'
|
|
target.mkdir(parents=True, exist_ok=True)
|
|
if (target / '.env').exists():
|
|
raise RuntimeError('Existing configuration retained; edit it deliberately instead of regenerating secrets')
|
|
access = json.loads((target / 'pve-access.json').read_text())
|
|
access['PVE_URL']=f'https://{args.pve_hostname}:8006'
|
|
now = datetime.datetime.now(datetime.timezone.utc)
|
|
key = rsa.generate_private_key(public_exponent=65537, key_size=3072)
|
|
name = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, 'VDI local device CA')])
|
|
ca = x509.CertificateBuilder().subject_name(name).issuer_name(name).public_key(key.public_key()).serial_number(x509.random_serial_number()).not_valid_before(now-datetime.timedelta(minutes=5)).not_valid_after(now+datetime.timedelta(days=3650)).add_extension(x509.BasicConstraints(ca=True,path_length=0),critical=True).add_extension(x509.KeyUsage(True,False,False,False,False,True,True,False,False),critical=True).sign(key,hashes.SHA256())
|
|
server_key = rsa.generate_private_key(public_exponent=65537, key_size=3072)
|
|
server = x509.CertificateBuilder().subject_name(x509.Name([x509.NameAttribute(NameOID.COMMON_NAME,str(ip))])).issuer_name(name).public_key(server_key.public_key()).serial_number(x509.random_serial_number()).not_valid_before(now-datetime.timedelta(minutes=5)).not_valid_after(now+datetime.timedelta(days=365)).add_extension(x509.BasicConstraints(ca=False,path_length=None),critical=True).add_extension(x509.SubjectAlternativeName([x509.IPAddress(ip),x509.DNSName('localhost')]),critical=False).add_extension(x509.ExtendedKeyUsage([x509.oid.ExtendedKeyUsageOID.SERVER_AUTH]),critical=False).sign(key,hashes.SHA256())
|
|
tls = target / 'tls'; tls.mkdir(exist_ok=True)
|
|
def save_private(path, data):
|
|
path.write_bytes(data); os.chmod(path, 0o600)
|
|
for name, obj in [('ca',key),('server',server_key)]:
|
|
save_private(tls/f'{name}-key.pem', obj.private_bytes(serialization.Encoding.PEM,serialization.PrivateFormat.PKCS8,serialization.NoEncryption()))
|
|
(tls/'ca.pem').write_bytes(ca.public_bytes(serialization.Encoding.PEM))
|
|
(tls/'server.pem').write_bytes(server.public_bytes(serialization.Encoding.PEM)+ca.public_bytes(serialization.Encoding.PEM))
|
|
env = dict(VDI_DB_PASSWORD=secrets.token_hex(24),VDI_JWT_SECRET=secrets.token_hex(48),VDI_ADMIN_USERNAME='admin',VDI_ADMIN_PASSWORD=secrets.token_urlsafe(24),VDI_LIVE_BIND_IP=str(ip),PVE_HOSTNAME=args.pve_hostname,PVE_HOST_IP=str(ipaddress.ip_address(args.pve_ip)),**access)
|
|
save_private(target/'.env', ''.join(f'{k}={v}\n' for k,v in env.items()).encode())
|
|
save_private(target/'admin-login.txt', f'Console: http://127.0.0.1:5182\nUsername: {env["VDI_ADMIN_USERNAME"]}\nPassword: {env["VDI_ADMIN_PASSWORD"]}\nDevice HTTPS: https://{ip}:8443\n'.encode())
|
|
print('Private environment, admin login, CA and HTTPS certificate generated in .local/live')
|