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

refactor(agent): expose app metadata for csec via global symbol #922

Open
wants to merge 13 commits into
base: security-agent-support
Choose a base branch
from
Open
103 changes: 64 additions & 39 deletions agent/csec_metadata.c
Original file line number Diff line number Diff line change
@@ -1,48 +1,73 @@
/*
* Copyright 2024 New Relic Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/

#include "csec_metadata.h"
#include "util_strings.h"
#include "php_hash.h"
#include "php_api_internal.h"

static void nr_csec_php_add_assoc_string_const(zval* arr,
const char* key,
const char* value) {
char* val = NULL;
#include "util_memory.h"

#include "nr_axiom.h"
#include "nr_agent.h"
#include "nr_app.h"
#include "php_includes.h"
#include "php_compat.h"
#include "php_newrelic.h"

if (NULL == arr || NULL == key || NULL == value) {
return;
int nr_php_csec_get_metadata(const nr_php_csec_metadata_key_t key, char** p) {
const char* value = NULL;

if (NULL == p) {
return -1;
}

val = nr_strdup(value);
nr_php_add_assoc_string(arr, key, val);
nr_free(val);
}
if (NULL == NRPRG(app)) {
return -2;
}

switch (key) {
case NR_PHP_CSEC_METADATA_HIGH_SECURITY:
if (NRPRG(app)->info.high_security) {
value = "true";
} else {
value = "false";
}
break;
case NR_PHP_CSEC_METADATA_ENTITY_NAME:
value = nr_app_get_entity_name(NRPRG(app));
break;
case NR_PHP_CSEC_METADATA_ENTITY_TYPE:
value = nr_app_get_entity_type(NRPRG(app));
break;
case NR_PHP_CSEC_METADATA_ENTITY_GUID:
value = nr_app_get_entity_guid(NRPRG(app));
break;
case NR_PHP_CSEC_METADATA_HOST_NAME:
value = nr_app_get_host_name(NRPRG(app));
break;
case NR_PHP_CSEC_METADATA_AGENT_RUN_ID:
value = NRPRG(app)->agent_run_id;
break;
case NR_PHP_CSEC_METADATA_ACCOUNT_ID:
value = NRPRG(app)->account_id;
break;
case NR_PHP_CSEC_METADATA_LICENSE:
value = NRPRG(license).value;
break;
case NR_PHP_CSEC_METADATA_PLICENSE:
value = NRPRG(app)->plicense;
break;
default:
return -4;
}

#ifdef TAGS
void zif_newrelic_get_security_metadata(void); /* ctags landing pad only */
void newrelic_get_security_metadata(void); /* ctags landing pad only */
#endif
PHP_FUNCTION(newrelic_get_security_metadata) {

NR_UNUSED_RETURN_VALUE;
NR_UNUSED_RETURN_VALUE_PTR;
NR_UNUSED_RETURN_VALUE_USED;
NR_UNUSED_THIS_PTR;
NR_UNUSED_EXECUTE_DATA;

array_init(return_value);

nr_csec_php_add_assoc_string_const(return_value, KEY_ENTITY_NAME, nr_app_get_entity_name(NRPRG(app)));
nr_csec_php_add_assoc_string_const(return_value, KEY_ENTITY_TYPE, nr_app_get_entity_type(NRPRG(app)));
nr_csec_php_add_assoc_string_const(return_value, KEY_ENTITY_GUID, nr_app_get_entity_guid(NRPRG(app)));
nr_csec_php_add_assoc_string_const(return_value, KEY_HOSTNAME, nr_app_get_host_name(NRPRG(app)));
nr_csec_php_add_assoc_string_const(return_value, KEY_LICENSE, NRPRG(license).value);

if (NRPRG(app)) {
nr_csec_php_add_assoc_string_const(return_value, KEY_AGENT_RUN_ID, NRPRG(app)->agent_run_id);
nr_csec_php_add_assoc_string_const(return_value, KEY_ACCOUNT_ID, NRPRG(app)->account_id);
nr_csec_php_add_assoc_string_const(return_value, KEY_PLICENSE, NRPRG(app)->plicense);
int high_security = NRPRG(app)->info.high_security;
add_assoc_long(return_value, KEY_HIGH_SECURITY, (long)high_security);
if (NULL == value) {
return -5;
}

*p = nr_strdup(value);
if (NULL == *p) {
return -3;
}
return 0;
}
49 changes: 38 additions & 11 deletions agent/csec_metadata.h
Original file line number Diff line number Diff line change
@@ -1,12 +1,39 @@
#include "php_agent.h"
#include "util_hashmap.h"
/*
* Copyright 2024 New Relic Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/

#define KEY_ENTITY_NAME "entity.name"
#define KEY_ENTITY_TYPE "entity.type"
#define KEY_ENTITY_GUID "entity.guid"
#define KEY_HOSTNAME "hostname"
#define KEY_AGENT_RUN_ID "agent.run.id"
#define KEY_ACCOUNT_ID "account.id"
#define KEY_LICENSE "license"
#define KEY_PLICENSE "plicense"
#define KEY_HIGH_SECURITY "high_security"
#ifndef CSEC_METADATA_H
#define CSEC_METADATA_H

typedef enum {
NR_PHP_CSEC_METADATA_HIGH_SECURITY = 1,
NR_PHP_CSEC_METADATA_ENTITY_NAME,
NR_PHP_CSEC_METADATA_ENTITY_TYPE,
NR_PHP_CSEC_METADATA_ENTITY_GUID,
NR_PHP_CSEC_METADATA_HOST_NAME,
NR_PHP_CSEC_METADATA_AGENT_RUN_ID,
NR_PHP_CSEC_METADATA_ACCOUNT_ID,
NR_PHP_CSEC_METADATA_LICENSE,
NR_PHP_CSEC_METADATA_PLICENSE
} nr_php_csec_metadata_key_t;

/*
* Purpose : Copy requested app meta data into allocated *value.
* The caller is responsible for freeing the memory
* allocated. The value is a string representation of
* the requested metadata.
*
* Params : Pointer to a nr_php_csec_metadata_t structure
*
* Returns : 0 for success
* -1 for invalid input
* -2 for invalid internal state
* -3 for inability to allocate memory
* -4 for invalid metadata key
* -5 for inability to retrieve metadata value
*/
extern int nr_php_csec_get_metadata(const nr_php_csec_metadata_key_t k, char** value);
typedef int (*nr_php_csec_get_metadata_t)(const nr_php_csec_metadata_key_t k, char** value);
#define NR_PHP_CSEC_GET_METADATA "nr_php_csec_get_metadata"
#endif
1 change: 1 addition & 0 deletions agent/export.syms
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
get_module
nr_php_csec_get_metadata
2 changes: 0 additions & 2 deletions agent/php_api_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@
*/
extern PHP_FUNCTION(newrelic_get_request_metadata);

extern PHP_FUNCTION(newrelic_get_security_metadata);

#ifdef ENABLE_TESTING_API

/*
Expand Down
13 changes: 8 additions & 5 deletions agent/php_minit.c
Original file line number Diff line number Diff line change
Expand Up @@ -719,11 +719,14 @@ PHP_MINIT_FUNCTION(newrelic) {
nr_wordpress_minit();
nr_php_set_opcode_handlers();

if (!NR_PHP_PROCESS_GLOBALS(nr_security_agent_enabled) || !NR_PHP_PROCESS_GLOBALS(nr_security_enabled) || NR_PHP_PROCESS_GLOBALS(high_security)) {
nrl_info(NRL_INIT, "New Relic Security is completely disabled by one of the user provided config `newrelic.security.enabled`, `newrelic.security.agent.enabled` or `newrelic.high_security`. Not loading security capabilities.");
nrl_debug(NRL_INIT, "newrelic.security.agent.enabled : %s", NR_PHP_PROCESS_GLOBALS(nr_security_enabled) ? "true" : "false");
nrl_debug(NRL_INIT, "newrelic.security.enabled : %s", NR_PHP_PROCESS_GLOBALS(nr_security_agent_enabled) ? "true" : "false");
nrl_debug(NRL_INIT, "newrelic.high_security : %s", NR_PHP_PROCESS_GLOBALS(high_security) ? "true" : "false");
if (NR_PHP_PROCESS_GLOBALS(nr_security_agent_enabled)
&& NR_PHP_PROCESS_GLOBALS(nr_security_enabled)
&& !NR_PHP_PROCESS_GLOBALS(high_security)) {
nrl_info(
NRL_INIT,
"New Relic Security is enabled by the user provided config "
"`newrelic.security.enabled`, `newrelic.security.agent.enabled` and "
"`newrelic.high_security`. Security capabilities will be loaded.");
}

nrl_debug(NRL_INIT, "MINIT processing done");
Expand Down
2 changes: 0 additions & 2 deletions agent/php_newrelic.c
Original file line number Diff line number Diff line change
Expand Up @@ -343,11 +343,9 @@ static zend_function_entry newrelic_functions[] = {
#ifdef PHP8
PHP_FE(newrelic_get_linking_metadata, newrelic_arginfo_void)
PHP_FE(newrelic_get_trace_metadata, newrelic_arginfo_void)
PHP_FE(newrelic_get_security_metadata, newrelic_arginfo_void)
#else
PHP_FE(newrelic_get_linking_metadata, 0)
PHP_FE(newrelic_get_trace_metadata, 0)
PHP_FE(newrelic_get_security_metadata, 0)
#endif /* PHP 8 */
/*
* Integration test helpers
Expand Down
83 changes: 0 additions & 83 deletions agent/scripts/newrelic.ini.template
Original file line number Diff line number Diff line change
Expand Up @@ -1333,86 +1333,3 @@ newrelic.daemon.logfile = "/var/log/newrelic/newrelic-daemon.log"
; for vulnerability management.
;
;newrelic.vulnerability_management.package_detection.enabled = true

; Setting: newrelic.security.enabled
; Type : boolean
; Scope : system
; Default: false
; Info : Indicates if attack detection security module is to be enabled
;
;newrelic.security.enabled = true

; Setting: newrelic.security.mode
; Type : string
; Scope : system
; Default: "IAST"
; Info : Security module provides two modes "IAST" or "RASP"
; See documentation for more details
;
;newrelic.security.mode = "IAST"

; Setting: newrelic.security.validator_service_endpoint_url
; Type : string
; Scope : system
; Default: "wss://csec.nr-data.net"
; Info : New Relic<E2><80><99>s security module SaaS connection URLs
;
;newrelic.security.validator_service_url = "wss://csec.nr-data.net"

; Setting: newrelic.security.agent.enabled
; Type : boolean
; Scope : system
; Default: false
; Info : Used to enable security module, default false is equivalent to
; security module not even loaded. If this setting is set to true,
; then only security module is loaded and to enable it, a restart
; of application is required. This is different than
; newrelic.security.enabled, in terms that security.enabled decides
; runtime behavior of security module but security.agent.enabled
; would not even load the security module when set to false
;
;newrelic.security.agent.enabled = false

; Setting: newrelic.security.detection.rci.enabled
; Type : boolean
; Scope : system
; Default: true
; Info : Indicates if detection of remote code injection attack category is to be enabled
;
;newrelic.security.detection.rci.enabled = true

; Setting: newrelic.security.detection.rxss.enabled
; Type : boolean
; Scope : system
; Default: true
; Info : Indicates if detection of reflected xss attack category is to be enabled
;
;newrelic.security.detection.rxss.enabled = true

; Setting: newrelic.security.detection.deserialization.enabled
; Type : boolean
; Scope : system
; Default: true
; Info : Indicates if detection of deserialization attack category is to be enabled
;
;newrelic.security.detection.deserialization.enabled = true

; Setting: newrelic.security.request.body_limit
; Type : unsigned integer
; Scope : system
; Default: 300
; Info : Sets the maximum limit of the request body to be read in kb.
;
;newrelic.security.request.body_limit = 300

; Setting: newrelic.security.validator.client_ssl_cert_filepath
; Type : string
; Scope : system
; Default: none
; Info : Sets the full path of the client certificate in PEM
; format. When set, this certificate will be used to
; authenticate the New Relic IAST Security Engine's url. If
; not set, the default certificate will be used. Make
; sure the file permissions are correct.
;
;newrelic.security.validator.client_ssl_cert_filepath = ""
Loading