-
Notifications
You must be signed in to change notification settings - Fork 59
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 473121e
Showing
18 changed files
with
1,846 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# Standard Python stuff | ||
*.pyc | ||
/build/ | ||
/dist/ | ||
/venv/ | ||
/*.egg-info/ | ||
|
||
# testing | ||
/.tox/ | ||
|
||
# make sure users don't commit private key material | ||
*.json | ||
*.pem | ||
*.der | ||
# ... as well as external IO plugin script | ||
/external_pem.sh | ||
|
||
# `sshfs user@host:$ROOT public_html/` and `--default_root=public_html` | ||
/public_html/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
1. Read MANIFESTO from README. | ||
|
||
2. https://google.github.io/styleguide/pyguide.html and | ||
https://www.python.org/dev/peps/pep-0008/ |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
include README.md | ||
include CONTRIBUTING.md | ||
include LICENSE.txt |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
# simp_le | ||
|
||
Simple [Let's Encrypt](https://letsencrypt.org) client. | ||
|
||
```shell | ||
simp_le -f fullchain.pem -f key.pem \ | ||
-d example.com -d www.example.com --default_root /var/www/html \ | ||
-d other.com:/var/www/other_html | ||
``` | ||
|
||
For more info see `simp_le --help`. | ||
|
||
## Manifest | ||
|
||
1. [UNIX philosophy](https://en.wikipedia.org/wiki/Unix_philosophy): | ||
Do one thing and do it well! | ||
|
||
2. `simp_le --valid_min ${seconds?} -f cert.pem` implies that | ||
`cert.pem` is valid for at at least `valid_min`. Register new ACME | ||
CA account if necessary. Issue new certificate if no previous | ||
key/certificate/chain found. Renew only if necessary. | ||
|
||
3. (Sophisticated) "manager" for | ||
`${webroot?}/.well-known/acme-challenges` only. No challenges other | ||
than `http-01`. Existing web-server must be be running already. | ||
|
||
4. No magical webserver auto-configuration. | ||
|
||
5. Owner of `${webroot?}/.well-known/acme-challenges` must be able to | ||
run the script, without privilege escalation (`sudo`, `root`, | ||
etc.). | ||
|
||
6. `crontab` friendly: fully automatable - no prompts, etc. | ||
|
||
7. No configuration files. CLI flags as the sole interface! Users | ||
should write their own wrapper scripts or use shell aliases if | ||
necessary. | ||
|
||
8. Support multiple domains with multiple roots. Always create single | ||
SAN certificate per `simp_le` run. | ||
|
||
9. Flexible storage capabilities. Built-in `simp_le -f fullchain.pem | ||
-f privkey.pem`, `simp_le -f chain.pem -f cert.pem -d privkey.pem`, | ||
etc. Extensions through `simp_le -f external_pem.sh`. | ||
|
||
10. Do not allow specifying output file paths. Users should symlink if | ||
necessary! | ||
|
||
11. No need to allow arbitrary command when renewal has happened: just | ||
compare cert before and after (`sha256sum`, `mtime`, etc.). | ||
|
||
12. `--server` (support multiple CAs). | ||
|
||
## Installation | ||
|
||
```shell | ||
sudo ./bootstrap.sh | ||
./venv.sh | ||
. venv/bin/activate | ||
``` | ||
|
||
## Examples | ||
|
||
Have a look into `./examples/`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
#!/bin/sh -xe | ||
|
||
bootstrap_deb () { | ||
apt-get update | ||
|
||
install () { | ||
apt-get install -y --no-install-recommends "$@" | ||
} | ||
|
||
install \ | ||
ca-certificates \ | ||
gcc \ | ||
libssl-dev \ | ||
libffi-dev \ | ||
python \ | ||
python-dev \ | ||
python-virtualenv | ||
|
||
# virtualenv binary can be found in different packages depending on | ||
# distro version | ||
install virtualenv || true | ||
} | ||
|
||
bootstrap_rpm () { | ||
installer=$(command -v dnf || command -v yum) | ||
"${installer?}" install -y \ | ||
ca-certificates \ | ||
gcc \ | ||
libffi-devel \ | ||
openssl-devel \ | ||
python \ | ||
python-devel \ | ||
python-virtualenv | ||
} | ||
|
||
if [ -f /etc/debian_version ] | ||
then | ||
bootstrap_deb | ||
elif [ -f /etc/redhat-release ] | ||
then | ||
bootstrap_rpm | ||
fi |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
#!/bin/sh | ||
# Dummy example external script that loads/saves key/cert/chain to | ||
# /tmp/foo; `simp_le -f external_pem.sh`. | ||
|
||
load () { | ||
cat /tmp/foo | ||
} | ||
|
||
save () { | ||
cat - > /tmp/foo | ||
} | ||
|
||
persisted () { | ||
echo key cert chain | ||
} | ||
|
||
case $1 in | ||
save) | ||
save | ||
;; | ||
load) | ||
load | ||
;; | ||
persisted) | ||
persisted | ||
;; | ||
esac |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
/build/ | ||
/dist/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
all: | ||
pyinstaller simp_le.spec | ||
|
||
clean: | ||
rm -rf build dist |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
[PyInstaller](http://www.pyinstaller.org/) setup for simp_le. | ||
|
||
```shell | ||
pip install -r requirements.txt | ||
make clean all | ||
./dist/simp_le --test | ||
./dist/simp_le --help | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import collections | ||
import json | ||
import pkg_resources | ||
|
||
def dump_entry_points(tmp_entry_points_path, *distribution_names): | ||
"""Dump entry points database. | ||
Compile a database by going through all entry points registered by | ||
distributions listed in `distribution_names`. Serialize database to | ||
JSON and dump to a file (located in `tmp_entry_points_path`) that | ||
can be later copied to the one-folder/one-file distribution and used | ||
by `rthook-entrypoints.iter_entry_points`. | ||
""" | ||
entry_points = collections.defaultdict(collections.defaultdict) | ||
for name in distribution_names: | ||
entry_map = pkg_resources.get_distribution(name).get_entry_map() | ||
for group, eps in entry_map.iteritems(): | ||
entry_points[group][name] = [str(ep) for ep in eps.itervalues()] | ||
with open(tmp_entry_points_path, 'w') as fp: | ||
fp.write(json.dumps(entry_points)) | ||
return entry_points |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
pyinstaller>=3.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
"""PyInstaller runtime hook for setuptools entry points. | ||
Monkey patches `pkg_resources.iter_entry_points` to return all entry | ||
points as saved by `entrypoints.dump_entry_points` in the PyInstaller | ||
spec file. | ||
""" | ||
import functools | ||
import json | ||
import os | ||
import pkg_resources | ||
import sys | ||
|
||
|
||
class Distribution(object): | ||
"""Fake setuptools distribution.""" | ||
def __init__(self, key): | ||
self.key = key | ||
|
||
def requires(self, *unused_args, **unused_kwargs): | ||
return [] | ||
|
||
def patch(mod): | ||
"""Monkey patch module's attributes.""" | ||
def wrapper(f): # pylint: disable=missing-docstring | ||
old = getattr(mod, f.__name__, f) | ||
def wrapper2(*args, **kwargs): # pylint: disable=missing-docstring | ||
return f(old, *args, **kwargs) | ||
setattr(mod, f.__name__, wrapper2) | ||
return wrapper2 | ||
return wrapper | ||
|
||
def iter_entry_points_factory(all_entry_points): | ||
"""Make patchable ``iter_entry_points`` that uses ``all_entry_points``.""" | ||
def iter_entry_points(old_iter_entry_points, group, *args, **kwargs): | ||
"""Monkey patched ``iter_entry_points``.""" | ||
if group in all_entry_points: | ||
for dist_name, entry_points in all_entry_points[group].iteritems(): | ||
dist = Distribution(dist_name) | ||
return [pkg_resources.EntryPoint.parse(entry_point, dist=dist) | ||
for entry_point in entry_points] | ||
else: | ||
return old_iter_entry_points(group, *args, **kwargs) | ||
return iter_entry_points | ||
|
||
def main(): | ||
"""Monkey-patch `pkg_resources` with correct database.""" | ||
entry_points_path = os.path.join(sys._MEIPASS, 'entry_points.json') | ||
with open(entry_points_path) as fp: | ||
all_entry_points = json.loads(fp.read()) | ||
patch(pkg_resources)(iter_entry_points_factory(all_entry_points)) | ||
|
||
|
||
if __name__ == '__main__': | ||
main() # pragma: no cover |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
# -*- mode: python -*- | ||
import os | ||
import pkg_resources | ||
import sys | ||
|
||
sys.path.insert(0, '.') | ||
import entrypoints | ||
|
||
TMP_ENTRY_POINTS_PATH = os.path.join(workpath, 'entry_points.json') | ||
ENTRY_POINTS = [('entry_points.json', TMP_ENTRY_POINTS_PATH, 'DATA')] | ||
entrypoints.dump_entry_points( | ||
TMP_ENTRY_POINTS_PATH, | ||
'cryptography', | ||
) | ||
|
||
_CRYPTOGRAPHY_BACKENDS = [ | ||
ep.module_name for ep in pkg_resources.iter_entry_points( | ||
'cryptography.backends') | ||
] | ||
_HIDDEN_IMPORTS = _CRYPTOGRAPHY_BACKENDS + [ | ||
'cffi', | ||
'werkzeug.exceptions', | ||
] | ||
|
||
block_cipher = None | ||
|
||
MAIN = Analysis( | ||
[os.path.join('..', 'simp_le.py')], | ||
binaries=None, | ||
datas=None, | ||
hiddenimports=_HIDDEN_IMPORTS, | ||
hookspath=[], | ||
runtime_hooks=['rthook-entrypoints.py'], | ||
excludes=[], | ||
win_no_prefer_redirects=False, | ||
win_private_assemblies=False, | ||
cipher=block_cipher, | ||
) | ||
|
||
MAIN_PYZ = PYZ( | ||
MAIN.pure, | ||
MAIN.zipped_data, | ||
cipher=block_cipher, | ||
) | ||
|
||
MAIN_EXE = EXE( | ||
MAIN_PYZ, | ||
MAIN.scripts, | ||
MAIN.binaries, | ||
MAIN.zipfiles, | ||
MAIN.datas, | ||
ENTRY_POINTS, | ||
name='simp_le', | ||
debug=False, | ||
strip=False, | ||
upx=True, | ||
console=True, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import sys | ||
import setuptools | ||
|
||
|
||
install_requires = [ | ||
'acme==0.0.0.dev20151114', | ||
'cryptography', | ||
'pyOpenSSL', | ||
'requests', | ||
] | ||
|
||
if sys.version_info < (2, 7): | ||
install_requires.extend([ | ||
'argparse', | ||
'mock<1.1.0', | ||
]) | ||
else: | ||
install_requires.extend([ | ||
'mock', | ||
]) | ||
|
||
tests_require = [ | ||
'pep8', | ||
'pylint', | ||
] | ||
|
||
setuptools.setup( | ||
name='simp_le', | ||
author='Jakub Warmuz', | ||
author_email='jakub@warmuz.org', | ||
license='GPLv3', | ||
|
||
py_modules=['simp_le'], | ||
install_requires=install_requires, | ||
extras_require={ | ||
'tests': tests_require, | ||
}, | ||
entry_points={ | ||
'console_scripts': [ | ||
'simp_le = simp_le:main', | ||
], | ||
}, | ||
) |
Oops, something went wrong.