Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google Firebase SSL Certificate - My certificate has a large number of other websites listed

Problem: Other domains are listed in my Google Firebase SSL certificate.

I created a firebase project to test firebase authentication emails from Cloud Functions. firebase.jhanley.com

I have separate code that runs in Cloud Functions that validates SSL certificates for each domain that I own / manage (code below). The primary purpose of this code is to send an email when a domain's SSL certificate is about to expire. Some of our SSL certificates must be renewed manually.

The problem is that my code that checks the SSL certificate is returning a huge number of other domain names for my SSL certificate. When I look at the SSL certificate with Chrome, I also see these other domain names. I do want my site associated with these other sites.

A reduced list of the domains that I see in my SSL certificate for Firebase:

2r5consultoria.com.br
addlix.com
admin.migrationcover.ae
admin.thermoply.com
akut-med.zeitnachweise.de
...
firebase.jhanley.com
...

Q) Why is this happening with Firebase SSL and is there a solution?

Q) Does Firebase support installing your own SSL certificate?

Python 3.x code that runs in Cloud Functions that processes SSL certificates by connecting to each domain name from a list.

Note: This code does not have any (known) problems. I am including the source code to create added value for others in the community.

""" Routines to process SSL certificates """

import  sys
import  datetime
import  socket
import  ssl
import  time
import  myhtml

g_email_required = False    # This is set during processing if a warning or error was detected

def get_email_requred():
    return g_email_required

def ssl_get_cert(hostname):
    """ This function returns an SSL certificate from a host """

    context = ssl.create_default_context()

    conn = context.wrap_socket(
        socket.socket(socket.AF_INET),
        server_hostname=hostname)

    # 3 second timeout because Google Cloud Functions has runtime limitations
    conn.settimeout(3.0)

    try:
        conn.connect((hostname, 443))
    except Exception as ex:
        print("{}: Exception: {}".format(hostname, ex), file=sys.stderr)
        return False, str(ex)

    host_ssl_info = conn.getpeercert()

    return host_ssl_info, ''

def get_ssl_info(host):
    """ This function retrieves the SSL certificate for host """
    # If we receive an error, retry up to three times waiting 10 seconds each time.

    retry = 0
    err = ''

    while retry < 3:
        ssl_info, err = ssl_get_cert(host)

        if ssl_info is not False:
            return ssl_info, ''

        retry += 1
        print('    retrying ...')
        time.sleep(10)

    return False, err

def get_ssl_issuer_name(ssl_info):
    """ Return the IssuerName from the SSL certificate """

    issuerName = ''

    issuer = ssl_info['issuer']

    # pylint: disable=line-too-long
    # issuer looks like this:
    # This is a set of a set of a set of key / value pairs.
    # ((('countryName', 'US'),), (('organizationName', "Let's Encrypt"),), (('commonName', "Let's Encrypt Authority X3"),))

    for item in issuer:
        # item will look like this as it goes thru the issuer set
        # Note that this is a set of a set
        #
        # (('countryName', 'US'),)
        # (('organizationName', "Let's Encrypt"),)
        # (('commonName', "Let's Encrypt Authority X3"),)

        s = item[0]

        # s will look like this as it goes thru the isser set
        # Note that this is now a set
        #
        # ('countryName', 'US')
        # ('organizationName', "Let's Encrypt")
        # ('commonName', "Let's Encrypt Authority X3")

        # break the set into "key" and "value" pairs
        k = s[0]
        v = s[1]

        if k == 'organizationName':
            if v != '':
                issuerName = v
                continue

        if k == 'commonName':
            if v != '':
                issuerName = v

    return issuerName

def get_ssl_subject_alt_names(ssl_info):
    """ Return the Subject Alt Names """

    altNames = ''

    subjectAltNames = ssl_info['subjectAltName']

    index = 0
    for item in subjectAltNames:
        altNames += item[1]
        index += 1

        if index < len(subjectAltNames):
            altNames += ', '

    return altNames

def process_hostnames(msg_body, hostnames, days_left):
    """ Process the SSL certificate for each hostname """

    # pylint: disable=global-statement
    global g_email_required

    ssl_date_fmt = r'%b %d %H:%M:%S %Y %Z'

    for host in hostnames:
        f_expired = False

        print('Processing host:', host)

        ssl_info, err = get_ssl_info(host)

        if ssl_info is False:
            msg_body = myhtml.add_row(msg_body, host, err, '', '', '', True)
            g_email_required = True
            continue

        #print(ssl_info)

        issuerName = get_ssl_issuer_name(ssl_info)

        altNames = get_ssl_subject_alt_names(ssl_info)

        l_expires = datetime.datetime.strptime(ssl_info['notAfter'], ssl_date_fmt)

        remaining = l_expires - datetime.datetime.utcnow()

        if remaining < datetime.timedelta(days=0):
            # cert has already expired - uhoh!
            cert_status = "Expired"
            f_expired = True
            g_email_required = True
        elif remaining < datetime.timedelta(days=days_left):
            # expires sooner than the buffer
            cert_status = "Time to Renew"
            f_expired = True
            g_email_required = True
        else:
            # everything is fine
            cert_status = "OK"
            f_expired = False

        msg_body = myhtml.add_row(msg_body, host, cert_status, str(l_expires), issuerName, altNames, f_expired)

    return msg_body
like image 430
John Hanley Avatar asked Nov 26 '18 01:11

John Hanley


People also ask

Can I use the same SSL certificate on multiple sites?

The simple answer is a resounding Yes! You absolutely can use one SSL certificate for multiple domains — or one SSL certificate for multiple subdomains in addition to domains.

Can you have multiple SSL certificates for one domain?

You can install multiple SSL certificates on a domain, but first a word of caution. A lot of people want to know whether you can install multiple SSL certificates on a single domain. The answer is yes.

How many SSL certificates can a domain have?

In most cases, you'll only need one SSL certificate for your domain. But in certain cases, you might need two certificates for a single domain.


1 Answers

This is happening because Firebase will automatically create shared certificates for customers. This does not represent a security risk for your site, as Firebase retains full control of the certificate private keys. Certificates are shared to allow us to offer HTTPS + custom domains without an additional fee for our free plan customers.

If you are on the Blaze (pay-as-you-go) plan for your project, you can send a request to Firebase support and we can migrate you to a dedicated certificate. This is only available for Blaze plan customers.

Firebase Hosting does not currently support uploading custom certificates. If this is a use case that's important to you, I'd recommend filing a feature request (again, through Firebase support) so that we can evaluate it for future improvements to the product.

like image 181
Michael Bleigh Avatar answered Sep 27 '22 16:09

Michael Bleigh