diff --git a/certbot/cli.py b/certbot/cli.py index 97b1a5399..b4460f681 100644 --- a/certbot/cli.py +++ b/certbot/cli.py @@ -265,8 +265,9 @@ class HelpfulArgumentParser(object): self.VERBS = {"auth": main.obtain_cert, "certonly": main.obtain_cert, "config_changes": main.config_changes, "run": main.run, "install": main.install, "plugins": main.plugins_cmd, - "renew": main.renew, "revoke": main.revoke, - "rollback": main.rollback, "everything": main.run} + "register": main.register, "renew": main.renew, + "revoke": main.revoke, "rollback": main.rollback, + "everything": main.run} # List of topics for which additional help can be provided HELP_TOPICS = ["all", "security", "paths", "automation", "testing"] + list(self.VERBS) @@ -591,6 +592,11 @@ def prepare_and_parse_args(plugins, args, detect_defaults=False): "certificates. Updates to the Subscriber Agreement will still " "affect you, and will be effective 14 days after posting an " "update to the web site.") + helpful.add( + None, "--update-registration", action="store_true", + help="With the register verb, indicates that details associated " + "with an existing registration, such as the e-mail address, " + "should be updated, rather than registering a new account.") helpful.add(None, "-m", "--email", help=config_help("email")) # positional arg shadows --domains, instead of appending, and # --domains is useful, because it can be stored in config diff --git a/certbot/main.py b/certbot/main.py index 309889e8e..08a5a3ea4 100644 --- a/certbot/main.py +++ b/certbot/main.py @@ -10,6 +10,7 @@ import traceback import zope.component +from acme import errors as acme_errors from acme import jose import certbot @@ -363,6 +364,33 @@ def _init_le_client(config, authenticator, installer): return client.Client(config, acc, authenticator, installer, acme=acme) +def register(config, unused_plugins): + """Create or modify accounts on the server.""" + + # Currently, only --update-registration is implemented. Issue #2446 + # calls for a fuller register verb, to allow better separation of + # account management from obtaining certs. + if not config.update_registration: + return "Currently, only register --update-registration is implemented." + if config.email is None: + return ("Currently, --update-registration can only change the e-mail " + "address\nassociated with an account. A new e-mail address is " + "required\n(hint: --email)") + acc, acme = _determine_account(config) + acme_client = client.Client(config, acc, None, None, acme=acme) + try: + updated_reg = client.messages.Registration.from_data(email=config.email) + acme_client.acme.update_registration(acme_client.account.regr, + updated_reg) + except acme_errors.UnexpectedUpdate: + # We expect the unexpected update! + pass + query_data = acme_client.acme.query_registration(acme_client.account.regr) + # We rely on an ACME exception to interrupt this process if it didn't work. + print("Registration change succeeded. New registration data:\n") + print(query_data) + + def install(config, plugins): """Install a previously obtained cert in a server.""" # XXX: Update for renewer/RenewableCert