Skip to content

Commit

Permalink
Merge pull request #327 from newrelic/feature/grpc-inst/endpoint
Browse files Browse the repository at this point in the history
API Endpoint and User Class Detection support for gRPC
  • Loading branch information
IshikaDawda authored Sep 20, 2024
2 parents e0207e8 + fed109e commit 4ffd609
Show file tree
Hide file tree
Showing 10 changed files with 161 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package io.grpc;

import com.newrelic.agent.security.instrumentation.grpc1220.GrpcUtils;
import com.newrelic.api.agent.security.NewRelicSecurity;
import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper;
import com.newrelic.api.agent.security.schema.ApplicationURLMapping;
import com.newrelic.api.agent.security.utils.logging.LogLevel;
import com.newrelic.api.agent.weaver.MatchType;
import com.newrelic.api.agent.weaver.Weave;
import com.newrelic.api.agent.weaver.Weaver;

@Weave(originalName = "io.grpc.BindableService", type = MatchType.Interface)
public class BindableService_Instrumentation {
public ServerServiceDefinition bindService() {
ServerServiceDefinition returnValue = Weaver.callOriginal();

try {
String handler = this.getClass().getName();
for (ServerMethodDefinition<?, ?> serverMethod : returnValue.getMethods()) {
MethodDescriptor<?, ?> methodDescriptor = serverMethod.getMethodDescriptor();
String url = methodDescriptor.getFullMethodName();
String methodType = methodDescriptor.getType().name();
URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(methodType, url, handler));
}
} catch (Exception e){
String message = "Instrumentation library: %s , error while getting app endpoints : %s";
NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(message, GrpcUtils.GRPC_1_22_0, e.getMessage()), e, this.getClass().getName());
}

return returnValue;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import com.newrelic.api.agent.Token;
import com.newrelic.api.agent.Trace;
import com.newrelic.api.agent.security.NewRelicSecurity;
import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper;
import com.newrelic.api.agent.security.schema.Framework;
import com.newrelic.api.agent.security.schema.SecurityMetaData;
import com.newrelic.api.agent.weaver.MatchType;
import com.newrelic.api.agent.weaver.NewField;
Expand All @@ -32,6 +34,7 @@ public void onMessage(ReqT message) {
if (isLockAcquired) {
GrpcUtils.preProcessSecurityHook(message, GrpcUtils.Type.REQUEST, descriptorForType.getFullName());
}
ServletHelper.registerUserLevelCode(Framework.GRPC.name());
try {
Weaver.callOriginal();
} finally {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,13 @@
package io.grpc.internal;

import com.newrelic.agent.security.instrumentation.grpc1220.GrpcServerUtils;
import com.newrelic.agent.security.instrumentation.grpc1220.GrpcUtils;
import com.newrelic.agent.security.instrumentation.grpc1220.processor.MonitorGrpcRequestQueueThread;
import com.newrelic.api.agent.NewRelic;
import com.newrelic.api.agent.security.NewRelicSecurity;
import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper;
import com.newrelic.api.agent.security.schema.Framework;
import com.newrelic.api.agent.security.utils.logging.LogLevel;
import com.newrelic.api.agent.weaver.Weave;
import com.newrelic.api.agent.weaver.Weaver;
import io.grpc.Context;
Expand All @@ -29,6 +34,14 @@ private <ReqT, RespT> ServerStreamListener startCall(ServerStream_Instrumentatio
stream.tokenForCsec = NewRelic.getAgent().getTransaction().getToken();
MonitorGrpcRequestQueueThread.submitNewTask();
boolean isLockAcquired = GrpcServerUtils.acquireLockIfPossible();
try {
if (NewRelicSecurity.isHookProcessingActive()){
NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().setRoute(methodDef.getMethodDescriptor().getFullMethodName());
NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().setFramework(Framework.GRPC);
}
} catch (Exception e) {
NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_ROUTE_FOR_INCOMING_REQUEST, GrpcUtils.GRPC_1_22_0, e.getMessage()), e, this.getClass().getName());
}
if (isLockAcquired) {
GrpcServerUtils.preprocessSecurityHook(stream, methodDef, headers, this.getClass().getName());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package io.grpc;

import com.newrelic.agent.security.instrumentation.grpc140.GrpcUtils;
import com.newrelic.api.agent.security.NewRelicSecurity;
import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper;
import com.newrelic.api.agent.security.schema.ApplicationURLMapping;
import com.newrelic.api.agent.security.utils.logging.LogLevel;
import com.newrelic.api.agent.weaver.MatchType;
import com.newrelic.api.agent.weaver.Weave;
import com.newrelic.api.agent.weaver.Weaver;

@Weave(originalName = "io.grpc.BindableService", type = MatchType.Interface)
public class BindableService_Instrumentation {
public ServerServiceDefinition bindService() {
ServerServiceDefinition returnValue = Weaver.callOriginal();

try {
String handler = this.getClass().getName();
for (ServerMethodDefinition<?, ?> serverMethod : returnValue.getMethods()) {
MethodDescriptor<?, ?> methodDescriptor = serverMethod.getMethodDescriptor();
String url = methodDescriptor.getFullMethodName();
String methodType = methodDescriptor.getType().name();
URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(methodType, url, handler));
}
} catch (Exception e){
String message = "Instrumentation library: %s , error while getting app endpoints : %s";
NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(message, GrpcUtils.GRPC_1_4_0, e.getMessage()), e, this.getClass().getName());
}

return returnValue;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import com.newrelic.api.agent.Token;
import com.newrelic.api.agent.Trace;
import com.newrelic.api.agent.security.NewRelicSecurity;
import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper;
import com.newrelic.api.agent.security.schema.Framework;
import com.newrelic.api.agent.security.schema.SecurityMetaData;
import com.newrelic.api.agent.weaver.MatchType;
import com.newrelic.api.agent.weaver.NewField;
Expand All @@ -32,6 +34,7 @@ public void onMessage(ReqT message) {
if (isLockAcquired) {
GrpcUtils.preProcessSecurityHook(message, GrpcUtils.Type.REQUEST, descriptorForType.getFullName());
}
ServletHelper.registerUserLevelCode(Framework.GRPC.name());
try {
Weaver.callOriginal();
} finally {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,13 @@
package io.grpc.internal;

import com.newrelic.agent.security.instrumentation.grpc140.GrpcServerUtils;
import com.newrelic.agent.security.instrumentation.grpc140.GrpcUtils;
import com.newrelic.agent.security.instrumentation.grpc140.processor.MonitorGrpcRequestQueueThread;
import com.newrelic.api.agent.NewRelic;
import com.newrelic.api.agent.security.NewRelicSecurity;
import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper;
import com.newrelic.api.agent.security.schema.Framework;
import com.newrelic.api.agent.security.utils.logging.LogLevel;
import com.newrelic.api.agent.weaver.Weave;
import com.newrelic.api.agent.weaver.Weaver;
import io.grpc.Context;
Expand All @@ -28,6 +33,14 @@ private <ReqT, RespT> ServerStreamListener startCall(ServerStream_Instrumentatio
stream.tokenForCsec = NewRelic.getAgent().getTransaction().getToken();
MonitorGrpcRequestQueueThread.submitNewTask();
boolean isLockAcquired = GrpcServerUtils.acquireLockIfPossible();
try {
if (NewRelicSecurity.isHookProcessingActive()){
NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().setRoute(methodDef.getMethodDescriptor().getFullMethodName());
NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().setFramework(Framework.GRPC);
}
} catch (Exception e){
NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_ROUTE_FOR_INCOMING_REQUEST, GrpcUtils.GRPC_1_4_0, e.getMessage()), e, this.getClass().getName());
}
if (isLockAcquired) {
GrpcServerUtils.preprocessSecurityHook(stream, methodDef, headers, this.getClass().getName());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package io.grpc;

import com.newrelic.agent.security.instrumentation.grpc1400.GrpcUtils;
import com.newrelic.api.agent.security.NewRelicSecurity;
import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper;
import com.newrelic.api.agent.security.schema.ApplicationURLMapping;
import com.newrelic.api.agent.security.utils.logging.LogLevel;
import com.newrelic.api.agent.weaver.MatchType;
import com.newrelic.api.agent.weaver.Weave;
import com.newrelic.api.agent.weaver.Weaver;

@Weave(originalName = "io.grpc.BindableService", type = MatchType.Interface)
public class BindableService_Instrumentation {
public ServerServiceDefinition bindService() {
ServerServiceDefinition returnValue = Weaver.callOriginal();

try {
String handler = this.getClass().getName();
for (ServerMethodDefinition<?, ?> serverMethod : returnValue.getMethods()) {
MethodDescriptor<?, ?> methodDescriptor = serverMethod.getMethodDescriptor();
String url = methodDescriptor.getFullMethodName();
String methodType = methodDescriptor.getType().name();
URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(methodType, url, handler));
}
} catch (Exception e){
String message = "Instrumentation library: %s , error while getting app endpoints : %s";
NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(message, GrpcUtils.GRPC_1_40_0, e.getMessage()), e, this.getClass().getName());
}

return returnValue;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import com.newrelic.api.agent.Token;
import com.newrelic.api.agent.Trace;
import com.newrelic.api.agent.security.NewRelicSecurity;
import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper;
import com.newrelic.api.agent.security.schema.Framework;
import com.newrelic.api.agent.security.schema.SecurityMetaData;
import com.newrelic.api.agent.weaver.MatchType;
import com.newrelic.api.agent.weaver.NewField;
Expand All @@ -32,6 +34,7 @@ public void onMessage(ReqT message) {
if (isLockAcquired) {
GrpcUtils.preProcessSecurityHook(message, GrpcUtils.Type.REQUEST, descriptorForType.getFullName());
}
ServletHelper.registerUserLevelCode(Framework.GRPC.name());
try {
Weaver.callOriginal();
} finally {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
package io.grpc.internal;

import com.newrelic.agent.security.instrumentation.grpc1400.GrpcServerUtils;
import com.newrelic.agent.security.instrumentation.grpc1400.GrpcUtils;
import com.newrelic.agent.security.instrumentation.grpc1400.processor.MonitorGrpcRequestQueueThread;
import com.newrelic.api.agent.NewRelic;
import com.newrelic.api.agent.security.NewRelicSecurity;
import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper;
import com.newrelic.api.agent.security.schema.Framework;
import com.newrelic.api.agent.security.utils.logging.LogLevel;
import com.newrelic.api.agent.weaver.NewField;
import com.newrelic.api.agent.weaver.Weave;
import com.newrelic.api.agent.weaver.Weaver;
Expand All @@ -28,6 +33,14 @@ private void streamCreatedInternal(final ServerStream stream, final String metho
private <ReqT, RespT> ServerMethodDefinition<?, ?> wrapMethod(ServerStream_Instrumentation stream, ServerMethodDefinition<ReqT, RespT> methodDef, StatsTraceContext statsTraceCtx) {
stream.tokenForCsec = NewRelic.getAgent().getTransaction().getToken();
boolean isLockAcquired = GrpcServerUtils.acquireLockIfPossible();
try {
if (NewRelicSecurity.isHookProcessingActive()){
NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().setRoute(methodDef.getMethodDescriptor().getFullMethodName());
NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().setFramework(Framework.GRPC);
}
} catch (Exception e) {
NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_ROUTE_FOR_INCOMING_REQUEST, GrpcUtils.GRPC_1_40_0, e.getMessage()), e, this.getClass().getName());
}
if (isLockAcquired) {
GrpcServerUtils.preprocessSecurityHook(stream, methodDef, headers, this.getClass().getName());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -628,6 +628,7 @@ private UserClassEntity setUserClassEntityByAnnotation(StackTraceElement[] servi
}

private UserClassEntity setUserClassEntity(AbstractOperation operation, SecurityMetaData securityMetaData) {
boolean frameworkSpecificEntityFound = false;
UserClassEntity userClassEntity = new UserClassEntity();
StackTraceElement userStackTraceElement = securityMetaData.getCustomAttribute(GenericHelper.USER_CLASS_ENTITY, StackTraceElement.class);
if(userStackTraceElement == null && securityMetaData.getMetaData().getServiceTrace() != null && securityMetaData.getMetaData().getServiceTrace().length > 0){
Expand All @@ -651,21 +652,19 @@ private UserClassEntity setUserClassEntity(AbstractOperation operation, Security
}
switch (framework){
case "vertx-web":
if(i-1 >= 0) {
case "GRPC":
if(!frameworkSpecificEntityFound && i-1 >= 0) {
userClassEntity = setUserClassEntityForVertx(operation, userStackTraceElement, userClassEntity, securityMetaData.getMetaData().isUserLevelServiceMethodEncountered(), i);
if(userClassEntity.getUserClassElement() != null){
return userClassEntity;
frameworkSpecificEntityFound = true;
}
}
break;
default:
if(userStackTraceElement != null){
if(StringUtils.equals(stackTraceElement.getClassName(), userStackTraceElement.getClassName())
&& StringUtils.equals(stackTraceElement.getMethodName(), userStackTraceElement.getMethodName())){
userClassEntity.setUserClassElement(stackTraceElement);
userClassEntity.setCalledByUserCode(securityMetaData.getMetaData().isUserLevelServiceMethodEncountered());
return userClassEntity;
}
if(userStackTraceElement != null && StringUtils.equals(stackTraceElement.getClassName(), userStackTraceElement.getClassName())
&& StringUtils.equals(stackTraceElement.getMethodName(), userStackTraceElement.getMethodName())){
userClassEntity.setUserClassElement(stackTraceElement);
userClassEntity.setCalledByUserCode(securityMetaData.getMetaData().isUserLevelServiceMethodEncountered());
}
}
}
Expand All @@ -675,8 +674,16 @@ private UserClassEntity setUserClassEntity(AbstractOperation operation, Security
return userClassEntity;
}

if (frameworkSpecificEntityFound && userClassEntity.getUserClassElement() != null && !securityMetaData.getMetaData().isFoundAnnotedUserLevelServiceMethod()){
return userClassEntity;
}

if (userClassEntity.getUserClassElement() != null){
return userClassEntity;
}

// user class identification using annotations
if (userClassEntity.getUserClassElement() == null && securityMetaData.getMetaData().isFoundAnnotedUserLevelServiceMethod()) {
if (securityMetaData.getMetaData().isFoundAnnotedUserLevelServiceMethod()) {
return setUserClassEntityByAnnotation(securityMetaData.getMetaData().getServiceTrace());
}

Expand Down

0 comments on commit 4ffd609

Please sign in to comment.