diff --git a/build-tools/geode-build-tools/src/main/java/org/apache/geode/gradle/plugins/SbomSupport.java b/build-tools/geode-build-tools/src/main/java/org/apache/geode/gradle/plugins/SbomSupport.java new file mode 100644 index 000000000000..bace6bd07ed6 --- /dev/null +++ b/build-tools/geode-build-tools/src/main/java/org/apache/geode/gradle/plugins/SbomSupport.java @@ -0,0 +1,55 @@ +/* + * 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. + */ +package org.apache.geode.gradle.plugins; + +import org.gradle.util.GradleVersion; + +/** + * Decides whether the running Gradle version is new enough to generate SBOMs (GEODE-10481). + * + *

The version-comparison logic is kept here as a small, dependency-light unit so it can be + * unit-tested without standing up a Gradle build. SBOM generation itself stays feature-flagged + * and is wired up in later phases; this class only provides the compatibility gate. + */ +public final class SbomSupport { + + /** + * Minimum Gradle version required to generate SBOMs with the CycloneDX 1.x plugin line that + * Geode pins while it builds on Gradle 7.x. + */ + public static final String MINIMUM_GRADLE_VERSION = "7.0"; + + private SbomSupport() { + // static utility + } + + /** + * Returns true if {@code currentVersion} is greater than or equal to {@code minimumVersion}. + */ + public static boolean isGradleVersionSupported(String currentVersion, String minimumVersion) { + return GradleVersion.version(currentVersion) + .compareTo(GradleVersion.version(minimumVersion)) >= 0; + } + + /** + * Returns true if the Gradle version running this build satisfies {@link #MINIMUM_GRADLE_VERSION}. + */ + public static boolean isCurrentGradleVersionSupported() { + return GradleVersion.current() + .compareTo(GradleVersion.version(MINIMUM_GRADLE_VERSION)) >= 0; + } +} diff --git a/build-tools/geode-build-tools/src/test/java/org/apache/geode/gradle/plugins/SbomSupportTest.java b/build-tools/geode-build-tools/src/test/java/org/apache/geode/gradle/plugins/SbomSupportTest.java new file mode 100644 index 000000000000..f8f0d5443b93 --- /dev/null +++ b/build-tools/geode-build-tools/src/test/java/org/apache/geode/gradle/plugins/SbomSupportTest.java @@ -0,0 +1,50 @@ +/* + * 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. + */ +package org.apache.geode.gradle.plugins; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; + +public class SbomSupportTest { + + @Test + public void pinnedGradleMeetsMinimum() { + assertTrue(SbomSupport.isGradleVersionSupported("7.3.3", SbomSupport.MINIMUM_GRADLE_VERSION)); + } + + @Test + public void equalVersionIsSupported() { + assertTrue(SbomSupport.isGradleVersionSupported("7.0", "7.0")); + } + + @Test + public void newerMajorVersionIsSupported() { + assertTrue(SbomSupport.isGradleVersionSupported("8.5", "7.0")); + } + + @Test + public void olderVersionIsNotSupported() { + assertFalse(SbomSupport.isGradleVersionSupported("6.8.3", "7.0")); + } + + @Test + public void currentBuildGradleIsSupported() { + assertTrue(SbomSupport.isCurrentGradleVersionSupported()); + } +} diff --git a/build.gradle b/build.gradle index f18bc03e23a1..1d2b0b3caacf 100755 --- a/build.gradle +++ b/build.gradle @@ -31,6 +31,10 @@ plugins { id "org.sonarqube" version "3.3" apply false id 'me.champeau.gradle.jmh' version '0.5.3' apply false id "de.undercouch.download" version "5.0.1" apply false + // GEODE-10481: SBOM generation. Declared but NOT applied here (see the SBOM block below); + // pinned to the CycloneDX 1.x line because 2.x/3.x require Gradle 8+, while Geode currently + // builds on Gradle 7.3.3. + id "org.cyclonedx.bom" version "1.7.4" apply false id 'org.apache.geode.gradle.geode-dependency-constraints' apply false id 'geode-publish-artifacts' apply false id 'geode-publish-common' apply false @@ -43,6 +47,7 @@ plugins { } import org.apache.geode.gradle.plugins.PasswordDialog +import org.apache.geode.gradle.plugins.SbomSupport wrapper { @@ -165,6 +170,25 @@ tasks.register('generate') { // `afterEvaluate.rootProject.generate.dependsOn(generateProto)` } +// GEODE-10481: Software Bill of Materials (SBOM) foundation -- Phase 1 / PR 1. +// Scaffolding only: SBOM generation is OFF by default (see 'geode.sbom.enabled' in +// gradle.properties) and no SBOM is produced by any existing task. Later phases wire the +// CycloneDX plugin (declared 'apply false' above) into the build behind that flag. +// The version-comparison logic lives in SbomSupport (build-tools/geode-build-tools) so it is +// covered by a unit test (SbomSupportTest). +tasks.register('validateGradleCompatibility') { + group = 'verification' + description = "Checks that the running Gradle version supports SBOM generation (GEODE-10481)." + doLast { + def current = org.gradle.util.GradleVersion.current().version + if (!SbomSupport.isCurrentGradleVersionSupported()) { + throw new GradleException("SBOM generation (GEODE-10481) requires Gradle >= " + + "${SbomSupport.MINIMUM_GRADLE_VERSION}, but this build is using ${current}.") + } + logger.lifecycle("Gradle ${current} satisfies the SBOM minimum (${SbomSupport.MINIMUM_GRADLE_VERSION}).") + } +} + tasks.register('printTestClasspath') { group 'Build' description "Print the classpath used in all tests for all subprojects" diff --git a/gradle.properties b/gradle.properties index 72695f0437e1..b963b4f4d666 100755 --- a/gradle.properties +++ b/gradle.properties @@ -89,3 +89,7 @@ org.gradle.internal.http.socketTimeout=120000 org.gradle.internal.http.connectionTimeout=120000 junit.jupiter.testclass.order.default = org.junit.jupiter.api.ClassOrderer$Random + +# GEODE-10481: Software Bill of Materials (SBOM) generation toggle. +# OFF by default. Reserved for later SBOM phases; not yet consumed by any task. +geode.sbom.enabled = false diff --git a/proposals/GEODE-10481/todo.md b/proposals/GEODE-10481/todo.md index 83550f05c6c9..ad6167cc1d59 100644 --- a/proposals/GEODE-10481/todo.md +++ b/proposals/GEODE-10481/todo.md @@ -1,160 +1,37 @@ -# GEODE-10481 SBOM Implementation TODO +# GEODE-10481 — SBOM Implementation Plan (CycloneDX 1.x + Gradle 7.3.3) + +## Decisions +- Generate **CycloneDX** SBOMs. Pinned to the CycloneDX **1.x** plugin line because 2.x/3.x require + Gradle 8+, while Geode builds on **Gradle 7.3.3**. Revisit when Geode moves to Gradle 8. +- Delivered in **4 PRs** (down from the original 12 — the rest was gold-plating or separable). +- **Vulnerability scanning** (Trivy/Grype/SARIF) is **descoped to its own ticket**: it *consumes* an + SBOM and is a distinct security feature, not part of SBOM generation. + +--- + +## PR 1 — Foundation & compatibility gate ✅ (this iteration) +Completely inert: no SBOM is produced, zero impact on existing builds. +- [x] Declare CycloneDX plugin in root `build.gradle`, `apply false` (1.x line: `1.7.4`) +- [x] `geode.sbom.enabled` flag in `gradle.properties` (OFF by default) +- [x] `validateGradleCompatibility` task +- [x] Version-comparison logic extracted to `SbomSupport` (`build-tools/geode-build-tools`) and + unit-tested (`SbomSupportTest`, 5 cases) +- [x] Verified zero impact: build configures, SBOM off, task prints the compatibility result + +## PR 2 — Generate SBOMs for all library modules +- [ ] Apply CycloneDX to all non-assembly modules (via `subprojects`/convention), gated by `geode.sbom.enabled` +- [ ] `cyclonedxBom { }` config: schema version, `projectType = library`, output format(s), serial number +- [ ] `generateSbom` aggregator task across modules +- [ ] Integration test: SBOM is produced and schema-valid + +## PR 3 — Distribution SBOM + ASF metadata + signing +- [ ] geode-assembly aggregate SBOM (`projectType = application`) +- [ ] ASF metadata (supplier / manufacturer / licenses) +- [ ] Include the SBOM in the distribution archive +- [ ] GPG-sign the SBOM (reuse the existing ASF signing infrastructure) + +## PR 4 — CI / release wiring + docs +- [ ] `gradle.yml`: generate + upload SBOM artifact +- [ ] release flow: include + sign SBOM in release artifacts +- [ ] Documentation (how to generate, where SBOMs land) -## Current Status: Proposal Reviewed ✅ - -## Implementation Checklist - -Each phase represents a logical grouping of related work that builds incrementally. - -### Phase 1: Foundation & Infrastructure (PRs 1-2) -**Goal**: Establish safe SBOM infrastructure and intelligent generation logic - -- [ ] **PR 1: Plugin Foundation & Compatibility Validation** - - [ ] Add CycloneDX plugin to root build.gradle (disabled by default) - - [ ] Add validateGradleCompatibility task for version checking - - [ ] Add basic plugin configuration structure for future use - - [ ] Create unit tests for compatibility validation logic - - [ ] Verify zero impact on existing builds - -- [ ] **PR 2: Context Detection Logic** - - [ ] Implement context detection (CI, release, explicit SBOM request) - - [ ] Add shouldGenerateSbom logic with boolean combinations - - [ ] Add gradle.properties configuration for SBOM optimization - - [ ] Create comprehensive unit tests for all context scenarios - - [ ] Verify context detection accuracy in all environments - -**Phase Deliverable**: Complete SBOM infrastructure ready for activation - -### Phase 2: Core SBOM Generation (PRs 3-5) -**Goal**: Implement and scale SBOM generation across all modules - -- [ ] **PR 3: Basic SBOM Generation for Single Module** - - [ ] Enable SBOM generation for geode-common module only - - [ ] Configure basic CycloneDX settings and output format - - [ ] Add integration tests for SBOM content validation - - [ ] Validate SBOM format compliance and accuracy - - [ ] Measure and document performance impact - -- [ ] **PR 4: Multi-Module SBOM Configuration** - - [ ] Apply SBOM configuration to all 30+ non-assembly modules - - [ ] Implement generateSbom coordinating task for all modules - - [ ] Add module-specific configuration handling - - [ ] Create comprehensive multi-module integration tests - - [ ] Performance benchmarking across all modules - -- [ ] **PR 5: Assembly Module Integration** - - [ ] Configure SBOM generation for geode-assembly module (application type) - - [ ] Add ASF compliance metadata (supplier, manufacturer information) - - [ ] Implement generateDistributionSbom task for packaging - - [ ] Integrate with existing distribution packaging process - - [ ] Add assembly SBOM validation tests and metadata verification - -**Phase Deliverable**: Complete SBOM generation for all modules including assembly - -### Phase 3: Performance & Production Readiness (PR 6) -**Goal**: Optimize SBOM generation for production use - -- [ ] **PR 6: Performance Optimization & Caching** - - [ ] Enable parallel execution configuration for SBOM tasks - - [ ] Implement proper Gradle build caching for SBOM generation - - [ ] Add performance monitoring and benchmarking capabilities - - [ ] Optimize for <3% total build time impact target - - [ ] Add performance regression testing framework - -**Phase Deliverable**: Production-ready performance for SBOM generation - -### Phase 4: CI/CD Integration (PRs 7-9) -**Goal**: Integrate SBOM generation into all automated workflows - -- [ ] **PR 7: Basic GitHub Actions Integration** - - [ ] Update existing gradle.yml workflow to include generateSbom - - [ ] Add conditional SBOM generation in CI environment - - [ ] Implement SBOM artifact upload for CI builds - - [ ] Ensure backward compatibility with existing workflow - - [ ] Test CI workflow execution and artifact verification - -- [ ] **PR 8: Dedicated SBOM Workflow** - - [ ] Create new sbom.yml workflow for dedicated SBOM processing - - [ ] Add SBOM format validation in CI environment - - [ ] Implement basic security scanning integration - - [ ] Add comprehensive SBOM quality assurance pipeline - - [ ] Test workflow execution and validation pipeline verification - -- [ ] **PR 9: Release Workflow Integration** - - [ ] Create release.yml workflow with SBOM packaging - - [ ] Add SBOM inclusion in release artifacts and distributions - - [ ] Implement release candidate SBOM generation - - [ ] Update release scripts for SBOM integration - - [ ] Test release workflow simulation and artifact packaging verification - -**Phase Deliverable**: Complete SBOM integration in all CI/CD pipelines - -### Phase 5: Compliance & Security (PRs 10-11) -**Goal**: Add enterprise-grade compliance and security features - -- [ ] **PR 10: ASF Compliance & Signing Integration** - - [ ] Add GPG signing for SBOM artifacts - - [ ] Implement deterministic SBOM generation for reproducible builds - - [ ] Add ASF metadata validation and compliance checking - - [ ] Integrate with existing ASF signing infrastructure - - [ ] Test signing verification and metadata compliance validation - -- [ ] **PR 11: Security Scanning & Format Validation** - - [ ] Integrate vulnerability scanning tools (Trivy, Grype) - - [ ] Add SARIF reporting to GitHub Security tab - - [ ] Implement security policy validation - - [ ] Create security monitoring and alerting - - [ ] Add CycloneDX format validation and schema compliance - - [ ] Implement SPDX export capability for broader compatibility - - [ ] Add compliance reporting and validation tools - - [ ] Create format conversion and validation utilities - - [ ] Test vulnerability detection, security reporting, and format compliance - -**Phase Deliverable**: Enterprise-ready SBOM with full compliance and security features - -### Phase 6: Documentation & Finalization (PR 12) -**Goal**: Complete the implementation with comprehensive documentation and community readiness - -- [ ] **PR 12: Documentation, Testing & Final Polish** - - [ ] Add comprehensive SBOM generation documentation - - [ ] Create developer usage guides and best practices - - [ ] Add troubleshooting guide and FAQ sections - - [ ] Create integration examples and use cases - - [ ] Add end-to-end integration tests covering all scenarios - - [ ] Implement comprehensive validation suite - - [ ] Add performance regression testing framework - - [ ] Create automated testing for all SBOM workflows - - [ ] Address community feedback and edge cases - - [ ] Add final optimizations and performance improvements - - [ ] Complete ASF compliance validation and certification - - [ ] Prepare for community adoption and maintenance - - [ ] Execute complete validation suite and community review integration - -**Phase Deliverable**: Production-ready SBOM implementation with community approval - -## Current Priorities -1. **Next Action**: Begin Phase 1 - Foundation & Infrastructure (PRs 1-2) -2. **Focus Area**: Establishing safe SBOM infrastructure and intelligent generation logic -3. **Risk Management**: Ensure all changes are feature-flagged and reversible -4. **New Structure**: 6 logical phases with meaningful groupings of related work - -## Notes -- Each phase represents a logical grouping of related work (2-3 PRs per phase) -- All PRs within phases should maintain backward compatibility -- Each PR should be independently testable and deployable -- Performance impact should be measured at each step -- Community feedback should be incorporated throughout the process -- Clear phase deliverables defined to measure progress toward complete solution - -## Dependencies Tracking -- [ ] CycloneDX Gradle Plugin 3.0+ availability confirmed -- [ ] GitHub Actions runner compatibility verified -- [ ] GPG signing infrastructure access confirmed -- [ ] Security scanning tool integration capabilities verified - -## Success Metrics -- Build time impact: <3% increase target -- Test coverage: >90% for new functionality -- Zero regression in existing functionality -- Complete ASF compliance achievement -- Community adoption and feedback integration