@@ -64,6 +64,7 @@ public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $buil
64
64
$ node
65
65
->children ()
66
66
->scalarNode ('string_key ' )->end ()
67
+ ->scalarNode ('env_string_key ' )->end ()
67
68
->scalarNode ('other_string_key ' )->end ()
68
69
->scalarNode ('another_string_key ' )->end ()
69
70
->scalarNode ('string_key_with_quoted_hex_value ' )->end ()
@@ -76,6 +77,7 @@ public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $buil
76
77
->scalarNode ('string_key_with_default ' )->end ()
77
78
->variableNode ('undefined_key ' )->end ()
78
79
->variableNode ('${STRING_VALUE} ' )->end ()
80
+ ->scalarNode ('recursive_key ' )->end ()
79
81
->end ()
80
82
;
81
83
@@ -90,6 +92,8 @@ public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $buil
90
92
'FLOAT_VALUE ' => '1.1 ' ,
91
93
'HEX_VALUE ' => '0xdeadbeef ' ,
92
94
'INVALID_MAP_VALUE ' => "value \nkey:value " ,
95
+ 'DO_NOT_REPLACE_ME ' => 'Never use this value ' , // An unused environment variable
96
+ 'REPLACE_ME ' => '${DO_NOT_REPLACE_ME} ' , // A valid replacement text, used verbatim, not replaced with "Never use this value"
93
97
]),
94
98
]),
95
99
);
@@ -98,6 +102,7 @@ public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $buil
98
102
$ parsed = $ factory ->process ([
99
103
Yaml::parse (<<<'YAML'
100
104
string_key: ${STRING_VALUE} # Valid reference to STRING_VALUE
105
+ env_string_key: ${env:STRING_VALUE} # Valid reference to STRING_VALUE
101
106
other_string_key: "${STRING_VALUE}" # Valid reference to STRING_VALUE inside double quotes
102
107
another_string_key: "${BOOl_VALUE}" # Valid reference to BOOl_VALUE inside double quotes
103
108
string_key_with_quoted_hex_value: "${HEX_VALUE}" # Valid reference to HEX_VALUE inside double quotes
@@ -110,12 +115,14 @@ public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $buil
110
115
string_key_with_default: ${UNDEFINED_KEY:-fallback} # UNDEFINED_KEY is not defined but a default value is included
111
116
undefined_key: ${UNDEFINED_KEY} # Invalid reference, UNDEFINED_KEY is not defined and is replaced with ""
112
117
${STRING_VALUE}: value # Invalid reference, substitution is not valid in mapping keys and reference is ignored
118
+ recursive_key: ${REPLACE_ME} # Valid reference to REPLACE_ME
113
119
YAML),
114
120
]);
115
121
116
122
$ this ->assertSame (
117
123
Yaml::parse (<<<'YAML'
118
124
string_key: value # Interpreted as type string, tag URI tag:yaml.org,2002:str
125
+ env_string_key: value # Interpreted as type string, tag URI tag:yaml.org,2002:str
119
126
other_string_key: "value" # Interpreted as type string, tag URI tag:yaml.org,2002:str
120
127
another_string_key: "true" # Interpreted as type string, tag URI tag:yaml.org,2002:str
121
128
string_key_with_quoted_hex_value: "0xdeadbeef" # Interpreted as type string, tag URI tag:yaml.org,2002:str
@@ -129,6 +136,7 @@ public function getConfig(ComponentProviderRegistry $registry, NodeBuilder $buil
129
136
# undefined_key removed as null is treated as unset
130
137
undefined_key: # Interpreted as type null, tag URI tag:yaml.org,2002:null
131
138
${STRING_VALUE}: value # Interpreted as type string, tag URI tag:yaml.org,2002:str
139
+ recursive_key: ${DO_NOT_REPLACE_ME} # Interpreted as type string, tag URI tag:yaml.org,2002:str
132
140
YAML),
133
141
self ::getPropertiesFromPlugin ($ parsed ),
134
142
);
@@ -152,6 +160,24 @@ public function test_env_substitution_string(): void
152
160
$ this ->assertSame ('example-service ' , self ::getPropertiesFromPlugin ($ parsed )['resource ' ]['attributes ' ]['service.name ' ]);
153
161
}
154
162
163
+ #[BackupGlobals(true )]
164
+ #[CoversNothing]
165
+ public function test_env_substitution_with_env_prefix (): void
166
+ {
167
+ $ _SERVER ['OTEL_SERVICE_NAME ' ] = 'example-service ' ;
168
+ $ parsed = self ::factory ()->process ([[
169
+ 'file_format ' => '0.1 ' ,
170
+ 'resource ' => [
171
+ 'attributes ' => [
172
+ 'service.name ' => '${env:OTEL_SERVICE_NAME} ' ,
173
+ ],
174
+ ],
175
+ ]]);
176
+
177
+ $ this ->assertInstanceOf (ComponentPlugin::class, $ parsed );
178
+ $ this ->assertSame ('example-service ' , self ::getPropertiesFromPlugin ($ parsed )['resource ' ]['attributes ' ]['service.name ' ]);
179
+ }
180
+
155
181
#[BackupGlobals(true )]
156
182
public function test_env_substitution_non_string (): void
157
183
{
@@ -167,6 +193,29 @@ public function test_env_substitution_non_string(): void
167
193
$ this ->assertSame (2048 , self ::getPropertiesFromPlugin ($ parsed )['attribute_limits ' ]['attribute_value_length_limit ' ]);
168
194
}
169
195
196
+ /**
197
+ * It MUST NOT be possible to inject environment variable by environment variables.
198
+ * For example, see references to DO_NOT_REPLACE_ME environment variable
199
+ */
200
+ #[BackupGlobals(true )]
201
+ #[CoversNothing]
202
+ public function test_env_substitution_recursive_does_not_inject_environment_variables (): void
203
+ {
204
+ $ _SERVER ['DO_NOT_REPLACE_ME ' ] = 'Never use this value ' ;
205
+ $ _SERVER ['REPLACE_ME ' ] = '${DO_NOT_REPLACE_ME} ' ;
206
+ $ parsed = self ::factory ()->process ([[
207
+ 'file_format ' => '0.1 ' ,
208
+ 'resource ' => [
209
+ 'attributes ' => [
210
+ 'service.name ' => '${REPLACE_ME} ' ,
211
+ ],
212
+ ],
213
+ ]]);
214
+
215
+ $ this ->assertInstanceOf (ComponentPlugin::class, $ parsed );
216
+ $ this ->assertSame ('${DO_NOT_REPLACE_ME} ' , self ::getPropertiesFromPlugin ($ parsed )['resource ' ]['attributes ' ]['service.name ' ]);
217
+ }
218
+
170
219
/**
171
220
* If a property has a default value defined (i.e. is _not_ required) and is
172
221
* missing or present but null, Create MUST ensure the SDK component is configured
0 commit comments