uacme - ACMEv2 client written in plain C with minimal
dependencies
uacme [-a|--acme-url URL]
[-b|--bits BITS] [-c|--confdir
DIR] [-d|--days DAYS] [-e|--eab
KEYID:KEY] [-f|--force] [-h|--hook
PROGRAM] [-l|--alternate N | FP]
[-m|--must-staple] [-n|--never-create]
[-o|--no-ocsp] [-r|--reason CODE]
[-s|--staging] [-t|--type RSA|EC]
[-v|--verbose ...] [-V|--version]
[-y|--yes] [-?|--help] new [EMAIL]
| update [EMAIL] | deactivate | newkey |
issue IDENTIFIER [ALTNAME ...]] | issue
CSRFILE | revoke CERTFILE [CERTKEYFILE]
uacme is a client for the ACMEv2 protocol described in
RFC8555, written in plain C with minimal dependencies (libcurl and one of
GnuTLS, OpenSSL or mbedTLS). The ACMEv2 protocol allows a Certificate
Authority (https://letsencrypt.org is a popular one) and an applicant to
automate the process of verification and certificate issuance. The protocol
also provides facilities for other certificate management functions, such as
certificate revocation. For more information see
https://tools.ietf.org/html/rfc8555
-a, --acme-url URL
ACMEv2 server directory object
URL. If not
specified
uacme uses one of the following:
https://acme-v02.api.letsencrypt.org/directory
production URL
https://acme-staging-v02.api.letsencrypt.org/directory
staging URL (see -s, --staging below)
-b, --bits BITS
key bit length (default 2048 for RSA, 256 for EC). Only
applies to newly generated keys. RSA key length must be a multiple of 8
between 2048 and 8192. EC key length must be either 256
(NID_X9_62_prime256v1 curve) or 384 (NID_secp384r1 curve).
-c, --confdir CONFDIR
Use configuration directory
CONFDIR (default
/etc/ssl/uacme). The structure is as follows (multiple
IDENTIFIERs allowed)
CONFDIR/private/key.pem
ACME account private key
CONFDIR/private/IDENTIFIER/key.pem
certificate key for IDENTIFIER
CONFDIR/IDENTIFIER/cert.pem
certificate for IDENTIFIER
-d, --days DAYS
Do not reissue certificates that are still valid for
longer than DAYS (default 30). See also -o, --no-ocsp.
-e, --eab KEYID:KEY
Specify RFC8555 External Account Binding credentials
according to https://tools.ietf.org/html/rfc8555#section-7.3.4, in order to
associate a new ACME account with an existing account in a non-ACME system
such as a CA customer database. KEYID must be an ASCII string.
KEY must be base64url-encoded.
-f, --force
Force certificate reissuance regardless of expiration
date.
-h, --hook PROGRAM
Challenge hook program. If not specified
uacme
interacts with the user for every ACME challenge, printing information about
the challenge type, token and authorization on stderr. If specified
uacme executes
PROGRAM (a binary, a shell script or any file
that can be executed by the operating system) for every challenge with the
following 5 string arguments:
METHOD
one of
begin,
done or
failed.
begin
is called at the beginning of the challenge.
PROGRAM must return 0 to accept it. Any other return code declines the
challenge. Neither done nor failed method calls are made for
declined challenges.
done
is called upon successful completion of an accepted
challenge.
failed
is called upon failure of an accepted challenge.
TYPE
challenge type (dns-01, http-01 or
tls-alpn-01)
IDENT
The identifier the challenge refers to
TOKEN
The challenge token
AUTH
The key authorization (for dns-01 and
tls-alpn-01 already converted to the base64url-encoded SHA256 digest
format)
-l, --alternate N | FP
According to
https://tools.ietf.org/html/rfc8555#section-7.4.2 the server MAY provide one
or more additional certificate download URLs, each pointing to alternative
certificate chains starting with the same end-entity certificate. This option
allows selecting one such chain in one of two ways. A positive integer
N makes uacme select the Nth alternative chain in the order
presented by the server. A colon (:) separated list of two or more
2-digit hexadecimal numbers FP makes uacme select the first
alternative chain containing a certificate whose SHA256 fingerprint begins
with FP. In both cases uacme falls back to the main certificate
URL if it cannot match an alternative chain or the download thereof
fails.
-m, --must-staple
Request certificates with the RFC7633 Certificate Status
Request TLS Feature Extension, informally also known as "OCSP
Must-Staple". This option is ignored when using an externally supplied
Certificate Signing Request file (see USAGE below).
-n, --never-create
By default uacme creates directories/keys if they
do not exist. When this option is specified uacme never does so and
instead exits with an error if anything required is missing.
-o, --no-ocsp
When this flag is not specified and the
certificate has an Authority Information Access extension with an OCSP server
location according to https://tools.ietf.org/html/rfc5280#section-4.2.2.1
uacme makes an OCSP request to the server; if the certificate is
reported as revoked uacme forces reissuance regardless of the
expiration date. See also -d, --days.
-r, --reason CODE
Use CODE (default 0) as reason code in revocation
requests. A list of values is at
https://tools.ietf.org/html/rfc5280#section-5.3.1.
-s, --staging
Use Let’s Encrypt staging URL for testing. This
only works if -a, --acme-url is NOT specified.
-t, --type=RSA | EC
Key type, either RSA or EC. Only applies to newly
generated keys. The bit length can be specified with -b, --bits.
-v, --verbose
By default uacme only produces output upon errors
or when user interaction is required. When this option is specified
uacme prints information about what is going on on stderr. This option
can be specified more than once to increase verbosity.
-V, --version
Print program version on stderr and exit.
-y, --yes
Autoaccept ACME server terms (if any) upon new account
creation.
-?, --help
Print a brief usage text on stderr and exit.
uacme [OPTIONS ...] new [EMAIL]
Create a new ACME account with optional EMAIL
contact. If the account private key does not exist at
CONFDIR/private/key.pem a new key is generated unless -n,
--never-create is specified. A valid account must be created before
any other operation can succeed (with the exception of certificate revocation
requests signed by the certificate private key). Any certificate issued by the
ACME server is associated with a single account. An account can be associated
with multiple certificates, subject of course to the rate limits imposed by
the ACME server.
uacme [OPTIONS ...] update [EMAIL]
Update the EMAIL associated with the ACME account
corresponding to the account private key. If EMAIL is not specified the
account contact email is removed.
uacme [OPTIONS ...] deactivate
Deactivate the ACME account corresponding to the account
private key. WARNING this action is irreversible. Users may wish to do
this when the account key is compromised or decommissioned. A deactivated
account can no longer request certificate issuances and revocations or access
resources related to the account.
uacme [OPTIONS ...] newkey
Change the ACME account private key. If the new account
private key does not exist at CONFDIR/private/newkey.pem it is
generated unless -n, --never-create is specified. The new key is then
submitted to the server and if the operation succeeds the old key is
hardlinked to CONFDIR/private/key-TIMESTAMP.pem before renaming
CONFDIR/private/newkey.pem to CONFDIR/private/key.pem.
uacme [OPTIONS ...] issue IDENTIFIER
[ALTNAME ...]
Issue a certificate for IDENTIFIER with zero or
more ALTNAMEs. If a certificate is already available at
CONFDIR/IDENTIFIER/cert.pem for the specified IDENTIFIER and
ALTNAMEs and is still valid for longer than DAYS no action is
taken unless -f, --force is specified or -o, --no-ocsp is
not specified and the certificate is reported as revoked by the OCSP
server. The new certificate is saved to CONFDIR/IDENTIFIER/cert.pem. If
the certificate file already exists it is hardlinked to
CONFDIR/IDENTIFIER/cert-TIMESTAMP.pem before overwriting. The private
key for the certificate is loaded from
CONFDIR/private/IDENTIFIER/key.pem. If no such file exists, a new key
is generated unless -n, --never-create is specified. Wildcard
IDENTIFIERs or ALTNAMEs are dealt with correctly, as long as the
ACME server supports them; note that any such wildcards are automatically
removed from the configuration subdirectory name: for example a certificate
for *.test.com is saved to CONFDIR/test.com/cert.pem. IP address
IDENTIFIERs and ALTNAMEs are also supported according to
https://tools.ietf.org/html/rfc8738#section-3
uacme [OPTIONS ...] issue CSRFILE
Issue a certificate based on a RFC2986 Certificate
Signing Request contained in CSRFILE, which must be in PEM format. In
this mode of issuance uacme neither needs nor generates the certificate
private key, but it is of course the responsibility of the user to ensure that
the CSR is constructed and signed appropriately. If a certificate file
CSRBASE-cert.pem (where CSRBASE is obtained by stripping the
extension, if any, from CSRFILE) is already available in the same
directory containing CSRFILE, and is still valid for longer than
DAYS no action is taken unless -f, --force is specified or
-o, --no-ocsp is not specified and the certificate is reported
as revoked by the OCSP server. If the certificate file already exists it is
hardlinked to BASENAME-cert-TIMESTAMP.pem before overwriting. Wildcard
identifiers in the CSR are dealt with correctly, as long as the ACME server
supports them. IP addresses are also supported according to
https://tools.ietf.org/html/rfc8738#section-3
uacme [OPTIONS ...] revoke CERTFILE
[CERTKEYFILE]
Revoke the certificate stored in CERTFILE. The
revocation request is signed with the private key of either the certificate,
when CERTKEYFILE is specified; or the ACME account associated with the
certificate, when only CERTFILE is specified. In the first instance the
account key and the configuration directory are not required. If successful
CERTFILE is renamed to revoked-TIMESTAMP.pem. The reason code in
the revocation request defaults to 0 but it can be specified by the user with
-r, --reason.
0
Success
1
Certificate not reissued because it is still
current
2
Failure (syntax or usage error; configuration error;
processing failure; unexpected error).
The uacme.sh hook script included in the distribution can
be used to automate the certificate issuance with http-01 challenges,
provided a web server for the domain being validated runs on the same
machine, with webroot at /var/www
#!/bin/sh
CHALLENGE_PATH=/var/www/.well-known/acme-challenge
ARGS=5
E_BADARGS=85
if test $# -ne "$ARGS"
then
echo "Usage: $(basename "$0") method type ident token auth" 1>&2
exit $E_BADARGS
fi
METHOD=$1
TYPE=$2
IDENT=$3
TOKEN=$4
AUTH=$5
case "$METHOD" in
"begin")
case "$TYPE" in
http-01)
echo -n "${AUTH}" > "${CHALLENGE_PATH}/${TOKEN}"
exit $?
;;
*)
exit 1
;;
esac
;;
"done"|"failed")
case "$TYPE" in
http-01)
rm "${CHALLENGE_PATH}/${TOKEN}"
exit $?
;;
*)
exit 1
;;
esac
;;
*)
echo "$0: invalid method" 1>&2
exit 1
esac
If you believe you have found a bug, please create a new issue at
https://github.com/ndilieto/uacme/issues with any applicable
information.
uacme was written by Nicola Di Lieto
Copyright © 2019-2023 Nicola Di Lieto
<nicola.dilieto@gmail.com>
This file is part of uacme.
uacme is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
uacme is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see http://www.gnu.org/licenses/.