@@ -452,3 +452,15 @@ def compare_signatures(old_sigs, curr_sigs):
msg.extend([' ' + line for line in output.splitlines()])
msg.append('')
return '\n'.join(msg)
+
+
+def get_git_toplevel(directory):
+ """
+ Try and find the top of the git repository that directory might be in.
+ Returns the top-level directory, or None.
+ """
+ cmd = ["git", "-C", directory, "rev-parse", "--show-toplevel"]
+ try:
+ return subprocess.check_output(cmd, text=True).strip()
+ except:
+ return None
@@ -7,7 +7,7 @@ import glob
import os
import unittest
import re
-from checklayer import get_signatures, LayerType, check_command, get_depgraph, compare_signatures
+from checklayer import get_signatures, LayerType, check_command, compare_signatures, get_git_toplevel
from checklayer.case import OECheckLayerTestCase
class CommonCheckLayer(OECheckLayerTestCase):
@@ -40,6 +40,38 @@ class CommonCheckLayer(OECheckLayerTestCase):
email_regex = re.compile(r"[^@]+@[^@]+")
self.assertTrue(email_regex.match(data))
+ def find_file_by_name(self, globs):
+ """
+ Utility function to find a file that matches the specified list of
+ globs, in either the layer directory itself or the repository top-level
+ directory.
+ """
+ directories = [self.tc.layer["path"]]
+ toplevel = get_git_toplevel(directories[0])
+ if toplevel:
+ directories.append(toplevel)
+
+ for path in directories:
+ for name in globs:
+ files = glob.glob(os.path.join(path, name))
+ if files:
+ return sorted(files)[0]
+ return None
+
+ def test_security(self):
+ """
+ Test that the layer has a SECURITY.md (or similar) file, either in the
+ layer itself or at the top of the containing git repository.
+ """
+ if self.tc.layer["type"] == LayerType.CORE:
+ raise unittest.SkipTest("Core layer's SECURITY is top level")
+
+ filename = self.find_file_by_name(("SECURITY", "SECURITY.*"))
+ self.assertTrue(filename, msg="Layer doesn't contain a SECURITY.md file.")
+
+ size = os.path.getsize(filename)
+ self.assertGreater(size, 0, msg=f"{filename} has no content.")
+
def test_parse(self):
check_command('Layer %s failed to parse.' % self.tc.layer['name'],
'bitbake -p')
Add a check for a SECURITY.md file (or similar) to yocto-check-layer, as knowing where to report security issues is important. Signed-off-by: Ross Burton <ross.burton@arm.com> --- scripts/lib/checklayer/__init__.py | 12 +++++++++ scripts/lib/checklayer/cases/common.py | 34 +++++++++++++++++++++++++- 2 files changed, 45 insertions(+), 1 deletion(-)