Files
Investidor-V2/tools/portal-country-https-active-cert.py
nala 287e991486
tests / ci (push) Waiting to run
oportunidades 7
2026-10-13 11:40:29 +02:00

39 lines
4.4 KiB
Python

"""Prepare a separate proposed local active certificate, without trusting or installing it."""
from pathlib import Path
from datetime import datetime,timedelta,timezone
import json
from cryptography import x509
from cryptography.x509.oid import NameOID,ExtendedKeyUsageOID
from cryptography.hazmat.primitives import hashes,serialization
from cryptography.hazmat.primitives.asymmetric import rsa
ROOT=Path(__file__).resolve().parent.parent;PRIVATE=ROOT/'storage/app/private/investmoz-v2/portal-audit'
meta=json.loads((PRIVATE/'country-https-latest.json').read_text());work=Path(meta['work'])/'active-tls-prepared';work.mkdir(exist_ok=False)
out=ROOT/'outputs/investmoz-country02-https-20261011';now=datetime.now(timezone.utc)
ca_key=rsa.generate_private_key(public_exponent=65537,key_size=2048);key=rsa.generate_private_key(public_exponent=65537,key_size=2048)
name=x509.Name([x509.NameAttribute(NameOID.COMMON_NAME,'InvestMoz portal-investidor.test local 20261011')])
ca=(x509.CertificateBuilder().subject_name(name).issuer_name(name).public_key(ca_key.public_key()).serial_number(x509.random_serial_number())
.not_valid_before(now-timedelta(minutes=5)).not_valid_after(now+timedelta(days=365))
.add_extension(x509.BasicConstraints(ca=True,path_length=0),True).add_extension(x509.KeyUsage(False,False,False,False,False,True,True,False,False),True)
.add_extension(x509.NameConstraints([x509.DNSName('portal-investidor.test')],None),True).sign(ca_key,hashes.SHA256()))
leaf=(x509.CertificateBuilder().subject_name(x509.Name([x509.NameAttribute(NameOID.COMMON_NAME,'portal-investidor.test')])).issuer_name(name)
.public_key(key.public_key()).serial_number(x509.random_serial_number()).not_valid_before(now-timedelta(minutes=5)).not_valid_after(now+timedelta(days=90))
.add_extension(x509.BasicConstraints(ca=False,path_length=None),True).add_extension(x509.SubjectAlternativeName([x509.DNSName('portal-investidor.test')]),False)
.add_extension(x509.ExtendedKeyUsage([ExtendedKeyUsageOID.SERVER_AUTH]),False).add_extension(x509.KeyUsage(True,False,True,False,False,False,False,False,False),True)
.sign(ca_key,hashes.SHA256()))
assert key.public_key().public_bytes(serialization.Encoding.DER,serialization.PublicFormat.SubjectPublicKeyInfo)==leaf.public_key().public_bytes(serialization.Encoding.DER,serialization.PublicFormat.SubjectPublicKeyInfo)
(work/'portal-investidor.test-key.pem').write_bytes(key.private_bytes(serialization.Encoding.PEM,serialization.PrivateFormat.PKCS8,serialization.NoEncryption()))
(work/'portal-investidor.test-fullchain.pem').write_bytes(leaf.public_bytes(serialization.Encoding.PEM)+ca.public_bytes(serialization.Encoding.PEM))
(work/'portal-investidor.test-ca.cer').write_bytes(ca.public_bytes(serialization.Encoding.DER))
public=out/'certificados-publicos';public.mkdir(exist_ok=True)
for name in ['portal-investidor.test-ca.cer','portal-investidor.test-fullchain.pem']:(public/name).write_bytes((work/name).read_bytes())
cert={'prepared_not_installed':True,'prepared_not_trusted':True,'SAN':['portal-investidor.test'],'issuer':ca.subject.rfc4514_string(),'root_thumbprint':ca.fingerprint(hashes.SHA1()).hex().upper(),
'root_sha256':ca.fingerprint(hashes.SHA256()).hex(),'leaf_sha256':leaf.fingerprint(hashes.SHA256()).hex(),'leaf_valid_until':leaf.not_valid_after_utc.isoformat(),
'root_valid_until':ca.not_valid_after_utc.isoformat(),'private_key_public_key_matches':True,'private_key_kept_out_of_bundle':True,'signing_key_not_persisted':True,
'deployment_private_directory':'C:/Users/macbook/.config/investmoz/tls','active_trust_store_changed':False,'qa_ca_not_reused':True,
'renewal':'Before leaf expiry prepare new certificate and trust chain, review/retest before replacement. If using an organization CA instead, seal another configuration hash before applying.'}
(out/'certificado-ativo-proposto.json').write_text(json.dumps(cert,ensure_ascii=False,indent=2),encoding='utf-8')
plan=json.loads((out/'plano-https-ativo.json').read_text());plan['certificate_required'].update(cert);plan['certificate_required'].pop('issuer_and_expiry',None)
plan['code_hash']=json.loads(Path(json.loads((PRIVATE/'country-https-backup-latest.json').read_text())['path']).read_text())['code_hash']
(out/'plano-https-ativo.json').write_text(json.dumps(plan,ensure_ascii=False,indent=2),encoding='utf-8')
print(json.dumps({'result':'active certificate prepared privately; not installed/trusted','public_metadata':str(out/'certificado-ativo-proposto.json'),'active_changes':0}))