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  }