Skip to content
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

Remove home directory mandate for IAST initailisation #313

Merged
merged 13 commits into from
Aug 12, 2024
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
import com.newrelic.agent.security.instrumentator.os.OSVariables;
import com.newrelic.agent.security.instrumentator.os.OsVariablesInstance;
import com.newrelic.agent.security.instrumentator.utils.AgentUtils;
import com.newrelic.agent.security.intcodeagent.exceptions.SecurityNoticeError;
import com.newrelic.agent.security.intcodeagent.filelogging.FileLoggerThreadPool;
import com.newrelic.api.agent.security.utils.logging.LogLevel;
import com.newrelic.agent.security.intcodeagent.filelogging.LogWriter;
import com.newrelic.agent.security.intcodeagent.models.collectorconfig.CollectorConfig;
import com.newrelic.agent.security.intcodeagent.utils.CommonUtils;
import com.newrelic.agent.security.util.IUtilConstants;
import com.newrelic.api.agent.NewRelic;
import com.newrelic.api.agent.security.instrumentation.helpers.LowSeverityHelper;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.comparator.LastModifiedFileComparator;
import org.apache.commons.io.filefilter.FileFilterUtils;
Expand All @@ -23,6 +23,8 @@
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import static com.newrelic.agent.security.util.IUtilConstants.DIRECTORY_PERMISSION;

Expand All @@ -46,28 +48,24 @@ public class AgentConfig {

private OSVariables osVariables;

private Map<String, String> noticeErrorCustomParams = new HashMap<>();

private AgentConfig(){
}

public void instantiate(){
//Set k2 home path
try {
boolean validHomePath = setK2HomePath();
System.out.println("New Relic Security Agent: Setting csec home path to directory:"+NR_CSEC_HOME);
} catch (IOException e) {
String tmpDir = System.getProperty("java.io.tmpdir");
System.err.println("[NR-CSEC-JA] "+e.getMessage()+" Please find the error in " + tmpDir + File.separator + "NR-CSEC-Logger.err");
throw new RuntimeException("CSEC Agent Exiting!!! Unable to create csec home directory", e);
boolean validHomePath = setSecurityHomePath();
if(validHomePath) {
System.out.println("New Relic Security Agent: Setting csec home path to directory: " + NR_CSEC_HOME);
}
isNRSecurityEnabled = NewRelic.getAgent().getConfig().getValue(IUtilConstants.NR_SECURITY_ENABLED, false);
// Set required Group
groupName = applyRequiredGroup();
// Enable low severity hooks
// Set required LogLevel
logLevel = applyRequiredLogLevel();

//Instantiation call please do not move or repeat this.
osVariables = OsVariablesInstance.instantiate().getOsVariables();
// Set required LogLevel
logLevel = applyRequiredLogLevel();
}

private static final class InstanceHolder {
Expand Down Expand Up @@ -103,48 +101,59 @@ private String applyRequiredLogLevel() {
return logLevel;
}

public boolean setK2HomePath() throws IOException {
String agentJarLocation = NewRelic.getAgent().getConfig().getValue(AGENT_JAR_LOCATION);
if (NewRelic.getAgent().getConfig().getValue(AGENT_HOME) != null) {
public boolean setSecurityHomePath(){
noticeErrorCustomParams.put(IUtilConstants.LOG_FILE_PATH, NewRelic.getAgent().getConfig().getValue(IUtilConstants.LOG_FILE_PATH));
noticeErrorCustomParams.put(AGENT_JAR_LOCATION, NewRelic.getAgent().getConfig().getValue(AGENT_JAR_LOCATION));
noticeErrorCustomParams.put(AGENT_HOME, NewRelic.getAgent().getConfig().getValue(AGENT_HOME));
if(NewRelic.getAgent().getConfig().getValue(IUtilConstants.LOG_FILE_PATH) != null) {
NR_CSEC_HOME = NewRelic.getAgent().getConfig().getValue(IUtilConstants.LOG_FILE_PATH);
} else if (NewRelic.getAgent().getConfig().getValue(AGENT_JAR_LOCATION) != null) {
NR_CSEC_HOME = NewRelic.getAgent().getConfig().getValue(AGENT_JAR_LOCATION);
} else if (NewRelic.getAgent().getConfig().getValue(AGENT_HOME) != null) {
//system property `newrelic.home` or environment variable `NEWRELIC_HOME`
NR_CSEC_HOME = NewRelic.getAgent().getConfig().getValue(AGENT_HOME);
} else if (StringUtils.isNotBlank(agentJarLocation)){
//fallback to agent_jar_location as home
NR_CSEC_HOME = agentJarLocation;
} else {
System.err.println("[NR-CSEC-JA] Missing or Incorrect system property `newrelic.home` or environment variable `NEWRELIC_HOME`. Collector exiting.");
NewRelic.noticeError(new SecurityNoticeError("CSEC home directory creation failed, reason directory not found. Please check the agent configs"), noticeErrorCustomParams, true);
System.err.println("[NR-CSEC-JA] CSEC home directory not found. Please check the agent configs or system property `newrelic.home` or environment variable `NEWRELIC_HOME`.");
return false;
}
Path k2homePath = Paths.get(NR_CSEC_HOME, IUtilConstants.NR_SECURITY_HOME);
if(!CommonUtils.forceMkdirs(k2homePath, DIRECTORY_PERMISSION)){
System.err.println(String.format("[NR-CSEC-JA] CSEC home directory creation failed at %s", NR_CSEC_HOME));
Path SecurityhomePath = Paths.get(NR_CSEC_HOME, IUtilConstants.NR_SECURITY_HOME);
NR_CSEC_HOME = SecurityhomePath.toString();
try {
noticeErrorCustomParams.put("CSEC_HOME", SecurityhomePath.toString());
if(!CommonUtils.forceMkdirs(SecurityhomePath, DIRECTORY_PERMISSION)){
NewRelic.noticeError(String.format("CSEC home directory creation failed, reason : %s", NR_CSEC_HOME), noticeErrorCustomParams, true);
System.err.printf("[NR-CSEC-JA] CSEC home directory creation failed at %s%n", NR_CSEC_HOME);
return false;
}
} catch (IOException e) {
NewRelic.noticeError(new SecurityNoticeError(String.format("CSEC home directory creation failed, reason %s. Please check the agent configs", e.getMessage()), e), noticeErrorCustomParams, true);
return false;
}
NR_CSEC_HOME = k2homePath.toString();
AgentUtils.getInstance().getStatusLogValues().put("csec-home", NR_CSEC_HOME);
AgentUtils.getInstance().getStatusLogValues().put("csec-home-permissions", String.valueOf(k2homePath.toFile().canWrite() && k2homePath.toFile().canRead()));
AgentUtils.getInstance().getStatusLogValues().put("agent-location", agentJarLocation);
if (!isValidK2HomePath(NR_CSEC_HOME)) {
System.err.println("[NR-CSEC-JA] Incomplete startup env parameters provided : Missing or Incorrect 'newrelic.home'. Collector exiting.");
return false;
}
return true;
AgentUtils.getInstance().getStatusLogValues().put("csec-home-permissions", String.valueOf(SecurityhomePath.toFile().canWrite() && SecurityhomePath.toFile().canRead()));
AgentUtils.getInstance().getStatusLogValues().put("agent-location", NewRelic.getAgent().getConfig().getValue(AGENT_JAR_LOCATION));
return isValidSecurityHomePath(NR_CSEC_HOME);
}

private static boolean isValidK2HomePath(String k2Home) {
if (StringUtils.isNotBlank(k2Home) && Paths.get(k2Home).toFile().isDirectory()) {
private boolean isValidSecurityHomePath(String securityHome) {
if (StringUtils.isNotBlank(securityHome) && Paths.get(securityHome).toFile().isDirectory()) {
long avail = 0;
try {
avail = Files.getFileStore(Paths.get(k2Home)).getUsableSpace();
avail = Files.getFileStore(Paths.get(securityHome)).getUsableSpace();
} catch (Exception e) {
return true;
}

if (avail > FileUtils.ONE_GB) {
return true;
}
System.err.println(String.format("[NR-CSEC-JA] Insufficient disk space available to the location %s is : %s", k2Home, FileUtils.byteCountToDisplaySize(avail)));
noticeErrorCustomParams.put("CSEC_HOME_DISK_AVL_BYTES", String.valueOf(avail));
NewRelic.noticeError("CSEC home directory creation failed, reason : Insufficient disk space available to the location " + securityHome + " is : " + FileUtils.byteCountToDisplaySize(avail), noticeErrorCustomParams, true);
System.err.println(String.format("[NR-CSEC-JA] Insufficient disk space available to the location %s is : %s", securityHome, FileUtils.byteCountToDisplaySize(avail)));
return false;
}
NewRelic.noticeError("CSEC home directory creation failed, reason : CSEC home directory not found :"+securityHome, noticeErrorCustomParams, true);
return false;
}

Expand Down Expand Up @@ -204,7 +213,7 @@ public void setNRSecurityEnabled(boolean NRSecurityEnabled) {
isNRSecurityEnabled = NRSecurityEnabled;
}

public String getK2Home() {
public String getSecurityHome() {
return NR_CSEC_HOME;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
import com.newrelic.agent.security.AgentConfig;
import com.newrelic.agent.security.AgentInfo;
import com.newrelic.agent.security.intcodeagent.logging.IAgentConstants;
import com.newrelic.agent.security.util.IUtilConstants;
import com.newrelic.api.agent.NewRelic;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.SystemUtils;

import java.io.File;
Expand All @@ -18,8 +17,6 @@ public class OsVariablesInstance {
public static final String TMP = "tmp";
public static final String SNAPSHOTS = "snapshots";

public static final String LOG_FILE_PATH = "log_file_path";

private static OsVariablesInstance instance;

private final static Object lock = new Object();
Expand All @@ -28,26 +25,11 @@ public class OsVariablesInstance {

private OsVariablesInstance() {
osVariables = new OSVariables();
/*Path k2root = Paths.get(AgentInfo.getInstance().getK2Home(), K_2_ROOT);
if (!k2root.toFile().isDirectory()) {
k2root.toFile().mkdir();
}

try {
Files.setPosixFilePermissions(k2root, PosixFilePermissions.fromString("rwxrwxrwx"));
} catch (Exception e) {
}*/

// osVariables.setK2RootDir(k2root.toString());
// osVariables.setLogDirectory(Paths.get(k2root.toString(), LOGS, LANGUAGE_AGENT, AgentInfo.getInstance().getApplicationUUID()).toString());


if(NewRelic.getAgent().getConfig().getValue(LOG_FILE_PATH) != null) {
osVariables.setLogDirectory(Paths.get(NewRelic.getAgent().getConfig().getValue(LOG_FILE_PATH), IUtilConstants.NR_SECURITY_HOME, LOGS).toString());
} else {
osVariables.setLogDirectory(Paths.get(AgentConfig.getInstance().getK2Home(), LOGS).toString());
if(StringUtils.isNotBlank(AgentConfig.getInstance().getSecurityHome())) {
osVariables.setLogDirectory(Paths.get(AgentConfig.getInstance().getSecurityHome(), LOGS).toString());
osVariables.setTmpDirectory(Paths.get(AgentConfig.getInstance().getSecurityHome(), TMP, LANGUAGE_AGENT, AgentInfo.getInstance().getApplicationUUID()).toString());
}
osVariables.setTmpDirectory(Paths.get(AgentConfig.getInstance().getK2Home(), TMP, LANGUAGE_AGENT, AgentInfo.getInstance().getApplicationUUID()).toString());
osVariables.setSnapshotDir(Paths.get(osVariables.getLogDirectory(), SNAPSHOTS).toString());
// osVariables.setPolicyConfigPath(Paths.get(k2root.toString(), CONFIG, LANGUAGE_AGENT).toString());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import com.newrelic.agent.security.intcodeagent.websocket.WSClient;
import com.newrelic.agent.security.intcodeagent.websocket.WSReconnectionST;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.util.concurrent.TimeUnit;
Expand Down Expand Up @@ -74,7 +75,9 @@ public static void shutdownLogic(boolean doResetInstrumentation) {
ControlCommandProcessorThreadPool.shutDownPool();
EventSendPool.shutDownPool();
WSReconnectionST.shutDownPool();
FileUtils.deleteQuietly(new File(OsVariablesInstance.getInstance().getOsVariables().getTmpDirectory()));
if(StringUtils.isNotBlank(OsVariablesInstance.getInstance().getOsVariables().getTmpDirectory())) {
FileUtils.deleteQuietly(new File(OsVariablesInstance.getInstance().getOsVariables().getTmpDirectory()));
}

} catch (Throwable e) {
logger.log(LogLevel.SEVERE, "Error while shutting down executor pools : ", e,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.newrelic.agent.security.intcodeagent.exceptions;

public class SecurityNoticeError extends Exception {

public SecurityNoticeError(){
super();
}

public SecurityNoticeError(String message) {
super(message);
}

public SecurityNoticeError(String message, Throwable cause) {
super(message, cause);
}

public SecurityNoticeError(Throwable cause) {
super(cause);
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package com.newrelic.agent.security.intcodeagent.filelogging;

import com.newrelic.agent.security.AgentInfo;
import com.newrelic.agent.security.instrumentator.os.OSVariables;
import com.newrelic.agent.security.instrumentator.os.OsVariablesInstance;
import com.newrelic.agent.security.instrumentator.utils.AgentUtils;
import com.newrelic.agent.security.intcodeagent.models.javaagent.LogMessage;
import com.newrelic.agent.security.intcodeagent.properties.K2JALogProperties;
import com.newrelic.agent.security.intcodeagent.websocket.EventSendPool;
import com.newrelic.agent.security.intcodeagent.websocket.JsonConverter;
import com.newrelic.api.agent.security.utils.logging.LogLevel;
import org.apache.commons.lang3.StringUtils;

import java.io.IOException;
import java.util.concurrent.*;
Expand All @@ -26,6 +29,8 @@ public class FileLoggerThreadPool {

protected boolean isLoggingToStdOut = false;

private static OSVariables osVariables = OsVariablesInstance.getInstance().getOsVariables();

private FileLoggerThreadPool() throws IOException {
// load the settings
int queueSize = 15000;
Expand All @@ -36,6 +41,19 @@ private FileLoggerThreadPool() throws IOException {
maxfilesize = LogFileHelper.logFileLimit()*1024;

TimeUnit timeUnit = TimeUnit.SECONDS;
try {
if(LogFileHelper.isLoggingToStdOut()){
this.isLoggingToStdOut = true;
}
} catch (NumberFormatException e){}

if(!isLoggingToStdOut && StringUtils.isNotBlank(osVariables.getLogDirectory())) {
isLoggingActive = false;
isInitLoggingActive = false;
return;
}



boolean allowCoreThreadTimeOut = false;
executor = new ThreadPoolExecutor(corePoolSize, maxPoolSize, keepAliveTime, timeUnit,
Expand All @@ -62,11 +80,6 @@ public Thread newThread(Runnable r) {
return t;
}
});
try {
if(LogFileHelper.isLoggingToStdOut()){
this.isLoggingToStdOut = true;
}
} catch (NumberFormatException e){}

}

Expand Down Expand Up @@ -122,22 +135,22 @@ public static FileLoggerThreadPool getInstance() {
}

public void log(LogLevel logLevel, String event, String logSourceClassName) {
if (logLevel.getLevel() == 1 || logLevel.getLevel() > LogWriter.defaultLogLevel) {
if (!isLoggingActive || logLevel.getLevel() == 1 || logLevel.getLevel() > LogWriter.defaultLogLevel) {
return;
}
executor.submit(new LogWriter(logLevel, event, logSourceClassName, Thread.currentThread().getName()));
}

public void log(LogLevel logLevel, String event, Throwable throwableEvent, String logSourceClassName) {
if (logLevel.getLevel() == 1 || logLevel.getLevel() > LogWriter.defaultLogLevel) {
if (!isLoggingActive ||logLevel.getLevel() == 1 || logLevel.getLevel() > LogWriter.defaultLogLevel) {
return;
}
executor.submit(new LogWriter(logLevel, event, throwableEvent, logSourceClassName, Thread.currentThread().getName()));
}

public void logInit(LogLevel logLevel, String event, String logSourceClassName) {
postLogMessage(logLevel, event, null, logSourceClassName);
if (logLevel.getLevel() == 1 || logLevel.getLevel() > InitLogWriter.defaultLogLevel) {
if (!isInitLoggingActive || logLevel.getLevel() == 1 || logLevel.getLevel() > InitLogWriter.defaultLogLevel) {
return;
}
if(!isLoggingToStdOut) {
Expand All @@ -148,7 +161,7 @@ public void logInit(LogLevel logLevel, String event, String logSourceClassName)

public void logInit(LogLevel logLevel, String event, Throwable throwableEvent, String logSourceClassName) {
postLogMessage(logLevel, event, throwableEvent, logSourceClassName);
if (logLevel.getLevel() == 1 || logLevel.getLevel() > InitLogWriter.defaultLogLevel) {
if (!isInitLoggingActive || logLevel.getLevel() == 1 || logLevel.getLevel() > InitLogWriter.defaultLogLevel) {
return;
}
if(!isLoggingToStdOut) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,7 @@ public class InitLogWriter implements Runnable {
fileName = new File(osVariables.getLogDirectory(), "java-security-collector-init.log").getAbsolutePath();
currentLogFile = new File(fileName);
currentLogFileName = fileName;
if(!createLogFile()) {
osVariables.setLogDirectory(Paths.get(AgentConfig.getInstance().getK2Home(), LOGS).toString());
fileName = new File(osVariables.getLogDirectory(), "java-security-collector-init.log").getAbsolutePath();
currentLogFile = new File(fileName);
currentLogFileName = fileName;
createLogFile();
}

createLogFile();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,14 +103,7 @@ private static boolean createLogFile() {
fileName = new File(osVariables.getLogDirectory(), "java-security-collector.log").getAbsolutePath();
currentLogFile = new File(fileName);
currentLogFileName = fileName;
if(!createLogFile()) {
osVariables.setLogDirectory(Paths.get(AgentConfig.getInstance().getK2Home(), LOGS).toString());
fileName = new File(osVariables.getLogDirectory(), "java-security-collector.log").getAbsolutePath();
currentLogFile = new File(fileName);
currentLogFileName = fileName;
createLogFile();
}

createLogFile();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.AgeFileFilter;
import org.apache.commons.io.filefilter.DirectoryFileFilter;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.io.IOException;
Expand All @@ -33,6 +34,9 @@ public class FileCleaner {
public void run() {
long delay = Instant.now().toEpochMilli() - TimeUnit.MINUTES.toMillis(2);
logger.log(LogLevel.INFO, FILE_CLEANER_INVOKED_INITIATING_TEMP_FILE_DIRECTORY_CLEANUP, FileCleaner.class.getName());
if(StringUtils.isBlank(osVariables.getTmpDirectory())) {
return;
}
FileUtils.iterateFiles(new File(osVariables.getTmpDirectory()), new AgeFileFilter(delay), DirectoryFileFilter.INSTANCE).forEachRemaining( file -> {
FileUtils.deleteQuietly(file);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public interface IUtilConstants {
String NR_SECURITY_CA_BUNDLE_PATH = "security.ca_bundle_path";
String NR_CSEC_DEBUG_LOGFILE_SIZE = "NR_CSEC_DEBUG_LOGFILE_SIZE";
String NR_CSEC_DEBUG_LOGFILE_MAX_COUNT = "NR_CSEC_DEBUG_LOGFILE_MAX_COUNT";
String LOG_FILE_PATH = "log_file_path";
String NR_SECURITY_HOME = "nr-security-home";
String PROCESSED = "PROCESSED";
String ERROR = "ERROR";
Expand Down
Loading
Loading