Use this encryption to apply for a free HTTPS SSL certificate and download it to the server through a Python script for automatic update

Posted by dgwade on Sat, 22 Jan 2022 11:16:47 +0100

Whimsical journey: my original blog is completely knocked by hand, absolutely not carried, and there can be no repetition in the whole network; I have no team, only share for technology lovers, and all content does not involve advertising. All my articles are only published in CSDN and personal blog (must be the domain name of fantasy journey). In addition, they are all stolen!

This article is applicable to individual developers who require automatic deployment after certificate update (server software other than IIS) and can accept a certain cost (19 yuan)

In March last year, the website used SSL certificate, first using Tencent cloud free certificate. Although the certificate is valid for one year, the free version only supports a single domain name, which is very unfriendly to the developers of many small and micro service sites. So I found it on Zhihu To encrypt here( https://letsencrypt.osfipin.com/ ).

This is a package based on Let's Encrypt project. We chose it mainly because of its simple and once and for all verification method and API support, which is convenient for us to deploy to our own server.

If your requirement is SSL certificate management uploaded to Alibaba cloud and other cloud service providers, you can consider it instead of local deployment OHTTPS(https://ohttps.com/) , the operation is more convenient and the cost is close.

We first register the account, then click the three horizontal bars in the upper left corner to obtain points, recharge a certain amount to ensure that the account balance reaches 200 points, and then click points exchange to exchange for VIP. Then apply for the certificate. If you can already use automatic verification, it's best. If not, it doesn't matter. First, it's a little troublesome to configure DNS verification for several times. After the application is completed, it can be changed to automatic verification.

About automatic reaffirmation: it's better if you have money to automatically reaffirmation (it's not expensive, one dollar for each update), but the next method in this article can only use automatic verification, just need you to click the button on the website every time you update.

After following the above operations, you should see an interface like this:

We first manually deploy the certificate, then remember the given automatic verification ID, and then we can code it!

The code is very simple, more scalable than the official script, and compatible with Linux and Windows at the same time. What needs to be changed is at the beginning, and what should be mentioned is explained in the notes.

From 13 days before each expiration, the program will pull the certificate every 12 hours until the validity period of the certificate becomes longer (that is, it has been re applied on the official website).

API KEY acquisition: click the three bars in the upper left corner of this encrypted web page, API interface, and create a KEY

##### User Info #####

email = "mail@yixiangzhilv.com"  # To encrypt the registered mailbox
key = "APIKEY"  # Your API KEY
cids = ["29dwnz"]  # The automatic authentication ID of each certificate that needs to be updated
crt_files = ["E:/Desktop/fullchain.crt"]  # The local path of the certificate file to be updated (the order corresponds to cid)
crt_key_files = ["E:/Desktop/private.pem"]  # Certificate key file (corresponding to cid in sequence)
reload_shell = ["nginx -s reload"]  # Commands to execute after updating the certificate

##### End User Info #####

import os
import shutil
import time
import requests as rq
import zipfile

# Build API request parameters
head = {"Authorization": "Bearer %s:%s" % (key, email)}
url = "https://api.osfipin.com/letsencrypt/api/order/down?type=auto&day&id="
# Get fullchain. From the downloaded file CRT and private pem
crt_file_name = "fullchain.crt"
crt_key_file_name = "private.pem"


def unzip(file_name):
    # Unzip the zip file
    zip_file = zipfile.ZipFile(file_name)
    if os.path.isdir(file_name + "_files"):
        pass
    else:
        os.mkdir(file_name + "_files")
    for names in zip_file.namelist():
        zip_file.extract(names, file_name + "_files/")
    zip_file.close()
    return file_name + "_files"


def ftime():
    # Gets the formatted time display
    return time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())


def get_etime(file):
    # Check the validity of crt file and return GMT format string
    return os.popen("openssl x509 -in %s -noout -enddate -checkend 9123200" %
                    file).read().splitlines()[0].split("=")[1]


while True:
    # Traverse all certificate information
    for i in range(len(cids)):
        # Initialization name information
        crt_file = crt_files[i]
        crt_key_file = crt_key_files[i]
        cid = cids[i]

        # Check the current crt file expiration time (etime is in GMT format and etimes is timestamp)
        etime = ""
        etimes = 0
        if os.path.isfile(crt_file):
            etime = get_etime(crt_file)
            etimes = time.mktime(time.strptime(etime, "%b %d %H:%M:%S %Y GMT"))

        # Update within 13 days of expiration
        if etimes - time.time() < 86400 * 13:
            # Download and save the certificate file (zip format)
            r = rq.get(url + cid, headers=head)
            zname = r.headers["Content-Disposition"].split("=")[-1]
            with open(zname, "wb") as f:
                f.write(r.content)

            # Extract and update the file
            fname = unzip(zname)
            shutil.copyfile(fname + "/" + crt_file_name, crt_file)
            shutil.copyfile(fname + "/" + crt_key_file_name, crt_key_file)
            etime = get_etime(crt_file)

            print("%s: Update succeeded. Valid until after update%s. " % (ftime(), etime))

            # Restart the service and delete the downloaded temporary files
            for j in reload_shell:
                os.system(j)
            os.remove(zname)
            shutil.rmtree(fname)
        else:
            print("%s: Current certificate is valid until%s, Not updated yet." % (ftime(), etime))

    # Sleep for 12 hours
    time.sleep(3600 * 12)

Using nohup or screen to suspend the script, you can update the certificate with just a finger every quarter!

Topics: Python Web Development SSL https