Coder Social home page Coder Social logo

manuale's People

Contributors

eroen avatar haddoncd avatar jgiannuzzi avatar mbr avatar robbat2 avatar szepeviktor avatar veeti avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

manuale's Issues

Account import/export

  • Import existing RSA key and create account with it/find existing account
  • Convenience command to export the account key as PEM

Full elliptic curve support

Allow creation of certificates and accounts (if supported?) using EC keys. Also allow the user to specify the curve.

(Pull requests welcome!)

Issue should require CSR XOR domain(s)

Please change the issue command to disallow conflicting parameters.

  1. Domains (optionally with a pre-existing key to use).
  2. CSR, no domains, no key: Both key & domains are implicitly included in the CSR.

At present, if you specify a CSR, the domains will be used for printing on screen, but might not match the CSR at all. This can be very confusing when you are trying to debug errors.

How to renew authorisation?

Hi

Apologies if I'm about to ask something that is more down to how Let's Encrypt works ...

I've just started trying your tool. I've authorised a domain and the completion has said "Authorization lasts until 2016-11-20T19:13:05Z". What isn't clear is what do I do in order to "renew" that authorisation?

If I just run "manuale authorize ", will that give me a fresh TXT record that I've got to plug into the DNS or will it extend the authorisation of the domain now that it has been authorised?

I'm trying to understand how renewal in general (authorisation and certificate) works with your tool.

Thanks.

Split challenge generation & challenge verification

For ease of automation, please split the generation of a challenge & the verification call.

Workflow example.

  1. manuale authorize --generate-only --method dns example.com >somefile
  2. grep TXT somefile | $custom_update_DNS --append example.com
  3. manuale authorize --verify-only --method dns example.com

`manuale register ...` "unhandled error": stat: can't specify None for path argument

git clone https://github.com/veeti/manuale.git
cd manuale
git log | head
    commit 1de8f90bc8ec633b0c53cf0d1b923fe8b39c82e4
    Author: Veeti Paananen <[email protected]>
    Date:   Tue Feb 9 19:07:44 2016 +0200

        1.0.2.dev0

    commit c826e2483b5515a3e316bafa33fac248c6e91993
    Author: Veeti Paananen <[email protected]>
    Date:   Tue Feb 9 18:54:27 2016 +0200


python --version
    Python 3.4.1
python setup.py install
which manuale
    /usr/bin/manuale
manuale -h
    usage: manuale [-h] [--server SERVER] [--account ACCOUNT]
                   {register,authorize,issue,revoke,info,version} ...

    Interact with ACME certification authorities such as Let's Encrypt.

    No idea what you're doing? Register an account, authorize your domains and
    issue a certificate or two. Call a command with -h for more instructions.

    positional arguments:
      {register,authorize,issue,revoke,info,version}
        register            Create a new account and register
        authorize           Verify domain ownership
        issue               Request a new certificate
        revoke              Revoke an issued certificate
        info                Shows account information from the service
        version             Show the version number

    optional arguments:
      -h, --help            show this help message and exit
      --server SERVER, -s SERVER
                            The ACME server to use (default:
                            https://acme-v01.api.letsencrypt.org/)
      --account ACCOUNT, -a ACCOUNT
                            The account file to use or create (default:
                            account.json)

manuale register [email protected]
    You're about to register a new account with the e-mail [email protected]. Continue? [Y/n] Y
    Generating a new account key. This might take a second.
    Key generated.
    Registering...
    Oops! An unhandled error occurred. Please file a bug.
    stat: can't specify None for path argument
    Traceback (most recent call last):
      File "/usr/lib/python3.4/site-packages/manuale-1.0.2.dev0-py3.4.egg/manuale/cli.py", line 229, in main
        args.func(args)
      File "/usr/lib/python3.4/site-packages/manuale-1.0.2.dev0-py3.4.egg/manuale/cli.py", line 97, in _register
        register(args.server, args.account, args.email)
      File "/usr/lib/python3.4/site-packages/manuale-1.0.2.dev0-py3.4.egg/manuale/register.py", line 35, in register
        registration = acme.register(email)
      File "/usr/lib/python3.4/site-packages/manuale-1.0.2.dev0-py3.4.egg/manuale/acme.py", line 48, in register
        "mailto:{}".format(email)
      File "/usr/lib/python3.4/site-packages/manuale-1.0.2.dev0-py3.4.egg/manuale/acme.py", line 165, in post
        header, protected = self.get_headers()
      File "/usr/lib/python3.4/site-packages/manuale-1.0.2.dev0-py3.4.egg/manuale/acme.py", line 38, in get_headers
        protected_header['nonce'] = self.get_nonce()
      File "/usr/lib/python3.4/site-packages/manuale-1.0.2.dev0-py3.4.egg/manuale/acme.py", line 30, in get_nonce
        return self.get('/directory').headers.get('Replay-Nonce')
      File "/usr/lib/python3.4/site-packages/manuale-1.0.2.dev0-py3.4.egg/manuale/acme.py", line 157, in get
        return requests.get(self.path(path), headers=_headers)
      File "/usr/lib/python3.4/site-packages/requests/api.py", line 67, in get
        return request('get', url, params=params, **kwargs)
      File "/usr/lib/python3.4/site-packages/requests/api.py", line 53, in request
        return session.request(method=method, url=url, **kwargs)
      File "/usr/lib/python3.4/site-packages/requests/sessions.py", line 468, in request
        resp = self.send(prep, **send_kwargs)
      File "/usr/lib/python3.4/site-packages/requests/sessions.py", line 576, in send
        r = adapter.send(request, **kwargs)
      File "/usr/lib/python3.4/site-packages/requests/adapters.py", line 342, in send
        self.cert_verify(conn, request.url, verify, cert)
      File "/usr/lib/python3.4/site-packages/requests/adapters.py", line 187, in cert_verify
        if not os.path.isdir(cert_loc):
      File "/usr/lib64/python3.4/genericpath.py", line 42, in isdir
        st = os.stat(s)
    TypeError: stat: can't specify None for path argument

env/bin/python setup.py install fails on OpenBSD 6.1

✔ user.tina ~/proj/manuale
$ ls -al
total 16
drwxr-xr-x   2 user  user   512 May 25 18:53 .
drwxr-xr-x  71 user  user  2048 May 17 15:45 ..

✔ user.tina ~/proj/manuale
$ git clone https://github.com/veeti/manuale .
Cloning into '.'...
remote: Counting objects: 200, done.
remote: Total 200 (delta 0), reused 0 (delta 0), pack-reused 200
Receiving objects: 100% (200/200), 40.43 KiB | 0 bytes/s, done.
Resolving deltas: 100% (123/123), done.

✔ user.tina ~/proj/manuale
$ python3.6 -m venv env

✔ user.tina ~/proj/manuale
$ env/bin/python setup.py install
running install
running bdist_egg
running egg_info
creating manuale.egg-info
writing manuale.egg-info/PKG-INFO
writing dependency_links to manuale.egg-info/dependency_links.txt
writing entry points to manuale.egg-info/entry_points.txt
writing requirements to manuale.egg-info/requires.txt
writing top-level names to manuale.egg-info/top_level.txt
writing manifest file 'manuale.egg-info/SOURCES.txt'
reading manifest file 'manuale.egg-info/SOURCES.txt'
reading manifest template 'MANIFEST.in'
writing manifest file 'manuale.egg-info/SOURCES.txt'
installing library code to build/bdist.openbsd-6.1-amd64/egg
running install_lib
running build_py
creating build
creating build/lib
creating build/lib/manuale
copying manuale/__init__.py -> build/lib/manuale
copying manuale/account.py -> build/lib/manuale
copying manuale/acme.py -> build/lib/manuale
copying manuale/authorize.py -> build/lib/manuale
copying manuale/cli.py -> build/lib/manuale
copying manuale/crypto.py -> build/lib/manuale
copying manuale/errors.py -> build/lib/manuale
copying manuale/helpers.py -> build/lib/manuale
copying manuale/info.py -> build/lib/manuale
copying manuale/issue.py -> build/lib/manuale
copying manuale/register.py -> build/lib/manuale
copying manuale/revoke.py -> build/lib/manuale
creating build/bdist.openbsd-6.1-amd64
creating build/bdist.openbsd-6.1-amd64/egg
creating build/bdist.openbsd-6.1-amd64/egg/manuale
copying build/lib/manuale/__init__.py -> build/bdist.openbsd-6.1-amd64/egg/manuale
copying build/lib/manuale/account.py -> build/bdist.openbsd-6.1-amd64/egg/manuale
copying build/lib/manuale/acme.py -> build/bdist.openbsd-6.1-amd64/egg/manuale
copying build/lib/manuale/authorize.py -> build/bdist.openbsd-6.1-amd64/egg/manuale
copying build/lib/manuale/cli.py -> build/bdist.openbsd-6.1-amd64/egg/manuale
copying build/lib/manuale/crypto.py -> build/bdist.openbsd-6.1-amd64/egg/manuale
copying build/lib/manuale/errors.py -> build/bdist.openbsd-6.1-amd64/egg/manuale
copying build/lib/manuale/helpers.py -> build/bdist.openbsd-6.1-amd64/egg/manuale
copying build/lib/manuale/info.py -> build/bdist.openbsd-6.1-amd64/egg/manuale
copying build/lib/manuale/issue.py -> build/bdist.openbsd-6.1-amd64/egg/manuale
copying build/lib/manuale/register.py -> build/bdist.openbsd-6.1-amd64/egg/manuale
copying build/lib/manuale/revoke.py -> build/bdist.openbsd-6.1-amd64/egg/manuale
byte-compiling build/bdist.openbsd-6.1-amd64/egg/manuale/__init__.py to __init__.cpython-36.pyc
byte-compiling build/bdist.openbsd-6.1-amd64/egg/manuale/account.py to account.cpython-36.pyc
byte-compiling build/bdist.openbsd-6.1-amd64/egg/manuale/acme.py to acme.cpython-36.pyc
byte-compiling build/bdist.openbsd-6.1-amd64/egg/manuale/authorize.py to authorize.cpython-36.pyc
byte-compiling build/bdist.openbsd-6.1-amd64/egg/manuale/cli.py to cli.cpython-36.pyc
byte-compiling build/bdist.openbsd-6.1-amd64/egg/manuale/crypto.py to crypto.cpython-36.pyc
byte-compiling build/bdist.openbsd-6.1-amd64/egg/manuale/errors.py to errors.cpython-36.pyc
byte-compiling build/bdist.openbsd-6.1-amd64/egg/manuale/helpers.py to helpers.cpython-36.pyc
byte-compiling build/bdist.openbsd-6.1-amd64/egg/manuale/info.py to info.cpython-36.pyc
byte-compiling build/bdist.openbsd-6.1-amd64/egg/manuale/issue.py to issue.cpython-36.pyc
byte-compiling build/bdist.openbsd-6.1-amd64/egg/manuale/register.py to register.cpython-36.pyc
byte-compiling build/bdist.openbsd-6.1-amd64/egg/manuale/revoke.py to revoke.cpython-36.pyc
creating build/bdist.openbsd-6.1-amd64/egg/EGG-INFO
copying manuale.egg-info/PKG-INFO -> build/bdist.openbsd-6.1-amd64/egg/EGG-INFO
copying manuale.egg-info/SOURCES.txt -> build/bdist.openbsd-6.1-amd64/egg/EGG-INFO
copying manuale.egg-info/dependency_links.txt -> build/bdist.openbsd-6.1-amd64/egg/EGG-INFO
copying manuale.egg-info/entry_points.txt -> build/bdist.openbsd-6.1-amd64/egg/EGG-INFO
copying manuale.egg-info/requires.txt -> build/bdist.openbsd-6.1-amd64/egg/EGG-INFO
copying manuale.egg-info/top_level.txt -> build/bdist.openbsd-6.1-amd64/egg/EGG-INFO
zip_safe flag not set; analyzing archive contents...
creating dist
creating 'dist/manuale-1.1.0-py3.6.egg' and adding 'build/bdist.openbsd-6.1-amd64/egg' to it
removing 'build/bdist.openbsd-6.1-amd64/egg' (and everything under it)
Processing manuale-1.1.0-py3.6.egg
Copying manuale-1.1.0-py3.6.egg to /home/user/proj/manuale/env/lib/python3.6/site-packages
Adding manuale 1.1.0 to easy-install.pth file
Installing manuale script to /home/user/proj/manuale/env/bin

Installed /home/user/proj/manuale/env/lib/python3.6/site-packages/manuale-1.1.0-py3.6.egg
Processing dependencies for manuale==1.1.0
Searching for requests
Reading https://pypi.python.org/simple/requests/
Downloading https://pypi.python.org/packages/72/46/4abc3f5aaf7bf16a52206bb0c68677a26c216c1e6625c78c5aef695b5359/requests-2.14.2.tar.gz#md5=4c3c169ed67466088a2a6947784fe444
Best match: requests 2.14.2
Processing requests-2.14.2.tar.gz
Writing /tmp/easy_install-ox29086u/requests-2.14.2/setup.cfg
Running requests-2.14.2/setup.py -q bdist_egg --dist-dir /tmp/easy_install-ox29086u/requests-2.14.2/egg-dist-tmp-cdeygr7_
warning: no files found matching 'test_requests.py'
creating /home/user/proj/manuale/env/lib/python3.6/site-packages/requests-2.14.2-py3.6.egg
Extracting requests-2.14.2-py3.6.egg to /home/user/proj/manuale/env/lib/python3.6/site-packages
Adding requests 2.14.2 to easy-install.pth file

Installed /home/user/proj/manuale/env/lib/python3.6/site-packages/requests-2.14.2-py3.6.egg
Searching for cryptography>=1.0
Reading https://pypi.python.org/simple/cryptography/
Downloading https://pypi.python.org/packages/ec/5f/d5bc241d06665eed93cd8d3aa7198024ce7833af7a67f6dc92df94e00588/cryptography-1.8.1.tar.gz#md5=9f28a9c141995cd2300d0976b4fac3fb
Best match: cryptography 1.8.1
Processing cryptography-1.8.1.tar.gz
Writing /tmp/easy_install-30e7tmsb/cryptography-1.8.1/setup.cfg
Running cryptography-1.8.1/setup.py -q bdist_egg --dist-dir /tmp/easy_install-30e7tmsb/cryptography-1.8.1/egg-dist-tmp-6i6tsjfg
_configtest.c:1: error: thread-local storage not supported for this target
Note: will not use '__thread' in the C code
***** The above error message can be safely ignored.


Installed /tmp/easy_install-30e7tmsb/cryptography-1.8.1/.eggs/cffi-1.10.0-py3.6-openbsd-6.1-amd64.egg
Searching for pycparser
Reading https://pypi.python.org/simple/pycparser/
Downloading https://pypi.python.org/packages/be/64/1bb257ffb17d01f4a38d7ce686809a736837ad4371bcc5c42ba7a715c3ac/pycparser-2.17.tar.gz#md5=ca98dcb50bc1276f230118f6af5a40c7
Best match: pycparser 2.17
Processing pycparser-2.17.tar.gz
Writing /tmp/easy_install-30e7tmsb/cryptography-1.8.1/temp/easy_install-i3hr8lo1/pycparser-2.17/setup.cfg
Running pycparser-2.17/setup.py -q bdist_egg --dist-dir /tmp/easy_install-30e7tmsb/cryptography-1.8.1/temp/easy_install-i3hr8lo1/pycparser-2.17/egg-dist-tmp-vavlbz1f
warning: no previously-included files matching 'yacctab.*' found under directory 'tests'
warning: no previously-included files matching 'lextab.*' found under directory 'tests'
warning: no previously-included files matching 'yacctab.*' found under directory 'examples'
warning: no previously-included files matching 'lextab.*' found under directory 'examples'
zip_safe flag not set; analyzing archive contents...
pycparser.ply.__pycache__.lex.cpython-36: module references __file__
pycparser.ply.__pycache__.lex.cpython-36: module MAY be using inspect.getsourcefile
pycparser.ply.__pycache__.ygen.cpython-36: module references __file__
pycparser.ply.__pycache__.yacc.cpython-36: module references __file__
pycparser.ply.__pycache__.yacc.cpython-36: module MAY be using inspect.getsourcefile
pycparser.ply.__pycache__.yacc.cpython-36: module MAY be using inspect.stack
creating /tmp/easy_install-30e7tmsb/cryptography-1.8.1/.eggs/pycparser-2.17-py3.6.egg
Extracting pycparser-2.17-py3.6.egg to /tmp/easy_install-30e7tmsb/cryptography-1.8.1/.eggs

Installed /tmp/easy_install-30e7tmsb/cryptography-1.8.1/.eggs/pycparser-2.17-py3.6.egg
no previously-included directories found matching 'docs/_build'
warning: no previously-included files matching '*' found under directory 'vectors'
build/temp.openbsd-6.1-amd64-3.6/_openssl.c:3484: error: expected identifier or '(' before numeric constant
build/temp.openbsd-6.1-amd64-3.6/_openssl.c:3485: error: expected identifier or '(' before numeric constant
build/temp.openbsd-6.1-amd64-3.6/_openssl.c:3486: error: expected identifier or '(' before numeric constant
build/temp.openbsd-6.1-amd64-3.6/_openssl.c: In function '_setup_ssl_threads':
build/temp.openbsd-6.1-amd64-3.6/_openssl.c:3589: warning: comparison is always false due to limited range of data type
error: Setup script exited with error: command 'cc' failed with exit status 1

✘ user.tina ~/proj/manuale
$ uname -mrsv 
OpenBSD 6.1 GENERIC.MP#20 amd64

✔ user.tina ~/proj/manuale
$ file build/temp.openbsd-6.1-amd64-3.6/_openssl.c 
build/temp.openbsd-6.1-amd64-3.6/_openssl.c: cannot stat 'build/temp.openbsd-6.1-amd64-3.6/_openssl.c' (No such file or directory)

✔ user.tina ~/proj/manuale
$ python3.6 --version                                                                                       
Python 3.6.0

"issue" usage is incorrect

usage: manuale issue [-h] [--key-size KEY_SIZE] [--key-file KEY_FILE]
[--csr-file CSR_FILE] [--output OUTPUT]
domain [domain ...]

it implies it's possible to specify multiple domains, but only one domain is ever processed.

Support Python2.7

Any chance you'd be willing to support 2.7? Would help me out a bunch. What's stopping this from being 2.7 compatible?.. hm, I guess just needs

from builtins import bytes
and to wrap the byte strings in bytes() ?

Renew

How no renew certificate?

'utf-8' codec can't decode byte 0xc5

After the prompt Press enter to continue. I accidentally pressed ű then ENTER

Oops! An unhandled error occurred. Please file a bug.
'utf-8' codec can't decode byte 0xc5 in position 0: unexpected end of data
Traceback (most recent call last):
  File "/home/prg474/.local/lib/python3.4/site-packages/manuale/cli.py", line 239, in main
    args.func(args)
  File "/home/prg474/.local/lib/python3.4/site-packages/manuale/cli.py", line 105, in _authorize
    authorize(args.server, account, args.domain, args.method)
  File "/home/prg474/.local/lib/python3.4/site-packages/manuale/authorize.py", line 109, in authorize
    input("Press enter to continue.")
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xc5 in position 0: unexpected end of data

Python 3.5 deprication notice

# manuale/crypto.py:80: CryptographyDeprecationWarning: signer and verifier have been deprecated.
# Please use sign and verify instead.
  signer = key.signer(padding.PKCS1v15(), hashes.SHA256())

@veeti Is it simply changing the name of functions?

Challenge support: tls-sni-02

Add support for the tls-sni-02 challenge.

This cannot be tested with Boulder/LE yet, but will be available in early 2018 with the updated API.

random certs deauthorzied and can not be renewed

Good day.
I do have right now 48 certs. They renewed at different dates, so I have max 19 renew in a week. But yesterday 18 of them did not renew with error:

Generating a 2048 bit RSA key. This might take a second.
Key generated.

Requesting certificate issuance...
Connection or service request failed. Aborting.
Error creating new cert :: authorizations for these names not found or expired: mysite.com (type urn:acme:error:unauthorized, HTTP 403)

How can I determine why it happened ? Or can you help me, or can I help you.
All certs issued max 2 months ago and some of them in use about half year (of course with renewing every 2 months)

Using a CSR without the private key

Using a command like manuale issue --csr-file cert.req my.chosen.domain does produce the correct result in that the certificate is issued based on the contents of the public key in cert.req. But manuale still also generates a (new) private key, if --key-file is not also used. This generated private key is also saved to a file and the user might get the impression that the generated key is the one to use, even if he provided a CSR that contains a different key.

The scenario I'm trying to accommodate is to have the certificate's private key only on the system that needs it, i.e. the machine that will be using the certificate to provide a service. The system that makes the certificate request with manuale via acme doesn't need the key.

My suggestion is to modify issue.py so that if a CSR is provided, generating a private key is always skipped because the public key is in the CSR. Basically moving

manuale/manuale/issue.py

Lines 33 to 45 in 99c9865

# Load key or generate
if key_file:
try:
with open(key_file, 'rb') as f:
certificate_key = load_private_key(f.read())
except (ValueError, AttributeError, TypeError, IOError) as e:
logger.error("Couldn't read certificate key.")
raise ManualeError(e)
else:
logger.info("Generating a {} bit RSA key. This might take a second.".format(key_size))
certificate_key = generate_rsa_key(key_size)
logger.info("Key generated.")
logger.info("")
to the else part at around

manuale/manuale/issue.py

Lines 55 to 56 in 99c9865

else:
csr = create_csr(certificate_key, domains)
and some private key file handling changes later in the file should take care of it.

Allow EC keys

Hi there, thanks for this great project.

At the moment, manuale does not officially support the use of EC keys. I know it is not optimal (mostly due to the function names) but just by commenting out 4 lines in crypto.py file, it is possible to use the client with the EC keys in addition to the RSA keys. Here is the part that needs to be commented out (crypto.py file lines 94-97):

    if not isinstance(key, RSAPrivateKey):
        raise ValueError("Key is not a private RSA key.")
    elif key.key_size < 2048:
        raise ValueError("The key must be 2048 bits or longer.")

I thought this little workaround might be useful for people who need EC certificates and wanted to share in an issue instead of sending a pull request.

Thanks again for providing a let's encrypt client with a sane user interface.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.