Repository
Munin (contrib)
Last change
2021-10-06
Graph Categories
Family
auto
Capabilities
Keywords
Language
Bash
License
GPL-2.0-only

letsencrypt_weekly

Example graph: 1 Example graph: 2

Name

letsencrypt_weekly - monitor the number of CSRs by week for /etc/letsencrypt/csr/

Description

This plugin monitors the number of certificate signing requests (CSRs) done with letsencrypt’s certbot. It tries to determine the registered domain and reports the number also per registered domain. For people running multiple servers this enables aggregation of those numbers across multiple nodes in the munin.conf

see https://letsencrypt.org/docs/rate-limits/

Configuration

You can configure the warning and critical limits for this plugin:

[letsencrypt_weekly]
# run with a user that is able to read /etc/letsencrypt/csr/ files and at least list directories in
# /etc/letsencrypt/archive/
user root
# warn when more than 40 certificates have been requested in the last week
env.warning :40
# critical when more than 50 certificates have been requested in the last week
env.critical :50

Aggregation Configuration

When you have multiple servers issuing certficates for the same registered domain you can aggregate the numbers with this config:

[letsencrypt]
    update no
    contact no
    # summarize letsencrypt_weekly from all hosts
    # see http://guide.munin-monitoring.org/en/latest/example/graph/aggregated-stack.html#extract-from-munin-conf
    # see http://guide.munin-monitoring.org/en/latest/example/graph/aggregate.html#example-plugin-aggregate

    letsencrypt_weekly_example_com.update no
    letsencrypt_weekly_example_com.graph_args --base 1000 -l 0
    letsencrypt_weekly_example_com.graph_category security
    letsencrypt_weekly_example_com.graph_period week
    letsencrypt_weekly_example_com.graph_title Letsencrypt example.com certificate requests
    letsencrypt_weekly_example_com.graph_vlabel requests / week
    letsencrypt_weekly_example_com.graph_scale no
    letsencrypt_weekly_example_com.graph_total Total
    letsencrypt_weekly_example_com.weekly.label Certificates for example.com
    letsencrypt_weekly_example_com.weekly.draw AREA
    letsencrypt_weekly_example_com.weekly.stack \
          line1_name=example.com;line1-host-name.example.com:letsencrypt_weekly.example_com_weekly \
          line2_name=example.com;line2-host-name.example.com:letsencrypt_weekly.example_com_weekly

    letsencrypt_renewal_weekly_example_com.update no
    letsencrypt_renewal_weekly_example_com.graph_args --base 1000 -l 0
    letsencrypt_renewal_weekly_example_com.graph_category security
    letsencrypt_renewal_weekly_example_com.graph_period week
    letsencrypt_renewal_weekly_example_com.graph_title Letsencrypt example.com certificate renewal requests
    letsencrypt_renewal_weekly_example_com.graph_vlabel requests / week
    letsencrypt_renewal_weekly_example_com.graph_scale no
    letsencrypt_renewal_weekly_example_com.graph_total Total
    letsencrypt_renewal_weekly_example_com.weekly.label Certificate renewals for example.com
    letsencrypt_renewal_weekly_example_com.weekly.draw AREA
    letsencrypt_renewal_weekly_example_com.weekly.stack \
          line1_name=example.com;line1-host-name.example.com:letsencrypt_weekly.example_com_renewal_weekly \
          line2_name=example.com;line2-host-name.example.com:letsencrypt_weekly.example_com_renewal_weekly

Dependencies

Dependencies: openssl

Author

andreas perhab - andreas.perhab@wt-io-it.at (https://www.wt-io-it.at/)

License

GPLv2

Magic Markers

#%# family=auto
#%# capabilities=autoconf
#!/bin/bash
: << =cut
=head1 NAME

letsencrypt_weekly - monitor the number of CSRs by week for /etc/letsencrypt/csr/

=head1 DESCRIPTION

This plugin monitors the number of certificate signing requests (CSRs) done with letsencrypt's certbot.
It tries to determine the registered domain and reports the number also per registered domain.
For people running multiple servers this enables aggregation of those numbers across multiple nodes in the munin.conf

see https://letsencrypt.org/docs/rate-limits/

=head1 CONFIGURATION

You can configure the warning and critical limits for this plugin:

  [letsencrypt_weekly]
  # run with a user that is able to read /etc/letsencrypt/csr/ files and at least list directories in
  # /etc/letsencrypt/archive/
  user root
  # warn when more than 40 certificates have been requested in the last week
  env.warning :40
  # critical when more than 50 certificates have been requested in the last week
  env.critical :50

=head1 AGGREGATION CONFIGURATION

When you have multiple servers issuing certficates for the same registered domain you can aggregate the numbers with
this config:

  [letsencrypt]
      update no
      contact no
      # summarize letsencrypt_weekly from all hosts
      # see http://guide.munin-monitoring.org/en/latest/example/graph/aggregated-stack.html#extract-from-munin-conf
      # see http://guide.munin-monitoring.org/en/latest/example/graph/aggregate.html#example-plugin-aggregate

      letsencrypt_weekly_example_com.update no
      letsencrypt_weekly_example_com.graph_args --base 1000 -l 0
      letsencrypt_weekly_example_com.graph_category security
      letsencrypt_weekly_example_com.graph_period week
      letsencrypt_weekly_example_com.graph_title Letsencrypt example.com certificate requests
      letsencrypt_weekly_example_com.graph_vlabel requests / week
      letsencrypt_weekly_example_com.graph_scale no
      letsencrypt_weekly_example_com.graph_total Total
      letsencrypt_weekly_example_com.weekly.label Certificates for example.com
      letsencrypt_weekly_example_com.weekly.draw AREA
      letsencrypt_weekly_example_com.weekly.stack \
            line1_name=example.com;line1-host-name.example.com:letsencrypt_weekly.example_com_weekly \
            line2_name=example.com;line2-host-name.example.com:letsencrypt_weekly.example_com_weekly

      letsencrypt_renewal_weekly_example_com.update no
      letsencrypt_renewal_weekly_example_com.graph_args --base 1000 -l 0
      letsencrypt_renewal_weekly_example_com.graph_category security
      letsencrypt_renewal_weekly_example_com.graph_period week
      letsencrypt_renewal_weekly_example_com.graph_title Letsencrypt example.com certificate renewal requests
      letsencrypt_renewal_weekly_example_com.graph_vlabel requests / week
      letsencrypt_renewal_weekly_example_com.graph_scale no
      letsencrypt_renewal_weekly_example_com.graph_total Total
      letsencrypt_renewal_weekly_example_com.weekly.label Certificate renewals for example.com
      letsencrypt_renewal_weekly_example_com.weekly.draw AREA
      letsencrypt_renewal_weekly_example_com.weekly.stack \
            line1_name=example.com;line1-host-name.example.com:letsencrypt_weekly.example_com_renewal_weekly \
            line2_name=example.com;line2-host-name.example.com:letsencrypt_weekly.example_com_renewal_weekly

=head1 Dependencies

Dependencies: openssl

=head1 AUTHOR

andreas perhab - andreas.perhab@wt-io-it.at (https://www.wt-io-it.at/)

=head1 LICENSE

GPLv2

=head1 MAGIC MARKERS

 #%# family=auto
 #%# capabilities=autoconf

=cut

. "$MUNIN_LIBDIR/plugins/plugin.sh"

warning=${warning:-:40}
critical=${critical:-:50} #letsencrypt doesn't allow more than 50 certificates per week
# see https://letsencrypt.org/docs/rate-limits/


get_files_and_domains() {
	find /etc/letsencrypt/csr/ -mtime -7 -type f -print0 2>/dev/null | xargs -0 -I pem bash -c 'echo -n "pem "; openssl req -in pem -text -noout | grep DNS: | sed "s/.*DNS://g"'
}

get_registered_domains() {
	local REMOVE_PATH
	local TRIM_SUBDOMAIN
	REMOVE_PATH='s,.*/,,;'
	TRIM_SUBDOMAIN='s/.*\.\([a-z0-9-]\+\.[a-z]\+\)/\1/;'
	find /etc/letsencrypt/archive/ -mindepth 1 -maxdepth 1 | sed "$REMOVE_PATH $TRIM_SUBDOMAIN" | sort | uniq
}

if [ "$1" = "autoconf" ] ; then
	test -d /etc/letsencrypt/csr/ && echo "yes" || echo "no (directory /etc/letsencrypt/csr does not exist)"
elif [ "$1" = "config" ] ; then
	echo "graph_title Letsencrypt certificate requests during last week"
	echo "graph_args --base 1000"
	echo "graph_vlabel Number of certificates"
	echo "graph_category security"
	echo "letsencrypt_weekly.label Letsencrypt certificates last week"
	for domain in $(get_registered_domains); do
		key=${domain//[-.]/_}
		echo "${key}_weekly.label $domain"
		print_warning "${key}_weekly"
		print_critical "${key}_weekly"
		echo "${key}_renewal_weekly.label $domain renewals"
	done
elif [ "$1" = "" ] ; then
	if existing_renewal_requests=$(get_files_and_domains); then
		value=$(echo "$existing_renewal_requests" | grep -v '^$' -c)
	else
		value="U"
	fi
	echo "letsencrypt_weekly.value $value"
	values=""
	for domain in $(get_registered_domains); do
		key=${domain//[-.]/_}
		if [ "$values" != "" ] ; then
			values="$values\n${key}_weekly.value 0\n${key}_renewal_weekly.value 0"
		else
			values="${key}_weekly.value 0\n${key}_renewal_weekly.value 0"
		fi
	done
	while read -r file_domain; do
		file=${file_domain% *}
		domain=${file_domain#* }
		registered_domain_key=$(echo "$domain" | sed 's/.*\.\([a-z0-9-]\+\.[a-z]\+\)/\1/;s/[-.]/_/g')
		previous_certs=$(find "/etc/letsencrypt/archive/$domain" -name 'cert*.pem' -not -cnewer "$file" | wc -l)	
		if [ "$previous_certs" -gt 0 ] ; then
			value_key="${registered_domain_key}_renewal_weekly.value "
		else
			value_key="${registered_domain_key}_weekly.value "
		fi
		old_value=$(echo -e "$values" | grep "$value_key" | sed 's/.* //g')
		value=$((old_value + 1))
		values=${values//$value_key$old_value/$value_key$value}
	done < <(get_files_and_domains)
	echo -e $"$values"
fi