diff --git a/.github/workflows/sbom.yml b/.github/workflows/sbom.yml
new file mode 100644
index 000000000000..d368c0e4e313
--- /dev/null
+++ b/.github/workflows/sbom.yml
@@ -0,0 +1,118 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+name: generate sboms
+
+on:
+ push:
+ tags:
+ - '[0-9]+.[0-9]+.[0-9]+*'
+ workflow_dispatch:
+
+permissions:
+ contents: read
+
+jobs:
+ ui-sbom:
+ name: ui sbom
+ runs-on: ubuntu-24.04
+ steps:
+ - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
+ with:
+ persist-credentials: false
+
+ - name: Generate UI SBOM
+ uses: sbomify/sbomify-action@master
+ env:
+ LOCK_FILE: ui/package-lock.json
+ OUTPUT_FILE: sbom.ui.cdx.json
+ COMPONENT_NAME: cloudstack-ui
+ COMPONENT_VERSION: ${{ github.ref_name }}
+ UPLOAD: false
+ ENRICH: true
+
+ - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
+ with:
+ name: sbom-ui
+ path: sbom.ui.cdx.json
+
+ java-sbom:
+ name: java sbom
+ runs-on: ubuntu-24.04
+ steps:
+ - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
+ with:
+ persist-credentials: false
+
+ - name: Setup Environment
+ uses: ./.github/actions/setup-env
+
+ - name: Generate Java SBOM
+ run: mvn -B -ntp -Dnoredist org.cyclonedx:cyclonedx-maven-plugin:makeAggregateBom
+
+ - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
+ with:
+ name: sbom-java
+ path: target/ACS.sbom.*
+
+ marvin-sbom:
+ name: marvin sbom
+ runs-on: ubuntu-24.04
+ steps:
+ - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
+ with:
+ persist-credentials: false
+
+ - name: Setup Environment
+ uses: ./.github/actions/setup-env
+ with:
+ install-python: 'true'
+
+ - name: Resolve marvin dependencies
+ run: |
+ # marvin's `packages` list includes the generated marvin.cloudstackAPI
+ # module, which is created at build time from the API spec and isn't
+ # checked in, so setup.py can't be built directly. Read the declared
+ # install_requires instead of building the package.
+ python3 -c "
+ import ast
+ tree = ast.parse(open('tools/marvin/setup.py').read())
+ for node in ast.walk(tree):
+ if isinstance(node, ast.Call) and getattr(node.func, 'id', None) == 'setup':
+ for kw in node.keywords:
+ if kw.arg == 'install_requires':
+ for elt in kw.value.elts:
+ print(elt.value)
+ " > marvin-install-requires.txt
+ python3 -m venv marvin-venv
+ marvin-venv/bin/pip install --quiet -r marvin-install-requires.txt
+ marvin-venv/bin/pip freeze > marvin-requirements.txt
+
+ - name: Generate marvin SBOM
+ uses: sbomify/sbomify-action@master
+ env:
+ LOCK_FILE: marvin-requirements.txt
+ OUTPUT_FILE: sbom.marvin.cdx.json
+ COMPONENT_NAME: cloudstack-marvin
+ COMPONENT_VERSION: ${{ github.ref_name }}
+ UPLOAD: false
+ ENRICH: true
+
+ - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
+ with:
+ name: sbom-marvin
+ path: sbom.marvin.cdx.json
diff --git a/pom.xml b/pom.xml
index 883e7a4e4db6..14d2688e09a2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -848,6 +848,33 @@
+
+ org.cyclonedx
+ cyclonedx-maven-plugin
+ 2.9.1
+
+
+ package
+ false
+
+ makeAggregateBom
+
+
+
+
+ application
+ 1.6
+ true
+ true
+ true
+ true
+ true
+ false
+ false
+ all
+ ACS.sbom
+
+