Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions api/types/authentication.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ type AuthPreference interface {
// IsSecondFactorWebauthnAllowed checks if users are allowed to register
// Webauthn devices.
IsSecondFactorWebauthnAllowed() bool
// IsAdminActionMFAEnforced checks if admin action MFA is enforced.
IsAdminActionMFAEnforced() bool

// GetConnectorName gets the name of the OIDC or SAML connector to use. If
// this value is empty, we fall back to the first connector in the backend.
Expand Down Expand Up @@ -325,6 +327,12 @@ func (c *AuthPreferenceV2) IsSecondFactorWebauthnAllowed() bool {
c.Spec.SecondFactor == constants.SecondFactorOn
}

// IsAdminActionMFAEnforced checks if admin action MFA is enforced. Currently, the only
// prerequisite for admin action MFA enforcement is whether Webauthn is enabled.
func (c *AuthPreferenceV2) IsAdminActionMFAEnforced() bool {
return c.IsSecondFactorWebauthnAllowed()
}

// GetConnectorName gets the name of the OIDC or SAML connector to use. If
// this value is empty, we fall back to the first connector in the backend.
func (c *AuthPreferenceV2) GetConnectorName() string {
Expand Down
5 changes: 2 additions & 3 deletions lib/authz/permissions.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ import (

"github.com/gravitational/teleport"
"github.com/gravitational/teleport/api/client/proto"
"github.com/gravitational/teleport/api/constants"
"github.com/gravitational/teleport/api/defaults"
mfav1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/mfa/v1"
"github.com/gravitational/teleport/api/mfa"
Expand Down Expand Up @@ -444,8 +443,8 @@ func (a *authorizer) isAdminActionAuthorizationRequired(ctx context.Context, aut
return false, trace.Wrap(err)
}

// Admin actions do not require MFA when Webauthn is not enabled.
if authpref.GetPreferredLocalMFA() != constants.SecondFactorWebauthn {
// Check if this cluster enforces MFA for admin actions.
if !authpref.IsAdminActionMFAEnforced() {
return false, nil
}

Expand Down
11 changes: 11 additions & 0 deletions tool/tctl/common/user_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import (

"github.com/gravitational/teleport"
"github.com/gravitational/teleport/api/constants"
"github.com/gravitational/teleport/api/mfa"
"github.com/gravitational/teleport/api/types"
"github.com/gravitational/teleport/lib/asciitable"
"github.com/gravitational/teleport/lib/auth"
Expand Down Expand Up @@ -297,6 +298,16 @@ func (u *UserCommand) Add(ctx context.Context, client auth.ClientI) error {
user.SetTraits(traits)
user.SetRoles(u.allowedRoles)

// Prompt for admin action MFA if required, allowing reuse for CreateResetPasswordToken.
if u.config.Auth.Preference.IsAdminActionMFAEnforced() {
mfaResponse, err := mfa.PerformAdminActionMFACeremony(ctx, client, "CreateUser", true /*allowReuse*/)
if err != nil {
return trace.Wrap(err)
} else if mfaResponse != nil {
ctx = mfa.ContextWithMFAResponse(ctx, mfaResponse)
}
}

if _, err := client.CreateUser(ctx, user); err != nil {
if trace.IsAlreadyExists(err) {
fmt.Printf(`NOTE: To update an existing local user:
Expand Down