github.com/google/osv-scalibr@v0.4.1/detector/cis/generic_linux/etcpasswdpermissions/etcpasswdpermissions_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 etcpasswdpermissions_test 16 17 import ( 18 "io/fs" 19 "runtime" 20 "slices" 21 "testing" 22 23 "github.com/google/go-cmp/cmp" 24 "github.com/google/go-cmp/cmp/cmpopts" 25 "github.com/google/osv-scalibr/detector/cis/generic_linux/etcpasswdpermissions" 26 "github.com/google/osv-scalibr/extractor" 27 scalibrfs "github.com/google/osv-scalibr/fs" 28 "github.com/google/osv-scalibr/inventory" 29 "github.com/google/osv-scalibr/packageindex" 30 ) 31 32 // A fake implementation of fs.FS where the only file is /etc/passwd and it has configurable permissions. 33 type fakeFS struct { 34 exists bool 35 perms fs.FileMode 36 uid uint32 37 gid uint32 38 } 39 40 func TestScan(t *testing.T) { 41 if !slices.Contains([]string{"linux"}, runtime.GOOS) { 42 t.Skipf("Skipping test for unsupported OS %q", runtime.GOOS) 43 } 44 45 wantTitle := "Ensure permissions on /etc/passwd are configured" 46 wantDesc := "The /etc/passwd file contains user account information that " + 47 "is used by many system utilities and therefore must be readable for these " + 48 "utilities to operate." 49 wantRec := "Run the following command to set permissions on /etc/passwd :\n" + 50 "# chown root:root /etc/passwd\n" + 51 "# chmod 644 /etc/passwd" 52 wantAdv := &inventory.GenericFindingAdvisory{ 53 ID: &inventory.AdvisoryID{ 54 Publisher: "CIS", 55 Reference: "etc-passwd-permissions", 56 }, 57 Title: wantTitle, 58 Description: wantDesc, 59 Recommendation: wantRec, 60 Sev: inventory.SeverityMinimal, 61 } 62 63 px, _ := packageindex.New([]*extractor.Package{}) 64 testCases := []struct { 65 desc string 66 fsys scalibrfs.FS 67 wantFindings []*inventory.GenericFinding 68 wantErr error 69 }{ 70 { 71 desc: "File doesn't exist", 72 fsys: &fakeFS{exists: false}, 73 wantFindings: nil, 74 }, 75 { 76 desc: "Permissions correct", 77 fsys: &fakeFS{exists: true, perms: 0644, uid: 0, gid: 0}, 78 wantFindings: nil, 79 }, 80 { 81 desc: "Permissions_incorrect", 82 fsys: &fakeFS{exists: true, perms: 0777, uid: 0, gid: 0}, 83 wantFindings: []*inventory.GenericFinding{{ 84 Adv: wantAdv, 85 Target: &inventory.GenericFindingTargetDetails{ 86 Extra: "/etc/passwd: file permissions 777, expected 644\n", 87 }, 88 }}, 89 }, 90 { 91 desc: "Permissions_and_uid_incorrect", 92 fsys: &fakeFS{exists: true, perms: 0777, uid: 10, gid: 0}, 93 wantFindings: []*inventory.GenericFinding{{ 94 Adv: wantAdv, 95 Target: &inventory.GenericFindingTargetDetails{ 96 Extra: "/etc/passwd: file permissions 777, expected 644\nfile owner 10, expected 0/root\n", 97 }, 98 }}, 99 }, 100 { 101 desc: "Permissions_and_gid_incorrect", 102 fsys: &fakeFS{exists: true, perms: 0777, uid: 0, gid: 10}, 103 wantFindings: []*inventory.GenericFinding{{ 104 Adv: wantAdv, 105 Target: &inventory.GenericFindingTargetDetails{ 106 Extra: "/etc/passwd: file permissions 777, expected 644\nfile group 10, expected 0/root\n", 107 }, 108 }}, 109 }, 110 } 111 112 for _, tc := range testCases { 113 t.Run(tc.desc, func(t *testing.T) { 114 det := etcpasswdpermissions.Detector{} 115 got, err := det.Scan(t.Context(), &scalibrfs.ScanRoot{FS: tc.fsys}, px) 116 findings := got.GenericFindings 117 if diff := cmp.Diff(tc.wantErr, err, cmpopts.EquateErrors()); diff != "" { 118 t.Errorf("detector.Scan(%v): unexpected error (-want +got):\n%s", tc.fsys, diff) 119 } 120 if diff := cmp.Diff(tc.wantFindings, findings); diff != "" { 121 t.Errorf("detector.Scan(%v): unexpected findings (-want +got):\n%s", tc.fsys, diff) 122 } 123 }) 124 } 125 }