Important note about SSL VPN compatibility for 20.0 MR1 with EoL SFOS versions and UTM9 OS. Learn more in the release notes.

This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Notification on Certificate expiration

Hello,

we have multiple environments of Sophos SG and XG Clusters. As we are not able to check every Cluster itself we automated a notification for WAF Certificate Expiration.

On SG this is built-in but not so on the XG.

I searched a little, and the last thing I think could help is to query it via api.

Is there any possibility to check this?

SNMP would be possible as well...

Any Insights?



This thread was automatically locked due to age.
Parents
  • You can indeed utilize the API for this purpose. However, it's not the most straightforward process since there isn't a direct method to instantly identify expiring certificates. Instead, you'll need to call an API endpoint that provides you with a .tar file. This file contains several components:

    • Entities.xml: Contains certificate information such as names as seen in your GUI.
    • *.pem: The certificate files themselves.
    • *.key: Private keys for the certificates.

    You'll need to extract the contents of the .tar file and then verify the validity of each .pem file.

    Please see the script provided below:

    import logging
    import tarfile
    from io import BytesIO
    import requests
    import urllib3
    import xmltodict
    from cryptography import x509
    from cryptography.hazmat.backends import default_backend
    
    # Setup
    sophos_api_url = 'https://sophos:4444/webconsole/APIController'
    sophos_api_username = 'admin'
    sophos_api_password = 'password'
    ssl_verify = False
    logging.basicConfig(level=logging.INFO)
    urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
    
    # Prepare XML Request
    xml = f"""
    <Request>
      <Login>
        <Username>{sophos_api_username}</Username>
        <Password>{sophos_api_password}</Password>
      </Login>
      <Get>
        <Certificate/>
      </Get>
    </Request>
    """
    
    # Execute API Request
    response = requests.request('GET', sophos_api_url, files={"reqxml": (None, xml)}, verify=ssl_verify)
    
    # Process Answer
    xml_info = {}
    cert_info = {}
    
    # Extract downloaded tar file in memory. The file contains an XML File and several Certificates
    # This script only handles PEM based certificates
    if response.status_code == 200:
        with tarfile.open(fileobj=BytesIO(response.content)) as tar:
            for member in tar.getmembers():
                f = tar.extractfile(member)
                if f:
                    content = f.read()
                    if member.name == "./Entities.xml":
                        try:
                            xml_data = xmltodict.parse(content)
                            for cert in xml_data['Response']['Certificate']:
                                xml_info[cert.get('CertificateFile')] = cert.get('Name')
                        except Exception as e:
                            logging.error(f"Error parsing XML: {e}")
                    else:
                        try:
                            cert = x509.load_pem_x509_certificate(content, default_backend())
                            cert_info[member.name.split('/')[-1]] = cert.not_valid_after_utc
                        except ValueError:
                            logging.warning(f"Skipping non-PEM file: {member.name}")
                        except Exception as e:
                            logging.error(f"Error loading certificate: {e}")
    else:
        logging.error(f"Error downloading file: Status-Code {response.status_code}")
    
    # Merge result dicts
    common_keys = xml_info.keys() & cert_info.keys()
    certificates = {xml_info[key]: cert_info[key] for key in common_keys}
    
    # Output
    for cert_name, valid_until in certificates.items():
        logging.info(f"Certificate Name: {cert_name}, Valid Until: {valid_until.strftime('%Y-%m-%d %H:%M:%S %Z')}")
    

  • Maybe a more performant approach would be to simply CURL the websites, the Firewall is offering and then extract the PEM Date there. This would mean, you dont have to download something, instead do a CURL and use some libs to get the date of the Website. 

    __________________________________________________________________________________________________________________

Reply
  • Maybe a more performant approach would be to simply CURL the websites, the Firewall is offering and then extract the PEM Date there. This would mean, you dont have to download something, instead do a CURL and use some libs to get the date of the Website. 

    __________________________________________________________________________________________________________________

Children
  • I believe that's possibly what   had in mind, but it was dismissed by  . Nonetheless, I consider both approaches to be viable. If you're managing numerous WAF rules with distinct certificates, or providing reverse proxy access to sites inaccessible to your monitoring system, then querying the certificates directly on the firewalls might be more straightforward. From a performance perspective, the API call is not particularly demanding—especially considering that this check would likely be conducted only once a day.

    But basically you're right - the API ideally should offer a more efficient method than simply supplying a collection of files within a .tar archive. To be honest, I've never seen such an approach before. Slight smile

    I just check on a XGS with 12 certificates:

    real 0m0.770s
    user 0m0.104s
    sys 0m0.004s