Skip to content

Commit 05ce03c

Browse files
authored
[linux_proc_extras] Add kernel FIPS mode metric (DataDog#24869)
* [linux_proc_extras] add kernel FIPS mode metric Signed-off-by: Jared Ledvina <jared.ledvina@datadoghq.com> * [linux_proc_extras] add type hints and test FIPS procfs path Signed-off-by: Jared Ledvina <jared.ledvina@datadoghq.com> --------- Signed-off-by: Jared Ledvina <jared.ledvina@datadoghq.com>
1 parent fed862c commit 05ce03c

6 files changed

Lines changed: 82 additions & 0 deletions

File tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add the `system.crypto.fips_enabled` metric reporting whether the kernel is running in FIPS mode, read from `/proc/sys/crypto/fips_enabled`.

linux_proc_extras/datadog_checks/linux_proc_extras/linux_proc_extras.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ def check(self, instance):
3737
self.get_inode_info()
3838
self.get_stat_info()
3939
self.get_entropy_info()
40+
self.get_fips_info()
4041
self.get_process_states()
4142
if self.instance.get('include_interrupt_metrics', False):
4243
self.get_interrupts_info()
@@ -48,6 +49,7 @@ def set_paths(self):
4849
"inode_info": "sys/fs/inode-nr",
4950
"stat_info": "stat",
5051
"entropy_info": "sys/kernel/random/entropy_avail",
52+
"fips_info": "sys/crypto/fips_enabled",
5153
"interrupts_info": "interrupts",
5254
}
5355

@@ -79,6 +81,24 @@ def get_entropy_info(self):
7981
entropy = entropy_info.readline()
8082
self.gauge('system.entropy.available', float(entropy), tags=self.tags)
8183

84+
def get_fips_info(self) -> None:
85+
fips_path = self.proc_path_map['fips_info']
86+
try:
87+
with open(fips_path, 'r') as fips_info:
88+
fips_enabled = int(fips_info.readline().strip())
89+
except FileNotFoundError:
90+
self.log.debug(
91+
"%s does not exist, the kernel was built without CONFIG_CRYPTO_FIPS "
92+
"and cannot be in FIPS mode: reporting 0",
93+
fips_path,
94+
)
95+
fips_enabled = 0
96+
except (OSError, ValueError) as e:
97+
self.log.warning("Could not determine kernel FIPS mode from %s: %s", fips_path, e)
98+
return
99+
100+
self.gauge('system.crypto.fips_enabled', float(fips_enabled), tags=self.tags)
101+
82102
def get_process_states(self):
83103
state_counts = defaultdict(int)
84104
prio_counts = defaultdict(int)

linux_proc_extras/metadata.csv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
metric_name,metric_type,interval,unit_name,per_unit_name,description,orientation,integration,short_name,curated_metric
2+
system.crypto.fips_enabled,gauge,,,,1 if the kernel is running in FIPS mode as reported by /proc/sys/crypto/fips_enabled and 0 otherwise,0,linux_proc_extras,fips enabled,
23
system.entropy.available,gauge,,,,system entropy,0,linux_proc_extras,entropy,
34
system.inodes.total,gauge,,,,number of inodes the system has allocated,0,linux_proc_extras,nr_inodes,
45
system.inodes.used,gauge,,,,number of used inodes,0,linux_proc_extras,used_inodes,

linux_proc_extras/tests/common.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
'system.linux.processes_created',
2323
'system.linux.interrupts',
2424
'system.entropy.available',
25+
'system.crypto.fips_enabled',
2526
'system.processes.states',
2627
'system.processes.priorities',
2728
]
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
1

linux_proc_extras/tests/test_linux_proc_extras.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66
import pytest
77
from mock import mock_open, patch
88

9+
from datadog_checks.base.stubs.aggregator import AggregatorStub
10+
from datadog_checks.base.stubs.datadog_agent import DatadogAgentStub
11+
from datadog_checks.linux_proc_extras import MoreUnixCheck
12+
913
from . import common
1014

1115
pytestmark = pytest.mark.unit
@@ -31,6 +35,11 @@ def test_check(aggregator, check):
3135
with patch('datadog_checks.linux_proc_extras.linux_proc_extras.open', m):
3236
check.get_stat_info()
3337

38+
with open(os.path.join(common.FIXTURE_DIR, "fips_enabled")) as f:
39+
m = mock_open(read_data=f.read())
40+
with patch('datadog_checks.linux_proc_extras.linux_proc_extras.open', m):
41+
check.get_fips_info()
42+
3443
with open(os.path.join(common.FIXTURE_DIR, "process_stats")) as f:
3544
with patch(
3645
'datadog_checks.linux_proc_extras.linux_proc_extras.get_subprocess_output', return_value=(f.read(), "", 0)
@@ -52,3 +61,52 @@ def test_check(aggregator, check):
5261
aggregator.assert_metric("system.linux.irq", value=None, tags=tags)
5362

5463
aggregator.assert_all_metrics_covered()
64+
65+
66+
@pytest.mark.parametrize('content, expected_value', [('1\n', 1.0), ('0\n', 0.0)])
67+
def test_fips_info(aggregator: AggregatorStub, check: MoreUnixCheck, content: str, expected_value: float) -> None:
68+
m = mock_open(read_data=content)
69+
with patch('datadog_checks.linux_proc_extras.linux_proc_extras.open', m):
70+
check.get_fips_info()
71+
72+
m.assert_called_once_with('/proc/sys/crypto/fips_enabled', 'r')
73+
aggregator.assert_metric('system.crypto.fips_enabled', value=expected_value, count=1, tags=[common.EXPECTED_TAG])
74+
aggregator.assert_all_metrics_covered()
75+
76+
77+
def test_fips_info_honors_procfs_path(
78+
aggregator: AggregatorStub, check: MoreUnixCheck, datadog_agent: DatadogAgentStub
79+
) -> None:
80+
with patch.dict(datadog_agent._config, {'procfs_path': '/host/proc'}):
81+
check.set_paths()
82+
83+
m = mock_open(read_data='1\n')
84+
with patch('datadog_checks.linux_proc_extras.linux_proc_extras.open', m):
85+
check.get_fips_info()
86+
87+
m.assert_called_once_with('/host/proc/sys/crypto/fips_enabled', 'r')
88+
aggregator.assert_metric('system.crypto.fips_enabled', value=1.0, count=1, tags=[common.EXPECTED_TAG])
89+
aggregator.assert_all_metrics_covered()
90+
91+
92+
def test_fips_info_missing_file(aggregator: AggregatorStub, check: MoreUnixCheck) -> None:
93+
with patch('datadog_checks.linux_proc_extras.linux_proc_extras.open', side_effect=FileNotFoundError):
94+
check.get_fips_info()
95+
96+
aggregator.assert_metric('system.crypto.fips_enabled', value=0.0, count=1, tags=[common.EXPECTED_TAG])
97+
aggregator.assert_all_metrics_covered()
98+
99+
100+
def test_fips_info_unreadable(aggregator: AggregatorStub, check: MoreUnixCheck) -> None:
101+
with patch('datadog_checks.linux_proc_extras.linux_proc_extras.open', side_effect=PermissionError):
102+
check.get_fips_info()
103+
104+
aggregator.assert_metric('system.crypto.fips_enabled', count=0)
105+
106+
107+
def test_fips_info_unparseable(aggregator: AggregatorStub, check: MoreUnixCheck) -> None:
108+
m = mock_open(read_data='not a number\n')
109+
with patch('datadog_checks.linux_proc_extras.linux_proc_extras.open', m):
110+
check.get_fips_info()
111+
112+
aggregator.assert_metric('system.crypto.fips_enabled', count=0)

0 commit comments

Comments
 (0)