Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 2 additions & 11 deletions packages/os/os.spec
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,6 @@ Conflicts: %{_cross_os}image-feature(no-host-containers)
Summary: Compliance check framework
Requires: (%{_cross_os}bloodhound-k8s if %{_cross_os}variant-runtime(k8s))
Requires: (%{_cross_os}bloodhound-k8s-overrides if %{_cross_os}variant-runtime(k8s))
Requires: (%{_cross_os}bloodhound-fips if %{_cross_os}image-feature(fips))
%description -n %{_cross_os}bloodhound
%{summary}.

Expand All @@ -415,12 +414,6 @@ Requires: (%{_cross_os}bloodhound and %{_cross_os}variant-runtime(k8s))
%description -n %{_cross_os}bloodhound-k8s-overrides
%{summary}.

%package -n %{_cross_os}bloodhound-fips
Summary: Compliance checks for FIPS
Requires: (%{_cross_os}bloodhound and %{_cross_os}image-feature(fips))
%description -n %{_cross_os}bloodhound-fips
%{summary}.

%package -n %{_cross_os}xfscli
Summary: XFS progs cli
%description -n %{_cross_os}xfscli
Expand Down Expand Up @@ -977,7 +970,9 @@ install -p -m 0644 %{S:400} %{S:401} %{S:402} %{buildroot}%{_cross_licensedir}
%files -n %{_cross_os}bloodhound
%{_cross_bindir}/bloodhound
%{_cross_bindir}/bottlerocket-cis-checks
%{_cross_bindir}/bottlerocket-fips-checks
%{_cross_libexecdir}/cis-checks/bottlerocket
%{_cross_libexecdir}/fips-checks/bottlerocket
%exclude %{_cross_libexecdir}/cis-checks/bottlerocket/br03040101.json

%files -n %{_cross_os}bloodhound-k8s
Expand All @@ -988,10 +983,6 @@ install -p -m 0644 %{S:400} %{S:401} %{S:402} %{buildroot}%{_cross_licensedir}
%{_cross_libexecdir}/cis-checks/bottlerocket/br03040101.json
%{_cross_libexecdir}/cis-checks/kubernetes/k8s04021000.json

%files -n %{_cross_os}bloodhound-fips
%{_cross_bindir}/bottlerocket-fips-checks
%{_cross_libexecdir}/fips-checks/bottlerocket

%files -n %{_cross_os}xfscli
%{_cross_sbindir}/xfs_admin
%{_cross_sbindir}/xfs_info
Expand Down
73 changes: 63 additions & 10 deletions sources/bloodhound/src/bin/bottlerocket-fips-checks/checks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,34 @@ const EXPECTED_FIPS_NAME: &str = "Amazon Linux 2023 Kernel Cryptographic API";
const FIPS_KERNEL_CHECK_MARKER: &str = "/etc/.fips-kernel-check-passed";
const FIPS_MODULE_CHECK_MARKER: &str = "/etc/.fips-module-check-passed";

/// Checks whether kernel FIPS mode is active by reading /proc/sys/crypto/fips_enabled.
fn is_fips_enabled(sac: &dyn SystemAccess) -> bool {
look_for_strings_in_file(sac, CRYPTO_FIPS_ENABLED, &[EXPECTED_FIPS_ENABLED]).unwrap_or(false)
}

/// Returns a SKIP result indicating FIPS is not enabled on this system.
fn skip_fips_not_enabled() -> CheckerResult {
CheckerResult {
status: CheckStatus::SKIP,
error: "FIPS mode is not enabled on this system".to_string(),
..Default::default()
}
}

// =>o.o<= =>o.o<= =>o.o<= =>o.o<= =>o.o<= =>o.o<= =>o.o<= =>o.o<= =>o.o<= =>o.o<=

pub struct FIPS01000000Checker {}

impl Checker for FIPS01000000Checker {
fn execute(&self, sac: &dyn SystemAccess) -> CheckerResult {
check_file_contains!(
sac,
CRYPTO_FIPS_ENABLED,
&[EXPECTED_FIPS_ENABLED],
format!("{CRYPTO_FIPS_ENABLED} != {EXPECTED_FIPS_ENABLED}"),
format!("{CRYPTO_FIPS_ENABLED} not found")
)
if is_fips_enabled(sac) {
CheckerResult {
status: CheckStatus::PASS,
..Default::default()
}
} else {
skip_fips_not_enabled()
}
}

fn metadata(&self) -> CheckerMetadata {
Expand All @@ -43,6 +58,9 @@ pub struct FIPS01010000Checker {}

impl Checker for FIPS01010000Checker {
fn execute(&self, sac: &dyn SystemAccess) -> CheckerResult {
if !is_fips_enabled(sac) {
return skip_fips_not_enabled();
}
check_file_contains!(
sac,
CRYPTO_FIPS_NAME,
Expand All @@ -54,7 +72,7 @@ impl Checker for FIPS01010000Checker {

fn metadata(&self) -> CheckerMetadata {
CheckerMetadata {
title: format!("FIPS module is {EXPECTED_FIPS_NAME}.").to_string(),
title: format!("FIPS module is {EXPECTED_FIPS_NAME}."),
id: "1.1".to_string(),
level: 0,
name: "fips01010000".to_string(),
Expand All @@ -69,13 +87,16 @@ pub struct FIPS01020000Checker {}

impl Checker for FIPS01020000Checker {
fn execute(&self, sac: &dyn SystemAccess) -> CheckerResult {
if !is_fips_enabled(sac) {
return skip_fips_not_enabled();
}

let result = check_file_exists!(
sac,
FIPS_KERNEL_CHECK_MARKER,
format!("{FIPS_KERNEL_CHECK_MARKER} not found")
);

// Check if we need to continue
if result.status == CheckStatus::FAIL {
return result;
}
Expand Down Expand Up @@ -118,7 +139,7 @@ mod tests {
usac.register_file(CRYPTO_FIPS_ENABLED, "0");
let checker = FIPS01000000Checker {};
let result = checker.execute(&usac);
assert_eq!(result.status, CheckStatus::FAIL);
assert_eq!(result.status, CheckStatus::SKIP);
}
#[test]
pub fn test_fips01000000checker_fips_enabled() {
Expand All @@ -140,6 +161,7 @@ mod tests {
#[test]
pub fn test_fips01010000checker_wrong_fips_name() {
let mut usac = UnitTestSystemAccess::default();
usac.register_file(CRYPTO_FIPS_ENABLED, EXPECTED_FIPS_ENABLED);
usac.register_file(CRYPTO_FIPS_NAME, "some wrong name");
let checker = FIPS01010000Checker {};
let result = checker.execute(&usac);
Expand All @@ -149,6 +171,7 @@ mod tests {
#[test]
pub fn test_fips01010000checker_passing() {
let mut usac = UnitTestSystemAccess::default();
usac.register_file(CRYPTO_FIPS_ENABLED, EXPECTED_FIPS_ENABLED);
usac.register_file(CRYPTO_FIPS_NAME, EXPECTED_FIPS_NAME);
let checker = FIPS01010000Checker {};
let result = checker.execute(&usac);
Expand All @@ -158,6 +181,7 @@ mod tests {
#[test]
pub fn test_fips01020000checker_missing_module_check_marker() {
let mut usac = UnitTestSystemAccess::default();
usac.register_file(CRYPTO_FIPS_ENABLED, EXPECTED_FIPS_ENABLED);
usac.register_file(FIPS_KERNEL_CHECK_MARKER, "1");
let checker = FIPS01020000Checker {};
let result = checker.execute(&usac);
Expand All @@ -166,6 +190,7 @@ mod tests {
#[test]
pub fn test_fips01020000checker_missing_kernel_check_marker() {
let mut usac = UnitTestSystemAccess::default();
usac.register_file(CRYPTO_FIPS_ENABLED, EXPECTED_FIPS_ENABLED);
usac.register_file(FIPS_MODULE_CHECK_MARKER, "1");
let checker = FIPS01020000Checker {};
let result = checker.execute(&usac);
Expand All @@ -174,10 +199,38 @@ mod tests {
#[test]
pub fn test_fips01020000checker_passing() {
let mut usac = UnitTestSystemAccess::default();
usac.register_file(CRYPTO_FIPS_ENABLED, EXPECTED_FIPS_ENABLED);
usac.register_file(FIPS_KERNEL_CHECK_MARKER, "1");
usac.register_file(FIPS_MODULE_CHECK_MARKER, "1");
let checker = FIPS01020000Checker {};
let result = checker.execute(&usac);
assert_eq!(result.status, CheckStatus::PASS);
}

#[test]
pub fn test_is_fips_enabled_true() {
let mut usac = UnitTestSystemAccess::default();
usac.register_file(CRYPTO_FIPS_ENABLED, EXPECTED_FIPS_ENABLED);
assert!(is_fips_enabled(&usac));
}

#[test]
pub fn test_is_fips_enabled_false() {
let mut usac = UnitTestSystemAccess::default();
usac.register_file(CRYPTO_FIPS_ENABLED, "0");
assert!(!is_fips_enabled(&usac));
}

#[test]
pub fn test_is_fips_enabled_missing_file() {
let usac = UnitTestSystemAccess::default();
assert!(!is_fips_enabled(&usac));
}

#[test]
pub fn test_skip_fips_not_enabled() {
let result = skip_fips_not_enabled();
assert_eq!(result.status, CheckStatus::SKIP);
assert!(!result.error.is_empty());
}
}
Loading