Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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).
*
* <p>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;
}
}
Original file line number Diff line number Diff line change
@@ -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());
}
}
24 changes: 24 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -43,6 +47,7 @@ plugins {
}

import org.apache.geode.gradle.plugins.PasswordDialog
import org.apache.geode.gradle.plugins.SbomSupport


wrapper {
Expand Down Expand Up @@ -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"
Expand Down
4 changes: 4 additions & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -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
195 changes: 36 additions & 159 deletions proposals/GEODE-10481/todo.md
Original file line number Diff line number Diff line change
@@ -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
Loading