Skip to content

Commit

Permalink
pam/integration-tests: Add TestNativeChangeAuthTok tests
Browse files Browse the repository at this point in the history
Repeat the tests we have for the CLI interface in the PAM native
interface too
  • Loading branch information
3v1n0 committed Jun 20, 2024
1 parent f592729 commit ef5b47e
Show file tree
Hide file tree
Showing 19 changed files with 3,971 additions and 0 deletions.
91 changes: 91 additions & 0 deletions pam/integration-tests/native_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,94 @@ func TestNativeAuthenticate(t *testing.T) {
})
}
}

func TestNativeChangeAuthTok(t *testing.T) {
t.Parallel()

outDir := t.TempDir()
cliEnv := prepareClientTest(t, outDir)

// we don't care about the output of gpasswd for this test, but we still need to mock it.
err := os.MkdirAll(filepath.Join(outDir, "gpasswd"), 0700)
require.NoError(t, err, "Setup: Could not create gpasswd output directory")
gpasswdOutput := filepath.Join(outDir, "gpasswd", "chauthtok.output")
groupsFile := filepath.Join(testutils.TestFamilyPath(t), "gpasswd.group")

const socketPathEnv = "AUTHD_TESTS_CLI_AUTHTOK_TESTS_SOCK"
defaultSocketPath := runAuthd(t, gpasswdOutput, groupsFile, true)

// If vhs is installed with "go install", we need to add GOPATH to PATH.
pathEnv := prependBinToPath(t)

currentDir, err := os.Getwd()
require.NoError(t, err, "Setup: Could not get current directory for the tests")

tests := map[string]struct {
tape string

currentUserNotRoot bool
}{
"Change password successfully and authenticate with new one": {tape: "passwd_simple"},
"Change passwd after MFA auth": {tape: "passwd_mfa"},

"Retry if new password is rejected by broker": {tape: "passwd_rejected"},
"Retry if password confirmation is not the same": {tape: "passwd_not_confirmed"},

"Prevent change password if auth fails": {tape: "passwd_auth_fail"},
"Prevent change password if current user is not root as can't authenticate": {tape: "passwd_not_root", currentUserNotRoot: true},
"Prevent change password if user do not exist": {tape: "passwd_unexistent_user"},

"Exit authd if local broker is selected": {tape: "passwd_local_broker"},
// FIXME: While this works now, it requires proper handling via signal_fd
"Exit authd if user sigints": {tape: "passwd_sigint"},
}
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
t.Parallel()

socketPath := defaultSocketPath
if tc.currentUserNotRoot {
socketPath = runAuthd(t, gpasswdOutput, groupsFile, false)
}

cliLog := prepareCLILogging(t)
t.Cleanup(func() {
saveArtifactsForDebug(t, []string{
filepath.Join(outDir, tc.tape+".gif"),
filepath.Join(outDir, tc.tape+".txt"),
cliLog,
})
})

// #nosec:G204 - we control the command arguments in tests
cmd := exec.Command("env", "vhs", filepath.Join(currentDir, "testdata", "native-tapes", tc.tape+".tape"))
cmd.Env = append(testutils.AppendCovEnv(cmd.Env), cliEnv...)
cmd.Env = append(cmd.Env, pathEnv,
fmt.Sprintf("%s=%s", socketPathEnv, socketPath),
fmt.Sprintf("AUTHD_PAM_CLI_LOG_DIR=%s", filepath.Dir(cliLog)),
fmt.Sprintf("AUTHD_PAM_CLI_TEST_NAME=%s", t.Name()),
"AUTHD_PAM_CLI_SUPPORTS_CONVERSATION=1",
)
cmd.Dir = outDir

out, err := cmd.CombinedOutput()
require.NoError(t, err, "Failed to run tape %q: %v: %s", tc.tape, err, out)

tmp, err := os.ReadFile(filepath.Join(outDir, tc.tape+".txt"))
require.NoError(t, err, "Could not read output file of tape %q", tc.tape)

// We need to format the output a little bit, since the txt file can have some noise at the beginning.
got := string(tmp)
splitTmp := strings.Split(got, "\n")
for i, str := range splitTmp {
if strings.Contains(str, " ./pam_authd passwd socket=$") {
got = strings.Join(splitTmp[i:], "\n")
break
}
}
got = permissionstestutils.IdempotentPermissionError(got)
want := testutils.LoadWithUpdateFromGolden(t, got)
require.Equal(t, want, got, "Output of tape %q does not match golden file", tc.tape)
})
}
}
Loading

0 comments on commit ef5b47e

Please sign in to comment.