Coder Social home page Coder Social logo

ruby-acme-cli's Introduction

ACME-Cli

Build Status Gem Version

Yet another ACME client (e.g. to use together with Letsencrypt CA to issue TLS certs) for command lines using Ruby.

Installation

  • This tool needs Ruby >= 2.1 (as the dependency acme-client needs that because of use of keyword arguments).
  • OpenSSL bindings
  • no sudo! (needs access to webserver-root /.well-known/acme-challenges alias for all domains - See later section for Nginx example)
# check your ruby version:
$ ruby --version
ruby 2.2.3p173 (2015-08-18 revision 51636) [x86_64-linux]

$ gem install acme-cli

$ acme-cli --version
0.2.0

Troubleshooting Ruby version

Unfortunately, most Linux distributions does not ship a current Ruby version (Version 1.9.3 or 2.0). Check, if your ruby version is at least 2.2. Otherwise you need to update the Ruby.

If you are installing this as a non-root user, you might want to try RVM. Installation itself needs no root, but needs some packages:

sudo apt-get install curl bison build-essential zlib1g-dev libssl-dev libreadline6-dev libxml2-dev libgmp-dev git-core

To install RVM:

gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
\curl -sSL https://get.rvm.io | bash -s stable  --autolibs=disable --auto-dotfiles

rvm install 2.2
source ~/.bashrc # or ~/.profile RVM tells you to reload your shell

ruby --version

Notice: If you are using RVM, all your cronjobs must be run as a login shell, otherwise RVM does not work:

* * * * * /bin/bash -l -c "acme-cli manage ..."

Another way, e.g. on Ubuntu 14.04 might be to use the Brightbox ppa.

Usage

Specify -t to use Letsencrypt test server. Without it, all requests are called against the production server, that might have some more strict rate limiting. If you are just toying around, add the -t flag.

# show all commands

acme-cli help

# show options for an individual command
acme-cli help cert

# creates account_key.json in current_dir
acme-cli register -t [email protected]

# authorize one or more domains/subdomains
acme-cli authorize -t --webroot-path /var/www/default example.com www.example.com somedir.example.com

# experimental: authorize all server_names in /etc/nginx/sites-enabled/*
acme-cli authorize_all -t --webroot-path /var/www/default

# create a certificate for domains that are already authorized within the last minutes (1h-2h I think)
# the first domain will be the cn subject. All other are subjectAlternateName
# if cert.pem already exists, will only create a new one if the old is expired
# (30 days before expiration) -> see full help
acme-cli help cert

acme-cli cert -t example.com www.example.com somdir.example.com
# will create key.pem fullchain.pem chain.pem and cert.pem in current directory

# checks validation date of given certificate.
# Exists non-zero if:
# * not exists (exit 1)
# * will expire in more than 30 days (exit code 2)
acme-cli check --days-valid 30 cert.pem

And last but not least, the meta command manage that integrated check + authorize + cert (intended to be run as cronjob):

$ acme-cli manage --days-valid 30 \
                       --account-key /home/acme/account_key.pem \
                       --webroot-path /home/acme/webroot/.well-known/acme-challenge \
                       --key-directory /home/acme/certs \
                       example.com www.example.com

2015-12-05 23:40:04 +0100: Certificate /home/acme/certs/example.com/cert.pem does not exists
2015-12-05 23:40:04 +0100: Authorizing example.com...
2015-12-05 23:40:04 +0100: existing account key found
2015-12-05 23:40:06 +0100: Authorization successful for example.com
2015-12-05 23:40:06 +0100: Authorizing www.example.com
2015-12-05 23:40:08 +0100: Authorization successful for www.example.com
2015-12-05 23:40:08 +0100: creating new private key to /home/acme/certs/example.com/key.pem...
2015-12-05 23:40:09 +0100: Certificate successfully created to /home/acme/certs/example.com/fullchain.pem /home/acme/certs/example.com/chain.pem and /home/acme/certs/example.com/cert.pem!
2015-12-05 23:40:09 +0100: Certificate valid until: 2016-03-04 21:40:00 UTC

# Run command again exits immediately:
$ acme-cli manage --days-valid 30 --account-key /home/acme/account_key.pem --webroot-path /home/acme/webroot/.wel
l-known/acme-challenge --key-directory /home/acme/certs \
      example.com www.example.com
2015-12-05 23:40:17 +0100: Certificate '/home/acme/certs/example.com/cert.pem' valid until 2016-03-04.
$ echo $?
1

This had:

  1. check if /home/acme/certs/example.com/cert.pem exists and expires in less than 30 days (or exit 1 at this point)
  2. authorize all domains + subdomains
  3. issue one certificate with those domains and place it under /home/acme/certs/example.com/[key.pem,fullchain.pem,chain.pem,cert.pem]
  4. exit 0 -> so can be && with service nginx reload or mail deliver

For running as cron, reducing log level to fatal might be desirable: acme-cli manage --log-level fatal.

Example integration Nginx:

server {
  listen 80;
  server_name example.com www.example.com somedir.example.com
  location /.well-known/acme-challenge {
	  alias /home/acme/webroot/.well-known/acme-challenge;
	  default_type "text/plain";
	  try_files $uri =404;
  }

notice the location - alias. Use this dir with --webroot-path for authorization.

Afterwards, use the fullchain.pem and key.pem:

server {
  listen 443 ssl;
  server_name example.com www.example.com;
  ssl on;
  ssl_certificate_key /home/acme/certs/example.com/key.pem;
  ssl_certificate /home/acme/certs/example.com/fullchain.pem;

  # use the settings from: https://gist.github.com/konklone/6532544

Development

After checking out the repo, run bin/setup to install dependencies. Then, run bin/console for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release to create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.

Contributing

  1. Fork it ( https://github.com/zealot128/ruby-acme-cli/fork )
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request

ruby-acme-cli's People

Contributors

beam avatar kenrick avatar kubicek avatar mantap123 avatar steveyken avatar troelskn avatar zealot128 avatar zygiss 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

Watchers

 avatar  avatar  avatar  avatar  avatar

ruby-acme-cli's Issues

`certificate_exists_and_valid_and_all_domains_included?` is confusing

The method returns false or exits. From the name, one would assume it to return a boolean in all cases. Either the method should be renamed (To something like ensure_certificate_exists_and_valid_and_all_domains_included! perhaps) or it should return true instead of exit 2. The latter is probably better, but would require calling code to change.

fullchain.pem is chain.pem + cert.pem, should be cert.pem + chain.pem

Using the generated fullchain.pem, nginx gives the following error:

2015/12/06 22:05:36 [emerg] 18678#0: SSL_CTX_use_PrivateKey_file("/home/letsencrypt/key.pem") failed (SSL: error:0B080074:x509 certificate routines:X509_check_private_key:key values mismatch)

Looking into the fullchain.pem, it contains the chain.pem followed by the cert.pem. According to http://nginx.org/en/docs/http/configuring_https_servers.html, the full chain needs to be the cert.pem followed by the chain.pem.

Regenerating the fullchain.pem in the correct order manually (cat cert.pem chain.pem > fullchain.pem) resovles the error.

Thanks for the gem!

undefined method light_black

I am using Capistrano for continuous deployment of my Ruby on Rails and NodeJS applications.
I found capistrano plugin: https://github.com/platanus/capistrano-lets-encrypt

It using your project as dependency. When I execute this command:
cap staging lets_encrypt:register --trace

My deployment process failed. After some hacks, light_black is an extension to string method on Ruby. It is provided by colorizegem. I check at my Gemfile.lock,colorize` gem was listed. I don't know why it was not loaded...

I will create pull request to fix this problem. ๐Ÿ˜„

** Invoke staging (first_time)
** Execute staging
** Invoke load:defaults (first_time)
** Execute load:defaults
** Invoke bundler:map_bins (first_time)
** Execute bundler:map_bins
** Invoke deploy:set_rails_env (first_time)
** Execute deploy:set_rails_env
** Invoke deploy:set_linked_dirs (first_time)
** Execute deploy:set_linked_dirs
** Invoke deploy:set_rails_env 
** Invoke rbenv:validate (first_time)
** Execute rbenv:validate
** Invoke rbenv:map_bins (first_time)
** Execute rbenv:map_bins
** Invoke lets_encrypt:register (first_time)
** Execute lets_encrypt:register
cap aborted!
NoMethodError: undefined method `light_black' for "2016-12-03 20:04:33 +0700":String
/Users/mantap123/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/letsencrypt-cli-0.4.1/lib/letsencrypt/cli/acme_wrapper.rb:17:in `block (2 levels) in log'
/Users/mantap123/.rbenv/versions/2.3.1/lib/ruby/2.3.0/logger.rb:546:in `format_message'
/Users/mantap123/.rbenv/versions/2.3.1/lib/ruby/2.3.0/logger.rb:434:in `add'
/Users/mantap123/.rbenv/versions/2.3.1/lib/ruby/2.3.0/logger.rb:489:in `info'
/Users/mantap123/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/letsencrypt-cli-0.4.1/lib/letsencrypt/cli/acme_wrapper.rb:20:in `log'
/Users/mantap123/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/letsencrypt-cli-0.4.1/lib/letsencrypt/cli/acme_wrapper.rb:168:in `find_or_create_pkey'
/Users/mantap123/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/letsencrypt-cli-0.4.1/lib/letsencrypt/cli/acme_wrapper.rb:160:in `account_key'
/Users/mantap123/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/letsencrypt-cli-0.4.1/lib/letsencrypt/cli/acme_wrapper.rb:24:in `client'
/Users/mantap123/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/capistrano-lets-encrypt-0.2.0/lib/capistrano/tasks/lets-encrypt.rake:174:in `client'
/Users/mantap123/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/capistrano-lets-encrypt-0.2.0/lib/capistrano/tasks/lets-encrypt.rake:17:in `block (2 levels) in <top (required)>'

Feature: configuration defaults

How about adding support for configuration defaults?

For instance /etc/letsencrypt-cli/letsencrypt-cli.yml with precedence over ~/.letsencrypt-cli.yml:


---
account-key: "/etc/letsencrypt/account_key.pem"
test: true

This would come in very handy for servers with numerous virtual hosts.

How to renew exist certs

Hi,

Is there any way to renew exist certs?

When I use manage command, it just told me to renew, but no way to update exist cert files unless remove them.

example:

 letsencrypt-cli manage --days-valid 20 --account-key /root/account_key.pem --key-directory /etc/letsencrypt/live --webroot-path /var/www/acme-challenge  xxx.example.com
2016-10-17 14:59:14 +0800: Certificate '/etc/letsencrypt/live/xxx.example.com/cert.pem' valid until 2016-10-31.
2016-10-17 14:59:14 +0800: Certificate '/etc/letsencrypt/live/xxx.example.com/cert.pem' should be renewed!
2016-10-17 14:59:14 +0800: Authorizing xxx.example.com..
2016-10-17 14:59:14 +0800: existing account key found
2016-10-17 14:59:25 +0800: Authorization successful for xxx.example.com

Unable to get cert or renew

Following the example in the documentation and issuing this command:

letsencrypt-cli authorize --webroot-path /var/www/html/site lms.mysite.com

It appears that lets-encrypt looks for the .well-known as part of the domain, not as a directory within it:

2017-01-30 20:52:58 +0000: Authorization error for lms.mysite.com
2017-01-30 20:52:58 +0000: Could not connect to lms.mysite.com.well-known

It should be going to lms.mysite.com/.well-known instead of lms.mysite.com.well-known, but I have no idea why it's not inserting that extra / or how to get it to do so; the examples don't show it, certainly.

This is odd as I'm confident the examples in the README worked before, but I can't get them to now. Any thoughts or suggestions?

Please rename project

For trademark reasons we cannot allow ACME clients to use our service's name (Let's Encrypt) in their name. Among other things, it can introduce confusion as to whether the client comes from us or someone else. We recommend you use the term "ACME" instead, in reference to the protocol implemented by your client. The term "ACME" is better because there are no trademark issues and the protocol is not specific to our CA so your client should work with other ACME-enabled CAs in the future.

I know this can be a pain but thanks for understanding.

Error with sshkit 1.8.1

I got error on colorized log used by acme_wrapper in this gem:

cap aborted!
NoMethodError: undefined method `light_black' for "2016-03-11 14:59:59 +0100":String
/Users/michele/.rvm/gems/ruby-2.2.2@rails5/gems/letsencrypt-cli-0.2.0/lib/letsencrypt/cli/acme_wrapper.rb:16:in `block (2 levels) in log'
/Users/michele/.rvm/rubies/ruby-2.2.2/lib/ruby/2.2.0/logger.rb:491:in `call'
/Users/michele/.rvm/rubies/ruby-2.2.2/lib/ruby/2.2.0/logger.rb:491:in `format_message'
/Users/michele/.rvm/rubies/ruby-2.2.2/lib/ruby/2.2.0/logger.rb:379:in `add'
/Users/michele/.rvm/rubies/ruby-2.2.2/lib/ruby/2.2.0/logger.rb:434:in `info'
/Users/michele/.rvm/gems/ruby-2.2.2@rails5/gems/letsencrypt-cli-0.2.0/lib/letsencrypt/cli/acme_wrapper.rb:19:in `log'
/Users/michele/.rvm/gems/ruby-2.2.2@rails5/gems/capistrano-lets-encrypt-0.2.0/lib/capistrano/tasks/lets-encrypt.rake:58:in `check_certificate'
/Users/michele/.rvm/gems/ruby-2.2.2@rails5/gems/capistrano-lets-encrypt-0.2.0/lib/capistrano/tasks/lets-encrypt.rake:32:in `block (3 levels) in <top (required)>'
/Users/michele/.rvm/gems/ruby-2.2.2@rails5/gems/sshkit-1.8.1/lib/sshkit/backends/abstract.rb:15:in `instance_exec'
/Users/michele/.rvm/gems/ruby-2.2.2@rails5/gems/sshkit-1.8.1/lib/sshkit/backends/abstract.rb:15:in `run'
/Users/michele/.rvm/gems/ruby-2.2.2@rails5/gems/sshkit-1.8.1/lib/sshkit/runners/parallel.rb:13:in `block (2 levels) in execute'
Tasks: TOP => lets_encrypt:authorize

I solved locking sshkit to 1.7.1:

gem 'sshkit', '1.7.1' 

uninitialized constant AcmeWrapper::Logger

I am getting a NameError with the version currently available via rubygems:

# letsencrypt-cli --version
0.4.0

# ruby --version
ruby 2.1.5p273 (2014-11-13) [x86_64-linux-gnu]

# letsencrypt-cli register [email protected]
/var/lib/gems/2.1.0/gems/letsencrypt-cli-0.4.0/lib/letsencrypt/cli/acme_wrapper.rb:13:in `log': uninitialized constant AcmeWrapper::Logger (NameError)
    from /var/lib/gems/2.1.0/gems/letsencrypt-cli-0.4.0/lib/letsencrypt/cli/acme_wrapper.rb:167:in `find_or_create_pkey'
    from /var/lib/gems/2.1.0/gems/letsencrypt-cli-0.4.0/lib/letsencrypt/cli/acme_wrapper.rb:159:in `account_key'
    from /var/lib/gems/2.1.0/gems/letsencrypt-cli-0.4.0/lib/letsencrypt/cli/acme_wrapper.rb:23:in `client'
    from /var/lib/gems/2.1.0/gems/letsencrypt-cli-0.4.0/lib/letsencrypt/cli/app.rb:23:in `register'
    from /usr/lib/ruby/vendor_ruby/thor/command.rb:27:in `run'
    from /usr/lib/ruby/vendor_ruby/thor/invocation.rb:126:in `invoke_command'
    from /usr/lib/ruby/vendor_ruby/thor.rb:359:in `dispatch'
    from /usr/lib/ruby/vendor_ruby/thor/base.rb:440:in `start'
    from /var/lib/gems/2.1.0/gems/letsencrypt-cli-0.4.0/exe/letsencrypt-cli:5:in `<top (required)>'
    from /usr/local/bin/letsencrypt-cli:23:in `load'
    from /usr/local/bin/letsencrypt-cli:23:in `<main>'

Manage command exited automatically if any host is valid

 letsencrypt-cli manage --days-valid 30 --account-key /root/account_key.pem --key-directory /etc/letsencrypt/live --webroot-path /var/www/acme-challenge example1.com example2.com
2016-10-17 15:27:47 +0800: Certificate '/etc/letsencrypt/live/example1.com/cert.pem' valid until 2016-12-27.

In my command I input 2 host but it exited automatically when the first one is valid.

Able to happen in newest version (0.4.1)

Certificate not regenerated when domains are added/removed

With the cert or manage commands, providing new domains or removing some will not regenerate a new certificate if the current one is not expired. Perhaps an option could be added to force regeneration if the provided domains don't strictly match the current certificate ?

An option to unconditionally regenerate could also be useful.

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.