configuration: Force user to agree to the authorities Terms of Service

Authorities (e.g. Let's Encrypt) usually have Terms of Serivce (ToS)
that have to be agreed to. Up until this point we automatically
indicated agreement to those ToS and sent the necessary value.

This commit changes the behaviour to be in line with recommendations
from Let's Encrypt that the user themselves have to indicate their
agreement by no longer automatically doing so (except for cases of
legacy configuration files to provide compatibility).

The user can now indicate ToS agreement by either setting the associated
configuration variable (authority_tos_agreement) to the required value
and/or providing the required value via a command-line parameter
(--authority-tos-agreement=<value>/--tos-agreement=<value>/--tos=<value>)
This commit is contained in:
Kishi85 2019-03-20 10:34:59 +01:00
parent 784badf54b
commit 316ecdba2e
5 changed files with 26 additions and 13 deletions

View File

@ -41,6 +41,8 @@ You can optionally provide the key files for the ACME protocol, if you do not th
Finally, you need to setup the configuration files, as shown in the next section.
While testing, you can use the acme-staging authority instead, in order to avoid issuing too many certificates.
Authorities (e.g. our default Let's Encrypt) will require you to accept their Terms of Service. This can be done either in the optional global config file and/or via a commandline parameter (see acertmgr.py --help).
Configuration
-------------
@ -58,12 +60,12 @@ All configuration files can use yaml (requires PyYAML) or json syntax.
#api: v1
#authority: "https://acme-v01.api.letsencrypt.org"
#authority: "https://acme-staging.api.letsencrypt.org"
#authority_agreement: "https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf"
#authority_tos_agreement: "https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf"
# Current (default) ACME v2 API with options:
#api: v2
#authority: "https://acme-v02.api.letsencrypt.org"
#authority: "https://acme-staging-v02.api.letsencrypt.org"
#authority_agreement: "True" # Indicates you agree to the ToS stated by the API provider
authority_tos_agreement: "true" # Indicates you agree to the ToS stated by the API provider
#authority_contact_email: "foo@b.ar" # For single addresses
#authority_contact_email: # For multiple addresses
# - "foo@b.ar"

View File

@ -35,7 +35,7 @@ class ACMEAuthority(AbstractACMEAuthority):
def __init__(self, config, key):
AbstractACMEAuthority.__init__(self, config, key)
self.ca = config['authority']
self.agreement = config['authority_agreement']
self.agreement = config['authority_tos_agreement']
# @brief create the header information for ACME communication
# @param key the account key

View File

@ -34,7 +34,7 @@ class ACMEAuthority(AbstractACMEAuthority):
AbstractACMEAuthority.__init__(self, config, key)
# Initialize config vars
self.ca = config['authority']
self.agreement = str(config.get('authority_agreement')) == 'true'
self.tos_agreed = str(config.get('authority_tos_agreement')).lower() == 'true'
contact_email = config.get('authority_contact_email')
if contact_email is None:
self.contact = None
@ -128,7 +128,7 @@ class ACMEAuthority(AbstractACMEAuthority):
def register_account(self):
protected = copy.deepcopy(self.account_protected)
payload = {
"termsOfServiceAgreed": self.agreement,
"termsOfServiceAgreed": self.tos_agreed,
"onlyReturnExisting": False,
}
if self.contact:

View File

@ -24,7 +24,7 @@ DEFAULT_KEY_LENGTH = 4096 # bits
DEFAULT_TTL = 30 # days
DEFAULT_API = "v2"
DEFAULT_AUTHORITY = "https://acme-v02.api.letsencrypt.org"
DEFAULT_AUTHORITY_AGREEMENT = "True"
LEGACY_AUTHORITY_TOS_AGREEMENT = "true"
# @brief augment configuration with defaults
@ -54,7 +54,7 @@ def update_config_value(config, name, localconfig, globalconfig, default):
# @brief load the configuration from a file
def parse_config_entry(entry, globalconfig, work_dir):
def parse_config_entry(entry, globalconfig, work_dir, authority_tos_agreement):
config = dict()
# Basic domain information
@ -71,8 +71,8 @@ def parse_config_entry(entry, globalconfig, work_dir):
# Certificate authority
update_config_value(config, 'authority', entry, globalconfig, DEFAULT_AUTHORITY)
# Certificate authority agreement
update_config_value(config, 'authority_agreement', entry, globalconfig, DEFAULT_AUTHORITY_AGREEMENT)
# Certificate authority ToS agreement
update_config_value(config, 'authority_tos_agreement', entry, globalconfig, authority_tos_agreement)
# Certificate authority contact email addresses
update_config_value(config, 'authority_contact_email', entry, globalconfig, None)
@ -148,6 +148,8 @@ def load():
help="domain configuration directory (default='{}')".format(DEFAULT_CONF_DIR))
parser.add_argument("-w", "--work-dir", nargs="?",
help="persistent work data directory (default=config_dir)")
parser.add_argument("--authority-tos-agreement", "--tos-agreement", "--tos", nargs="?",
help="Agree to the authorities Terms of Service (value required depends on authority)")
args = parser.parse_args()
# Determine global configuration file
@ -175,6 +177,15 @@ def load():
# .. or use the domain configuration directory otherwise
work_dir = domain_config_dir
# Determine authority agreement
if args.authority_tos_agreement:
authority_tos_agreement = args.authority_tos_agreement
elif global_config_file == LEGACY_CONF_FILE:
# Old global config file assumes ToS are agreed
authority_tos_agreement = LEGACY_AUTHORITY_TOS_AGREEMENT
else:
authority_tos_agreement = None
# load global configuration
globalconfig = dict()
if os.path.isfile(global_config_file):
@ -203,11 +214,11 @@ def load():
try:
import json
for entry in json.load(config_fd).items():
config.append(parse_config_entry(entry, globalconfig, work_dir))
config.append(parse_config_entry(entry, globalconfig, work_dir, authority_tos_agreement))
except ValueError:
import yaml
config_fd.seek(0)
for entry in yaml.safe_load(config_fd).items():
config.append(parse_config_entry(entry, globalconfig, work_dir))
config.append(parse_config_entry(entry, globalconfig, work_dir, authority_tos_agreement))
return config

View File

@ -4,12 +4,12 @@
#api: v1
#authority: "https://acme-v01.api.letsencrypt.org"
#authority: "https://acme-staging.api.letsencrypt.org"
#authority_agreement: "https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf"
#authority_tos_agreement: "https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf"
# Current (default) ACME v2 API with options:
#api: v2
#authority: "https://acme-v02.api.letsencrypt.org"
#authority: "https://acme-staging-v02.api.letsencrypt.org"
#authority_agreement: "True" # Indicates you agree to the ToS stated by the API provider
authority_tos_agreement: "true" # Indicates you agree to the ToS stated by the API provider
#authority_contact_email: "foo@b.ar" # For single addresses
#authority_contact_email: # For multiple addresses
# - "foo@b.ar"