Skip to content

[Feature:System] Updated Preferred Name Change Script #28

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 50 additions & 37 deletions preferred_name_logging/pnc_compile.pl
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
# Invoke with -y or --yesterday to compile with yesterday's timestamps.
# Useful if you run this script overnight starting after 12AM.

# Author: Peter Bailie, RPI Research Computing
# Date: April 29, 2022
# Author: Peter Bailie, RPI Research Computing
# Date: April 29, 2022
# Updated: February 7, 2023

use strict;
use warnings;
Expand All @@ -28,46 +29,58 @@
open my $psql_fh, "<:encoding(UTF-8)", $PSQL_LOG;
open my $pnc_fh, ">>:encoding(UTF-8)", $PNC_LOG;

my ($timestamp, $userid, $auth) = ("", "", "");
my ($oldfn, $newfn, $oldln, $newln, $line1, $line2);
# fn = firstname/givenname, ln = lastname/familyname
my ($timestamp, $userid, $auth, $oldfn, $newfn, $oldln, $newln, $line1, $line2);
my $regex_check = 1;
while (<$psql_fh>) {
($timestamp, $userid, $oldfn, $newfn, $oldln, $newln) = ($1, $2, $3, $4, $5, $6) if (/^${datestamp} (\d{2}:\d{2}:\d{2}\.\d{3} [A-Z]{3}).+DETAIL: USER_ID: "(.+?)" (?:PREFERRED_FIRSTNAME OLD: "(.*?)" NEW: "(.*?)" )?(?:PREFERRED_LASTNAME OLD: "(.*?)" NEW: "(.*?)")?$/);
$auth = $1 if (/\/\* AUTH: "(.+)" \*\//);
# $auth is always on a different line than $timestamp, $userid.
# But all three having data will indicate we have collected pref name change logs.
if ($timestamp ne "" && $userid ne "" && $auth ne "") {
# $oldfn, $newfn, $oldln, $oldfn -- some may be undefined.
# This happens when either the firstname or lastname change wasn't recorded in PSQL logs (because no change occured).
# Undefined vars need to be defined to prevent 'concatenation by undefned var' warning.
foreach ($oldfn, $newfn, $oldln, $newln) {
$_ = "" if (!defined $_);
if ($regex_check == 1) {
if ($_ =~ m/^${datestamp} (\d{2}:\d{2}:\d{2}\.\d{3} [A-Z]{3}).+LOG: PREFERRED_NAME DATA UPDATE$/) {
$timestamp = $1;
$regex_check = 2;
}

# If both old and new firstnames are blank, no change was logged.
if ($oldfn ne "" || $newfn ne "") {
($oldfn, $newfn) = rpad(19, $oldfn, $newfn);
$line1 = " OLD PREF FIRSTNAME: ${oldfn}";
$line2 = " NEW PREF FIRSTNAME: ${newfn}";
} else {
($line1, $line2) = ("", "");
($line1, $line2) = rpad(41, $line1, $line2);
} elsif ($regex_check == 2) {
if ($_ =~ m/DETAIL: USER_ID: "(.+?)" (?:PREFERRED_GIVENNAME OLD: "(.*?)" NEW: "(.*?)" )?(?:PREFERRED_FAMILYNAME OLD: "(.*?)" NEW: "(.*?)")?/) {
($userid, $oldfn, $newfn, $oldln, $newln) = ($1, $2, $3, $4, $5);
$regex_check = 3;
}
} elsif ($regex_check == 3) {
if ($_ =~ m/\/\* AUTH: "(.+)" \*\//) {
$auth = $1;

# If both old and new lastnames are blank, no change was logged.
if ($oldln ne "" || $newln ne "") {
($oldln, $oldfn) = rpad(19, $oldln, $oldfn);
$line1 .= " OLD PREF LASTNAME: ${oldln}\n";
$line2 .= " NEW PREF LASTNAME: ${newln}\n";
} else {
$line1 .= "\n";
$line2 .= "\n";
}
# $oldfn, $newfn, $oldln, $oldfn -- some may be undefined.
# This happens when either the givenname or familyname change wasn't recorded in PSQL logs (because no change occured).
# Undefined vars need to be defined to prevent 'concatenation by undefned var' warning.
foreach ($oldfn, $newfn, $oldln, $newln) {
$_ = "" if (!defined $_);
}

# If both old and new given names are blank, no change was logged.
if ($oldfn ne "" || $newfn ne "") {
($oldfn, $newfn) = rpad(19, $oldfn, $newfn);
$line1 = " OLD PREF GIVENNAME: ${oldfn}";
$line2 = " NEW PREF GIVENNAME: ${newfn}";
} else {
($line1, $line2) = ("", "");
($line1, $line2) = rpad(41, $line1, $line2);
}

($userid) = rpad(9, $userid);
print $pnc_fh "${datestamp} ${timestamp} USER: ${userid} CHANGED BY: ${auth}\n";
print $pnc_fh $line1;
print $pnc_fh $line2;
($timestamp, $userid, $auth) = ("", "", "");
# If both old and new family names are blank, no change was logged.
if ($oldln ne "" || $newln ne "") {
($oldln, $oldfn) = rpad(19, $oldln, $oldfn);
$line1 .= " OLD PREF FAMILYNAME: ${oldln}\n";
$line2 .= " NEW PREF FAMILYNAME: ${newln}\n";
} else {
$line1 .= "\n";
$line2 .= "\n";
}

($userid) = rpad(9, $userid);
print $pnc_fh "${datestamp} ${timestamp} USER: ${userid} CHANGED BY: ${auth}\n";
print $pnc_fh $line1;
print $pnc_fh $line2;

$regex_check = 1;
}
}
}

Expand Down
38 changes: 21 additions & 17 deletions preferred_name_logging/readme.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
# Preferred Name Logging
# Preferred Name Change Logging

## pnc_compile.pl
In the interests of diversity, Submitty provides for users to set a preferred name should it be different from their legal name. This feature can be abused, so changes to a user's preferred name is recorded into Postgresql's log for review. To make it easier to locate these logged messages, a sysadmin tools script, `pnc_compile.pl`, is provided to fetch the preferred name change logs from Postgresql and compile them into a human readable report.

This script will help track when user preferred names are changed. It attempts
to compile a report of who made a preferred name change, and what change had
occurred.
**IMPORTANT:** `pnc_compile.pl` needs to operate on a host that can directly access Postgresql's log. Typically, this means the script must be setup on the same server as Postgresql.

Submitty provides the preferred name change information in the Postgresql log.
This scipt is used to parse the Postgresql log and create its own report
of preferred name changes that is much more human readable.
1. Make sure your host has Perl 5.30.0 or later.
* Ubuntu 20.04 includes Perl 5.30.0.
2. Retrieve `pnc_compile.pl` from [Github](https://raw.githubusercontent.com/Submitty/SysadminTools/main/preferred_name_logging/pnc_compile.pl) (right click link and choose "Save Link As...")
3. Edit code file to setup its configuration.
* Locate the two lines shown below. They are near the top of the file. These lines dictate where to look for Postgresql's log and where to write the script's compiled log.
* `$PSQL_LOG` dictates where Postgresql's log is located. `$PNC_LOG` dictates where this script will record and append its report.
* The default for `$PSQL_LOG` is set for Postgresql 12 running in Ubuntu 20.04. The default for `$PNC_LOG` will write the script's report to the same directory as the script file.
* Change these values to match your host's setup.
```perl
my $PSQL_LOG = "/var/log/postgresql/postgresql-12-main.log";
my $PNC_LOG = "preferred_name_change_report.log";
```
4. Setup a cron schedule to run the script.
* Postgresql's log is typically owned by `root`, so it is mandatory to run the script as `root`.
* Be sure to set execute permission on the script.
* The script will parse Postgresql's log *by the current day's datestamp*, so it is intended that the script is run once per day.
* Alternatively, if you wish to schedule the crontab for overnight after 12AM, you can set the `-y` or `--yesterday` argument so the script will intentionally parse Postgresql's log by the *previous* day's datestamp. e.g. `/path/to/pnc_compile.pl -y`

This script will parse logs based on a specific datestamp. Since this script
acquires its datestamp based on GMT, it might work best when the postgresql logs
are timestamped in UTC.

This is intended to be run on the postgresql server on at least a daily basis.
Invoke the script with `-y` or `--yesterday` to parse logs with yesterday's
datestamp. That is useful to run the script overnight after 12AM.

## FERPA
# FERPA

Data processed and logged by this tool may be protected by
[FERPA (20 U.S.C. § 1232g)](https://www2.ed.gov/policy/gen/guid/fpco/ferpa/index.html).
Expand Down