Merge branch 'master' into file-to-str

Conflicts:
	letsencrypt/client/client.py
	letsencrypt/client/le_util.py
This commit is contained in:
Adam Woodbeck 2014-11-29 11:35:48 -05:00
commit 9efec15d0a
13 changed files with 127 additions and 55 deletions

1
.gitignore vendored
View file

@ -4,4 +4,5 @@ build/
dist/
venv/
.tox/
.coverage
m3

22
.travis.yml Normal file
View 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

View file

@ -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

View file

@ -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
"""

View file

@ -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.

View file

@ -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

View file

@ -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:

View file

@ -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)

View file

@ -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

View file

@ -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"""

View file

@ -3,3 +3,8 @@ zip_ok = false
[aliases]
dev = develop easy_install letsencrypt[testing]
[nosetests]
nocapture=1
cover-package=letsencrypt
cover-erase=1

View file

@ -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
View file

@ -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