com.newrelic.agent.security.AgentConfig Maven / Gradle / Ivy
package com.newrelic.agent.security;
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.RestrictionModeException;
import com.newrelic.agent.security.intcodeagent.exceptions.SecurityNoticeError;
import com.newrelic.agent.security.intcodeagent.filelogging.FileLoggerThreadPool;
import com.newrelic.agent.security.intcodeagent.models.collectorconfig.AgentMode;
import com.newrelic.agent.security.intcodeagent.models.collectorconfig.ScanControllers;
import com.newrelic.agent.security.intcodeagent.utils.CronExpression;
import com.newrelic.api.agent.security.Agent;
import com.newrelic.api.agent.security.schema.policy.*;
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 org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.ParseException;
import java.time.Instant;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.stream.Collectors;
import static com.newrelic.agent.security.util.IUtilConstants.*;
public class AgentConfig {
public static final String AGENT_JAR_LOCATION = "agent_jar_location";
public static final String AGENT_HOME = "agent_home";
public static final String INVALID_CRON_EXPRESSION_PROVIDED_FOR_IAST_RESTRICTED_MODE = "Invalid cron expression provided for IAST Mode";
public static final String ACCOUNT_ID_IS_REQUIRED_FOR_IAST_RESTRICTED_MODE = "Account ID is required for IAST Restricted Mode";
public static final String ACCOUNT_ID_LOCATION = "account_id_location";
public static final String ACCOUNT_ID_KEY = "account_id_key";
public static final String ROUTE = "route";
public static final String MAPPING_PARAMETERS_ARE_REQUIRED_FOR_IAST_RESTRICTED_MODE = "Mapping Parameters are required for IAST Restricted Mode";
public static final String DEFAULT_SCAN_SCHEDULE_EXPRESSION = "0 0 0 * * ?";
public static final String INVALID_SECURITY_CONFIGURATION_FOR_MODE_IAST_RESTRICTED = "Invalid Security Configuration for mode IAST_RESTRICTED ";
public static final String INVALID_SECURITY_CONFIGURATION = "Invalid Security Configuration ";
private static final Logger log = LoggerFactory.getLogger(AgentConfig.class);
private String NR_CSEC_HOME;
private String logLevel;
private String groupName;
private AgentMode agentMode;
private CollectorConfig config = new CollectorConfig();
private boolean isNRSecurityEnabled;
private static FileLoggerThreadPool logger;
private OSVariables osVariables;
private Map noticeErrorCustomParams = new HashMap<>();
private ScanControllers scanControllers = new ScanControllers();
private AgentConfig(){
}
public long instantiate() throws RestrictionModeException {
//Set k2 home path
boolean validHomePath = setSecurityHomePath();
if(validHomePath) {
System.out.println("New Relic Security Agent: Setting Security home path to directory: " + NR_CSEC_HOME);
}
isNRSecurityEnabled = NewRelic.getAgent().getConfig().getValue(IUtilConstants.NR_SECURITY_ENABLED, false);
// Set required Group
groupName = applyRequiredGroup();
Agent.getCustomNoticeErrorParameters().put(IUtilConstants.SECURITY_MODE, groupName);
// Enable low severity hooks
//Instantiation call please do not move or repeat this.
osVariables = OsVariablesInstance.instantiate().getOsVariables();
logger = FileLoggerThreadPool.getInstance();
//Do not repeat this task
logger.initialiseLogger();
// Set required LogLevel
logLevel = applyRequiredLogLevel();
try {
scanControllers.setScanInstanceCount(NewRelic.getAgent().getConfig().getValue(IUtilConstants.IAST_SCAN_INSTANCE_COUNT, 0));
} catch (NumberFormatException | ClassCastException e){
logger.log(LogLevel.FINEST, String.format("Error while reading IAST_SCAN_INSTANCE_COUNT %s , setting to default", NewRelic.getAgent().getConfig().getValue(IUtilConstants.IAST_SCAN_INSTANCE_COUNT)), AgentConfig.class.getName());
scanControllers.setScanInstanceCount(0);
}
//Always set IAST Test Identifier after IAST_SCAN_INSTANCE_COUNT
if(NewRelic.getAgent().getConfig().getValue(IUtilConstants.IAST_TEST_IDENTIFIER) instanceof String) {
scanControllers.setIastTestIdentifier(NewRelic.getAgent().getConfig().getValue(IUtilConstants.IAST_TEST_IDENTIFIER));
scanControllers.setScanInstanceCount(1);
} else {
scanControllers.setIastTestIdentifier(StringUtils.EMPTY);
}
instantiateAgentMode(groupName);
return triggerIAST();
}
public long triggerIAST() throws RestrictionModeException {
try {
if(agentMode.getScanSchedule().getNextScanTime() != null) {
logger.log(LogLevel.FINER, "Security Agent scan time is set to : " + agentMode.getScanSchedule().getNextScanTime(), AgentConfig.class.getName());
long delay = agentMode.getScanSchedule().getNextScanTime().getTime() - Instant.now().toEpochMilli();
return (delay > 0)? delay : 0;
}
} catch (Exception e){
RestrictionModeException restrictionModeException = new RestrictionModeException("Error while calculating next scan time for IAST Restricted Mode", e);
NewRelic.noticeError(restrictionModeException, Agent.getCustomNoticeErrorParameters(), true);
System.err.println("[NR-CSEC-JA] Error while calculating next scan time for IAST Restricted Mode. IAST Restricted Mode will be disabled.");
NewRelic.getAgent().getLogger().log(Level.WARNING, "[NR-CSEC-JA] Error while calculating next scan time for IAST Restricted Mode. IAST Restricted Mode will be disabled.");
throw restrictionModeException;
}
return 0;
}
private void instantiateAgentMode(String groupName) throws RestrictionModeException {
this.agentMode = new AgentMode(groupName);
switch (groupName){
case IAST:
readIastConfig();
break;
case RASP:
readRaspConfig();
break;
case IAST_RESTRICTED:
try {
readIastRestrictedConfig();
} catch (RestrictionModeException e) {
System.err.println("[NR-CSEC-JA] Error while reading IAST Restricted Mode Configuration. IAST Restricted Mode will be disabled.");
NewRelic.getAgent().getLogger().log(Level.WARNING, "[NR-CSEC-JA] Error while reading IAST Restricted Mode Configuration. IAST Restricted Mode will be disabled.");
NewRelic.noticeError(e, Agent.getCustomNoticeErrorParameters(), true);
AgentInfo.getInstance().agentStatTrigger(false);
throw e;
}
break;
default:
//this is default case which requires no changes
break;
}
try {
readScanSchedule();
readSkipScan();
updateSkipScanParameters();
} catch (RestrictionModeException e){
System.err.println("[NR-CSEC-JA] Error while reading IAST Scan Configuration. Security will be disabled.");
NewRelic.getAgent().getLogger().log(Level.WARNING, "[NR-CSEC-JA] Error while reading IAST Scan Configuration. Security will be disabled. Message : {0}", e.getMessage());
NewRelic.noticeError(e, Agent.getCustomNoticeErrorParameters(), true);
AgentInfo.getInstance().agentStatTrigger(false);
throw e;
}
logger.log(LogLevel.INFO, String.format("Security Agent Modes and Config : %s", agentMode), AgentConfig.class.getName());
}
private void readSkipScan() throws RestrictionModeException {
try {
agentMode.getSkipScan().setApis(NewRelic.getAgent().getConfig().getValue(SKIP_IAST_SCAN_API, Collections.emptyList()));
agentMode.getSkipScan().getParameters().setQuery(NewRelic.getAgent().getConfig().getValue(SKIP_IAST_SCAN_PARAMETERS_QUERY, Collections.emptyList()).stream()
.map(Object::toString)
.collect(Collectors.toList()));
agentMode.getSkipScan().getParameters().setHeader(NewRelic.getAgent().getConfig().getValue(SKIP_IAST_SCAN_PARAMETERS_HEADER, Collections.emptyList()).stream()
.map(Object::toString)
.collect(Collectors.toList()));
agentMode.getSkipScan().getParameters().setBody(NewRelic.getAgent().getConfig().getValue(SKIP_IAST_SCAN_PARAMETERS_BODY, Collections.emptyList()).stream()
.map(Object::toString)
.collect(Collectors.toList()));
agentMode.getSkipScan().getIastDetectionCategory().setInsecureSettingsEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_INSECURE_SETTINGS, false));
agentMode.getSkipScan().getIastDetectionCategory().setInvalidFileAccessEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_INVALID_FILE_ACCESS, false));
agentMode.getSkipScan().getIastDetectionCategory().setSqlInjectionEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_SQL_INJECTION, false));
agentMode.getSkipScan().getIastDetectionCategory().setNoSqlInjectionEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_NOSQL_INJECTION, false));
agentMode.getSkipScan().getIastDetectionCategory().setLdapInjectionEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_LDAP_INJECTION, false));
agentMode.getSkipScan().getIastDetectionCategory().setJavascriptInjectionEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_JAVASCRIPT_INJECTION, false));
agentMode.getSkipScan().getIastDetectionCategory().setCommandInjectionEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_COMMAND_INJECTION, false));
agentMode.getSkipScan().getIastDetectionCategory().setXpathInjectionEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_XPATH_INJECTION, false));
agentMode.getSkipScan().getIastDetectionCategory().setSsrfEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_SSRF, false));
agentMode.getSkipScan().getIastDetectionCategory().setRxssEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_RXSS, false));
agentMode.getSkipScan().getIastDetectionCategory().generateDisabledCategoriesCSV();
} catch (ClassCastException | NumberFormatException e){
throw new RestrictionModeException(INVALID_SECURITY_CONFIGURATION + e.getMessage(), e);
}
}
private void readScanSchedule() throws RestrictionModeException {
try {
agentMode.getScanSchedule().setDelay(NewRelic.getAgent().getConfig().getValue(SCAN_TIME_DELAY, 0));
agentMode.getScanSchedule().setDuration(NewRelic.getAgent().getConfig().getValue(SCAN_TIME_DURATION, 0));
agentMode.getScanSchedule().setSchedule(NewRelic.getAgent().getConfig().getValue(SCAN_TIME_SCHEDULE, StringUtils.EMPTY));
agentMode.getScanSchedule().setCollectSamples(NewRelic.getAgent().getConfig().getValue(SCAN_TIME_COLLECT_SAMPLES, false));
if (agentMode.getScanSchedule().getDelay() > 0) {
agentMode.getScanSchedule().setNextScanTime(new Date(Instant.now().toEpochMilli() + TimeUnit.MINUTES.toMillis(agentMode.getScanSchedule().getDelay())));
} else if (StringUtils.isNotBlank(agentMode.getScanSchedule().getSchedule())) {
agentMode.getScanSchedule().setScheduleOnce(false);
if (CronExpression.isValidExpression(agentMode.getScanSchedule().getSchedule())) {
try {
agentMode.getScanSchedule().setNextScanTime(new CronExpression(agentMode.getScanSchedule().getSchedule()).getTimeAfter(new Date()));
} catch (ParseException e) {
throw new RestrictionModeException(INVALID_CRON_EXPRESSION_PROVIDED_FOR_IAST_RESTRICTED_MODE, e);
}
} else {
throw new RestrictionModeException(INVALID_CRON_EXPRESSION_PROVIDED_FOR_IAST_RESTRICTED_MODE);
}
} else {
agentMode.getScanSchedule().setNextScanTime(new Date(Instant.now().toEpochMilli()));
}
agentMode.getScanSchedule().setDataCollectionTime(agentMode.getScanSchedule().getNextScanTime());
if(agentMode.getScanSchedule().isCollectSamples()){
agentMode.getScanSchedule().setNextScanTime(new Date(Instant.now().toEpochMilli()));
}
} catch (ClassCastException | NumberFormatException e){
throw new RestrictionModeException(INVALID_SECURITY_CONFIGURATION + e.getMessage(), e);
}
}
private void updateSkipScanParameters() {
if(this.agentMode.getIastScan().getRestrictionCriteria().getMappingParameters().getBody().isEnabled()){
this.agentMode.getSkipScan().getParameters().getBody().addAll(this.agentMode.getIastScan().getRestrictionCriteria().getMappingParameters().getBody().getLocations());
}
if(this.agentMode.getIastScan().getRestrictionCriteria().getMappingParameters().getQuery().isEnabled()){
this.agentMode.getSkipScan().getParameters().getQuery().addAll(this.agentMode.getIastScan().getRestrictionCriteria().getMappingParameters().getQuery().getLocations());
}
if(this.agentMode.getIastScan().getRestrictionCriteria().getMappingParameters().getHeader().isEnabled()){
this.agentMode.getSkipScan().getParameters().getHeader().addAll(this.agentMode.getIastScan().getRestrictionCriteria().getMappingParameters().getHeader().getLocations());
}
}
private void readIastConfig() {
this.agentMode.getIastScan().setEnabled(true);
this.agentMode.getRaspScan().setEnabled(false);
}
private void readIastRestrictedConfig() throws RestrictionModeException {
try {
this.agentMode.getIastScan().setRestricted(true);
Agent.getCustomNoticeErrorParameters().put(IAST_RESTRICTED, String.valueOf(true));
RestrictionCriteria restrictionCriteria = this.agentMode.getIastScan().getRestrictionCriteria();
restrictionCriteria.setAccountInfo(new AccountInfo(NewRelic.getAgent().getConfig().getValue(RESTRICTION_CRITERIA_ACCOUNT_INFO_ACCOUNT_ID)));
if(restrictionCriteria.getAccountInfo().isEmpty()) {
throw new RestrictionModeException(ACCOUNT_ID_IS_REQUIRED_FOR_IAST_RESTRICTED_MODE);
}
//Mapping parameters
this.agentMode.getIastScan().getRestrictionCriteria().getMappingParameters().getBody().setEnabled(NewRelic.getAgent().getConfig().getValue(RESTRICTION_CRITERIA_MAPPING_PARAMETERS_BODY_ENABLED, false));
this.agentMode.getIastScan().getRestrictionCriteria().getMappingParameters().getQuery().setEnabled(NewRelic.getAgent().getConfig().getValue(RESTRICTION_CRITERIA_MAPPING_PARAMETERS_QUERY_ENABLED, false));
this.agentMode.getIastScan().getRestrictionCriteria().getMappingParameters().getHeader().setEnabled(NewRelic.getAgent().getConfig().getValue(RESTRICTION_CRITERIA_MAPPING_PARAMETERS_HEADER_ENABLED, false));
this.agentMode.getIastScan().getRestrictionCriteria().getMappingParameters().getPath().setEnabled(NewRelic.getAgent().getConfig().getValue(RESTRICTION_CRITERIA_MAPPING_PARAMETERS_PATH_ENABLED, false));
this.agentMode.getIastScan().getRestrictionCriteria().getMappingParameters().getBody().setLocations(NewRelic.getAgent().getConfig().getValue(RESTRICTION_CRITERIA_MAPPING_PARAMETERS_BODY_LOCATION, Collections.emptyList()).stream()
.map(Object::toString)
.collect(Collectors.toList()));
this.agentMode.getIastScan().getRestrictionCriteria().getMappingParameters().getQuery().setLocations(NewRelic.getAgent().getConfig().getValue(RESTRICTION_CRITERIA_MAPPING_PARAMETERS_QUERY_LOCATION, Collections.emptyList()).stream()
.map(Object::toString)
.collect(Collectors.toList()));
this.agentMode.getIastScan().getRestrictionCriteria().getMappingParameters().getHeader().setLocations(NewRelic.getAgent().getConfig().getValue(RESTRICTION_CRITERIA_MAPPING_PARAMETERS_HEADER_LOCATION, Collections.emptyList()).stream()
.map(Object::toString)
.collect(Collectors.toList()));
//Strict Criteria
List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy