Ctrl K
ComunidadGuías…

tests/identity_reauth_approval_test.go

Rama master · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package main

import (
	"context"
	"testing"
	"time"

	"github.com/shellhub-io/shellhub/pkg/models"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

// TestSSHApprovalReauth covers the approval a login waits on when a policy asks an enrolled key to
// re-authenticate: proving the factor refreshes the identity's re-authentication, the endpoint that
// enrolls keys cannot stand in for it, and a lapsed window refuses the login without refreshing
// anything. When a policy asks for one is covered by [TestAccessPolicyReauth].
func TestSSHApprovalReauth(t *testing.T) {
	t.Parallel()

	ctx := context.Background()
	compose := newSSHEnvironment(t, ctx, newNamespace)
	_, device := startAcceptedAgent(t, ctx, compose)

	sshid := deviceSSHID(device)

	t.Run("re-authenticating refreshes the identity's last re-authentication", func(t *testing.T) {
		requireReauth(t, compose, "hourly", new(3600))
		signer, fingerprint := enrollOwnerKey(t, compose)

		compose.AgeSSHIdentityReauth(t, fingerprint, 24*time.Hour)
		stale := identityByFingerprint(t, compose, fingerprint).LastReauthAt
		require.NotNil(t, stale)

		parked := startLogin(t, compose, sshid, signer)
		prompt := parked.awaitApproval(t)
		require.Equal(t, models.SSHApprovalReauth, prompt.kind)

		parked.answer(reauthenticate(t, compose, fingerprint, prompt.code))
		require.NoError(t, parked.result(t))

		requireRecent(t, identityByFingerprint(t, compose, fingerprint).LastReauthAt)
		assert.Equal(t, models.SSHApprovalConfirmed, approvalState(t, compose, prompt.code))
	})

	t.Run("a re-authentication cannot be confirmed through the enrollment endpoint", func(t *testing.T) {
		requireReauth(t, compose, "always", nil)
		signer, fingerprint := enrollOwnerKey(t, compose)

		parked := startLogin(t, compose, sshid, signer)
		prompt := parked.awaitApproval(t)
		require.Equal(t, models.SSHApprovalReauth, prompt.kind)

		_, resp, err := confirmApprovalAs(t.Context(), compose, "", prompt.code, nil)
		require.NoError(t, err)
		assert.Equal(t, 403, resp.StatusCode(), resp.String())

		approval, resp, err := getApprovalAs(t.Context(), compose, "", prompt.code)
		require.NoError(t, err)
		require.Equal(t, 200, resp.StatusCode(), resp.String())
		assert.Equal(t, models.SSHApprovalReauth, approval.Kind)
		assert.Equal(t, models.SSHApprovalPending, approval.State)
		assert.Nil(t, identityByFingerprint(t, compose, fingerprint).LastReauthAt)

		parked.answer(reauthenticate(t, compose, fingerprint, prompt.code))
		require.NoError(t, parked.result(t))
	})

	t.Run("a re-authentication past its window is refused and refreshes nothing", func(t *testing.T) {
		requireReauth(t, compose, "always", nil)
		signer, fingerprint := enrollOwnerKey(t, compose)

		parked := startLogin(t, compose, sshid, signer)
		prompt := parked.awaitApproval(t)
		require.Equal(t, models.SSHApprovalReauth, prompt.kind)

		compose.ExpireSSHApproval(t, prompt.code)

		_, resp, err := postReauth(t.Context(), compose, fingerprint, prompt.code)
		require.NoError(t, err)
		assert.Equal(t, 404, resp.StatusCode(), resp.String())
		assert.Nil(t, identityByFingerprint(t, compose, fingerprint).LastReauthAt,
			"a step-up that released nothing must not refresh the identity")

		parked.answer(strayConfirmationCode)

		require.Error(t, parked.result(t))
		assert.Equal(t, expiredReason, parked.denial())
	})
}