github.com/gravitational/teleport/api@v0.0.0-20240507183017-3110591cbafc/mfa/prompt.go (about)

     1  /*
     2  Copyright 2023 Gravitational, Inc.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package mfa
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  
    23  	"github.com/gravitational/teleport/api/client/proto"
    24  )
    25  
    26  // Prompt is an MFA prompt.
    27  type Prompt interface {
    28  	// Run prompts the user to complete an MFA authentication challenge.
    29  	Run(ctx context.Context, chal *proto.MFAAuthenticateChallenge) (*proto.MFAAuthenticateResponse, error)
    30  }
    31  
    32  // PromptFunc is a function wrapper that implements the Prompt interface.
    33  type PromptFunc func(ctx context.Context, chal *proto.MFAAuthenticateChallenge) (*proto.MFAAuthenticateResponse, error)
    34  
    35  // Run prompts the user to complete an MFA authentication challenge.
    36  func (f PromptFunc) Run(ctx context.Context, chal *proto.MFAAuthenticateChallenge) (*proto.MFAAuthenticateResponse, error) {
    37  	return f(ctx, chal)
    38  }
    39  
    40  // PromptConstructor is a function that creates a new MFA prompt.
    41  type PromptConstructor func(...PromptOpt) Prompt
    42  
    43  // PromptConfig contains common mfa prompt config options.
    44  type PromptConfig struct {
    45  	// PromptReason is an optional message to share with the user before an MFA Prompt.
    46  	// It is intended to provide context about why the user is being prompted where it may
    47  	// not be obvious, such as for admin actions or per-session MFA.
    48  	PromptReason string
    49  	// DeviceType is an optional device description to emphasize during the prompt.
    50  	DeviceType DeviceDescriptor
    51  	// Quiet suppresses users prompts.
    52  	Quiet bool
    53  }
    54  
    55  // DeviceDescriptor is a descriptor for a device, such as "registered".
    56  type DeviceDescriptor string
    57  
    58  // DeviceDescriptorRegistered is a registered device.
    59  const DeviceDescriptorRegistered = "registered"
    60  
    61  // PromptOpt applies configuration options to a prompt.
    62  type PromptOpt func(*PromptConfig)
    63  
    64  // WithQuiet sets the prompt's Quiet field.
    65  func WithQuiet() PromptOpt {
    66  	return func(cfg *PromptConfig) {
    67  		cfg.Quiet = true
    68  	}
    69  }
    70  
    71  // WithPromptReason sets the prompt's PromptReason field.
    72  func WithPromptReason(hint string) PromptOpt {
    73  	return func(cfg *PromptConfig) {
    74  		cfg.PromptReason = hint
    75  	}
    76  }
    77  
    78  // WithPromptReasonAdminAction sets the prompt's PromptReason field to a standard admin action message.
    79  func WithPromptReasonAdminAction() PromptOpt {
    80  	const adminMFAPromptReason = "This is an admin-level action and requires MFA to complete"
    81  	return WithPromptReason(adminMFAPromptReason)
    82  }
    83  
    84  // WithPromptReasonSessionMFA sets the prompt's PromptReason field to a standard session mfa message.
    85  func WithPromptReasonSessionMFA(serviceType, serviceName string) PromptOpt {
    86  	return WithPromptReason(fmt.Sprintf("MFA is required to access %s %q", serviceType, serviceName))
    87  }
    88  
    89  // WithPromptDeviceType sets the prompt's DeviceType field.
    90  func WithPromptDeviceType(deviceType DeviceDescriptor) PromptOpt {
    91  	return func(cfg *PromptConfig) {
    92  		cfg.DeviceType = deviceType
    93  	}
    94  }