How to protect your audit trail in a SAS environment


SecurityIn a number of my previous blogs I have discussed auditing within a SAS environment and how to identity who has accessed data or changed reports. For many companies keeping an audit trail is very important. If you’re an administrator in your environment and auditing is important at your organization, here are a few steps to take to secure the auditing setup and possibly audit any changes made to it, all the while ensuring there are no gaps in collecting this information.

In a SAS deployment the logging configuration is stored in XML files for each server configuration.  The xml files can be secured with OS permissions to prevent unauthorized changes. However, there are a number of ways in which a user can temporarily adjust logging settings which may allow them to prevent audit messages from reaching a log.

Logging can be adjusted dynamically in:

SAS Code using logging functions and macros
SAS Management Console

As an example of how a user could circumvent the audit trail let’s look at an environment where logging has been configured to audit access to SAS datasets using the settings described in this blog. When auditing is enabled, messages are recorded in the log when users access a table. In the test case for the blog we have a stored process that prints a SAS dataset. When the stored process runs, the log will record the table that was opened and the user that opened it.


A user could turn auditing off by adding a call to the log4sas_logger function. The code below included at the start of the Stored Process (or any SAS program) would turn dataset audit logging off for the duration of the execution. Any access of datasets in the Stored Process would no longer be audited.

data _null_;
rc=log4sas_logger(“Audit.Data.Dataset.Open”, “level=off”);

There is an option we can add to the logger to prevent this from happening. The IMMUTABILITY option specifies whether a logger’s additivity and level settings are permanent or whether they can be changed by using the SAS language. In the code above the level of the logger was changed using the log4sas logger function.

If we add the immutability=”true” setting to the logger, this will prevent a user from adjusting the logging level dynamically using the DATA step functions. Attempts to adjust the logger's level will fail with an error. More about the Logging Facility.

<logger name=”Audit.Data.Dataset.Open” immutability=”true”>
 <appender-ref ref=”TimeBasedRollingFileAudit”/>
 <level value=”Trace”/>


However, this setting does not fully prevent dynamic changes to logging configuration. IMMUTABILITY is ignored for configuration changes made by administrators using SAS Management Console or the IOMOPERATE procedure.

Users who have access to the SAS Management Console Server Manager plug-in can change logging on the fly. In SAS Management Console select Server Manager > SASApp > SAS App Logical Stored Process Server > <machine> right-click and select Connect.  This will display the process ID of an active Stored Process Server. Select the PID and select the loggers tab. This tab displays the current setting for the active loggers on the SAS server. The Audit.Data.Dataset.Open logger has a level of TRACE, this is the setting that is writing audit messages about activity on the dataset to the log.


An administrator can change the level of the logger by right-clicking on the logger name, and selecting Properties. In this example we will turn logging off for the Audit.Data.Dataset.Open logger.


Now any run of a stored process will no longer record audit messages about data access to the log.

Users could also use PROC IOMOPERATE to change the logging configuration on a server. The code below dynamically finds the serverid of the stored process server and then turns audit logging off. The key piece of code is the set attribute line near the end:

%let spawnerURI = %str(iom://server:8581;Bridge;user=sasadm@saspw,pass=???);
proc iomoperate ;
 connect uri=”&spawnerURI”;
list spawned;
 list spawned out=obj_spawned;
data _null_;
 set work.obj_spawned;
 where upcase( serverComponent ) like ‘%STORED%’;
call symput(“stpid”, strip(serverid) );
proc iomoperate;
 connect uri=”&spawnerURI”
spawned=”&stpid”   ;
set attribute category=”Loggers” name=”Audit.Data.Dataset.Open” value=”OFF”;

You must be a SAS Administrator to change logging configuration dynamically with SAS Management Console and PROC IOMOPERATE. While access to this functionality can be restricted, it does leave a potential gap in the auditing setup.  As a further failsafe you can actually configure auditing so that any changes made to logging configuration results in audit messages about the change in a log file. Effective with SAS 9.4, the following loggers capture these changes:

  • Logging.Configuration.Logger
  • Logging.Configuration.Appender
  • Logging.Configuration.Config

Let’s see how we can audit changes that are made to the Stored Process server’s logging configuration file.  In the existing configuration file, add a new appender. The new appender (below) will write messages to a separate log in the audit directory of the Stored Process server (make sure this directory exists). The log will have a name similar to  AuditLogsSASApp_LoggingChange_2016-09-15_sasbi_16024.log

<!– Rolling log file with default rollover of midnight for Logging Auditing –>
 <appender class=”RollingFileAppender” name=”TimeBasedRollingFileLogging“>
 <param name=”Append” value=”false”/>
 <param name=”Unique” value=”true”/>
 <param name=”ImmediateFlush” value=”true”/>
 <rollingPolicy class=”TimeBasedRollingPolicy”>
 <param name=”FileNamePattern” value=”D:\SAS\vaconfig\Lev1\SASApp\StoredProcessServer\AuditLogs\SASApp_LoggingChange_%d_%S{hostname}_%S{pid}.log”/>
 <param name=”HeaderPattern” value=”Host: ‘%S{hostname}’, OS: ‘%S{os_family}’, Release: ‘%S{os_release}’, SAS Version: ‘%S{sup_ver_long2}’, Command: ‘%S{startup_cmd}'”/>
 <param name=”ConversionPattern” value=”%d %-5p [%t] %X{Client.ID}:%u – %m”/>

Now we will add a logger that references the new appender. The Audit.Logging logger will write all changes to loggers and appenders to the referenced appender.  After you make changes to logging configuration make sure you validate the server in SAS Management Console; syntax errors in logging configuration files can render SAS servers inoperable.

<logger name=”Audit.Logging” immutability=”true”>
 <level value=”Trace”/>
 <appender-ref ref=”TimeBasedRollingFileLogging”/>

Once you have this set up, any dynamic changes made to logging configuration, either through the SAS language, PROC IOMOPERATE or SAS Management Console, will write a record to the new logging configuration auditing log.


When auditing is a critical requirement for a SAS deployment it is important for administrators to close any gaps which would allow actions to fail to write audit records.

These gaps can be closed by:

  • Securing the logging configuration file using operating system permissions
  • Ensuring that key loggers are configured as immutable
  • Restricting access to the SAS Management Console Server Manager plug-in
  • Ensuring that only key administrators have access to credentials that can change auditing configuration using SAS Management Console and PROC IOMOPERATE
  • Configuring auditing for changes to the logging configuration

About Author

Gerry Nelson

Principal Technical Consultant

Gerry Nelson is an Advisory Technical Architect in the Global Enablement and Learning (GEL) Team within SAS R&D Division. His primary focus is on administration of SAS VIya environments, particularly automation, modernization, migration, and upgrading.


  1. Thanks for pointing out how a user can override the logging but do you have some suggested changes for capturing audit data? I'd like to be able to report on how much each user actually used SAS, what procs they use, and what databases and tables access.

Leave A Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Back to Top