(Implentation is currently "turned off" due to problems with apps hanging - 7/9/2016 10:22:09 AM ) We have limited resources (especially in temp storage space) so we do not want users to be able to come in and use those resources so heavily that other users are impacted. We have decided that we want to limit the total number of SAS apps that a user can run in one hour (100) and the most temp storage space they can use in a 12-hour period (5G) when we are running low on temorary disk space.
Our purpose here is to document the strategy / software used to implement these decisions.
The file sasapp.slist in /tmp/scratch is a key piece. The first (and usually only) line of this file has the current date in DDMMMYY format (e.g. 21OCT14). Subsequent lines will contain values of remote addresses of users who are being denied service for the remainder of today. That first line with just the current date is written by the applog.sas program (invoked at the end of each web app hopefully) when it detects that the current date differs from the slist date.
This is the key module for implementing the strategy. It is invoked by simply including it in a sas web app using:
The appuserck module opens and reads the slist file to see if the current vlue of _RMTADDR is matched on slist, which would mean this user has been denied service for the rest of the day. We would thus set the global parm unavailable to a value of 1 to tell the invoking program that they should deny service. Otherwise, we proceed to the following checks. We run a data step that scans our sas application log file (/var/log/sas_applog, written to by the applog.sas module which is invoked as the last thing done in most of our SAS-based web apps. We look at the most recent 2000 applog entries (lines on the file) and scan these looking for the current value of _RMTADDR. The log entry contains the following info:
[Special manual overrides to deny service to specific IPs Using appuserck.sas
Occasionally we see a user abusing the system but not getting denied by our std procedures. We can insert special code in the appuserck.sas module to simulate normal denial. We simply add code to check the value of the &rmtaddr parm and if it matches our manual-override IP then we manually deny service. We first did this 2-16-16 with special code entered at line 38. ]
Here is what the appuserck program does with this information:
Filters the input file so that only lines associated with the current value of _RMTADDR are processed.
Counts the number of log entries occurring within the last hour. If it exceeds 200 we deny service.
Sums the total temporary directory space left behind by this user within the past 12 hours. If it exceeds 5 gigabytes, and if a check of available temp space indicates we are over 65% full, then we deny service. (The somewhat arbitrary values used here: 12 hours, 5 Gig and 65% utilitzation are all parameters that we may tweak as time goes on if we see they are not adequate to solve our problem.)
When the program "denies service" it does 3 things:
Sets the global parm unavailable to 1 (or 2 if the user is already on slist).
Uses the errmsg global parm and the ckforerr macro to display a message back to the user.
Writes (in append mode) the current value of _RMTADDR to the slist file if unavailable ne 2.
First of all, this applies only to our SAS apps. It has no effect whatsoever on other non-sas apps, such as the acsprofile or applinks.
Only those applications that have the appuserck.sas %include statement will be affected. It will be easy to add to the list over time as we see other modules that are resulting in over usage. So far we have implemented checks on the following modules:
Obviously these applications have to be aware of the strategy and have to implement the denial of service by testing the value of a global parameter called unavailable. When this parameter ("flag") has a value of 1 or 2 (using the SAS logical variable convention where 1 is true and 0 is false) then the application needs to implement the denial by simply not generating any output.