Skip to content

Commit

Permalink
Disabled Python builtins in 'if' conditions
Browse files Browse the repository at this point in the history
Details:

* Disabled the use of Python builtins in the evaluation of 'fetch-condition' and
  'export-condition' in the metric definition file. (issue #463)

Signed-off-by: Andreas Maier <[email protected]>
  • Loading branch information
andy-maier committed Feb 23, 2024
1 parent 262177f commit 3f73453
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 3 deletions.
3 changes: 3 additions & 0 deletions docs/changes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ will also work with the prior version of the file (but not vice versa).
* Increased versions of GitHub Actions plugins to increase node.js runtime
to version 20.

* Disabled the use of Python builtins in the evaluation of 'fetch-condition' and
'export-condition' in the metric definition file. (issue #463)

**Known issues:**

* See `list of open issues`_.
Expand Down
4 changes: 2 additions & 2 deletions docs/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -929,7 +929,7 @@ Where:
* ``{fetch-condition}`` is a string that is evaluated as a Python expression and
that indicates whether the metric group can be fetched. For the metric group
to actually be fetched, the ``fetch`` property also needs to be True.
The expression may use the following variables:
The expression may use the following variables; builtins are not available:

- ``hmc_version`` - HMC version as a tuple of integers (M, N, U), e.g.
(2, 16, 0).
Expand All @@ -947,7 +947,7 @@ Where:
* ``{export-condition}`` is a string that is evaluated as a Python expression
and that controls whether the metric is exported. If it evaluates to false,
the export of the metric is disabled, regardless of other such controls.
The expression may use the following variables:
The expression may use the following variables; builtins are not available:

- ``hmc_version`` - HMC version as a tuple of integers (M, N, U), e.g.
(2, 16, 0).
Expand Down
42 changes: 42 additions & 0 deletions tests/test_all.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

"""Unit tests for the zhmc_prometheus_exporter"""

import re
import time
import datetime
import hashlib
Expand Down Expand Up @@ -225,6 +226,47 @@ def test_eval_condition_resource():
assert result == 'cpc_1'


TESTCASES_EVAL_CONDITION_ERROR = [
# (condition, warn_msg_pattern)
('dir()', "NameError: name 'dir' is not defined"),
('builtins.dir()', "NameError: name 'builtins' is not defined"),
('__builtins__["dir"]', "KeyError: 'dir'"),
]


@pytest.mark.parametrize(
"condition, warn_msg_pattern",
TESTCASES_EVAL_CONDITION_ERROR
)
def test_eval_condition_error(condition, warn_msg_pattern):
"""
Tests eval_condition() with evaluation errors.
"""
session = setup_faked_session()
client = zhmcclient.Client(session)
cpc = client.cpcs.find(name='cpc_1')

# Arbitrary values for these variables, since we are not testing that here:
hmc_version = '2.16.0'
hmc_api_version = (4, 10)
hmc_features = []
se_version = '2.15.0'
se_features = []
resource_obj = cpc

with pytest.warns(UserWarning) as warn_records:

# The code to be tested
zhmc_prometheus_exporter.eval_condition(
condition, hmc_version, hmc_api_version, hmc_features, se_version,
se_features, resource_obj)

# Evaluation errors surface as one UserWarning
assert len(warn_records) == 1
warn_record = warn_records[0]
assert re.search(warn_msg_pattern, str(warn_record.message))


# Fake HMC derived from
# github.com/zhmcclient/python-zhmcclient/zhmcclient_mock/_hmc.py
class TestCreateContext(unittest.TestCase):
Expand Down
3 changes: 2 additions & 1 deletion zhmc_prometheus_exporter/zhmc_prometheus_exporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,7 @@ def eval_condition(

# The variables that can be used in the expression
eval_vars = dict(
__builtins__={},
hmc_version=hmc_version,
hmc_api_version=hmc_api_version,
hmc_features=hmc_features,
Expand All @@ -583,7 +584,7 @@ def eval_condition(

try:
# pylint: disable=eval-used
result = eval(condition, None, eval_vars)
result = eval(condition, eval_vars, None)
except Exception as exc: # pylint: disable=broad-exception-caught
warnings.warn("Ignoring item because its condition {!r} does not "
"properly evaluate: {}: {}".
Expand Down

0 comments on commit 3f73453

Please sign in to comment.