diff --git a/imageroot/actions/upload-certificate/30certificate_changed b/imageroot/actions/upload-certificate/30certificate_changed new file mode 100755 index 0000000..dbc7432 --- /dev/null +++ b/imageroot/actions/upload-certificate/30certificate_changed @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 + +# +# Copyright (C) 2025 Nethesis S.r.l. +# SPDX-License-Identifier: GPL-3.0-or-later +# + +import os +import json +import agent +import sys +import base64 +from cryptography import x509 +from cryptography.hazmat.backends import default_backend + + +def main(): + request = json.load(sys.stdin) + bcert = base64.b64decode(request["certFile"]) + changed_dns_names = extract_cert_hostnames(bcert) + notify_certificate_changed_event(changed_dns_names) + +def extract_cert_hostnames(cert_data : bytearray) -> set: + """ + Extract the subject common name and subject alternative names (SAN) + from a PEM certificate. + + :param cert_data: Certificate, PEM-encoded. + :return: A set of certified host names. + """ + cert = x509.load_pem_x509_certificate(cert_data, default_backend()) + hostnames = set() + # Extract Common Name (CN) from the Subject field + subject = cert.subject + cn = subject.get_attributes_for_oid(x509.NameOID.COMMON_NAME) + if cn: + hostnames.add(cn[0].value) + # Extract Subject Alternative Names (SANs), if any + try: + ext = cert.extensions.get_extension_for_oid(x509.ExtensionOID.SUBJECT_ALTERNATIVE_NAME) + san = ext.value + hostnames.update(san.get_values_for_type(x509.DNSName)) + except x509.ExtensionNotFound: + pass + return hostnames + +def notify_certificate_changed_event(changed_dns_names): + rdb = agent.redis_connect(privileged=True) + rdb.publish(f"{os.environ['AGENT_ID']}/event/certificate-changed", json.dumps({ + "node_id": int(os.environ['NODE_ID']), + "module_id": os.environ['MODULE_ID'], + "names": list(changed_dns_names), + })) + +if __name__ == "__main__": + main()