/* * Copyright (C) 2021 Christian Pierre MOMON * * 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 . */ 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 */ 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); // Make a check. if (StringUtils.equals(line, anon.getLine())) { System.err.println("Anonymize failed detected: " + line); } } else { Log log = LogParser.parseErrorLog(line); anon = anonymizeError(log); } 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 = 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); } } }