diff --git a/.gitignore b/.gitignore index 77a795fa0..e06399ff4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ *.pyc +*.egg-info +build/ +dist/ m3 diff --git a/MANIFEST.in b/MANIFEST.in index 192128adf..caf2ae794 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1 +1,6 @@ -recursive-include letsencrypt/ * +recursive-include letsencrypt *.json +recursive-include letsencrypt *.sh +recursive-include letsencrypt *.conf +recursive-include letsencrypt *.cnf +include letsencrypt/client/ca_offerings +include letsencrypt/client/.ca_offerings diff --git a/README.md b/README.md index d0a11788c..5935845bf 100644 --- a/README.md +++ b/README.md @@ -6,32 +6,34 @@ This code intended for testing, demonstration, and integration engineering with OSes and hosting platforms. Currently the code works with Linux and Apache, though we will be expanding it to other platforms. -## Running the demo code on Ubuntu +## Running the demo code on Ubuntu -`sudo apt-get install python-pip python-crypto python-dev python-jsonschema python-augeas gcc python-m2crypto python-dialog` +`sudo apt-get install python python-setuptools python-dev python-augeas gcc` -`sudo pip install jose` +`python setup.py install --user` -`sudo ./letsencrypt.py` +`sudo ./letsencrypt.py` (or `~/.local/bin/letsencrypt`) -Hint: on Debian testing/unstable, python-dialog is unavailable and you may -need to do `sudo pip install python2-pythondialog` (lets-encrypt does not yet -handle debian unstable's Apache2 conf layout, either...) +Note, that letsencrypt does not yet handle Debian unstable's Apache2 +conf layout. +## Developing + +`python setup.py develop --user` ## Command line usage ``` -sudo ./letsencrypt.py (default authentication mode using pythondialog) options +sudo ./letsencrypt.py (default authentication mode using pythondialog) options ---text (text mode) ---privkey= (specify privatekey file to use to generate the certificate) ---csr= (Use a specific CSR. If this is specified, privkey must also be specified with the correct private key for the CSR) +--text (text mode) +--privkey= (specify privatekey file to use to generate the certificate) +--csr= (Use a specific CSR. If this is specified, privkey must also be specified with the correct private key for the CSR) --server (list the ACME CA server address) --revoke (revoke a certificate) --view-checkpoints (Used to view available checkpoints and see what configuration changes have been made) ---rollback=X (Revert the configuration X number of checkpoints) ---redirect (Automatically redirect all HTTP traffic to HTTPS for the newly authenticated vhost) +--rollback=X (Revert the configuration X number of checkpoints) +--redirect (Automatically redirect all HTTP traffic to HTTPS for the newly authenticated vhost) --no-redirect (Skip the HTTPS redirect question, allowing both HTTP and HTTPS) --agree-eula (Skip the end user agreement screen) ``` diff --git a/letsencrypt.py b/letsencrypt.py deleted file mode 100755 index 20f4f6ffb..000000000 --- a/letsencrypt.py +++ /dev/null @@ -1,121 +0,0 @@ -#!/usr/bin/env python - -# This file parses the command line and calls the appropriate functions - -import getopt -import os -import sys - -from letsencrypt.client import client -from letsencrypt.client import display -from letsencrypt.client.CONFIG import ACME_SERVER - -def main(): - # Check to make sure user is root - if not os.geteuid() == 0: - sys.exit("\nOnly root can run letsencrypt.\n") - # Parse options - try: - opts, args = getopt.getopt(sys.argv[1:], "", ["text", "test", - "view-checkpoints", - "privkey=", "csr=", - "server=", "rollback=", - "revoke", "agree-eula", - "redirect", - "no-redirect", - "help"]) - except getopt.GetoptError as err: - # print help info and exit - print str(err) - usage() - sys.exit(2) - - server = None - csr = None - privkey = None - curses = True - names = args - flag_revoke = False - redirect = None - eula = False - - for o, a in opts: - if o == "--text": - curses = False - elif o == "--csr": - csr = a - elif o == "--privkey": - privkey = a - elif o == "--server": - server = a - elif o == "--rollback": - from letsencrypt.client import configurator, logger - logger.setLogger(logger.FileLogger(sys.stdout)) - logger.setLogLevel(logger.INFO) - config = configurator.Configurator() - config.rollback_checkpoints(a) - config.restart() - sys.exit(0) - elif o == "--view-checkpoints": - from letsencrypt.client import configurator, logger - logger.setLogger(logger.FileLogger(sys.stdout)) - logger.setLogLevel(logger.INFO) - config = configurator.Configurator() - config.display_checkpoints() - sys.exit(0) - elif o == "--revoke": - # Do Stuff - flag_revoke = True - elif o == "--redirect": - redirect = True - elif o == "--no-redirect": - redirect = False - elif o == "--agree-eula": - eula = True - elif o == "--help": - print_options() - elif o == "--test": - #put any temporary tests in here - continue - - if curses: - display.setDisplay(display.NcursesDisplay()) - else: - display.setDisplay(display.FileDisplay(sys.stdout)) - - if not server: - server = ACME_SERVER - - c = client.Client(server, csr, privkey, curses) - if flag_revoke: - c.list_certs_keys() - else: - c.authenticate(args, redirect, eula) - -def usage(): - s = "Available options: --text, --privkey=, --csr=, --server=, " - s += "--rollback=, --view-checkpoints, --revoke, --agree-eula, --redirect," - s += " --no-redirect, --help" - print s - -def print_options(): - print "\nsudo ./letsencrypt.py (default authentication mode using pythondialog)" - options = [ "privkey= (specify privatekey file to use to generate the certificate)", - "csr= (Use a specific CSR. If this is specified, privkey " + - "must also be specified with the correct private key for the CSR)", - "server (list the ACME CA server address)", - "revoke (revoke a certificate)", - "view-checkpoints (Used to view available checkpoints and " + - "see what configuration changes have been made)", - "rollback=X (Revert the configuration X number of checkpoints)", - "redirect (Automatically redirect all HTTP traffic to " + - "HTTPS for the newly authenticated vhost)", - "no-redirect (Skip the HTTPS redirect question, " + - "allowing both HTTP and HTTPS)", - "agree-eula (Skip the end user agreement screen)" ] - for o in options: - print " --%s" % o - sys.exit(0) - -if __name__ == "__main__": - main() diff --git a/letsencrypt.py b/letsencrypt.py new file mode 120000 index 000000000..77b93ee70 --- /dev/null +++ b/letsencrypt.py @@ -0,0 +1 @@ +letsencrypt/scripts/main.py \ No newline at end of file diff --git a/letsencrypt/client/acme.py b/letsencrypt/client/acme.py index 70a5982ad..633b8c2b6 100755 --- a/letsencrypt/client/acme.py +++ b/letsencrypt/client/acme.py @@ -4,8 +4,10 @@ # validate JSON objects as ACME protocol messages import json, jsonschema +import pkg_resources -schemata = {schema: json.load(open("letsencrypt/client/schemata/%s.json" % schema)) for schema in [ +schemata = {schema: json.load(open(pkg_resources.resource_filename( + __name__, "schemata/%s.json" % schema))) for schema in [ "authorization", "authorizationRequest", "certificate", "certificateRequest", "challenge", "challengeRequest", "defer", "error", "revocation", "revocationRequest", "statusRequest"] diff --git a/letsencrypt/scripts/__init__.py b/letsencrypt/scripts/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/letsencrypt/scripts/main.py b/letsencrypt/scripts/main.py new file mode 100755 index 000000000..20f4f6ffb --- /dev/null +++ b/letsencrypt/scripts/main.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python + +# This file parses the command line and calls the appropriate functions + +import getopt +import os +import sys + +from letsencrypt.client import client +from letsencrypt.client import display +from letsencrypt.client.CONFIG import ACME_SERVER + +def main(): + # Check to make sure user is root + if not os.geteuid() == 0: + sys.exit("\nOnly root can run letsencrypt.\n") + # Parse options + try: + opts, args = getopt.getopt(sys.argv[1:], "", ["text", "test", + "view-checkpoints", + "privkey=", "csr=", + "server=", "rollback=", + "revoke", "agree-eula", + "redirect", + "no-redirect", + "help"]) + except getopt.GetoptError as err: + # print help info and exit + print str(err) + usage() + sys.exit(2) + + server = None + csr = None + privkey = None + curses = True + names = args + flag_revoke = False + redirect = None + eula = False + + for o, a in opts: + if o == "--text": + curses = False + elif o == "--csr": + csr = a + elif o == "--privkey": + privkey = a + elif o == "--server": + server = a + elif o == "--rollback": + from letsencrypt.client import configurator, logger + logger.setLogger(logger.FileLogger(sys.stdout)) + logger.setLogLevel(logger.INFO) + config = configurator.Configurator() + config.rollback_checkpoints(a) + config.restart() + sys.exit(0) + elif o == "--view-checkpoints": + from letsencrypt.client import configurator, logger + logger.setLogger(logger.FileLogger(sys.stdout)) + logger.setLogLevel(logger.INFO) + config = configurator.Configurator() + config.display_checkpoints() + sys.exit(0) + elif o == "--revoke": + # Do Stuff + flag_revoke = True + elif o == "--redirect": + redirect = True + elif o == "--no-redirect": + redirect = False + elif o == "--agree-eula": + eula = True + elif o == "--help": + print_options() + elif o == "--test": + #put any temporary tests in here + continue + + if curses: + display.setDisplay(display.NcursesDisplay()) + else: + display.setDisplay(display.FileDisplay(sys.stdout)) + + if not server: + server = ACME_SERVER + + c = client.Client(server, csr, privkey, curses) + if flag_revoke: + c.list_certs_keys() + else: + c.authenticate(args, redirect, eula) + +def usage(): + s = "Available options: --text, --privkey=, --csr=, --server=, " + s += "--rollback=, --view-checkpoints, --revoke, --agree-eula, --redirect," + s += " --no-redirect, --help" + print s + +def print_options(): + print "\nsudo ./letsencrypt.py (default authentication mode using pythondialog)" + options = [ "privkey= (specify privatekey file to use to generate the certificate)", + "csr= (Use a specific CSR. If this is specified, privkey " + + "must also be specified with the correct private key for the CSR)", + "server (list the ACME CA server address)", + "revoke (revoke a certificate)", + "view-checkpoints (Used to view available checkpoints and " + + "see what configuration changes have been made)", + "rollback=X (Revert the configuration X number of checkpoints)", + "redirect (Automatically redirect all HTTP traffic to " + + "HTTPS for the newly authenticated vhost)", + "no-redirect (Skip the HTTPS redirect question, " + + "allowing both HTTP and HTTPS)", + "agree-eula (Skip the end user agreement screen)" ] + for o in options: + print " --%s" % o + sys.exit(0) + +if __name__ == "__main__": + main() diff --git a/setup.py b/setup.py index 0d79a5762..4b1388cc8 100755 --- a/setup.py +++ b/setup.py @@ -1,5 +1,7 @@ #!/usr/bin/env python from setuptools import setup + + setup( name="letsencrypt", version="0.1", @@ -10,6 +12,7 @@ setup( packages=[ 'letsencrypt', 'letsencrypt.client', + 'letsencrypt.scripts', ], install_requires=[ #'dialog', @@ -23,7 +26,9 @@ setup( ], entry_points={ 'console_scripts': [ - 'letsencrypt = letsencrypt.client.client:authenticate' + 'letsencrypt = letsencrypt.scripts.main:main' ] }, + zip_safe=False, + include_package_data=True, )