mirror of
https://github.com/certbot/certbot.git
synced 2026-06-06 07:12:54 -04:00
Merge branch 'master' into file-to-str
Conflicts: letsencrypt/client/client.py letsencrypt/client/le_util.py
This commit is contained in:
commit
9efec15d0a
13 changed files with 127 additions and 55 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -4,4 +4,5 @@ build/
|
|||
dist/
|
||||
venv/
|
||||
.tox/
|
||||
.coverage
|
||||
m3
|
||||
|
|
|
|||
22
.travis.yml
Normal file
22
.travis.yml
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
# To mimic README.md installation and hacking instructions as much as
|
||||
# possible, this config file instructs Travis CI to create a build
|
||||
# environment for each supported Python version, and then for each of
|
||||
# those it runs tox with two environments: lint and pyXX corresponding
|
||||
# to the currently used Travis CI build Python version.
|
||||
|
||||
language: python
|
||||
|
||||
python:
|
||||
- "2.6"
|
||||
- "2.7"
|
||||
|
||||
before_install: >
|
||||
travis_retry sudo apt-get install python python-setuptools
|
||||
python-virtualenv python-dev gcc swig dialog libaugeas0 libssl-dev
|
||||
|
||||
install: travis_retry python setup.py dev # installs tox
|
||||
script: travis_retry tox
|
||||
|
||||
env:
|
||||
- TOXENV=py${TRAVIS_PYTHON_VERSION//[.]/}
|
||||
- TOXENV=lint
|
||||
73
README.md
73
README.md
|
|
@ -1,25 +1,56 @@
|
|||
This is the Let's Encrypt Agent DEVELOPER PREVIEW repository.
|
||||
# Let's Encrypt
|
||||
|
||||
DO NOT RUN THIS CODE ON A PRODUCTION WEBSERVER. IT WILL INSTALL CERTIFICATES
|
||||
SIGNED BY A TEST CA, AND WILL CAUSE CERT WARNINGS FOR USERS.
|
||||
[![Build Status]
|
||||
(https://travis-ci.org/letsencrypt/lets-encrypt-preview.svg?branch=master)]
|
||||
(https://travis-ci.org/letsencrypt/lets-encrypt-preview)
|
||||
|
||||
This code is 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.
|
||||
## Disclaimer
|
||||
|
||||
## Running the demo code on Ubuntu
|
||||
This is the [Let's Encrypt] Agent **DEVELOPER PREVIEW** repository.
|
||||
|
||||
**DO NOT RUN THIS CODE ON A PRODUCTION WEBSERVER. IT WILL INSTALL
|
||||
CERTIFICATES SIGNED BY A TEST CA, AND WILL CAUSE CERT WARNINGS FOR
|
||||
USERS.**
|
||||
|
||||
This code is intended for testing, demonstration, and integration
|
||||
engineering with OSes and hosting platforms. For the time being
|
||||
project focuses on Linux and Apache, though we will be expanding
|
||||
it to other platforms.
|
||||
|
||||
## Running the demo code
|
||||
|
||||
The demo code is supported and known to work on **Ubuntu only** (even
|
||||
closely related [Debian is known to fail]
|
||||
(https://github.com/letsencrypt/lets-encrypt-preview/issues/68)).
|
||||
Therefore, prerequisites for other platforms listed below are provided
|
||||
mainly for the [developers](#hacking) reference.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
In general:
|
||||
|
||||
* [swig] is required for compiling [m2crypto]
|
||||
* [augeas] is required for the `python-augeas` bindings
|
||||
|
||||
#### Ubuntu
|
||||
|
||||
```
|
||||
sudo apt-get install python python-setuptools python-virtualenv \
|
||||
python-dev gcc swig dialog libaugeas0 libssl-dev
|
||||
```
|
||||
|
||||
#### Mac OSX
|
||||
|
||||
`sudo brew install augeas swig`
|
||||
|
||||
### Installation
|
||||
|
||||
```
|
||||
virtualenv --no-site-packages venv
|
||||
./venv/bin/python setup.py install
|
||||
sudo ./venv/bin/letsencrypt
|
||||
```
|
||||
|
||||
Note, that letsencrypt does not yet handle Debian unstable's Apache2
|
||||
conf layout.
|
||||
|
||||
## Hacking
|
||||
|
||||
1. Bootstrap: `./venv/bin/python setup.py dev`
|
||||
|
|
@ -62,14 +93,20 @@ optional arguments:
|
|||
|
||||
## More Information
|
||||
|
||||
Further Setup, documentation and open projects are available in the [Wiki]
|
||||
(https://github.com/letsencrypt/lets-encrypt-preview/wiki)
|
||||
- Further setup, documentation and open projects are available in the
|
||||
[Wiki].
|
||||
|
||||
Join us at our IRC channel @ freenode.net #letsencrypt
|
||||
- Join us at our IRC channel: #letsencrypt at [Freenode].
|
||||
|
||||
Client software development can be discussed on this [mailing list]
|
||||
(https://groups.google.com/a/letsencrypt.org/forum/#!forum/client-dev)
|
||||
- Client software development can be discussed on this [mailing
|
||||
list]. To subscribe without a Google account, send an email to
|
||||
client-dev+subscribe@letsencrypt.org.
|
||||
|
||||
To subscribe without a Google account, send mail to
|
||||
[client-dev+subscribe@letsencrypt.org]
|
||||
(mailto:client-dev+subscribe@letsencrypt.org).
|
||||
|
||||
[augeas]: http://augeas.net
|
||||
[Freenode]: https://freenode.net
|
||||
[Let's Encrypt]: https://letsencrypt.org
|
||||
[m2crypto]: https://github.com/M2Crypto/M2Crypto
|
||||
[mailing list]: https://groups.google.com/a/letsencrypt.org/forum/#!forum/client-dev
|
||||
[swig]: http://www.swig.org
|
||||
[wiki]: https://github.com/letsencrypt/lets-encrypt-preview/wiki
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ def challenge_request(names):
|
|||
|
||||
|
||||
def authorization_request(req_id, name, server_nonce, responses, key_file):
|
||||
"""Create ACME "authoriazationRequest" message.
|
||||
"""Create ACME "authorizationRequest" message.
|
||||
|
||||
:param req_id: TODO
|
||||
:type req_id: TODO
|
||||
|
|
@ -98,7 +98,7 @@ def authorization_request(req_id, name, server_nonce, responses, key_file):
|
|||
:param key_file: TODO
|
||||
:type key_file: TODO
|
||||
|
||||
:returns: ACME "authoriazationRequest" message.
|
||||
:returns: ACME "authorizationRequest" message.
|
||||
:rtype: dict
|
||||
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -1242,9 +1242,9 @@ LogLevel warn \n\
|
|||
have permissions of root
|
||||
|
||||
"""
|
||||
le_util.make_or_verify_dir(CONFIG.CONFIG_DIR, 0755)
|
||||
le_util.make_or_verify_dir(CONFIG.WORK_DIR, 0755)
|
||||
le_util.make_or_verify_dir(CONFIG.BACKUP_DIR, 0755)
|
||||
le_util.make_or_verify_dir(CONFIG.CONFIG_DIR, 0o755)
|
||||
le_util.make_or_verify_dir(CONFIG.WORK_DIR, 0o755)
|
||||
le_util.make_or_verify_dir(CONFIG.BACKUP_DIR, 0o755)
|
||||
|
||||
def standardize_excl(self):
|
||||
"""Standardize the excl arguments for the Httpd lens in Augeas.
|
||||
|
|
|
|||
|
|
@ -257,7 +257,7 @@ class AugeasConfigurator(configurator.Configurator):
|
|||
:type save_files: set
|
||||
|
||||
"""
|
||||
le_util.make_or_verify_dir(cp_dir, 0755)
|
||||
le_util.make_or_verify_dir(cp_dir, 0o755)
|
||||
|
||||
existing_filepaths = []
|
||||
op_fd = None
|
||||
|
|
|
|||
|
|
@ -410,7 +410,7 @@ class Client(object):
|
|||
|
||||
"""
|
||||
cert_chain_abspath = None
|
||||
cert_fd, cert_file = le_util.unique_file(CONFIG.CERT_PATH, 644)
|
||||
cert_fd, cert_file = le_util.unique_file(CONFIG.CERT_PATH, 0o644)
|
||||
cert_fd.write(
|
||||
crypto_util.b64_cert_to_pem(certificate_dict["certificate"]))
|
||||
cert_fd.close()
|
||||
|
|
@ -418,7 +418,7 @@ class Client(object):
|
|||
cert_file)
|
||||
|
||||
if certificate_dict.get("chain", None):
|
||||
chain_fd, chain_fn = le_util.unique_file(CONFIG.CHAIN_PATH, 644)
|
||||
chain_fd, chain_fn = le_util.unique_file(CONFIG.CHAIN_PATH, 0o644)
|
||||
for cert in certificate_dict.get("chain", []):
|
||||
chain_fd.write(crypto_util.b64_cert_to_pem(cert))
|
||||
chain_fd.close()
|
||||
|
|
@ -527,7 +527,7 @@ class Client(object):
|
|||
|
||||
"""
|
||||
list_file = os.path.join(CONFIG.CERT_KEY_BACKUP, "LIST")
|
||||
le_util.make_or_verify_dir(CONFIG.CERT_KEY_BACKUP, 0700)
|
||||
le_util.make_or_verify_dir(CONFIG.CERT_KEY_BACKUP, 0o700)
|
||||
idx = 0
|
||||
|
||||
if encrypt:
|
||||
|
|
@ -658,10 +658,10 @@ class Client(object):
|
|||
self.privkey = key_pem
|
||||
|
||||
# Save file
|
||||
le_util.make_or_verify_dir(CONFIG.KEY_DIR, 0700)
|
||||
key_f, key_filename = le_util.unique_file(
|
||||
os.path.join(CONFIG.KEY_DIR, "key-letsencrypt.pem"), 0600)
|
||||
key_f.write(self.privkey)
|
||||
le_util.make_or_verify_dir(CONFIG.KEY_DIR, 0o700)
|
||||
key_f, self.key_file = le_util.unique_file(
|
||||
os.path.join(CONFIG.KEY_DIR, "key-letsencrypt.pem"), 0o600)
|
||||
key_f.write(key_pem)
|
||||
key_f.close()
|
||||
logger.info("Generating key: %s" % key_filename)
|
||||
else:
|
||||
|
|
@ -672,10 +672,10 @@ class Client(object):
|
|||
self.csr = csr_pem
|
||||
|
||||
# Save CSR
|
||||
le_util.make_or_verify_dir(CONFIG.CERT_DIR, 0755)
|
||||
csr_f, csr_filename = le_util.unique_file(
|
||||
os.path.join(CONFIG.CERT_DIR, "csr-letsencrypt.pem"), 0644)
|
||||
csr_f.write(self.csr)
|
||||
le_util.make_or_verify_dir(CONFIG.CERT_DIR, 0o755)
|
||||
csr_f, self.csr_file = le_util.unique_file(
|
||||
os.path.join(CONFIG.CERT_DIR, "csr-letsencrypt.pem"), 0o644)
|
||||
csr_f.write(csr_pem)
|
||||
csr_f.close()
|
||||
logger.info("Creating CSR: %s" % csr_filename)
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import os
|
|||
import stat
|
||||
|
||||
|
||||
def make_or_verify_dir(directory, mode=0755, uid=0):
|
||||
def make_or_verify_dir(directory, mode=0o755, uid=0):
|
||||
"""Make sure directory exists with proper permissions.
|
||||
|
||||
:param directory: Path to a directry.
|
||||
|
|
@ -50,7 +50,7 @@ def check_permissions(filepath, mode, uid=0):
|
|||
return stat.S_IMODE(file_stat.st_mode) == mode and file_stat.st_uid == uid
|
||||
|
||||
|
||||
def unique_file(default_name, mode=0644):
|
||||
def unique_file(default_name, mode=0o777):
|
||||
"""Safely finds a unique file for writing only (by default)."""
|
||||
count = 1
|
||||
f_parsed = os.path.splitext(default_name)
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ class MakeOrVerifyDirTest(unittest.TestCase):
|
|||
def setUp(self):
|
||||
self.root_path = tempfile.mkdtemp()
|
||||
self.path = os.path.join(self.root_path, 'foo')
|
||||
os.mkdir(self.path, 0400)
|
||||
os.mkdir(self.path, 0o400)
|
||||
|
||||
self.uid = os.getuid()
|
||||
|
||||
|
|
@ -29,16 +29,16 @@ class MakeOrVerifyDirTest(unittest.TestCase):
|
|||
|
||||
def test_creates_dir_when_missing(self):
|
||||
path = os.path.join(self.root_path, 'bar')
|
||||
self._call(path, 0650)
|
||||
self._call(path, 0o650)
|
||||
self.assertTrue(os.path.isdir(path))
|
||||
# TODO: check mode
|
||||
|
||||
def test_existing_correct_mode_does_not_fail(self):
|
||||
self._call(self.path, 0400)
|
||||
self._call(self.path, 0o400)
|
||||
# TODO: check mode
|
||||
|
||||
def test_existing_wrong_mode_fails(self):
|
||||
self.assertRaises(Exception, self._call, self.path, 0600)
|
||||
self.assertRaises(Exception, self._call, self.path, 0o600)
|
||||
|
||||
|
||||
class CheckPermissionsTest(unittest.TestCase):
|
||||
|
|
@ -61,12 +61,12 @@ class CheckPermissionsTest(unittest.TestCase):
|
|||
return check_permissions(self.path, mode, self.uid)
|
||||
|
||||
def test_ok_mode(self):
|
||||
os.chmod(self.path, 0600)
|
||||
self.assertTrue(self._call(0600))
|
||||
os.chmod(self.path, 0o600)
|
||||
self.assertTrue(self._call(0o600))
|
||||
|
||||
def test_wrong_mode(self):
|
||||
os.chmod(self.path, 0400)
|
||||
self.assertFalse(self._call(0600))
|
||||
os.chmod(self.path, 0o400)
|
||||
self.assertFalse(self._call(0o600))
|
||||
|
||||
|
||||
# https://en.wikipedia.org/wiki/Base64#Examples
|
||||
|
|
|
|||
|
|
@ -174,9 +174,9 @@ class NginxConfigurator(augeas_configurator.AugeasConfigurator):
|
|||
# permissions. Aim for defensive coding... make sure all input files
|
||||
# have permissions of root
|
||||
# """
|
||||
# le_util.make_or_verify_dir(CONFIG.CONFIG_DIR, 0755)
|
||||
# le_util.make_or_verify_dir(CONFIG.WORK_DIR, 0755)
|
||||
# le_util.make_or_verify_dir(CONFIG.BACKUP_DIR, 0755)
|
||||
# le_util.make_or_verify_dir(CONFIG.CONFIG_DIR, 0o755)
|
||||
# le_util.make_or_verify_dir(CONFIG.WORK_DIR, 0o755)
|
||||
# le_util.make_or_verify_dir(CONFIG.BACKUP_DIR, 0o755)
|
||||
|
||||
def restart(self, quiet=False):
|
||||
"""Restarts nginx server"""
|
||||
|
|
|
|||
|
|
@ -3,3 +3,8 @@ zip_ok = false
|
|||
|
||||
[aliases]
|
||||
dev = develop easy_install letsencrypt[testing]
|
||||
|
||||
[nosetests]
|
||||
nocapture=1
|
||||
cover-package=letsencrypt
|
||||
cover-erase=1
|
||||
|
|
|
|||
2
setup.py
2
setup.py
|
|
@ -15,6 +15,7 @@ install_requires = [
|
|||
testing_extras = [
|
||||
'coverage',
|
||||
'nose',
|
||||
'nosexcover',
|
||||
'pylint',
|
||||
'tox',
|
||||
]
|
||||
|
|
@ -33,6 +34,7 @@ setup(
|
|||
],
|
||||
install_requires=install_requires,
|
||||
tests_require=install_requires,
|
||||
test_suite='letsencrypt',
|
||||
extras_require={
|
||||
'testing': testing_extras,
|
||||
},
|
||||
|
|
|
|||
19
tox.ini
19
tox.ini
|
|
@ -4,14 +4,19 @@
|
|||
# and then run "tox" from this directory.
|
||||
|
||||
[tox]
|
||||
envlist = py26, py27, lint
|
||||
envlist = py26,py27,cover,lint
|
||||
|
||||
[testenv]
|
||||
commands = nosetests
|
||||
deps =
|
||||
nose
|
||||
commands =
|
||||
python setup.py dev
|
||||
python setup.py test -q # -q does not suppress errors
|
||||
|
||||
[testenv:cover]
|
||||
commands =
|
||||
python setup.py dev
|
||||
python setup.py nosetests --with-coverage --cover-min-percentage=100
|
||||
|
||||
[testenv:lint]
|
||||
commands = pylint letsencrypt
|
||||
deps =
|
||||
pylint
|
||||
commands =
|
||||
python setup.py dev
|
||||
pylint letsencrypt
|
||||
|
|
|
|||
Loading…
Reference in a new issue