go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/providers/os/resources/pam/parser_test.go (about) 1 // Copyright (c) Mondoo, Inc. 2 // SPDX-License-Identifier: BUSL-1.1 3 4 package pam 5 6 import ( 7 "os" 8 "strings" 9 "testing" 10 11 "github.com/stretchr/testify/assert" 12 13 "github.com/stretchr/testify/require" 14 ) 15 16 func TestParseLine(t *testing.T) { 17 t.Run("parsing conf lines", func(t *testing.T) { 18 line := "account required pam_opendirectory.so" 19 expected := &PamLine{ 20 PamType: "account", 21 Control: "required", 22 Module: "pam_opendirectory.so", 23 Options: []interface{}{}, 24 } 25 result, err := ParseLine(line) 26 require.NoError(t, err) 27 require.Equal(t, expected, result) 28 }) 29 30 t.Run("parsing conf lines with options", func(t *testing.T) { 31 line := "account required pam_opendirectory.so no_warn group=admin,wheel" 32 expected := &PamLine{ 33 PamType: "account", 34 Control: "required", 35 Module: "pam_opendirectory.so", 36 Options: []interface{}{"no_warn", "group=admin,wheel"}, 37 } 38 result, err := ParseLine(line) 39 require.NoError(t, err) 40 require.Equal(t, expected, result) 41 }) 42 43 t.Run("parsing conf lines with complicated control", func(t *testing.T) { 44 line := "account [default=bad success=ok user_unknown=ignore] pam_sss.so" 45 expected := &PamLine{ 46 PamType: "account", 47 Control: "[default=bad success=ok user_unknown=ignore]", 48 Module: "pam_sss.so", 49 Options: []interface{}{}, 50 } 51 result, err := ParseLine(line) 52 require.NoError(t, err) 53 require.Equal(t, expected, result) 54 }) 55 56 t.Run("parsing conf lines with complicated control and options", func(t *testing.T) { 57 line := "account [default=bad success=ok user_unknown=ignore] pam_opendirectory.so no_warn group=admin,wheel" 58 expected := &PamLine{ 59 PamType: "account", 60 Control: "[default=bad success=ok user_unknown=ignore]", 61 Module: "pam_opendirectory.so", 62 Options: []interface{}{"no_warn", "group=admin,wheel"}, 63 } 64 result, err := ParseLine(line) 65 require.NoError(t, err) 66 require.Equal(t, expected, result) 67 }) 68 69 t.Run("parsing conf lines with complicated control and options", func(t *testing.T) { 70 line := "account [default=bad] pam_opendirectory.so no_warn group=admin,wheel" 71 expected := &PamLine{ 72 PamType: "account", 73 Control: "[default=bad]", 74 Module: "pam_opendirectory.so", 75 Options: []interface{}{"no_warn", "group=admin,wheel"}, 76 } 77 result, err := ParseLine(line) 78 require.NoError(t, err) 79 require.Equal(t, expected, result) 80 }) 81 82 t.Run("parsing conf line with include", func(t *testing.T) { 83 line := "@include common-password" 84 expected := &PamLine{ 85 PamType: "@include", 86 Control: "common-password", 87 Module: "", 88 Options: []interface{}{}, 89 } 90 result, err := ParseLine(line) 91 require.NoError(t, err) 92 require.Equal(t, expected, result) 93 }) 94 } 95 96 func parsePamContent(content string) ([]*PamLine, error) { 97 entries := []*PamLine{} 98 lines := strings.Split(content, "\n") 99 for i := range lines { 100 line := lines[i] 101 entry, err := ParseLine(line) 102 if err != nil { 103 return nil, err 104 } 105 entries = append(entries, entry) 106 } 107 return entries, nil 108 } 109 110 func TestSimplePamConfigurationFile(t *testing.T) { 111 data, err := os.ReadFile("./testdata/simple") 112 require.NoError(t, err) 113 content := string(data) 114 115 expected := []*PamLine{ 116 nil, 117 { 118 PamType: "auth", 119 Control: "required", 120 Module: "pam_securetty.so", 121 Options: []interface{}{}, 122 }, 123 { 124 PamType: "auth", 125 Control: "required", 126 Module: "pam_unix.so", 127 Options: []interface{}{ 128 "nullok", 129 }, 130 }, 131 { 132 PamType: "auth", 133 Control: "required", 134 Module: "pam_nologin.so", 135 Options: []interface{}{}, 136 }, 137 { 138 PamType: "account", 139 Control: "required", 140 Module: "pam_unix.so", 141 Options: []interface{}{}, 142 }, 143 { 144 PamType: "password", 145 Control: "required", 146 Module: "pam_cracklib.so", 147 Options: []interface{}{ 148 "retry=3", 149 }, 150 }, 151 { 152 PamType: "password", 153 Control: "required", 154 Module: "pam_unix.so", 155 Options: []interface{}{ 156 "shadow", 157 "nullok", 158 "use_authtok", 159 }, 160 }, 161 { 162 PamType: "session", 163 Control: "required", 164 Module: "pam_unix.so", 165 Options: []interface{}{}, 166 }, 167 } 168 entries, err := parsePamContent(content) 169 require.NoError(t, err) 170 assert.Equal(t, expected, entries) 171 } 172 173 func TestRebootPamConfigurationFile(t *testing.T) { 174 data, err := os.ReadFile("./testdata/reboot") 175 require.NoError(t, err) 176 content := string(data) 177 178 expected := []*PamLine{ 179 nil, 180 { 181 PamType: "auth", 182 Control: "sufficient", 183 Module: "pam_rootok.so", 184 Options: []interface{}{}, 185 }, 186 { 187 PamType: "auth", 188 Control: "required", 189 Module: "pam_console.so", 190 Options: []interface{}{}, 191 }, 192 nil, 193 { 194 PamType: "account", 195 Control: "required", 196 Module: "pam_permit.so", 197 Options: []interface{}{}, 198 }, 199 } 200 entries, err := parsePamContent(content) 201 require.NoError(t, err) 202 assert.Equal(t, expected, entries) 203 } 204 205 func TestCommonSessionNonInteractivePamConfigurationFile(t *testing.T) { 206 data, err := os.ReadFile("./testdata/common-session-noninteractive") 207 require.NoError(t, err) 208 content := string(data) 209 210 expected := []*PamLine{ 211 { 212 PamType: "session", 213 Control: "[default=1]", 214 Module: "pam_permit.so", 215 Options: []interface{}{}, 216 }, 217 { 218 PamType: "session", 219 Control: "requisite", 220 Module: "pam_deny.so", 221 Options: []interface{}{}, 222 }, 223 { 224 PamType: "session", 225 Control: "required", 226 Module: "pam_permit.so", 227 Options: []interface{}{}, 228 }, 229 { 230 PamType: "session", 231 Control: "optional", 232 Module: "pam_umask.so", 233 Options: []interface{}{}, 234 }, 235 { 236 PamType: "session", 237 Control: "required", 238 Module: "pam_unix.so", 239 Options: []interface{}{}, 240 }, 241 { 242 PamType: "session", 243 Control: "optional", 244 Module: "pam_ecryptfs.so", 245 Options: []interface{}{ 246 "unwrap", 247 }, 248 }, 249 } 250 entries, err := parsePamContent(content) 251 require.NoError(t, err) 252 assert.Equal(t, expected, entries) 253 } 254 255 func TestIncludePamConfigurationFile(t *testing.T) { 256 data, err := os.ReadFile("./testdata/atd") 257 require.NoError(t, err) 258 content := string(data) 259 260 expected := []*PamLine{ 261 { 262 PamType: "auth", 263 Control: "required", 264 Module: "pam_env.so", 265 Options: []interface{}{}, 266 }, 267 { 268 PamType: "@include", 269 Control: "common-auth", 270 Module: "", 271 Options: []interface{}{}, 272 }, 273 { 274 PamType: "@include", 275 Control: "common-account", 276 Module: "", 277 Options: []interface{}{}, 278 }, 279 { 280 PamType: "@include", 281 Control: "common-session-noninteractive", 282 Module: "", 283 Options: []interface{}{}, 284 }, 285 { 286 PamType: "session", 287 Control: "required", 288 Module: "pam_limits.so", 289 Options: []interface{}{}, 290 }, 291 } 292 entries, err := parsePamContent(content) 293 require.NoError(t, err) 294 assert.Equal(t, expected, entries) 295 }