bandit.bbclass 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. # Class to scan Python code for security issues, using Bandit.
  2. #
  3. # $ bitbake python-foo -c bandit
  4. #
  5. # Writes the report to $DEPLOY_DIR/bandit/python-foo.html.
  6. # No output if no issues found, a warning if issues found.
  7. #
  8. # https://github.com/PyCQA/bandit
  9. # Default location of sources, based on standard distutils
  10. BANDIT_SOURCE ?= "${S}/build"
  11. # The report format to use.
  12. # https://bandit.readthedocs.io/en/latest/formatters/index.html
  13. BANDIT_FORMAT ?= "html"
  14. # Whether a scan should be done every time the recipe is built.
  15. #
  16. # By default the scanning needs to be done explicitly, but by setting BANDIT_AUTO
  17. # to 1 the scan will be done whenever the recipe it built. Note that you
  18. # shouldn't set BANDIT_AUTO to 1 globally as it will then try to scan every
  19. # recipe, including non-Python recipes, causing circular loops.
  20. BANDIT_AUTO ?= "0"
  21. # Whether Bandit finding issues results in a warning (0) or an error (1).
  22. BANDIT_FATAL ?= "0"
  23. do_bandit[depends] = "python3-bandit-native:do_populate_sysroot"
  24. python do_bandit() {
  25. import os, subprocess
  26. try:
  27. report = d.expand("${DEPLOY_DIR}/bandit/${PN}-${PV}.${BANDIT_FORMAT}")
  28. os.makedirs(os.path.dirname(report), exist_ok=True)
  29. args = ("bandit",
  30. "--format", d.getVar("BANDIT_FORMAT"),
  31. "--output", report,
  32. "-ll",
  33. "--recursive", d.getVar("BANDIT_SOURCE"))
  34. subprocess.check_output(args, stderr=subprocess.STDOUT)
  35. bb.note("Bandit found no issues (report written to %s)" % report)
  36. except subprocess.CalledProcessError as e:
  37. if e.returncode == 1:
  38. if oe.types.boolean(d.getVar("BANDIT_FATAL")):
  39. bb.error("Bandit found issues (report written to %s)" % report)
  40. else:
  41. bb.warn("Bandit found issues (report written to %s)" % report)
  42. else:
  43. bb.error("Bandit failed:\n" + e.output.decode("utf-8"))
  44. }
  45. python() {
  46. before = "do_build"
  47. after = "do_compile"
  48. if oe.types.boolean(d.getVar("BANDIT_AUTO")):
  49. bb.build.addtask("do_bandit", before, after, d)
  50. else:
  51. bb.build.addtask("do_bandit", None, after, d)
  52. }
  53. # TODO: store report in sstate
  54. # TODO: a way to pass extra args or .bandit file, basically control -ll