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  }