#  -*- 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 "recv Status-Server" 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 {
#
#  ...
#
#  recv Access-Request {
#
#      = 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.
#

#
#  Within this virtual server we provide only a `recv Status-Server`
#  section whose task is to perform the resource checks and sets the
#  status of the "control module"
#
server resource-check {

namespace = radius

listen {
	transport = udp
	udp {
		ipaddr = 127.0.0.1
		port = 18122
	}
	type = Status-Server
}

recv 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')
		}

	}

}

}
