@@ -50,6 +50,8 @@ const (
50
50
PackageSupplierNoAssertion = "NOASSERTION"
51
51
PackageSupplierOrganization = "Organization"
52
52
53
+ PackageAnnotatorToolField = "Tool"
54
+
53
55
RelationShipContains = common .TypeRelationshipContains
54
56
RelationShipDescribe = common .TypeRelationshipDescribe
55
57
RelationShipDependsOn = common .TypeRelationshipDependsOn
@@ -122,14 +124,17 @@ func (m *Marshaler) Marshal(ctx context.Context, bom *core.BOM) (*spdx.Document,
122
124
packages []* spdx.Package
123
125
)
124
126
127
+ // Lock time to use same time for all spdx fields
128
+ timeNow := clock .Now (ctx ).UTC ().Format (time .RFC3339 )
129
+
125
130
root := bom .Root ()
126
131
pkgDownloadLocation := m .packageDownloadLocation (root )
127
132
128
133
// Component ID => SPDX ID
129
134
packageIDs := make (map [uuid.UUID ]spdx.ElementID )
130
135
131
136
// Root package contains OS, OS packages, language-specific packages and so on.
132
- rootPkg , err := m .rootSPDXPackage (root , pkgDownloadLocation )
137
+ rootPkg , err := m .rootSPDXPackage (root , timeNow , pkgDownloadLocation )
133
138
if err != nil {
134
139
return nil , xerrors .Errorf ("failed to generate a root package: %w" , err )
135
140
}
@@ -144,7 +149,7 @@ func (m *Marshaler) Marshal(ctx context.Context, bom *core.BOM) (*spdx.Document,
144
149
if c .Root {
145
150
continue
146
151
}
147
- spdxPackage , err := m .spdxPackage (c , pkgDownloadLocation )
152
+ spdxPackage , err := m .spdxPackage (c , timeNow , pkgDownloadLocation )
148
153
if err != nil {
149
154
return nil , xerrors .Errorf ("spdx package error: %w" , err )
150
155
}
@@ -216,7 +221,7 @@ func (m *Marshaler) Marshal(ctx context.Context, bom *core.BOM) (*spdx.Document,
216
221
CreatorType : "Tool" ,
217
222
},
218
223
},
219
- Created : clock . Now ( ctx ). UTC (). Format ( time . RFC3339 ) ,
224
+ Created : timeNow ,
220
225
},
221
226
Packages : packages ,
222
227
Relationships : relationShips ,
@@ -237,7 +242,7 @@ func (m *Marshaler) packageDownloadLocation(root *core.Component) string {
237
242
return location
238
243
}
239
244
240
- func (m * Marshaler ) rootSPDXPackage (root * core.Component , pkgDownloadLocation string ) (* spdx.Package , error ) {
245
+ func (m * Marshaler ) rootSPDXPackage (root * core.Component , timeNow , pkgDownloadLocation string ) (* spdx.Package , error ) {
241
246
var externalReferences []* spdx.PackageExternalReference
242
247
// When the target is a container image, add PURL to the external references of the root package.
243
248
if root .PkgIdentifier .PURL != nil {
@@ -258,17 +263,25 @@ func (m *Marshaler) rootSPDXPackage(root *core.Component, pkgDownloadLocation st
258
263
PackageName : root .Name ,
259
264
PackageSPDXIdentifier : elementID (camelCase (string (root .Type )), pkgID ),
260
265
PackageDownloadLocation : pkgDownloadLocation ,
261
- PackageAttributionTexts : m . spdxAttributionTexts (root ),
266
+ Annotations : m . spdxAnnotations (root , timeNow ),
262
267
PackageExternalReferences : externalReferences ,
263
268
PrimaryPackagePurpose : pkgPurpose ,
264
269
}, nil
265
270
}
266
271
267
- func (m * Marshaler ) appendAttributionText ( attributionTexts []string , key , value string ) []string {
272
+ func (m * Marshaler ) appendAnnotation ( annotations []spdx. Annotation , timeNow , key , value string ) []spdx. Annotation {
268
273
if value == "" {
269
- return attributionTexts
274
+ return annotations
270
275
}
271
- return append (attributionTexts , fmt .Sprintf ("%s: %s" , key , value ))
276
+ return append (annotations , spdx.Annotation {
277
+ AnnotationDate : timeNow ,
278
+ AnnotationType : spdx .CategoryOther ,
279
+ Annotator : spdx.Annotator {
280
+ Annotator : fmt .Sprintf ("%s-%s" , CreatorTool , m .appVersion ),
281
+ AnnotatorType : PackageAnnotatorToolField ,
282
+ },
283
+ AnnotationComment : fmt .Sprintf ("%s: %s" , key , value ),
284
+ })
272
285
}
273
286
274
287
func (m * Marshaler ) purlExternalReference (packageURL string ) * spdx.PackageExternalReference {
@@ -287,7 +300,7 @@ func (m *Marshaler) advisoryExternalReference(primaryURL string) *spdx.PackageEx
287
300
}
288
301
}
289
302
290
- func (m * Marshaler ) spdxPackage (c * core.Component , pkgDownloadLocation string ) (spdx.Package , error ) {
303
+ func (m * Marshaler ) spdxPackage (c * core.Component , timeNow , pkgDownloadLocation string ) (spdx.Package , error ) {
291
304
pkgID , err := calcPkgID (m .hasher , c )
292
305
if err != nil {
293
306
return spdx.Package {}, xerrors .Errorf ("failed to get os metadata package ID: %w" , err )
@@ -343,7 +356,7 @@ func (m *Marshaler) spdxPackage(c *core.Component, pkgDownloadLocation string) (
343
356
PrimaryPackagePurpose : purpose ,
344
357
PackageDownloadLocation : pkgDownloadLocation ,
345
358
PackageExternalReferences : pkgExtRefs ,
346
- PackageAttributionTexts : m . spdxAttributionTexts ( c ),
359
+ Annotations : m . spdxAnnotations ( c , timeNow ),
347
360
PackageSourceInfo : sourceInfo ,
348
361
PackageSupplier : supplier ,
349
362
PackageChecksums : m .spdxChecksums (digests ),
@@ -365,16 +378,15 @@ func spdxPkgName(component *core.Component) string {
365
378
}
366
379
return component .Name
367
380
}
368
-
369
- func (m * Marshaler ) spdxAttributionTexts (c * core.Component ) []string {
370
- var texts []string
381
+ func (m * Marshaler ) spdxAnnotations (c * core.Component , timeNow string ) []spdx.Annotation {
382
+ var annotations []spdx.Annotation
371
383
for _ , p := range c .Properties {
372
384
// Add properties that are not in other fields.
373
385
if ! slices .Contains (duplicateProperties , p .Name ) {
374
- texts = m .appendAttributionText ( texts , p .Name , p .Value )
386
+ annotations = m .appendAnnotation ( annotations , timeNow , p .Name , p .Value )
375
387
}
376
388
}
377
- return texts
389
+ return annotations
378
390
}
379
391
380
392
func (m * Marshaler ) spdxLicense (c * core.Component ) string {
0 commit comments