|
@@ -2489,6 +2489,100 @@ func TestPreLoginUserCreation(t *testing.T) {
|
|
|
assert.NoError(t, err)
|
|
|
}
|
|
|
|
|
|
+func TestPreLoginHookPreserveMFAConfig(t *testing.T) {
|
|
|
+ if runtime.GOOS == osWindows {
|
|
|
+ t.Skip("this test is not available on Windows")
|
|
|
+ }
|
|
|
+ usePubKey := false
|
|
|
+ u := getTestUser(usePubKey)
|
|
|
+ err := dataprovider.Close()
|
|
|
+ assert.NoError(t, err)
|
|
|
+ err = config.LoadConfig(configDir, "")
|
|
|
+ assert.NoError(t, err)
|
|
|
+ providerConf := config.GetProviderConf()
|
|
|
+ err = os.WriteFile(preLoginPath, getPreLoginScriptContent(u, false), os.ModePerm)
|
|
|
+ assert.NoError(t, err)
|
|
|
+ providerConf.PreLoginHook = preLoginPath
|
|
|
+ err = dataprovider.Initialize(providerConf, configDir, true)
|
|
|
+ assert.NoError(t, err)
|
|
|
+
|
|
|
+ conn, client, err := getSftpClient(u, usePubKey)
|
|
|
+ if assert.NoError(t, err) {
|
|
|
+ defer conn.Close()
|
|
|
+ defer client.Close()
|
|
|
+ assert.NoError(t, checkBasicSFTP(client))
|
|
|
+ }
|
|
|
+ // add multi-factor authentication
|
|
|
+ user, _, err := httpdtest.GetUserByUsername(defaultUsername, http.StatusOK)
|
|
|
+ assert.NoError(t, err)
|
|
|
+ assert.Len(t, user.Filters.RecoveryCodes, 0)
|
|
|
+ assert.False(t, user.Filters.TOTPConfig.Enabled)
|
|
|
+ configName, _, secret, _, err := mfa.GenerateTOTPSecret(mfa.GetAvailableTOTPConfigNames()[0], user.Username)
|
|
|
+ assert.NoError(t, err)
|
|
|
+ user.Password = defaultPassword
|
|
|
+ user.Filters.TOTPConfig = sdk.TOTPConfig{
|
|
|
+ Enabled: true,
|
|
|
+ ConfigName: configName,
|
|
|
+ Secret: kms.NewPlainSecret(secret),
|
|
|
+ Protocols: []string{common.ProtocolSSH},
|
|
|
+ }
|
|
|
+ for i := 0; i < 12; i++ {
|
|
|
+ user.Filters.RecoveryCodes = append(user.Filters.RecoveryCodes, sdk.RecoveryCode{
|
|
|
+ Secret: kms.NewPlainSecret(fmt.Sprintf("RC-%v", strings.ToUpper(util.GenerateUniqueID()))),
|
|
|
+ })
|
|
|
+ }
|
|
|
+ err = dataprovider.UpdateUser(&user, "", "")
|
|
|
+ assert.NoError(t, err)
|
|
|
+
|
|
|
+ conn, client, err = getSftpClient(u, usePubKey)
|
|
|
+ if assert.NoError(t, err) {
|
|
|
+ defer conn.Close()
|
|
|
+ defer client.Close()
|
|
|
+ assert.NoError(t, checkBasicSFTP(client))
|
|
|
+ }
|
|
|
+
|
|
|
+ user, _, err = httpdtest.GetUserByUsername(defaultUsername, http.StatusOK)
|
|
|
+ assert.NoError(t, err)
|
|
|
+ assert.Len(t, user.Filters.RecoveryCodes, 12)
|
|
|
+ assert.True(t, user.Filters.TOTPConfig.Enabled)
|
|
|
+ assert.Equal(t, configName, user.Filters.TOTPConfig.ConfigName)
|
|
|
+ assert.Equal(t, []string{common.ProtocolSSH}, user.Filters.TOTPConfig.Protocols)
|
|
|
+ assert.Equal(t, kms.SecretStatusSecretBox, user.Filters.TOTPConfig.Secret.GetStatus())
|
|
|
+
|
|
|
+ err = os.WriteFile(extAuthPath, getExitCodeScriptContent(0), os.ModePerm)
|
|
|
+ assert.NoError(t, err)
|
|
|
+
|
|
|
+ conn, client, err = getSftpClient(u, usePubKey)
|
|
|
+ if assert.NoError(t, err) {
|
|
|
+ defer conn.Close()
|
|
|
+ defer client.Close()
|
|
|
+ assert.NoError(t, checkBasicSFTP(client))
|
|
|
+ }
|
|
|
+
|
|
|
+ user, _, err = httpdtest.GetUserByUsername(defaultUsername, http.StatusOK)
|
|
|
+ assert.NoError(t, err)
|
|
|
+ assert.Len(t, user.Filters.RecoveryCodes, 12)
|
|
|
+ assert.True(t, user.Filters.TOTPConfig.Enabled)
|
|
|
+ assert.Equal(t, configName, user.Filters.TOTPConfig.ConfigName)
|
|
|
+ assert.Equal(t, []string{common.ProtocolSSH}, user.Filters.TOTPConfig.Protocols)
|
|
|
+ assert.Equal(t, kms.SecretStatusSecretBox, user.Filters.TOTPConfig.Secret.GetStatus())
|
|
|
+
|
|
|
+ _, err = httpdtest.RemoveUser(user, http.StatusOK)
|
|
|
+ assert.NoError(t, err)
|
|
|
+ err = os.RemoveAll(user.GetHomeDir())
|
|
|
+ assert.NoError(t, err)
|
|
|
+
|
|
|
+ err = dataprovider.Close()
|
|
|
+ assert.NoError(t, err)
|
|
|
+ err = config.LoadConfig(configDir, "")
|
|
|
+ assert.NoError(t, err)
|
|
|
+ providerConf = config.GetProviderConf()
|
|
|
+ err = dataprovider.Initialize(providerConf, configDir, true)
|
|
|
+ assert.NoError(t, err)
|
|
|
+ err = os.Remove(preLoginPath)
|
|
|
+ assert.NoError(t, err)
|
|
|
+}
|
|
|
+
|
|
|
func TestPreDownloadHook(t *testing.T) {
|
|
|
if runtime.GOOS == osWindows {
|
|
|
t.Skip("this test is not available on Windows")
|
|
@@ -3336,6 +3430,101 @@ func TestLoginExternalAuthErrors(t *testing.T) {
|
|
|
assert.NoError(t, err)
|
|
|
}
|
|
|
|
|
|
+func TestExternalAuthPreserveMFAConfig(t *testing.T) {
|
|
|
+ if runtime.GOOS == osWindows {
|
|
|
+ t.Skip("this test is not available on Windows")
|
|
|
+ }
|
|
|
+ usePubKey := false
|
|
|
+ u := getTestUser(usePubKey)
|
|
|
+ err := dataprovider.Close()
|
|
|
+ assert.NoError(t, err)
|
|
|
+ err = config.LoadConfig(configDir, "")
|
|
|
+ assert.NoError(t, err)
|
|
|
+ providerConf := config.GetProviderConf()
|
|
|
+ err = os.WriteFile(extAuthPath, getExtAuthScriptContent(u, false, false, ""), os.ModePerm)
|
|
|
+ assert.NoError(t, err)
|
|
|
+ providerConf.ExternalAuthHook = extAuthPath
|
|
|
+ providerConf.ExternalAuthScope = 0
|
|
|
+ err = dataprovider.Initialize(providerConf, configDir, true)
|
|
|
+ assert.NoError(t, err)
|
|
|
+
|
|
|
+ conn, client, err := getSftpClient(u, usePubKey)
|
|
|
+ if assert.NoError(t, err) {
|
|
|
+ defer conn.Close()
|
|
|
+ defer client.Close()
|
|
|
+ assert.NoError(t, checkBasicSFTP(client))
|
|
|
+ }
|
|
|
+ // add multi-factor authentication
|
|
|
+ user, _, err := httpdtest.GetUserByUsername(defaultUsername, http.StatusOK)
|
|
|
+ assert.NoError(t, err)
|
|
|
+ assert.Len(t, user.Filters.RecoveryCodes, 0)
|
|
|
+ assert.False(t, user.Filters.TOTPConfig.Enabled)
|
|
|
+ configName, _, secret, _, err := mfa.GenerateTOTPSecret(mfa.GetAvailableTOTPConfigNames()[0], user.Username)
|
|
|
+ assert.NoError(t, err)
|
|
|
+ user.Password = defaultPassword
|
|
|
+ user.Filters.TOTPConfig = sdk.TOTPConfig{
|
|
|
+ Enabled: true,
|
|
|
+ ConfigName: configName,
|
|
|
+ Secret: kms.NewPlainSecret(secret),
|
|
|
+ Protocols: []string{common.ProtocolSSH},
|
|
|
+ }
|
|
|
+ for i := 0; i < 12; i++ {
|
|
|
+ user.Filters.RecoveryCodes = append(user.Filters.RecoveryCodes, sdk.RecoveryCode{
|
|
|
+ Secret: kms.NewPlainSecret(fmt.Sprintf("RC-%v", strings.ToUpper(util.GenerateUniqueID()))),
|
|
|
+ })
|
|
|
+ }
|
|
|
+ err = dataprovider.UpdateUser(&user, "", "")
|
|
|
+ assert.NoError(t, err)
|
|
|
+ // login again and check that the MFA configs are preserved
|
|
|
+ conn, client, err = getSftpClient(u, usePubKey)
|
|
|
+ if assert.NoError(t, err) {
|
|
|
+ defer conn.Close()
|
|
|
+ defer client.Close()
|
|
|
+ assert.NoError(t, checkBasicSFTP(client))
|
|
|
+ }
|
|
|
+
|
|
|
+ user, _, err = httpdtest.GetUserByUsername(defaultUsername, http.StatusOK)
|
|
|
+ assert.NoError(t, err)
|
|
|
+ assert.Len(t, user.Filters.RecoveryCodes, 12)
|
|
|
+ assert.True(t, user.Filters.TOTPConfig.Enabled)
|
|
|
+ assert.Equal(t, configName, user.Filters.TOTPConfig.ConfigName)
|
|
|
+ assert.Equal(t, []string{common.ProtocolSSH}, user.Filters.TOTPConfig.Protocols)
|
|
|
+ assert.Equal(t, kms.SecretStatusSecretBox, user.Filters.TOTPConfig.Secret.GetStatus())
|
|
|
+
|
|
|
+ err = os.WriteFile(extAuthPath, getExtAuthScriptContent(u, false, true, ""), os.ModePerm)
|
|
|
+ assert.NoError(t, err)
|
|
|
+
|
|
|
+ conn, client, err = getSftpClient(u, usePubKey)
|
|
|
+ if assert.NoError(t, err) {
|
|
|
+ defer conn.Close()
|
|
|
+ defer client.Close()
|
|
|
+ assert.NoError(t, checkBasicSFTP(client))
|
|
|
+ }
|
|
|
+
|
|
|
+ user, _, err = httpdtest.GetUserByUsername(defaultUsername, http.StatusOK)
|
|
|
+ assert.NoError(t, err)
|
|
|
+ assert.Len(t, user.Filters.RecoveryCodes, 12)
|
|
|
+ assert.True(t, user.Filters.TOTPConfig.Enabled)
|
|
|
+ assert.Equal(t, configName, user.Filters.TOTPConfig.ConfigName)
|
|
|
+ assert.Equal(t, []string{common.ProtocolSSH}, user.Filters.TOTPConfig.Protocols)
|
|
|
+ assert.Equal(t, kms.SecretStatusSecretBox, user.Filters.TOTPConfig.Secret.GetStatus())
|
|
|
+
|
|
|
+ _, err = httpdtest.RemoveUser(user, http.StatusOK)
|
|
|
+ assert.NoError(t, err)
|
|
|
+ err = os.RemoveAll(user.GetHomeDir())
|
|
|
+ assert.NoError(t, err)
|
|
|
+
|
|
|
+ err = dataprovider.Close()
|
|
|
+ assert.NoError(t, err)
|
|
|
+ err = config.LoadConfig(configDir, "")
|
|
|
+ assert.NoError(t, err)
|
|
|
+ providerConf = config.GetProviderConf()
|
|
|
+ err = dataprovider.Initialize(providerConf, configDir, true)
|
|
|
+ assert.NoError(t, err)
|
|
|
+ err = os.Remove(extAuthPath)
|
|
|
+ assert.NoError(t, err)
|
|
|
+}
|
|
|
+
|
|
|
func TestQuotaDisabledError(t *testing.T) {
|
|
|
err := dataprovider.Close()
|
|
|
assert.NoError(t, err)
|