-
Notifications
You must be signed in to change notification settings - Fork 572
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
https://datatracker.ietf.org/doc/html/rfc8555#section-7.3.4 Bonus: also implement https://datatracker.ietf.org/doc/html/rfc8555#section-7.3.3 (which will never happen on Letsencrypt, but may on other CAs) Send contact at register time if available (some CAs mandate this) Renamed `account` variable to the more appropriate: `response`. That is what this variable holds.
- Loading branch information
1 parent
ce0bbdb
commit a316469
Showing
2 changed files
with
32 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -122,6 +122,21 @@ and read your private account key and CSR. | |
python acme_tiny.py --account-key ./account.key --csr ./domain.csr --acme-dir /var/www/challenges/ > ./signed_chain.crt | ||
``` | ||
|
||
If your ACME CA mandates externalAccountBinding (eAB), provide those parameters like so: | ||
|
||
``` | ||
# Run the script on your server | ||
python acme_tiny.py --account-key ./account.key --csr ./domain.csr --acme-dir /var/www/challenges/ --eabkid 'PAtzxcSFQMQSdm9SLJTxCt0hwvvl5yNKPfnWBWqPk8o' --eabhmackey 'ZndUSkZvVldvMEFiRzQ5VWNCdERtNkNBNnBTcTl4czNKVEVxdUZiaEdpZXZNUVJBVmRuSFREcDJYX2s3X0NxTA' > ./signed_chain.crt | ||
``` | ||
|
||
Some ACME CA mandate a contact at registration: | ||
|
||
``` | ||
# Run the script on your server | ||
python acme_tiny.py --account-key ./account.key --csr ./domain.csr --acme-dir /var/www/challenges/ --contact [email protected] --eabkid 'PAtzxcSFQMQSdm9SLJTxCt0hwvvl5yNKPfnWBWqPk8o' --eabhmackey 'ZndUSkZvVldvMEFiRzQ5VWNCdERtNkNBNnBTcTl4czNKVEVxdUZiaEdpZXZNUVJBVmRuSFREcDJYX2s3X0NxTA' > ./signed_chain.crt | ||
``` | ||
|
||
|
||
### Step 5: Install the certificate | ||
|
||
The signed https certificate chain that is output by this script can be used along | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
#!/usr/bin/env python | ||
# Copyright Daniel Roesler, under MIT license, see LICENSE at github.com/diafygi/acme-tiny | ||
import argparse, subprocess, json, os, sys, base64, binascii, time, hashlib, re, copy, textwrap, logging | ||
import argparse, subprocess, json, os, sys, base64, binascii, time, hashlib, re, copy, textwrap, logging, hmac | ||
try: | ||
from urllib.request import urlopen, Request # Python 3 | ||
except ImportError: # pragma: no cover | ||
|
@@ -13,7 +13,7 @@ | |
LOGGER.addHandler(logging.StreamHandler()) | ||
LOGGER.setLevel(logging.INFO) | ||
|
||
def get_crt(account_key, csr, acme_dir, log=LOGGER, CA=DEFAULT_CA, disable_check=False, directory_url=DEFAULT_DIRECTORY_URL, contact=None, check_port=None): | ||
def get_crt(account_key, csr, acme_dir, log=LOGGER, CA=DEFAULT_CA, disable_check=False, directory_url=DEFAULT_DIRECTORY_URL, contact=None, check_port=None, eabkid=None, eabhmackey=None): | ||
directory, acct_headers, alg, jwk = None, None, None, None # global variables | ||
|
||
# helper functions - base64 encode for jose spec | ||
|
@@ -108,11 +108,19 @@ def _poll_until_not(url, pending_statuses, err_msg): | |
# create account, update contact details (if any), and set the global key identifier | ||
log.info("Registering account...") | ||
reg_payload = {"termsOfServiceAgreed": True} if contact is None else {"termsOfServiceAgreed": True, "contact": contact} | ||
account, code, acct_headers = _send_signed_request(directory['newAccount'], reg_payload, "Error registering") | ||
if eabkid and eabhmackey: # https://datatracker.ietf.org/doc/html/rfc8555#section-7.3.4 | ||
log.info("Building externalAccountBinding...") | ||
reg_payload['externalAccountBinding'] = _build_eab(directory['newAccount'], eabkid, eabhmackey, jwk) | ||
if contact: # some providers, e.g. buypass mandate contact at registration | ||
reg_payload["contact"] = contact | ||
response, code, acct_headers = _send_signed_request(directory['newAccount'], reg_payload, "Error registering") | ||
log.info("{0} Account ID: {1}".format("Registered!" if code == 201 else "Already registered!", acct_headers['Location'])) | ||
if contact is not None: | ||
account, _, _ = _send_signed_request(acct_headers['Location'], {"contact": contact}, "Error updating contact details") | ||
log.info("Updated contact details:\n{0}".format("\n".join(account['contact']))) | ||
if contact and code == 200: # 200 == already reg --> update | ||
response, _, _ = _send_signed_request(acct_headers['Location'], {"contact": contact}, "Error updating contact details") | ||
log.info("Updated contact details:\n{0}".format("\n".join(response['contact']))) | ||
# https://datatracker.ietf.org/doc/html/rfc8555#section-7.3.3 : #userActionRequired only for TOS in RFC8555 | ||
if code == 403 and response['type'] == 'urn:ietf:params:acme:error:userActionRequired': | ||
log.info("You must agree to updated TOS:\n", response['instance']) | ||
|
||
# create a new order | ||
log.info("Creating new order...") | ||
|
@@ -189,10 +197,12 @@ def main(argv=None): | |
parser.add_argument("--ca", default=DEFAULT_CA, help="DEPRECATED! USE --directory-url INSTEAD!") | ||
parser.add_argument("--contact", metavar="CONTACT", default=None, nargs="*", help="Contact details (e.g. mailto:[email protected]) for your account-key") | ||
parser.add_argument("--check-port", metavar="PORT", default=None, help="what port to use when self-checking the challenge file, default is port 80") | ||
parser.add_argument("--eabkid", metavar="KID", default=None, help="Key Identifier for External Account Binding") | ||
parser.add_argument("--eabhmackey", metavar="HMAC", default=None, help="HMAC key for External Account Binding") | ||
|
||
args = parser.parse_args(argv) | ||
LOGGER.setLevel(args.quiet or LOGGER.level) | ||
signed_crt = get_crt(args.account_key, args.csr, args.acme_dir, log=LOGGER, CA=args.ca, disable_check=args.disable_check, directory_url=args.directory_url, contact=args.contact, check_port=args.check_port) | ||
signed_crt = get_crt(args.account_key, args.csr, args.acme_dir, log=LOGGER, CA=args.ca, disable_check=args.disable_check, directory_url=args.directory_url, contact=args.contact, check_port=args.check_port, eabkid=args.eabkid, eabhmackey=args.eabhmackey) | ||
sys.stdout.write(signed_crt) | ||
|
||
if __name__ == "__main__": # pragma: no cover | ||
|