From 2b10be53d395127eff8ed3911ed0aec3d38733aa Mon Sep 17 00:00:00 2001 From: Michal Nowacki Date: Fri, 21 Jun 2024 12:03:51 -0400 Subject: [PATCH 1/5] expose app metadata for csec via global symbol Rather than providing a PHP user function to expose app metadata to PHP userland, export a global symbol for cseg agent to use. --- agent/csec_metadata.c | 69 +++++++++++++++++----------------------- agent/csec_metadata.h | 45 +++++++++++++++++++------- agent/export.syms | 1 + agent/php_api_internal.h | 2 -- agent/php_newrelic.c | 2 -- 5 files changed, 64 insertions(+), 55 deletions(-) diff --git a/agent/csec_metadata.c b/agent/csec_metadata.c index ba43b9c1a..0a9d9d47c 100644 --- a/agent/csec_metadata.c +++ b/agent/csec_metadata.c @@ -1,48 +1,37 @@ -#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; - - if (NULL == arr || NULL == key || NULL == value) { - return; - } +/* + * Copyright 2020 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ - val = nr_strdup(value); - nr_php_add_assoc_string(arr, key, val); - nr_free(val); -} - -#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) { +#include "csec_metadata.h" - NR_UNUSED_RETURN_VALUE; - NR_UNUSED_RETURN_VALUE_PTR; - NR_UNUSED_RETURN_VALUE_USED; - NR_UNUSED_THIS_PTR; - NR_UNUSED_EXECUTE_DATA; +#include "util_memory.h" - array_init(return_value); +#include "nr_axiom.h" +#include "nr_agent.h" +#include "nr_app.h" +#include "php_includes.h" +#include "php_compat.h" +#include "php_newrelic.h" - 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); +int nr_php_csec_get_metadata(nr_php_csec_metadata_t* csec_metadata) { + if (NULL == csec_metadata) { + return -1; + } - 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 == NRPRG(app)) { + return -2; } + csec_metadata->high_security = NRPRG(app)->info.high_security; + csec_metadata->entity_name = nr_strdup(nr_app_get_entity_name(NRPRG(app))); + csec_metadata->entity_type = nr_strdup(nr_app_get_entity_type(NRPRG(app))); + csec_metadata->entity_guid = nr_strdup(nr_app_get_entity_guid(NRPRG(app))); + csec_metadata->host_name = nr_strdup(nr_app_get_host_name(NRPRG(app))); + csec_metadata->agent_run_id = nr_strdup(NRPRG(app)->agent_run_id); + csec_metadata->account_id = nr_strdup(NRPRG(app)->account_id); + csec_metadata->license = nr_strdup(NRPRG(license).value); + csec_metadata->plicense = nr_strdup(NRPRG(app)->plicense); + + return 0; } diff --git a/agent/csec_metadata.h b/agent/csec_metadata.h index 1716f6da4..572ce0718 100644 --- a/agent/csec_metadata.h +++ b/agent/csec_metadata.h @@ -1,12 +1,35 @@ -#include "php_agent.h" -#include "util_hashmap.h" +/* + * Copyright 2020 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 struct _nr_php_csec_metadata_t { + int high_security; /* Indicates if high security been set locally for this + application */ + char* license; /* License key provided */ + char* plicense; /* Printable license (abbreviated for security) */ + char* host_name; /* Local host name reported to the daemon */ + char* entity_name; /* Entity name related to this application */ + char* entity_type; /* Entity type */ + char* account_id; /* Security : Added for getting account id */ + char* entity_guid; /* Entity guid related to this application */ + char* agent_run_id; /* The collector's agent run ID; assigned from the + New Relic backend */ +} nr_php_csec_metadata_t; + +/* + * Purpose : Return app meta data by populating nr_php_csec_metadata_t + * structure. The caller is responsible for freeing the memory + * allocated for the strings in the structure. + * + * Params : Pointer to a nr_php_csec_metadata_t structure + * + * Returns : 0 for success + * -1 for invalid input + * -2 for invalid internal state + */ +extern int nr_php_csec_get_metadata(nr_php_csec_metadata_t*); +#endif diff --git a/agent/export.syms b/agent/export.syms index c1252e827..7e8f1e2c4 100644 --- a/agent/export.syms +++ b/agent/export.syms @@ -1 +1,2 @@ get_module +nr_php_csec_get_metadata diff --git a/agent/php_api_internal.h b/agent/php_api_internal.h index f8ae9a653..61db36648 100644 --- a/agent/php_api_internal.h +++ b/agent/php_api_internal.h @@ -16,8 +16,6 @@ */ extern PHP_FUNCTION(newrelic_get_request_metadata); -extern PHP_FUNCTION(newrelic_get_security_metadata); - #ifdef ENABLE_TESTING_API /* diff --git a/agent/php_newrelic.c b/agent/php_newrelic.c index fb81d65b2..912dff365 100644 --- a/agent/php_newrelic.c +++ b/agent/php_newrelic.c @@ -342,11 +342,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 From 813807aaee3ba556d1c85f10512beacca277cea6 Mon Sep 17 00:00:00 2001 From: Michal Nowacki Date: Fri, 21 Jun 2024 12:34:52 -0400 Subject: [PATCH 2/5] make `nr_php_csec_get_metadata` easier to use --- agent/csec_metadata.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/agent/csec_metadata.h b/agent/csec_metadata.h index 572ce0718..ca7a8f332 100644 --- a/agent/csec_metadata.h +++ b/agent/csec_metadata.h @@ -32,4 +32,6 @@ typedef struct _nr_php_csec_metadata_t { * -2 for invalid internal state */ extern int nr_php_csec_get_metadata(nr_php_csec_metadata_t*); +typedef int (*nr_php_csec_get_metadata_t)(nr_php_csec_metadata_t*); +#define NR_PHP_CSEC_GET_METADATA "nr_php_csec_get_metadata" #endif From 562e434d9ed6e7e3a6738f796aaf5934a64ca34a Mon Sep 17 00:00:00 2001 From: Michal Nowacki Date: Tue, 25 Jun 2024 19:17:09 -0400 Subject: [PATCH 3/5] refactor to avoid 'transport' struct Replace 'transport' struct, which would have to be versioned, with a simple getter API of `get(key, &ptr)` signature. --- agent/csec_metadata.c | 60 ++++++++++++++++++++++++++++++++++--------- agent/csec_metadata.h | 39 ++++++++++++++-------------- 2 files changed, 68 insertions(+), 31 deletions(-) diff --git a/agent/csec_metadata.c b/agent/csec_metadata.c index 0a9d9d47c..0f9571a7b 100644 --- a/agent/csec_metadata.c +++ b/agent/csec_metadata.c @@ -1,5 +1,5 @@ /* - * Copyright 2020 New Relic Corporation. All rights reserved. + * Copyright 2024 New Relic Corporation. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ @@ -14,8 +14,10 @@ #include "php_compat.h" #include "php_newrelic.h" -int nr_php_csec_get_metadata(nr_php_csec_metadata_t* csec_metadata) { - if (NULL == csec_metadata) { +int nr_php_csec_get_metadata(const nr_php_csec_metadata_key_t key, void** p) { + const char* value = NULL; + + if (NULL == p) { return -1; } @@ -23,15 +25,49 @@ int nr_php_csec_get_metadata(nr_php_csec_metadata_t* csec_metadata) { return -2; } - csec_metadata->high_security = NRPRG(app)->info.high_security; - csec_metadata->entity_name = nr_strdup(nr_app_get_entity_name(NRPRG(app))); - csec_metadata->entity_type = nr_strdup(nr_app_get_entity_type(NRPRG(app))); - csec_metadata->entity_guid = nr_strdup(nr_app_get_entity_guid(NRPRG(app))); - csec_metadata->host_name = nr_strdup(nr_app_get_host_name(NRPRG(app))); - csec_metadata->agent_run_id = nr_strdup(NRPRG(app)->agent_run_id); - csec_metadata->account_id = nr_strdup(NRPRG(app)->account_id); - csec_metadata->license = nr_strdup(NRPRG(license).value); - csec_metadata->plicense = nr_strdup(NRPRG(app)->plicense); + switch (key) { + case NR_PHP_CSEC_METADATA_HIGH_SECURITY: + *p = nr_zalloc(sizeof(int)); + if (NULL == *p) { + return -3; + } + *((int*)*p) = NRPRG(app)->info.high_security; + return 0; + 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; + } + if (NULL == value) { + return -5; + } + + *p = nr_strdup(value); + if (NULL == *p) { + return -3; + } return 0; } diff --git a/agent/csec_metadata.h b/agent/csec_metadata.h index ca7a8f332..c47bf97d9 100644 --- a/agent/csec_metadata.h +++ b/agent/csec_metadata.h @@ -1,37 +1,38 @@ /* - * Copyright 2020 New Relic Corporation. All rights reserved. + * Copyright 2024 New Relic Corporation. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ #ifndef CSEC_METADATA_H #define CSEC_METADATA_H -typedef struct _nr_php_csec_metadata_t { - int high_security; /* Indicates if high security been set locally for this - application */ - char* license; /* License key provided */ - char* plicense; /* Printable license (abbreviated for security) */ - char* host_name; /* Local host name reported to the daemon */ - char* entity_name; /* Entity name related to this application */ - char* entity_type; /* Entity type */ - char* account_id; /* Security : Added for getting account id */ - char* entity_guid; /* Entity guid related to this application */ - char* agent_run_id; /* The collector's agent run ID; assigned from the - New Relic backend */ -} nr_php_csec_metadata_t; +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 : Return app meta data by populating nr_php_csec_metadata_t - * structure. The caller is responsible for freeing the memory - * allocated for the strings in the structure. + * Purpose : Copy requested app meta data into allocated *value. + * The caller is responsible for freeing the memory + * allocated. * * 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(nr_php_csec_metadata_t*); -typedef int (*nr_php_csec_get_metadata_t)(nr_php_csec_metadata_t*); +extern int nr_php_csec_get_metadata(const nr_php_csec_metadata_key_t k, void** value); +typedef int (*nr_php_csec_get_metadata_t)(const nr_php_csec_metadata_key_t k, void** value); #define NR_PHP_CSEC_GET_METADATA "nr_php_csec_get_metadata" #endif From 71b7e93a6af2c433fe5ef2864f6c2752ed0dd3e2 Mon Sep 17 00:00:00 2001 From: Michal Nowacki Date: Wed, 26 Jun 2024 14:24:01 -0400 Subject: [PATCH 4/5] simplify return value - always a string This approach adds some level of protection (compiler type checking) from misusing the API. --- agent/csec_metadata.c | 12 ++++++------ agent/csec_metadata.h | 7 ++++--- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/agent/csec_metadata.c b/agent/csec_metadata.c index 0f9571a7b..af8af2d91 100644 --- a/agent/csec_metadata.c +++ b/agent/csec_metadata.c @@ -14,7 +14,7 @@ #include "php_compat.h" #include "php_newrelic.h" -int nr_php_csec_get_metadata(const nr_php_csec_metadata_key_t key, void** p) { +int nr_php_csec_get_metadata(const nr_php_csec_metadata_key_t key, char** p) { const char* value = NULL; if (NULL == p) { @@ -27,12 +27,12 @@ int nr_php_csec_get_metadata(const nr_php_csec_metadata_key_t key, void** p) { switch (key) { case NR_PHP_CSEC_METADATA_HIGH_SECURITY: - *p = nr_zalloc(sizeof(int)); - if (NULL == *p) { - return -3; + if (NRPRG(app)->info.high_security) { + value = "true"; + } else { + value = "false"; } - *((int*)*p) = NRPRG(app)->info.high_security; - return 0; + break; case NR_PHP_CSEC_METADATA_ENTITY_NAME: value = nr_app_get_entity_name(NRPRG(app)); break; diff --git a/agent/csec_metadata.h b/agent/csec_metadata.h index c47bf97d9..a98b79339 100644 --- a/agent/csec_metadata.h +++ b/agent/csec_metadata.h @@ -21,7 +21,8 @@ typedef enum { /* * Purpose : Copy requested app meta data into allocated *value. * The caller is responsible for freeing the memory - * allocated. + * allocated. The value is a string representation of + * the requested metadata. * * Params : Pointer to a nr_php_csec_metadata_t structure * @@ -32,7 +33,7 @@ typedef enum { * -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, void** value); -typedef int (*nr_php_csec_get_metadata_t)(const nr_php_csec_metadata_key_t k, void** 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 From 587a75dadc5f7bb394e199478907846daec1909a Mon Sep 17 00:00:00 2001 From: Anmol Jain Date: Wed, 22 Jan 2025 12:40:58 +0530 Subject: [PATCH 5/5] remove csec agent config, update status log for csec config --- agent/php_minit.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/agent/php_minit.c b/agent/php_minit.c index 6a013e238..d6410e40f 100644 --- a/agent/php_minit.c +++ b/agent/php_minit.c @@ -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");