logar/src/fr/devinsy/logar/app/anonymizer/Anonymizer.java

276 lines
7.8 KiB
Java

/*
* Copyright (C) 2021 Christian Pierre MOMON <christian@momon.org>
*
* This file is part of Logar, simple tool to manage http log files.
*
* Logar is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* Logar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Logar. If not, see <http://www.gnu.org/licenses/>.
*/
package fr.devinsy.logar.app.anonymizer;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.time.format.DateTimeParseException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.GZIPOutputStream;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.april.logar.util.LineIterator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.devinsy.logar.app.log.Log;
import fr.devinsy.logar.app.log.LogParser;
/**
* The Class Anonymizer.
*/
/**
* @author cpm
*
*/
public final class Anonymizer
{
private static Logger logger = LoggerFactory.getLogger(Anonymizer.class);
public static final Pattern IPV4_PATTERN = Pattern.compile("\\d{0,3}\\.\\d{0,3}\\.\\d{0,3}\\.\\d{0,3}");
public static final Pattern IPV6_PATTERN = Pattern.compile("([0-9a-f]{1,4}:{1,2}){4,7}([0-9a-f]){1,4}", Pattern.CASE_INSENSITIVE);
private AnonMap map;
/**
* Instantiates a new anonymizer.
*/
public Anonymizer()
{
this.map = new AnonMap();
}
/**
* Anonymize.
*
* @param source
* the source
* @param target
* the target
*/
public void anonymize(final File source)
{
if (source == null)
{
throw new IllegalArgumentException("Null parameter.");
}
else if (!source.isFile())
{
throw new IllegalArgumentException("Parameter is not a file.");
}
else if (!StringUtils.containsAny(source.getName(), "access", "error"))
{
throw new IllegalArgumentException("File name does not contain 'access' or 'error'.");
}
else
{
System.out.println("== Anonymize log for [" + source.getName() + "]");
boolean isAccessFile = source.getName().contains("access");
File target;
if (source.getName().endsWith(".log.gz"))
{
target = new File(source.getParentFile(), source.getName().replace(".log.gz", "-anon.log.gz"));
}
else
{
target = new File(source.getParentFile(), source.getName().replace(".log", "-anon.log"));
}
PrintWriter out = null;
try
{
LineIterator iterator = new LineIterator(source);
out = new PrintWriter(new GZIPOutputStream(new FileOutputStream(target)));
while (iterator.hasNext())
{
String line = iterator.next();
try
{
Log anon;
if (isAccessFile)
{
Log log = LogParser.parseAccessLog(line);
// logger.info("line={}", line);
// logger.info("log =[{}][{}][{}]", log.getIp(),
// log.getUser(), log.getDatetime());
anon = anonymizeAccess(log);
// logger.info("anon=[{}][{}][{}]", anon.getIp(),
// anon.getUser(), anon.getDatetime());
// logger.info("anon={}", anon);
}
else
{
Log log = LogParser.parseErrorLog(line);
anon = anonymizeError(log);
}
// Make a check.
if (StringUtils.equals(line, anon.getLine()))
{
System.err.println("Anonymize failed detected: " + line);
}
out.println(anon);
}
catch (IllegalArgumentException exception)
{
System.out.println("Bad format line: " + line);
exception.printStackTrace();
}
catch (DateTimeParseException exception)
{
System.out.println("Bad datetime format: " + line);
}
}
}
catch (IOException exception)
{
System.err.println("Error with file [" + source.getAbsolutePath() + "]");
exception.printStackTrace();
}
finally
{
IOUtils.closeQuietly(out);
}
}
}
/**
* Anonymize.
*
* @param log
* the log
* @return the log
*/
public Log anonymizeAccess(final Log log)
{
Log result;
//
String anonIp = this.map.anonymizeIp(log.getIp());
String line = log.getLine().replace(log.getIp(), anonIp);
//
if (!StringUtils.equals(log.getUser(), "-"))
{
String anonUser = this.map.anonymizeUser(log.getUser());
line.replaceFirst(" " + log.getUser(), anonUser);
}
//
result = new Log(line, log.getDatetime());
//
return result;
}
/**
* Anonymize error.
*
* @param log
* the log
* @return the log
*/
public Log anonymizeError(final Log log)
{
Log result;
// Search and anonymized Ipv4 addresses.
Matcher matcher = IPV4_PATTERN.matcher(log.getLine());
String anonLine = log.getLine();
while (matcher.find())
{
String left = anonLine.substring(0, matcher.start());
String ipv4 = matcher.group();
String right = anonLine.substring(matcher.end());
String anonIpv4 = this.map.get(ipv4);
anonLine = left + anonIpv4 + right;
}
// Search and anonymized Ipv4 addresses.
matcher = IPV6_PATTERN.matcher(anonLine);
while (matcher.find())
{
String left = anonLine.substring(0, matcher.start());
String ipv6 = matcher.group();
String right = anonLine.substring(matcher.end());
String anonIpv6 = this.map.get(ipv6);
anonLine = left + anonIpv6 + right;
}
result = new Log(anonLine, log.getDatetime());
//
return result;
}
/**
* Gets the map table.
*
* @return the map table
*/
public AnonMap getMapTable()
{
AnonMap result;
result = this.map;
//
return result;
}
/**
* Inits the map.
*
* @param source
* the source
*/
public void loadMapTable(final File source)
{
if (source != null)
{
this.map.addAll(AnonMapFile.load(source));
}
}
/**
* Save map table.
*
* @param target
* the target
*/
public void SaveMapTable(final File target)
{
if (target != null)
{
AnonMapFile.save(target, this.map);
}
}
}