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

Changes for NR CSEC module support #1222

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
7b240aa
Changes required for K2 JC init.
harshit-ap Apr 19, 2022
33807bf
Changes required for K2 JC init : Append to System Class path
harshit-ap Apr 19, 2022
52509cd
Log message inside newrelic logfile regarding invoke of K2.
harshit-ap May 3, 2022
1136ff3
New getGuid() API for NR Transaction
harshit-ap Sep 26, 2022
93302a8
Expose agent_run_id in config
lovesh-ap Oct 14, 2022
a1e2a18
Revert "New getGuid() API for NR Transaction"
harshit-ap Nov 8, 2022
aa9bfc8
Making NewRelic Weaver API artifact publishable to maven
harshit-ap Nov 8, 2022
97e1b4b
Integration changes for security agent.
harshit-ap Dec 6, 2022
ea76482
Change in real Security API impl load and use
harshit-ap Dec 6, 2022
3685238
Exposing agent-bridge and agent-bridge-datastore projects to support …
harshit-ap Dec 19, 2022
e0ae9e5
Exposing account_id config attrib via AgentConfig.
harshit-ap Jan 19, 2023
c49b887
Force reload NewRelicSecurity class after placing ClassTransformer.
harshit-ap Jan 23, 2023
bc91e85
Making CSEC collector version configurable via gradle.properties.
harshit-ap Feb 2, 2023
87cd0f9
Loading CSEC instrumentations after local agent config is read & secu…
harshit-ap Feb 9, 2023
0ddba3e
Changed CSEC component version to 1.0.0-SNAPSHOT
harshit-ap Feb 10, 2023
b90d4cd
Remove temporary weave violation printing
harshit-ap Feb 10, 2023
7a7fb4a
Added CSEC required class_transformer excludes.
harshit-ap Feb 13, 2023
45df669
Added option to provide release version suffix.
harshit-ap Feb 14, 2023
1982336
Added CSEC required class_transformer excludes.
harshit-ap Feb 14, 2023
211f810
Added CSEC required class_transformer excludes.
harshit-ap Feb 14, 2023
13d926e
Disable NR security module if security.enable is missing from config
lovesh-ap Feb 21, 2023
13bb23a
Passing instrumentation ref to CSEC
harshit-ap Mar 2, 2023
e8c660d
Merge branch 'origin-main' into v2/nr/instrumentation-changes
harshit-ap Mar 2, 2023
1a82ea4
Update newrelic.yml with security configs
lovesh-ap Mar 9, 2023
8f7a616
[UPDATE] update security config JIRA tracker : NR-96986
lovesh-ap Mar 10, 2023
7ddc989
Allow exposing Weaver to be used via maven local
harshit-ap Mar 10, 2023
901f7fd
Added agent_home and agent_jar_location to agent config.
harshit-ap Mar 10, 2023
b397eb0
Change CSEC module version to 1.0.1
harshit-ap Mar 24, 2023
419b487
[FIX] NR-93687, add excludes of Specific InputStream classes, invoke …
lovesh-ap Apr 6, 2023
433c907
[FIX] NR-105675, fix required jboss adjustments for com.nr.instrument…
lovesh-ap Apr 11, 2023
cd9bb51
Added agent_home and agent_jar_location to agent config.
harshit-ap Apr 12, 2023
128c392
Merge branch 'oss-k2-main' into oss-k2-v2/nr/instrumentation-changes
harshit-ap Apr 25, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions agent-bridge-datastore/build.gradle
Original file line number Diff line number Diff line change
@@ -1,3 +1,43 @@
import com.nr.builder.publish.PublishConfig

plugins {
id("maven-publish")
id("signing")
}

jar {
from("$rootDir/LICENSE")
manifest {
attributes 'Implementation-Title': 'New Relic Bridge DataStore', 'Implementation-Version': project.version
}
}

java {
withSourcesJar()
withJavadocJar()
}

tasks.withType(GenerateModuleMetadata.class) {
enabled = false
}


tasks.withType(Javadoc).configureEach {
javadocTool = javaToolchains.javadocToolFor {
languageVersion = JavaLanguageVersion.of(11)
}

options.addBooleanOption("-frames", true)
options.addBooleanOption("-no-module-directories", true)
}

PublishConfig.config(
project,
"New Relic Java Bridge",
"Bridge DataStore") { it ->
it.from(components.java)
}

dependencies {
implementation(project(":newrelic-api"))
implementation(project(":newrelic-weaver-api"))
Expand Down
40 changes: 40 additions & 0 deletions agent-bridge/build.gradle
Original file line number Diff line number Diff line change
@@ -1,3 +1,43 @@
import com.nr.builder.publish.PublishConfig

plugins {
id("maven-publish")
id("signing")
}

jar {
from("$rootDir/LICENSE")
manifest {
attributes 'Implementation-Title': 'New Relic Bridge', 'Implementation-Version': project.version
}
}

java {
withSourcesJar()
withJavadocJar()
}

tasks.withType(GenerateModuleMetadata.class) {
enabled = false
}


tasks.withType(Javadoc).configureEach {
javadocTool = javaToolchains.javadocToolFor {
languageVersion = JavaLanguageVersion.of(11)
}

options.addBooleanOption("-frames", true)
options.addBooleanOption("-no-module-directories", true)
}

PublishConfig.config(
project,
"New Relic Java Bridge",
"Bridge") { it ->
it.from(components.java)
}

dependencies {
api(project(":newrelic-api"))
api(project(":newrelic-weaver-api"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,9 @@

package com.newrelic.agent.bridge;

import com.newrelic.api.agent.ApplicationNamePriority;
import com.newrelic.api.agent.*;
import com.newrelic.api.agent.DistributedTracePayload;
import com.newrelic.api.agent.ExtendedRequest;
import com.newrelic.api.agent.Headers;
import com.newrelic.api.agent.InboundHeaders;
import com.newrelic.api.agent.Request;
import com.newrelic.api.agent.Response;
import com.newrelic.api.agent.Segment;
import com.newrelic.api.agent.TransactionNamePriority;
import com.newrelic.api.agent.TransportType;

import java.net.URI;
import java.util.Collection;
Expand Down Expand Up @@ -318,6 +311,11 @@ public void insertDistributedTraceHeaders(Headers headers) {
public void acceptDistributedTraceHeaders(TransportType transportType, Headers headers) {
}

@Override
public Object getSecurityMetaData() {
return new Object();
}

@Override
public void setTransportType(TransportType transportType) {
}
Expand Down
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ allprojects {

group = 'com.newrelic.agent.java'
version = agentVersion + (project.findProperty("release") == "true" ? "" : "-SNAPSHOT")
version = version + (project.findProperty("release-suffix") != null ? project.findProperty("release-suffix") : "")

idea.module {
outputDir file('build/classes/main')
Expand Down
1 change: 1 addition & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# The agent version.
agentVersion=8.2.0
csecCollectorVersion=1.0.1-SNAPSHOT

newrelicDebug=false
org.gradle.jvmargs=-Xmx2048m
Expand Down
4 changes: 4 additions & 0 deletions newrelic-agent/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ plugins {

repositories {
mavenCentral()
mavenLocal()
jcenter()
}

Expand Down Expand Up @@ -59,6 +60,8 @@ dependencies {
jarIntoJar project(":agent-bridge-datastore")
jarIntoJar project(":newrelic-weaver-api")
jarIntoJar project(":newrelic-weaver-scala-api")
jarIntoJar("com.newrelic.agent.java.security:newrelic-security-api:${csecCollectorVersion}")
jarIntoJar("com.newrelic.agent.java.security:newrelic-security-agent:${csecCollectorVersion}")

shadowIntoJar project(":agent-interfaces")
shadowIntoJar project(":agent-model")
Expand Down Expand Up @@ -263,6 +266,7 @@ task newrelicVersionedAgentJar(type: Jar) {
// All projects have the same version, so we can safely remove this version from the name.
from(project.configurations.jarIntoJar) {
rename("-${project.version}", "")
rename("-${csecCollectorVersion}", "")
}

from(zipTree(project.tasks['transformedShadowJar'].archiveFile.get().asFile.path))
Expand Down
45 changes: 40 additions & 5 deletions newrelic-agent/src/main/java/com/newrelic/agent/Agent.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,7 @@

import com.google.common.collect.ImmutableMap;
import com.newrelic.agent.bridge.AgentBridge;
import com.newrelic.agent.config.AgentJarHelper;
import com.newrelic.agent.config.ConfigService;
import com.newrelic.agent.config.ConfigServiceFactory;
import com.newrelic.agent.config.JarResource;
import com.newrelic.agent.config.JavaVersionUtils;
import com.newrelic.agent.config.*;
import com.newrelic.agent.core.CoreService;
import com.newrelic.agent.core.CoreServiceImpl;
import com.newrelic.agent.logging.AgentLogManager;
Expand All @@ -27,7 +23,10 @@
import com.newrelic.agent.util.UnwindableInstrumentationImpl;
import com.newrelic.agent.util.asm.ClassStructure;
import com.newrelic.bootstrap.BootstrapAgent;
import com.newrelic.api.agent.NewRelic;
import com.newrelic.api.agent.security.NewRelicSecurity;
import com.newrelic.bootstrap.BootstrapLoader;
import com.newrelic.bootstrap.EmbeddedJarFilesImpl;
import com.newrelic.weave.utils.Streams;
import org.objectweb.asm.ClassReader;

Expand Down Expand Up @@ -227,6 +226,41 @@ public static void continuePremain(String agentArgs, Instrumentation inst, long
instrumentation.started();
}
lifecycleObserver.agentStarted();
InitialiseNewRelicSecurityIfAllowed(inst);
}

private static void InitialiseNewRelicSecurityIfAllowed(Instrumentation inst) {
// Do not initialise New Relic Security module so that it stays in NoOp mode if force disabled.
if(NewRelic.getAgent().getConfig().getValue("security.agent.enabled", true) &&
NewRelic.getAgent().getConfig().getValue("security.enabled") != null) {
try {
LOG.log(Level.INFO, "Invoking New Relic Security module");
ServiceFactory.getServiceManager().getRPMServiceManager().addConnectionListener(new ConnectionListener() {
@Override
public void connected(IRPMService rpmService, AgentConfig agentConfig) {
try {
URL securityJarURL = EmbeddedJarFilesImpl.INSTANCE.getJarFileInAgent(BootstrapLoader.NEWRELIC_SECURITY_AGENT).toURI().toURL();
LOG.log(Level.INFO, "Connected to New Relic cloud. Starting New Relic Security module");
NewRelicSecurity.getAgent().refreshState(securityJarURL, inst);
NewRelicSecurity.markAgentAsInitialised();
} catch (IOException e) {
throw new RuntimeException(e);
}
}

@Override
public void disconnected(IRPMService rpmService) {
NewRelicSecurity.getAgent().deactivateSecurity();
}
});
} catch (Throwable t2) {
// TODO : Give a generic error here.
LOG.error("license_key is empty in the config. Not starting New Relic Security Agent.");
}
} else {
LOG.warning("New Relic Security is completely disabled forcefully by user provided config `security.agent.enabled`. " +
"Not loading security capabilities.");
}
}

private static Instrumentation maybeWrapInstrumentation(Instrumentation inst) {
Expand Down Expand Up @@ -255,6 +289,7 @@ private static boolean tryToInitializeServiceManager(Instrumentation inst) {

// Now that we know the agent is enabled, add the ApiClassTransformer
BootstrapLoader.forceCorrectNewRelicApi(inst);
BootstrapLoader.forceCorrectNewRelicSecurityApi(inst);

// init problem classes before class transformer service is active
InitProblemClasses.loadInitialClasses();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
import com.newrelic.api.agent.NewRelic;
import com.newrelic.api.agent.Request;
import com.newrelic.api.agent.Response;
import com.newrelic.api.agent.security.schema.SecurityMetaData;
import org.objectweb.asm.Opcodes;

import java.lang.management.GarbageCollectorMXBean;
Expand Down Expand Up @@ -242,6 +243,8 @@ public AppNameAndConfig call() throws Exception {
// count of active tokens and tracers
private final AtomicInteger activeCount;

private final SecurityMetaData securityMetaData;

private final MetricAggregator metricAggregator = new AbstractMetricAggregator() {
@Override
protected void doRecordResponseTimeMetric(String name, long totalTime, long exclusiveTime, TimeUnit timeUnit) {
Expand Down Expand Up @@ -456,6 +459,7 @@ protected Transaction() {
runningChildren = new LazyMapImpl<>(factory);
activeTokensCache = new AtomicReference<>();
activeCount = new AtomicInteger(0);
securityMetaData = new SecurityMetaData();
}

// This method must be called after construction. This is ugly, but avoids
Expand Down Expand Up @@ -2562,4 +2566,8 @@ int getCountOfRunningAndFinishedTransactionActivities() {
return runningChildren.size() + finishedChildren.size();
}
}

public SecurityMetaData getSecurityMetaData() {
return securityMetaData;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,11 @@
import com.newrelic.agent.bridge.NoOpWebResponse;
import com.newrelic.agent.bridge.Token;
import com.newrelic.agent.bridge.TracedActivity;
import com.newrelic.api.agent.Headers;
import com.newrelic.api.agent.NewRelic;
import com.newrelic.api.agent.TransportType;
import com.newrelic.api.agent.*;
import com.newrelic.agent.bridge.WebResponse;
import com.newrelic.agent.service.ServiceFactory;
import com.newrelic.agent.tracers.Tracer;
import com.newrelic.api.agent.ApplicationNamePriority;
import com.newrelic.api.agent.DistributedTracePayload;
import com.newrelic.api.agent.ExtendedRequest;
import com.newrelic.api.agent.InboundHeaders;
import com.newrelic.api.agent.Request;
import com.newrelic.api.agent.Response;
import com.newrelic.api.agent.Segment;
import com.newrelic.api.agent.TracedMethod;
import com.newrelic.api.agent.TransactionNamePriority;

import java.net.URI;
import java.util.Map;
Expand Down Expand Up @@ -523,6 +513,15 @@ public void acceptDistributedTraceHeaders(TransportType transportType, Headers h
HeadersUtil.parseAndAcceptDistributedTraceHeaders(tx, headers);
}

@Override
public Object getSecurityMetaData() {
Transaction tx = getTransactionIfExists();
if (tx != null) {
return tx.getSecurityMetaData();
}
return null;
}

@Override
public void setTransportType(TransportType transportType) {
Transaction tx = getTransactionIfExists();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import com.newrelic.agent.config.internal.DeepMapClone;
import com.newrelic.agent.database.SqlObfuscator;
import com.newrelic.agent.reinstrument.RemoteInstrumentationServiceImpl;
import com.newrelic.agent.transport.ConnectionResponse;

import java.util.ArrayList;
import java.util.Collections;
Expand Down Expand Up @@ -199,6 +200,13 @@ public static void mergeServerData(Map<String, Object> settings, Map<String, Obj
addServerProp(EXPECTED_CLASSES, serverData.get(ErrorCollectorConfigImpl.EXPECTED_CLASSES), settings);
addServerProp(EXPECTED_STATUS_CODES, serverData.get(ErrorCollectorConfigImpl.EXPECTED_STATUS_CODES), settings);

// Adding agent_run_id & account_id to config as required by K2 agent
addServerProp(ConnectionResponse.AGENT_RUN_ID_KEY, serverData.get(ConnectionResponse.AGENT_RUN_ID_KEY), settings);
addServerProp(DistributedTracingConfig.ACCOUNT_ID, serverData.get(DistributedTracingConfig.ACCOUNT_ID), settings);
addServerProp("agent_home", ConfigFileHelper.getNewRelicDirectory().getAbsolutePath(), settings);
if(AgentJarHelper.getAgentJarDirectory() != null) {
addServerProp("agent_jar_location", AgentJarHelper.getAgentJarDirectory().getAbsolutePath(), settings);
}
if (settingsConfig.getProperty(SECURITY_POLICIES_TOKEN) != null) {
addServerProp(RECORD_SQL, recordSqlSecure, settings);
// Root
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.google.common.base.Joiner;
import com.newrelic.agent.Agent;
import com.newrelic.agent.DebugFlag;
import com.newrelic.agent.security.intcodeagent.websocket.JsonConverter;
import com.newrelic.agent.transaction.TransactionNamingScheme;
import com.newrelic.agent.transport.DataSenderImpl;
import com.newrelic.agent.util.Strings;
Expand Down Expand Up @@ -782,9 +783,38 @@ private BrowserMonitoringConfig initBrowserMonitoringConfig() {
private ClassTransformerConfig initClassTransformerConfig(boolean liteMode) {
boolean customTracingEnabled = getProperty(ENABLE_CUSTOM_TRACING, DEFAULT_ENABLE_CUSTOM_TRACING);
Map<String, Object> props = nestedProps(CLASS_TRANSFORMER);
props = placeSecurityCollectorRelatedModification(props);
return ClassTransformerConfigImpl.createClassTransformerConfig(props, customTracingEnabled, liteMode);
}

/**
* CSEC specific excludes needed to allow functioning with java.io.InputStream and OutputStream instrumentation.
*/
private Map<String, Object> placeSecurityCollectorRelatedModification(Map<String, Object> props) {
if(getProperty("security") != null) {
if(props == null) {
props = new HashMap<>();
} else {
props = new HashMap<>(props);
}
Set<String> securityExcludes = new HashSet<>() ;
securityExcludes.add("java/util/zip/InflaterInputStream");
securityExcludes.add("java/util/zip/ZipFile$ZipFileInputStream");
securityExcludes.add("java/util/zip/ZipFile$ZipFileInflaterInputStream");
securityExcludes.add("com/newrelic/.*");
securityExcludes.add("com/nr/.*");

Object userProvidedExcludes = props.get(ClassTransformerConfigImpl.EXCLUDES);
if(userProvidedExcludes instanceof String) {
securityExcludes.add((String) userProvidedExcludes);
} else if(userProvidedExcludes instanceof Set){
securityExcludes.addAll((Collection<? extends String>) userProvidedExcludes);
}
props.put(ClassTransformerConfigImpl.EXCLUDES, securityExcludes);
}
return props;
}

private CircuitBreakerConfig initCircuitBreakerConfig() {
Map<String, Object> props = nestedProps(CircuitBreakerConfig.PROPERTY_NAME);
return new CircuitBreakerConfig(props);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,7 @@
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLDecoder;
import java.net.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
Expand Down
Loading