mirror of
https://github.com/certbot/certbot.git
synced 2026-07-28 00:24:35 +02:00
Merge remote-tracking branch 'origin/master' into explain_no_ip_certs
This commit is contained in:
+6
-6
@@ -38,20 +38,20 @@ matrix:
|
||||
env: TOXENV=py27 BOULDER_INTEGRATION=1
|
||||
- python: "2.7"
|
||||
env: TOXENV=py27-oldest BOULDER_INTEGRATION=1
|
||||
- python: "2.7"
|
||||
env: TOXENV=cover
|
||||
- python: "2.7"
|
||||
env: TOXENV=lint
|
||||
- sudo: required
|
||||
env: TOXENV=le_auto
|
||||
services: docker
|
||||
before_install:
|
||||
- python: "2.7"
|
||||
env: TOXENV=cover
|
||||
- python: "3.3"
|
||||
env: TOXENV=py33
|
||||
- python: "3.4"
|
||||
env: TOXENV=py34
|
||||
- python: "3.5"
|
||||
env: TOXENV=py35
|
||||
- sudo: required
|
||||
env: TOXENV=le_auto
|
||||
services: docker
|
||||
before_install:
|
||||
|
||||
# Only build pushes to the master branch, PRs, and branches beginning with
|
||||
# `test-`. This reduces the number of simultaneous Travis runs, which speeds
|
||||
|
||||
+1
-1
@@ -58,7 +58,7 @@ RUN virtualenv --no-site-packages -p python2 /opt/letsencrypt/venv && \
|
||||
-e /opt/letsencrypt/src/letsencrypt-nginx \
|
||||
-e /opt/letsencrypt/src/letshelp-letsencrypt \
|
||||
-e /opt/letsencrypt/src/letsencrypt-compatibility-test \
|
||||
-e /opt/letsencrypt/src[dev,docs,testing]
|
||||
-e /opt/letsencrypt/src[dev,docs]
|
||||
|
||||
# install in editable mode (-e) to save space: it's not possible to
|
||||
# "rm -rf /opt/letsencrypt/src" (it's stays in the underlaying image);
|
||||
|
||||
+4
-4
@@ -51,11 +51,11 @@ client will guide you through the process of obtaining and installing certs
|
||||
interactively.
|
||||
|
||||
You can also tell it exactly what you want it to do from the command line.
|
||||
For instance, if you want to obtain a cert for ``thing.com``,
|
||||
``www.thing.com``, and ``otherthing.net``, using the Apache plugin to both
|
||||
For instance, if you want to obtain a cert for ``example.com``,
|
||||
``www.example.com``, and ``other.example.net``, using the Apache plugin to both
|
||||
obtain and install the certs, you could do this::
|
||||
|
||||
./letsencrypt-auto --apache -d thing.com -d www.thing.com -d otherthing.net
|
||||
./letsencrypt-auto --apache -d example.com -d www.example.com -d other.example.net
|
||||
|
||||
(The first time you run the command, it will make an account, and ask for an
|
||||
email and agreement to the Let's Encrypt Subscriber Agreement; you can
|
||||
@@ -64,7 +64,7 @@ automate those with ``--email`` and ``--agree-tos``)
|
||||
If you want to use a webserver that doesn't have full plugin support yet, you
|
||||
can still use "standalone" or "webroot" plugins to obtain a certificate::
|
||||
|
||||
./letsencrypt-auto certonly --standalone --email admin@thing.com -d thing.com -d www.thing.com -d otherthing.net
|
||||
./letsencrypt-auto certonly --standalone --email admin@example.com -d example.com -d www.example.com -d other.example.net
|
||||
|
||||
|
||||
Understanding the client in more depth
|
||||
|
||||
Vendored
+9
@@ -5,10 +5,19 @@
|
||||
VAGRANTFILE_API_VERSION = "2"
|
||||
|
||||
# Setup instructions from docs/contributing.rst
|
||||
# Script installs dependencies for tox and boulder integration
|
||||
$ubuntu_setup_script = <<SETUP_SCRIPT
|
||||
cd /vagrant
|
||||
./letsencrypt-auto-source/letsencrypt-auto --os-packages-only
|
||||
./tools/venv.sh
|
||||
wget https://storage.googleapis.com/golang/go1.5.3.linux-amd64.tar.gz -P /tmp/
|
||||
sudo tar -C /usr/local -xzf /tmp/go1.5.3.linux-amd64.tar.gz
|
||||
if ! grep -Fxq "export GOROOT=/usr/local/go" /home/vagrant/.profile ; then echo "export GOROOT=/usr/local/go" >> /home/vagrant/.profile; fi
|
||||
if ! grep -Fxq "export PATH=\\$GOROOT/bin:\\$PATH" /home/vagrant/.profile ; then echo "export PATH=\\$GOROOT/bin:\\$PATH" >> /home/vagrant/.profile; fi
|
||||
if ! grep -Fxq "export GOPATH=\\$HOME/go" /home/vagrant/.profile ; then echo "export GOPATH=\\$HOME/go" >> /home/vagrant/.profile; fi
|
||||
if ! grep -Fxq "cd /vagrant/; ./tests/boulder-start.sh &" /etc/rc.local ; then sed -i -e '$i \cd /vagrant/; ./tests/boulder-start.sh &\n' /etc/rc.local; fi
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
sudo -E apt-get -q -y install git make libltdl-dev mariadb-server rabbitmq-server nginx-light
|
||||
SETUP_SCRIPT
|
||||
|
||||
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
||||
|
||||
+11
-10
@@ -180,40 +180,41 @@ class Client(object): # pylint: disable=too-many-instance-attributes
|
||||
raise errors.UnexpectedUpdate(authzr)
|
||||
return authzr
|
||||
|
||||
def request_challenges(self, identifier, new_authzr_uri):
|
||||
def request_challenges(self, identifier, new_authzr_uri=None):
|
||||
"""Request challenges.
|
||||
|
||||
:param identifier: Identifier to be challenged.
|
||||
:type identifier: `.messages.Identifier`
|
||||
|
||||
:param str new_authzr_uri: new-authorization URI
|
||||
:param .messages.Identifier identifier: Identifier to be challenged.
|
||||
:param str new_authzr_uri: ``new-authorization`` URI. If omitted,
|
||||
will default to value found in ``directory``.
|
||||
|
||||
:returns: Authorization Resource.
|
||||
:rtype: `.AuthorizationResource`
|
||||
|
||||
"""
|
||||
new_authz = messages.NewAuthorization(identifier=identifier)
|
||||
response = self.net.post(new_authzr_uri, new_authz)
|
||||
response = self.net.post(self.directory.new_authz
|
||||
if new_authzr_uri is None else new_authzr_uri,
|
||||
new_authz)
|
||||
# TODO: handle errors
|
||||
assert response.status_code == http_client.CREATED
|
||||
return self._authzr_from_response(response, identifier)
|
||||
|
||||
def request_domain_challenges(self, domain, new_authz_uri):
|
||||
def request_domain_challenges(self, domain, new_authzr_uri=None):
|
||||
"""Request challenges for domain names.
|
||||
|
||||
This is simply a convenience function that wraps around
|
||||
`request_challenges`, but works with domain names instead of
|
||||
generic identifiers.
|
||||
generic identifiers. See ``request_challenges`` for more
|
||||
documentation.
|
||||
|
||||
:param str domain: Domain name to be challenged.
|
||||
:param str new_authzr_uri: new-authorization URI
|
||||
|
||||
:returns: Authorization Resource.
|
||||
:rtype: `.AuthorizationResource`
|
||||
|
||||
"""
|
||||
return self.request_challenges(messages.Identifier(
|
||||
typ=messages.IDENTIFIER_FQDN, value=domain), new_authz_uri)
|
||||
typ=messages.IDENTIFIER_FQDN, value=domain), new_authzr_uri)
|
||||
|
||||
def answer_challenge(self, challb, response):
|
||||
"""Answer challenge.
|
||||
|
||||
@@ -38,6 +38,8 @@ class ClientTest(unittest.TestCase):
|
||||
'https://www.letsencrypt-demo.org/acme/new-reg',
|
||||
messages.Revocation:
|
||||
'https://www.letsencrypt-demo.org/acme/revoke-cert',
|
||||
messages.NewAuthorization:
|
||||
'https://www.letsencrypt-demo.org/acme/new-authz',
|
||||
})
|
||||
|
||||
from acme.client import Client
|
||||
@@ -142,7 +144,7 @@ class ClientTest(unittest.TestCase):
|
||||
regr = self.client.update_registration.call_args[0][0]
|
||||
self.assertEqual(self.regr.terms_of_service, regr.body.agreement)
|
||||
|
||||
def test_request_challenges(self):
|
||||
def _prepare_response_for_request_challenges(self):
|
||||
self.response.status_code = http_client.CREATED
|
||||
self.response.headers['Location'] = self.authzr.uri
|
||||
self.response.json.return_value = self.authz.to_json()
|
||||
@@ -150,10 +152,20 @@ class ClientTest(unittest.TestCase):
|
||||
'next': {'url': self.authzr.new_cert_uri},
|
||||
}
|
||||
|
||||
self.client.request_challenges(self.identifier, self.authzr.uri)
|
||||
# TODO: test POST call arguments
|
||||
def test_request_challenges(self):
|
||||
self._prepare_response_for_request_challenges()
|
||||
self.client.request_challenges(self.identifier)
|
||||
self.net.post.assert_called_once_with(
|
||||
self.directory.new_authz,
|
||||
messages.NewAuthorization(identifier=self.identifier))
|
||||
|
||||
# TODO: split here and separate test
|
||||
def test_requets_challenges_custom_uri(self):
|
||||
self._prepare_response_for_request_challenges()
|
||||
self.client.request_challenges(self.identifier, 'URI')
|
||||
self.net.post.assert_called_once_with('URI', mock.ANY)
|
||||
|
||||
def test_request_challenges_unexpected_update(self):
|
||||
self._prepare_response_for_request_challenges()
|
||||
self.response.json.return_value = self.authz.update(
|
||||
identifier=self.identifier.update(value='foo')).to_json()
|
||||
self.assertRaises(
|
||||
@@ -162,15 +174,20 @@ class ClientTest(unittest.TestCase):
|
||||
|
||||
def test_request_challenges_missing_next(self):
|
||||
self.response.status_code = http_client.CREATED
|
||||
self.assertRaises(
|
||||
errors.ClientError, self.client.request_challenges,
|
||||
self.identifier, self.regr)
|
||||
self.assertRaises(errors.ClientError, self.client.request_challenges,
|
||||
self.identifier)
|
||||
|
||||
def test_request_domain_challenges(self):
|
||||
self.client.request_challenges = mock.MagicMock()
|
||||
self.assertEqual(
|
||||
self.client.request_challenges(self.identifier),
|
||||
self.client.request_domain_challenges('example.com', self.regr))
|
||||
self.client.request_domain_challenges('example.com'))
|
||||
|
||||
def test_request_domain_challenges_custom_uri(self):
|
||||
self.client.request_challenges = mock.MagicMock()
|
||||
self.assertEqual(
|
||||
self.client.request_challenges(self.identifier, 'URI'),
|
||||
self.client.request_domain_challenges('example.com', 'URI'))
|
||||
|
||||
def test_answer_challenge(self):
|
||||
self.response.links['up'] = {'url': self.challr.authzr_uri}
|
||||
|
||||
+7
-6
@@ -34,17 +34,18 @@ if sys.version_info < (2, 7):
|
||||
else:
|
||||
install_requires.append('mock')
|
||||
|
||||
dev_extras = [
|
||||
'nose',
|
||||
'pep8',
|
||||
'tox',
|
||||
]
|
||||
|
||||
docs_extras = [
|
||||
'Sphinx>=1.0', # autodoc_member_order = 'bysource', autodoc_default_flags
|
||||
'sphinx_rtd_theme',
|
||||
'sphinxcontrib-programoutput',
|
||||
]
|
||||
|
||||
testing_extras = [
|
||||
'nose',
|
||||
'tox',
|
||||
]
|
||||
|
||||
|
||||
setup(
|
||||
name='acme',
|
||||
@@ -74,8 +75,8 @@ setup(
|
||||
include_package_data=True,
|
||||
install_requires=install_requires,
|
||||
extras_require={
|
||||
'dev': dev_extras,
|
||||
'docs': docs_extras,
|
||||
'testing': testing_extras,
|
||||
},
|
||||
entry_points={
|
||||
'console_scripts': [
|
||||
|
||||
+1
-1
@@ -139,7 +139,7 @@ client's priorities. The Mozilla security team is likely to have more
|
||||
resources and expertise to bring to bear on evaluating reasons why its
|
||||
recommendations should be updated.
|
||||
|
||||
The Let's Encrpyt project will entertain proposals to create a *very*
|
||||
The Let's Encrypt project will entertain proposals to create a *very*
|
||||
small number of alternative configurations (apart from Modern,
|
||||
Intermediate, and Old) that there's reason to believe would be widely
|
||||
used by sysadmins; this would usually be a preferable course to modifying
|
||||
|
||||
@@ -96,6 +96,14 @@ Integration testing with the boulder CA
|
||||
Generally it is sufficient to open a pull request and let Github and Travis run
|
||||
integration tests for you.
|
||||
|
||||
However, if you prefer to run tests, you can use Vagrant, using the Vagrantfile
|
||||
in Let's Encrypt's repository. To execute the tests on a Vagrant box, the only
|
||||
command you are required to run is::
|
||||
|
||||
./tests/boulder-integration.sh
|
||||
|
||||
Otherwise, please follow the following instructions.
|
||||
|
||||
Mac OS X users: Run ``./tests/mac-bootstrap.sh`` instead of
|
||||
``boulder-start.sh`` to install dependencies, configure the
|
||||
environment, and start boulder.
|
||||
|
||||
+148
-48
@@ -49,7 +49,7 @@ or for full help, type:
|
||||
|
||||
``letsencrypt-auto`` is the recommended method of running the Let's Encrypt
|
||||
client beta releases on systems that don't have a packaged version. Debian,
|
||||
Arch linux, FreeBSD, and OpenBSD now have native packages, so on those
|
||||
Arch Linux, Gentoo, FreeBSD, and OpenBSD now have native packages, so on those
|
||||
systems you can just install ``letsencrypt`` (and perhaps
|
||||
``letsencrypt-apache``). If you'd like to run the latest copy from Git, or
|
||||
run your own locally modified copy of the client, follow the instructions in
|
||||
@@ -71,7 +71,9 @@ Plugin Auth Inst Notes
|
||||
=========== ==== ==== ===============================================================
|
||||
apache_ Y Y Automates obtaining and installing a cert with Apache 2.4 on
|
||||
Debian-based distributions with ``libaugeas0`` 1.0+.
|
||||
standalone_ Y N Uses a "standalone" webserver to obtain a cert.
|
||||
standalone_ Y N Uses a "standalone" webserver to obtain a cert. This is useful
|
||||
on systems with no webserver, or when direct integration with
|
||||
the local webserver is not supported or not desired.
|
||||
webroot_ Y N Obtains a cert by writing to the webroot directory of an
|
||||
already running webserver.
|
||||
manual_ Y N Helps you obtain a cert by giving you instructions to perform
|
||||
@@ -91,6 +93,46 @@ This automates both obtaining *and* installing certs on an Apache
|
||||
webserver. To specify this plugin on the command line, simply include
|
||||
``--apache``.
|
||||
|
||||
Webroot
|
||||
-------
|
||||
|
||||
If you're running a local webserver for which you have the ability
|
||||
to modify the content being served, and you'd prefer not to stop the
|
||||
webserver during the certificate issuance process, you can use the webroot
|
||||
plugin to obtain a cert by including ``certonly`` and ``--webroot`` on
|
||||
the command line. In addition, you'll need to specify ``--webroot-path``
|
||||
or ``-w`` with the top-level directory ("web root") containing the files
|
||||
served by your webserver. For example, ``--webroot-path /var/www/html``
|
||||
or ``--webroot-path /usr/share/nginx/html`` are two common webroot paths.
|
||||
|
||||
If you're getting a certificate for many domains at once, the plugin
|
||||
needs to know where each domain's files are served from, which could
|
||||
potentially be a separate directory for each domain. When requested a
|
||||
certificate for multiple domains, each domain will use the most recently
|
||||
specified ``--webroot-path``. So, for instance,
|
||||
|
||||
``letsencrypt certonly --webroot -w /var/www/example/ -d www.example.com -d example.com -w /var/www/other -d other.example.net -d another.other.example.net``
|
||||
|
||||
would obtain a single certificate for all of those names, using the
|
||||
``/var/www/example`` webroot directory for the first two, and
|
||||
``/var/www/other`` for the second two.
|
||||
|
||||
The webroot plugin works by creating a temporary file for each of your requested
|
||||
domains in ``${webroot-path}/.well-known/acme-challenge``. Then the Let's
|
||||
Encrypt validation server makes HTTP requests to validate that the DNS for each
|
||||
requested domain resolves to the server running letsencrypt. An example request
|
||||
made to your web server would look like:
|
||||
|
||||
::
|
||||
|
||||
66.133.109.36 - - [05/Jan/2016:20:11:24 -0500] "GET /.well-known/acme-challenge/HGr8U1IeTW4kY_Z6UIyaakzOkyQgPr_7ArlLgtZE8SX HTTP/1.1" 200 87 "-" "Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)"
|
||||
|
||||
Note that to use the webroot plugin, your server must be configured to serve
|
||||
files from hidden directories. If ``/.well-known`` is treated specially by
|
||||
your webserver configuration, you might need to modify the configuration
|
||||
to ensure that files inside ``/.well-known/acme-challenge`` are served by
|
||||
the webserver.
|
||||
|
||||
Standalone
|
||||
----------
|
||||
|
||||
@@ -104,39 +146,10 @@ one of the options shown below on the command line.
|
||||
* ``--standalone-supported-challenges http-01`` to use port 80
|
||||
* ``--standalone-supported-challenges tls-sni-01`` to use port 443
|
||||
|
||||
Webroot
|
||||
-------
|
||||
|
||||
If you're running a webserver that you don't want to stop to use
|
||||
standalone, you can use the webroot plugin to obtain a cert by
|
||||
including ``certonly`` and ``--webroot`` on the command line. In
|
||||
addition, you'll need to specify ``--webroot-path`` or ``-w`` with the root
|
||||
directory of the files served by your webserver. For example,
|
||||
``--webroot-path /var/www/html`` or
|
||||
``--webroot-path /usr/share/nginx/html`` are two common webroot paths.
|
||||
|
||||
If you're getting a certificate for many domains at once, each domain will use
|
||||
the most recent ``--webroot-path``. So for instance:
|
||||
|
||||
``letsencrypt certonly --webroot -w /var/www/example/ -d www.example.com -d example.com -w /var/www/eg -d eg.is -d www.eg.is``
|
||||
|
||||
Would obtain a single certificate for all of those names, using the
|
||||
``/var/www/example`` webroot directory for the first two, and
|
||||
``/var/www/eg`` for the second two.
|
||||
|
||||
The webroot plugin works by creating a temporary file for each of your requested
|
||||
domains in ``${webroot-path}/.well-known/acme-challenge``. Then the Let's
|
||||
Encrypt validation server makes HTTP requests to validate that the DNS for each
|
||||
requested domain resolves to the server running letsencrypt. An example request
|
||||
made to your web server would look like:
|
||||
|
||||
::
|
||||
|
||||
66.133.109.36 - - [05/Jan/2016:20:11:24 -0500] "GET /.well-known/acme-challenge/HGr8U1IeTW4kY_Z6UIyaakzOkyQgPr_7ArlLgtZE8SX HTTP/1.1" 200 87 "-" "Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)"
|
||||
|
||||
Note that to use the webroot plugin, your server must be configured to serve
|
||||
files from hidden directories.
|
||||
|
||||
The standalone plugin does not rely on any other server software running
|
||||
on the machine where you obtain the certificate. It must still be possible
|
||||
for that machine to accept inbound connections from the Internet on the
|
||||
specified port using each requested domain name.
|
||||
|
||||
Manual
|
||||
------
|
||||
@@ -146,7 +159,8 @@ other than your target webserver or perform the steps for domain
|
||||
validation yourself, you can use the manual plugin. While hidden from
|
||||
the UI, you can use the plugin to obtain a cert by specifying
|
||||
``certonly`` and ``--manual`` on the command line. This requires you
|
||||
to copy and paste commands into another terminal session.
|
||||
to copy and paste commands into another terminal session, which may
|
||||
be on a different computer.
|
||||
|
||||
Nginx
|
||||
-----
|
||||
@@ -157,7 +171,7 @@ is still experimental, however, and is not installed with
|
||||
letsencrypt-auto_. If installed, you can select this plugin on the
|
||||
command line by including ``--nginx``.
|
||||
|
||||
Third party plugins
|
||||
Third-party plugins
|
||||
-------------------
|
||||
|
||||
These plugins are listed at
|
||||
@@ -171,21 +185,61 @@ Renewal
|
||||
days). Make sure you renew the certificates at least once in 3
|
||||
months.
|
||||
|
||||
In order to renew certificates simply call the ``letsencrypt`` (or
|
||||
letsencrypt-auto_) again, and use the same values when prompted. You can
|
||||
automate it slightly by passing necessary flags on the CLI (see `--help
|
||||
all`), or even further using the :ref:`config-file`. The ``--force-renew``
|
||||
flag may be helpful for automating renewal; it causes the expiration time
|
||||
of the certificate(s) to be ignored when considering renewal. If you're
|
||||
sure that UI doesn't prompt for any details you can add the command to
|
||||
``crontab`` (make it less than every 90 days to avoid problems, say
|
||||
every month).
|
||||
The ``letsencrypt`` client now supports a ``renew`` action to check
|
||||
all installed certificates for impending expiry and attempt to renew
|
||||
them. The simplest form is simply
|
||||
|
||||
``letsencrypt renew``
|
||||
|
||||
This will attempt to renew any previously-obtained certificates that
|
||||
expire in less than 30 days. The same plugin and options that were used
|
||||
at the time the certificate was originally issued will be used for the
|
||||
renewal attempt, unless you specify other plugins or options.
|
||||
|
||||
If you're sure that this command executes successfully without human
|
||||
intervention, you can add the command to ``crontab`` (since certificates
|
||||
are only renewed when they're determined to be near expiry, the command
|
||||
can run on a regular basis, like every week or every day); note that
|
||||
the current version provides detailed output describing either renewal
|
||||
success or failure.
|
||||
|
||||
The ``--force-renew`` flag may be helpful for automating renewal;
|
||||
it causes the expiration time of the certificate(s) to be ignored when
|
||||
considering renewal, and attempts to renew each and every installed
|
||||
certificate regardless of its age. (This form is not appropriate to run
|
||||
daily because each certificate will be renewed every day, which will
|
||||
quickly run into the certificate authority rate limit.)
|
||||
|
||||
Note that options provided to ``letsencrypt renew`` will apply to
|
||||
*every* certificate for which renewal is attempted; for example,
|
||||
``letsencrypt renew --rsa-key-size 4096`` would try to replace every
|
||||
near-expiry certificate with an equivalent certificate using a 4096-bit
|
||||
RSA public key. If a certificate is successfully renewed using
|
||||
specified options, those options will be saved and used for future
|
||||
renewals of that certificate.
|
||||
|
||||
|
||||
An alternative form that provides for more fine-grained control over the
|
||||
renewal process (while renewing specified certificates one at a time),
|
||||
is ``letsencrypt certonly`` with the complete set of subject domains of
|
||||
a specific certificate specified via `-d` flags, like
|
||||
|
||||
``letsencrypt certonly -d example.com -d www.example.com``
|
||||
|
||||
(All of the domains covered by the certificate must be specified in
|
||||
this case in order to renew and replace the old certificate rather
|
||||
than obtaining a new one; don't forget any `www.` domains! Specifying
|
||||
a subset of the domains creates a new, separate certificate containing
|
||||
only those domains, rather than replacing the original certificate.)
|
||||
The ``certonly`` form attempts to renew one individual certificate.
|
||||
|
||||
|
||||
Please note that the CA will send notification emails to the address
|
||||
you provide if you do not renew certificates that are about to expire.
|
||||
|
||||
Let's Encrypt is working hard on automating the renewal process. Until
|
||||
the tool is ready, we are sorry for the inconvenience!
|
||||
Let's Encrypt is working hard on improving the renewal process, and we
|
||||
apologize for any inconveniences you encounter in integrating these
|
||||
commands into your individual environment.
|
||||
|
||||
|
||||
.. _where-certs:
|
||||
@@ -375,6 +429,52 @@ If you don't want to use the Apache plugin, you can omit the
|
||||
|
||||
Packages for Debian Jessie are coming in the next few weeks.
|
||||
|
||||
**Gentoo**
|
||||
|
||||
The official Let's Encrypt client is available in Gentoo Portage. If you
|
||||
want to use the Apache plugin, it has to be installed separately:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
emerge -av app-crypt/letsencrypt
|
||||
emerge -av app-crypt/letsencrypt-apache
|
||||
|
||||
Currently, only the Apache plugin is included in Portage. However, if you
|
||||
want the nginx plugin, you can use Layman to add the mrueg overlay which
|
||||
does include the nginx plugin package:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
emerge -av app-portage/layman
|
||||
layman -S
|
||||
layman -a mrueg
|
||||
emerge -av app-crypt/letsencrypt-nginx
|
||||
|
||||
When using the Apache plugin, you will run into a "cannot find a cert or key
|
||||
directive" error if you're sporting the default Gentoo ``httpd.conf``.
|
||||
You can fix this by commenting out two lines in ``/etc/apache2/httpd.conf``
|
||||
as follows:
|
||||
|
||||
Change
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
<IfDefine SSL>
|
||||
LoadModule ssl_module modules/mod_ssl.so
|
||||
</IfDefine>
|
||||
|
||||
to
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
#<IfDefine SSL>
|
||||
LoadModule ssl_module modules/mod_ssl.so
|
||||
#</IfDefine>
|
||||
|
||||
For the time being, this is the only way for the Apache plugin to recognise
|
||||
the appropriate directives when installing the certificate.
|
||||
Note: this change is not required for the other plugins.
|
||||
|
||||
**Other Operating Systems**
|
||||
|
||||
OS packaging is an ongoing effort. If you'd like to package
|
||||
|
||||
@@ -17,7 +17,7 @@ RUN apt-get update && \
|
||||
apt-get clean
|
||||
RUN pip install nose
|
||||
|
||||
RUN mkdir -p /home/lea/letsencrypt/letsencrypt
|
||||
RUN mkdir -p /home/lea/letsencrypt
|
||||
|
||||
# Install fake testing CA:
|
||||
COPY ./tests/certs/ca/my-root-ca.crt.pem /usr/local/share/ca-certificates/
|
||||
|
||||
@@ -18,25 +18,31 @@ set -e # Work even if somebody does "sh thisscript.sh".
|
||||
XDG_DATA_HOME=${XDG_DATA_HOME:-~/.local/share}
|
||||
VENV_NAME="letsencrypt"
|
||||
VENV_PATH=${VENV_PATH:-"$XDG_DATA_HOME/$VENV_NAME"}
|
||||
VENV_BIN=${VENV_PATH}/bin
|
||||
LE_AUTO_VERSION="0.4.0"
|
||||
VENV_BIN="$VENV_PATH/bin"
|
||||
LE_AUTO_VERSION="0.5.0.dev0"
|
||||
|
||||
# This script takes the same arguments as the main letsencrypt program, but it
|
||||
# additionally responds to --verbose (more output) and --debug (allow support
|
||||
# for experimental platforms)
|
||||
for arg in "$@" ; do
|
||||
# This first clause is redundant with the third, but hedging on portability
|
||||
if [ "$arg" = "-v" ] || [ "$arg" = "--verbose" ] || echo "$arg" | grep -E -- "-v+$" ; then
|
||||
VERBOSE=1
|
||||
elif [ "$arg" = "--no-self-upgrade" ] ; then
|
||||
# Do not upgrade this script (also prevents client upgrades, because each
|
||||
# copy of the script pins a hash of the python client)
|
||||
NO_SELF_UPGRADE=1
|
||||
elif [ "$arg" = "--os-packages-only" ] ; then
|
||||
OS_PACKAGES_ONLY=1
|
||||
elif [ "$arg" = "--debug" ]; then
|
||||
DEBUG=1
|
||||
fi
|
||||
case "$arg" in
|
||||
--debug)
|
||||
DEBUG=1;;
|
||||
--os-packages-only)
|
||||
OS_PACKAGES_ONLY=1;;
|
||||
--no-self-upgrade)
|
||||
# Do not upgrade this script (also prevents client upgrades, because each
|
||||
# copy of the script pins a hash of the python client)
|
||||
NO_SELF_UPGRADE=1;;
|
||||
--verbose)
|
||||
VERBOSE=1;;
|
||||
[!-]*|-*[!v]*|-)
|
||||
# Anything that isn't -v, -vv, etc.: that is, anything that does not
|
||||
# start with a -, contains anything that's not a v, or is just "-"
|
||||
;;
|
||||
*) # -v+ remains.
|
||||
VERBOSE=1;;
|
||||
esac
|
||||
done
|
||||
|
||||
# letsencrypt-auto needs root access to bootstrap OS dependencies, and
|
||||
@@ -91,21 +97,18 @@ ExperimentalBootstrap() {
|
||||
}
|
||||
|
||||
DeterminePythonVersion() {
|
||||
if command -v python2.7 > /dev/null ; then
|
||||
export LE_PYTHON=${LE_PYTHON:-python2.7}
|
||||
elif command -v python27 > /dev/null ; then
|
||||
export LE_PYTHON=${LE_PYTHON:-python27}
|
||||
elif command -v python2 > /dev/null ; then
|
||||
export LE_PYTHON=${LE_PYTHON:-python2}
|
||||
elif command -v python > /dev/null ; then
|
||||
export LE_PYTHON=${LE_PYTHON:-python}
|
||||
else
|
||||
echo "Cannot find any Pythons... please install one!"
|
||||
for LE_PYTHON in "$LE_PYTHON" python2.7 python27 python2 python; do
|
||||
# Break (while keeping the LE_PYTHON value) if found.
|
||||
command -v "$LE_PYTHON" > /dev/null && break
|
||||
done
|
||||
if [ "$?" != "0" ]; then
|
||||
echo "Cannot find any Pythons; please install one!"
|
||||
exit 1
|
||||
fi
|
||||
export LE_PYTHON
|
||||
|
||||
PYVER=`"$LE_PYTHON" --version 2>&1 | cut -d" " -f 2 | cut -d. -f1,2 | sed 's/\.//'`
|
||||
if [ $PYVER -lt 26 ]; then
|
||||
PYVER=`"$LE_PYTHON" -V 2>&1 | cut -d" " -f 2 | cut -d. -f1,2 | sed 's/\.//'`
|
||||
if [ "$PYVER" -lt 26 ]; then
|
||||
echo "You have an ancient version of Python entombed in your operating system..."
|
||||
echo "This isn't going to work; you'll need at least version 2.6."
|
||||
exit 1
|
||||
@@ -324,13 +327,13 @@ BootstrapGentooCommon() {
|
||||
|
||||
case "$PACKAGE_MANAGER" in
|
||||
(paludis)
|
||||
"$SUDO" cave resolve --keep-targets if-possible $PACKAGES -x
|
||||
"$SUDO" cave resolve --preserve-world --keep-targets if-possible $PACKAGES -x
|
||||
;;
|
||||
(pkgcore)
|
||||
"$SUDO" pmerge --noreplace $PACKAGES
|
||||
"$SUDO" pmerge --noreplace --oneshot $PACKAGES
|
||||
;;
|
||||
(portage|*)
|
||||
"$SUDO" emerge --noreplace $PACKAGES
|
||||
"$SUDO" emerge --noreplace --oneshot $PACKAGES
|
||||
;;
|
||||
esac
|
||||
}
|
||||
@@ -345,20 +348,27 @@ BootstrapFreeBsd() {
|
||||
|
||||
BootstrapMac() {
|
||||
if ! hash brew 2>/dev/null; then
|
||||
echo "Homebrew Not Installed\nDownloading..."
|
||||
echo "Homebrew not installed.\nDownloading..."
|
||||
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
|
||||
fi
|
||||
|
||||
brew install augeas
|
||||
brew install dialog
|
||||
if [ -z "$(brew list --versions augeas)" ]; then
|
||||
echo "augeas not installed.\nInstalling augeas from Homebrew..."
|
||||
brew install augeas
|
||||
fi
|
||||
|
||||
if [ -z "$(brew list --versions dialog)" ]; then
|
||||
echo "dialog not installed.\nInstalling dialog from Homebrew..."
|
||||
brew install dialog
|
||||
fi
|
||||
|
||||
if ! hash pip 2>/dev/null; then
|
||||
echo "pip Not Installed\nInstalling python from Homebrew..."
|
||||
echo "pip not installed.\nInstalling python from Homebrew..."
|
||||
brew install python
|
||||
fi
|
||||
|
||||
if ! hash virtualenv 2>/dev/null; then
|
||||
echo "virtualenv Not Installed\nInstalling with pip"
|
||||
echo "virtualenv not installed.\nInstalling with pip..."
|
||||
pip install virtualenv
|
||||
fi
|
||||
}
|
||||
@@ -412,9 +422,10 @@ TempDir() {
|
||||
|
||||
|
||||
|
||||
if [ "$NO_SELF_UPGRADE" = 1 ]; then
|
||||
if [ "$1" = "--le-auto-phase2" ]; then
|
||||
# Phase 2: Create venv, install LE, and run.
|
||||
|
||||
shift 1 # the --le-auto-phase2 arg
|
||||
if [ -f "$VENV_BIN/letsencrypt" ]; then
|
||||
INSTALLED_VERSION=$("$VENV_BIN/letsencrypt" --version 2>&1 | cut -d " " -f 2)
|
||||
else
|
||||
@@ -1630,8 +1641,10 @@ UNLIKELY_EOF
|
||||
# Report error. (Otherwise, be quiet.)
|
||||
echo "Had a problem while downloading and verifying Python packages:"
|
||||
echo "$PEEP_OUT"
|
||||
rm -rf "$VENV_PATH"
|
||||
exit 1
|
||||
fi
|
||||
echo "Installation succeeded."
|
||||
fi
|
||||
echo "Requesting root privileges to run letsencrypt..."
|
||||
echo " " $SUDO "$VENV_BIN/letsencrypt" "$@"
|
||||
@@ -1653,10 +1666,11 @@ else
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Checking for new version..."
|
||||
TEMP_DIR=$(TempDir)
|
||||
# ---------------------------------------------------------------------------
|
||||
cat << "UNLIKELY_EOF" > "$TEMP_DIR/fetch.py"
|
||||
if [ "$NO_SELF_UPGRADE" != 1 ]; then
|
||||
echo "Checking for new version..."
|
||||
TEMP_DIR=$(TempDir)
|
||||
# ---------------------------------------------------------------------------
|
||||
cat << "UNLIKELY_EOF" > "$TEMP_DIR/fetch.py"
|
||||
"""Do downloading and JSON parsing without additional dependencies. ::
|
||||
|
||||
# Print latest released version of LE to stdout:
|
||||
@@ -1785,25 +1799,27 @@ if __name__ == '__main__':
|
||||
exit(main())
|
||||
|
||||
UNLIKELY_EOF
|
||||
# ---------------------------------------------------------------------------
|
||||
DeterminePythonVersion
|
||||
REMOTE_VERSION=`"$LE_PYTHON" "$TEMP_DIR/fetch.py" --latest-version`
|
||||
if [ "$LE_AUTO_VERSION" != "$REMOTE_VERSION" ]; then
|
||||
echo "Upgrading letsencrypt-auto $LE_AUTO_VERSION to $REMOTE_VERSION..."
|
||||
# ---------------------------------------------------------------------------
|
||||
DeterminePythonVersion
|
||||
REMOTE_VERSION=`"$LE_PYTHON" "$TEMP_DIR/fetch.py" --latest-version`
|
||||
if [ "$LE_AUTO_VERSION" != "$REMOTE_VERSION" ]; then
|
||||
echo "Upgrading letsencrypt-auto $LE_AUTO_VERSION to $REMOTE_VERSION..."
|
||||
|
||||
# Now we drop into Python so we don't have to install even more
|
||||
# dependencies (curl, etc.), for better flow control, and for the option of
|
||||
# future Windows compatibility.
|
||||
"$LE_PYTHON" "$TEMP_DIR/fetch.py" --le-auto-script "v$REMOTE_VERSION"
|
||||
# Now we drop into Python so we don't have to install even more
|
||||
# dependencies (curl, etc.), for better flow control, and for the option of
|
||||
# future Windows compatibility.
|
||||
"$LE_PYTHON" "$TEMP_DIR/fetch.py" --le-auto-script "v$REMOTE_VERSION"
|
||||
|
||||
# Install new copy of letsencrypt-auto. This preserves permissions and
|
||||
# ownership from the old copy.
|
||||
# TODO: Deal with quotes in pathnames.
|
||||
echo "Replacing letsencrypt-auto..."
|
||||
echo " " $SUDO cp "$TEMP_DIR/letsencrypt-auto" "$0"
|
||||
$SUDO cp "$TEMP_DIR/letsencrypt-auto" "$0"
|
||||
# TODO: Clean up temp dir safely, even if it has quotes in its path.
|
||||
rm -rf "$TEMP_DIR"
|
||||
fi # should upgrade
|
||||
"$0" --no-self-upgrade "$@"
|
||||
# Install new copy of letsencrypt-auto. This preserves permissions and
|
||||
# ownership from the old copy.
|
||||
# TODO: Deal with quotes in pathnames.
|
||||
echo "Replacing letsencrypt-auto..."
|
||||
echo " " $SUDO cp "$TEMP_DIR/letsencrypt-auto" "$0"
|
||||
$SUDO cp "$TEMP_DIR/letsencrypt-auto" "$0"
|
||||
# TODO: Clean up temp dir safely, even if it has quotes in its path.
|
||||
rm -rf "$TEMP_DIR"
|
||||
fi # A newer version is available.
|
||||
fi # Self-upgrading is allowed.
|
||||
|
||||
"$0" --le-auto-phase2 "$@"
|
||||
fi
|
||||
|
||||
@@ -18,25 +18,31 @@ set -e # Work even if somebody does "sh thisscript.sh".
|
||||
XDG_DATA_HOME=${XDG_DATA_HOME:-~/.local/share}
|
||||
VENV_NAME="letsencrypt"
|
||||
VENV_PATH=${VENV_PATH:-"$XDG_DATA_HOME/$VENV_NAME"}
|
||||
VENV_BIN=${VENV_PATH}/bin
|
||||
VENV_BIN="$VENV_PATH/bin"
|
||||
LE_AUTO_VERSION="{{ LE_AUTO_VERSION }}"
|
||||
|
||||
# This script takes the same arguments as the main letsencrypt program, but it
|
||||
# additionally responds to --verbose (more output) and --debug (allow support
|
||||
# for experimental platforms)
|
||||
for arg in "$@" ; do
|
||||
# This first clause is redundant with the third, but hedging on portability
|
||||
if [ "$arg" = "-v" ] || [ "$arg" = "--verbose" ] || echo "$arg" | grep -E -- "-v+$" ; then
|
||||
VERBOSE=1
|
||||
elif [ "$arg" = "--no-self-upgrade" ] ; then
|
||||
# Do not upgrade this script (also prevents client upgrades, because each
|
||||
# copy of the script pins a hash of the python client)
|
||||
NO_SELF_UPGRADE=1
|
||||
elif [ "$arg" = "--os-packages-only" ] ; then
|
||||
OS_PACKAGES_ONLY=1
|
||||
elif [ "$arg" = "--debug" ]; then
|
||||
DEBUG=1
|
||||
fi
|
||||
case "$arg" in
|
||||
--debug)
|
||||
DEBUG=1;;
|
||||
--os-packages-only)
|
||||
OS_PACKAGES_ONLY=1;;
|
||||
--no-self-upgrade)
|
||||
# Do not upgrade this script (also prevents client upgrades, because each
|
||||
# copy of the script pins a hash of the python client)
|
||||
NO_SELF_UPGRADE=1;;
|
||||
--verbose)
|
||||
VERBOSE=1;;
|
||||
[!-]*|-*[!v]*|-)
|
||||
# Anything that isn't -v, -vv, etc.: that is, anything that does not
|
||||
# start with a -, contains anything that's not a v, or is just "-"
|
||||
;;
|
||||
*) # -v+ remains.
|
||||
VERBOSE=1;;
|
||||
esac
|
||||
done
|
||||
|
||||
# letsencrypt-auto needs root access to bootstrap OS dependencies, and
|
||||
@@ -91,21 +97,18 @@ ExperimentalBootstrap() {
|
||||
}
|
||||
|
||||
DeterminePythonVersion() {
|
||||
if command -v python2.7 > /dev/null ; then
|
||||
export LE_PYTHON=${LE_PYTHON:-python2.7}
|
||||
elif command -v python27 > /dev/null ; then
|
||||
export LE_PYTHON=${LE_PYTHON:-python27}
|
||||
elif command -v python2 > /dev/null ; then
|
||||
export LE_PYTHON=${LE_PYTHON:-python2}
|
||||
elif command -v python > /dev/null ; then
|
||||
export LE_PYTHON=${LE_PYTHON:-python}
|
||||
else
|
||||
echo "Cannot find any Pythons... please install one!"
|
||||
for LE_PYTHON in "$LE_PYTHON" python2.7 python27 python2 python; do
|
||||
# Break (while keeping the LE_PYTHON value) if found.
|
||||
command -v "$LE_PYTHON" > /dev/null && break
|
||||
done
|
||||
if [ "$?" != "0" ]; then
|
||||
echo "Cannot find any Pythons; please install one!"
|
||||
exit 1
|
||||
fi
|
||||
export LE_PYTHON
|
||||
|
||||
PYVER=`"$LE_PYTHON" --version 2>&1 | cut -d" " -f 2 | cut -d. -f1,2 | sed 's/\.//'`
|
||||
if [ $PYVER -lt 26 ]; then
|
||||
PYVER=`"$LE_PYTHON" -V 2>&1 | cut -d" " -f 2 | cut -d. -f1,2 | sed 's/\.//'`
|
||||
if [ "$PYVER" -lt 26 ]; then
|
||||
echo "You have an ancient version of Python entombed in your operating system..."
|
||||
echo "This isn't going to work; you'll need at least version 2.6."
|
||||
exit 1
|
||||
@@ -168,9 +171,10 @@ TempDir() {
|
||||
|
||||
|
||||
|
||||
if [ "$NO_SELF_UPGRADE" = 1 ]; then
|
||||
if [ "$1" = "--le-auto-phase2" ]; then
|
||||
# Phase 2: Create venv, install LE, and run.
|
||||
|
||||
shift 1 # the --le-auto-phase2 arg
|
||||
if [ -f "$VENV_BIN/letsencrypt" ]; then
|
||||
INSTALLED_VERSION=$("$VENV_BIN/letsencrypt" --version 2>&1 | cut -d " " -f 2)
|
||||
else
|
||||
@@ -207,8 +211,10 @@ UNLIKELY_EOF
|
||||
# Report error. (Otherwise, be quiet.)
|
||||
echo "Had a problem while downloading and verifying Python packages:"
|
||||
echo "$PEEP_OUT"
|
||||
rm -rf "$VENV_PATH"
|
||||
exit 1
|
||||
fi
|
||||
echo "Installation succeeded."
|
||||
fi
|
||||
echo "Requesting root privileges to run letsencrypt..."
|
||||
echo " " $SUDO "$VENV_BIN/letsencrypt" "$@"
|
||||
@@ -230,31 +236,34 @@ else
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Checking for new version..."
|
||||
TEMP_DIR=$(TempDir)
|
||||
# ---------------------------------------------------------------------------
|
||||
cat << "UNLIKELY_EOF" > "$TEMP_DIR/fetch.py"
|
||||
if [ "$NO_SELF_UPGRADE" != 1 ]; then
|
||||
echo "Checking for new version..."
|
||||
TEMP_DIR=$(TempDir)
|
||||
# ---------------------------------------------------------------------------
|
||||
cat << "UNLIKELY_EOF" > "$TEMP_DIR/fetch.py"
|
||||
{{ fetch.py }}
|
||||
UNLIKELY_EOF
|
||||
# ---------------------------------------------------------------------------
|
||||
DeterminePythonVersion
|
||||
REMOTE_VERSION=`"$LE_PYTHON" "$TEMP_DIR/fetch.py" --latest-version`
|
||||
if [ "$LE_AUTO_VERSION" != "$REMOTE_VERSION" ]; then
|
||||
echo "Upgrading letsencrypt-auto $LE_AUTO_VERSION to $REMOTE_VERSION..."
|
||||
# ---------------------------------------------------------------------------
|
||||
DeterminePythonVersion
|
||||
REMOTE_VERSION=`"$LE_PYTHON" "$TEMP_DIR/fetch.py" --latest-version`
|
||||
if [ "$LE_AUTO_VERSION" != "$REMOTE_VERSION" ]; then
|
||||
echo "Upgrading letsencrypt-auto $LE_AUTO_VERSION to $REMOTE_VERSION..."
|
||||
|
||||
# Now we drop into Python so we don't have to install even more
|
||||
# dependencies (curl, etc.), for better flow control, and for the option of
|
||||
# future Windows compatibility.
|
||||
"$LE_PYTHON" "$TEMP_DIR/fetch.py" --le-auto-script "v$REMOTE_VERSION"
|
||||
# Now we drop into Python so we don't have to install even more
|
||||
# dependencies (curl, etc.), for better flow control, and for the option of
|
||||
# future Windows compatibility.
|
||||
"$LE_PYTHON" "$TEMP_DIR/fetch.py" --le-auto-script "v$REMOTE_VERSION"
|
||||
|
||||
# Install new copy of letsencrypt-auto. This preserves permissions and
|
||||
# ownership from the old copy.
|
||||
# TODO: Deal with quotes in pathnames.
|
||||
echo "Replacing letsencrypt-auto..."
|
||||
echo " " $SUDO cp "$TEMP_DIR/letsencrypt-auto" "$0"
|
||||
$SUDO cp "$TEMP_DIR/letsencrypt-auto" "$0"
|
||||
# TODO: Clean up temp dir safely, even if it has quotes in its path.
|
||||
rm -rf "$TEMP_DIR"
|
||||
fi # should upgrade
|
||||
"$0" --no-self-upgrade "$@"
|
||||
# Install new copy of letsencrypt-auto. This preserves permissions and
|
||||
# ownership from the old copy.
|
||||
# TODO: Deal with quotes in pathnames.
|
||||
echo "Replacing letsencrypt-auto..."
|
||||
echo " " $SUDO cp "$TEMP_DIR/letsencrypt-auto" "$0"
|
||||
$SUDO cp "$TEMP_DIR/letsencrypt-auto" "$0"
|
||||
# TODO: Clean up temp dir safely, even if it has quotes in its path.
|
||||
rm -rf "$TEMP_DIR"
|
||||
fi # A newer version is available.
|
||||
fi # Self-upgrading is allowed.
|
||||
|
||||
"$0" --le-auto-phase2 "$@"
|
||||
fi
|
||||
|
||||
@@ -11,13 +11,13 @@ BootstrapGentooCommon() {
|
||||
|
||||
case "$PACKAGE_MANAGER" in
|
||||
(paludis)
|
||||
"$SUDO" cave resolve --keep-targets if-possible $PACKAGES -x
|
||||
"$SUDO" cave resolve --preserve-world --keep-targets if-possible $PACKAGES -x
|
||||
;;
|
||||
(pkgcore)
|
||||
"$SUDO" pmerge --noreplace $PACKAGES
|
||||
"$SUDO" pmerge --noreplace --oneshot $PACKAGES
|
||||
;;
|
||||
(portage|*)
|
||||
"$SUDO" emerge --noreplace $PACKAGES
|
||||
"$SUDO" emerge --noreplace --oneshot $PACKAGES
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
@@ -1,19 +1,26 @@
|
||||
BootstrapMac() {
|
||||
if ! hash brew 2>/dev/null; then
|
||||
echo "Homebrew Not Installed\nDownloading..."
|
||||
echo "Homebrew not installed.\nDownloading..."
|
||||
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
|
||||
fi
|
||||
|
||||
brew install augeas
|
||||
brew install dialog
|
||||
if [ -z "$(brew list --versions augeas)" ]; then
|
||||
echo "augeas not installed.\nInstalling augeas from Homebrew..."
|
||||
brew install augeas
|
||||
fi
|
||||
|
||||
if [ -z "$(brew list --versions dialog)" ]; then
|
||||
echo "dialog not installed.\nInstalling dialog from Homebrew..."
|
||||
brew install dialog
|
||||
fi
|
||||
|
||||
if ! hash pip 2>/dev/null; then
|
||||
echo "pip Not Installed\nInstalling python from Homebrew..."
|
||||
echo "pip not installed.\nInstalling python from Homebrew..."
|
||||
brew install python
|
||||
fi
|
||||
|
||||
if ! hash virtualenv 2>/dev/null; then
|
||||
echo "virtualenv Not Installed\nInstalling with pip"
|
||||
echo "virtualenv not installed.\nInstalling with pip..."
|
||||
pip install virtualenv
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ from contextlib import contextmanager
|
||||
from functools import partial
|
||||
from json import dumps
|
||||
from os import chmod, environ
|
||||
from os.path import abspath, dirname, join
|
||||
from os.path import abspath, dirname, exists, join
|
||||
import re
|
||||
from shutil import copy, rmtree
|
||||
import socket
|
||||
@@ -338,6 +338,12 @@ class AutoTests(TestCase):
|
||||
self.assertIn("THE FOLLOWING PACKAGES DIDN'T MATCH THE "
|
||||
"HASHES SPECIFIED IN THE REQUIREMENTS",
|
||||
exc.output)
|
||||
ok_(not exists(join(venv_dir, 'letsencrypt')),
|
||||
msg="The virtualenv was left around, even though "
|
||||
"installation didn't succeed. We shouldn't do "
|
||||
"this, as it foils our detection of whether we "
|
||||
"need to recreate the virtualenv, which hinges "
|
||||
"on the presence of $VENV_BIN/letsencrypt.")
|
||||
else:
|
||||
self.fail("Peep didn't detect a bad hash and stop the "
|
||||
"installation.")
|
||||
|
||||
+2
-14
@@ -319,12 +319,11 @@ def _handle_identical_cert_request(config, cert):
|
||||
elif config.verb == "certonly":
|
||||
keep_opt = "Keep the existing certificate for now"
|
||||
choices = [keep_opt,
|
||||
"Renew & replace the cert (limit ~5 per 7 days)",
|
||||
"Cancel this operation and do nothing"]
|
||||
"Renew & replace the cert (limit ~5 per 7 days)"]
|
||||
|
||||
display = zope.component.getUtility(interfaces.IDisplay)
|
||||
response = display.menu(question, choices, "OK", "Cancel", default=0)
|
||||
if response[0] == "cancel" or response[1] == 2:
|
||||
if response[0] == display_util.CANCEL:
|
||||
# TODO: Add notification related to command-line options for
|
||||
# skipping the menu for this case.
|
||||
raise errors.Error(
|
||||
@@ -1973,17 +1972,6 @@ def main(cli_args=sys.argv[1:]):
|
||||
zope.component.provideUtility(report)
|
||||
atexit.register(report.atexit_print_messages)
|
||||
|
||||
if not os.geteuid() == 0:
|
||||
logger.warning(
|
||||
"Root (sudo) is required to run most of letsencrypt functionality.")
|
||||
# check must be done after arg parsing as --help should work
|
||||
# w/o root; on the other hand, e.g. "letsencrypt run
|
||||
# --authenticator dns" or "letsencrypt plugins" does not
|
||||
# require root as well
|
||||
#return (
|
||||
# "{0}Root is required to run letsencrypt. Please use sudo.{0}"
|
||||
# .format(os.linesep))
|
||||
|
||||
return config.func(config, plugins)
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
"""Let's Encrypt user-supplied configuration."""
|
||||
import copy
|
||||
import os
|
||||
import urlparse
|
||||
|
||||
from six.moves.urllib import parse # pylint: disable=import-error
|
||||
import zope.interface
|
||||
|
||||
from letsencrypt import constants
|
||||
@@ -50,7 +50,7 @@ class NamespaceConfig(object):
|
||||
@property
|
||||
def server_path(self):
|
||||
"""File path based on ``server``."""
|
||||
parsed = urlparse.urlparse(self.namespace.server)
|
||||
parsed = parse.urlparse(self.namespace.server)
|
||||
return (parsed.netloc + parsed.path).replace('/', os.path.sep)
|
||||
|
||||
@property
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
"""Plugin common functions."""
|
||||
import os
|
||||
import pkg_resources
|
||||
import re
|
||||
import shutil
|
||||
import tempfile
|
||||
|
||||
import OpenSSL
|
||||
import pkg_resources
|
||||
import zope.interface
|
||||
|
||||
from acme.jose import util as jose_util
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
"""Tests for letsencrypt.plugins.disco."""
|
||||
import pkg_resources
|
||||
import unittest
|
||||
|
||||
import mock
|
||||
import pkg_resources
|
||||
import zope.interface
|
||||
|
||||
from letsencrypt import errors
|
||||
|
||||
+24
-13
@@ -112,6 +112,21 @@ def update_configuration(lineagename, target, cli_config):
|
||||
return configobj.ConfigObj(config_filename)
|
||||
|
||||
|
||||
def get_link_target(link):
|
||||
"""Get an absolute path to the target of link.
|
||||
|
||||
:param str link: Path to a symbolic link
|
||||
|
||||
:returns: Absolute path to the target of link
|
||||
:rtype: str
|
||||
|
||||
"""
|
||||
target = os.readlink(link)
|
||||
if not os.path.isabs(target):
|
||||
target = os.path.join(os.path.dirname(link), target)
|
||||
return os.path.abspath(target)
|
||||
|
||||
|
||||
class RenewableCert(object): # pylint: disable=too-many-instance-attributes
|
||||
"""Renewable certificate.
|
||||
|
||||
@@ -194,13 +209,15 @@ class RenewableCert(object): # pylint: disable=too-many-instance-attributes
|
||||
|
||||
def _check_symlinks(self):
|
||||
"""Raises an exception if a symlink doesn't exist"""
|
||||
def check(link):
|
||||
"""Checks if symlink points to a file that exists"""
|
||||
return os.path.exists(os.path.realpath(link))
|
||||
for kind in ALL_FOUR:
|
||||
if not check(getattr(self, kind)):
|
||||
link = getattr(self, kind)
|
||||
if not os.path.islink(link):
|
||||
raise errors.CertStorageError(
|
||||
"link: {0} does not exist".format(getattr(self, kind)))
|
||||
"expected {0} to be a symlink".format(link))
|
||||
target = get_link_target(link)
|
||||
if not os.path.exists(target):
|
||||
raise errors.CertStorageError("target {0} of symlink {1} does "
|
||||
"not exist".format(target, link))
|
||||
|
||||
def _consistent(self):
|
||||
"""Are the files associated with this lineage self-consistent?
|
||||
@@ -225,10 +242,7 @@ class RenewableCert(object): # pylint: disable=too-many-instance-attributes
|
||||
return False
|
||||
for kind in ALL_FOUR:
|
||||
link = getattr(self, kind)
|
||||
where = os.path.dirname(link)
|
||||
target = os.readlink(link)
|
||||
if not os.path.isabs(target):
|
||||
target = os.path.join(where, target)
|
||||
target = get_link_target(link)
|
||||
|
||||
# Each element's link must point within the cert lineage's
|
||||
# directory within the official archive directory
|
||||
@@ -343,10 +357,7 @@ class RenewableCert(object): # pylint: disable=too-many-instance-attributes
|
||||
logger.debug("Expected symlink %s for %s does not exist.",
|
||||
link, kind)
|
||||
return None
|
||||
target = os.readlink(link)
|
||||
if not os.path.isabs(target):
|
||||
target = os.path.join(os.path.dirname(link), target)
|
||||
return os.path.abspath(target)
|
||||
return get_link_target(link)
|
||||
|
||||
def current_version(self, kind):
|
||||
"""Returns numerical version of the specified item.
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
"""Tests for letsencrypt.storage."""
|
||||
import datetime
|
||||
import pytz
|
||||
import os
|
||||
import tempfile
|
||||
import shutil
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
import configobj
|
||||
import mock
|
||||
import pytz
|
||||
|
||||
from letsencrypt import configuration
|
||||
from letsencrypt import errors
|
||||
@@ -687,6 +687,10 @@ class RenewableCertTests(BaseRenewableCertTest):
|
||||
self.assertRaises(errors.CertStorageError,
|
||||
storage.RenewableCert,
|
||||
self.config.filename, self.cli_config)
|
||||
os.symlink("missing", self.config[ALL_FOUR[0]])
|
||||
self.assertRaises(errors.CertStorageError,
|
||||
storage.RenewableCert,
|
||||
self.config.filename, self.cli_config)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
[easy_install]
|
||||
zip_ok = false
|
||||
|
||||
[aliases]
|
||||
dev = develop easy_install letsencrypt[dev,docs,testing]
|
||||
|
||||
[nosetests]
|
||||
nocapture=1
|
||||
cover-package=letsencrypt,acme,letsencrypt_apache,letsencrypt_nginx
|
||||
|
||||
@@ -65,7 +65,12 @@ else:
|
||||
dev_extras = [
|
||||
# Pin astroid==1.3.5, pylint==1.4.2 as a workaround for #289
|
||||
'astroid==1.3.5',
|
||||
'coverage',
|
||||
'nose',
|
||||
'nosexcover',
|
||||
'pep8',
|
||||
'pylint==1.4.2', # upstream #248
|
||||
'tox',
|
||||
'twine',
|
||||
'wheel',
|
||||
]
|
||||
@@ -77,14 +82,6 @@ docs_extras = [
|
||||
'sphinxcontrib-programoutput',
|
||||
]
|
||||
|
||||
testing_extras = [
|
||||
'coverage',
|
||||
'nose',
|
||||
'nosexcover',
|
||||
'pep8',
|
||||
'tox',
|
||||
]
|
||||
|
||||
setup(
|
||||
name='letsencrypt',
|
||||
version=version,
|
||||
@@ -120,7 +117,6 @@ setup(
|
||||
extras_require={
|
||||
'dev': dev_extras,
|
||||
'docs': docs_extras,
|
||||
'testing': testing_extras,
|
||||
},
|
||||
|
||||
# to test all packages run "python setup.py test -s
|
||||
|
||||
+2
-2
@@ -4,8 +4,8 @@
|
||||
export VENV_ARGS="--python python2"
|
||||
|
||||
./tools/_venv_common.sh \
|
||||
-e acme[testing] \
|
||||
-e .[dev,docs,testing] \
|
||||
-e acme[dev] \
|
||||
-e .[dev,docs] \
|
||||
-e letsencrypt-apache \
|
||||
-e letsencrypt-nginx \
|
||||
-e letshelp-letsencrypt \
|
||||
|
||||
+2
-2
@@ -4,5 +4,5 @@
|
||||
export VENV_NAME="${VENV_NAME:-venv3}"
|
||||
export VENV_ARGS="--python python3"
|
||||
|
||||
./bootstrap/dev/_venv_common.sh \
|
||||
-e acme[testing] \
|
||||
./tools/_venv_common.sh \
|
||||
-e acme[dev] \
|
||||
|
||||
@@ -15,9 +15,9 @@ envlist = py{26,27,33,34,35},py{26,27}-oldest,cover,lint
|
||||
# packages installed separately to ensure that downstream deps problems
|
||||
# are detected, c.f. #1002
|
||||
commands =
|
||||
pip install -e acme[testing]
|
||||
pip install -e acme[dev]
|
||||
nosetests -v acme
|
||||
pip install -e .[testing]
|
||||
pip install -e .[dev]
|
||||
nosetests -v letsencrypt
|
||||
pip install -e letsencrypt-apache
|
||||
nosetests -v letsencrypt_apache
|
||||
@@ -40,23 +40,23 @@ deps =
|
||||
|
||||
[testenv:py33]
|
||||
commands =
|
||||
pip install -e acme[testing]
|
||||
pip install -e acme[dev]
|
||||
nosetests -v acme
|
||||
|
||||
[testenv:py34]
|
||||
commands =
|
||||
pip install -e acme[testing]
|
||||
pip install -e acme[dev]
|
||||
nosetests -v acme
|
||||
|
||||
[testenv:py35]
|
||||
commands =
|
||||
pip install -e acme[testing]
|
||||
pip install -e acme[dev]
|
||||
nosetests -v acme
|
||||
|
||||
[testenv:cover]
|
||||
basepython = python2.7
|
||||
commands =
|
||||
pip install -e acme -e .[testing] -e letsencrypt-apache -e letsencrypt-nginx -e letshelp-letsencrypt
|
||||
pip install -e acme[dev] -e .[dev] -e letsencrypt-apache -e letsencrypt-nginx -e letshelp-letsencrypt
|
||||
./tox.cover.sh
|
||||
|
||||
[testenv:lint]
|
||||
@@ -66,7 +66,7 @@ basepython = python2.7
|
||||
# duplicate code checking; if one of the commands fails, others will
|
||||
# continue, but tox return code will reflect previous error
|
||||
commands =
|
||||
pip install -e acme -e .[dev] -e letsencrypt-apache -e letsencrypt-nginx -e letsencrypt-compatibility-test -e letshelp-letsencrypt
|
||||
pip install -e acme[dev] -e .[dev] -e letsencrypt-apache -e letsencrypt-nginx -e letsencrypt-compatibility-test -e letshelp-letsencrypt
|
||||
./pep8.travis.sh
|
||||
pylint --rcfile=.pylintrc letsencrypt
|
||||
pylint --rcfile=acme/.pylintrc acme/acme
|
||||
|
||||
Reference in New Issue
Block a user