[yocto] [meta-security][PATCH 13/14] runtime qa: moderize ima test

Armin Kuster akuster808 at gmail.com
Sun May 26 21:56:40 PDT 2019


Signed-off-by: Armin Kuster <akuster808 at gmail.com>
---
 meta-integrity/lib/oeqa/runtime/__init__.py  |   0
 meta-integrity/lib/oeqa/runtime/cases/ima.py | 129 +++++++++++++++++++
 meta-integrity/lib/oeqa/runtime/ima.py       |  82 ------------
 3 files changed, 129 insertions(+), 82 deletions(-)
 delete mode 100644 meta-integrity/lib/oeqa/runtime/__init__.py
 create mode 100644 meta-integrity/lib/oeqa/runtime/cases/ima.py
 delete mode 100644 meta-integrity/lib/oeqa/runtime/ima.py

diff --git a/meta-integrity/lib/oeqa/runtime/__init__.py b/meta-integrity/lib/oeqa/runtime/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/meta-integrity/lib/oeqa/runtime/cases/ima.py b/meta-integrity/lib/oeqa/runtime/cases/ima.py
new file mode 100644
index 0000000..0c8617a
--- /dev/null
+++ b/meta-integrity/lib/oeqa/runtime/cases/ima.py
@@ -0,0 +1,129 @@
+#!/usr/bin/env python
+#
+# Authors:  Cristina Moraru <cristina.moraru at intel.com>
+#           Alexandru Cornea <alexandru.cornea at intel.com>
+
+import string
+from time import sleep
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.runtime.decorator.package import OEHasPackage
+from oeqa.core.decorator.data import skipIfNotFeature
+from oeqa.core.decorator.data import skipIfDataVar, skipIfNotDataVar
+import bb
+blacklist = ["/usr/bin/uz", "/bin/su.shadow"]
+
+class IMACheck(OERuntimeTestCase):
+
+    @classmethod
+    def setUpClass(cls):
+        locations = ["/bin", "/usr/bin"]
+        cls.binaries = []
+        for l in locations:
+            status, output = cls.tc.target.run("find %s -type f" % l)
+            cls.binaries.extend(output.split("\n"))
+
+        cls.total = len(cls.binaries)
+
+
+    @OETestDepends(['ssh.SSHTest.test_ssh'])
+    def test_ima_enabled(self):
+        ''' Test if IMA policy is loaded before systemd starts'''
+
+        ima_search = "ima: "
+        systemd_search = "systemd .* running"
+        status, output = self.target.run("dmesg | grep -n '%s'" % ima_search)
+        self.assertEqual( status, 0, "Did not find '%s' in dmesg" % ima_search)
+
+
+    @skipIfNotFeature('systemd',
+                      'Test requires systemd to be in DISTRO_FEATURES')
+    @skipIfNotDataVar('VIRTUAL-RUNTIME_init_manager', 'systemd',
+                      'systemd is not the init manager for this image')
+    @OETestDepends(['ima.IMACheck.test_ima_enabled'])
+    def test_ima_before_systemd(self):
+        ''' Test if IMA policy is loaded before systemd starts'''
+        ima_search = "ima: "
+        systemd_search = "systemd .* running"
+        status, output = self.target.run("dmesg | grep -n '%s'" % ima_search)
+        self.assertEqual( status, 0, "Did not find '%s' in dmesg" % ima_search)
+        ima_id = int(output.split(":")[0])
+        status, output = self.target.run("dmesg | grep -n '%s'" % systemd_search)
+        self.assertEqual(status, 0, "Did not find '%s' in dmesg" % systemd_search)
+        init_id = int(output.split(":")[0])
+        if ima_id > init_id:
+            self.fail("IMA does not start before systemd")
+
+
+    @OETestDepends(['ima.IMACheck.test_ima_enabled'])
+    def test_ima_hash(self):
+        ''' Test if IMA stores correct file hash '''
+        filename = "/etc/filetest"
+        ima_measure_file = "/sys/kernel/security/ima/ascii_runtime_measurements"
+        status, output = self.target.run("echo test > %s" % filename)
+        self.assertEqual(status, 0, "Cannot create file %s on target" % filename)
+
+        # wait for the IMA system to update the entry
+        maximum_tries = 30
+        tries = 0
+        status, output = self.target.run("sha1sum %s" %filename)
+        sleep(2)
+        current_hash = output.split()[0]
+        ima_hash = ""
+
+        while tries < maximum_tries:
+            status, output = self.target.run("cat %s | grep %s" \
+                % (ima_measure_file, filename))
+            # get last entry, 4th field
+            if status == 0:
+                tokens = output.split("\n")[-1].split()[3]
+                ima_hash = tokens.split(":")[1]
+                if ima_hash == current_hash:
+                    break
+
+            tries += 1
+            sleep(1)
+
+        # clean target
+        self.target.run("rm %s" % filename)
+        if ima_hash != current_hash:
+            self.fail("Hash stored by IMA does not match actual hash")
+
+
+    @OETestDepends(['ima.IMACheck.test_ima_enabled'])
+    def test_ima_signature(self):
+        ''' Test if IMA stores correct signature for system binaries'''
+        passed = 0
+        failed = 0
+        for b in self.binaries:
+            if b in blacklist:
+                continue
+            status, output = self.target.run("evmctl ima_verify %s" % b)
+            if status != 0:
+                failed += 1
+            else:
+                passed += 1
+
+        if failed == self.total:
+             self.fail("Signature verifications failed (%s)" % self.total)
+
+        #bb.warn("pass: %s, fail: %s, Total: %s" % (passed, failed, total))
+
+    @OETestDepends(['ima.IMACheck.test_ima_enabled'])
+    def test_ima_overwrite(self):
+        ''' Test if IMA prevents overwriting signed files '''
+        passed = 0
+        failed = 0
+        for b in self.binaries:
+            if b in blacklist:
+                continue
+            self.target.run("echo 'foo' >> %s" % b )
+            status, output = self.target.run("evmctl ima_verify %s" % b)
+
+            if status != 0:
+                failed += 1
+            else:
+                passed += 1
+
+        if failed == self.total:
+             self.fail("Overwritting verifications failed (%s)" % self.total)
diff --git a/meta-integrity/lib/oeqa/runtime/ima.py b/meta-integrity/lib/oeqa/runtime/ima.py
deleted file mode 100644
index 2e5b258..0000000
--- a/meta-integrity/lib/oeqa/runtime/ima.py
+++ /dev/null
@@ -1,82 +0,0 @@
-#!/usr/bin/env python
-#
-# Authors:  Cristina Moraru <cristina.moraru at intel.com>
-#           Alexandru Cornea <alexandru.cornea at intel.com>
-
-import unittest
-import string
-from time import sleep
-from oeqa.oetest import oeRuntimeTest, skipModule
-from oeqa.utils.decorators import *
-
- at tag(TestType = 'FVT', FeatureID = 'IOTOS-617,IOTOS-619')
-class IMACheck(oeRuntimeTest):
-    def test_ima_before_systemd(self):
-        ''' Test if IMA policy is loaded before systemd starts'''
-
-        ima_search = "IMA: policy update completed"
-        systemd_search = "systemd .* running"
-        status, output = self.target.run("dmesg | grep -n '%s'" %ima_search)
-        self.assertEqual( status, 0, "Did not find '%s' in dmesg" %ima_search)
-        ima_id = int(output.split(":")[0])
-        status, output = self.target.run("dmesg | grep -n '%s'" %systemd_search)
-        self.assertEqual(status, 0, "Did not find '%s' in dmesg" %systemd_search)
-        init_id = int(output.split(":")[0])
-        if ima_id > init_id:
-            self.fail("IMA does not start before systemd")
-
-    def test_ima_hash(self):
-        ''' Test if IMA stores correct file hash '''
-        filename = "/etc/filetest"
-        ima_measure_file = "/sys/kernel/security/ima/ascii_runtime_measurements"
-        status, output = self.target.run("echo test > %s" %filename)
-        self.assertEqual(status, 0, "Cannot create file %s on target" %filename)
-
-        # wait for the IMA system to update the entry
-        maximum_tries = 30
-        tries = 0
-        status, output = self.target.run("sha1sum %s" %filename)
-        current_hash = output.split()[0]
-        ima_hash = ""
-
-        while tries < maximum_tries:
-            status, output = self.target.run("cat %s | grep %s" \
-                                            %(ima_measure_file, filename))
-            # get last entry, 4th field
-            if status == 0:
-                tokens = output.split("\n")[-1].split()[3]
-                ima_hash = tokens.split(":")[1]
-                if ima_hash == current_hash:
-                    break
-
-            tries += 1
-            sleep(1)
-
-        # clean target
-        self.target.run("rm %s" %filename)
-        if ima_hash != current_hash:
-            self.fail("Hash stored by IMA does not match actual hash")
-
-    def test_ima_signature(self):
-        ''' Test if IMA stores correct signature for system binaries'''
-        locations = ["/bin", "/usr/bin"]
-        binaries = []
-        for l in locations:
-            status, output = self.target.run("find %s -type f" %l)
-            binaries.extend(output.split("\n"))
-
-        for b in binaries:
-            status, output = self.target.run("evmctl ima_verify %s" %b)
-            if "Verification is OK" not in output:
-                self.fail("IMA signature verification fails for file %s" %b)
-
-    def test_ima_overwrite(self):
-        ''' Test if IMA prevents overwriting signed files '''
-        status, output = self.target.run("find /bin -type f")
-        self.assertEqual(status, 0 , "ssh to device fail: %s" %output)  
-        signed_file = output.strip().split()[0]
-        print("\n signed_file is %s" % signed_file)
-        status, output = self.target.run(" echo 'foo' >> %s" %signed_file)
-        self.assertNotEqual(status, 0 , "Signed file could be written")
-        self.assertIn("Permission denied", output,
-                      "Did not find expected error message. Got: %s" %output)
-- 
2.17.1



More information about the yocto mailing list