vhost-audit/index.php

193 lines
5.1 KiB
PHP

<?
/*
TODO:
- Audit collapse animation is jerky and lame
- Suppress errors in cron script and schedule
- Cron script shouldn't wallop json files while it's running
- Update styles and icons in UI when files are (un)ignored
- Add option to show all ignores/acks
- Add option to clear all ignores/acks
- Adding directory aknowlegement could be useful for plugin
updates and new sites.
*/
require_once('template.php');
$errors = array();
$sites = array();
$slugs = array();
$audits = array();
$ignores = array();
$changed_files = array();
$unacked_files = array();
$unacked_scripts = array();
$unacked_sites = array();
$audit_dir = 'json';
$warn_age = 1 * 24 * 60 * 60; # 1 day, 24 hours, or seconds
# need to keep this in sync with vhost-audit.pl
$scripts = array('/.php$/', '/.htaccess$/', '/.js$/');
$sites_file = 'sites.txt';
if ( ($sites = @file($sites_file, FILE_IGNORE_NEW_LINES)) !== FALSE ) {
$site_count = count($sites);
sort($sites);
}
else {
$errors[] = 'Could not open sites file, ' . $sites_file;
}
foreach ($sites as $site) {
$parts = explode('/', $site);
$hostname = $parts[count($parts) -2];
$slugs[$site] = preg_replace('/\./', '_', $hostname);
$audit_file = $audit_dir . '/' . $hostname . '.json';
$ignore_file = $audit_dir . '/' . $hostname . '-ignore.json';
# pull in a site's ignore file
if ( file_exists($ignore_file) ) {
if ( ($ignore_json = @file_get_contents($ignore_file)) !== FALSE ) {
$ignore_json = utf8_encode($ignore_json);
$ignore = @json_decode($ignore_json, true);
if ($ignore === null) {
$ignore = array();
}
$ignores[$site] = $ignore;
}
else {
$errors[] = 'Could not open ignore file, ' . $ignore_file;
}
}
# pull in a site's audit file
if ( file_exists($audit_file) ) {
if ( ($audit_json = @file_get_contents($audit_file)) !== FALSE ) {
$audit_json = utf8_encode($audit_json);
$audit = @json_decode($audit_json, true);
if ($audit === null) {
$audit = array('data' => array());
}
ksort($audit['data']);
foreach ( array_keys($audit['data']) as $date) {
if ( is_array($audit['data'][$date]['files']) ) {
ksort($audit['data'][$date]['files']);
}
else {
$audit['data'][$date]['files'] = array();
}
foreach ( $audit['data'][$date]['files'] as $file => $action ) {
$dir = dirname($file);
if (substr($dir, -1) !== '/') {
$dir .= '/';
}
$audit['data'][$date]['files'][$file]
= array('action' => $action);
if ( isset($ignores[$site][$file]) ) {
if ( $ignores[$site][$file]['action'] == 'acknowledge' ) {
if ( $ignores[$site][$file]['date'] > $date ) {
$audit['data'][$date]['files'][$file]['status']
= 'acknowledge';
}
}
elseif ( $ignores[$site][$file]['action'] == 'ignore_file' ) {
$audit['data'][$date]['files'][$file]['status']
= 'ignore_file';
}
}
elseif ( isset($ignores[$site][$dir]['action']) ) {
$audit['data'][$date]['files'][$file]['status']
= 'ignore_dir';
}
else {
$unacked_files[] = $site . $file;
$is_script = false;
foreach ($scripts AS $script) {
if ( preg_match($script, $file) ) {
$is_script = true;
break;
}
}
if ( $is_script ) {
$unacked_scripts[] = $site . $file;
$unacked_sites[$site] = true;
}
}
}
}
$lastrun = $audit['lastrun'];
$audits[$site] = $audit;
}
else {
$errors[] = 'Could not open audit file, ' . $audit_file;
}
}
else {
$errors[] = "Audit file ($audit_file) not found";
}
$tot_changes += $audit['changes'];
$tot_scripts += $audit['scripts'];
}
#print_r($unacked_scripts);exit;
$tot_unacked_changes = count($unacked_files);
$tot_unacked_scripts = count($unacked_scripts);
$unacked_sites = array_keys($unacked_sites);
#echo('<pre>Audits: ');
#print_r($audits);
#echo('Ignores: ');
#print_r($ignores);
#echo('</pre>');
#exit;
if ( $_SERVER['HTTP_ACCEPT'] == 'application/json' || $_SERVER['CONTENT_TYPE'] == 'application/json') {
if ( $tot_unacked_scripts == 0 ) {
$message = 'OK';
}
else {
$message = 'Unacknowledged script changes in: ' . join(', ', $unacked_sites);
}
header('Content-type: application/json');
$response = array(
'sites' => $site_count,
'changes' => $tot_changes,
'scripts' => $tot_scripts,
'unacked_changes' => $tot_unacked_changes,
'unacked_scripts' => $tot_unacked_scripts,
'unacked_sites' => $unacked_sites,
'message' => $message
);
echo(json_encode($response, JSON_PRETTY_PRINT));
exit;
}
else {
$T = new Template('templates/index.php');
$T->set('errors', $errors);
$T->set('message', $message);
$T->set('sites', $sites);
$T->set('site_count', $site_count);
$T->set('slugs', $slugs);
$T->set('ignores', $ignores);
$T->set('audits', $audits);
$T->set('warn_age', $warn_age);
$T->set('scripts', $scripts);
$T->set('tot_changes', $tot_changes);
$T->set('tot_scripts', $tot_scripts);
$T->set('tot_unacked_changes', $tot_unacked_changes);
$T->set('tot_unacked_scripts', $tot_unacked_scripts);
$T->set('unacked_sites', $unacked_sites);
echo($T->fetch());
exit;
}
?>