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

New config for nrsecurityagent #984

Merged
merged 17 commits into from
Nov 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion v3/integrations/nrsecurityagent/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/newrelic/go-agent/v3/integrations/nrsecurityagent
go 1.21

require (
github.com/newrelic/csec-go-agent v1.4.0
github.com/newrelic/csec-go-agent v1.5.0
github.com/newrelic/go-agent/v3 v3.35.0
github.com/newrelic/go-agent/v3/integrations/nrsqlite3 v1.2.0
gopkg.in/yaml.v2 v2.4.0
Expand Down
97 changes: 95 additions & 2 deletions v3/integrations/nrsecurityagent/nrsecurityagent.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"io/ioutil"
"os"
"strconv"
"strings"

securityAgent "github.com/newrelic/csec-go-agent"
"github.com/newrelic/go-agent/v3/internal"
Expand All @@ -31,6 +32,11 @@ func defaultSecurityConfig() SecurityConfig {
cfg.Security.Agent.Enabled = true
cfg.Security.Detection.Rxss.Enabled = true
cfg.Security.Request.BodyLimit = 300
cfg.Security.ExcludeFromIastScan.HttpRequestParameters.Header = make([]string, 0)
cfg.Security.ExcludeFromIastScan.HttpRequestParameters.Body = make([]string, 0)
cfg.Security.ExcludeFromIastScan.HttpRequestParameters.Query = make([]string, 0)
cfg.Security.ExcludeFromIastScan.API = make([]string, 0)
cfg.Security.ScanControllers.IastScanRequestRateLimit = 3600
return cfg
}

Expand Down Expand Up @@ -63,7 +69,7 @@ func InitSecurityAgent(app *newrelic.Application, opts ...ConfigOption) error {

appConfig, isValid := app.Config()
if !isValid {
return fmt.Errorf("Newrelic application value cannot be read; did you call newrelic.NewApplication?")
return fmt.Errorf("Newrelic application value cannot be read; did you call newrelic.NewApplication?")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is that a typo or do you intend the extra space to be added to the error string?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes extra space is typo.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok we can fix it on release.

}
app.UpdateSecurityConfig(c.Security)
if !appConfig.HighSecurity && isSecurityAgentEnabled() {
Expand Down Expand Up @@ -109,8 +115,24 @@ func ConfigSecurityFromYaml() ConfigOption {
// NEW_RELIC_SECURITY_VALIDATOR_SERVICE_URL provides URL for the security validator service
// NEW_RELIC_SECURITY_MODE scanning mode: "IAST" for now
// NEW_RELIC_SECURITY_AGENT_ENABLED (boolean)
// NEW_RELIC_SECURITY_DETECTION_RXSS_ENABLED (boolean)
// NEW_RELIC_SECURITY_REQUEST_BODY_LIMIT (integer) set limit on read request body in kb. By default, this is "300"
//
// NEW_RELIC_SECURITY_SCAN_SCHEDULE_DELAY (integer) The delay field indicated time in minutes before the IAST scan starts after the application starts. By default is 0 min.
// NEW_RELIC_SECURITY_SCAN_SCHEDULE_DURATION (integer) The duration field specifies the duration of the IAST scan in minutes. This determines how long the scan will run. By default is forever.
// NEW_RELIC_SECURITY_SCAN_SCHEDULE_SCHEDULE (string) The schedule field specifies a cron expression that defines when the IAST scan should run.
// NEW_RELIC_SECURITY_SCAN_SCHEDULE_ALWAYS_SAMPLE_TRACES (boolean) always_sample_traces permits IAST to actively gather trace data in the background, and the collected data will be used by Security Agent to perform an IAST Scan at the scheduled time.
// NEW_RELIC_SECURITY_SCAN_CONTROLLERS_IAST_SCAN_REQUEST_RATE_LIMIT (integer) The IAST Scan Rate Limit settings limit the maximum number of analysis probes or requests that can be sent to the application in a minute, By default is 3600.
//
// NEW_RELIC_SECURITY_EXCLUDE_FROM_IAST_SCAN_IAST_DETECTION_CATEGORY_INSECURE_SETTINGS (boolean)
// NEW_RELIC_SECURITY_EXCLUDE_FROM_IAST_SCAN_IAST_DETECTION_CATEGORY_INVALID_FILE_ACCESS (boolean)
// NEW_RELIC_SECURITY_EXCLUDE_FROM_IAST_SCAN_IAST_DETECTION_CATEGORY_SQL_INJECTION (boolean)
// NEW_RELIC_SECURITY_EXCLUDE_FROM_IAST_SCAN_IAST_DETECTION_CATEGORY_NOSQL_INJECTION (boolean)
// NEW_RELIC_SECURITY_EXCLUDE_FROM_IAST_SCAN_IAST_DETECTION_CATEGORY_LDAP_INJECTION (boolean)
// NEW_RELIC_SECURITY_EXCLUDE_FROM_IAST_SCAN_IAST_DETECTION_CATEGORY_JAVASCRIPT_INJECTION (boolean)
// NEW_RELIC_SECURITY_EXCLUDE_FROM_IAST_SCAN_IAST_DETECTION_CATEGORY_COMMAND_INJECTION (boolean)
// NEW_RELIC_SECURITY_EXCLUDE_FROM_IAST_SCAN_IAST_DETECTION_CATEGORY_XPATH_INJECTION (boolean)
// NEW_RELIC_SECURITY_EXCLUDE_FROM_IAST_SCAN_IAST_DETECTION_CATEGORY_SSRF (boolean)
// NEW_RELIC_SECURITY_EXCLUDE_FROM_IAST_SCAN_IAST_DETECTION_CATEGORY_RXSS (boolean)

func ConfigSecurityFromEnvironment() ConfigOption {
return func(cfg *SecurityConfig) {
Expand Down Expand Up @@ -145,6 +167,37 @@ func ConfigSecurityFromEnvironment() ConfigOption {
assignBool(&cfg.Security.Agent.Enabled, "NEW_RELIC_SECURITY_AGENT_ENABLED")
assignBool(&cfg.Security.Detection.Rxss.Enabled, "NEW_RELIC_SECURITY_DETECTION_RXSS_ENABLED")
assignInt(&cfg.Security.Request.BodyLimit, "NEW_RELIC_SECURITY_REQUEST_BODY_LIMIT")

assignInt(&cfg.Security.ScanSchedule.Delay, "NEW_RELIC_SECURITY_SCAN_SCHEDULE_DELAY")
assignInt(&cfg.Security.ScanSchedule.Duration, "NEW_RELIC_SECURITY_SCAN_SCHEDULE_DURATION")
assignString(&cfg.Security.ScanSchedule.Schedule, "NEW_RELIC_SECURITY_SCAN_SCHEDULE_SCHEDULE")
assignBool(&cfg.Security.ScanSchedule.AllowIastSampleCollection, "NEW_RELIC_SECURITY_SCAN_SCHEDULE_ALWAYS_SAMPLE_TRACES")
assignInt(&cfg.Security.ScanControllers.IastScanRequestRateLimit, "NEW_RELIC_SECURITY_SCAN_CONTROLLERS_IAST_SCAN_REQUEST_RATE_LIMIT")

assignBool(&cfg.Security.ExcludeFromIastScan.IastDetectionCategory.InsecureSettings, "NEW_RELIC_SECURITY_EXCLUDE_FROM_IAST_SCAN_IAST_DETECTION_CATEGORY_INSECURE_SETTINGS")
assignBool(&cfg.Security.ExcludeFromIastScan.IastDetectionCategory.InvalidFileAccess, "NEW_RELIC_SECURITY_EXCLUDE_FROM_IAST_SCAN_IAST_DETECTION_CATEGORY_INVALID_FILE_ACCESS")
assignBool(&cfg.Security.ExcludeFromIastScan.IastDetectionCategory.SQLInjection, "NEW_RELIC_SECURITY_EXCLUDE_FROM_IAST_SCAN_IAST_DETECTION_CATEGORY_SQL_INJECTION")
assignBool(&cfg.Security.ExcludeFromIastScan.IastDetectionCategory.NosqlInjection, "NEW_RELIC_SECURITY_EXCLUDE_FROM_IAST_SCAN_IAST_DETECTION_CATEGORY_NOSQL_INJECTION")
assignBool(&cfg.Security.ExcludeFromIastScan.IastDetectionCategory.LdapInjection, "NEW_RELIC_SECURITY_EXCLUDE_FROM_IAST_SCAN_IAST_DETECTION_CATEGORY_LDAP_INJECTION")
assignBool(&cfg.Security.ExcludeFromIastScan.IastDetectionCategory.JavascriptInjection, "NEW_RELIC_SECURITY_EXCLUDE_FROM_IAST_SCAN_IAST_DETECTION_CATEGORY_JAVASCRIPT_INJECTION")
assignBool(&cfg.Security.ExcludeFromIastScan.IastDetectionCategory.CommandInjection, "NEW_RELIC_SECURITY_EXCLUDE_FROM_IAST_SCAN_IAST_DETECTION_CATEGORY_COMMAND_INJECTION")
assignBool(&cfg.Security.ExcludeFromIastScan.IastDetectionCategory.XpathInjection, "NEW_RELIC_SECURITY_EXCLUDE_FROM_IAST_SCAN_IAST_DETECTION_CATEGORY_XPATH_INJECTION")
assignBool(&cfg.Security.ExcludeFromIastScan.IastDetectionCategory.Ssrf, "NEW_RELIC_SECURITY_EXCLUDE_FROM_IAST_SCAN_IAST_DETECTION_CATEGORY_SSRF")
assignBool(&cfg.Security.ExcludeFromIastScan.IastDetectionCategory.Rxss, "NEW_RELIC_SECURITY_EXCLUDE_FROM_IAST_SCAN_IAST_DETECTION_CATEGORY_RXSS")

if env := os.Getenv("NEW_RELIC_SECURITY_EXCLUDE_FROM_IAST_SCAN_API"); env != "" {
cfg.Security.ExcludeFromIastScan.API = strings.Split(env, ",")
}
if env := os.Getenv("NEW_RELIC_SECURITY_EXCLUDE_FROM_IAST_SCAN_HTTP_REQUEST_PARAMETERS_HEADER"); env != "" {
cfg.Security.ExcludeFromIastScan.HttpRequestParameters.Header = strings.Split(env, ",")
}
if env := os.Getenv("NEW_RELIC_SECURITY_EXCLUDE_FROM_IAST_SCAN_HTTP_REQUEST_PARAMETERS_QUERY"); env != "" {
cfg.Security.ExcludeFromIastScan.HttpRequestParameters.Query = strings.Split(env, ",")
}
if env := os.Getenv("NEW_RELIC_SECURITY_EXCLUDE_FROM_IAST_SCAN_HTTP_REQUEST_PARAMETERS_BODY"); env != "" {
cfg.Security.ExcludeFromIastScan.HttpRequestParameters.Body = strings.Split(env, ",")
}

}
}

Expand Down Expand Up @@ -182,3 +235,43 @@ func ConfigSecurityRequestBodyLimit(bodyLimit int) ConfigOption {
cfg.Security.Request.BodyLimit = bodyLimit
}
}

// ConfigScanScheduleDelay is used to set delay for scan schedule.
// The delay field indicated time in minutes before the IAST scan starts after the application starts
func ConfigScanScheduleDelay(delay int) ConfigOption {
return func(cfg *SecurityConfig) {
cfg.Security.ScanSchedule.Delay = delay
}
}

// ConfigScanScheduleDuration is used to set duration for scan schedule.
// The duration field specifies the duration of the IAST scan in minutes. This determines how long the scan will run.
func ConfigScanScheduleDuration(duration int) ConfigOption {
return func(cfg *SecurityConfig) {
cfg.Security.ScanSchedule.Duration = duration
}
}

// ConfigScanScheduleSetSchedule is used to set schedule for scan schedule.
// The schedule field specifies a cron expression that defines when the IAST scan should run.
func ConfigScanScheduleSetSchedule(schedule string) ConfigOption {
return func(cfg *SecurityConfig) {
cfg.Security.ScanSchedule.Schedule = schedule
}
}

// ConfigScanScheduleAllowIastSampleCollection is used to allow or disallow IAST sample collection
// always_sample_traces permits IAST to actively gather trace data in the background, and the collected data will be used by Security Agent to perform an IAST Scan at the scheduled time.
func ConfigScanScheduleAllowIastSampleCollection(isAllowed bool) ConfigOption {
return func(cfg *SecurityConfig) {
cfg.Security.ScanSchedule.AllowIastSampleCollection = isAllowed
}
}

// ConfigScanControllersIastScanRequestRateLimit is used to set IAST scan request rate limit.
// The IAST Scan Rate Limit settings limit the maximum number of analysis probes or requests that can be sent to the application in a minute
func ConfigIastScanRequestRateLimit(limit int) ConfigOption {
return func(cfg *SecurityConfig) {
cfg.Security.ScanControllers.IastScanRequestRateLimit = limit
}
}
2 changes: 1 addition & 1 deletion v3/newrelic/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ func (txn *Transaction) SetWebRequest(r WebRequest) {
return
}
if IsSecurityAgentPresent() {
secureAgent.SendEvent("INBOUND", r, txn.GetCsecAttributes())
secureAgent.SendEvent("INBOUND", r, txn.GetCsecAttributes(), txn.GetLinkingMetadata().TraceID)
}
txn.thread.logAPIError(txn.thread.SetWebRequest(r), "set web request", nil)
}
Expand Down
Loading