8000 GitHub - f5devcentral/kojot-acme: An ACMEv2 client utility function for integration and advanced features on the F5 BIG-IP
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

f5devcentral/kojot-acme

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

72 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

KOJOT-ACME

An ACMEv2 client utility function for integration and advanced features on the F5 BIG-IP

Major Updates May 09, 2025 - See updates section at bottom for changes

This project defines a set of utility functions for the Dehydrated ACMEv2 client, supporting direct integration with F5 BIG-IP, and including additional advanced features:

  • Simple installation, configuration, and scheduling
  • Supports renewal with existing private keys to enable certificate automation in HSM/FIPS environments
  • Supports per-domain configurations, to multiple ACME providers
  • Supports both the HTTP-01 and DNS-01 validation mechanisms
  • Supports wildcard certificates for DNS-01 and EAB providers
  • Supports OCSP and periodic revocation testing
  • Supports External Account Binding (EAB)
  • Supports SAN certificate renewal
  • Supports explicit proxy egress
  • Supports granular scheduling
  • Supports SMTP Reporting
  • Supports high availability
  • Supports debug logging

Why Kojot? Often pronounce "koyot", this is a word for "coyote" that has origins in Czech, Hungarian, Polish, and Serbo-Croatian languages. But most important, a famous coyote you may know, Wile E. Coyote, was a great consumer of ACME services, so the name checks out. ;)



${\LARGE{\textnormal{\textbf{\color{blue}Installation\ and\ Configuration}}}}$

Installation to the BIG-IP is simple. The only constraint is that the certificate objects installed on the BIG-IP must be named after the certificate subject name (unless the --alias flag is used). For example, if the certificate subject name is www.foo.com, then the installed certificate and key must also be named www.foo.com. Certificate automation is predicated on this naming construct. To install the utility functions to the BIG-IP:


  • ${\normalsize{\textbf{\color{red}Step\ 1}}}$ (Install): SSH to the BIG-IP shell and run the following command. This will install all required components to the /shared/acme folder on the BIG-IP. In an HA environment, perform this action on both BIG-IP instances.

    curl -s https://raw.githubusercontent.com/f5devcentral/kojot-acme/main/install.sh | bash

    Optionally to include a proxy server to access the installation, add the -x (proxy) and --proxy argument (note the double set of double-dashes in Bash argument). The -x is an argument to the command line to use a proxy to fetch the install.sh script, and the --proxy argument is passed to the script itself.

    curl -ks -x 172.16.1.144:3128 https://raw.githubusercontent.com/f5devcentral/kojot-acme/main/install.sh | bash -s -- --proxy 172.16.1.144:3128
  • ${\normalsize{\textbf{\color{red}Step\ 2}}}$ (Certificates Configuration): Update the new dg_acme_config data group and add entries for each managed domain (certificate subject). You must minimally include the subject/domain (key) and a corresponding --ca value. In an HA environment, this data group is synced between the peers. See the Certificates Configuration Options section below for additional details. Examples:

    www.foo.com := --ca https://acme-v02.api.letsencrypt.org/directory
    www.bar.com := --ca https://acme.zerossl.com/v2/DV90 --config /shared/acme/config_www_example_com
    www.baz.com := --ca https://acme.locallab.com:9000/directory -a rsa
  • ${\normalsize{\textbf{\color{red}Step\ 3}}}$ (Provider Configuration): Adjust the default provider configuration config file in the /shared/acme folder as needed for your specific provider. In most cases you will only need a single provider config file, but this utility allows for per-provider configurations. For example, you can define separate config files when EAB is needed for some provider(s), but not others. In an HA environment, the utility ensures these config files are available to the peer. See the ACME Provider Configuration Options section below for additional details.

  • ${\normalsize{\textbf{\color{red}Step\ 4}}}$ (HTTP Virtual Servers): For HTTP-01 validation, minimally ensure that an HTTP virtual server exists on the BIG-IP that matches the DNS resolution of each target domain (certificate subject). As a function of the ACMEv2 http-01 challenge process, the ACME server will attempt to contact the requested domain IP address on port 80 (HTTP). Attach the acme_handler_rule iRule to each HTTP virtual server.

  • ${\normalsize{\textbf{\color{red}Step\ 5}}}$ (Initial Fetch): Initiate an ACMEv2 fetch. This command will loop through the dg_acme_config certificates configuration data group and perform required ACMEv2 certificate renewal operations for each configured domain. By default, if no certificate and key exists for a domain, ACMEv2 renewal will generate a new certificate and key. If a private key exists, a CSR is generated from the existing key to renew the certificate only. This it to support HSM/FIPS environments, but can be disabled to always generate a new private key. See the Utility Command Line Options and ACME Povider Configuration Options sections below for additional details.

    cd /shared/acme
    ./f5acmehandler.sh --verbose
  • ${\normalsize{\textbf{\color{red}Step\ 6}}}$ (Schedule): Once all configuration updates have been made and the utility function is working as desired, define scheduling to automate the process. By default, each domain (certificate) is checked against the defined threshold (default: 30 days) and only continues if the threshold is exceeded. In an HA environment, perform this action on both BIG-IP instances. See the Scheduling section below for additional details. For example, to set a weekly schedule, to initiate an update check every Monday at 4am:

    cd /shared/acme
    ./f5acmehandler.sh --schedule "00 04 * * 1"
    
  • ${\normalsize{\textbf{\color{red}Step\ 7}}}$ (Client SSL Profile): The f5acmehandler.sh utility maintains the freshness of the certificates (and private keys) installed on the BIG-IP. Ultimately, these certificates and keys will then need to be applied to SSL profiles, and the SSL profiles applied to application virtual servers. Creating the SSL profiles and virtual servers is outside the scope of this utility, but optionally you can set the CREATEPROFILE option in the client config file to 'true' to have the utility create a client SSL profile if missing, and attach the certificate and key to that profile.



${\LARGE{\textnormal{\textbf{\color{blue}Configuration\ Details}}}}$

The ACMEv2 configuration is broken into two components --> the provider configuration that describes the ACMEv2 server (including validation mode, authentication, and revocation settings), and the certificates configuration that describes each managed certificate. The provider configuration is stored in config files in the /shared/acme working folder. A default config file is included, but others can be created if multiple ACMEv2 providers are needed and require different settings. The certificates configuration is stored in the dg_acme_config data group and must minimally include the provider URL, but may also point to a specific config file. If the config file is not specified, the default will be used.

Configuration options for this utility are found in the following locations:

Certificates Configuration Options define the set of domains that are to be handled, the (CA) directory URL of the designated ACMEv2 provider, and any optional unique configuration settings. This list is maintained in a BIG-IP data group (dg_acme_config)

Certificate configuration options are specified in the dg_acme_config data group for each domain (certificate subject). Each entry in the data group must include a String: the domain name (ex. www.foo.com), and a Value consisting of a number of configuration options:


Value Options Description Examples Required
--ca Defines the ACME provider URL --ca https://acme-v02.api.letsencrypt.org/directory (Let's Encrypt)
--ca https://acme-staging-v02.api.letsencrypt.org/directory (LE Staging)
--ca https://acme.zerossl.com/v2/DV90 (ZeroSSL)
--ca https://api.buypass.com/acme/directory (Buypass)
--ca https://api.test4.buypass.no/acme/directory (Buypass Test)
$${\normalsize{\textbf{\color{red}Yes}}}$$
--config Defines an alternate config file (default: /shared/acme/config) --config /shared/acme/config_www_foo_com $${\normalsize{\textbf{\color{black}No}}}$$
-a Overrides the required leaf certificate algorithm specified in the config file. (default: rsa) -a rsa
-a prime256v1
-a secp384r1
$${\normalsize{\textbf{\color{black}No}}}$$
-d Includes additional DNS subject-alternative-name (SAN) values in the certificate. This option can be used multiple times. -d foo.f5labs.com -d bar.f5labs.com $${\normalsize{\textbf{\color{black}No}}}$$
--alias Allows for wildcard certificate requests on dns-01 and EAB (authenticated http-01) validations. The --alias flag moves the name of the object to the alias context. --alias wildcard_f5labs_com $${\normalsize{\textbf{\color{black}No}}}$$

Examples:

www.foo.com := --ca https://acme-v02.api.letsencrypt.org/directory
www.bar.com := --ca https://acme.zerossl.com/v2/DV90 --config /shared/acme/config_www_example_com
www.baz.com := --ca https://acme.locallab.com:9000/directory -a rsa
www.baz.com := --ca https://acme.locallab.com:9000/directory -a rsa -d foo.baz.com -d bar.baz.com
*.baz.com := --ca https://acme.locallab.com:9000/directory --alias wildcard_baz_com

Note the following:

  • In using the -d option to include additional SAN values, ACME providers will typically also require validation of these hostnames as well. Ensure that DNS for each of these also resolve to an IP address on the BIG-IP that can answer the ACME challenge.
  • The -d option only applies to new certificates. Once a certificate has been created, the ACME renewal will retain the SAN values in the existing certificate.
  • The --alias option supports wilcard certificates using either dns-01 validation method, or EAB (pre-authenticated) http-01. In general practice and per RFCs, wildcard certificates are not supported for http-01 validation unless EAB pre-authentication is used.

Providers Configuration Options define the per-provider ACMEv2 attributes. These settings are maintained in a config text file stored in the "/shared/acme" folder on the BIG-IP.

Within the /shared/acme/config file are a number of additional client attributes. This utility allows for per-domain configurations, for example, when EAB is needed for some providers, but not others. Adjust the following atttributes as required for your ACME provider(s). All additional config files must start with "config_" (ex. config_www_foo_com).

Config Options Description
CURL_OPTS Defines specific attributes used in the underlying Curl functions. This could minimally include: --http1.1 = use HTTP/1.1 -k = ignore certificate errors -x [proxy-url:port] = use an explicit proxy
KEY_ALGO Defines the required leaf certificate algorithm (rsa, prime256v1, or secp384r1)
KEYSIZE Defines the required leaf certificate key size (default: 4096)
CONTACT_EMAIL Defines the registration account name and must be unique per provider requirements
OCSP_MUST_STAPLE Option to add CSR-flag indicating OCSP stapling to be mandatory (default: no)
THRESHOLD Threshold in days when a certificate must be renewed (default: 30 days)
ACME_METHOD Defines the ACMEv2 validation method to use (http-01, or dns-01) (default: http-01)
DNS_2_PHASE When using dns-01 validation, enabled manual 2 phase validation (create DNS entry manually, clean DNS entry manually)
DNS_DELAY When using dns-01 validation, defines the delay between deploying the DNS validation, and cleaning up the DNS entry (allows additional time for slow changes)
DNSAPI When using dns-01 validation, defines the name of the validation script in the /shared/acme/dnsapi folder that will perform deploy and clean functions. The DNS provider will typically have additional variables that must be created (i.e., JWT token, user:pass, etc.)
FORCE_SYNC Option to force HA sync on certificate updates. When disabled, change data is stored to iFile object and requires an auto sync to ensure consistency. When this option is enabled, an HA sync is triggered when there is an update to any of the certificates. (default: false)
DEVICE_GROUP When FORCE_SYNC is true, you must also specify the BIG-IP Device Group name.
ALWAYS_GENERATE_KEY Set to true to always generate a private key. Otherwise a CSR is created from an existing key to support HSM/FIPS environments (default: false)
CHECK_REVOCATION Set to true to attempt OCSP revocation check on existing certificates (default: false)
ERRORLOG Set to true to generate error logging (default: true)
DEBUGLOG Set to true to generate debug logging (default: false)
SYSLOG Set to a Syslog facility and severity level if Syslog is required for log events (ex. local0.err). Leave empty to disable Syslog.
RENEW_DAYS Minimum days before expiration to automatically renew certificate (default: 30)
OCSP_FETCH Fetch OCSP responses (default: no)
OCSP_DAYS OCSP refresh interval (default: 5 days)
EAB_KID/EAB_HMAC_KEY Extended Account Binding (EAB) support
FULLCHAIN Set to true to install the complete certificate chain, or false to only install the leaf certificate (default: true)
ZEROCYLE Set to preferred number of zeroization cycles for shredding created private keys (default: 3 cycles)
CREATEPROFILE Set to true to generate new client SSL profiles with new certs/keys (default: false)
Utility Command Line Options are command line arguments for the f5acmehandler.sh script used in maintenance operations.

The f5acmehandler.sh utility script also supports a set of commandline options for general maintenance usage. When no command options are specified, the utility loops through the dg_acme_config data group and performs required ACMEv2 certificate renewal operations for each configured domain.

Command Line Arguments Description
--force Overrides the default certificate renewal threshold check (default 30 days)
--domain [domain] Performs ACME renewal functions for a single specified domain. Can be combined with --force
Examples:
--domain www.foo.com
--domain www.bar.com --force
--listaccounts Lists the registered ACME provider accounts
--schedule [cron] Takes a cron string and installs this utility as a cron-scheduled process
--testrevocation [domain] Attempt to performs an OCSP revocation check on an existing certificate (domain)
--uninstall Deletes the cron scheduling
--verbose Dump verbose output to stdout
--save Save the local config to HA central store (only for HA)
--help Shows the help information for above command options
Scheduling Options

Scheduling is configured by adding the --scheduling command line argument, followed by a valid cron string. No validation is performed on the cron string input. Please take care to enter a valid string. A few recommended resources for developing cron strings are here:

As a quick example:

Cron String Description
00 04 1 * * Sets a monthly schedule to initiate an update on the 1st day of each month at 04:00
00 04 * * 1 Sets a weekly schedule to initiate an update on Monday of every week at 04:00
00 04 * * * Sets a daily schedule to initiate an update every day at 04:00

where:

1. minutes (0-59)
2. hour (0-23)
3. day of the month (1-31)
4. month (1-12)
5. day of the week (0-6)
./f5acmehandler.sh --schedule "00 04 * * 1"


${\LARGE{\textnormal{\textbf{\color{blue}ACME\ Protocol\ Flow}}}}$

Provided below are detailed descriptions of the control flows. The ACME Utility Architecture section describes the files and folders in use. The ACME Functional Flow on BIG-IP section describes the interaction of f5acmehandler and ACME client processes. The ACME Protocol Flow Reference details the general ACMEv2 protocol flow per RFC8555.

ACME Utility Architecture

The f5acmehandler utility contains the following files and folders in the /shared/acme/ folder on the BIG-IP, plus other BIG-IP objects:

File/Folder/Object Description
/shared/acme/accounts/ The Folder containing registration information (subfolders) for each ACME provider.
/shared/acme/certs/ The Folder for ephemeral certificate information (CSRs, certificates), cleared after each ACME renewal operation.
/shared/acme/config A text file containing the client configuration. Multiple provider-specific config files may be created as needed.
/shared/acme/config_reporting A text file containing the smtp reporting configuration.
/shared/acme/bin/dehydrated The ACME (dehydrated) client script.
/shared/acme/f5acmehandler.sh The ACME client wrapper utility script. This is the script that gets scheduled, and handles all renewal processing.
/shared/acme/f5hook.sh The ACME client hook script. This script is called by the ACME client to handle deploy challenge and clean challenge actions.
/shared/acme/dnsapi The folder containing any scripts used to control dns-01 validation deploy and clean DNS entry functions to a remote DNS provider.
acme_handler_rule BIG-IP iRule applied to port 80/HTTP VIPs for each application, responsible for handling the ACMEv2 challenge.
dg_acme_challenge BIG-IP data group used for ephemeral storage of ACMEv2 challenge tokens.
dg_acme_config BIG-IP data group used to manage the global configuration.
f5_acme_account_state BIG-IP iFile object used in HA environments to maintain account registration state between BIG-IP peers.
f5_acme_config_state BIG-IP iFile object used in HA environments to maintain per-domain configuration state(s) between BIG-IP peers.
f5_acme_dnsapi_state BIG-IP iFile object used in HA environments to maintain DNS api scripts between BIG-IP peers.

The install.sh script is called from a Bash shell on the BIG-IP to:

  • Create the base /shared/acme/ folder on the BIG-IP
  • Create the /shared/acme/bin and /shared/acme/dnsapi folders
  • Download the dehydrated ACME client to /shared/acme/bin
  • Create the dg_acme_config and dg_acme_challenge data groups on the BIG-IP
  • Create the acme_handler_rule iRule on the BIG-IP
  • Create the /var/log/acmehandler log file on the BIG-IP

ACME Functional Flow on BIG-IP

The fundamental functional flow is illustrated here.

ACME Functional Flow on BIG-IP

On f5acmehandler.sh script initiation, the dg_acme_config data group is read, and for each domain entry the following logic is applied:

  • Certificate does not exist: If the domain (certificate) does not exist on the BIG-IP, the ACME client is triggered directly with corresponding configuration settings. During ACME client processing, a separate hook script is called to perform the following actions:

    • deploy_challenge: Take the token filename and token value passed to the client from the ACME server, and insert those as ephemeral entries in an dg_acme_challenge data group. The ACME server will issue an http-01 challenge to a corresponding HTTP virtual server on the BIG-IP. An iRule on the VIP reads from the data group and responds to the ACME challenge with the correct token.

    • clean_challenge: Once the ACME server has completed its http-01 challenge, the ephemeral entry is removed from the data group.

    • deploy_cert: The ACME server will return a new certificate and private key to the ACME client, which is then installed to the BIG-IP.


  • Certificate exists: If the domain (certificate) exists on the BIG-IP, the certificate's expiration date is compared to the defined THRESHOLD value. If the date is less than the THRESHOLD, processing for this domain ends. If the date is greater than or equal to the THRESHOLD, or the --force commandline argument is used with f5acmehandler.sh:

    • Always generate key: If the ALWAYS_GENERATE_KEY setting is true, the ACME client is triggered directly and continues as described above as if the certificate does not exist. In this case, however, the resulting certificate and private key replace an existing certificate/key pair on the BIG-IP.

    • Generate CSR: Otherwise, a CSR is generated from the existing private key and then passed to the ACME client. When using the ACME client with a CSR, only the deploy_challenge and clean_challenge functions are called. The renewed certificate is passed back to f5acmehandler, which then replaces the existing certificate on the BIG-IP.


Note: Any key material created in the BIG-IP file system is zeroized with a minimal of three wipe cycles. This can be changed by adjusting the ZEROCYCLE value in the f5hook.sh script.


ACME Protocol Flow Reference

The ACMEv2 protocol process is expertly described in the following diagram

(source: https://cms.step.plumbing/uploads/acme_how_it_works_88d170c87a.png)

ACME Functional Flow on BIG-IP



${\LARGE{\textnormal{\textbf{\color{blue}Additional\ Configuration\ Options}}}}$

Below are descriptions of additional features and environment options.

Working with External Account Binding (EAB)

External Account Binding (EAB) "pre-authentication" is defined in the ACME RFC. This is used to associate an ACME account with an existing account in a non-ACME system. The CA operating the ACME server provides a MAC Key and Key Identifier, which must be included in the ACME client registration process. The client MAC and Key ID are specified within the /shared/acme/config file. Example:

# Extended Account Binding (EAB) support
EAB_KID=kid-1
EAB_HMAC_KEY=zWNDZM6eQGHWpSRTPal5eIUYFTu7EajVIoguysqZ9wG44nMEtx3MUAsUDkMTQ12W

Working with ACMEv2 DNS-01 validation

A short description of the ACMEv2 dns-01 validation process

The ACMEv2 dns-01 validation method follows RFC8555, whereby:

  • The ACMEv2 client contacts the ACMEv2 server for a certificate request/renewal.
  • The server responds with a token for each validation method it supports (i.e., http-01, dns-01, tls-alpn-01).
  • The client takes the token and creates a DNS TXT record, named _acme-challenge.(hostname) in the target DNS zone, for the target hostname (ex. "_acme-challenge.www.f5labs.com"), with the token as its value.
  • The client then contacts the ACMEv2 server indicating it wants to use dns-01 and is ready for validation. The server will then query Internet DNS looking for this TXT record and the pre-established token value.
  • The client will periodically query the ACMEv2 server for its validation status. When the server has indicated validation success, the client will then send a CSR for the requested certificate. The server then responds with the path to download the new certificate.
  • Once the client has acquired the new certificate, it can now delete the DNS TXT record.

Enabling ACMEv2 dns-01 validation

For the two steps above involving manipulation of the DNS TXT record, the client typically uses a set of API calls -- one to deploy (add) the TXT record, and one to clean (delete) the TXT record. This process can also be done manually in a "2-step" method, but the automated approach is preferred if the DNS service supports it. For the automated process, this project supports a "hook" method that calls a separate "dnsapi" script on each function (deploy, clean). The script must be located in the dnsapi subfolder. A set of working samples are included in the dnsapi repository folder (not copied over in the install), gratuitously borrowed from acme.sh and modified for local use. Unfortunately, no two DNS providers have the same API structure, so a different script is needed for each that you will need. To enable ACMEv2 dns-01 validation, perform the following steps:

  • Create your DNS API script and place it in the dnsapi subfolder. By convention (not required), the name of the script should start with "dns_", include the name of the DNS provider, and end with the ".sh" file extension. Example:

    dns_myprovider.sh
  • Update the ACME_METHOD variable in your provider config file to equal dns-01.

    ACME_METHOD="dns-01"
  • Specify the DNS API script in your provider config file in the DNSAPI variable (without .sh extenstion). You may also include any other variables in the config file that your script will need to communicate with the DNS server (ex. JWT/OAUTH tokens, user/pass). Example:

    DNSAPI=dns_myprovider
    DNSOAUTHID=62e2c497-fdb3-4456-b3fb-28464eaa58d0
    DNSSECRET=6574cV4f92U8Tb476XWY53TVU293WW
  • Optionally update the DNS_DELAY variable in your provider config file if additional time (in seconds) is needed between deploy and clean functions. In some cases a DNS provider will take some extra time to refresh newly added records.

    DNS_DELAY=30
  • Optionally update the DNS_2_PHASE variable in your provider config file if the DNS server must be edited manually (not via API). When set to "true", the script will display the DNS TXT record name and token value, and then pause to allow you to go create the record. When done, hit the Enter key to proceed. The script will then pause again to allow you to go delete the record. Hit Enter a second time to complete the request/renewal.

    DNS_2_PHASE="true"
  • Test that ACMEv2 dns-01 validation is working by issuing a request with verbose logging enabled:

    ./f5acmehandler.sh --force --verbose

Managing the DNS API script

  • Your DNS API script must contain two primary functions, named the same as the filename, followed by "_add" and "_rm". Example:

    If the name of the script is dns_myprovider.sh, then the following functions must exist in the script:

    dns_myprovider_add() { ... code to add a DNS TXT record ... }
    dns_myprovider_rm() { ... code to delete a DNS TXT record ... }
    

    Additional functions may also be created to satisfy various tasks, but only the _add() and _rm() functions are called from the hook process.

  • The _add( ) function will receive two values: the full domain name (ex. _acme-challenge.www.f5labs.com), and the token value (ex. "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"). It must then use the DNS provider's API to create a DNS TXT record for the subdomain portion (_acme-challenge.www) in the corresponding DNS zone (f5labs.com), with the value of the token. Once this function completes, issue a return 0 to alert the hook process to notify the ACMEv2 server that validation can continue. Any errors should return 1.

  • The _rm( ) function will receive two values: the full domain name (ex. _acme-challenge.www.f5labs.com), and the token value (ex. "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"). In most cases, however, only the full domain is needed. It must then use the DNS provider's API to delete the DNS TXT record. Most DNS providers will require you to first query for the record ID, and then delete the record by its ID. Once the function completes, issue a return 0 to alert the hook process to continue. Any errors should return 1. The next step after this will be for the ACMEv2 client to fetch and install the new certificate.

  • Many of the examples also contain a _get_root( ) function that splits the full domain name into separate subdomain and fulldomain variables, and optionally checks that the zone exists. The subdomain is the value added as a TXT record (ex. _acme-challenge.www) for the zone (ex. f5labs.com).

  • Your DNS API script can also take advantage of the built-in logging architecture. To use this, call the f5_process_errors( ) function with a message string. Prepend the following value for different behaviors:

    • "ERROR" - sends messages to the defined error log
    • "DEBUG" - sends messages to the defined debug log (and to stdout if using --verbose on command line)
    • "PANIC" - sends messages to stdout and log file (and syslog if enabled)
    • "VERBOSE" - sends all messages to stdout and to syslog (if syslog is enabled)

    Example:

    f5_process_errors "ERROR dns_myprovider: You have not set the dnsimple oauth token yet"
    f5_process_errors "DEBUG dns_myprovider: Removed record: $item"
    f5_process_errors "PANIC dns_myprovider: Connectivity error to the DNS API"

The below can be used as a starting point template for creating a new DNS API script:

#!/usr/bin/env sh

MY_DNS_API="https://api.myprovider.com/api/v1"

########## Public Functions ##########

# Usage: add  _acme-challenge.www.domain.com   "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_myprovider_add() {
    fulldomain=$1
    txtvalue=$2

    ## sets subdmain variable
    _get_root "$fulldomain"

    ## Add code here to add the DNS TXT record to the zone.
    ## Return 1 on any errors
    ## Example: for zone .f5labs.com
    ##  _acme-challenge.www = TXT "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"

    return 0
}
# Usage: rm  _acme-challenge.www.domain.com   "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_myprovider_rm() {
    fulldomain=$1

    ## sets subdmain variable
    _get_root "$fulldomain"

    ## Add code here to delete the DNS TXT record from the zone.
    ## Return 1 on any errors
    
    return 0
}

########## Private Functions ##########

_get_root() {
    domain=$1

    _subdomain=$(printf "%s" "$domain" | cut -d . -f 1-2)

    return 0
}
Working with wildcard certificates

Wildcard certificate renewal is possible using the --alias option in the certificate configuration data group. As a function of the RFCs, and of the ACMEv2 mechanisms, wildcard certificates are only supported via dns-01 validation, and in some cases via EAB (pre-authenticated) http-01. To use this feature:

  • Enter a wildcard certificate string into the data group string entry (ex. *.f5labs.com)
  • Add the --alias option to the data group value entry and specify a name (ex. --alias wildcard_f5labs_com)

The name is arbitrary but must follow BIG-IP convention as it will be used as the named certificate object in the BIG-IP configuration. A complete example would look like this:

*.f5labs.com := --ca https://smallstep.f5labs.com:9000/acme/acme/directory --alias wildcard_f5labs_com
Working with Syslog reporting

To push log information to Syslog, simply update the SYSLOG variable in the provider config file to indicate the Syslog facility and severity level (ex.local0.err == local0 facility with "err" severity).

Working with certificate configs in alternate partitions

To use a certificates configuration data group stored in an alternate partition/folder, update the DGCONFIG variable directly in the f5acmehandler.sh script. Use of an alternate partition/folder is generally required when making data group changes via AS3 automation.

Working with OCSP and Periodic Revocation Testing

As a function of the utility, OCSP revocation status can be tested on existing certificates. This is set with the CHECK_REVOCATION value in the client config file, by default disabled (false). When enabled, and the certificate exists on the BIG-IP, the PEM certificate, issuer, and OCSP URI values are collected and a direct OCSP check is performed. If the certificate is revoked, a new certificate and private key are requested (vs. generating a CSR on the existing private key).

It is also possible to perform a direct check of revocation with the --testrevocation command line argument, followed by the certificate name (domain) as specified on the BIG-IP.

cd /shared/acme
./f5acmehandler.sh --testrevocation foo.f5labs.com

This will return one of the following possible values:

Value Description
revoked The OCSP check was successful and the response was revoked
notrevoked The OCSP check was successful and the response was not revoked
unavailable The OCSP check was not performed, in the case that the utility is unable to collect a chain (issuer) and OCSP URI value from the certificate

Working with High Availability

In an HA environment, the f5acmehandler.sh utility stores state information in iFile objects. On start, account and config state are pulled from the iFiles, and on completion, the account and config state is pushed back to iFiles if any changes are detected:

iFile Description
f5_acme_account_state Stores the compressed and encoded contents of the /shared/acme/accounts folder
f5_acme_config_state Stores the compressed and encoded contents of all "config*" files in /shared/acme
f5_acme_dnsapi_state Stores the compressed and encoded contents of the /shared/acme/dnsapi folder

While account state is always read from and pushed back to iFile (in an HA environment), the --save command-line option enables the utility script to read from local config files, then pushing all config state up to iFiles on completion. In Standalone environments, account and config state are always stored locally in the /shared/acme folder.

./f5acmehandler.sh --save

Working with BIG-IQ

Working with BIG-IQ primarily involves "Script Management", and can broken down into the following set of tasks:

  • On the BIG-IP(s), ensure Advanced Shell access is enabled for the admin user:

    • System --> Users --> User List --> Admin user
    • Terminal Access: Advanced shell
  • Installing the f5acmehandler utility (on all managed BIG-IP devices)

    • Devices --> Script Management --> Scripts (Add)

      • Name: Install f5acmehandler utility
      • Script:
      curl -s https://raw.githubusercontent.com/f5devcentral/kojot-acme/main/install.sh | bash
      
      • Save & Close
    • Devices --> Script Management --> Scripts (Run)

      • Name: Install f5acmehandler utility
      • Script: (select script)
      • Select BIG-IP Devices: (select all managed BIG-IP devices)
  • Scheduling the f5acmehandler utility (on all managed BIG-IP devices)

    • Devices --> Script Management --> Scripts (Add)

      • Name: Schedule f5acmehandler utility
      • Script:
      tmsh modify ltm data-group internal dg_acme_config records replace-all-with { \
      "bar.acmelabs.com" { data "-a rsa --ca https://10.1.30.6:14000/dir" } \
      "foo.acmelabs.com" { data "-a rsa --ca https://10.1.30.6:9000/acme/acme/directory" } \
      "test.acmelabs.com" { data "-a rsa --ca https://10.1.30.6:14000/dir" } \
      "www.acmelabs.com" { data "-a rsa --ca https://10.1.30.6:9000/acme/acme/directory" } }
      
      • Save & Close
    • Devices --> Script Management --> Scripts (Run)

      • Name: Schedule f5acmehandler utility
      • Script: (select script)
      • Select BIG-IP Devices: (select all managed BIG-IP devices)
  • Initiating a first run of the f5acmehandler utility (on the active BIG-IP devices)

    • Devices --> Script Management --> Scripts (Add)

      • Name: Run f5acmehandler utility
      • Script:
      /shared/acme/f5acmehandler.sh --verbose
      
      • Save & Close
    • Devices --> Script Management --> Scripts (Run)

      • Name: Run f5acmehandler utility
      • Script: (select script)
      • A21E
      • Select BIG-IP Devices: (select the active BIG-IP devices)

Reporting

The f5acmehandler utility can generate reports on renewal functions and send an email via SMTP configuration. This configuration is stored in the /shared/acme/config_reporting file:

Value Options Description
ENABLE_REPORTING Set to 'true' to enable EMAIL reporting.
MAILHUB Set this to the email SMTP host and port. Example: smtp.sendgrid.net:587
USERSTARTTLS Set this to 'yes' to enable StartTLS, as required by the SMTP server.
USETLS Set this to 'yes' to enable SSL/TLS, as required by the SMTP server.
AUTHUSER Set the username if the SMTP server requires authentication. No quotation marks needed here.
AUTHPASS Set the user password if the SMTP server requires authentication. No quotation marks needed here.
REPORT_FROM Set the email address of the sender.
REPORT_TO Set the email address of the receiver.
REPORT_SUBJECT Set the email Subject line.
TLS_CA_FILE Set this to the local path of a CA certificate bundle file for validating the SMTP server certificate. The install script automatically copies the ca-bundle.crt file to the local working directory, so this would be '/shared/acme/ca-default.crt'.
FROMLINEOVERRIDE Set to 'yes' to override the From line. This is needed by the utility script.

With the above settings defined, you can test the SMTP config from the BIG-IP command line with the following:

echo -e "From: <sender email address>\nSubject: Test Email\n\nTest Email" | ssmtp -v -C /shared/acme/config_reporting <receiver email address>

Verbosity is set in the ssmtp command so the full transaction will dump to stdout for troubleshooting.


Upgrading

If upgrading from a previous version of this utility, follow the below instructions:

  • If you've made changes to the default config file, create a copy of this file. The installer will replace it with the default values. In the case of updating to the 2025 May release, new options are included in this config. You will need to transcribe your own settings to the new config file to pick up the updates.

  • Re-run the installer script. This will perform the following functions:

    • Re-install the new versions of the utility scripts (f5acmehandler.sh and f5hooks.sh).
    • Re-install the default config file. Again, if changes have been made to this file for your environment, make a copy of your version before upgrading. You will need to transcribe your settings to this new config file to pick up the utility updates.
    • Create a bin folder under /shared/acme, copy a project local version of dehydrated to this folder, and delete the version in the root folder.
    • Create a dnsapi folder under /shared/acme. This folder will be empty by default. To use dns-01 validation, create your DNS API script in this folder. More information on dns-01 usage in the "Working with ACMEv2 DNS-01 validation" section.
    • All other folders (accounts, certs, chains) will remain intact through the upgrade.

Perform the above upgrade steps on both BIG-IP peers in an HA environment, then issue an initial fetch from the command line of the active peer:

./f5acmehandler.sh --force --verbose
Uninstall

To uninstall all objects:

curl -s https://raw.githubusercontent.com/f5devcentral/kojot-acme/main/uninstall.sh | bash

Note that the dg_acme_challenge data group, and acme_handler_rule iRule are not deleted in the uninstall script, as they are referenced outside of the f5acmehandler.sh utility.



${\LARGE{\textnormal{\textbf{\color{blue}Troubleshooting}}}}$

Error Messaging

The f5acmehandler.sh utility provides the following error messages:

Message Description
PANIC: There was an error accessing the dg_acme_config data group. Please re-install. The global configuration data group cannot be found. Re-install the utility from the repo to repair.
PANIC: Specified config file for (DOMAIN) does not exist (CONFIG FILE) A config file (--config file) specified in the global configuration data group does not exist. Confirm that the file exists and path is correct.
PANIC: Configuration entry for (DOMAIN) must include a "--ca" option. Skipping. A domain entry in the global configuration data group is missing the --ca option. This value is required for all domain entries.
PANIC: Configuration entry (DOMAIN) is incorrect. Skipping. A domain entry in the global configuration data group does not meet minimal fully qualified domain name pattern validation.
PANIC: Connectivity error for (DOMAIN). Please verify configuration (CA URL) The ACME client was unable to connect to the defined ACME provider URL. Verify that --ca value is correct in the global configuration data group.
ERROR: Please correct the format of supplied cron string. No schedule applied. A supplied CRON string in a --schedule operation does not meet minimum CRON pattern validation.

General Troubleshooting

Below are a common set of steps for troubleshooting utility operations:

  • Use the --verbose option on the command line to output debug messaging. This will most often display any issues during the ACME renewal process.
  • If verbose logging indicates a registration issue with a provider, delete the respective provider subfolder under the /shared/acme/accounts folder. The registered providers can be listed using the --listaccounts command line option. The utility will attempt to re-register to the provider on next run.
  • Use the --domain, --force, and --verbose command line options to test against a single provider for easier troubleshooting. It may also be beneficial to stand up one of the local ACME services (via Docker-Compose) to test general functionality if the real ACME providers inforce connection limits.



${\LARGE{\textnormal{\textbf{\color{blue}Testing}}}}$

There are a number of ways to test the f5acmehandler utility, including validation against local ACME services. The acme-servers folder contains Docker-Compose options for spinning up local Smallstep Step-CA and Pebble ACME servers. The following describes a very simple testing scenario using one of these tools.

  • On the BIG-IP, install the f5acmehandler utility components on the BIG-IP instance. SSH to the BIG-IP shell and run the following command:

    curl -s https://raw.githubusercontent.com/f5devcentral/kojot-acme/main/install.sh | bash
  • Install the Smallstep Step-CA ACME server instance on a local Linux machine. Adjust the local /etc/hosts DNS entries at the bottom of the docker-compose YAML file accordingly to allow the ACME server to locally resolve your ACME client instance (the set of BIG-IP HTTP virtual servers). This command will create an ACME service listening on HTTPS port 9000.

    git clone https://github.com/f5devcentral/kojot-acme.git
    cd kojot-acme/acme-servers/
    docker-compose -f docker-compose-smallstep-ca.yaml up -d
  • On the BIG-IP, for each of the above /etc/hosts entries, ensure that a matching HTTP virtual server exists on the BIG-IP. Define the destination IP (same as /etc/hosts entry), port 80, a generic http profile, the proper listening VLAN, and attach the acme_handler_rule iRule.

  • On the BIG-IP, update the dg_acme_config data group and add an entry for each domain (certificate). This should match each /etc/hosts domain entry specified in the docker-compose file.

    www.foo.com := --ca https://<acme-server-ip>:9000/acme/acme/directory
    www.bar.com := --ca https://<acme-server-ip>:9000/acme/acme/directory -a rsa
  • To view DEBUG logs for the f5acmehandler processing, ensure that the DEBUGLOG entry in the config file is set to true. Then in a separate SSH window to the BIG-IP, tail the acmehandler log file:

    tail -f /var/log/acmehandler

    or use the --verbose option with the f5acmehandler.sh script:

    ./f5acmehandler.sh --verbose
  • Trigger an initial ACMEv2 certificate fetch. This will loop through the dg_acme_config data group and process ACME certificate renewal for each domain. In this case, it will create both the certificate and private key and install these to the BIG-IP. You can then use these in client SSL profiles that get attached to HTTPS virtual servers. In the BIG-IP, under System - Certificate Management - Traffic Certificate Management - SSL Certificate List, observe the installed certificate(s) and key(s).

  • Trigger a subsequent ACME certificate fetch, specifying a single domain and forcing renewal. Before launching the following command, open the properties of one of the certificates in the BIG-IP UI. After the command completes, refresh the certificate properties and observe the updated Serial Number and Fingerprint values.

    ./f5acmehandler.sh --domain www.foo.com --force


${\LARGE{\textnormal{\textbf{\color{blue}Credits}}}}$

Special thanks to:



Updates

Major Updates: 2025 May


About

An ACMEv2 client utility function for integration and advanced features on the F5 BIG-IP

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 3

  •  
  •  
  •  

Languages

0