Code Monkey home page Code Monkey logo

lcget's Introduction

lcget is a wrapper (written in Tcl/expect) for letsencrypt which automates the task of completing challenges for remote server/domains from a local machine. It relieves you of the pain of running multiple commands in multiple terminals. Most of the time, a single command in a single terminal will be enough to get the certificate from Let's Encrypt. It doesn't require sudo access on remote host if the document root is in /home directory i.e for shared hosting.

Mechanism:

lcget is an expect script which runs the letsencrypt command and monitor its' output. When the challenge appears on the output of letsencrypt command, the script parses necessary information about the challenge and tries to complete the challenge itself.

To complete the http challenge in manual mode, lcget requires ssh access to the remote host i.e it runs ssh commands to the remote host to meet the necessary requirements for the acme challenge.

Currently, only the http challenge in manual mode is supported.

Dependencies:

The script depends on the following tools/scripts:

  1. letsencrypt (certbot): The letsencrypt tool itself.
  2. expect: You may need to install this first if not installed.
  3. ssh: It is installed by default in most Unix based system.
  4. jssh: It is a wrapper to automate ssh login and/or running ssh commands.

To install jssh, download the jssh script and put it in a bin directory which is in the PATH environment variable (e.g /usr/bin). The lcget script uses jssh command to execute it by default. You can run jssh from any arbitrary path too; in that case, use the the lcget option -jp to provide the jssh path. For example:

lcget certonly --manual -d example.com -m [email protected] -jp /path/to/jssh

Install:

First you will need to give execution permission to the script. An octal 755 permission is recommended.

  • You can run the script with full path or with ./lcget by cding into the directory where it resides.
  • You can just copy the script into a standard bin directory (e.g /usr/bin).
  • Or you can run the install.sh script which tries to install it in ~/bin along with jssh.

Installing examples:

Installing in /usr/bin :

chmod 755 path/to/lcget
sudo cp path/to/lcget /usr/bin

Installing in ~/bin :

chmod 755 path/to/lcget
cp path/to/lcget $HOME/bin
# Now add $HOME/bin to PATH environment variable if not added already
var=$HOME/bin
if ! echo $PATH | grep -q  ":$var\([/:]\|$\)"; then echo "export PATH=\$PATH:$var" >> ~/.bashrc && . ~/.bashrc ;fi

Note:

If the script isn't recognized as an executable by the system, then you may try the lcget-sh script provided. Furthermore, you can change the path of lcget to the actual path inside the lcget-sh script:

#!/bin/sh
expect /actual/path/to/lcget ${1+"$@"}

and install lcget-sh instead of lcget. In this case, you will be using lcget-sh as the lcget command.

Or you can try fixing the shebang line (#!/usr/bin/expect --) to the correct one for an expect script if it is supported (don't forget the -- part though).

Usage:

lcget [native or letsencrypt options]

native options: These are the options parsed and recognized by lcget. These are:

  • --launcher-path, -lp : Launcher path. You can define the letsencrypt launcher path with this option.
  • -jssh-path, -jp : Arbitrary jssh path. If given jssh will be run with the full path specified.
  • --help, -h : This is a mixed option. It will print both lcget and letsencrypt help.
  • --version: This is a mixed option. It will print version info for both lcget and letsencrypt.

letsencrypt options: These are the options recognized by letsencrypt. These options are same as the options supported by the letsencrypt launcher.

How to:

We will need to prepare a jssh config file for each of the domains we want to get Let's Encrypt ssl certificate for. We will do this just once, after that we will be running the lcget command only.

Create jssh config file:

The config file must follow the naming convention: domain.conf e.g example.com.conf for example.com, www.example.com.conf for www.example.com etc...

To create a jssh config file run jssh -aw -c in a terminal and fill out necessary information. For example:

~$ jssh -aw -c

    Give an easy and memorable name to your config file, something like example.com.
    Later you will call jssh with this name to login to remote.
    
Enter config file name (without .conf): 
example.com
Overwrite (y/n)?: 
y
Enter domain/IP: 
example.com
Enter port number: 
22
Enter username: 
neurobin

    If a working directory is specified, jssh -cdw example.com
    will run cd WorkDir just after logging in.
    
Enter working directory: 
$HOME/public_html

    Saved as: /home/user/.neurobin/jssh/example.com.conf
    You will call jssh for this configuration like this:
    jssh example.com other_ssh_options_or_args
    'jssh example.com' is the native jssh part. All other arguments
    will be forwarded to ssh command. Any jssh native option
    must be passed before example.com.
    You can edit the config file to make further changes.
    

    Additional: /home/user/.neurobin/jssh/www.example.com.conf

This will create a config file for example.com and also for www.example.com with the same configuration ( because of the -aw flag passed with jssh).

You must give the document root of your domain as the working directory.

As www.example.com generally points to example.com i.e the config for both of them are same, we could create a symbolic link named www.example.com.conf too instead of actual file.

You will need to create jssh config file for each of your domains.

For sub-domains you can just create subdomain.rootdomain.conf file with the same credentials as rootdomain except the working directory; working directory must be the document root of the subdomain/domain. In this case ssh will login with the credentials of root domain.

Note:

  • The config file stores username, port, domain name/IP and working directory (in this case document root).

Run lcget and get the certificate:

Now all we have to do is to run the lcget command with appropriate options. The following is an example which uses a letsencrypt configuration file (All outputs are shown):

~$ lcget certonly -c neurobin.ini
Requesting root privileges to run certbot...
  /home/user/.local/share/letsencrypt/bin/letsencrypt --text certonly -c neurobin.ini
[sudo] password for user: 
Make sure your web server displays the following content at
http://challenge.neurobin.org/.well-known/acme-challenge/s3xMuDO7WwjTUX6pbAq8hj1Ixpf4V-Rin9FBmdHDV14 before continuing:

s3xMuDO7WwjTUX6pbAq8hj1Ixpf4V-Rin9FBmdHDV14.fl_1v9fRIhdgCXPAMg0ohwMfX66pkSQ_eTJjm2tejZc

If you don't have HTTP server configured, you can run the following
command on the target server (as root):

mkdir -p /tmp/certbot/public_html/.well-known/acme-challenge
cd /tmp/certbot/public_html
printf "%s" s3xMuDO7WwjTUX6pbAq8hj1Ixpf4V-Rin9FBmdHDV14.fl_1v9fRIhdgCXPAMg0ohwMfX66pkSQ_eTJjm2tejZc > .well-known/acme-challenge/s3xMuDO7WwjTUX6pbAq8hj1Ixpf4V-Rin9FBmdHDV14
# run only once per server:
$(command -v python2 || command -v python2.7 || command -v python2.6) -c \
"import BaseHTTPServer, SimpleHTTPServer; \
s = BaseHTTPServer.HTTPServer(('', 80), SimpleHTTPServer.SimpleHTTPRequestHandler); \
s.serve_forever()" 
Press ENTER to continue

Protocol: http://
Domain: challenge.neurobin.org
File: .well-known/acme-challenge/s3xMuDO7WwjTUX6pbAq8hj1Ixpf4V-Rin9FBmdHDV14
Content: s3xMuDO7WwjTUX6pbAq8hj1Ixpf4V-Rin9FBmdHDV14.fl_1v9fRIhdgCXPAMg0ohwMfX66pkSQ_eTJjm2tejZc

Trying to complete challenge for challenge.neurobin.org

Completing challenge...
Created dir : .well-known/acme-challenge
Created file: .well-known/acme-challenge/s3xMuDO7WwjTUX6pbAq8hj1Ixpf4V-Rin9FBmdHDV14

Done for challenge.neurobin.org

Make sure your web server displays the following content at
http://www.challenge.neurobin.org/.well-known/acme-challenge/DKCumvxBheZMe_cfxA83uhIA7OrTu9RZBdxxaMEbAJ8 before continuing:

DKCumvxBheZMe_cfxA83uhIA7OrTu9RZBdxxaMEbAJ8.fl_1v9fRIhdgCXPAMg0ohwMfX66pkSQ_eTJjm2tejZc

If you don't have HTTP server configured, you can run the following
command on the target server (as root):

mkdir -p /tmp/certbot/public_html/.well-known/acme-challenge
cd /tmp/certbot/public_html
printf "%s" DKCumvxBheZMe_cfxA83uhIA7OrTu9RZBdxxaMEbAJ8.fl_1v9fRIhdgCXPAMg0ohwMfX66pkSQ_eTJjm2tejZc > .well-known/acme-challenge/DKCumvxBheZMe_cfxA83uhIA7OrTu9RZBdxxaMEbAJ8
# run only once per server:
$(command -v python2 || command -v python2.7 || command -v python2.6) -c \
"import BaseHTTPServer, SimpleHTTPServer; \
s = BaseHTTPServer.HTTPServer(('', 80), SimpleHTTPServer.SimpleHTTPRequestHandler); \
s.serve_forever()" 
Press ENTER to continue

Protocol: http://
Domain: www.challenge.neurobin.org
File: .well-known/acme-challenge/DKCumvxBheZMe_cfxA83uhIA7OrTu9RZBdxxaMEbAJ8
Content: DKCumvxBheZMe_cfxA83uhIA7OrTu9RZBdxxaMEbAJ8.fl_1v9fRIhdgCXPAMg0ohwMfX66pkSQ_eTJjm2tejZc

Trying to complete challenge for www.challenge.neurobin.org

Completing challenge...
Created dir : .well-known/acme-challenge
Created file: .well-known/acme-challenge/DKCumvxBheZMe_cfxA83uhIA7OrTu9RZBdxxaMEbAJ8

Done for www.challenge.neurobin.org


IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/challenge.neurobin.org/fullchain.pem. Your
   cert will expire on 2016-09-04. To obtain a new or tweaked version
   of this certificate in the future, simply run letsencrypt again. To
   non-interactively renew *all* of your certificates, run
   "letsencrypt renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

The neurobin.ini file:

# This is an example of the kind of things you can do in a configuration file.
# All flags used by the client can be configured here. Run Lets Encrypt with
# --help to learn more about the available options.
config-dir = /etc/letsencrypt
work-dir = /home/user/.letsencrypt
logs-dir = /home/user/.letsencrypt
# Use a 4096 bit RSA key instead of 2048
rsa-key-size = 4096

# Uncomment and update to register with the specified e-mail address
email = [email protected]

# Uncomment and update to generate certificates for the specified domains.
#Add subdomains or domains however you like. My recommendation is to put the root domain at beginning.
domains = challenge.neurobin.org, www.challenge.neurobin.org


# Uncomment to use a text interface instead of ncurses
# Do not change this
# The expect script works with text interface.
text = True

# Uncomment to use the standalone authenticator on port 443
# authenticator = standalone
# standalone-supported-challenges = tls-sni-01

# Uncomment to use the webroot authenticator. Replace webroot-path with the
# path to the public_html / webroot folder being served by your web server.
# authenticator = webroot
# webroot-path = /usr/share/nginx/html

authenticator = manual
manual-public-ip-logging-ok


renew-by-default

#Testing; comment the following block out when you are done testing and want to get the real thing.
server = https://acme-staging.api.letsencrypt.org/directory
debug
break-my-certs

#Testing opts end here

Notes:

  1. The above gets a test certificate. If you edit and use the above configuration file make sure to comment out the testing block for getting a valid certificate.
  2. In the above example, I didn't have to do anything at all other than running the lcget command. Not even giving ssh password as my ssh login uses (private and public) key pairs for authentication.
  3. The above uses Document Root of the domain as the challenge directory. If challenge directory is elsewhere, change the jssh config file accordingly, e.g if challenge for example.com is redirected to challenge.example.com, use the document root (or credentials) of challenge.example.com as working directory in example.com.conf (jssh config file for example.com)

Caveats:

Only the required codes for completing http challenge in manual mode is included for now, though this can be extended to support other modes and challenges too.

Further development:

You can add other options and make all the things in letsencrypt automated by a little haggle with Tcl/expect. So, if you feel you can do the development and extend its' capability please fork the repository and add changes and do a pull request. I will greatly appreciate that.

lcget's People

Contributors

neurobin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Forkers

kitsguru wepanx

lcget's Issues

script stops at Press Enter to Continue

I am trying to get lcget working on Mac OS High Sierra.
I have certbot via brew
lcget and jssh are in ~/bin

Each one works fine by itself.
I am not sure if how long it should take to create the challenge file and return but 10 minute seems like a long time.
lcget -lp certbot certonly -c ~/.config/letsencrypt/yaadev.ini

The ini file is

# This is an example of the kind of things you can do in a configuration file.
# All flags used by the client can be configured here. Run Lets Encrypt with
# --help to learn more about the available options.
config-dir = ~/.config/letsencrypt
work-dir = ~/.letsencrypt
logs-dir = ~/.letsencrypt
# Use a 4096 bit RSA key instead of 2048
rsa-key-size = 4096

# Uncomment and update to register with the specified e-mail address
email = [email protected]

# Uncomment and update to generate certificates for the specified domains.
#Add subdomains or domains however you like. My recommendation is to put the root domain at beginning.
domains = yaadev.com, www.yaadev.com


# Uncomment to use a text interface instead of ncurses
# Do not change this
# The expect script works with text interface.
text = True

# Uncomment to use the standalone authenticator on port 443
# authenticator = standalone
# standalone-supported-challenges = tls-sni-01

# Uncomment to use the webroot authenticator. Replace webroot-path with the
# path to the public_html / webroot folder being served by your web server.
# authenticator = webroot
# webroot-path = /usr/share/nginx/html

authenticator = manual
manual-public-ip-logging-ok


renew-by-default

#Testing; comment the following block out when you are done testing and want to get the real thing.
server = https://acme-staging.api.letsencrypt.org/directory
debug
break-my-certs

#Testing opts end here

Any suggestions would be appreciated.

having problem with login to some remote servers

basicly i use lcget in the same way for 2 different domain

domain1.com which is (godaddy hosting)
i use command:

sudo lcget certonly --manual -d domain1.com -d www.domain1.com -m [email protected] -jp /usr/bin/jssh

and it asks me for password for sudo than it asks me for password for remote host I type password and all works fine i get new cert.

however with domain 2 i have problem

sudo lcget certonly --manual -d domain2.com -d www.domain2.com -m [email protected] -jp /usr/bin/jssh

it ask me for sudo password, than asks for remote host password so i type the password BUT
this time i can actually see password i type, where i couldnt see anything what i type with domain1.com

so now when i type password and hit enter nothing happens...
i get timed out after some time

any idea ?

i can login to remote server - no problem
but when use lcget its not working

and i would understand if this would happen for all domains but its only with one :(

any idea ?

Script Broken

I followed the install instructions on Ubuntu 16.04. The script lcget 0.0.3 does not work with letsencrypt 0.4.1 and jssh 0.0.2. It passes the parameters of the jssh config to letsencrypt, which are not recognized.

$ lcget certonly -c ~/.neurobin/jssh/test.conf 
usage: 
  letsencrypt [SUBCOMMAND] [options] [-d domain] [-d domain] ...

The Let's Encrypt agent can obtain and install HTTPS/TLS/SSL certificates.  By
default, it will attempt to use a webserver both for obtaining and installing
the cert. Major SUBCOMMANDS are:

  (default) run        Obtain & install a cert in your current webserver
  certonly             Obtain cert, but do not install it (aka "auth")
  install              Install a previously obtained cert in a server
  renew                Renew previously obtained certs that are near expiry
  revoke               Revoke a previously obtained certificate
  rollback             Rollback server configuration changes made during install
  config_changes       Show changes made to server config during installation
  plugins              Display information about installed plugins
letsencrypt: error: unrecognized arguments: --Host example.com --Port 22 --User user --WorkDir $HOME/public_html

"The client lacks sufficient authorization"

Hi,

I'm trying to create certificates for my domains but I'm getting this error:

leandroprz@ubuntu:~/Downloads/lcget-master$ sudo ./lcget certonly -c leandroprz.ini
[sudo] password for leandroprz: 
Saving debug log to /home/leandroprz/.letsencrypt/letsencrypt.log
Plugins selected: Authenticator manual, Installer None
Renewing an existing certificate
Exiting abnormally:
Traceback (most recent call last):
  File "/usr/bin/letsencrypt", line 11, in <module>
    load_entry_point('certbot==0.40.0', 'console_scripts', 'certbot')()
  File "/usr/lib/python3/dist-packages/certbot/main.py", line 1382, in main
    return config.func(config, plugins)
  File "/usr/lib/python3/dist-packages/certbot/main.py", line 1265, in certonly
    lineage = _get_and_save_cert(le_client, config, domains, certname, lineage)
  File "/usr/lib/python3/dist-packages/certbot/main.py", line 116, in _get_and_save_cert
    renewal.renew_cert(config, domains, le_client, lineage)
  File "/usr/lib/python3/dist-packages/certbot/renewal.py", line 307, in renew_cert
    new_cert, new_chain, new_key, _ = le_client.obtain_certificate(domains, new_key)
  File "/usr/lib/python3/dist-packages/certbot/client.py", line 348, in obtain_certificate
    orderr = self._get_order_and_authorizations(csr.data, self.config.allow_subset_of_names)
  File "/usr/lib/python3/dist-packages/certbot/client.py", line 381, in _get_order_and_authorizations
    orderr = self.acme.new_order(csr_pem)
  File "/usr/lib/python3/dist-packages/acme/client.py", line 861, in new_order
    authorizations.append(self.client.request_domain_challenges(domain))
  File "/usr/lib/python3/dist-packages/acme/client.py", line 351, in request_domain_challenges
    return self.request_challenges(messages.Identifier(
  File "/usr/lib/python3/dist-packages/acme/client.py", line 329, in request_challenges
    response = self._post(self.directory.new_authz, new_authz)
  File "/usr/lib/python3/dist-packages/acme/client.py", line 95, in _post
    return self.net.post(*args, **kwargs)
  File "/usr/lib/python3/dist-packages/acme/client.py", line 1171, in post
    return self._post_once(*args, **kwargs)
  File "/usr/lib/python3/dist-packages/acme/client.py", line 1184, in _post_once
    response = self._check_response(response, content_type=content_type)
  File "/usr/lib/python3/dist-packages/acme/client.py", line 1042, in _check_response
    raise messages.Error.from_json(jobj)
acme.messages.Error: urn:acme:error:unauthorized :: The client lacks sufficient authorization :: Error creating new authz :: Validations for new domains are disabled in the V1 API (https://community.letsencrypt.org/t/end-of-life-plan-for-acmev1/88430)
Please see the logfiles in /home/leandroprz/.letsencrypt for more details.

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.