Skip to content

Commit

Permalink
Don't generate DSA ssh key if system FIPS is enabled
Browse files Browse the repository at this point in the history
  • Loading branch information
s0undt3ch committed Sep 13, 2021
1 parent d6859b6 commit e43bfe6
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 4 deletions.
1 change: 1 addition & 0 deletions changelog/80.improvement.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The ``sshd`` server no longer generates ``dsa`` keys if the system has FIPS enabled
1 change: 1 addition & 0 deletions requirements/tests.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
-r base.txt
docker
pytest-subtests
pyfakefs; python_version >= '3.5'
4 changes: 3 additions & 1 deletion src/saltfactories/daemons/sshd.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

from saltfactories.bases import Daemon
from saltfactories.exceptions import FactoryFailure
from saltfactories.utils import platform
from saltfactories.utils import ports
from saltfactories.utils import running_username
from saltfactories.utils import socket
Expand Down Expand Up @@ -97,7 +98,8 @@ def _write_config(self):
config_lines.append("{} {}\n".format(key, value))

# Let's generate the host keys
self._generate_server_dsa_key()
if platform.is_fips_enabled() is False:
self._generate_server_dsa_key()
self._generate_server_ecdsa_key()
self._generate_server_ed25519_key()
for host_key in pathlib.Path(self.config_dir).glob("ssh_host_*_key"):
Expand Down
37 changes: 37 additions & 0 deletions src/saltfactories/utils/platform.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
Platform related utilities
"""
import pathlib
import shutil
import subprocess
import sys

import salt.utils.platform
Expand Down Expand Up @@ -154,3 +157,37 @@ def on_platforms(
return True

return False


def is_fips_enabled():
"""
Check is FIPS is enabled
:return bool: Return true when enabled
"""
if pathlib.Path("/etc/system-fips").exists():
return True
kernel_fips_enabled_path = pathlib.Path("/proc/sys/crypto/fips_enabled")
if kernel_fips_enabled_path.exists() and kernel_fips_enabled_path.read_text().strip() == "1":
return True
sysctl_path = shutil.which("sysctl")
if not sysctl_path:
return False
ret = subprocess.run(
[sysctl_path, "crypto.fips_enabled"],
check=False,
shell=False,
stdout=subprocess.PIPE,
universal_newlines=True,
)
if ret.returncode == 0:
stripped_output = ret.stdout.strip()
if not stripped_output:
# No output?
return False
if "=" not in stripped_output:
# Don't know how to parse this
return False
if stripped_output.split("=")[-1].strip() == "1":
return True
return False
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
"""
tests.unit.utils.test_platforms
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tests.unit.utils.test_platform
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Tests for saltfactories.utils.platforms
Tests for saltfactories.utils.platform
"""
import subprocess
import sys
from unittest import mock

import pytest

import saltfactories.utils.platform


Expand Down Expand Up @@ -127,3 +131,38 @@ def test_is_not_aarch64():
return_value = False
with mock.patch("sys.platform", "not_aarch64"):
assert saltfactories.utils.platform.is_aarch64() is return_value


@pytest.mark.skipif(sys.version_info < (3, 6), reason="pyfakes is not available on Py3.5")
def test_is_fips_enabled_etc_system_fips(fs):
fs.create_file("/etc/system-fips")
assert saltfactories.utils.platform.is_fips_enabled() is True


@pytest.mark.skipif(sys.version_info < (3, 6), reason="pyfakes is not available on Py3.5")
@pytest.mark.parametrize("value, expected", [("0", False), ("1", True)])
def test_is_fips_enabled_procfs(fs, value, expected):
fs.create_file("/proc/sys/crypto/fips_enabled", contents=value)
assert saltfactories.utils.platform.is_fips_enabled() is expected


@pytest.mark.parametrize(
"output, expected",
(
("", False),
("crypto.fips_enabled", False),
("crypto.fips_enabled =", False),
("crypto.fips_enabled = 0", False),
("crypto.fips_enabled=1", True),
("crypto.fips_enabled = 1", True),
("crypto.fips_enabled = 1", True),
),
)
def test_is_fips_enabled_sysctl(output, expected):
subprocess_run_return_value = subprocess.CompletedProcess(
args=(), returncode=0, stdout=output, stderr=None
)
with mock.patch("shutil.which", return_value="sysctl"), mock.patch(
"subprocess.run", return_value=subprocess_run_return_value
):
assert saltfactories.utils.platform.is_fips_enabled() is expected

0 comments on commit e43bfe6

Please sign in to comment.