sbom.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. # Copyright (c) 2020, 2021 The Linux Foundation
  2. #
  3. # SPDX-License-Identifier: Apache-2.0
  4. import os
  5. from west import log
  6. from zspdx.walker import WalkerConfig, Walker
  7. from zspdx.scanner import ScannerConfig, scanDocument
  8. from zspdx.writer import writeSPDX
  9. # SBOMConfig contains settings that will be passed along to the various
  10. # SBOM maker subcomponents.
  11. class SBOMConfig:
  12. def __init__(self):
  13. super(SBOMConfig, self).__init__()
  14. # prefix for Document namespaces; should not end with "/"
  15. self.namespacePrefix = ""
  16. # location of build directory
  17. self.buildDir = ""
  18. # location of SPDX document output directory
  19. self.spdxDir = ""
  20. # should also analyze for included header files?
  21. self.analyzeIncludes = False
  22. # should also add an SPDX document for the SDK?
  23. self.includeSDK = False
  24. # create Cmake file-based API directories and query file
  25. # Arguments:
  26. # 1) build_dir: build directory
  27. def setupCmakeQuery(build_dir):
  28. # check that query dir exists as a directory, or else create it
  29. cmakeApiDirPath = os.path.join(build_dir, ".cmake", "api", "v1", "query")
  30. if os.path.exists(cmakeApiDirPath):
  31. if not os.path.isdir(cmakeApiDirPath):
  32. log.err(f'cmake api query directory {cmakeApiDirPath} exists and is not a directory')
  33. return False
  34. # directory exists, we're good
  35. else:
  36. # create the directory
  37. os.makedirs(cmakeApiDirPath, exist_ok=False)
  38. # check that codemodel-v2 exists as a file, or else create it
  39. queryFilePath = os.path.join(cmakeApiDirPath, "codemodel-v2")
  40. if os.path.exists(queryFilePath):
  41. if not os.path.isfile(queryFilePath):
  42. log.err(f'cmake api query file {queryFilePath} exists and is not a directory')
  43. return False
  44. # file exists, we're good
  45. return True
  46. else:
  47. # file doesn't exist, let's create it
  48. os.mknod(queryFilePath)
  49. return True
  50. # main entry point for SBOM maker
  51. # Arguments:
  52. # 1) cfg: SBOMConfig
  53. def makeSPDX(cfg):
  54. # report any odd configuration settings
  55. if cfg.analyzeIncludes and not cfg.includeSDK:
  56. log.wrn(f"config: requested to analyze includes but not to generate SDK SPDX document;")
  57. log.wrn(f"config: will proceed but will discard detected includes for SDK header files")
  58. # set up walker configuration
  59. walkerCfg = WalkerConfig()
  60. walkerCfg.namespacePrefix = cfg.namespacePrefix
  61. walkerCfg.buildDir = cfg.buildDir
  62. walkerCfg.analyzeIncludes = cfg.analyzeIncludes
  63. walkerCfg.includeSDK = cfg.includeSDK
  64. # make and run the walker
  65. w = Walker(walkerCfg)
  66. retval = w.makeDocuments()
  67. if not retval:
  68. log.err("SPDX walker failed; bailing")
  69. return False
  70. # set up scanner configuration
  71. scannerCfg = ScannerConfig()
  72. # scan each document from walker
  73. if cfg.includeSDK:
  74. scanDocument(scannerCfg, w.docSDK)
  75. scanDocument(scannerCfg, w.docApp)
  76. scanDocument(scannerCfg, w.docZephyr)
  77. scanDocument(scannerCfg, w.docBuild)
  78. # write each document, in this particular order so that the
  79. # hashes for external references are calculated
  80. # write SDK document, if we made one
  81. if cfg.includeSDK:
  82. retval = writeSPDX(os.path.join(cfg.spdxDir, "sdk.spdx"), w.docSDK)
  83. if not retval:
  84. log.err("SPDX writer failed for SDK document; bailing")
  85. return False
  86. # write app document
  87. retval = writeSPDX(os.path.join(cfg.spdxDir, "app.spdx"), w.docApp)
  88. if not retval:
  89. log.err("SPDX writer failed for app document; bailing")
  90. return False
  91. # write zephyr document
  92. writeSPDX(os.path.join(cfg.spdxDir, "zephyr.spdx"), w.docZephyr)
  93. if not retval:
  94. log.err("SPDX writer failed for zephyr document; bailing")
  95. return False
  96. # write build document
  97. writeSPDX(os.path.join(cfg.spdxDir, "build.spdx"), w.docBuild)
  98. if not retval:
  99. log.err("SPDX writer failed for build document; bailing")
  100. return False
  101. return True