# -*- text -*-
######################################################################
#
#  This virtual server provides an example of how to dynamically amend the
#  control flow within some virtual server's policy on the basis of the status
#  of some resource, such as an external database.
#
#  This resource-check virtual server receives periodic dummy server-status
#  requests that trigger an arbitrary set of checks. On the basis of those
#  checks the status of an instance of the rlm_always module, that we refer to
#  as the "control module", is updated to reflect the system status.
#
#  Elsewhere, some other virtual server (the "controlled virtual server") uses
#  the control module to make decisions during the processing of incoming
#  requests. By amending the status of the control module in response to the
#  system status this virtual server is able to manipulate the outcome of the
#  controlled virtual server.
#
#  Firstly, the authorize section of this virtual server will need to be
#  amended to check the status of the external resources and to set the status
#  of the control module appropriately, as described in the inline comments
#  below...
#
#  In addition to configuring and activating this virtual server, a control
#  module must be configured as an instance of rlm_always in mods-enabled, for
#  example:
#
#    always db_online {
#        # Default to online
#        rcode = ok
#    }
#
#  Now trigger the resource checks by sending a server-status request to this
#  virtual server, as follows:
#
#    echo "Message-Authenticator = 0x00" | \
#      radclient -r 1 -t 3 -q 127.0.0.1:18122 status testing123
#
#  The trigger could be invoked by a cron job or if more frequent checks than
#  once per minute are required a systemd timer might be used.
#
#  The current status of the control module can be examined at any time using
#  radmin:
#
#    radmin -e 'show module status db_online'
#
#  For radmin to work requires that the control-socket virtual server is
#  configured and enabled.
#
#  The controlled virtual server will contain some control flow decision that
#  uses the control module, for example:
#
#    server default {
#
#    ...
#
#    authorize {
#
#        #  If the database is not healthy then remain silent to trigger
#        #  NAS failover
#        #
#        db_online {
#            fail = 1
#        }
#        if (fail) {
#             do_not_respond
#        }
#
#        sql
#
#        pap
#    }
#
#    ...
#
#
#  The configuration for this virtual server follows and should be amended as
#  required...
#


#
#  Listen on a local port for Server-Status requests that trigger the resource
#  checks.
#
#  This uses the normal set of clients, with the same secret as for
#  authentication and accounting.
#
listen {
	type = status
	ipaddr = 127.0.0.1
	port = 18122
	virtual_server = resource_check
}


#
#  Within this virual server we provide only an Autz-Type Status-Server section
#  whose task is to perform the resource checks and sets the status of the
#  "control module"
#
server resource-check {

authorize {

Autz-Type Status-Server {

	#
	#  In this example we check whether a PostgreSQL database is in
	#  recovery (or inaccessible) and when this is the case we fail the
	#  db_online control module.
	#
	#  Other modules could be used here.
	#
	#  You can even invoke synchronous checks using the %{exec:...} xlat in
	#  which case timeout should be set to less than the check trigger
	#  interval to avoid buildup of checks when resources do not respond.
	#  See rlm_exec for details.
	#
	if ("%{sql:SELECT pg_is_in_recovery()}" != "f") {

		# Fail the db_online module, if it isn't already
		if ("%{db_online:}" != "fail") {
			%{db_online:fail}
		}

	} else {

		# Set the db_online module status to alive, if it isn't already
		if ("%{db_online:}" != "alive") {
			%{db_online:alive}
		}

	}

}

}

}
