@@ -59,22 +59,8 @@ type DocumentType string
59
59
60
60
// Document* is the enumerables of DocumentType
61
61
const (
62
- DocumentITE6SLSA DocumentType = "SLSA"
63
- DocumentITE6Generic DocumentType = "ITE6"
64
- DocumentITE6Vul DocumentType = "ITE6VUL"
65
- DocumentITE6EOL DocumentType = "ITE6EOL"
66
- // ClearlyDefined
67
- DocumentITE6ClearlyDefined DocumentType = "ITE6CD"
68
- DocumentDSSE DocumentType = "DSSE"
69
- DocumentSPDX DocumentType = "SPDX"
70
- DocumentOpaque DocumentType = "OPAQUE"
71
- DocumentScorecard DocumentType = "SCORECARD"
72
- DocumentCycloneDX DocumentType = "CycloneDX"
73
- DocumentDepsDev DocumentType = "DEPS_DEV"
74
- DocumentCsaf DocumentType = "CSAF"
75
- DocumentOpenVEX DocumentType = "OPEN_VEX"
76
- DocumentIngestPredicates DocumentType = "INGEST_PREDICATES"
77
- DocumentUnknown DocumentType = "UNKNOWN"
62
+ DocumentSBOM DocumentType = "SBOM"
63
+ DocumentOpenVEX DocumentType = "OPEN_VEX"
78
64
)
79
65
80
66
// FormatType describes the document format for malform checks
@@ -142,6 +128,10 @@ func main() {
142
128
rootCmd .Flags ().StringP ("token-endpoint" , "k" , "" , "Token endpoint URL (required)" )
143
129
rootCmd .Flags ().StringP ("alias" , "a" , "" , "Alias that supersedes the subject in Kusari platform (optional)" )
144
130
rootCmd .Flags ().StringP ("document-type" , "d" , "" , "Type of the document (image or build) sbom (optional)" )
131
+ rootCmd .Flags ().Bool ("open-vex" , false , "Indicate that this is an OpenVEX document (optional, only works with files)" )
132
+ rootCmd .Flags ().String ("tag" , "" , "Tag value to set in the document wrapper upload meta (optional, e.g. govulncheck)" )
133
+ rootCmd .Flags ().String ("software-id" , "" , "Kusari Platform Software ID value to set in the document wrapper upload meta (optional)" )
134
+ rootCmd .Flags ().String ("sbom-subject" , "" , "Kusari Platform Software sbom subject substring value to set in the document wrapper upload meta (optional)" )
145
135
146
136
// Bind flags to Viper with error handling
147
137
mustBindPFlag (rootCmd , "file-path" )
@@ -151,6 +141,10 @@ func main() {
151
141
mustBindPFlag (rootCmd , "token-endpoint" )
152
142
mustBindPFlag (rootCmd , "alias" )
153
143
mustBindPFlag (rootCmd , "document-type" )
144
+ mustBindPFlag (rootCmd , "open-vex" )
145
+ mustBindPFlag (rootCmd , "tag" )
146
+ mustBindPFlag (rootCmd , "software-id" )
147
+ mustBindPFlag (rootCmd , "sbom-subject" )
154
148
155
149
// Allow environment variables
156
150
viper .SetEnvPrefix ("UPLOADER" )
@@ -205,12 +199,21 @@ func uploadFiles(cmd *cobra.Command, args []string) {
205
199
tokenEndPoint := viper .GetString ("token-endpoint" )
206
200
alias := viper .GetString ("alias" )
207
201
docType := viper .GetString ("document-type" )
202
+ isOpenVex := viper .GetBool ("open-vex" )
203
+ tag := viper .GetString ("tag" )
204
+ softwareID := viper .GetString ("software-id" )
205
+ sbomSubject := viper .GetString ("sbom-subject" )
208
206
209
207
// Validate required configuration
210
208
if filePath == "" || clientID == "" || clientSecret == "" ||
211
209
tenantEndPoint == "" || tokenEndPoint == "" {
212
210
log .Fatal ().Msg ("All required parameters must be provided" )
213
211
}
212
+
213
+ if isOpenVex && (tag == "" || (softwareID == "" && sbomSubject == "" )) {
214
+ log .Fatal ().Msg ("When using OpenVEX, tag must be specified, and so must software-id or sbom-subject" )
215
+ }
216
+
214
217
// Get authorized client
215
218
authorizedClient := getAuthorizedClient (ctx , clientID , clientSecret , tokenEndPoint )
216
219
defaultClient := & http.Client {}
@@ -223,13 +226,26 @@ func uploadFiles(cmd *cobra.Command, args []string) {
223
226
Msg ("Error getting file info" )
224
227
}
225
228
229
+ if fileInfo .IsDir () && isOpenVex {
230
+ log .Fatal ().Msg ("OpenVEX can't be used with directories, only single files" )
231
+ }
232
+
226
233
uploadMeta := map [string ]string {}
227
234
if alias != "" {
228
235
uploadMeta ["alias" ] = alias
229
236
}
230
237
if docType != "" {
231
238
uploadMeta ["type" ] = docType
232
239
}
240
+ if tag != "" {
241
+ uploadMeta ["tag" ] = tag
242
+ }
243
+ if softwareID != "" {
244
+ uploadMeta ["software_id" ] = softwareID
245
+ }
246
+ if sbomSubject != "" {
247
+ uploadMeta ["sbom_subject" ] = sbomSubject
248
+ }
233
249
234
250
// Upload based on file type
235
251
if fileInfo .IsDir () {
@@ -239,7 +255,7 @@ func uploadFiles(cmd *cobra.Command, args []string) {
239
255
Msg ("Directory upload failed" )
240
256
}
241
257
} else {
242
- if err := uploadSingleFile (authorizedClient , defaultClient , tenantEndPoint , filePath , uploadMeta ); err != nil {
258
+ if err := uploadSingleFile (authorizedClient , defaultClient , tenantEndPoint , filePath , isOpenVex , uploadMeta ); err != nil {
243
259
log .Fatal ().
244
260
Err (err ).
245
261
Msg ("Single file upload failed" )
@@ -297,14 +313,13 @@ func getPresignedUrl(authorizedClient HttpClient, tenantApiEndpoint string, payl
297
313
}
298
314
299
315
// uploadDirectory uses filepath.Walk to walk through the directory and upload the files that are found
300
- func uploadDirectory (authorizedClient , defaultClient HttpClient , tenantApiEndpoint ,
301
- dirPath string , uploadMeta map [string ]string ) error {
316
+ func uploadDirectory (authorizedClient , defaultClient HttpClient , tenantApiEndpoint , dirPath string , uploadMeta map [string ]string ) error {
302
317
err := filepath .Walk (dirPath , func (path string , info os.FileInfo , err error ) error {
303
318
if err != nil {
304
319
return err
305
320
}
306
321
if ! info .IsDir () {
307
- err = uploadSingleFile (authorizedClient , defaultClient , tenantApiEndpoint , path , uploadMeta )
322
+ err = uploadSingleFile (authorizedClient , defaultClient , tenantApiEndpoint , path , false , uploadMeta )
308
323
if err != nil {
309
324
return fmt .Errorf ("uploadSingleFile failed with error: %w" , err )
310
325
}
@@ -315,7 +330,8 @@ func uploadDirectory(authorizedClient, defaultClient HttpClient, tenantApiEndpoi
315
330
}
316
331
317
332
// uploadSingleFile creates a presigned URL for the filepath and calls uploadFile to upload the actual file
318
- func uploadSingleFile (authorizedClient , defaultClient HttpClient , tenantApiEndpoint , filePath string , uploadMeta map [string ]string ) error {
333
+ func uploadSingleFile (authorizedClient , defaultClient HttpClient , tenantApiEndpoint , filePath string , isOpenVex bool ,
334
+ uploadMeta map [string ]string ) error {
319
335
// check that the file is not empty
320
336
checkFile , err := os .Stat (filePath )
321
337
if err != nil {
@@ -345,14 +361,21 @@ func uploadSingleFile(authorizedClient, defaultClient HttpClient, tenantApiEndpo
345
361
}
346
362
347
363
// pass in default client without the jwt other wise it will error with both the presigned url and jwt
348
- return uploadBlob (defaultClient , presignedUrl , filePath , blob , uploadMeta )
364
+ return uploadBlob (defaultClient , presignedUrl , filePath , blob , isOpenVex , uploadMeta )
349
365
}
350
366
351
367
// uploadBlob takes the file and creates a `processor.Document` blob which is uploaded to S3
352
- func uploadBlob (defaultClient HttpClient , presignedUrl , filePath string , readFile []byte , uploadMeta map [string ]string ) error {
368
+ func uploadBlob (defaultClient HttpClient , presignedUrl , filePath string , readFile []byte , isOpenVex bool ,
369
+ uploadMeta map [string ]string ) error {
370
+
371
+ doctype := DocumentSBOM
372
+ if isOpenVex {
373
+ doctype = DocumentOpenVEX
374
+ }
375
+
353
376
baseDoc := & Document {
354
377
Blob : readFile ,
355
- Type : DocumentUnknown ,
378
+ Type : doctype ,
356
379
Format : FormatUnknown ,
357
380
SourceInformation : SourceInformation {
358
381
Collector : "Kusari-Uploader" ,
0 commit comments