package org.cagrid.gaards.authentication.service; import gov.nih.nci.security.authentication.BetterLockoutManager; import gov.nih.nci.security.authentication.LockoutManager; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.HashSet; import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.commons.vfs2.FileChangeEvent; import org.apache.commons.vfs2.FileListener; import org.apache.commons.vfs2.FileObject; import org.apache.commons.vfs2.FileSystemManager; import org.apache.commons.vfs2.VFS; import org.apache.commons.vfs2.impl.DefaultFileMonitor; /** * WhitelistUpdater Tool to listen for changes to the whitelist file and update * the lockout manager accordingly * * @author ervin */ public class WhitelistUpdater { private static Log LOG = LogFactory.getLog(WhitelistUpdater.class); private File monitoredDirectory = null; private String monitoredFilename = null; private Set<String> previousWhitelist = null; public static void monitorWhitelist(String whitelistFile) throws Exception { WhitelistUpdater updater = new WhitelistUpdater(whitelistFile); updater.startMonitoring(); } private WhitelistUpdater(String whitelistFilename) { File file = new File(whitelistFilename); this.monitoredDirectory = file.getParentFile(); this.monitoredFilename = file.getName(); LOG.debug("Monitoring for changes to " + monitoredFilename + " in directory " + monitoredDirectory); this.previousWhitelist = new HashSet<String>(); } public void startMonitoring() throws Exception { FileSystemManager fsManager = VFS.getManager(); FileObject listendir = fsManager.resolveFile(monitoredDirectory.getAbsolutePath()); FileListener listener = new FileListener() { @Override public void fileDeleted(FileChangeEvent event) throws Exception { // verify the filename is the one we're interested in String filename = event.getFile().getName().getBaseName(); if (monitoredFilename.equals(filename)) { LOG.info("Whitelist file " + monitoredFilename + " was deleted. Purging whitelist"); BetterLockoutManager lockoutManager = LockoutManager.getInstance().getDelegatedLockoutManager(); synchronized (previousWhitelist) { // delist all previously known whitelisted users // doing this rather than a blanket removal of every ID in the whitelist // preserves any IDs that might have been added by other mechanisms // than the whitelist file. for (String whitelistedUser : previousWhitelist) { lockoutManager.unWhitelistUser(whitelistedUser); } previousWhitelist.clear(); } } else { LOG.debug("Noticed the file " + filename + " was deleted; ignoring since it's not " + monitoredFilename); } } @Override public void fileCreated(FileChangeEvent event) throws Exception { // verify the filename is the one we're interested in String filename = event.getFile().getName().getBaseName(); if (monitoredFilename.equals(filename)) { LOG.info("Whitelist file " + monitoredFilename + " was created. Loading whitelist"); BetterLockoutManager lockoutManager = LockoutManager.getInstance().getDelegatedLockoutManager(); synchronized (previousWhitelist) { try { File whitelistFile = new File(event.getFile().getName().getPathDecoded()); BufferedReader reader = new BufferedReader(new FileReader(whitelistFile)); String userId = null; while ((userId = reader.readLine()) != null) { userId = userId.trim(); LOG.debug("Found " + userId + " in the whitelist"); lockoutManager.whitelistUser(userId); previousWhitelist.add(userId); } } catch (IOException ex) { LOG.error("Error reading whitelist: " + ex.getMessage(), ex); LOG.error("Suggest deleting the whitelist file to purge, and recreating the list"); } } } else { LOG.debug("Noticed the file " + filename + " was created; ignoring since it's not " + monitoredFilename); } } @Override public void fileChanged(FileChangeEvent event) throws Exception { // verify the filename is the one we're interested in String filename = event.getFile().getName().getBaseName(); if (monitoredFilename.equals(filename)) { LOG.info("Whitelist file " + monitoredFilename + " was changed. Loading whitelist"); BetterLockoutManager lockoutManager = LockoutManager.getInstance().getDelegatedLockoutManager(); synchronized (previousWhitelist) { try { File whitelistFile = new File(event.getFile().getName().getPathDecoded()); BufferedReader reader = new BufferedReader(new FileReader(whitelistFile)); Set<String> loadedWhitelist = new HashSet<String>(); String userId = null; while ((userId = reader.readLine()) != null) { userId = userId.trim(); LOG.debug("Found " + userId + " in the whitelist"); lockoutManager.whitelistUser(userId); loadedWhitelist.add(userId); } reader.close(); // remove any entries from the previous whitelist that are NOT in the loaded one previousWhitelist.removeAll(loadedWhitelist); for (String removedId : previousWhitelist) { LOG.debug("User " + removedId + " was not in the new list; removing"); lockoutManager.unWhitelistUser(removedId); } previousWhitelist.clear(); previousWhitelist.addAll(loadedWhitelist); } catch (IOException ex) { LOG.error("Error reading whitelist: " + ex.getMessage(), ex); LOG.error("Suggest deleting the whitelist file to purge, and recreating the list"); } } } else { LOG.debug("Noticed the file " + filename + " was changed; ignoring since it's not " + monitoredFilename); } } }; DefaultFileMonitor fm = new DefaultFileMonitor(listener); fm.setRecursive(true); fm.addFile(listendir); fm.start(); // if the file already exists, fire off a fake event to the listener to force-load the list FileObject whitelist = fsManager.resolveFile(monitoredDirectory, monitoredFilename); if (whitelist.exists()) { listener.fileCreated(new FileChangeEvent(whitelist)); } } public static void main(String[] args) { try { WhitelistUpdater.monitorWhitelist("etc/lockout-whitelist.txt"); String waitForIt = new BufferedReader(new InputStreamReader(System.in)).readLine(); System.out.println(waitForIt); } catch (Exception ex) { ex.printStackTrace(); } } }