Yesterday I finally lost my patience with the developer’s eternal problem of having to skip the untrusted self-signed certificate interstitial warning screens, and so I decided to solve it properly<\/em>. The problem has got worse recently due to a combination of changes in the world and my projects:<\/p>\n Being RSI conscious and generally lazy, having to click three more things each dev-cycle is a major pain. Also the fact that Browsersync stops working every time too makes it even more work to resume – involving double-clicking the failed GET in the network tab, and accepting the same warning message in a temporary browser window.<\/p>\n After reading the Chrome team’s official vision<\/a>, and with my recent experience in setting up a personal CA for a business to allow them to use client-certificates for authenticating remote staff, I decided the best, most permanent solution is to use a personal CA added to the trust root of the local host, which signs the local cert – instead of self-signing.<\/p>\n While the process is actually easy to perform, I found as usual the historical complexities of the OpenSSL command line options and configuration files, plus the lack of a single article on this specific approach, meant I had to fiddle around for a while to get it right.<\/p>\n Things that made it tricky:<\/p>\n I started from this simplified gist<\/a>\u00a0and my knowledge of the fabulously professional and detailed OpenSSL DIY-CA guide by Jamie Nguyen<\/a>\u00a0(aimed at production quality so the setup is a bit over-complex for local dev).<\/p>\n The configuration file\u00a0mysite.local.conf<\/span>, which contains sections for both the “req -config” option and the “x509 -extfile” option is as follows.<\/p>\n The important part for generating a CSR with SANs with “req” command and then making the certificate signed with the CA with “x509” command,\u00a0 is for the “req” command the\u00a0config line “req_extensions = v3_ca” tells it to find the extensions section with the SAN, but for “x509” it’s the “-extensions v3_ca<\/span>” option which points to the same section in the “-extfile<\/span>” file. This took me a while to get right – although it seems obvious now!<\/p>\n The process – to create a CA and create a certificate for the local site with the above SANs:<\/p>\n 1. Make root CA Key<\/span><\/p>\n 2. Create and self-sign the CA Root Certificate<\/span><\/p>\n Once that’s done, this CA can be used to issue many site certificates.<\/p>\n 3. Make local site key<\/span><\/p>\n 4. Make certificate request (CSR)<\/span><\/p>\n 5. Generate and sign the site certificate.<\/span><\/p>\n 6. Install the certificates.<\/p>\n The critical step which makes all the difference to this approach is getting your host to trust the personal CA. This is slightly different for Windows, Mac and Unix, or iOS, but the principle is the same – you add it to the list of “trusted roots”.<\/p>\n In Mac, you can open a .crt file which will add it into your Keychain Access, under Login Keychain > Certificates Category.<\/p>\n Then you must open the “Trust” section and set it to “Always Trust”.<\/p>\n Once you have done this any site certificate signed by this fake CA will be trusted by your entire machine<\/em> – in theory all applications, all browsers and the O\/S itself. This is important to developers using various tools – IDEs, Postman, CURL or other API clients. It’s not just a specific solution for Chrome (like startup flags).<\/p>\n After copying the site certificate and key into place in my ExpressJS app, and restarting finally Chrome shows the valid “Secure” icon! No more interstitials…<\/p>\n If you inspect the certificate in Chrome, you should see both the site cert and the CA cert are both valid and trusted.<\/p>\n The site (the SANs are under Details):<\/p>\n The CA:<\/p>\n <\/p>\n I also had to add it to <\/span>Browsersync<\/span><\/a>\u00a0configuration:<\/span><\/p>\n Which also started working again on Gulp restart.<\/span><\/p>\n Now this is working and stable, it really has made a difference to my workflow – just one less level of friction and annoyance in my daily grind. I’ll have to find something else to get annoyed about now.<\/p>\n","protected":false},"excerpt":{"rendered":" Yesterday I finally lost my patience with the developer’s eternal problem of having to skip the untrusted self-signed certificate interstitial warning screens, and so I decided to solve it properly. The problem has got worse recently due to a combination … Continue reading \n
\n
[req]\r\ndefault_bits = 2048\r\nprompt = no\r\ndefault_md = sha256\r\ndistinguished_name = req_distinguished_name\r\nreq_extensions = v3_ca\r\n\r\n[req_distinguished_name]\r\nC = AU\r\nST = SYDNEY\r\nL = NSW\r\nO = MyOrganisation\r\nOU = MyOrganisation Unit\r\nCN = *.local\r\n\r\n[v3_ca]\r\nbasicConstraints = CA:FALSE\r\nkeyUsage = digitalSignature, keyEncipherment\r\nsubjectAltName = @alternate_names\r\n\r\n# I added localhost wildcards for general compatibility with older projects.\r\n[alternate_names]\r\nDNS.1 = localhost\r\nDNS.2 = *.localhost\r\nDNS.2 = *.local\r\nDNS.3 = mysite.local<\/pre>\n
openssl genrsa -des3 -out rootCA.key 4096\r\n> secret\r\n<\/span><\/pre>\nopenssl req -x509 -new -nodes -key rootCA.key -sha256 -days 1024 -out rootCA.crt -config mysite.local.conf<\/span><\/pre>\nopenssl genrsa -out mysite.local.key 2048<\/span><\/pre>\nopenssl req -new -key mysite.local.key -out mysite.local.csr -config mysite.local.conf<\/span><\/pre>\nopenssl x509 -req -in mysite.local.csr -CA rootCA.crt -CAkey rootCA.key -CAcreateserial \\\r\n -out mysite.local.crt -days 500 -sha256 -extfile mysite.local.conf -extensions v3_ca\r\n<\/span>> secret<\/span><\/pre>\n
<\/a><\/p>\n
<\/a><\/p>\n
<\/a><\/p>\nbrowserSync.init({<\/span>\r\n https: {<\/span>\r\n key: \"..\/ssl\/mysite.local.key\",<\/span>\r\n cert: \"..\/ssl\/mysite.local.crt\"<\/span>\r\n },<\/span>\r\n});<\/span><\/pre>\n