github.com/anchore/syft@v1.38.2/syft/linux/identify_release_test.go (about) 1 package linux 2 3 import ( 4 "io" 5 "os" 6 "testing" 7 8 "github.com/stretchr/testify/assert" 9 "github.com/stretchr/testify/require" 10 11 "github.com/anchore/syft/syft/source" 12 "github.com/anchore/syft/syft/source/directorysource" 13 ) 14 15 func TestIdentifyRelease(t *testing.T) { 16 tests := []struct { 17 fixture string 18 release *Release 19 }{ 20 { 21 fixture: "test-fixtures/os/alpine", 22 release: &Release{ 23 PrettyName: "Alpine Linux v3.11", 24 Name: "Alpine Linux", 25 ID: "alpine", 26 IDLike: nil, 27 VersionID: "3.11.6", 28 HomeURL: "https://alpinelinux.org/", 29 BugReportURL: "https://bugs.alpinelinux.org/", 30 }, 31 }, 32 { 33 fixture: "test-fixtures/os/amazon", 34 release: &Release{ 35 PrettyName: "Amazon Linux 2", 36 Name: "Amazon Linux", 37 ID: "amzn", 38 IDLike: []string{ 39 "centos", 40 "rhel", 41 "fedora", 42 }, 43 Version: "2", 44 VersionID: "2", 45 HomeURL: "https://amazonlinux.com/", 46 CPEName: "cpe:2.3:o:amazon:amazon_linux:2", 47 }, 48 }, 49 { 50 fixture: "test-fixtures/os/busybox", 51 release: &Release{ 52 PrettyName: "BusyBox v1.31.1", 53 Name: "busybox", 54 ID: "busybox", 55 IDLike: []string{"busybox"}, 56 Version: "1.31.1", 57 VersionID: "1.31.1", 58 }, 59 }, 60 { 61 fixture: "test-fixtures/os/centos", 62 release: &Release{ 63 PrettyName: "CentOS Linux 8 (Core)", 64 Name: "CentOS Linux", 65 ID: "centos", 66 IDLike: []string{"rhel", 67 "fedora", 68 }, 69 Version: "8 (Core)", 70 VersionID: "8", 71 HomeURL: "https://www.centos.org/", 72 BugReportURL: "https://bugs.centos.org/", 73 CPEName: "cpe:/o:centos:centos:8", 74 }, 75 }, 76 { 77 fixture: "test-fixtures/os/debian", 78 release: &Release{ 79 PrettyName: "Debian GNU/Linux 8 (jessie)", 80 Name: "Debian GNU/Linux", 81 ID: "debian", 82 IDLike: nil, 83 Version: "8 (jessie)", 84 VersionID: "8", 85 HomeURL: "http://www.debian.org/", 86 SupportURL: "http://www.debian.org/support", 87 BugReportURL: "https://bugs.debian.org/", 88 }, 89 }, 90 { 91 fixture: "test-fixtures/os/fedora", 92 release: &Release{ 93 PrettyName: "Fedora Linux 36 (Container Image)", 94 Name: "Fedora Linux", 95 ID: "fedora", 96 IDLike: nil, 97 Version: "36 (Container Image)", 98 VersionID: "36", 99 Variant: "Container Image", 100 VariantID: "container", 101 HomeURL: "https://fedoraproject.org/", 102 SupportURL: "https://ask.fedoraproject.org/", 103 BugReportURL: "https://bugzilla.redhat.com/", 104 PrivacyPolicyURL: "https://fedoraproject.org/wiki/Legal:PrivacyPolicy", 105 CPEName: "cpe:/o:fedoraproject:fedora:36", 106 SupportEnd: "2023-05-16", 107 }, 108 }, 109 { 110 fixture: "test-fixtures/os/redhat/from-os-release", 111 release: &Release{ 112 PrettyName: "Red Hat Enterprise Linux Server 7.3 (Maipo)", 113 Name: "Red Hat Enterprise Linux Server", 114 ID: "rhel", 115 IDLike: []string{"fedora"}, 116 Version: "7.3 (Maipo)", 117 VersionID: "7.3", 118 HomeURL: "https://www.redhat.com/", 119 BugReportURL: "https://bugzilla.redhat.com/", 120 CPEName: "cpe:/o:redhat:enterprise_linux:7.3:GA:server", 121 }, 122 }, 123 { 124 fixture: "test-fixtures/os/redhat/from-redhat-release", 125 release: &Release{ 126 PrettyName: "Red Hat Enterprise Linux release 8.10 (Ootpa)", 127 Name: "Red Hat Enterprise Linux", 128 ID: "rhel", 129 IDLike: []string{"rhel"}, 130 Version: "8.10 (Ootpa)", 131 VersionID: "8.10", 132 }, 133 }, 134 { 135 fixture: "test-fixtures/os/ubuntu", 136 release: &Release{ 137 PrettyName: "Ubuntu 20.04 LTS", 138 Name: "Ubuntu", 139 ID: "ubuntu", 140 IDLike: []string{"debian"}, 141 Version: "20.04 LTS (Focal Fossa)", 142 VersionCodename: "focal", 143 VersionID: "20.04", 144 HomeURL: "https://www.ubuntu.com/", 145 SupportURL: "https://help.ubuntu.com/", 146 BugReportURL: "https://bugs.launchpad.net/ubuntu/", 147 PrivacyPolicyURL: "https://www.ubuntu.com/legal/terms-and-policies/privacy-policy", 148 }, 149 }, 150 { 151 fixture: "test-fixtures/os/oraclelinux", 152 release: &Release{ 153 PrettyName: "Oracle Linux Server 8.3", 154 Name: "Oracle Linux Server", 155 ID: "ol", 156 IDLike: []string{"fedora"}, 157 Version: "8.3", 158 VersionID: "8.3", 159 Variant: "Server", 160 VariantID: "server", 161 HomeURL: "https://linux.oracle.com/", 162 BugReportURL: "https://bugzilla.oracle.com/", 163 CPEName: "cpe:/o:oracle:linux:8:3:server", 164 }, 165 }, 166 { 167 fixture: "test-fixtures/os/empty", 168 }, 169 { 170 fixture: "test-fixtures/os/custom", 171 release: &Release{ 172 PrettyName: "CentOS Linux 8 (Core)", 173 Name: "Scientific Linux", 174 ID: "scientific", 175 IDLike: []string{ 176 "rhel", 177 "fedora", 178 }, 179 Version: "16 (Core)", 180 VersionID: "8", 181 HomeURL: "https://www.centos.org/", 182 BugReportURL: "https://bugs.centos.org/", 183 CPEName: "cpe:/o:centos:centos:8", 184 }, 185 }, 186 { 187 fixture: "test-fixtures/os/opensuse-leap", 188 release: &Release{ 189 PrettyName: "openSUSE Leap 15.2", 190 Name: "openSUSE Leap", 191 ID: "opensuse-leap", 192 IDLike: []string{ 193 "suse", 194 "opensuse", 195 }, 196 Version: "15.2", 197 VersionID: "15.2", 198 HomeURL: "https://www.opensuse.org/", 199 BugReportURL: "https://bugs.opensuse.org", 200 CPEName: "cpe:/o:opensuse:leap:15.2", 201 }, 202 }, 203 { 204 fixture: "test-fixtures/os/sles", 205 release: &Release{ 206 PrettyName: "SUSE Linux Enterprise Server 15 SP2", 207 Name: "SLES", 208 ID: "sles", 209 IDLike: []string{"suse"}, 210 Version: "15-SP2", 211 VersionID: "15.2", 212 CPEName: "cpe:/o:suse:sles:15:sp2", 213 }, 214 }, 215 { 216 fixture: "test-fixtures/os/photon", 217 release: &Release{ 218 PrettyName: "VMware Photon OS/Linux", 219 Name: "VMware Photon OS", 220 ID: "photon", 221 IDLike: nil, 222 Version: "2.0", 223 VersionID: "2.0", 224 HomeURL: "https://vmware.github.io/photon/", 225 BugReportURL: "https://github.com/vmware/photon/issues", 226 }, 227 }, 228 { 229 fixture: "test-fixtures/os/arch", 230 release: &Release{ 231 PrettyName: "Arch Linux", 232 Name: "Arch Linux", 233 ID: "arch", 234 IDLike: nil, 235 BuildID: "rolling", 236 HomeURL: "https://www.archlinux.org/", 237 SupportURL: "https://bbs.archlinux.org/", 238 BugReportURL: "https://bugs.archlinux.org/", 239 }, 240 }, 241 { 242 fixture: "test-fixtures/partial-fields/missing-id", 243 release: &Release{ 244 Name: "Debian GNU/Linux", 245 IDLike: []string{"debian"}, 246 VersionID: "8", 247 }, 248 }, 249 { 250 fixture: "test-fixtures/partial-fields/unknown-id", 251 release: &Release{ 252 Name: "Debian GNU/Linux", 253 ID: "my-awesome-distro", 254 IDLike: []string{"debian"}, 255 VersionID: "8", 256 }, 257 }, 258 { 259 fixture: "test-fixtures/partial-fields/missing-version", 260 release: &Release{ 261 Name: "Debian GNU/Linux", 262 IDLike: []string{"debian"}, 263 }, 264 }, 265 { 266 fixture: "test-fixtures/os/centos6", 267 release: &Release{ 268 PrettyName: "centos", 269 Name: "centos", 270 ID: "centos", 271 IDLike: []string{"centos"}, 272 Version: "6", 273 VersionID: "6", 274 CPEName: "cpe:/o:centos:linux:6:GA", 275 }, 276 }, 277 { 278 fixture: "test-fixtures/os/centos5", 279 release: &Release{ 280 PrettyName: "CentOS release 5.7 (Final)", 281 Name: "CentOS", 282 ID: "centos", 283 IDLike: []string{"centos"}, 284 Version: "5.7", 285 VersionID: "5.7", 286 }, 287 }, 288 { 289 fixture: "test-fixtures/os/mariner", 290 release: &Release{ 291 PrettyName: "CBL-Mariner/Linux", 292 Name: "Common Base Linux Mariner", 293 ID: "mariner", 294 IDLike: nil, 295 Version: "1.0.20210901", 296 VersionID: "1.0", 297 HomeURL: "https://aka.ms/cbl-mariner", 298 SupportURL: "https://aka.ms/cbl-mariner", 299 BugReportURL: "https://aka.ms/cbl-mariner", 300 }, 301 }, 302 { 303 fixture: "test-fixtures/os/rockylinux", 304 release: &Release{ 305 PrettyName: "Rocky Linux 8.4 (Green Obsidian)", 306 Name: "Rocky Linux", 307 ID: "rocky", 308 IDLike: []string{ 309 "rhel", 310 "fedora", 311 }, 312 Version: "8.4 (Green Obsidian)", 313 VersionID: "8.4", 314 HomeURL: "https://rockylinux.org/", 315 BugReportURL: "https://bugs.rockylinux.org/", 316 CPEName: "cpe:/o:rocky:rocky:8.4:GA", 317 }, 318 }, 319 { 320 fixture: "test-fixtures/os/almalinux", 321 release: &Release{ 322 PrettyName: "AlmaLinux 8.4 (Electric Cheetah)", 323 Name: "AlmaLinux", 324 ID: "almalinux", 325 IDLike: []string{ 326 "rhel", 327 "centos", 328 "fedora", 329 }, 330 Version: "8.4 (Electric Cheetah)", 331 VersionID: "8.4", 332 HomeURL: "https://almalinux.org/", 333 BugReportURL: "https://bugs.almalinux.org/", 334 CPEName: "cpe:/o:almalinux:almalinux:8.4:GA", 335 }, 336 }, 337 { 338 fixture: "test-fixtures/os/wolfi", 339 release: &Release{ 340 PrettyName: "Wolfi", 341 Name: "Wolfi", 342 ID: "wolfi", 343 VersionID: "20220914", 344 HomeURL: "https://wolfi.dev", 345 }, 346 }, 347 } 348 349 for _, test := range tests { 350 t.Run(test.fixture, func(t *testing.T) { 351 s, err := directorysource.New(directorysource.Config{ 352 Path: test.fixture, 353 }) 354 require.NoError(t, err) 355 356 resolver, err := s.FileResolver(source.SquashedScope) 357 require.NoError(t, err) 358 359 assert.Equal(t, test.release, IdentifyRelease(resolver)) 360 }) 361 } 362 } 363 364 func TestParseOsRelease(t *testing.T) { 365 366 tests := []struct { 367 fixture string 368 release *Release 369 }{ 370 { 371 fixture: "test-fixtures/ubuntu-20.04", 372 373 release: &Release{ 374 PrettyName: "Ubuntu 20.04 LTS", 375 Name: "Ubuntu", 376 ID: "ubuntu", 377 IDLike: []string{"debian"}, 378 Version: "20.04 LTS (Focal Fossa)", 379 VersionID: "20.04", 380 VersionCodename: "focal", 381 HomeURL: "https://www.ubuntu.com/", 382 SupportURL: "https://help.ubuntu.com/", 383 BugReportURL: "https://bugs.launchpad.net/ubuntu/", 384 PrivacyPolicyURL: "https://www.ubuntu.com/legal/terms-and-policies/privacy-policy", 385 }, 386 }, 387 388 { 389 fixture: "test-fixtures/debian-8", 390 391 release: &Release{ 392 PrettyName: "Debian GNU/Linux 8 (jessie)", 393 Name: "Debian GNU/Linux", 394 ID: "debian", 395 IDLike: nil, 396 Version: "8 (jessie)", 397 VersionID: "8", 398 HomeURL: "http://www.debian.org/", 399 SupportURL: "http://www.debian.org/support", 400 BugReportURL: "https://bugs.debian.org/", 401 }, 402 }, 403 404 { 405 fixture: "test-fixtures/centos-8", 406 407 release: &Release{ 408 PrettyName: "CentOS Linux 8 (Core)", 409 Name: "CentOS Linux", 410 ID: "centos", 411 IDLike: []string{ 412 "rhel", 413 "fedora", 414 }, 415 Version: "8 (Core)", 416 VersionID: "8", 417 HomeURL: "https://www.centos.org/", 418 BugReportURL: "https://bugs.centos.org/", 419 CPEName: "cpe:/o:centos:centos:8", 420 }, 421 }, 422 423 { 424 fixture: "test-fixtures/rhel-8", 425 426 release: &Release{ 427 PrettyName: "Red Hat Enterprise Linux 8.1 (Ootpa)", 428 Name: "Red Hat Enterprise Linux", 429 ID: "rhel", 430 IDLike: []string{"fedora"}, 431 Version: "8.1 (Ootpa)", 432 VersionID: "8.1", 433 HomeURL: "https://www.redhat.com/", 434 BugReportURL: "https://bugzilla.redhat.com/", 435 CPEName: "cpe:/o:redhat:enterprise_linux:8.1:GA", 436 }, 437 }, 438 439 { 440 fixture: "test-fixtures/unprintable", 441 442 release: &Release{ 443 PrettyName: "Debian GNU/Linux 8 (jessie)", 444 Name: "Debian GNU/Linux", 445 ID: "debian", 446 IDLike: nil, 447 Version: "8 (jessie)", 448 VersionID: "8", 449 HomeURL: "http://www.debian.org/", 450 SupportURL: "http://www.debian.org/support", 451 BugReportURL: "https://bugs.debian.org/", 452 }, 453 }, 454 } 455 456 for _, test := range tests { 457 t.Run(test.fixture, 458 func(t *testing.T) { 459 release, 460 err := parseOsRelease(retrieveFixtureContentsAsString(test.fixture, 461 t)) 462 require.NoError(t, 463 err) 464 assert.Equal(t, 465 test.release, 466 release) 467 }) 468 } 469 470 } 471 472 func TestParseSystemReleaseCPE(t *testing.T) { 473 tests := []struct { 474 fixture string 475 release *Release 476 }{ 477 { 478 fixture: "test-fixtures/os/centos6/etc/system-release-cpe", 479 release: &Release{ 480 PrettyName: "centos", 481 Name: "centos", 482 ID: "centos", 483 IDLike: []string{"centos"}, 484 Version: "6", 485 VersionID: "6", 486 CPEName: "cpe:/o:centos:linux:6:GA", 487 }, 488 }, 489 { 490 fixture: "test-fixtures/bad-system-release-cpe", 491 release: nil, 492 }, 493 } 494 495 for _, test := range tests { 496 t.Run(test.fixture, func(t *testing.T) { 497 contents := retrieveFixtureContentsAsString(test.fixture, t) 498 release, err := parseSystemReleaseCPE(contents) 499 require.NoError(t, err) 500 if test.release == nil { 501 assert.Nil(t, release) 502 return 503 } 504 505 assert.Equal(t, test.release, release) 506 }) 507 } 508 } 509 510 func TestParseRedhatRelease(t *testing.T) { 511 tests := []struct { 512 fixture string 513 name string 514 release *Release 515 }{ 516 { 517 fixture: "test-fixtures/os/centos5/etc/redhat-release", 518 name: "Centos 5", 519 release: &Release{ 520 PrettyName: "CentOS release 5.7 (Final)", 521 Name: "CentOS", 522 ID: "centos", 523 IDLike: []string{"centos"}, 524 Version: "5.7", 525 VersionID: "5.7", 526 }, 527 }, 528 { 529 fixture: "test-fixtures/bad-redhat-release", 530 name: "Centos 5 Bad Redhat Release", 531 release: nil, 532 }, 533 } 534 535 for _, test := range tests { 536 t.Run(test.name, func(t *testing.T) { 537 release, err := parseRedhatRelease(retrieveFixtureContentsAsString(test.fixture, t)) 538 require.NoError(t, err) 539 if test.release == nil { 540 assert.Nil(t, release) 541 return 542 } 543 544 assert.Equal(t, test.release, release) 545 }) 546 } 547 } 548 549 func retrieveFixtureContentsAsString(fixturePath string, t *testing.T) string { 550 fixture, err := os.Open(fixturePath) 551 if err != nil { 552 t.Fatalf("could not open test fixture=%s: %+v", fixturePath, err) 553 } 554 defer fixture.Close() 555 556 b, err := io.ReadAll(fixture) 557 if err != nil { 558 t.Fatalf("unable to read fixture file: %+v", err) 559 } 560 561 return string(b) 562 }