# Pull request proposal: automatic certificate renewal

**URL:** <https://discourse.nodered.org/t/pull-request-proposal-automatic-certificate-renewal/21282>\
**Category:** Feature Requests\
**Created:** [4 February 2020 21:26 UTC](https://discourse.nodered.org/t/pull-request-proposal-automatic-certificate-renewal/21282 "2020-02-04T21:26:45Z")\
**Posts on this page:** 1\
**Showing post:** 14

<div class="post-metadata">

**Author:** ![BartButenaers](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bartbutenaers/32/10476_2.png) [@BartButenaers](https://discourse.nodered.org/u/BartButenaers)\
**Post date:** [19 March 2020 20:32 UTC](https://discourse.nodered.org/t/pull-request-proposal-automatic-certificate-renewal/21282/14 "2020-03-19T20:32:21Z")

</div>

> [@knolleary](#):
>
> I think it would be better if it were all under the https setting and the cert properties can either be the cert content itself (as is today), or a function. If it's a function and a refresh interval is also specified under the HTTPS property, then we will call it as needed.

Hey Nick,  
Some delay due to a surgery...  
Have the third implementation already running a couple of weeks on my RPI, and had no issues yet...

The _ **settings.js** _ file now looks like this:

```auto
    // The following property can be used to enable HTTPS
    // See http://nodejs.org/api/https.html#https_https_createserver_options_requestlistener
    // for details on its contents.
    // See the comment at the top of this file on how to load the `fs` module used by this setting.
    //https: {
    // key: fs.readFileSync('privkey.pem'),
    // cert: fs.readFileSync('cert.pem')
    //},
    // This 'https' property can also be a function. For example for automatic certificate renewal 
    // (see the 'credentialRenewalTime' property below), this property needs to be a function:
    //https: function() {
    // return {
    // key: fs.readFileSync('privkey.pem'),
    // cert: fs.readFileSync('cert.pem')
    // }
    //},

    // The following property can be used to load renewed credential files at regular time intervals (seconds).
    // Prerequisite: the 'https' session should be enabled (based on a function)!
    // Caution: NodeJs version 11 or above is required to use this option!
    //credentialRenewalTime: 3600,

```

When the _'credentialRenewalTime'_ is activated, the _'https'_ property MUST be a function. Otherwise the OLD file contents (cached by 'require') will be reused over and over again. I think that some users might forget about this, and will not understand why the certificate isn't renewed in their browser. Therefore I have decided to let the renewal fail (with console log) in that case, to minimize the risc for such mistakes:

And the _ **red.js** _ file now looks like this:

```auto
if (settings.https) {
    var startupHttps = settings.https;
    
    if (typeof startupHttps === "function") {
        // Get the result of the function, because createServer doesn't accept functions as input
        startupHttps = startupHttps();
    }  

    server = https.createServer(startupHttps,function(req,res) {app(req,res);});
    
    // Setup automatic certificate renewal for NodeJs version 11 and above
    if (settings.credentialRenewalTime) {
        if (server.setSecureContext) {
            console.log("Checking renewed credentials every " + parseInt(settings.credentialRenewalTime) + " seconds.");
            setInterval(function () {
                try {
                    //console.log("Checking for renewed credentials.");
                    var renewedHttps = settings.https;
                    
                    if (typeof renewedHttps !== "function") {
                        console.log("Cannot renew credentials when the https property isn't a function.");
                        return;
                    }
                    
                    // Get the result of the function, because createServer doesn't accept functions as input
                    renewedHttps = renewedHttps();
                    
                    if (!renewedHttps.key || !renewedHttps.cert) {
                        console.log("Cannot renew credentials when the https property function doesn't return a 'key' and 'cert'.");
                        return;
                    }
                        
                    // Only update the credentials in the server when key or cert has changed
                    if(!server.key || !server.cert || !server.key.equals(renewedHttps.key) || !server.cert.equals(renewedHttps.cert)) {
                        server.setSecureContext(renewedHttps);
                        console.log("The credentials have been renewed.");
                    }
                } catch(err) {
                    console.log("Cannot renew the credentials: " + err);
                }
            }, parseInt(settings.credentialRenewalTime) * 1000);
        } else {
            console.log("Cannot renew credentials automatically. NodeJs version 11 or above is required.");
        }
    }
} else {
    server = http.createServer(function(req,res) {app(req,res);});
}

```

Don't think there is any impact on the mechanism as is today: as long as the _'https'_ function isn't a function and the _'credentialRenewalTime'_ isn't activated, it should run like it used to do in the past...

I have added a check to make sure the file contents have _ **changed** _, before loading them into the webserver. Just to be sure that we don't have any impact on the running server when the file contents haven't been renewed. That way it is even safe to set the _'credentialRenewalTime'_ property to run much more often, if that should be required for some use case ...

Hopefully this implementation finally fits the "_clean API"_ test?

Thanks for reviewing!  
Bart

---

_[View the full topic](https://discourse.nodered.org/t/pull-request-proposal-automatic-certificate-renewal/21282)._
