github.com/google/osv-scalibr@v0.4.1/binary/proto/result_test.go (about) 1 // Copyright 2025 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package proto_test 16 17 import ( 18 "errors" 19 "runtime" 20 "slices" 21 "testing" 22 "time" 23 24 "github.com/docker/docker/api/types/container" 25 "github.com/google/go-cmp/cmp" 26 "github.com/google/go-cmp/cmp/cmpopts" 27 scalibr "github.com/google/osv-scalibr" 28 "github.com/google/osv-scalibr/binary/proto" 29 "github.com/google/osv-scalibr/extractor" 30 ctrdfs "github.com/google/osv-scalibr/extractor/filesystem/containers/containerd" 31 "github.com/google/osv-scalibr/extractor/filesystem/containers/podman" 32 "github.com/google/osv-scalibr/extractor/filesystem/language/dotnet/depsjson" 33 "github.com/google/osv-scalibr/extractor/filesystem/language/java/javalockfile" 34 "github.com/google/osv-scalibr/extractor/filesystem/language/java/pomxmlnet" 35 "github.com/google/osv-scalibr/extractor/filesystem/language/javascript/packagejson" 36 javascriptmeta "github.com/google/osv-scalibr/extractor/filesystem/language/javascript/packagejson/metadata" 37 "github.com/google/osv-scalibr/extractor/filesystem/language/python/requirements" 38 "github.com/google/osv-scalibr/extractor/filesystem/language/python/wheelegg" 39 "github.com/google/osv-scalibr/extractor/filesystem/os/dpkg" 40 dpkgmeta "github.com/google/osv-scalibr/extractor/filesystem/os/dpkg/metadata" 41 "github.com/google/osv-scalibr/extractor/filesystem/os/homebrew" 42 "github.com/google/osv-scalibr/extractor/filesystem/os/nix" 43 nixmeta "github.com/google/osv-scalibr/extractor/filesystem/os/nix/metadata" 44 "github.com/google/osv-scalibr/extractor/filesystem/os/pacman" 45 pacmanmeta "github.com/google/osv-scalibr/extractor/filesystem/os/pacman/metadata" 46 "github.com/google/osv-scalibr/extractor/filesystem/os/portage" 47 portagemeta "github.com/google/osv-scalibr/extractor/filesystem/os/portage/metadata" 48 "github.com/google/osv-scalibr/extractor/filesystem/os/rpm" 49 rpmmeta "github.com/google/osv-scalibr/extractor/filesystem/os/rpm/metadata" 50 "github.com/google/osv-scalibr/extractor/filesystem/os/winget" 51 wingetmeta "github.com/google/osv-scalibr/extractor/filesystem/os/winget/metadata" 52 "github.com/google/osv-scalibr/extractor/filesystem/sbom/cdx" 53 cdxmeta "github.com/google/osv-scalibr/extractor/filesystem/sbom/cdx/metadata" 54 ctrdruntime "github.com/google/osv-scalibr/extractor/standalone/containers/containerd" 55 ctrdruntimemd "github.com/google/osv-scalibr/extractor/standalone/containers/containerd/containerdmetadata" 56 "github.com/google/osv-scalibr/extractor/standalone/containers/docker" 57 winmetadata "github.com/google/osv-scalibr/extractor/standalone/windows/common/metadata" 58 "github.com/google/osv-scalibr/extractor/standalone/windows/dismpatch" 59 "github.com/google/osv-scalibr/inventory" 60 "github.com/google/osv-scalibr/inventory/vex" 61 "github.com/google/osv-scalibr/plugin" 62 "github.com/google/osv-scalibr/purl" 63 "github.com/google/osv-scalibr/veles" 64 "github.com/google/osv-scalibr/veles/secrets/gcpsak" 65 protobuf "google.golang.org/protobuf/proto" 66 "google.golang.org/protobuf/testing/protocmp" 67 68 spb "github.com/google/osv-scalibr/binary/proto/scan_result_go_proto" 69 "google.golang.org/protobuf/types/known/timestamppb" 70 ) 71 72 var ( 73 purlDPKGAnnotationPackage = &extractor.Package{ 74 Name: "software", 75 Version: "1.0.0", 76 PURLType: purl.TypeDebian, 77 Metadata: &dpkgmeta.Metadata{ 78 PackageName: "software", 79 PackageVersion: "1.0.0", 80 OSID: "debian", 81 OSVersionCodename: "jammy", 82 Maintainer: "maintainer", 83 Architecture: "amd64", 84 }, 85 Locations: []string{"/file1"}, 86 Plugins: []string{dpkg.Name}, 87 ExploitabilitySignals: []*vex.PackageExploitabilitySignal{&vex.PackageExploitabilitySignal{ 88 Plugin: dpkg.Name, 89 Justification: vex.ComponentNotPresent, 90 MatchesAllVulns: true, 91 }}, 92 } 93 purlDPKGAnnotationPackageProto = &spb.Package{ 94 Name: "software", 95 Version: "1.0.0", 96 Purl: &spb.Purl{ 97 Purl: "pkg:deb/debian/software@1.0.0?arch=amd64&distro=jammy", 98 Type: purl.TypeDebian, 99 Namespace: "debian", 100 Name: "software", 101 Version: "1.0.0", 102 Qualifiers: []*spb.Qualifier{ 103 {Key: "arch", Value: "amd64"}, 104 {Key: "distro", Value: "jammy"}, 105 }, 106 }, 107 Ecosystem: "Debian", 108 Metadata: &spb.Package_DpkgMetadata{ 109 DpkgMetadata: &spb.DPKGPackageMetadata{ 110 PackageName: "software", 111 PackageVersion: "1.0.0", 112 OsId: "debian", 113 OsVersionCodename: "jammy", 114 Maintainer: "maintainer", 115 Architecture: "amd64", 116 }, 117 }, 118 Locations: []string{"/file1"}, 119 // TODO(b/400910349): Remove once integrators stop using these fields. 120 Plugins: []string{"os/dpkg"}, 121 ExploitabilitySignals: []*spb.PackageExploitabilitySignal{&spb.PackageExploitabilitySignal{ 122 Plugin: dpkg.Name, 123 Justification: spb.VexJustification_COMPONENT_NOT_PRESENT, 124 VulnFilter: &spb.PackageExploitabilitySignal_MatchesAllVulns{MatchesAllVulns: true}, 125 }}, 126 } 127 ) 128 129 func TestScanResultToProtoAndBack(t *testing.T) { 130 endTime := time.Now() 131 startTime := endTime.Add(time.Second * -10) 132 success := &plugin.ScanStatus{Status: plugin.ScanStatusSucceeded} 133 successProto := &spb.ScanStatus{Status: spb.ScanStatus_SUCCEEDED} 134 failure := &plugin.ScanStatus{Status: plugin.ScanStatusFailed, FailureReason: "failure"} 135 failureProto := &spb.ScanStatus{Status: spb.ScanStatus_FAILED, FailureReason: "failure"} 136 purlDPKGPackage := &extractor.Package{ 137 Name: "software", 138 Version: "1.0.0", 139 PURLType: purl.TypeDebian, 140 Metadata: &dpkgmeta.Metadata{ 141 PackageName: "software", 142 PackageVersion: "1.0.0", 143 OSID: "debian", 144 OSVersionCodename: "jammy", 145 Maintainer: "maintainer", 146 Architecture: "amd64", 147 }, 148 Locations: []string{"/file1"}, 149 Plugins: []string{dpkg.Name}, 150 } 151 purlPythonPackage := &extractor.Package{ 152 Name: "software", 153 Version: "1.0.0", 154 PURLType: purl.TypePyPi, 155 Locations: []string{"/file1"}, 156 Plugins: []string{wheelegg.Name}, 157 Metadata: &wheelegg.PythonPackageMetadata{ 158 Author: "author", 159 AuthorEmail: "author@corp.com", 160 }, 161 } 162 pythonRequirementsPackage := &extractor.Package{ 163 Name: "foo", 164 Version: "1.0", 165 PURLType: purl.TypePyPi, 166 Locations: []string{"/file1"}, 167 Plugins: []string{requirements.Name}, 168 Metadata: &requirements.Metadata{ 169 HashCheckingModeValues: []string{"sha256:123"}, 170 VersionComparator: ">=", 171 Requirement: "foo>=1.0", 172 }, 173 } 174 purlJavascriptPackage := &extractor.Package{ 175 Name: "software", 176 Version: "1.0.0", 177 PURLType: purl.TypeNPM, 178 Metadata: &javascriptmeta.JavascriptPackageJSONMetadata{ 179 Maintainers: []*javascriptmeta.Person{ 180 { 181 Name: "maintainer1", 182 Email: "maintainer1@corp.com", 183 URL: "https://blog.maintainer1.com", 184 }, 185 { 186 Name: "maintainer2", 187 Email: "maintainer2@corp.com", 188 }, 189 }, 190 Source: javascriptmeta.Unknown, 191 }, 192 Locations: []string{"/file1"}, 193 Plugins: []string{packagejson.Name}, 194 } 195 196 purlDotnetDepsJSONPackage := &extractor.Package{ 197 Name: "software", 198 Version: "1.0.0", 199 PURLType: purl.TypeNuget, 200 Metadata: &depsjson.Metadata{ 201 PackageName: "software", 202 PackageVersion: "1.0.0", 203 Type: "type", 204 }, 205 Locations: []string{"/file1"}, 206 Plugins: []string{depsjson.Name}, 207 } 208 209 purlDotnetDepsJSONPackageProto := &spb.Package{ 210 Name: "software", 211 Version: "1.0.0", 212 Purl: &spb.Purl{ 213 Purl: "pkg:nuget/software@1.0.0", 214 Type: purl.TypeNuget, 215 Name: "software", 216 Version: "1.0.0", 217 }, 218 Ecosystem: "NuGet", 219 Locations: []string{"/file1"}, 220 Plugins: []string{"dotnet/depsjson"}, 221 Metadata: &spb.Package_DepsjsonMetadata{ 222 DepsjsonMetadata: &spb.DEPSJSONMetadata{ 223 PackageName: "software", 224 PackageVersion: "1.0.0", 225 Type: "type", 226 }, 227 }, 228 } 229 230 windowsPackage := &extractor.Package{ 231 Name: "windows_server_2019", 232 Version: "10.0.17763.3406", 233 PURLType: "windows", 234 Metadata: &winmetadata.OSVersion{ 235 Product: "windows_server_2019", 236 FullVersion: "10.0.17763.3406", 237 }, 238 Plugins: []string{dismpatch.Name}, 239 } 240 241 purlDPKGPackageProto := &spb.Package{ 242 Name: "software", 243 Version: "1.0.0", 244 Purl: &spb.Purl{ 245 Purl: "pkg:deb/debian/software@1.0.0?arch=amd64&distro=jammy", 246 Type: purl.TypeDebian, 247 Namespace: "debian", 248 Name: "software", 249 Version: "1.0.0", 250 Qualifiers: []*spb.Qualifier{ 251 {Key: "arch", Value: "amd64"}, 252 {Key: "distro", Value: "jammy"}, 253 }, 254 }, 255 Ecosystem: "Debian", 256 Metadata: &spb.Package_DpkgMetadata{ 257 DpkgMetadata: &spb.DPKGPackageMetadata{ 258 PackageName: "software", 259 PackageVersion: "1.0.0", 260 OsId: "debian", 261 OsVersionCodename: "jammy", 262 Maintainer: "maintainer", 263 Architecture: "amd64", 264 }, 265 }, 266 Locations: []string{"/file1"}, 267 Plugins: []string{"os/dpkg"}, 268 } 269 purlPythonPackageProto := &spb.Package{ 270 Name: "software", 271 Version: "1.0.0", 272 Purl: &spb.Purl{ 273 Purl: "pkg:pypi/software@1.0.0", 274 Type: purl.TypePyPi, 275 Name: "software", 276 Version: "1.0.0", 277 }, 278 Ecosystem: "PyPI", 279 Locations: []string{"/file1"}, 280 Plugins: []string{"python/wheelegg"}, 281 Metadata: &spb.Package_PythonMetadata{ 282 PythonMetadata: &spb.PythonPackageMetadata{ 283 Author: "author", 284 AuthorEmail: "author@corp.com", 285 }, 286 }, 287 } 288 pythonRequirementsPackageProto := &spb.Package{ 289 Name: "foo", 290 Version: "1.0", 291 Purl: &spb.Purl{ 292 Purl: "pkg:pypi/foo@1.0", 293 Type: purl.TypePyPi, 294 Name: "foo", 295 Version: "1.0", 296 }, 297 Ecosystem: "PyPI", 298 Locations: []string{"/file1"}, 299 Plugins: []string{"python/requirements"}, 300 Metadata: &spb.Package_PythonRequirementsMetadata{ 301 PythonRequirementsMetadata: &spb.PythonRequirementsMetadata{ 302 HashCheckingModeValues: []string{"sha256:123"}, 303 VersionComparator: ">=", 304 Requirement: "foo>=1.0", 305 }, 306 }, 307 } 308 purlJavascriptPackageProto := &spb.Package{ 309 Name: "software", 310 Version: "1.0.0", 311 Purl: &spb.Purl{ 312 Purl: "pkg:npm/software@1.0.0", 313 Type: purl.TypeNPM, 314 Name: "software", 315 Version: "1.0.0", 316 }, 317 Ecosystem: "npm", 318 Locations: []string{"/file1"}, 319 Plugins: []string{"javascript/packagejson"}, 320 Metadata: &spb.Package_JavascriptMetadata{ 321 JavascriptMetadata: &spb.JavascriptPackageJSONMetadata{ 322 Source: spb.PackageSource_UNKNOWN, 323 Maintainers: []string{ 324 "maintainer1 <maintainer1@corp.com> (https://blog.maintainer1.com)", 325 "maintainer2 <maintainer2@corp.com>", 326 }, 327 }, 328 }, 329 } 330 cdxPackage := &extractor.Package{ 331 Name: "openssl", 332 Version: "1.1.1", 333 PURLType: purl.TypeNPM, 334 Metadata: &cdxmeta.Metadata{ 335 PURL: &purl.PackageURL{ 336 Type: purl.TypeNPM, 337 Name: "openssl", 338 Version: "1.1.1", 339 }, 340 }, 341 Locations: []string{"/openssl"}, 342 Plugins: []string{cdx.Name}, 343 } 344 cdxPackageProto := &spb.Package{ 345 Name: "openssl", 346 Version: "1.1.1", 347 Ecosystem: "npm", 348 Purl: &spb.Purl{ 349 Purl: "pkg:npm/openssl@1.1.1", 350 Type: purl.TypeNPM, 351 Name: "openssl", 352 Version: "1.1.1", 353 }, 354 Metadata: &spb.Package_CdxMetadata{ 355 CdxMetadata: &spb.CDXPackageMetadata{ 356 Purl: &spb.Purl{ 357 Purl: "pkg:npm/openssl@1.1.1", 358 Type: purl.TypeNPM, 359 Name: "openssl", 360 Version: "1.1.1", 361 }, 362 }, 363 }, 364 Locations: []string{"/openssl"}, 365 Plugins: []string{"sbom/cdx"}, 366 } 367 purlRPMPackage := &extractor.Package{ 368 Name: "openssh-clients", 369 Version: "5.3p1", 370 PURLType: purl.TypeRPM, 371 Metadata: &rpmmeta.Metadata{ 372 PackageName: "openssh-clients", 373 SourceRPM: "openssh-5.3p1-124.el6_10.src.rpm", 374 Epoch: 2, 375 OSID: "rhel", 376 OSVersionID: "8.9", 377 OSBuildID: "", 378 OSName: "Red Hat Enterprise Linux", 379 Vendor: "CentOS", 380 Architecture: "x86_64", 381 }, 382 Licenses: []string{"BSD"}, 383 Locations: []string{"/file1"}, 384 Plugins: []string{rpm.Name}, 385 } 386 purlRPMPackageProto := &spb.Package{ 387 Name: "openssh-clients", 388 Version: "5.3p1", 389 Purl: &spb.Purl{ 390 Purl: "pkg:rpm/rhel/openssh-clients@5.3p1?arch=x86_64&distro=rhel-8.9&epoch=2&sourcerpm=openssh-5.3p1-124.el6_10.src.rpm", 391 Type: purl.TypeRPM, 392 Namespace: "rhel", 393 Name: "openssh-clients", 394 Version: "5.3p1", 395 Qualifiers: []*spb.Qualifier{ 396 {Key: "arch", Value: "x86_64"}, 397 {Key: "distro", Value: "rhel-8.9"}, 398 {Key: "epoch", Value: "2"}, 399 {Key: "sourcerpm", Value: "openssh-5.3p1-124.el6_10.src.rpm"}, 400 }, 401 }, 402 Licenses: []string{"BSD"}, 403 Ecosystem: "Red Hat", 404 Metadata: &spb.Package_RpmMetadata{ 405 RpmMetadata: &spb.RPMPackageMetadata{ 406 PackageName: "openssh-clients", 407 SourceRpm: "openssh-5.3p1-124.el6_10.src.rpm", 408 Epoch: 2, 409 OsId: "rhel", 410 OsVersionId: "8.9", 411 OsBuildId: "", 412 OsName: "Red Hat Enterprise Linux", 413 Vendor: "CentOS", 414 Architecture: "x86_64", 415 }, 416 }, 417 Locations: []string{"/file1"}, 418 Plugins: []string{"os/rpm"}, 419 } 420 purlPACMANPackage := &extractor.Package{ 421 Name: "zstd", 422 Version: "1.5.6-1", 423 PURLType: purl.TypePacman, 424 Metadata: &pacmanmeta.Metadata{ 425 PackageName: "zstd", 426 PackageVersion: "1.5.6-1", 427 OSID: "arch", 428 OSVersionID: "20241201.0.284684", 429 }, 430 Locations: []string{"/file1"}, 431 Plugins: []string{pacman.Name}, 432 } 433 purlPACMANPackageProto := &spb.Package{ 434 Name: "zstd", 435 Version: "1.5.6-1", 436 Purl: &spb.Purl{ 437 Purl: "pkg:pacman/arch/zstd@1.5.6-1?distro=20241201.0.284684", 438 Type: purl.TypePacman, 439 Namespace: "arch", 440 Name: "zstd", 441 Version: "1.5.6-1", 442 Qualifiers: []*spb.Qualifier{ 443 {Key: "distro", Value: "20241201.0.284684"}, 444 }, 445 }, 446 Ecosystem: "", 447 Metadata: &spb.Package_PacmanMetadata{ 448 PacmanMetadata: &spb.PACMANPackageMetadata{ 449 PackageName: "zstd", 450 PackageVersion: "1.5.6-1", 451 OsId: "arch", 452 OsVersionId: "20241201.0.284684", 453 }, 454 }, 455 Locations: []string{"/file1"}, 456 Plugins: []string{"os/pacman"}, 457 } 458 purlPORTAGEPackage := &extractor.Package{ 459 Name: "Capture-Tiny", 460 Version: "0.480.0-r1", 461 PURLType: purl.TypePortage, 462 Metadata: &portagemeta.Metadata{ 463 PackageName: "Capture-Tiny", 464 PackageVersion: "0.480.0-r1", 465 OSID: "gentoo", 466 OSVersionID: "2.17", 467 }, 468 Locations: []string{"/file1"}, 469 Plugins: []string{portage.Name}, 470 } 471 purlPORTAGEPackageProto := &spb.Package{ 472 Name: "Capture-Tiny", 473 Version: "0.480.0-r1", 474 Purl: &spb.Purl{ 475 Purl: "pkg:portage/gentoo/Capture-Tiny@0.480.0-r1?distro=2.17", 476 Type: purl.TypePortage, 477 Namespace: "gentoo", 478 Name: "Capture-Tiny", 479 Version: "0.480.0-r1", 480 Qualifiers: []*spb.Qualifier{ 481 {Key: "distro", Value: "2.17"}, 482 }, 483 }, 484 Ecosystem: "", 485 Metadata: &spb.Package_PortageMetadata{ 486 PortageMetadata: &spb.PortagePackageMetadata{ 487 PackageName: "Capture-Tiny", 488 PackageVersion: "0.480.0-r1", 489 OsId: "gentoo", 490 OsVersionId: "2.17", 491 }, 492 }, 493 Locations: []string{"/file1"}, 494 Plugins: []string{"os/portage"}, 495 } 496 purlNixPackage := &extractor.Package{ 497 Name: "attr", 498 Version: "2.5.2", 499 PURLType: purl.TypeNix, 500 Metadata: &nixmeta.Metadata{ 501 PackageName: "attr", 502 PackageVersion: "2.5.2", 503 OSID: "nixos", 504 OSVersionCodename: "vicuna", 505 OSVersionID: "24.11", 506 }, 507 Locations: []string{"/file1"}, 508 Plugins: []string{nix.Name}, 509 } 510 purlNixPackageProto := &spb.Package{ 511 Name: "attr", 512 Version: "2.5.2", 513 Purl: &spb.Purl{ 514 Purl: "pkg:nix/attr@2.5.2?distro=vicuna", 515 Type: purl.TypeNix, 516 Name: "attr", 517 Version: "2.5.2", 518 Qualifiers: []*spb.Qualifier{ 519 {Key: "distro", Value: "vicuna"}, 520 }, 521 }, 522 Ecosystem: "", 523 Metadata: &spb.Package_NixMetadata{ 524 NixMetadata: &spb.NixPackageMetadata{ 525 PackageName: "attr", 526 PackageVersion: "2.5.2", 527 OsId: "nixos", 528 OsVersionCodename: "vicuna", 529 OsVersionId: "24.11", 530 }, 531 }, 532 Locations: []string{"/file1"}, 533 Plugins: []string{"os/nix"}, 534 } 535 purlHomebrewPackage := &extractor.Package{ 536 Name: "rclone", 537 Version: "1.67.0", 538 PURLType: purl.TypeBrew, 539 Metadata: &homebrew.Metadata{}, 540 Locations: []string{"/file1"}, 541 Plugins: []string{homebrew.Name}, 542 } 543 purlHomebrewPackageProto := &spb.Package{ 544 Name: "rclone", 545 Version: "1.67.0", 546 Purl: &spb.Purl{ 547 Purl: "pkg:brew/rclone@1.67.0", 548 Type: purl.TypeBrew, 549 Name: "rclone", 550 Version: "1.67.0", 551 }, 552 Metadata: &spb.Package_HomebrewMetadata{}, 553 Locations: []string{"/file1"}, 554 Plugins: []string{"os/homebrew"}, 555 } 556 purlWingetPackage := &extractor.Package{ 557 Name: "Git.Git", 558 Version: "2.50.1", 559 PURLType: purl.TypeWinget, 560 Metadata: &wingetmeta.Metadata{ 561 Name: "Git", 562 ID: "Git.Git", 563 Version: "2.50.1", 564 Moniker: "git", 565 Channel: "", 566 Tags: []string{"git", "vcs"}, 567 Commands: []string{"git"}, 568 }, 569 Locations: []string{"/file1"}, 570 Plugins: []string{winget.Name}, 571 } 572 purlWingetPackageProto := &spb.Package{ 573 Name: "Git.Git", 574 Version: "2.50.1", 575 Purl: &spb.Purl{ 576 Purl: "pkg:winget/Git.Git@2.50.1", 577 Type: purl.TypeWinget, 578 Name: "Git.Git", 579 Version: "2.50.1", 580 }, 581 Metadata: &spb.Package_WingetMetadata{ 582 WingetMetadata: &spb.WingetPackageMetadata{ 583 Name: "Git", 584 Id: "Git.Git", 585 Version: "2.50.1", 586 Moniker: "git", 587 Channel: "", 588 Tags: []string{"git", "vcs"}, 589 Commands: []string{"git"}, 590 }, 591 }, 592 Locations: []string{"/file1"}, 593 Plugins: []string{"os/winget"}, 594 } 595 containerdPackage := &extractor.Package{ 596 Name: "gcr.io/google-samples/hello-app:1.0", 597 Version: "sha256:b1455e1c4fcc5ea1023c9e3b584cd84b64eb920e332feff690a2829696e379e7", 598 Metadata: &ctrdfs.Metadata{ 599 Namespace: "default", 600 ImageName: "gcr.io/google-samples/hello-app:1.0", 601 ImageDigest: "sha256:b1455e1c4fcc5ea1023c9e3b584cd84b64eb920e332feff690a2829696e379e7", 602 Runtime: "io.containerd.runc.v2", 603 PID: 8915, 604 Snapshotter: "overlayfs", 605 SnapshotKey: "abcweraweroiuojgawer1", 606 LowerDir: "/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/1/fs", 607 UpperDir: "/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/4/fs", 608 WorkDir: "/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/4/work", 609 }, 610 Locations: []string{"/file4"}, 611 Plugins: []string{ctrdfs.Name}, 612 } 613 containerdPackageProto := &spb.Package{ 614 Name: "gcr.io/google-samples/hello-app:1.0", 615 Version: "sha256:b1455e1c4fcc5ea1023c9e3b584cd84b64eb920e332feff690a2829696e379e7", 616 Ecosystem: "", 617 Metadata: &spb.Package_ContainerdContainerMetadata{ 618 ContainerdContainerMetadata: &spb.ContainerdContainerMetadata{ 619 NamespaceName: "default", 620 ImageName: "gcr.io/google-samples/hello-app:1.0", 621 ImageDigest: "sha256:b1455e1c4fcc5ea1023c9e3b584cd84b64eb920e332feff690a2829696e379e7", 622 Runtime: "io.containerd.runc.v2", 623 Pid: 8915, 624 Snapshotter: "overlayfs", 625 SnapshotKey: "abcweraweroiuojgawer1", 626 LowerDir: "/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/1/fs", 627 UpperDir: "/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/4/fs", 628 WorkDir: "/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/4/work", 629 }, 630 }, 631 Locations: []string{"/file4"}, 632 Plugins: []string{"containers/containerd"}, 633 } 634 containerdRuntimePackage := &extractor.Package{ 635 Name: "gcr.io/google-samples/hello-app:1.0", 636 Version: "sha256:b1455e1c4fcc5ea1023c9e3b584cd84b64eb920e332feff690a2829696e379e7", 637 Metadata: &ctrdruntimemd.Metadata{ 638 Namespace: "default", 639 ImageName: "gcr.io/google-samples/hello-app:1.0", 640 ImageDigest: "sha256:b1455e1c4fcc5ea1023c9e3b584cd84b64eb920e332feff690a2829696e379e7", 641 Runtime: "io.containerd.runc.v2", 642 ID: "1234567890", 643 PID: 8915, 644 RootFS: "/run/containerd/io.containerd.runtime.v2.task/default/1234567890/rootfs", 645 }, 646 Locations: []string{"/file7"}, 647 Plugins: []string{ctrdruntime.Name}, 648 } 649 containerdRuntimePackageProto := &spb.Package{ 650 Name: "gcr.io/google-samples/hello-app:1.0", 651 Version: "sha256:b1455e1c4fcc5ea1023c9e3b584cd84b64eb920e332feff690a2829696e379e7", 652 Ecosystem: "", 653 Metadata: &spb.Package_ContainerdRuntimeContainerMetadata{ 654 ContainerdRuntimeContainerMetadata: &spb.ContainerdRuntimeContainerMetadata{ 655 NamespaceName: "default", 656 ImageName: "gcr.io/google-samples/hello-app:1.0", 657 ImageDigest: "sha256:b1455e1c4fcc5ea1023c9e3b584cd84b64eb920e332feff690a2829696e379e7", 658 Runtime: "io.containerd.runc.v2", 659 Id: "1234567890", 660 Pid: 8915, 661 RootfsPath: "/run/containerd/io.containerd.runtime.v2.task/default/1234567890/rootfs", 662 }, 663 }, 664 Locations: []string{"/file7"}, 665 Plugins: []string{"containers/containerd-runtime"}, 666 } 667 windowsPackageProto := &spb.Package{ 668 Name: "windows_server_2019", 669 Version: "10.0.17763.3406", 670 Metadata: &spb.Package_WindowsOsVersionMetadata{ 671 WindowsOsVersionMetadata: &spb.WindowsOSVersion{ 672 Product: "windows_server_2019", 673 FullVersion: "10.0.17763.3406", 674 }, 675 }, 676 Purl: &spb.Purl{ 677 Purl: "pkg:generic/microsoft/windows_server_2019@10.0.17763.3406?buildnumber=10.0.17763.3406", 678 Type: purl.TypeGeneric, 679 Namespace: "microsoft", 680 Name: "windows_server_2019", 681 Version: "10.0.17763.3406", 682 Qualifiers: []*spb.Qualifier{ 683 { 684 Key: "buildnumber", 685 Value: "10.0.17763.3406", 686 }, 687 }, 688 }, 689 Plugins: []string{"windows/dismpatch"}, 690 } 691 mavenPackage := &extractor.Package{ 692 Name: "abc:xyz", 693 Version: "1.0.0", 694 PURLType: purl.TypeMaven, 695 Locations: []string{"/pom.xml"}, 696 Plugins: []string{pomxmlnet.Name}, 697 Metadata: &javalockfile.Metadata{ 698 GroupID: "abc", 699 ArtifactID: "xyz", 700 IsTransitive: true, 701 }, 702 } 703 mavenPackageProto := &spb.Package{ 704 Name: "abc:xyz", 705 Version: "1.0.0", 706 Ecosystem: "Maven", 707 Purl: &spb.Purl{ 708 Purl: "pkg:maven/abc/xyz@1.0.0", 709 Type: purl.TypeMaven, 710 Name: "xyz", 711 Namespace: "abc", 712 Version: "1.0.0", 713 }, 714 Locations: []string{"/pom.xml"}, 715 Plugins: []string{"java/pomxmlnet"}, 716 Metadata: &spb.Package_JavaLockfileMetadata{ 717 JavaLockfileMetadata: &spb.JavaLockfileMetadata{ 718 ArtifactId: "xyz", 719 GroupId: "abc", 720 IsTransitive: true, 721 }, 722 }, 723 } 724 725 podmanPackage := &extractor.Package{ 726 Name: "docker.io/redis", 727 Version: "a8036f14f15ead9517115576fb4462894a000620c2be556410f6c24afb8a482b", 728 Metadata: &podman.Metadata{ 729 ExposedPorts: map[uint16][]string{6379: {"tcp"}}, 730 PID: 4232, 731 Status: "running", 732 NameSpace: "", 733 StartedTime: endTime.Add(-10 * time.Minute), 734 FinishedTime: endTime.Add(-5 * time.Minute), 735 ExitCode: 0, 736 Exited: false, 737 }, 738 Plugins: []string{podman.Name}, 739 } 740 podmanPackageProto := &spb.Package{ 741 Name: "docker.io/redis", 742 Version: "a8036f14f15ead9517115576fb4462894a000620c2be556410f6c24afb8a482b", 743 Metadata: &spb.Package_PodmanMetadata{ 744 PodmanMetadata: &spb.PodmanMetadata{ 745 ExposedPorts: map[uint32]*spb.Protocol{6379: {Names: []string{"tcp"}}}, 746 Pid: 4232, 747 NamespaceName: "", 748 StartedTime: timestamppb.New(endTime.Add(-10 * time.Minute)), 749 FinishedTime: timestamppb.New(endTime.Add(-5 * time.Minute)), 750 Status: "running", 751 ExitCode: 0, 752 Exited: false, 753 }, 754 }, 755 Plugins: []string{"containers/podman"}, 756 } 757 758 gcpsakSecret := &inventory.Secret{ 759 Secret: gcpsak.GCPSAK{ 760 PrivateKeyID: "some-private-key-id", 761 ServiceAccount: "some-service-account@gserviceaccount.iam.google.com", 762 Signature: make([]byte, 256), 763 }, 764 Location: "/foo/bar/baz.json", 765 Validation: inventory.SecretValidationResult{ 766 At: startTime, 767 Status: veles.ValidationInvalid, 768 }, 769 } 770 gcpsakSecretProto := &spb.Secret{ 771 Secret: &spb.SecretData{ 772 Secret: &spb.SecretData_Gcpsak{ 773 Gcpsak: &spb.SecretData_GCPSAK{ 774 PrivateKeyId: "some-private-key-id", 775 ClientEmail: "some-service-account@gserviceaccount.iam.google.com", 776 Signature: make([]byte, 256), 777 }, 778 }, 779 }, 780 Status: &spb.SecretStatus{ 781 Status: spb.SecretStatus_INVALID, 782 LastUpdated: timestamppb.New(startTime), 783 }, 784 Locations: []*spb.Location{ 785 &spb.Location{ 786 Location: &spb.Location_Filepath{ 787 Filepath: &spb.Filepath{ 788 Path: "/foo/bar/baz.json", 789 }, 790 }, 791 }, 792 }, 793 } 794 gcpsakSecretWithExtra := &inventory.Secret{ 795 Secret: gcpsak.GCPSAK{ 796 PrivateKeyID: "some-private-key-id", 797 ServiceAccount: "some-service-account@gserviceaccount.iam.google.com", 798 Signature: make([]byte, 256), 799 Extra: &gcpsak.ExtraFields{ 800 Type: "service_account", 801 ProjectID: "some-project-id", 802 ClientID: "1122334455", 803 AuthURI: "https://accounts.google.com/o/oauth2/auth", 804 TokenURI: "https://oauth2.googleapis.com/token", 805 AuthProviderX509CertURL: "https://www.googleapis.com/oauth2/v1/certs", 806 ClientX509CertURL: "https://www.googleapis.com/robot/v1/metadata/x509/some-service-account%40gserviceaccount.iam.google.com", 807 UniverseDomain: "googleapis.com", 808 PrivateKey: "-----BEGIN PRIVATE KEY-----\nREDACTED\n-----END PRIVATE KEY-----\n", 809 }, 810 }, 811 Location: "/foo/bar/baz.json", 812 Validation: inventory.SecretValidationResult{ 813 At: startTime, 814 Status: veles.ValidationInvalid, 815 }, 816 } 817 gcpsakSecretProtoWithExtra := &spb.Secret{ 818 Secret: &spb.SecretData{ 819 Secret: &spb.SecretData_Gcpsak{ 820 Gcpsak: &spb.SecretData_GCPSAK{ 821 PrivateKeyId: "some-private-key-id", 822 ClientEmail: "some-service-account@gserviceaccount.iam.google.com", 823 Signature: make([]byte, 256), 824 Type: "service_account", 825 ProjectId: "some-project-id", 826 ClientId: "1122334455", 827 AuthUri: "https://accounts.google.com/o/oauth2/auth", 828 TokenUri: "https://oauth2.googleapis.com/token", 829 AuthProviderX509CertUrl: "https://www.googleapis.com/oauth2/v1/certs", 830 ClientX509CertUrl: "https://www.googleapis.com/robot/v1/metadata/x509/some-service-account%40gserviceaccount.iam.google.com", 831 UniverseDomain: "googleapis.com", 832 PrivateKey: "-----BEGIN PRIVATE KEY-----\nREDACTED\n-----END PRIVATE KEY-----\n", 833 }, 834 }, 835 }, 836 Status: &spb.SecretStatus{ 837 Status: spb.SecretStatus_INVALID, 838 LastUpdated: timestamppb.New(startTime), 839 }, 840 Locations: []*spb.Location{ 841 &spb.Location{ 842 Location: &spb.Location_Filepath{ 843 Filepath: &spb.Filepath{ 844 Path: "/foo/bar/baz.json", 845 }, 846 }, 847 }, 848 }, 849 } 850 851 dockerPackage := &extractor.Package{ 852 Name: "redis", 853 Version: "sha256:a8036f14f15ead9517115576fb4462894a000620c2be556410f6c24afb8a482b", 854 Metadata: &docker.Metadata{ 855 ImageName: "redis", 856 ImageDigest: "sha256:a8036f14f15ead9517115576fb4462894a000620c2be556410f6c24afb8a482b", 857 ID: "3ea6adad2e94daf386e1d6c5960807b41f19da2333e8a6261065c1cb8e85ac81", 858 Ports: []container.Port{{IP: "127.0.0.1", PrivatePort: 6379, PublicPort: 1112, Type: "tcp"}}, 859 }, 860 Plugins: []string{docker.Name}, 861 } 862 863 dockerPackageProto := &spb.Package{ 864 Name: "redis", 865 Version: "sha256:a8036f14f15ead9517115576fb4462894a000620c2be556410f6c24afb8a482b", 866 Metadata: &spb.Package_DockerContainersMetadata{ 867 DockerContainersMetadata: &spb.DockerContainersMetadata{ 868 ImageName: "redis", 869 ImageDigest: "sha256:a8036f14f15ead9517115576fb4462894a000620c2be556410f6c24afb8a482b", 870 Id: "3ea6adad2e94daf386e1d6c5960807b41f19da2333e8a6261065c1cb8e85ac81", 871 Ports: []*spb.DockerPort{ 872 {Ip: "127.0.0.1", PrivatePort: 6379, PublicPort: 1112, Type: "tcp"}, 873 }, 874 }, 875 }, 876 Plugins: []string{"containers/docker"}, 877 } 878 879 licensePackage := &extractor.Package{ 880 Name: "express", 881 Version: "4.17.1", 882 Licenses: []string{"MIT"}, 883 } 884 licensePackageProto := &spb.Package{ 885 Name: "express", 886 Version: "4.17.1", 887 Licenses: []string{"MIT"}, 888 } 889 890 testCases := []struct { 891 desc string 892 res *scalibr.ScanResult 893 want *spb.ScanResult 894 wantErr error 895 excludeForOS []string // skip test for these operating systems 896 }{ 897 { 898 desc: "Successful_scan", 899 res: &scalibr.ScanResult{ 900 Version: "1.0.0", 901 StartTime: startTime, 902 EndTime: endTime, 903 Status: success, 904 PluginStatus: []*plugin.Status{ 905 { 906 Name: "ext", 907 Version: 2, 908 Status: success, 909 }, 910 { 911 Name: "det", 912 Version: 3, 913 Status: success, 914 }, 915 }, 916 Inventory: inventory.Inventory{ 917 Packages: []*extractor.Package{ 918 purlDPKGPackage, 919 purlDPKGAnnotationPackage, 920 purlPythonPackage, 921 pythonRequirementsPackage, 922 purlJavascriptPackage, 923 purlDotnetDepsJSONPackage, 924 cdxPackage, 925 windowsPackage, 926 purlHomebrewPackage, 927 pkgWithLayerStruct, 928 }, 929 ContainerImageMetadata: []*extractor.ContainerImageMetadata{ 930 cimStructForTest, 931 }, 932 GenericFindings: []*inventory.GenericFinding{ 933 { 934 Adv: &inventory.GenericFindingAdvisory{ 935 ID: &inventory.AdvisoryID{ 936 Publisher: "CVE", 937 Reference: "CVE-1234", 938 }, 939 Title: "Title", 940 Description: "Description", 941 Recommendation: "Recommendation", 942 Sev: inventory.SeverityMedium, 943 }, 944 Target: &inventory.GenericFindingTargetDetails{ 945 Extra: "extra details", 946 }, 947 Plugins: []string{"cve/cve-1234-finder"}, 948 ExploitabilitySignals: []*vex.FindingExploitabilitySignal{{ 949 Plugin: dpkg.Name, 950 Justification: vex.ComponentNotPresent, 951 }}, 952 }, 953 }, 954 }, 955 }, 956 want: &spb.ScanResult{ 957 Version: "1.0.0", 958 StartTime: timestamppb.New(startTime), 959 EndTime: timestamppb.New(endTime), 960 Status: successProto, 961 PluginStatus: []*spb.PluginStatus{ 962 { 963 Name: "ext", 964 Version: 2, 965 Status: successProto, 966 }, 967 { 968 Name: "det", 969 Version: 3, 970 Status: successProto, 971 }, 972 }, 973 Inventory: &spb.Inventory{ 974 Packages: []*spb.Package{ 975 purlDPKGPackageProto, 976 purlDPKGAnnotationPackageProto, 977 purlPythonPackageProto, 978 pythonRequirementsPackageProto, 979 purlJavascriptPackageProto, 980 purlDotnetDepsJSONPackageProto, 981 cdxPackageProto, 982 windowsPackageProto, 983 purlHomebrewPackageProto, 984 pkgWithLayerProto, 985 }, 986 ContainerImageMetadata: []*spb.ContainerImageMetadata{ 987 cimProtoForTest, 988 }, 989 GenericFindings: []*spb.GenericFinding{ 990 { 991 Adv: &spb.GenericFindingAdvisory{ 992 Id: &spb.AdvisoryId{ 993 Publisher: "CVE", 994 Reference: "CVE-1234", 995 }, 996 Title: "Title", 997 Description: "Description", 998 Recommendation: "Recommendation", 999 Sev: spb.SeverityEnum_MEDIUM, 1000 }, 1001 Target: &spb.GenericFindingTargetDetails{ 1002 Extra: "extra details", 1003 }, 1004 Plugins: []string{"cve/cve-1234-finder"}, 1005 ExploitabilitySignals: []*spb.FindingExploitabilitySignal{{ 1006 Plugin: dpkg.Name, 1007 Justification: spb.VexJustification_COMPONENT_NOT_PRESENT, 1008 }}, 1009 }, 1010 }, 1011 }, 1012 }, 1013 }, 1014 { 1015 desc: "Successful_RPM_scan_linux-only", 1016 res: &scalibr.ScanResult{ 1017 Version: "1.0.0", 1018 StartTime: startTime, 1019 EndTime: endTime, 1020 Status: success, 1021 PluginStatus: []*plugin.Status{ 1022 { 1023 Name: "ext", 1024 Version: 2, 1025 Status: success, 1026 }, 1027 }, 1028 Inventory: inventory.Inventory{ 1029 Packages: []*extractor.Package{purlRPMPackage}, 1030 }, 1031 }, 1032 want: &spb.ScanResult{ 1033 Version: "1.0.0", 1034 StartTime: timestamppb.New(startTime), 1035 EndTime: timestamppb.New(endTime), 1036 Status: successProto, 1037 PluginStatus: []*spb.PluginStatus{ 1038 { 1039 Name: "ext", 1040 Version: 2, 1041 Status: successProto, 1042 }, 1043 }, 1044 Inventory: &spb.Inventory{ 1045 Packages: []*spb.Package{purlRPMPackageProto}, 1046 GenericFindings: []*spb.GenericFinding{}, 1047 }, 1048 }, 1049 excludeForOS: []string{"windows", "darwin"}, 1050 }, 1051 { 1052 desc: "Successful_PACMAN_scan_linux-only", 1053 res: &scalibr.ScanResult{ 1054 Version: "1.0.0", 1055 StartTime: startTime, 1056 EndTime: endTime, 1057 Status: success, 1058 PluginStatus: []*plugin.Status{ 1059 { 1060 Name: "ext", 1061 Version: 2, 1062 Status: success, 1063 }, 1064 }, 1065 Inventory: inventory.Inventory{ 1066 Packages: []*extractor.Package{purlPACMANPackage}, 1067 }, 1068 }, 1069 want: &spb.ScanResult{ 1070 Version: "1.0.0", 1071 StartTime: timestamppb.New(startTime), 1072 EndTime: timestamppb.New(endTime), 1073 Status: successProto, 1074 PluginStatus: []*spb.PluginStatus{ 1075 { 1076 Name: "ext", 1077 Version: 2, 1078 Status: successProto, 1079 }, 1080 }, 1081 Inventory: &spb.Inventory{ 1082 Packages: []*spb.Package{purlPACMANPackageProto}, 1083 GenericFindings: []*spb.GenericFinding{}, 1084 }, 1085 }, 1086 excludeForOS: []string{"windows", "darwin"}, 1087 }, 1088 { 1089 desc: "Successful_PORTAGE_scan_linux-only", 1090 res: &scalibr.ScanResult{ 1091 Version: "1.0.0", 1092 StartTime: startTime, 1093 EndTime: endTime, 1094 Status: success, 1095 PluginStatus: []*plugin.Status{ 1096 { 1097 Name: "ext", 1098 Version: 2, 1099 Status: success, 1100 }, 1101 }, 1102 Inventory: inventory.Inventory{ 1103 Packages: []*extractor.Package{purlPORTAGEPackage}, 1104 }, 1105 }, 1106 want: &spb.ScanResult{ 1107 Version: "1.0.0", 1108 StartTime: timestamppb.New(startTime), 1109 EndTime: timestamppb.New(endTime), 1110 Status: successProto, 1111 PluginStatus: []*spb.PluginStatus{ 1112 { 1113 Name: "ext", 1114 Version: 2, 1115 Status: successProto, 1116 }, 1117 }, 1118 Inventory: &spb.Inventory{ 1119 Packages: []*spb.Package{purlPORTAGEPackageProto}, 1120 GenericFindings: []*spb.GenericFinding{}, 1121 }, 1122 }, 1123 excludeForOS: []string{"windows", "darwin"}, 1124 }, 1125 { 1126 desc: "Successful_Nix_scan_linux-only", 1127 res: &scalibr.ScanResult{ 1128 Version: "1.0.0", 1129 StartTime: startTime, 1130 EndTime: endTime, 1131 Status: success, 1132 PluginStatus: []*plugin.Status{ 1133 { 1134 Name: "ext", 1135 Version: 2, 1136 Status: success, 1137 }, 1138 }, 1139 Inventory: inventory.Inventory{ 1140 Packages: []*extractor.Package{purlNixPackage}, 1141 }, 1142 }, 1143 want: &spb.ScanResult{ 1144 Version: "1.0.0", 1145 StartTime: timestamppb.New(startTime), 1146 EndTime: timestamppb.New(endTime), 1147 Status: successProto, 1148 PluginStatus: []*spb.PluginStatus{ 1149 { 1150 Name: "ext", 1151 Version: 2, 1152 Status: successProto, 1153 }, 1154 }, 1155 Inventory: &spb.Inventory{ 1156 Packages: []*spb.Package{purlNixPackageProto}, 1157 GenericFindings: []*spb.GenericFinding{}, 1158 }, 1159 }, 1160 excludeForOS: []string{"windows", "darwin"}, 1161 }, 1162 { 1163 desc: "Successful_Homebrew_scan_darwin-only", 1164 res: &scalibr.ScanResult{ 1165 Version: "1.0.0", 1166 StartTime: startTime, 1167 EndTime: endTime, 1168 Status: success, 1169 PluginStatus: []*plugin.Status{ 1170 { 1171 Name: "ext", 1172 Version: 2, 1173 Status: success, 1174 }, 1175 }, 1176 Inventory: inventory.Inventory{ 1177 Packages: []*extractor.Package{purlHomebrewPackage}, 1178 }, 1179 }, 1180 want: &spb.ScanResult{ 1181 Version: "1.0.0", 1182 StartTime: timestamppb.New(startTime), 1183 EndTime: timestamppb.New(endTime), 1184 Status: successProto, 1185 PluginStatus: []*spb.PluginStatus{ 1186 { 1187 Name: "ext", 1188 Version: 2, 1189 Status: successProto, 1190 }, 1191 }, 1192 Inventory: &spb.Inventory{ 1193 Packages: []*spb.Package{purlHomebrewPackageProto}, 1194 GenericFindings: []*spb.GenericFinding{}, 1195 }, 1196 }, 1197 excludeForOS: []string{"windows", "linux"}, 1198 }, 1199 { 1200 desc: "Successful_winget_scan_windows-only", 1201 res: &scalibr.ScanResult{ 1202 Version: "1.0.0", 1203 StartTime: startTime, 1204 EndTime: endTime, 1205 Status: success, 1206 PluginStatus: []*plugin.Status{ 1207 { 1208 Name: "ext", 1209 Version: 2, 1210 Status: success, 1211 }, 1212 }, 1213 Inventory: inventory.Inventory{ 1214 Packages: []*extractor.Package{purlWingetPackage}, 1215 }, 1216 }, 1217 want: &spb.ScanResult{ 1218 Version: "1.0.0", 1219 StartTime: timestamppb.New(startTime), 1220 EndTime: timestamppb.New(endTime), 1221 Status: successProto, 1222 PluginStatus: []*spb.PluginStatus{ 1223 { 1224 Name: "ext", 1225 Version: 2, 1226 Status: successProto, 1227 }, 1228 }, 1229 Inventory: &spb.Inventory{ 1230 Packages: []*spb.Package{purlWingetPackageProto}, 1231 GenericFindings: []*spb.GenericFinding{}, 1232 }, 1233 }, 1234 excludeForOS: []string{"darwin", "linux"}, 1235 }, 1236 { 1237 desc: "Successful_containerd_scan_linux-only", 1238 res: &scalibr.ScanResult{ 1239 Version: "1.0.0", 1240 StartTime: startTime, 1241 EndTime: endTime, 1242 Status: success, 1243 PluginStatus: []*plugin.Status{ 1244 { 1245 Name: "ext", 1246 Version: 2, 1247 Status: success, 1248 }, 1249 }, 1250 Inventory: inventory.Inventory{ 1251 Packages: []*extractor.Package{containerdPackage}, 1252 }, 1253 }, 1254 want: &spb.ScanResult{ 1255 Version: "1.0.0", 1256 StartTime: timestamppb.New(startTime), 1257 EndTime: timestamppb.New(endTime), 1258 Status: successProto, 1259 PluginStatus: []*spb.PluginStatus{ 1260 { 1261 Name: "ext", 1262 Version: 2, 1263 Status: successProto, 1264 }, 1265 }, 1266 Inventory: &spb.Inventory{ 1267 Packages: []*spb.Package{containerdPackageProto}, 1268 GenericFindings: []*spb.GenericFinding{}, 1269 }, 1270 }, 1271 // TODO(b/349138656): Remove windows from this exclusion when containerd is supported 1272 // on Windows. 1273 excludeForOS: []string{"windows", "darwin"}, 1274 }, 1275 { 1276 desc: "Successful_containerd_runtime_scan_linux-only", 1277 res: &scalibr.ScanResult{ 1278 Version: "1.0.0", 1279 StartTime: startTime, 1280 EndTime: endTime, 1281 Status: success, 1282 PluginStatus: []*plugin.Status{ 1283 { 1284 Name: "ext", 1285 Version: 2, 1286 Status: success, 1287 }, 1288 }, 1289 Inventory: inventory.Inventory{ 1290 Packages: []*extractor.Package{containerdRuntimePackage}, 1291 }, 1292 }, 1293 want: &spb.ScanResult{ 1294 Version: "1.0.0", 1295 StartTime: timestamppb.New(startTime), 1296 EndTime: timestamppb.New(endTime), 1297 Status: successProto, 1298 PluginStatus: []*spb.PluginStatus{ 1299 { 1300 Name: "ext", 1301 Version: 2, 1302 Status: successProto, 1303 }, 1304 }, 1305 Inventory: &spb.Inventory{ 1306 Packages: []*spb.Package{containerdRuntimePackageProto}, 1307 GenericFindings: []*spb.GenericFinding{}, 1308 }, 1309 }, 1310 // TODO(b/349138656): Remove windows from this exclusion when containerd is supported 1311 // on Windows. 1312 excludeForOS: []string{"windows", "darwin"}, 1313 }, 1314 { 1315 desc: "Successful_docker_scan", 1316 res: &scalibr.ScanResult{ 1317 Version: "1.0.0", 1318 StartTime: startTime, 1319 EndTime: endTime, 1320 Status: success, 1321 PluginStatus: []*plugin.Status{ 1322 { 1323 Name: "ext", 1324 Version: 2, 1325 Status: success, 1326 }, 1327 }, 1328 Inventory: inventory.Inventory{ 1329 Packages: []*extractor.Package{dockerPackage}, 1330 }, 1331 }, 1332 want: &spb.ScanResult{ 1333 Version: "1.0.0", 1334 StartTime: timestamppb.New(startTime), 1335 EndTime: timestamppb.New(endTime), 1336 Status: successProto, 1337 PluginStatus: []*spb.PluginStatus{ 1338 { 1339 Name: "ext", 1340 Version: 2, 1341 Status: successProto, 1342 }, 1343 }, 1344 Inventory: &spb.Inventory{ 1345 Packages: []*spb.Package{dockerPackageProto}, 1346 GenericFindings: []*spb.GenericFinding{}, 1347 }, 1348 }, 1349 }, 1350 { 1351 desc: "Successful_podman_runtime_scan_linux-only", 1352 res: &scalibr.ScanResult{ 1353 Version: "1.0.0", 1354 StartTime: startTime, 1355 EndTime: endTime, 1356 Status: success, 1357 PluginStatus: []*plugin.Status{ 1358 { 1359 Name: "ext", 1360 Version: 2, 1361 Status: success, 1362 }, 1363 }, 1364 Inventory: inventory.Inventory{ 1365 Packages: []*extractor.Package{podmanPackage}, 1366 }, 1367 }, 1368 want: &spb.ScanResult{ 1369 Version: "1.0.0", 1370 StartTime: timestamppb.New(startTime), 1371 EndTime: timestamppb.New(endTime), 1372 Status: successProto, 1373 PluginStatus: []*spb.PluginStatus{ 1374 { 1375 Name: "ext", 1376 Version: 2, 1377 Status: successProto, 1378 }, 1379 }, 1380 Inventory: &spb.Inventory{ 1381 Packages: []*spb.Package{podmanPackageProto}, 1382 GenericFindings: []*spb.GenericFinding{}, 1383 }, 1384 }, 1385 excludeForOS: []string{"windows", "darwin"}, 1386 }, 1387 { 1388 desc: "advisory_without_id,_should_error", 1389 res: &scalibr.ScanResult{ 1390 Version: "1.0.0", 1391 StartTime: startTime, 1392 EndTime: endTime, 1393 Status: success, 1394 PluginStatus: []*plugin.Status{ 1395 { 1396 Name: "ext", 1397 Version: 2, 1398 Status: success, 1399 }, 1400 { 1401 Name: "det", 1402 Version: 3, 1403 Status: success, 1404 }, 1405 }, 1406 Inventory: inventory.Inventory{ 1407 Packages: []*extractor.Package{purlDPKGPackage, purlPythonPackage, purlJavascriptPackage, cdxPackage}, 1408 GenericFindings: []*inventory.GenericFinding{ 1409 { 1410 Adv: &inventory.GenericFindingAdvisory{ 1411 Title: "Title", 1412 Description: "Description", 1413 Recommendation: "Recommendation", 1414 Sev: inventory.SeverityMedium, 1415 }, 1416 Target: &inventory.GenericFindingTargetDetails{ 1417 Extra: "extra details", 1418 }, 1419 }, 1420 }, 1421 }, 1422 }, 1423 wantErr: proto.ErrAdvisoryIDMissing, 1424 }, 1425 { 1426 desc: "no_advisory,_should_error", 1427 res: &scalibr.ScanResult{ 1428 Version: "1.0.0", 1429 StartTime: startTime, 1430 EndTime: endTime, 1431 Status: success, 1432 PluginStatus: []*plugin.Status{ 1433 { 1434 Name: "ext", 1435 Version: 2, 1436 Status: success, 1437 }, 1438 { 1439 Name: "det", 1440 Version: 3, 1441 Status: success, 1442 }, 1443 }, 1444 Inventory: inventory.Inventory{ 1445 Packages: []*extractor.Package{purlDPKGPackage, purlPythonPackage, purlJavascriptPackage, cdxPackage}, 1446 GenericFindings: []*inventory.GenericFinding{ 1447 { 1448 Target: &inventory.GenericFindingTargetDetails{ 1449 Extra: "extra details", 1450 }, 1451 }, 1452 }, 1453 }, 1454 }, 1455 wantErr: proto.ErrAdvisoryMissing, 1456 }, 1457 { 1458 desc: "Failed_scan", 1459 res: &scalibr.ScanResult{ 1460 Version: "1.0.0", 1461 StartTime: startTime, 1462 EndTime: endTime, 1463 Status: failure, 1464 PluginStatus: []*plugin.Status{ 1465 { 1466 Name: "ext", 1467 Version: 2, 1468 Status: failure, 1469 }, 1470 { 1471 Name: "det", 1472 Version: 3, 1473 Status: failure, 1474 }, 1475 }, 1476 }, 1477 want: &spb.ScanResult{ 1478 Version: "1.0.0", 1479 StartTime: timestamppb.New(startTime), 1480 EndTime: timestamppb.New(endTime), 1481 Status: failureProto, 1482 Inventory: &spb.Inventory{}, 1483 PluginStatus: []*spb.PluginStatus{ 1484 { 1485 Name: "ext", 1486 Version: 2, 1487 Status: failureProto, 1488 }, 1489 { 1490 Name: "det", 1491 Version: 3, 1492 Status: failureProto, 1493 }, 1494 }, 1495 }, 1496 }, 1497 { 1498 desc: "pom.xml_inventories_with_transitive_dependencies", 1499 res: &scalibr.ScanResult{ 1500 Version: "1.0.0", 1501 StartTime: startTime, 1502 EndTime: endTime, 1503 Status: success, 1504 Inventory: inventory.Inventory{ 1505 Packages: []*extractor.Package{mavenPackage}, 1506 }, 1507 }, 1508 want: &spb.ScanResult{ 1509 Version: "1.0.0", 1510 StartTime: timestamppb.New(startTime), 1511 EndTime: timestamppb.New(endTime), 1512 Status: successProto, 1513 Inventory: &spb.Inventory{ 1514 Packages: []*spb.Package{mavenPackageProto}, 1515 GenericFindings: []*spb.GenericFinding{}, 1516 }, 1517 }, 1518 }, 1519 { 1520 desc: "secret_containing_a_GCP_service_account_key", 1521 res: &scalibr.ScanResult{ 1522 Version: "1.0.0", 1523 StartTime: startTime, 1524 EndTime: endTime, 1525 Status: success, 1526 Inventory: inventory.Inventory{ 1527 Secrets: []*inventory.Secret{gcpsakSecret}, 1528 }, 1529 }, 1530 want: &spb.ScanResult{ 1531 Version: "1.0.0", 1532 StartTime: timestamppb.New(startTime), 1533 EndTime: timestamppb.New(endTime), 1534 Status: successProto, 1535 Inventory: &spb.Inventory{ 1536 Secrets: []*spb.Secret{gcpsakSecretProto}, 1537 }, 1538 }, 1539 }, 1540 { 1541 desc: "secret_containing_a_GCP_service_account_key_with_extra_information", 1542 res: &scalibr.ScanResult{ 1543 Version: "1.0.0", 1544 StartTime: startTime, 1545 EndTime: endTime, 1546 Status: success, 1547 Inventory: inventory.Inventory{ 1548 Secrets: []*inventory.Secret{gcpsakSecretWithExtra}, 1549 }, 1550 }, 1551 want: &spb.ScanResult{ 1552 Version: "1.0.0", 1553 StartTime: timestamppb.New(startTime), 1554 EndTime: timestamppb.New(endTime), 1555 Status: successProto, 1556 Inventory: &spb.Inventory{ 1557 Secrets: []*spb.Secret{gcpsakSecretProtoWithExtra}, 1558 }, 1559 }, 1560 }, 1561 { 1562 desc: "package_containing_license_data", 1563 res: &scalibr.ScanResult{ 1564 Version: "1.0.0", 1565 StartTime: startTime, 1566 EndTime: endTime, 1567 Status: success, 1568 Inventory: inventory.Inventory{ 1569 Packages: []*extractor.Package{licensePackage}, 1570 }, 1571 }, 1572 want: &spb.ScanResult{ 1573 Version: "1.0.0", 1574 StartTime: timestamppb.New(startTime), 1575 EndTime: timestamppb.New(endTime), 1576 Status: successProto, 1577 Inventory: &spb.Inventory{ 1578 Packages: []*spb.Package{licensePackageProto}, 1579 }, 1580 }, 1581 }, 1582 } 1583 1584 for _, tc := range testCases { 1585 t.Run(tc.desc, func(t *testing.T) { 1586 if slices.Contains(tc.excludeForOS, runtime.GOOS) { 1587 t.Skipf("Skipping test %q on %s", tc.desc, runtime.GOOS) 1588 } 1589 1590 got, err := proto.ScanResultToProto(tc.res) 1591 if !errors.Is(err, tc.wantErr) { 1592 t.Fatalf("proto.ScanResultToProto(%v) err: got %v, want %v", tc.res, err, tc.wantErr) 1593 } 1594 1595 opts := append([]cmp.Option{ 1596 protocmp.Transform(), 1597 cmpopts.EquateEmpty(), 1598 }, pkgOpts...) 1599 1600 if diff := cmp.Diff(tc.want, got, opts...); diff != "" { 1601 t.Errorf("proto.ScanResultToProto(%v) returned unexpected diff (-want +got):\n%s", tc.res, diff) 1602 } 1603 1604 if err != nil { 1605 return 1606 } 1607 1608 gotStruct, err := proto.ScanResultFromProto(tc.want) 1609 if !errors.Is(err, tc.wantErr) { 1610 t.Fatalf("proto.ScanResultToProto(%v) err: got %v, want %v", tc.res, err, tc.wantErr) 1611 } 1612 if diff := cmp.Diff(tc.res, gotStruct, opts...); diff != "" { 1613 t.Errorf("proto.ScanResultToProto(%v) returned unexpected diff (-want +got):\n%s", tc.res, diff) 1614 } 1615 1616 // TODO - b/421456154: test conversion of remaining types. 1617 invProto := protobuf.Clone(got.GetInventory()).(*spb.Inventory) 1618 invProto.GenericFindings = nil 1619 invProto.Secrets = nil 1620 1621 tc.res.Inventory.GenericFindings = nil 1622 tc.res.Inventory.Secrets = nil 1623 1624 opts = []cmp.Option{ 1625 cmpopts.IgnoreFields(extractor.LayerMetadata{}, "ParentContainer"), 1626 cmpopts.EquateEmpty(), 1627 } 1628 1629 gotInv := proto.InventoryToStruct(invProto) 1630 if diff := cmp.Diff(tc.res.Inventory, *gotInv, opts...); diff != "" { 1631 t.Errorf("proto.InventoryToStruct(%v) returned unexpected diff (-want +got):\n%s", invProto, diff) 1632 } 1633 }) 1634 } 1635 }