From d9778c52bb81490596591a9763c9654de4ecf39a Mon Sep 17 00:00:00 2001 From: Thomas Lange Date: Thu, 22 Dec 2016 03:45:07 +0100 Subject: Parsing command-line arguments with the getopts shell builtin. --- painless-le.sh | 25 ++++++++++++++++++++++--- readme.md | 12 ++++++------ 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/painless-le.sh b/painless-le.sh index efd0bc2..160f5a8 100755 --- a/painless-le.sh +++ b/painless-le.sh @@ -13,8 +13,27 @@ # # #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# -[ -z "$1" ] && echo 'Missing argument $1' && exit 1 || ARGUMENT_DIRECTORY="$1" -[ -z "$2" ] && echo 'Missing argument $2' && exit 1 || ARGUMENT_HOSTNAMES="$2" +#=============================================================================== +# Parsing command-line arguments with the getopts shell builtin +#=============================================================================== +while getopts :i:h: opt +do + case $opt in + i) ARGUMENT_DIRECTORY="$OPTARG" ;; + h) ARGUMENT_HOSTNAMES="$OPTARG" ;; + esac +done + +#=============================================================================== +# Checking if all required command-line arguments are provided +#=============================================================================== +[ -z "${ARGUMENT_DIRECTORY}" ] && echo "$0: Missing argument: [-i directory]" >&2 +[ -z "${ARGUMENT_HOSTNAMES}" ] && echo "$0: Missing argument: [-h hostnames]" >&2 + +#=============================================================================== +# Abort execution if required command-line argument is missing +#=============================================================================== +[ -z "${ARGUMENT_DIRECTORY}" ] || [ -z "${ARGUMENT_HOSTNAMES}" ] && exit 1 #=============================================================================== # Define the ACME endpoint address @@ -48,7 +67,7 @@ openssl req -config <(cat "${OPENSSLCONF}" <(printf "[SAN]\nsubjectAltName=DNS:` # Checking if Certificate-Signing-Request (CSR) was successfully created #=============================================================================== if [ $? != 0 ]; then - echo "[ABORTING]: Certificate-Signing-Request (CSR) could not be created!" + echo "$0: Certificate-Signing-Request (CSR) could not be created!" >&2 exit 1 fi diff --git a/readme.md b/readme.md index bb73578..422d363 100644 --- a/readme.md +++ b/readme.md @@ -1,5 +1,5 @@ # PainlessLE: Let's Encrypt Certificate Issuing -Painless issuing a single [X.509 certificate](https://tools.ietf.org/html/rfc5280) for a bunch of hostnames from the **Let's Encrypt** Certification Authority (CA) without having a HTTP server installed (or for those people who do not want to touch their HTTP web directories and place a specific file to accomplish the ACME challenge). PainlessLE assumes that there is already a manually created RSA private key which is used for the Certificate-Signing-Request (CSR) by OpenSSL. The location for the RSA private key is defined within the `"CONFIDENTIAL"` variable and the path should exist with the correct UNIX file permissions. +Painless issuing a single [X.509 certificate](https://tools.ietf.org/html/rfc5280) for a bunch of hostnames from the **Let's Encrypt** Certification Authority (CA) without having an HTTP server installed (or for those people who do not want to touch their HTTP web directories and place a specific file to accomplish the ACME challenge). PainlessLE assumes that there is already a manually created RSA private key which is used for the Certificate-Signing-Request (CSR) by OpenSSL. The location for the RSA private key is defined within the `"CONFIDENTIAL"` variable and the path should exist with the correct UNIX file permissions. ## Requirements The [Certbot client](https://certbot.eff.org/) must be installed on your machine because PainlessLE uses this piece of software to communicate over the [ACME protocol](https://tools.ietf.org/html/draft-ietf-acme-acme-01) with the ACME endpoint of Let's Encrypt and runs the ACME challenge. There are no known further requirements for the usage of PainlessLE on Debian GNU/Linux at this time. @@ -8,19 +8,19 @@ The [Certbot client](https://certbot.eff.org/) must be installed on your machine Change the `LETSENCRYPT_ENDPOINT` to the address of the ACME staging API for testing purposes. You also can define a command within `LETSENCRYPT_COMMAND_BEFORE` to shutting down a running webserver to release the HTTP(S) port for the standalone webserver before certbot runs the ACME challenge. You can restart your webserver after the ACME challenge is completed within `LETSENCRYPT_COMMAND_AFTER`. ## Arguments -1. `ARGUMENT_DIRECTORY` contains a string with the directory path where the certificates should be installed. This directory should already contain a manually created RSA private key for the Certificate-Signing-Request (CSR). It's always a good idea to handle the RSA private keys manually because you may use [HTTP Public-Key-Pinning (HPKP)](https://tools.ietf.org/html/rfc7469) so that you must ensure, that the RSA private key does not change. +1. `ARGUMENT_DIRECTORY [-i]` contains a string with the directory path where the certificates should be installed. This directory should already contain a manually created RSA private key for the Certificate-Signing-Request (CSR). It's always a good idea to handle the RSA private keys manually because you may use [HTTP Public-Key-Pinning (HPKP)](https://tools.ietf.org/html/rfc7469) so that you must ensure, that the RSA private key does not change. -2. `ARGUMENT_HOSTNAMES` contains a colon (`:`) separated string with the DNS hostnames to include within the certificate. The string must be formatted as follows, without containing colons anywhere except **between** the hostnames: `example.org:blog.example.org:shop.example.org` +2. `ARGUMENT_HOSTNAMES [-h]` contains a colon (`:`) separated string with the DNS hostnames to include within the certificate. The string must be formatted as follows, without containing colons anywhere except **between** the hostnames: `example.org:blog.example.org:shop.example.org` ## Example -Lets assume that you want to get a single X.509 certificate from the Let's Encrypt CA which includes three hostnames of your domain `example.org` (main domain, blog subdomain and shop subdomain). You already have a RSA private key with the correct UNIX file permissions stored within the following example directory with the name `confidential.pem`: +Lets assume that you want to get a single X.509 certificate from the Let's Encrypt CA which includes three hostnames of your domain `example.org` (main domain, blog subdomain and shop subdomain). You already have an RSA private key with the correct UNIX file permissions stored within the following example directory with the name `confidential.pem`: /etc/painless-le/example.org/ └── [-rw-r----- user group ] confidential.pem -The next step is to execute `painless-le.sh` and providing the only two command-line arguments which are described above. In this example, the complete command-line string with the desired install directory `/etc/painless-le/example.org` and the desired hostnames `example.org`, `blog.example.org` and `shop.example.org` looks as follows: +The next step is to execute `painless-le.sh` and providing the `-i` and `-h` arguments which are described above. In this example, the complete command-line string with the desired install directory `/etc/painless-le/example.org` and the desired hostnames `example.org`, `blog.example.org` and `shop.example.org` looks as follows: - painless-le.sh /etc/painless-le/example.org/ "example.org:blog.example.org:shop.example.org" + painless-le.sh -i /etc/painless-le/example.org/ -h "example.org:blog.example.org:shop.example.org" The certbot client will now contacting the ACME challenge servers and runs a temporary standalone webserver on your machine to accomplish the ACME challenge. If all works fine, you have nothing to intervene. After the command was successfully executed, you will see your certificates within your desired install directory (the certificates inherit the permissions of the `confidential.pem` file) and you're done: -- cgit v1.2.3