Compare commits

..

60 Commits
master ... v2

Author SHA1 Message Date
AJ ONeal 4f9173eb4a retry on bad nonce 2019-05-28 05:15:46 -06:00
AJ ONeal 43ccd091b2 make polling faster, enable status updates 2019-05-28 05:11:00 -06:00
AJ ONeal 52ce530aff fix POST-as-POST 2019-05-28 04:40:59 -06:00
AJ ONeal 96b9cd1a74 fix POST-as-GET 2019-05-28 04:31:50 -06:00
AJ ONeal ed1170fc7c better error handling 2019-05-28 04:18:58 -06:00
AJ ONeal 68ce90afe1 better error handling 2019-05-28 04:08:09 -06:00
AJ ONeal c7a6cafae2 ACME spec compatibility notice 2019-05-23 14:12:24 -06:00
AJ ONeal bb16c69fb8 better logging, update kickoff 2019-05-23 13:50:31 -06:00
AJ ONeal 1998c3d119 log cleanup 2019-05-23 13:36:19 -06:00
AJ ONeal d9da4c0989 multiple domains 2019-05-22 03:44:09 -06:00
AJ ONeal dd9c54c45c multiple domains 2019-05-22 03:33:51 -06:00
AJ ONeal 0405a7db90 using new acme 2019-05-22 02:45:19 -06:00
AJ ONeal 49d5346615 refactor 2019-05-22 02:38:21 -06:00
AJ ONeal 330e0e7832 worked with a domain, yay 2019-05-21 00:59:20 -06:00
AJ ONeal 19cc513174 WIP almost working 2019-05-21 00:37:07 -06:00
AJ ONeal 7484ffcd11 WIP: moving to bluecrypt 2019-05-19 01:10:49 -06:00
AJ ONeal 98c8db8973 WIP: breaking into smaller pieces 2019-05-19 00:21:26 -06:00
AJ ONeal 8ce44bc414 rebrand Root 2019-04-09 07:50:34 +00:00
AJ ONeal ab67741604 rebrand Root 2019-04-09 07:46:59 +00:00
AJ ONeal b7dd224426 update to rootprojects.org 2019-04-08 19:51:33 +00:00
John Shaver 65974b57c1 Merge branch 'live-site' of ssh://git.coolaj86.com:22042/coolaj86/greenlock.html into live-site 2019-03-16 21:58:16 -07:00
John Shaver b1fc2bcc14 fix wildcard certificate verification 2019-03-16 21:51:41 -07:00
AJ ONeal 8d31bf7754 GA -> web-only 2018-11-16 05:50:15 +00:00
AJ ONeal 1c57a342d0 reposition 2018-11-15 06:57:35 +00:00
AJ ONeal f27b386ba4 update legal link (and link to 'us') 2018-11-15 06:55:10 +00:00
AJ ONeal 55a30888ff add privacy policy 2018-11-15 06:50:37 +00:00
AJ ONeal 95e807be73 test key support BEFORE creating keys 2018-11-10 18:50:05 +00:00
AJ ONeal 268f83b49e tested working in firefox 2018-11-10 09:18:59 +00:00
AJ ONeal 09ff0b3adc use the opts we built, duh 2018-11-10 07:58:02 +00:00
AJ ONeal 8a7183ed9c don't eager assign CSR 2018-11-10 07:20:53 +00:00
AJ ONeal a7462db2c8 test ecdsa support, spaces for whitespace 2018-11-09 21:21:40 -07:00
AJ ONeal 2cc5a41268 lint and fix and use domains.generateKeypair 2018-11-09 21:05:53 -07:00
AJ ONeal d63d8e1aed lint 2018-11-09 20:41:41 -07:00
John Shaver 6f188cefb8 Now uses RSA keys for firefox browser. 2018-11-09 13:57:59 -08:00
AJ ONeal bddf85dfe6 Merge branch 'live-site' of ssh://git.coolaj86.com:22042/coolaj86/greenlock.html into live-site 2018-09-17 05:14:03 +00:00
AJ ONeal c6052bcf73 update contact info 2018-09-17 05:13:55 +00:00
John Shaver 78515f165c Fix legal link and preloading files 2018-09-12 09:29:04 -07:00
John Shaver 68253cbe54 You can now tab select check boxes. 2018-09-10 23:39:49 -07:00
John Shaver 9143545389 Added download links for certs and changed some formatting. 2018-08-21 14:15:09 -07:00
John Shaver 3e865a2fb7 Added styling to key/cert page. 2018-08-21 13:10:18 -07:00
John Shaver 6ce81beaec Fixed link to hosted app. 2018-08-21 13:06:27 -07:00
John Shaver c6c06b06f0 First 2 steps down. 2018-08-17 22:21:12 -07:00
John Shaver a32287c3f8 Added a terrible temorary fix to the tables. 2018-08-16 20:24:51 -07:00
John Shaver 6a05569ab5 Some style chages on first/second step. 2018-08-16 20:01:51 -07:00
John Shaver c3c9696799 Progress bar is in place. 2018-08-11 22:15:06 -07:00
John Shaver b86074920a Added Javascript needed warning. 2018-07-26 14:36:47 -07:00
John Shaver 8610baf0e0 fixed blink on loading strait to step2 2018-07-26 13:38:07 -07:00
John Shaver 3cfbc9339b Tied in new homepage with the rest of the app. 2018-07-26 12:55:31 -07:00
John Shaver 62f3d28a71 Some styling updates and created a separate front page. 2018-07-23 14:23:10 -07:00
John Shaver 430b589038 Center, shrink logo. 2018-07-20 14:41:34 -07:00
John Shaver 6d3c3a9e61 No longer fails due to new challenge types. 2018-07-19 15:50:27 -07:00
AJ ONeal 61b2c76822 Merge branch 'master' into live-site 2018-05-14 19:31:54 +00:00
AJ ONeal d0ea6822ea Merge branch 'master' into live-site 2018-05-14 19:26:52 +00:00
AJ ONeal 4bfef46295 Merge branch 'master' into live-site 2018-05-14 18:56:59 +00:00
AJ ONeal 42a589f5c0 add google analytics 2018-05-14 18:55:21 +00:00
AJ ONeal 5d07cec7a3 Merge branch 'master' into live-site 2018-05-14 18:54:05 +00:00
AJ ONeal ceb109e652 fix typo 2018-05-05 04:42:17 +00:00
AJ ONeal ed2739cb20 add line break 2018-05-05 00:01:54 +00:00
AJ ONeal 2be09788ce Merge branch 'master' into live-site 2018-05-05 00:01:03 +00:00
AJ ONeal 3854e6b430 save contact 2018-05-04 23:59:05 +00:00
12 changed files with 3818 additions and 4886 deletions

View File

@ -1,4 +0,0 @@
{
"trailingComma": "none",
"useTabs": true
}

View File

@ -1,8 +1,10 @@
# Greenlock™ in your Browser Greenlock™ in your Browser
=========================
Taking greenlock™ (Let's Encrypt v2 / ACME client) where it's never been before: Your browser! Taking greenlock™ (Let's Encrypt v2 / ACME client) where it's never been before: Your browser!
# Official Site Official Site
=============
This app is available at <https://greenlock.domains>. This app is available at <https://greenlock.domains>.
@ -12,12 +14,14 @@ If it doesn't, please open an issue to let us know why.
We'd much rather improve the app than have a hundred different versions running in the wild. We'd much rather improve the app than have a hundred different versions running in the wild.
However, in keeping to our values we've released the source for others to inspect, improve, and modify. However, in keeping to our values we've released the source for others to inspect, improve, and modify.
# Trademark Notice Trademark Notice
================
Greenlock&trade; is our trademark. If you do host your own copy of this app, Greenlock&trade; is our trademark. If you do host your own copy of this app,
please do provide attribution, but please also use your branding. please do provide attribution, but please also use your branding.
# Install Install
=======
```bash ```bash
git clone ssh://gitea@git.coolaj86.com:22042/coolaj86/greenlock.html.git git clone ssh://gitea@git.coolaj86.com:22042/coolaj86/greenlock.html.git
@ -26,7 +30,8 @@ pushd greenlock.html/
popd popd
``` ```
# Usage Usage
=====
Simply host from your webserver. Simply host from your webserver.

View File

@ -1,99 +1,62 @@
<!DOCTYPE html>
<html> <html>
<head> <head>
<title>Greenlock&trade;</title> <title>Greenlock&trade;</title>
<meta <meta property="og:image" content="https://greenlock.domains/img/greenlock-mark-400x400.png" />
property="og:image"
content="https://greenlock.domains/img/greenlock-mark-400x400.png"
/>
<style> <style>
@font-face { @font-face {
font-family: "Source Sans Pro"; font-family: 'Source Sans Pro';
font-style: normal; font-style: normal;
font-display: block; font-display: block;
font-weight: 400; font-weight: 400;
src: local("Source Sans Pro Regular"), local("SourceSansPro-Regular"), src: local('Source Sans Pro Regular'), local('SourceSansPro-Regular'), url(./fonts/6xK3dSBYKcSV-LCoeQqfX1RYOo3qOK7l.woff2) format('woff2');
url(./fonts/6xK3dSBYKcSV-LCoeQqfX1RYOo3qOK7l.woff2) format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193,
U+2212, U+2215, U+FEFF, U+FFFD;
} }
@font-face { @font-face {
font-family: "Source Sans Pro"; font-family: 'Source Sans Pro';
font-style: normal; font-style: normal;
font-weight: 700; font-weight: 700;
font-display: block; font-display: block;
src: local("Source Sans Pro Bold"), local("SourceSansPro-Bold"), src: local('Source Sans Pro Bold'), local('SourceSansPro-Bold'), url(./fonts/6xKydSBYKcSV-LCoeQqfX1RYOo3ig4vwlxdu.woff2) format('woff2');
url(./fonts/6xKydSBYKcSV-LCoeQqfX1RYOo3ig4vwlxdu.woff2) unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
format("woff2");
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193,
U+2212, U+2215, U+FEFF, U+FFFD;
} }
@font-face { @font-face {
font-family: "Source Code Pro"; font-family: 'Source Code Pro';
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
src: local("Source Code Pro"), local("SourceCodePro-Regular"), src: local('Source Code Pro'), local('SourceCodePro-Regular'), url(./fonts/HI_SiYsKILxRpg3hIP6sJ7fM7PqlPevW.woff2) format('woff2');
url(./fonts/HI_SiYsKILxRpg3hIP6sJ7fM7PqlPevW.woff2) format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193,
U+2212, U+2215, U+FEFF, U+FFFD;
} }
</style> </style>
<link href="styles/main.css" rel="stylesheet" /> <link href="styles/main.css" rel="stylesheet">
<link <link rel="preload" href="./fonts/6xKydSBYKcSV-LCoeQqfX1RYOo3ig4vwlxdu.woff2" as="font" crossorigin="anonymous">
rel="preload" <link rel="preload" href="./fonts/6xK3dSBYKcSV-LCoeQqfX1RYOo3qOK7l.woff2" as="font" crossorigin="anonymous">
href="./fonts/6xKydSBYKcSV-LCoeQqfX1RYOo3ig4vwlxdu.woff2"
as="font" <link rel="preload" href="./fonts/HI_SiYsKILxRpg3hIP6sJ7fM7PqlPevW.woff2" as="font" crossorigin="anonymous">
crossorigin="anonymous" <link rel="preload" href="./js/bluecrypt-acme.js" as="script">
/> <link rel="preload" href="./js/greenlock.js" as="script">
<link
rel="preload"
href="./fonts/6xK3dSBYKcSV-LCoeQqfX1RYOo3qOK7l.woff2"
as="font"
crossorigin="anonymous"
/>
<link
rel="preload"
href="./fonts/HI_SiYsKILxRpg3hIP6sJ7fM7PqlPevW.woff2"
as="font"
crossorigin="anonymous"
/>
<link rel="preload" href="./js/bluecrypt-acme.js" as="script" />
<link rel="preload" href="./js/greenlock.js" as="script" />
</head> </head>
<body hidden> <body hidden>
<!-- let's define our SVG that we will reuse --> <!-- let's define our SVG that we will reuse -->
<svg <svg xmlns="http://www.w3.org/2000/svg" width="0" height="0" viewBox="0 0 24 24">
xmlns="http://www.w3.org/2000/svg"
width="0"
height="0"
viewbox="0 0 24 24"
>
<defs> <defs>
<g id="svg-check"> <g id="svg-check">
<path fill="none" d="M0 0h24v24H0z" /> <path fill="none" d="M0 0h24v24H0z"/>
<path d="M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z" /> <path d="M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z"/>
</g> </g>
<g id="svg-checked"> <g id="svg-checked">
<path d="M0 0h24v24H0z" fill="none" /> <path d="M0 0h24v24H0z" fill="none"/>
<path <path d="M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.11 0 2-.9 2-2V5c0-1.1-.89-2-2-2zm-9 14l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/>
d="M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.11 0 2-.9 2-2V5c0-1.1-.89-2-2-2zm-9 14l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"
/>
</g> </g>
<g id="svg-unchecked"> <g id="svg-unchecked">
<path <path d="M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"/>
d="M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z" <path d="M0 0h24v24H0z" fill="none"/>
/>
<path d="M0 0h24v24H0z" fill="none" />
</g> </g>
<g id="svg-download"> <g id="svg-download">
<path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z" /> <path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"/>
<path d="M0 0h24v24H0z" fill="none" /> <path d="M0 0h24v24H0z" fill="none"/>
</g> </g>
</defs> </defs>
</svg> </svg>
@ -102,11 +65,7 @@
<div id="js-progress-bar" class="progress-bar"> <div id="js-progress-bar" class="progress-bar">
<div class="progress-bar-step"> <div class="progress-bar-step">
<div class="circle"> <div class="circle">
<svg <svg display="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
display="none"
xmlns="http://www.w3.org/2000/svg"
viewbox="0 0 24 24"
>
<use xlink:href="#svg-check"></use> <use xlink:href="#svg-check"></use>
</svg> </svg>
</div> </div>
@ -114,11 +73,7 @@
</div> </div>
<div class="progress-bar-step"> <div class="progress-bar-step">
<div class="circle"> <div class="circle">
<svg <svg display="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
display="none"
xmlns="http://www.w3.org/2000/svg"
viewbox="0 0 24 24"
>
<use xlink:href="#svg-check"></use> <use xlink:href="#svg-check"></use>
</svg> </svg>
</div> </div>
@ -126,22 +81,16 @@
</div> </div>
<div class="progress-bar-step"> <div class="progress-bar-step">
<div class="circle"> <div class="circle">
<svg <svg display="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
display="none"
xmlns="http://www.w3.org/2000/svg"
viewbox="0 0 24 24"
>
<use xlink:href="#svg-check"></use> <use xlink:href="#svg-check"></use>
</svg> </svg>
</div> </div>
<div class="progress-step-label"> <div class="progress-step-label"><div>Install certificates</div></div>
<div>Install certificates</div>
</div>
</div> </div>
<!-- hide until the steps are all updated <!-- hide until the steps are all updated
<div class="progress-bar-step"> <div class="progress-bar-step">
<div class="circle"> <div class="circle">
<svg display="none" xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"> <svg display="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<use xlink:href="#svg-check"></use> <use xlink:href="#svg-check"></use>
</svg> </svg>
</div> </div>
@ -149,112 +98,52 @@
</div> </div>
--> -->
</div> </div>
<div class="greenlock-logo-badge"> <div class="greenlock-logo-badge"><img src="./img/greenlock-mark-400x400.png"></div>
<img src="./img/greenlock-mark-400x400.png" />
</div>
<div class="greenlock-name">Greenlock</div> <div class="greenlock-name">Greenlock</div>
</div> </div>
<div class="column-row"> <div class="column-row">
<form class="js-acme-form js-acme-form-domains"> <form class="js-acme-form js-acme-form-domains">
<h1><label>What's your domain?</label></h1> <h1><label>What's your domain?</label></h1>
<h4>Certificates are valid for 90 days. Renewal is free :)</h4> <h4>Certificates are valid for 90 days. Renewal is free :)</h4>
<input <input class="js-acme-domains" type="text" placeholder="example.com,*.example.com" required>
class="js-acme-domains" <br>
type="text"
placeholder="example.com,*.example.com"
required
/>
<br />
<button type="submit">Next</button> <button type="submit">Next</button>
<br /> <br>
<br /> <br>
<br /> <br>
<label <label><input class="js-acme-api-type" name="acme-api-type" type="radio" value="v02" checked required>
><input Production</label>
class="js-acme-api-type" <label><input class="js-acme-api-type" name="acme-api-type" type="radio" value="staging-v02" required>
name="acme-api-type" Testing</label>
type="radio" <br>
value="v02" <input class="js-acme-directory-url" type="url" placeholder="ACME directory url">
checked
required
/>
Production</label
>
<label
><input
class="js-acme-api-type"
name="acme-api-type"
type="radio"
value="staging-v02"
required
/>
Testing</label
>
<br />
<input
class="js-acme-directory-url"
type="url"
placeholder="ACME directory url"
/>
</form> </form>
<!-- Step 2 Create Account --> <!-- Step 2 Create Account -->
<form class="js-acme-form js-acme-form-account"> <form class="js-acme-form js-acme-form-account">
<h1><label>What's your email?</label></h1> <h1><label>What's your email?</label></h1>
<input <input class="js-acme-account-email acme-account-email" type="email" placeholder="john@doe.family" required>
class="js-acme-account-email acme-account-email"
type="email"
placeholder="john@doe.family"
required
/>
<div class="checkbox-array"> <div class="checkbox-array">
<label> <label>
<input class="js-acme-account-tos" type="checkbox" required /> <input class="js-acme-account-tos" type="checkbox" required>
<svg <svg class="icon-checked-box" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
class="icon-checked-box"
xmlns="http://www.w3.org/2000/svg"
viewbox="0 0 24 24"
>
<use xlink:href="#svg-checked"></use> <use xlink:href="#svg-checked"></use>
</svg> </svg>
<svg <svg class="icon-unchecked-box" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
class="icon-unchecked-box"
xmlns="http://www.w3.org/2000/svg"
viewbox="0 0 24 24"
>
<use xlink:href="#svg-unchecked"></use> <use xlink:href="#svg-unchecked"></use>
</svg> </svg>
Agree to &nbsp;<a class="js-acme-tos-url" target="acme-tos" Agree to &nbsp<a class="js-acme-tos-url" target="acme-tos">Let's Encrypt&trade; Terms of Service</a>?
>Let's Encrypt&trade; Terms of Service</a
>?
</label> </label>
<label> <label>
<input <input class="js-greenlock-account-tos" type="checkbox" required>
class="js-greenlock-account-tos" <svg class="icon-checked-box" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
type="checkbox"
required
/>
<svg
class="icon-checked-box"
xmlns="http://www.w3.org/2000/svg"
viewbox="0 0 24 24"
>
<use xlink:href="#svg-checked"></use> <use xlink:href="#svg-checked"></use>
</svg> </svg>
<svg <svg class="icon-unchecked-box" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
class="icon-unchecked-box"
xmlns="http://www.w3.org/2000/svg"
viewbox="0 0 24 24"
>
<use xlink:href="#svg-unchecked"></use> <use xlink:href="#svg-unchecked"></use>
</svg> </svg>
Agree to &nbsp<a Agree to &nbsp<a class="js-gl-tos" target="_blank" href="/legal/#terms">Greenlock&trade; Terms of Service</a>?
class="js-gl-tos"
target="_blank"
href="/legal/#terms"
>Greenlock&trade; Terms of Service</a
>?
</label> </label>
</div> </div>
<!-- <!--
@ -262,41 +151,28 @@
<br> <br>
<br> <br>
--> -->
<button class="button-next js-account-next" type="submit"> <button class="button-next js-account-next" type="submit">Next</button>
Next
</button>
<div class="email-usage"> <div class="email-usage">
Why do we need your email? We link your SSL certificates to the Why do we need your email?
email you use so that you'll be notified before the certificate We link your SSL certificates to the email you use so that you'll
expires and so you can manage your certificates in the future. be notified before the certificate expires and so you can manage
your certificates in the future.
</div> </div>
</form> </form>
<!-- Step 3 Set Challanges --> <!-- Step 3 Set Challanges -->
<form class="js-acme-form js-acme-form-challenges"> <form class="js-acme-form js-acme-form-challenges">
<h1>Let's verify your domain</h1> <h1>Let's verify your domain</h1>
<div class="js-acme-challenges"> <div class="js-acme-challenges">
<div class="tabbed-selector"> <div class="tabbed-selector">
<label> <label>
<input <input class="js-acme-challenge-type" name="acme-challenge-type" type="radio" value="http-01" checked required>
class="js-acme-challenge-type"
name="acme-challenge-type"
type="radio"
value="http-01"
checked
required
/>
File Upload File Upload
<div></div> <div></div>
</label> </label>
<label> <label>
<input <input class="js-acme-challenge-type" name="acme-challenge-type" type="radio" value="dns-01" required>
class="js-acme-challenge-type"
name="acme-challenge-type"
type="radio"
value="dns-01"
required
/>
DNS Record DNS Record
<div></div> <div></div>
</label> </label>
@ -311,35 +187,26 @@
<div class="file-ver-info-header">FILENAME</div> <div class="file-ver-info-header">FILENAME</div>
<pre class="js-acme-ver-file-location">...loading</pre> <pre class="js-acme-ver-file-location">...loading</pre>
</div> </div>
<hr /> <hr>
<div> <div>
<div class="file-ver-info-header">CONTENTS</div> <div class="file-ver-info-header">CONTENTS</div>
<pre class="js-acme-ver-content">...loading</pre> <pre class="js-acme-ver-content">...loading</pre>
</div> </div>
<div class="download-file"> <div class="download-file">
<svg <svg class="mdicon icon-download" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
class="mdicon icon-download"
xmlns="http://www.w3.org/2000/svg"
viewbox="0 0 24 24"
>
<use xlink:href="#svg-download"></use> <use xlink:href="#svg-download"></use>
</svg> </svg>
<a <a class="js-download-verify-link" href="data:text/octet-stream;base64,SGVsbG8gV29ybGQuLi4=" download="hello.txt" target="_blank">
class="js-download-verify-link"
href="data:text/octet-stream;base64,SGVsbG8gV29ybGQuLi4="
download="hello.txt"
target="_blank"
>
Download Download
</a> </a>
</div> </div>
<hr /> <hr>
<div> <div>
<div class="file-ver-info-header">LOCATION</div> <div class="file-ver-info-header">LOCATION</div>
<pre class="js-acme-ver-uri">..loading</pre> <pre class="js-acme-ver-uri">..loading</pre>
</div> </div>
</div> </div>
<br /> <br>
</div> </div>
</div> </div>
<div class="js-acme-verification-dns-01"> <div class="js-acme-verification-dns-01">
@ -349,16 +216,12 @@
<div class="js-acme-ver-txt-host">loading...</div> <div class="js-acme-ver-txt-host">loading...</div>
<div class="acme-ver-dns-label">TXT Value</div> <div class="acme-ver-dns-label">TXT Value</div>
<div class="js-acme-ver-txt-value">loading...</div> <div class="js-acme-ver-txt-value">loading...</div>
<br /> <br>
</div> </div>
<p> <p><strong>Warning</strong>:
<strong>Warning</strong>: You should wait at least 30 seconds You should wait at least 30 seconds after setting DNS records before continuing.</p>
after setting DNS records before continuing. <p><strong>Google DNS Users</strong>:
</p> You may need to wait up to 5 minutes.</p>
<p>
<strong>Google DNS Users</strong>: You may need to wait up to
5 minutes.
</p>
</div> </div>
</div> </div>
@ -370,16 +233,12 @@
<div class="js-acme-ver-txt-host">loading...</div> <div class="js-acme-ver-txt-host">loading...</div>
<div class="acme-ver-dns-label">TXT Value</div> <div class="acme-ver-dns-label">TXT Value</div>
<div class="js-acme-ver-txt-value">loading...</div> <div class="js-acme-ver-txt-value">loading...</div>
<br /> <br>
</div> </div>
<p> <p><strong>Warning</strong>:
<strong>Warning</strong>: You should wait at least 30 seconds You should wait at least 30 seconds after setting DNS records before continuing.</p>
after setting DNS records before continuing. <p><strong>Google DNS</strong>:
</p> You may need to wait up to 5 minutes.</p>
<p>
<strong>Google DNS</strong>: You may need to wait up to 5
minutes.
</p>
</div> </div>
</div> </div>
</div> </div>
@ -393,8 +252,8 @@
<div class="js-challenge-responses" hidden> <div class="js-challenge-responses" hidden>
Checking Checking
<span class="js-challenge-response-altname">&nbsp;</span> <span class="js-challenge-response-altname">&nbsp;</span>
using <span class="js-challenge-response-type">&nbsp;</span> : using <span class="js-challenge-response-type">&nbsp;</span>
<span class="js-challenge-response-status">&nbsp;</span> : <span class="js-challenge-response-status">&nbsp;</span>
</div> </div>
<!-- <!--
@ -427,44 +286,28 @@
<h2><label>privkey.pem</label></h2> <h2><label>privkey.pem</label></h2>
<div class="acme-result-privkey file-preview"> <div class="acme-result-privkey file-preview">
<div class="paper-fold"></div> <div class="paper-fold"></div>
<pre id="js-privkey"></pre> <pre id="js-privkey">
</pre>
</div> </div>
<div class="download-file"> <div class="download-file">
<svg <svg class="mdicon icon-download" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
class="mdicon icon-download"
xmlns="http://www.w3.org/2000/svg"
viewbox="0 0 24 24"
>
<use xlink:href="#svg-download"></use> <use xlink:href="#svg-download"></use>
</svg> </svg>
<a <a id="js-download-privkey-link" href="data:text/octet-stream;base64,SGVsbG8gV29ybGQuLi4=" download="privkey.pem" target="_blank">
id="js-download-privkey-link"
href="data:text/octet-stream;base64,SGVsbG8gV29ybGQuLi4="
download="privkey.pem"
target="_blank"
>
Download Download
</a> </a>
</div> </div>
<h2><label>fullchain.pem</label></h2> <h2><label>fullchain.pem</label></h2>
<div class="acme-result-fullchain file-preview"> <div class="acme-result-fullchain file-preview">
<div class="paper-fold"></div> <div class="paper-fold"></div>
<pre id="js-fullchain"></pre> <pre id="js-fullchain">
</pre>
</div> </div>
<div class="download-file"> <div class="download-file">
<svg <svg class="mdicon icon-download" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
class="mdicon icon-download"
xmlns="http://www.w3.org/2000/svg"
viewbox="0 0 24 24"
>
<use xlink:href="#svg-download"></use> <use xlink:href="#svg-download"></use>
</svg> </svg>
<a <a id="js-download-fullchain-link" href="data:text/octet-stream;base64,SGVsbG8gV29ybGQuLi4=" download="fullchain.pem" target="_blank">
id="js-download-fullchain-link"
href="data:text/octet-stream;base64,SGVsbG8gV29ybGQuLi4="
download="fullchain.pem"
target="_blank"
>
Download Download
</a> </a>
</div> </div>
@ -497,58 +340,37 @@
<a href="#">Advanced (copy and paste)</a> <a href="#">Advanced (copy and paste)</a>
<br> <br>
<button type="submit">Start Over</button> <button type="submit">Start Over</button>
--></div> -->
</form> </form>
</div>
<div><small><center>
<div> <div>
<small A <a href="https://rootprojects.org/" target="_blank">Root</a> Project
><center> | <a href="https://git.coolaj86.com/coolaj86/greenlock.html" target="_blank">View Source</a> (git)
<div> | <a href="https://rootprojects.org/legal/#terms" target="_blank">Terms of Service</a>
A | <a href="https://rootprojects.org/legal/#privacy" target="_blank">Privacy Policy</a>
<a href="https://rootprojects.org/" target="_blank">Root</a>
Project |
<a
href="https://git.coolaj86.com/coolaj86/greenlock.html"
target="_blank"
>View Source</a
>
(git) |
<a href="https://rootprojects.org/legal/#terms" target="_blank"
>Terms of Service</a
>
|
<a
href="https://rootprojects.org/legal/#privacy"
target="_blank"
>Privacy Policy</a
>
</div> </div>
<!-- or <!-- or
<pre><code>git clone https://git.coolaj86.com/coolaj86/greenlock.html.git</code></pre> <pre><code>git clone https://git.coolaj86.com/coolaj86/greenlock.html.git</code></pre>
Or view the live site code (same as live-site branch): Or view the live site code (same as live-site branch):
<pre><code>wget https://greenlock.domains --mirror --convert-links --adjust-extension --page-requisites --no-parent</code></pre> <pre><code>wget https://greenlock.domains --mirror --convert-links --adjust-extension --page-requisites --no-parent</code></pre>
--> -->
</center></small </center></small></div>
> <br>
</div>
<br />
<script src="./js/bluecrypt-acme.js"></script> <script src="./js/bluecrypt-acme.js"></script>
<script src="./js/greenlock.js"></script> <script src="./js/greenlock.js"></script>
<!-- Global site tag (gtag.js) - Google Analytics --> <!-- Global site tag (gtag.js) - Google Analytics -->
<script <script async src="https://www.googletagmanager.com/gtag/js?id=UA-118745161-2"></script>
async
src="https://www.googletagmanager.com/gtag/js?id=UA-118745161-2"
></script>
<script> <script>
window.dataLayer = window.dataLayer || []; window.dataLayer = window.dataLayer || [];
function gtag() { function gtag(){dataLayer.push(arguments);}
dataLayer.push(arguments); gtag('js', new Date());
}
gtag("js", new Date());
gtag("config", "UA-118745161-2"); gtag('config', 'UA-118745161-2');
</script> </script>
</div> </div>
</div> </div>

File diff suppressed because it is too large Load Diff

View File

@ -1,54 +1,45 @@
(function() { (function () {
"use strict"; 'use strict';
/*global URLSearchParams,Headers*/ /*global URLSearchParams,Headers*/
var PromiseA = window.Promise; var PromiseA = window.Promise;
var VERSION = "2"; var VERSION = '2';
// ACME recommends ECDSA P-256, but RSA 2048 is still required by some old servers (like what replicated.io uses ) // ACME recommends ECDSA P-256, but RSA 2048 is still required by some old servers (like what replicated.io uses )
// ECDSA P-384, P-521, and RSA 3072, 4096 are NOT recommend standards (and not properly supported) // ECDSA P-384, P-521, and RSA 3072, 4096 are NOT recommend standards (and not properly supported)
var BROWSER_SUPPORTS_RSA = false; var BROWSER_SUPPORTS_RSA = false;
var ECDSA_OPTS = { kty: "EC", namedCurve: "P-256" }; var ECDSA_OPTS = { kty: 'EC', namedCurve: 'P-256' };
var RSA_OPTS = { kty: "RSA", modulusLength: 2048 }; var RSA_OPTS = { kty: 'RSA', modulusLength: 2048 };
var Promise = window.Promise; var Promise = window.Promise;
var Keypairs = window.Keypairs; var Keypairs = window.Keypairs;
var ACME = window.ACME; var ACME = window.ACME;
var CSR = window.CSR; var CSR = window.CSR;
var $qs = function(s) { var $qs = function (s) { return window.document.querySelector(s); };
return window.document.querySelector(s); var $qsa = function (s) { return window.document.querySelectorAll(s); };
};
var $qsa = function(s) {
return window.document.querySelectorAll(s);
};
var acme; var acme;
var info = {}; var info = {};
var steps = {}; var steps = {};
var i = 1; var i = 1;
var apiUrl = "https://acme-{{env}}.api.letsencrypt.org/directory"; var apiUrl = 'https://acme-{{env}}.api.letsencrypt.org/directory';
// fix previous browsers // fix previous browsers
var isCurrent = localStorage.getItem("version") === VERSION; var isCurrent = (localStorage.getItem('version') === VERSION);
if (!isCurrent) { if (!isCurrent) {
localStorage.clear(); localStorage.clear();
localStorage.setItem("version", VERSION); localStorage.setItem('version', VERSION);
} }
localStorage.setItem("version", VERSION); localStorage.setItem('version', VERSION);
function updateApiType() { function updateApiType() {
/*jshint validthis: true */ /*jshint validthis: true */
var input = var input = this || Array.prototype.filter.call(
this || $qsa('.js-acme-api-type'), function ($el) { return $el.checked; }
Array.prototype.filter.call($qsa(".js-acme-api-type"), function($el) { )[0];
return $el.checked;
})[0];
//#console.log('ACME api type radio:', input.value); //#console.log('ACME api type radio:', input.value);
$qs(".js-acme-directory-url").value = apiUrl.replace( $qs('.js-acme-directory-url').value = apiUrl.replace(/{{env}}/g, input.value);
/{{env}}/g,
input.value
);
} }
function hideForms() { function hideForms() {
$qsa(".js-acme-form").forEach(function(el) { $qsa('.js-acme-form').forEach(function (el) {
el.hidden = true; el.hidden = true;
}); });
} }
@ -71,14 +62,11 @@
} }
function newAlert(str) { function newAlert(str) {
return new Promise(function() { return new Promise(function () {
setTimeout(function() { setTimeout(function () {
window.alert(str); window.alert(str);
if (window.confirm("Start over?")) { if (window.confirm("Start over?")) {
document.location.href = document.location.href.replace( document.location.href = document.location.href.replace(/\/app.*/, '/');
/\/app.*/,
"/"
);
} }
}, 10); }, 10);
}); });
@ -88,66 +76,48 @@
var j = i; var j = i;
i += 1; i += 1;
return PromiseA.resolve() return PromiseA.resolve().then(function () {
.then(function() {
return steps[j].submit(ev); return steps[j].submit(ev);
}) }).catch(function (err) {
.catch(function(err) {
var ourfault = true; var ourfault = true;
console.error(err); console.error(err);
if (/failed to fetch/i.test(err.message)) { if (/failed to fetch/i.test(err.message)) {
return newAlert("Network connection failure."); return newAlert("Network connection failure.");
} }
if ("E_ACME_CHALLENGE" === err.code) { if ('E_ACME_CHALLENGE' === err.code) {
if ("dns-01" === err.type) { if ('dns-01' === err.type) {
ourfault = false; ourfault = false;
return newAlert( return newAlert("It looks like the DNS record you set for "
"It looks like the DNS record you set for " + + err.altname + " was incorrect or did not propagate. "
err.altname + + "The error message was '" + err.message + "'");
" was incorrect or did not propagate. " + } else if ('http-01' === err.type) {
"The error message was '" +
err.message +
"'"
);
} else if ("http-01" === err.type) {
ourfault = false; ourfault = false;
return newAlert( return newAlert("It looks like the file you uploaded for "
"It looks like the file you uploaded for " + + err.altname + " was incorrect or could not be downloaded. "
err.altname + + "The error message was '" + err.message + "'");
" was incorrect or could not be downloaded. " +
"The error message was '" +
err.message +
"'"
);
} }
} }
if (ourfault) { if (ourfault) {
err.auth = undefined; err.auth = undefined;
window.alert( window.alert("Something went wrong. It's probably our fault, not yours."
"Something went wrong. It's probably our fault, not yours." + + " Please email aj@rootprojects.org to let him know. The error message is: \n"
" Please email aj@rootprojects.org to let him know. The error message is: \n" + + JSON.stringify(err, null, 2));
JSON.stringify(err, null, 2) return new Promise(function () {});
);
return new Promise(function() {});
} }
}); });
} }
function testKeypairSupport() { function testKeypairSupport() {
return Keypairs.generate(RSA_OPTS) return Keypairs.generate(RSA_OPTS).then(function () {
.then(function() {
console.info("[crypto] RSA is supported"); console.info("[crypto] RSA is supported");
BROWSER_SUPPORTS_RSA = true; BROWSER_SUPPORTS_RSA = true;
}) }).catch(function () {
.catch(function() {
console.warn("[crypto] RSA is NOT supported"); console.warn("[crypto] RSA is NOT supported");
return Keypairs.generate(ECDSA_OPTS) return Keypairs.generate(ECDSA_OPTS).then(function () {
.then(function() { console.info('[crypto] ECDSA is supported');
console.info("[crypto] ECDSA is supported"); }).catch(function (e) {
})
.catch(function(e) {
console.warn("[crypto] EC is NOT supported"); console.warn("[crypto] EC is NOT supported");
throw e; throw e;
}); });
@ -155,15 +125,8 @@
} }
function getServerKeypair() { function getServerKeypair() {
var sortedAltnames = info.identifiers var sortedAltnames = info.identifiers.map(function (ident) { return ident.value; }).sort().join(',');
.map(function(ident) { var serverJwk = JSON.parse(localStorage.getItem('server:' + sortedAltnames) || 'null');
return ident.value;
})
.sort()
.join(",");
var serverJwk = JSON.parse(
localStorage.getItem("server:" + sortedAltnames) || "null"
);
if (serverJwk) { if (serverJwk) {
return PromiseA.resolve(serverJwk); return PromiseA.resolve(serverJwk);
} }
@ -176,222 +139,178 @@
keypairOpts = ECDSA_OPTS; keypairOpts = ECDSA_OPTS;
} }
return Keypairs.generate(RSA_OPTS) return Keypairs.generate(RSA_OPTS).catch(function (err) {
.catch(function(err) { console.error("[Error] Keypairs.generate(" + JSON.stringify(RSA_OPTS) + "):");
console.error(
"[Error] Keypairs.generate(" + JSON.stringify(RSA_OPTS) + "):"
);
throw err; throw err;
}) }).then(function (pair) {
.then(function(pair) { localStorage.setItem('server:'+sortedAltnames, JSON.stringify(pair.private));
localStorage.setItem(
"server:" + sortedAltnames,
JSON.stringify(pair.private)
);
return pair.private; return pair.private;
}); });
} }
function getAccountKeypair(email) { function getAccountKeypair(email) {
var json = localStorage.getItem("account:" + email); var json = localStorage.getItem('account:'+email);
if (json) { if (json) {
return Promise.resolve(JSON.parse(json)); return Promise.resolve(JSON.parse(json));
} }
return Keypairs.generate(ECDSA_OPTS) return Keypairs.generate(ECDSA_OPTS).catch(function (err) {
.catch(function(err) { console.warn("[Error] Keypairs.generate(" + JSON.stringify(ECDSA_OPTS) + "):\n", err);
console.warn( return Keypairs.generate(RSA_OPTS).catch(function (err) {
"[Error] Keypairs.generate(" + JSON.stringify(ECDSA_OPTS) + "):\n", console.error("[Error] Keypairs.generate(" + JSON.stringify(RSA_OPTS) + "):");
err
);
return Keypairs.generate(RSA_OPTS).catch(function(err) {
console.error(
"[Error] Keypairs.generate(" + JSON.stringify(RSA_OPTS) + "):"
);
throw err; throw err;
}); });
}) }).then(function (pair) {
.then(function(pair) { localStorage.setItem('account:'+email, JSON.stringify(pair.private));
localStorage.setItem("account:" + email, JSON.stringify(pair.private));
return pair.private; return pair.private;
}); });
} }
function updateChallengeType() { function updateChallengeType() {
/*jshint validthis: true*/ /*jshint validthis: true*/
var input = var input = this || Array.prototype.filter.call(
this || $qsa('.js-acme-challenge-type'), function ($el) { return $el.checked; }
Array.prototype.filter.call($qsa(".js-acme-challenge-type"), function( )[0];
$el $qs('.js-acme-verification-wildcard').hidden = true;
) { $qs('.js-acme-verification-http-01').hidden = true;
return $el.checked; $qs('.js-acme-verification-dns-01').hidden = true;
})[0];
$qs(".js-acme-verification-wildcard").hidden = true;
$qs(".js-acme-verification-http-01").hidden = true;
$qs(".js-acme-verification-dns-01").hidden = true;
if (info.challenges.wildcard) { if (info.challenges.wildcard) {
$qs(".js-acme-verification-wildcard").hidden = false; $qs('.js-acme-verification-wildcard').hidden = false;
} }
if (info.challenges[input.value]) { if (info.challenges[input.value]) {
$qs(".js-acme-verification-" + input.value).hidden = false; $qs('.js-acme-verification-' + input.value).hidden = false;
} }
} }
function saveContact(email, domains) { function saveContact(email, domains) {
// to be used for good, not evil // to be used for good, not evil
return window return window.fetch('https://api.rootprojects.org/api/rootprojects.org/public/community', {
.fetch( method: 'POST'
"https://api.rootprojects.org/api/rootprojects.org/public/community", , cors: true
{ , headers: new Headers({ 'Content-Type': 'application/json' })
method: "POST", , body: JSON.stringify({
cors: true, address: email
headers: new Headers({ "Content-Type": "application/json" }), , project: 'greenlock-domains@rootprojects.org'
body: JSON.stringify({ , timezone: new Intl.DateTimeFormat().resolvedOptions().timeZone
address: email, , domain: domains.join(',')
project: "greenlock-domains@rootprojects.org",
timezone: new Intl.DateTimeFormat().resolvedOptions().timeZone,
domain: domains.join(",")
}) })
} }).catch(function (err) {
)
.catch(function(err) {
console.error(err); console.error(err);
}); });
} }
steps[1] = function() { steps[1] = function () {
console.info("\n1. Show domains form"); console.info("\n1. Show domains form");
updateProgress(0); updateProgress(0);
hideForms(); hideForms();
$qs(".js-acme-form-domains").hidden = false; $qs('.js-acme-form-domains').hidden = false;
}; };
steps[1].submit = function() { steps[1].submit = function () {
console.info( console.info("[submit] 1. Process domains, create ACME client", info.domains);
"[submit] 1. Process domains, create ACME client", info.domains = $qs('.js-acme-domains').value
info.domains .replace(/https?:\/\//g, ' ').replace(/[,+]/g, ' ').trim().split(/\s+/g);
); console.info("[domains]", info.domains.join(' '));
info.domains = $qs(".js-acme-domains")
.value.replace(/https?:\/\//g, " ")
.replace(/[,+]/g, " ")
.trim()
.split(/\s+/g);
console.info("[domains]", info.domains.join(" "));
info.identifiers = info.domains.map(function(hostname) { info.identifiers = info.domains.map(function (hostname) {
return { type: "dns", value: hostname.toLowerCase().trim() }; return { type: 'dns', value: hostname.toLowerCase().trim() };
}); });
info.identifiers.sort(function(a, b) { info.identifiers.sort(function (a, b) {
if (a === b) { if (a === b) { return 0; }
return 0; if (a < b) { return 1; }
} if (a > b) { return -1; }
if (a < b) {
return 1;
}
if (a > b) {
return -1;
}
}); });
var acmeDirectoryUrl = $qs(".js-acme-directory-url").value; var acmeDirectoryUrl = $qs('.js-acme-directory-url').value;
acme = ACME.create({ Keypairs: Keypairs, CSR: CSR }); acme = ACME.create({ Keypairs: Keypairs, CSR: CSR });
return acme.init(acmeDirectoryUrl).then(function(directory) { return acme.init(acmeDirectoryUrl).then(function (directory) {
$qs(".js-acme-tos-url").href = directory.meta.termsOfService; $qs('.js-acme-tos-url').href = directory.meta.termsOfService;
return steps[i](); return steps[i]();
}); });
}; };
steps[2] = function() { steps[2] = function () {
console.info("\n2. Show account (email, ToS) form"); console.info("\n2. Show account (email, ToS) form");
updateProgress(0); updateProgress(0);
hideForms(); hideForms();
$qs(".js-acme-form-account").hidden = false; $qs('.js-acme-form-account').hidden = false;
}; };
steps[2].submit = function() { steps[2].submit = function () {
console.info("[submit] 2. Create ACME account (get Key ID)"); console.info("[submit] 2. Create ACME account (get Key ID)");
var email = $qs(".js-acme-account-email") var email = $qs('.js-acme-account-email').value.toLowerCase().trim();
.value.toLowerCase()
.trim();
info.email = email; info.email = email;
info.contact = ["mailto:" + email]; info.contact = [ 'mailto:' + email ];
info.agree = $qs(".js-acme-account-tos").checked; info.agree = $qs('.js-acme-account-tos').checked;
//info.greenlockAgree = $qs('.js-gl-tos').checked; //info.greenlockAgree = $qs('.js-gl-tos').checked;
// TODO ping with version and account creation // TODO ping with version and account creation
setTimeout(saveContact, 100, email, info.domains); setTimeout(saveContact, 100, email, info.domains);
$qs(".js-account-next").disabled = true; $qs('.js-account-next').disabled = true;
return info.cryptoCheck return info.cryptoCheck.then(function () {
.then(function() { return getAccountKeypair(email).then(function (jwk) {
return getAccountKeypair(email).then(function(jwk) {
// TODO save account id rather than always retrieving it? // TODO save account id rather than always retrieving it?
console.info("[accounts] upsert for", email); console.info("[accounts] upsert for", email);
return acme.accounts return acme.accounts.create({
.create({ email: email
email: email, , agreeToTerms: info.agree && true
agreeToTerms: info.agree && true, , accountKeypair: { privateKeyJwk: jwk }
accountKeypair: { privateKeyJwk: jwk } }).then(function (account) {
})
.then(function(account) {
console.info("[accounts] result:", account); console.info("[accounts] result:", account);
info.account = account; info.account = account;
info.privateJwk = jwk; info.privateJwk = jwk;
info.email = email; info.email = email;
}) }).catch(function (err) {
.catch(function(err) {
console.error("[accounts] failed to upsert account:"); console.error("[accounts] failed to upsert account:");
console.error(err); console.error(err);
return newAlert(err.message || JSON.stringify(err, null, 2)); return newAlert(err.message || JSON.stringify(err, null, 2));
}); });
}); });
}) }).then(function () {
.then(function() {
var jwk = info.privateJwk; var jwk = info.privateJwk;
var account = info.account; var account = info.account;
console.info("[orders] requesting"); console.info("[orders] requesting");
return acme.orders return acme.orders.request({
.request({ account: account
account: account, , accountKeypair: { privateKeyJwk: jwk }
accountKeypair: { privateKeyJwk: jwk }, , domains: info.domains
domains: info.domains }).then(function (order) {
})
.then(function(order) {
info.order = order; info.order = order;
console.info("[orders] created ", order); console.info("[orders] created ", order);
var claims = order.claims; var claims = order.claims;
var obj = { "dns-01": [], "http-01": [], wildcard: [] }; var obj = { 'dns-01': [], 'http-01': [], 'wildcard': [] };
info.challenges = obj; info.challenges = obj;
var $httpList = $qs(".js-acme-http"); var $httpList = $qs('.js-acme-http');
var $dnsList = $qs(".js-acme-dns"); var $dnsList = $qs('.js-acme-dns');
var $wildList = $qs(".js-acme-wildcard"); var $wildList = $qs('.js-acme-wildcard');
var httpTpl = $httpList.innerHTML; var httpTpl = $httpList.innerHTML;
var dnsTpl = $dnsList.innerHTML; var dnsTpl = $dnsList.innerHTML;
var wildTpl = $wildList.innerHTML; var wildTpl = $wildList.innerHTML;
$httpList.innerHTML = ""; $httpList.innerHTML = '';
$dnsList.innerHTML = ""; $dnsList.innerHTML = '';
$wildList.innerHTML = ""; $wildList.innerHTML = '';
claims.forEach(function(claim) { claims.forEach(function (claim) {
//#console.log("claims[i]", claim); //#console.log("claims[i]", claim);
var hostname = claim.identifier.value; var hostname = claim.identifier.value;
claim.challenges.forEach(function(c) { claim.challenges.forEach(function (c) {
var auth = c; var auth = c;
var data = { var data = {
type: c.type, type: c.type
hostname: hostname, , hostname: hostname
url: c.url, , url: c.url
token: c.token, , token: c.token
httpPath: auth.challengeUrl, , httpPath: auth.challengeUrl
httpAuth: auth.keyAuthorization, , httpAuth: auth.keyAuthorization
dnsType: "TXT", , dnsType: 'TXT'
dnsHost: auth.dnsHost, , dnsHost: auth.dnsHost
dnsAnswer: auth.keyAuthorizationDigest , dnsAnswer: auth.keyAuthorizationDigest
}; };
//#console.log("claims[i].challenge", data); //#console.log("claims[i].challenge", data);
@ -399,36 +318,26 @@
if (claim.wildcard) { if (claim.wildcard) {
obj.wildcard.push(data); obj.wildcard.push(data);
$tpl.innerHTML = wildTpl; $tpl.innerHTML = wildTpl;
$tpl.querySelector(".js-acme-ver-txt-host").innerHTML = $tpl.querySelector(".js-acme-ver-txt-host").innerHTML = data.dnsHost;
data.dnsHost; $tpl.querySelector(".js-acme-ver-txt-value").innerHTML = data.dnsAnswer;
$tpl.querySelector(".js-acme-ver-txt-value").innerHTML =
data.dnsAnswer;
$wildList.appendChild($tpl); $wildList.appendChild($tpl);
} else if (obj[data.type]) { } else if(obj[data.type]) {
obj[data.type].push(data); obj[data.type].push(data);
if ("dns-01" === data.type) { if ('dns-01' === data.type) {
$tpl.innerHTML = dnsTpl; $tpl.innerHTML = dnsTpl;
$tpl.querySelector(".js-acme-ver-txt-host").innerHTML = $tpl.querySelector(".js-acme-ver-txt-host").innerHTML = data.dnsHost;
data.dnsHost; $tpl.querySelector(".js-acme-ver-txt-value").innerHTML = data.dnsAnswer;
$tpl.querySelector(".js-acme-ver-txt-value").innerHTML =
data.dnsAnswer;
$dnsList.appendChild($tpl); $dnsList.appendChild($tpl);
} else if ("http-01" === data.type) { } else if ('http-01' === data.type) {
$tpl.innerHTML = httpTpl; $tpl.innerHTML = httpTpl;
$tpl.querySelector( $tpl.querySelector(".js-acme-ver-file-location").innerHTML = data.httpPath.split("/").slice(-1);
".js-acme-ver-file-location" $tpl.querySelector(".js-acme-ver-content").innerHTML = data.httpAuth;
).innerHTML = data.httpPath.split("/").slice(-1); $tpl.querySelector(".js-acme-ver-uri").innerHTML = data.httpPath;
$tpl.querySelector(".js-acme-ver-content").innerHTML =
data.httpAuth;
$tpl.querySelector(".js-acme-ver-uri").innerHTML =
data.httpPath;
$tpl.querySelector(".js-download-verify-link").href = $tpl.querySelector(".js-download-verify-link").href =
"data:text/octet-stream;base64," + "data:text/octet-stream;base64," + window.btoa(data.httpAuth);
window.btoa(data.httpAuth); $tpl.querySelector(".js-download-verify-link").download = data.httpPath.split("/").slice(-1);
$tpl.querySelector(
".js-download-verify-link"
).download = data.httpPath.split("/").slice(-1);
$httpList.appendChild($tpl); $httpList.appendChild($tpl);
} }
} }
@ -438,92 +347,81 @@
// hide wildcard if no wildcard // hide wildcard if no wildcard
// hide http-01 and dns-01 if only wildcard // hide http-01 and dns-01 if only wildcard
if (!obj.wildcard.length) { if (!obj.wildcard.length) {
$qs(".js-acme-wildcard-challenges").hidden = true; $qs('.js-acme-wildcard-challenges').hidden = true;
} }
if (!obj["http-01"].length) { if (!obj['http-01'].length) {
$qs(".js-acme-challenges").hidden = true; $qs('.js-acme-challenges').hidden = true;
} }
console.info("[housekeeping] challenges", info.challenges); console.info("[housekeeping] challenges", info.challenges);
updateChallengeType(); updateChallengeType();
return steps[i](); return steps[i]();
}) }).catch(function (err) {
.catch(function(err) {
if (err.detail || err.urn) { if (err.detail || err.urn) {
console.error("(Probably) User Error:"); console.error("(Probably) User Error:");
console.error(err); console.error(err);
return newAlert( return newAlert("There was an error, probably with your email or domain:\n" + err.message);
"There was an error, probably with your email or domain:\n" +
err.message
);
} }
throw err; throw err;
}); });
}) }).catch(function (err) {
.catch(function(err) { console.error('Step \'\' Error:');
console.error("Step '' Error:");
console.error(err, err.stack); console.error(err, err.stack);
return newAlert( return newAlert("An error happened (but it's not your fault)."
"An error happened (but it's not your fault)." + + " Email aj@rootprojects.org to let him know that 'order and get challenges' failed.");
" Email aj@rootprojects.org to let him know that 'order and get challenges' failed."
);
}); });
}; };
steps[3] = function() { steps[3] = function () {
console.info("\n3. Present challenge options"); console.info("\n3. Present challenge options");
updateProgress(1); updateProgress(1);
hideForms(); hideForms();
$qs(".js-acme-form-challenges").hidden = false; $qs('.js-acme-form-challenges').hidden = false;
}; };
steps[3].submit = function() { steps[3].submit = function () {
console.info("[submit] 3. Fulfill challenges, fetch certificate"); console.info("[submit] 3. Fulfill challenges, fetch certificate");
var challengePriority = ["dns-01"]; var challengePriority = [ 'dns-01' ];
if ("http-01" === $qs(".js-acme-challenge-type:checked").value) { if ('http-01' === $qs('.js-acme-challenge-type:checked').value) {
challengePriority.unshift("http-01"); challengePriority.unshift('http-01');
} }
console.info("[challenge] selected ", challengePriority[0]); console.info("[challenge] selected ", challengePriority[0]);
// for now just show the next page immediately (its a spinner) // for now just show the next page immediately (its a spinner)
steps[i](); steps[i]();
return getAccountKeypair(info.email).then(function(jwk) { return getAccountKeypair(info.email).then(function (jwk) {
// TODO put a test challenge in the list // TODO put a test challenge in the list
// info.order.claims.push(...) // info.order.claims.push(...)
// TODO warn about wait-time if DNS // TODO warn about wait-time if DNS
return getServerKeypair().then(function(serverJwk) { return getServerKeypair().then(function (serverJwk) {
return acme.orders return acme.orders.complete({
.complete({ account: info.account
account: info.account, , accountKeypair: { privateKeyJwk: jwk }
accountKeypair: { privateKeyJwk: jwk }, , order: info.order
order: info.order, , domains: info.domains
domains: info.domains, , domainKeypair: { privateKeyJwk: serverJwk }
domainKeypair: { privateKeyJwk: serverJwk }, , challengePriority: challengePriority
challengePriority: challengePriority, , challenges: false
challenges: false, , onChallengeStatus: function (details) {
onChallengeStatus: function(details) { $qs('.js-challenge-responses').hidden = false;
$qs(".js-challenge-responses").hidden = false; $qs('.js-challenge-response-type').innerText = details.type;
$qs(".js-challenge-response-type").innerText = details.type; $qs('.js-challenge-response-status').innerText = details.status;
$qs(".js-challenge-response-status").innerText = details.status; $qs('.js-challenge-response-altname').innerText = details.altname;
$qs(".js-challenge-response-altname").innerText = details.altname;
} }
}) }).then(function (certs) {
.then(function(certs) { return Keypairs.export({ jwk: serverJwk }).then(function (keyPem) {
return Keypairs.export({ jwk: serverJwk }).then(function(keyPem) { console.info('WINNING!');
console.info("WINNING!");
console.info(certs); console.info(certs);
var fullChainText = [ $qs('#js-fullchain').innerHTML = [
certs.cert.trim() + "\n", certs.cert.trim() + "\n"
certs.chain + "\n" , certs.chain + "\n"
].join("\n"); ].join("\n");
$qs("#js-fullchain").innerHTML = fullChainText;
$qs("#js-download-fullchain-link").href = $qs("#js-download-fullchain-link").href =
"data:text/octet-stream;base64," + window.btoa(fullChainText); "data:text/octet-stream;base64," + window.btoa(certs);
$qs("#js-privkey").innerHTML = keyPem; $qs('#js-privkey').innerHTML = keyPem;
$qs("#js-download-privkey-link").href = $qs("#js-download-privkey-link").href =
"data:text/octet-stream;base64," + window.btoa(keyPem); "data:text/octet-stream;base64," + window.btoa(keyPem);
return submitForm(); return submitForm();
@ -534,49 +432,50 @@
}; };
// spinner // spinner
steps[4] = function() { steps[4] = function () {
console.info("\n4. Show loading spinner"); console.info('\n4. Show loading spinner');
updateProgress(1); updateProgress(1);
hideForms(); hideForms();
$qs(".js-acme-form-poll").hidden = false; $qs('.js-acme-form-poll').hidden = false;
}; };
steps[4].submit = function() { steps[4].submit = function () {
console.info("[submit] 4. Order complete"); console.info('[submit] 4. Order complete');
return steps[i](); return steps[i]();
}; };
steps[5] = function() { steps[5] = function () {
console.info("\n5. Present certificates (yay!)"); console.info('\n5. Present certificates (yay!)');
updateProgress(2); updateProgress(2);
hideForms(); hideForms();
$qs(".js-acme-form-download").hidden = false; $qs('.js-acme-form-download').hidden = false;
}; };
function init() { function init() {
$qsa(".js-acme-api-type").forEach(function($el) { $qsa('.js-acme-api-type').forEach(function ($el) {
$el.addEventListener("change", updateApiType); $el.addEventListener('change', updateApiType);
}); });
updateApiType(); updateApiType();
$qsa(".js-acme-form").forEach(function($el) { $qsa('.js-acme-form').forEach(function ($el) {
$el.addEventListener("submit", function(ev) { $el.addEventListener('submit', function (ev) {
ev.preventDefault(); ev.preventDefault();
return submitForm(ev); return submitForm(ev);
}); });
}); });
$qsa(".js-acme-challenge-type").forEach(function($el) { $qsa('.js-acme-challenge-type').forEach(function ($el) {
$el.addEventListener("change", updateChallengeType); $el.addEventListener('change', updateChallengeType);
}); });
var params = new URLSearchParams(window.location.search);
var apiType = params.get("acme-api-type") || "staging-v02";
if (params.has("acme-domains")) {
$qs(".js-acme-domains").value = params.get("acme-domains");
$qsa(".js-acme-api-type").forEach(function(ele) { var params = new URLSearchParams(window.location.search);
if (ele.value === apiType) { var apiType = params.get('acme-api-type') || "staging-v02";
if (params.has('acme-domains')) {
$qs('.js-acme-domains').value = params.get('acme-domains');
$qsa('.js-acme-api-type').forEach(function(ele) {
if(ele.value === apiType) {
ele.checked = true; ele.checked = true;
} }
}); });
@ -590,20 +489,16 @@
} }
init(); init();
$qs("body").hidden = false; $qs('body').hidden = false;
// in the background // in the background
info.cryptoCheck = testKeypairSupport() info.cryptoCheck = testKeypairSupport().then(function () {
.then(function() {
console.info("[crypto] self-check: passed"); console.info("[crypto] self-check: passed");
}) }).catch(function (err) {
.catch(function(err) { console.error('[crypto] could not use either RSA nor EC.');
console.error("[crypto] could not use either RSA nor EC.");
console.error(err); console.error(err);
window.alert( window.alert("Generating secure certificates requires a browser with cryptography support."
"Generating secure certificates requires a browser with cryptography support." + + "Please consider a recent version of Chrome, Firefox, or Safari.");
"Please consider a recent version of Chrome, Firefox, or Safari."
);
throw err; throw err;
}); });
})(); }());

View File

@ -15,8 +15,7 @@ a {
color: #1a1a1a; color: #1a1a1a;
} }
input[type="email"], input[type=email], input[type=text] {
input[type="text"] {
font-size: 1em; font-size: 1em;
padding: 0.444444444em 0.888889em; padding: 0.444444444em 0.888889em;
width: 100%; width: 100%;
@ -90,6 +89,7 @@ pre {
text-align: center; text-align: center;
position: absolute; position: absolute;
left: 50%; left: 50%;
=: block font-size: ;
top: 139%; top: 139%;
font-size: 0.722222222em; font-size: 0.722222222em;
white-space: nowrap; white-space: nowrap;
@ -111,8 +111,7 @@ pre {
padding: 1.6em 2.9333em 1.6em 1.6em; padding: 1.6em 2.9333em 1.6em 1.6em;
} }
.js-progress-step-complete > .circle, .js-progress-step-complete > .circle, .js-progress-step-started > .circle {
.js-progress-step-started > .circle {
background-color: #5bc17f; background-color: #5bc17f;
} }
@ -128,29 +127,28 @@ pre {
padding: 1em 0; padding: 1em 0;
} }
.checkbox-array input[type="checkbox"] { .checkbox-array input[type=checkbox] {
opacity: 0; opacity: 0;
position: absolute; position: absolute;
} }
.checkbox-array input[type="checkbox"] ~ .icon-checked-box { .checkbox-array input[type=checkbox] ~ .icon-checked-box {
display: none; display: none;
} }
.checkbox-array input[type="checkbox"] ~ .icon-unchecked-box { .checkbox-array input[type=checkbox] ~ .icon-unchecked-box {
display: initial; display: initial;
} }
.checkbox-array input[type="checkbox"]:checked ~ .icon-checked-box { .checkbox-array input[type=checkbox]:checked ~ .icon-checked-box {
display: initial; display: initial;
} }
.checkbox-array input[type="checkbox"]:checked ~ .icon-unchecked-box { .checkbox-array input[type=checkbox]:checked ~ .icon-unchecked-box {
display: none; display: none;
} }
.checkbox-array .icon-checked-box, .checkbox-array .icon-checked-box, .checkbox-array .icon-unchecked-box {
.checkbox-array .icon-unchecked-box {
width: 1.333333333em; width: 1.333333333em;
fill: #5bc17f; fill: #5bc17f;
margin-right: 0.666666667em; margin-right: 0.666666667em;
@ -163,8 +161,7 @@ pre {
margin: 0.4em 0; margin: 0.4em 0;
} }
.checkbox-array input[type="checkbox"]:focus ~ .icon-checked-box, .checkbox-array input[type=checkbox]:focus ~ .icon-checked-box, .checkbox-array input[type=checkbox]:focus ~ .icon-unchecked-box {
.checkbox-array input[type="checkbox"]:focus ~ .icon-unchecked-box {
background: #5bc17f52; background: #5bc17f52;
} }
@ -184,10 +181,6 @@ pre {
margin: 1em 0; margin: 1em 0;
} }
button {
cursor: pointer;
}
.tabbed-selector label { .tabbed-selector label {
width: 50%; width: 50%;
padding: 0.5em 0; padding: 0.5em 0;
@ -199,7 +192,7 @@ button {
text-align: center; text-align: center;
} }
.tabbed-selector input[type="radio"] { .tabbed-selector input[type=radio] {
display: none; display: none;
} }
@ -229,13 +222,7 @@ button {
border-bottom: solid #d9d9d9 1px; border-bottom: solid #d9d9d9 1px;
right: 0; right: 0;
top: 0; top: 0;
background: linear-gradient( background: linear-gradient(45deg, #f7f7f7 0%,#f7f7f7 50%,#ffffff 50%,#ffffff 100%);
45deg,
#f7f7f7 0%,
#f7f7f7 50%,
#ffffff 50%,
#ffffff 100%
);
} }
.file-ver-info-header { .file-ver-info-header {
@ -269,6 +256,8 @@ button {
word-break: break-all; word-break: break-all;
} }
.cert-download-container { .cert-download-container {
margin: 0 -31%; margin: 0 -31%;
} }

View File

@ -1,137 +1,72 @@
<html> <html>
<head> <head>
<title>Greenlock&trade;</title> <title>Greenlock&trade;</title>
<meta <meta property="og:image" content="https://greenlock.domains/img/greenlock-mark-400x400.png" />
property="og:image" <link href="styles/main.css" rel="stylesheet">
content="https://greenlock.domains/img/greenlock-mark-400x400.png"
/>
<link href="styles/main.css" rel="stylesheet" />
<style> <style>
@font-face { @font-face {
font-family: "Source Sans Pro"; font-family: 'Source Sans Pro';
font-style: normal; font-style: normal;
font-display: block; font-display: block;
font-weight: 400; font-weight: 400;
src: local("Source Sans Pro Regular"), local("SourceSansPro-Regular"), src: local('Source Sans Pro Regular'), local('SourceSansPro-Regular'), url(./fonts/6xK3dSBYKcSV-LCoeQqfX1RYOo3qOK7l.woff2) format('woff2');
url(./fonts/6xK3dSBYKcSV-LCoeQqfX1RYOo3qOK7l.woff2) format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193,
U+2212, U+2215, U+FEFF, U+FFFD;
} }
@font-face { @font-face {
font-family: "Source Sans Pro"; font-family: 'Source Sans Pro';
font-style: normal; font-style: normal;
font-weight: 700; font-weight: 700;
font-display: block; font-display: block;
src: local("Source Sans Pro Bold"), local("SourceSansPro-Bold"), src: local('Source Sans Pro Bold'), local('SourceSansPro-Bold'), url(./fonts/6xKydSBYKcSV-LCoeQqfX1RYOo3ig4vwlxdu.woff2) format('woff2');
url(./fonts/6xKydSBYKcSV-LCoeQqfX1RYOo3ig4vwlxdu.woff2) unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
format("woff2");
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193,
U+2212, U+2215, U+FEFF, U+FFFD;
} }
</style> </style>
<link <link rel="preload" href="./app/fonts/6xKydSBYKcSV-LCoeQqfX1RYOo3ig4vwlxdu.woff2" as="font" crossorigin="anonymous">
rel="preload" <link rel="preload" href="./app/fonts/6xK3dSBYKcSV-LCoeQqfX1RYOo3qOK7l.woff2" as="font" crossorigin="anonymous">
href="./app/fonts/6xKydSBYKcSV-LCoeQqfX1RYOo3ig4vwlxdu.woff2" <link rel="prefetch" href="./app/fonts/HI_SiYsKILxRpg3hIP6sJ7fM7PqlPevW.woff2" as="font" crossorigin="anonymous">
as="font" <link rel="prefetch" href="./app/js/bluecrypt-acme.js" as="script">
crossorigin="anonymous" <link rel="prefetch" href="./app/js/greenlock.js" as="script">
/> <link rel="prefetch" href="./js/app.js" as="script">
<link
rel="preload"
href="./app/fonts/6xK3dSBYKcSV-LCoeQqfX1RYOo3qOK7l.woff2"
as="font"
crossorigin="anonymous"
/>
<link
rel="prefetch"
href="./app/fonts/HI_SiYsKILxRpg3hIP6sJ7fM7PqlPevW.woff2"
as="font"
crossorigin="anonymous"
/>
<link rel="prefetch" href="./app/js/bluecrypt-acme.js" as="script" />
<link rel="prefetch" href="./app/js/greenlock.js" as="script" />
<link rel="prefetch" href="./js/app.js" as="script" />
</head> </head>
<body class="js-app-ready"> <body class="js-app-ready">
<script> <script>
document.querySelector("body").classList.remove("js-app-ready"); document.querySelector('body').classList.remove("js-app-ready");
</script> </script>
<div class="column-container wide"> <div class="column-container wide">
<div class="column-row"> <div class="column-row">
<img alt="Greenlock logo" src="img/greenlock-146.png" /> <img src="img/greenlock-146.png">
</div> </div>
<div class="column-row"> <div class="column-row">
<h1>Get the green lock for your website</h1> <h1>Get the green lock for your website</h1>
</div> </div>
<div class="column-row"> <div class="column-row">
<div class="js-javascript-warning"> <div class="js-javascript-warning">
Greenlock will process the CSR in the browser and request the Greenlock will process the CSR in the browser and request the certificates directly from letsencrypt.org.
certificates directly from letsencrypt.org. Please enable Javascript Please enable Javascript before continuing.
before continuing.
</div> </div>
<form id="js-acme-form" action="./app/" method="GET"> <form id="js-acme-form" action="./app/" method="GET">
<div class="domain-psuedo-input"> <div class="domain-psuedo-input">
<span class="secure-green">Secure</span> | <span class="secure-green">Secure</span> | <span class="secure-green">https:</span>//<input aria-label="domains to secure" id="acme-domains" type="text" name="acme-domains" placeholder="Your domain name" required>
<span class="secure-green">https:</span>//<input
aria-label="domains to secure"
id="acme-domains"
type="text"
name="acme-domains"
placeholder="Your domain name"
required
/>
</div> </div>
<button type="submit">Go</button> <button type="submit">Go</button>
<div class="domain-subtext"> <div class="domain-subtext">Domain, subdomain, or wildcard domain</div>
Domain, subdomain, or wildcard domain
</div>
<div class="acme-advanced-fields"> <div class="acme-advanced-fields">
<label <label><input name="acme-api-type" type="radio" value="v02" checked required>
><input
name="acme-api-type"
type="radio"
value="v02"
checked
required
/>
Production Production
</label> </label>
<label <label><input name="acme-api-type" type="radio" value="staging-v02" required>
><input Testing</label>
name="acme-api-type" <input id="js-acme-api-url" type="url" placeholder="ACME directory url">
type="radio" <br>
value="staging-v02"
required
/>
Testing</label
>
<input
id="js-acme-api-url"
type="url"
placeholder="ACME directory url"
/>
<br />
API Compatibility: Let's Encrypt v2 / ACME draft 15 API Compatibility: Let's Encrypt v2 / ACME draft 15
<div> <div>
<br /> <br>
A A <a href="https://rootprojects.org/" target="_blank">Root</a> Project
<a href="https://rootprojects.org/" target="_blank">Root</a> | <a href="https://git.coolaj86.com/coolaj86/greenlock.html" target="_blank">View Source</a> (git)
Project | | <a href="https://rootprojects.org/legal/#terms" target="_blank">Terms of Service</a>
<a | <a href="https://rootprojects.org/legal/#privacy" target="_blank">Privacy Policy</a>
href="https://git.coolaj86.com/coolaj86/greenlock.html"
target="_blank"
>View Source</a
>
(git) |
<a href="https://rootprojects.org/legal/#terms" target="_blank"
>Terms of Service</a
>
|
<a href="https://rootprojects.org/legal/#privacy" target="_blank"
>Privacy Policy</a
>
</div> </div>
</div> </div>
</form> </form>
@ -139,9 +74,7 @@
<div class="column-row"> <div class="column-row">
<div class="why-you-need"> <div class="why-you-need">
<h2>Why you need HTTPS</h2> <h2>Why you need HTTPS</h2>
SSL Certificates are required for secure login, accepting payments, SSL Certificates are required for secure login, accepting payments, and for browsers like Google Chrome to stop showing security warnings to your users.
and for browsers like Google Chrome to stop showing security warnings
to your users.
</div> </div>
</div> </div>
<!-- or <!-- or
@ -153,18 +86,13 @@
<script src="./js/app.js"></script> <script src="./js/app.js"></script>
<!-- Global site tag (gtag.js) - Google Analytics --> <!-- Global site tag (gtag.js) - Google Analytics -->
<script <script async src="https://www.googletagmanager.com/gtag/js?id=UA-118745161-2"></script>
async
src="https://www.googletagmanager.com/gtag/js?id=UA-118745161-2"
></script>
<script> <script>
window.dataLayer = window.dataLayer || []; window.dataLayer = window.dataLayer || [];
function gtag() { function gtag(){dataLayer.push(arguments);}
dataLayer.push(arguments); gtag('js', new Date());
}
gtag("js", new Date());
gtag("config", "UA-118745161-2"); gtag('config', 'UA-118745161-2');
</script> </script>
</div> </div>
</body> </body>

View File

@ -1,4 +0,0 @@
mkdir -p app\js\
bitsadmin.exe /transfer "JobName" https://rootprojects.org/acme/bluecrypt-acme.js "%cd%\app\js\bluecrypt-acme.js"
bitsadmin.exe /transfer "JobName" https://rootprojects.org/acme/bluecrypt-acme.min.js "%cd%\app\js\bluecrypt-acme.min.js"

View File

@ -5,3 +5,16 @@ pushd app/js/
wget -c https://rootprojects.org/acme/bluecrypt-acme.js wget -c https://rootprojects.org/acme/bluecrypt-acme.js
wget -c https://rootprojects.org/acme/bluecrypt-acme.min.js wget -c https://rootprojects.org/acme/bluecrypt-acme.min.js
popd popd
mkdir -p app/js/pkijs.org/v1.3.33/
pushd app/js/pkijs.org/v1.3.33/
wget -c https://raw.githubusercontent.com/PeculiarVentures/PKI.js/41b63af760cacb565dd850fb3466ada4ca163eff/org/pkijs/common.js
wget -c https://raw.githubusercontent.com/PeculiarVentures/PKI.js/41b63af760cacb565dd850fb3466ada4ca163eff/org/pkijs/x509_schema.js
wget -c https://raw.githubusercontent.com/PeculiarVentures/PKI.js/41b63af760cacb565dd850fb3466ada4ca163eff/org/pkijs/x509_simpl.js
wget -c https://raw.githubusercontent.com/PeculiarVentures/ASN1.js/f7181c21c61e53a940ea24373ab489ad86d51bc1/org/pkijs/asn1.js
popd
mkdir -p app/js/browser-csr/v1.0.0-alpha/
pushd app/js/browser-csr/v1.0.0-alpha/
wget -c https://git.coolaj86.com/coolaj86/browser-csr.js/raw/commit/01cdc0e91b5bf03f12e1b25b4129e3cde927987c/csr.js
popd

View File

@ -1,39 +1,32 @@
(function() { (function () {
"use strict"; 'use strict';
var $qs = function(s) { var $qs = function (s) { return window.document.querySelector(s); };
return window.document.querySelector(s);
};
$qs(".js-javascript-warning").hidden = true; $qs('.js-javascript-warning').hidden = true;
var apiUrl = "https://acme-{{env}}.api.letsencrypt.org/directory"; var apiUrl = 'https://acme-{{env}}.api.letsencrypt.org/directory';
function updateApiType() { function updateApiType() {
var formData = new FormData($qs("#js-acme-form")); var formData = new FormData($qs("#js-acme-form"));
console.log("ACME api type radio:"); console.log('ACME api type radio:');
var value = formData.get("acme-api-type"); var value = formData.get("acme-api-type");
$qs("#js-acme-api-url").value = apiUrl.replace(/{{env}}/g, value); $qs('#js-acme-api-url').value = apiUrl.replace(/{{env}}/g, value);
} }
$qs("#js-acme-form").addEventListener("change", updateApiType); $qs('#js-acme-form').addEventListener('change', updateApiType);
//$qs('#js-acme-form').addEventListener('submit', prettyRedirect); //$qs('#js-acme-form').addEventListener('submit', prettyRedirect);
updateApiType(); updateApiType();
try { try {
document.fonts document.fonts.load().then(function() {
.load() $qs('body').classList.add("js-app-ready");
.then(function() { }).catch(function(e) {
$qs("body").classList.add("js-app-ready"); $qs('body').classList.add("js-app-ready");
})
.catch(function(e) {
$qs("body").classList.add("js-app-ready");
}); });
} catch (e) { } catch(e) {
setTimeout(function() { setTimeout(function() {$qs('body').classList.add("js-app-ready");}, 200);
$qs("body").classList.add("js-app-ready");
}, 200);
} }
})(); }());

View File

@ -1,315 +1,201 @@
<!DOCTYPE html> <h1>Greetings!</h1>
<html>
<head>
<title>Root Legal</title>
</head>
<body>
<h1>Greetings!</h1>
<p> <p>I, AJ ONeal, am not a big fan of legalize, but I am a fan of communicating
I, AJ ONeal, am not a big fan of legalize, but I am a fan of communicating clearly. I hope that this accomplish both defining some legal boundaries as well
clearly. I hope that this accomplish both defining some legal boundaries as communicating in a friendly and clear way, at least to the degree that suits
as well as communicating in a friendly and clear way, at least to the our needs for the current stage of our products and services.
degree that suits our needs for the current stage of our products and
services.
</p>
<p> <p>This is important because it is our intent to create sustainable open source
This is important because it is our intent to create sustainable open projects, which means that we do want to create brand value, grow community,
source projects, which means that we do want to create brand value, grow and, eventually, be able to work full time on creating more great software and services.
community, and, eventually, be able to work full time on creating more
great software and services.
</p>
<p> <p>If you'd like to contact me, especially if you feel that I (or we) have made
If you'd like to contact me, especially if you feel that I (or we) have a mistake in how we operate, please do so:
made a mistake in how we operate, please do so:
</p>
<ul> <ul>
<li><a href="mailto:coolaj86@gmail.com">coolaj86@gmail.com</a></li> <li><a href="mailto:coolaj86@gmail.com">coolaj86@gmail.com</a></li>
<li><a href="tel:+13852360466">+1 (385) 236-0466</a></li> <li><a href="tel:+13852360466">+1 (385) 236-0466</a></li>
<li><a href="http://coolaj86.com">https://coolaj86.com</a></li> <li><a href="http://coolaj86.com">https://coolaj86.com</a></li>
</ul> </ul>
<h1>Contents</h1> <h1>Contents</h1>
<p>Here's what I've worked through so far:</p> <p>Here's what I've worked through so far:
<ul> <ul>
<li><a href="#greenlock">Greelock Domains</a></li> <li><a href="#greenlock">Greelock Domains</a></li>
<li><a href="#licensing">Licensing</a></li> <li><a href="#licensing">Licensing</a></li>
<li><a href="#terms">Terms of Service</a></li> <li><a href="#terms">Terms of Service</a></li>
<li><a href="#trademark">Trademark</a></li> <li><a href="#trademark">Trademark</a></li>
<li><a href="#privacy">Privacy</a></li> <li><a href="#privacy">Privacy</a></li>
</ul> </ul>
<h1 id="greenlock">Greenlock Domains&trade;</h1> <h1 id="greenlock">Greenlock Domains&trade;</h1>
<p> <p>Greenlock Domains is a service provided by
Greenlock Domains is a service provided by <em><a href="https://coolaj86.com">AJ</a>, Brian,
<em <a href="https://jshaver.net">John</a>, &amp; Josh</em>
><a href="https://coolaj86.com">AJ</a>, Brian, (collectively <a href="https://therootcompany.com">Root</a>)
<a href="https://jshaver.net">John</a>, &amp; Josh</em for automated TLS, SSL, and HTTPS.
>
(collectively <a href="https://therootcompany.com">Root</a>) for automated
TLS, SSL, and HTTPS.
</p>
<ul> <ul>
<li> <li><a href="https://greenlock.domains" target="_blank">
<a href="https://greenlock.domains" target="_blank"> https://greenlock.domains</a></li>
https://greenlock.domains</a
>
</li>
<li> <li><a href="https://git.coolaj86.com/coolaj86/greenlock-express.js" target="_blank">
<a https://git.coolaj86.com/coolaj86/greenlock-express.js</a></li>
href="https://git.coolaj86.com/coolaj86/greenlock-express.js"
target="_blank"
>
https://git.coolaj86.com/coolaj86/greenlock-express.js</a
>
</li>
<li> <li><a href="https://git.coolaj86.com/coolaj86/greenlock.js" target="_blank">
<a https://git.coolaj86.com/coolaj86/greenlock.js</a></li>
href="https://git.coolaj86.com/coolaj86/greenlock.js"
target="_blank"
>
https://git.coolaj86.com/coolaj86/greenlock.js</a
>
</li>
<li> <li><a href="https://git.coolaj86.com/coolaj86/greenlock.html" target="_blank">
<a https://git.coolaj86.com/coolaj86/greenlock.html</a></li>
href="https://git.coolaj86.com/coolaj86/greenlock.html" </ul>
target="_blank"
>
https://git.coolaj86.com/coolaj86/greenlock.html</a
>
</li>
</ul>
<p> <p>Greenlock Domains is an important product / service combo to us
Greenlock Domains is an important product / service combo to us because because it's a huge milestone on the path to a more decentralized web.
it's a huge milestone on the path to a more decentralized web. We believe We believe in <em>ownership</em> and <em>control</em> and we're
in building a <a href="https://therootcompany.com">Home Server</a>
<em>ownership</em> and <em>control</em> and we're building a because we envision a world in which everyone is empowered to make
<a href="https://therootcompany.com">Home Server</a> because we envision a the choice of whether to rent or own their stuff.
world in which everyone is empowered to make the choice of whether to rent
or own their stuff.
</p>
<p> <p>If we don't do this, well, with the way the cloud is headed,
If we don't do this, well, with the way the cloud is headed, renting may renting may be the only option in the future.
be the only option in the future.
</p>
<p>We need <em>Root</em> because we want ownership.</p> <p>We need <em>Root</em> because we want ownership.
<p> <p>If at any time you feel that any of our messaging or practices
If at any time you feel that any of our messaging or practices are in are in conflict with our mission or these values, please let us know.
conflict with our mission or these values, please let us know.
</p>
<h1 id="licensing">Licensing</h1> <h1 id="licensing">Licensing</h1>
<p> <p>Each of our products comes with its own LICENSE file and the license(s)
Each of our products comes with its own LICENSE file and the license(s) may alse be in some sort of manifest file (such as package.json).
may alse be in some sort of manifest file (such as package.json).
</p>
<p> <p>We typically use the MIT and Apache-2.0 licenses for libraries that we
We typically use the MIT and Apache-2.0 licenses for libraries that we actively want others to copy, modify, use and redistribute.
actively want others to copy, modify, use and redistribute.
</p>
<p> <p>We typically use ISC and MPL-2.0 with products for which we're a little more
We typically use ISC and MPL-2.0 with products for which we're a little concerned about branding or about which we have particularly strong opinions.
more concerned about branding or about which we have particularly strong
opinions.
</p>
<p> <p>Although we do keep some of our software proprietary and we do use trademarks,
Although we do keep some of our software proprietary and we do use because we believe in empowerment and choice we do our best to provide usable
trademarks, because we believe in empowerment and choice we do our best to self-service forms of our products and services for personal use.
provide usable self-service forms of our products and services for
personal use.
</p>
<p> <p>If at any time you feel that our Licensing is in conflict with our mission or values,
If at any time you feel that our Licensing is in conflict with our mission please let us know.
or values, please let us know.
</p>
<h1 id="terms">Terms of Service</h1> <h1 id="terms">Terms of Service</h1>
<p> <p>We want to make the world a better place.
We want to make the world a better place. Everyone has a different Everyone has a different definition of what "a better place" means,
definition of what "a better place" means, so the purpose of our terms is so the purpose of our terms is to rule out some things that
to rule out some things that we think makes the world (and particularly we think makes the world (and particularly our world) a worse place:
our world) a worse place:
</p>
<p> <p>You agree that you will use the Greenlock&trade; service, code, libraries,
You agree that you will use the Greenlock&trade; service, code, libraries, documentation, etc (provided by <a href="#greenlock">us</a>)
documentation, etc (provided by <a href="#greenlock">us</a>) primarily for primarily for securing network connections for yourself, your customers,
securing network connections for yourself, your customers, on your and on your and your customer's devices on internets, intranets, and... other nets.
your customer's devices on internets, intranets, and... other nets.
</p>
<p> <p>You agree that you will take reasonable measures to keep up-to-date with security
You agree that you will take reasonable measures to keep up-to-date with releases.
security releases.
</p>
<p> <p>You agree to not use our products or services in a way that would cause unusual
You agree to not use our products or services in a way that would cause or undue burden on our servers or services, our partners servers or services, or our
unusual or undue burden on our servers or services, our partners servers customers servers or services, or in a way that harms or misrepresents the reputation
or services, or our customers servers or services, or in a way that harms or brand value (including causing brand confusion) of the aforementioned parties
or misrepresents the reputation or brand value (including causing brand (or really anybody).
confusion) of the aforementioned parties (or really anybody).
</p>
<p> <p>This is not to say that you can't publicly have a negative opinion, but don't
This is not to say that you can't publicly have a negative opinion, but bite the hand that feeds and don't be vicious or misrepresentative.
don't bite the hand that feeds and don't be vicious or misrepresentative.
</p>
<p> <p>If you have a use case that may be in violation of these terms (particularly
If you have a use case that may be in violation of these terms the part about undue burden), but you feel contributes to making the world a better
(particularly the part about undue burden), but you feel contributes to place, we're here to help (assuming it also aligns with our values).
making the world a better place, we're here to help (assuming it also Although it may not be appropriate to use our services, but perhaps we can help
aligns with our values). Although it may not be appropriate to use our you with a solution based on our no-cost, low-cost or open source products.
services, but perhaps we can help you with a solution based on our
no-cost, low-cost or open source products.
</p>
<p> <p>If at any time you feel that our Terms of Service are in conflict with our
If at any time you feel that our Terms of Service are in conflict with our mission or values, please let us know.
mission or values, please let us know.
</p>
<h1 id="trademark">Trademark</h1> <h1 id="trademark">Trademark</h1>
<p> <p>"Greenlock" and the "green G lock" mark are Trademarks of
"Greenlock" and the "green G lock" mark are Trademarks of <a href="https://coolaj86.com" target="_blank">AJ ONeal</a>.
<a href="https://coolaj86.com" target="_blank">AJ ONeal</a>.
</p>
<p> <p>We'll be coming out with a brand guide as to how you should use
We'll be coming out with a brand guide as to how you should use the marks. the marks. In the meantime: don't change the proportions, colors
In the meantime: don't change the proportions, colors (excepting the case (excepting the case of greyscale and black and white).
of greyscale and black and white).
</p>
<p> <p>It is appropriate to use the trademark in a way that promotes the
It is appropriate to use the trademark in a way that promotes the brand brand with proper attribution, linking to the official project repositories, etc.
with proper attribution, linking to the official project repositories,
etc.
</p>
<p> <p>It is appropriate use the name greenlock in a plugin for Greenlock&trade;,
It is appropriate use the name greenlock in a plugin for Greenlock&trade;, as long as it is clear that it is a community contribution.
as long as it is clear that it is a community contribution.
</p>
<p> <p>If you create a "hard" fork of our code or any products or services,
If you create a "hard" fork of our code or any products or services, you you should give your fork its own name, and not use ours.
should give your fork its own name, and not use ours. That sound, we That sound, we gladly welcome your suggestiosn and pull requests.
gladly welcome your suggestiosn and pull requests.
</p>
<p> <p>If you mirror our code you should make it clear that it is a mirror
If you mirror our code you should make it clear that it is a mirror and and link to the official repository.
link to the official repository. in association with usand the disclose in association with usand the disclose that you use Greenlock
that you use Greenlock
</p>
<p> <p>If at any time you feel that our Trademark policies are in conflict with our
If at any time you feel that our Trademark policies are in conflict with values, please let us know.
our values, please let us know.
</p>
<h1 id="privacy">Privacy Policy</h1> <h1 id="privacy">Privacy Policy</h1>
<p>What we collect and (more importantly) <em>Why</em>:</p> <p>What we collect and (more importantly) <em>Why</em>:
<p><strong>Name</strong>:</p> <p><strong>Name</strong>:
<p> <p>In the cases that we collect your name, it's because we want to know how to address you.
In the cases that we collect your name, it's because we want to know how All four of us want to be personable if and when we reach out.
to address you. All four of us want to be personable if and when we reach
out.
</p>
<p><strong>Email</strong>:</p> <p><strong>Email</strong>:
<p> <p>There are three main purposes for which we may use your email address:
There are three main purposes for which we may use your email address:
</p>
<p> <p>1. A one-time outreach to ask if you were able to do what you intended to do.
1. A one-time outreach to ask if you were able to do what you intended to We want to make a great product. Although open source projects traditionally have
do. We want to make a great product. Although open source projects a <em>reactive</em> approach to communication (i.e. you file a bug and wait for a response),
traditionally have a <em>reactive</em> approach to communication (i.e. you we believe that creating sustainable open source requires a <em>proactive</em> approach.
file a bug and wait for a response), we believe that creating sustainable
open source requires a <em>proactive</em> approach.
</p>
<p> <p>2. Security and legal notifications. It's important that we have a way to contact you
2. Security and legal notifications. It's important that we have a way to if we've made a mistake or discover a mistake that needs to be addressed. This
contact you if we've made a mistake or discover a mistake that needs to be may include vulnerabilities as well as mandatory upgrades (such as when a
addressed. This may include vulnerabilities as well as mandatory upgrades significant change to the Let's Encrypt API is made). Making sure that our products
(such as when a significant change to the Let's Encrypt API is made). work and are secure aligns with our values and contributes to our brand identity.
Making sure that our products work and are secure aligns with our values
and contributes to our brand identity.
</p>
<p> <p>3. Opt-in updates. Many of you want to know when we have significant feature updates
3. Opt-in updates. Many of you want to know when we have significant or when we have something that we believe is really valuable to share. We've created an
feature updates or when we have something that we believe is really opt-in avenue for that. And you can always opt-out as well.
valuable to share. We've created an opt-in avenue for that. And you can
always opt-out as well.
</p>
<p><strong>Telemetry</strong>:</p> <p><strong>Telemetry</strong>:
<p> <p>We believe that the current open source model needs improvement - it often
We believe that the current open source model needs improvement - it often relies heavily on large centralized platforms which aggregate a lot of user
relies heavily on large centralized platforms which aggregate a lot of information for the platform without appropriately targeting the relationship
user information for the platform without appropriately targeting the between authors and users of projcts (i.e. npm, github, etc). We believe that
relationship between authors and users of projcts (i.e. npm, github, etc). making open source sustainable means a greater focus on empowering authors
We believe that making open source sustainable means a greater focus on and users. We've learned from other projects (Caddy, Heroku, and others) which
empowering authors and users. We've learned from other projects (Caddy, use telemetry as part of a proactive approach to open source and we believe that
Heroku, and others) which use telemetry as part of a proactive approach to it can be a great avenue for us to be proactive as well.
open source and we believe that it can be a great avenue for us to be
proactive as well.
</p>
<p> <p>We may use telemetry about operating system, browser, node version, code version,
We may use telemetry about operating system, browser, node version, code and other system-level information to better understand how we can serve our users (you)
version, and other system-level information to better understand how we and proactively solve problems that we might not otherwise hear about. For example, if
can serve our users (you) and proactively solve problems that we might not we see many page visits in a certain browser (or installs with a new version of node),
otherwise hear about. For example, if we see many page visits in a certain but few successful registrations, we know that something is wrong.
browser (or installs with a new version of node), but few successful
registrations, we know that something is wrong.
</p>
<p><strong>Other</strong>:</p> <p><strong>Other</strong>:
<p> <p>We also use Google Analytics on our web sites for basic functionality.
We also use Google Analytics on our web sites for basic functionality. Other than that, nothing else comes to mind right now.
Other than that, nothing else comes to mind right now. As we consider what As we consider what we will do in the future, it will be measured against our mission and values.
we will do in the future, it will be measured against our mission and We never want to come across as spammy or forceful. We want to do things that help us build
values. We never want to come across as spammy or forceful. We want to do our brand, acknowledge our customers; things that are proactive, and that
things that help us build our brand, acknowledge our customers; things promote sustainable source.
that are proactive, and that promote sustainable source.
</p>
<p> <p>If at any time you feel that our Privacy policy is in conflict with our mission or values,
If at any time you feel that our Privacy policy is in conflict with our please let us know.
mission or values, please let us know.
</p>
<br /> <br>
<br /> <br>
<p>Copyright 2018 AJ ONeal</p> <p>Copyright 2018 AJ ONeal
</body>
</html>

View File

@ -10,7 +10,7 @@ body {
margin-top: 5.777777778em; margin-top: 5.777777778em;
min-height: 36em; min-height: 36em;
font-size: 18px; font-size: 18px;
font-family: "Source Sans Pro", sans-serif; font-family: 'Source Sans Pro', sans-serif;
font-stretch: normal; font-stretch: normal;
line-height: 1.33; line-height: 1.33;
letter-spacing: -0.4px; letter-spacing: -0.4px;
@ -46,7 +46,6 @@ button {
color: white; color: white;
height: 40px; height: 40px;
line-height: 1.13; line-height: 1.13;
cursor: pointer;
} }
.acme-advanced-fields { .acme-advanced-fields {
@ -69,7 +68,7 @@ input#acme-domains:before {
.domain-psuedo-input { .domain-psuedo-input {
display: inline-block; display: inline-block;
margin-right: 0.6666667em; margin-right: .6666667em;
border: solid #d9d9d9 1px; border: solid #d9d9d9 1px;
border-radius: 2px; border-radius: 2px;
padding: 0.44444444em; padding: 0.44444444em;
@ -112,4 +111,5 @@ body.js-app-ready {
margin: 0.6em; margin: 0.6em;
padding: 0.5em 1em; padding: 0.5em 1em;
width: 30em; width: 30em;
} }