|
| 1 | +# Implementation Plan: SBOM Augmentation Feature (Issue #219) |
| 2 | + |
| 3 | +## Issue Summary |
| 4 | +GitHub Issue: https://github.com/interlynk-io/sbomasm/issues/219 |
| 5 | + |
| 6 | +The user needs to augment existing SBOMs with additional components and dependency relationships **without** introducing a new root package. Current implementation always requires creating a new root package when assembling SBOMs, which causes duplicate or unwanted root components when trying to simply add delta information to an existing SBOM. |
| 7 | + |
| 8 | +## Problem Analysis |
| 9 | + |
| 10 | +### Current Behavior |
| 11 | +1. **Forced Root Package Creation**: The `assemble` command always requires app name/version parameters (`-n`, `-v`, `-t`) and creates a new root package, even when the user wants to preserve the existing primary component. |
| 12 | + |
| 13 | +2. **Configuration Validation**: In `pkg/assemble/config.go:276-285`, the configuration validation enforces that app name and version are required, making it impossible to skip root package creation. |
| 14 | + |
| 15 | +3. **Merge Strategies**: Current merge strategies (flat, hierarchical, assembly) all assume creating a new primary component that wraps the input SBOMs: |
| 16 | + - **Flat merge**: Creates new root with all components flattened |
| 17 | + - **Hierarchical merge**: Creates new root with input primary components as children |
| 18 | + - **Assembly merge**: Creates new root but keeps relationships independent |
| 19 | + |
| 20 | +4. **Component Deduplication**: The `uniqueComponentService` deduplicates components based on `type-name-version` but doesn't handle the case where the primary component should be preserved from one of the inputs. |
| 21 | + |
| 22 | +### Root Cause |
| 23 | +The architecture assumes all assembly operations are combining multiple independent SBOMs into a new product, rather than augmenting an existing SBOM with additional information. There's no concept of a "primary SBOM" that should retain its structure while incorporating delta changes. |
| 24 | + |
| 25 | +## Proposed Solution |
| 26 | + |
| 27 | +### 1. New Augmentation Mode |
| 28 | +Introduce a new **augmentation mode** that allows merging delta SBOMs into a primary SBOM without creating a new root package. |
| 29 | + |
| 30 | +### 2. Command Line Interface Changes |
| 31 | + |
| 32 | +#### Option A: Primary SBOM Flag (Recommended) |
| 33 | +```bash |
| 34 | +sbomasm assemble --primary-sbom sbom-1.json --augment sbom-2.json -o sbom-3.json |
| 35 | +``` |
| 36 | + |
| 37 | +#### Option B: Component Linking via Identifiers |
| 38 | +```bash |
| 39 | +sbomasm assemble --primary-sbom sbom-1.json --method purl --id 'pkg:npm/component@1.0.0' sbom-2.json -o sbom-3.json |
| 40 | +``` |
| 41 | + |
| 42 | +#### Option C: Configuration File Approach |
| 43 | +```yaml |
| 44 | +augment: |
| 45 | + primary_sbom: sbom-1.json |
| 46 | + method: purl # or cpe, or name-version |
| 47 | + mappings: |
| 48 | + - target: 'pkg:npm/c1@1.0.0' |
| 49 | + delta: sbom-2.json |
| 50 | + - target: 'pkg:npm/c3@1.0.0' |
| 51 | + delta: sbom-3.json |
| 52 | +``` |
| 53 | +
|
| 54 | +### 3. Required Code Changes |
| 55 | +
|
| 56 | +#### 3.1 Command Structure (`cmd/assemble.go`) |
| 57 | +- Add new flags: `--primary-sbom`, `--augment`, `--method`, `--id` |
| 58 | +- Make `-n`, `-v`, `-t` optional when using augmentation mode |
| 59 | +- Add validation for augmentation-specific parameters |
| 60 | + |
| 61 | +#### 3.2 Configuration Updates (`pkg/assemble/config.go`) |
| 62 | +- Add `AugmentMode` struct: |
| 63 | + ```go |
| 64 | + type augmentMode struct { |
| 65 | + Enabled bool |
| 66 | + PrimarySBOM string |
| 67 | + Method string // "purl", "cpe", "name-version" |
| 68 | + Mappings []ComponentMapping |
| 69 | + } |
| 70 | + ``` |
| 71 | +- Update validation to skip app name/version requirements in augment mode |
| 72 | +- Add primary SBOM validation |
| 73 | + |
| 74 | +#### 3.3 New Augmentation Logic (`pkg/assemble/augment.go`) |
| 75 | +Create new file with augmentation-specific logic: |
| 76 | +- `loadPrimarySBOM()`: Load and preserve primary SBOM structure |
| 77 | +- `findTargetComponent()`: Locate component to augment using specified method |
| 78 | +- `mergeComponents()`: Add new components without duplicating existing ones |
| 79 | +- `mergeDependencies()`: Add new dependency relationships |
| 80 | +- `mergeMetadata()`: Optionally merge/override metadata fields |
| 81 | + |
| 82 | +#### 3.4 Combiner Updates (`pkg/assemble/combiner.go`) |
| 83 | +- Add augmentation path in `combine()` method |
| 84 | +- Route to augmentation logic when mode is enabled |
| 85 | + |
| 86 | +#### 3.5 CDX Implementation (`pkg/assemble/cdx/augment.go`) |
| 87 | +- Implement CycloneDX-specific augmentation: |
| 88 | + - Preserve primary component from base SBOM |
| 89 | + - Match components using BOMRef, PURL, or CPE |
| 90 | + - Merge component trees at specified attachment points |
| 91 | + - Handle dependency graph updates |
| 92 | + |
| 93 | +#### 3.6 SPDX Implementation (`pkg/assemble/spdx/augment.go`) |
| 94 | +- Implement SPDX-specific augmentation: |
| 95 | + - Preserve primary package |
| 96 | + - Match packages using SPDX identifiers or external refs |
| 97 | + - Update relationships without duplicating |
| 98 | + |
| 99 | +## Implementation Steps |
| 100 | + |
| 101 | +### Phase 1: Core Infrastructure (Week 1) |
| 102 | +1. Add command-line flags and parameters |
| 103 | +2. Update configuration structures |
| 104 | +3. Implement validation logic for augmentation mode |
| 105 | +4. Create base augmentation interfaces |
| 106 | + |
| 107 | +### Phase 2: Augmentation Logic (Week 2) |
| 108 | +1. Implement primary SBOM loading and preservation |
| 109 | +2. Create component matching algorithms (PURL, CPE, name-version) |
| 110 | +3. Implement component and dependency merging |
| 111 | +4. Handle metadata merging/override options |
| 112 | + |
| 113 | +### Phase 3: Format-Specific Implementation (Week 3) |
| 114 | +1. Complete CycloneDX augmentation |
| 115 | +2. Complete SPDX augmentation |
| 116 | +3. Handle format-specific edge cases |
| 117 | +4. Ensure proper ID mapping and resolution |
| 118 | + |
| 119 | +### Phase 4: Testing & Documentation (Week 4) |
| 120 | +1. Unit tests for augmentation logic |
| 121 | +2. Integration tests with sample SBOMs |
| 122 | +3. Update documentation and examples |
| 123 | +4. Performance testing with large SBOMs |
| 124 | + |
| 125 | +## Test Cases |
| 126 | + |
| 127 | +### Basic Augmentation |
| 128 | +1. **Single Component Addition**: Add C4 to SBOM with C1, C2, C3 |
| 129 | +2. **Dependency Addition**: Add relationships C1→C4, C4→C3 |
| 130 | +3. **Metadata Override**: Update component metadata (version, licenses, etc.) |
| 131 | + |
| 132 | +### Complex Scenarios |
| 133 | +1. **Multiple Delta SBOMs**: Apply multiple augmentations in sequence |
| 134 | +2. **Nested Components**: Augment components within component trees |
| 135 | +3. **Circular Dependencies**: Handle circular dependency detection |
| 136 | +4. **Large SBOMs**: Performance with 10,000+ components |
| 137 | + |
| 138 | +### Error Cases |
| 139 | +1. **Missing Target Component**: Handle when specified component not found |
| 140 | +2. **Conflicting Information**: Resolve conflicts between base and delta |
| 141 | +3. **Invalid Relationships**: Prevent invalid dependency relationships |
| 142 | + |
| 143 | +## Backwards Compatibility |
| 144 | + |
| 145 | +1. **Existing Commands**: All existing assemble modes remain unchanged |
| 146 | +2. **Configuration Files**: Old configs continue to work |
| 147 | +3. **Default Behavior**: Without augmentation flags, behavior is identical |
| 148 | + |
| 149 | +## Performance Considerations |
| 150 | + |
| 151 | +1. **Component Lookup**: Use hash maps for O(1) component lookup |
| 152 | +2. **Memory Usage**: Stream processing for large SBOMs |
| 153 | +3. **Deduplication**: Efficient duplicate detection algorithms |
| 154 | + |
| 155 | +## Security Implications |
| 156 | + |
| 157 | +1. **Input Validation**: Validate all external references (PURLs, CPEs) |
| 158 | +2. **Cycle Prevention**: Prevent circular dependencies |
| 159 | +3. **Data Integrity**: Preserve cryptographic hashes and signatures |
| 160 | + |
| 161 | +## Documentation Updates |
| 162 | + |
| 163 | +1. **User Guide**: Add augmentation examples and use cases |
| 164 | +2. **API Documentation**: Document new interfaces and methods |
| 165 | +3. **Migration Guide**: Help users transition from workarounds |
| 166 | + |
| 167 | +## Future Enhancements |
| 168 | + |
| 169 | +1. **Batch Operations**: Support multiple augmentations in single command |
| 170 | +2. **Conflict Resolution**: Advanced strategies for handling conflicts |
| 171 | +3. **Validation Rules**: Custom validation for augmented SBOMs |
| 172 | +4. **Rollback Support**: Undo augmentation operations |
| 173 | + |
| 174 | +## Success Metrics |
| 175 | + |
| 176 | +1. **Functionality**: Successfully augment SBOMs without new root packages |
| 177 | +2. **Performance**: < 2 second processing for 1000-component SBOMs |
| 178 | +3. **Compatibility**: 100% backward compatibility with existing features |
| 179 | +4. **User Experience**: Intuitive CLI interface and clear error messages |
| 180 | + |
| 181 | +## Related Issues |
| 182 | +- Issue #128: Discussion about primary component selection |
| 183 | +- Issue #134: Primary component file specification |
| 184 | + |
| 185 | +## References |
| 186 | +- Original Issue: https://github.com/interlynk-io/sbomasm/issues/219 |
| 187 | +- CycloneDX Specification: https://cyclonedx.org/specification/ |
| 188 | +- SPDX Specification: https://spdx.github.io/spdx-spec/ |
0 commit comments