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