github.com/letsencrypt/boulder@v0.20251208.0/web/probs.go (about)

     1  package web
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  
     7  	berrors "github.com/letsencrypt/boulder/errors"
     8  	"github.com/letsencrypt/boulder/probs"
     9  )
    10  
    11  func problemDetailsForBoulderError(err *berrors.BoulderError, msg string) *probs.ProblemDetails {
    12  	var outProb *probs.ProblemDetails
    13  
    14  	switch err.Type {
    15  	case berrors.Malformed:
    16  		outProb = probs.Malformed(fmt.Sprintf("%s :: %s", msg, err))
    17  	case berrors.Unauthorized:
    18  		outProb = probs.Unauthorized(fmt.Sprintf("%s :: %s", msg, err))
    19  	case berrors.NotFound:
    20  		outProb = probs.NotFound(fmt.Sprintf("%s :: %s", msg, err))
    21  	case berrors.RateLimit:
    22  		outProb = probs.RateLimited(fmt.Sprintf("%s :: %s", msg, err))
    23  	case berrors.InternalServer:
    24  		// Internal server error messages may include sensitive data, so we do
    25  		// not include it.
    26  		outProb = probs.ServerInternal(msg)
    27  	case berrors.RejectedIdentifier:
    28  		outProb = probs.RejectedIdentifier(fmt.Sprintf("%s :: %s", msg, err))
    29  	case berrors.InvalidEmail:
    30  		outProb = probs.InvalidContact(fmt.Sprintf("%s :: %s", msg, err))
    31  	case berrors.CAA:
    32  		outProb = probs.CAA(fmt.Sprintf("%s :: %s", msg, err))
    33  	case berrors.MissingSCTs:
    34  		// MissingSCTs are an internal server error, but with a specific error
    35  		// message related to the SCT problem
    36  		outProb = probs.ServerInternal(fmt.Sprintf("%s :: %s", msg, "Unable to meet CA SCT embedding requirements"))
    37  	case berrors.OrderNotReady:
    38  		outProb = probs.OrderNotReady(fmt.Sprintf("%s :: %s", msg, err))
    39  	case berrors.BadPublicKey:
    40  		outProb = probs.BadPublicKey(fmt.Sprintf("%s :: %s", msg, err))
    41  	case berrors.BadCSR:
    42  		outProb = probs.BadCSR(fmt.Sprintf("%s :: %s", msg, err))
    43  	case berrors.AlreadyReplaced:
    44  		outProb = probs.AlreadyReplaced(fmt.Sprintf("%s :: %s", msg, err))
    45  	case berrors.AlreadyRevoked:
    46  		outProb = probs.AlreadyRevoked(fmt.Sprintf("%s :: %s", msg, err))
    47  	case berrors.BadRevocationReason:
    48  		outProb = probs.BadRevocationReason(fmt.Sprintf("%s :: %s", msg, err))
    49  	case berrors.UnsupportedContact:
    50  		outProb = probs.UnsupportedContact(fmt.Sprintf("%s :: %s", msg, err))
    51  	case berrors.Conflict:
    52  		outProb = probs.Conflict(fmt.Sprintf("%s :: %s", msg, err))
    53  	case berrors.InvalidProfile:
    54  		outProb = probs.InvalidProfile(fmt.Sprintf("%s :: %s", msg, err))
    55  	case berrors.BadSignatureAlgorithm:
    56  		outProb = probs.BadSignatureAlgorithm(fmt.Sprintf("%s :: %s", msg, err))
    57  	case berrors.AccountDoesNotExist:
    58  		outProb = probs.AccountDoesNotExist(fmt.Sprintf("%s :: %s", msg, err))
    59  	case berrors.BadNonce:
    60  		// We stuff extra internal info into bad nonce errors, but none of it is
    61  		// really actionable by the end-user, so overwrite the user-visible message.
    62  		outProb = probs.BadNonce("JWS has an invalid anti-replay nonce")
    63  	default:
    64  		// Internal server error messages may include sensitive data, so we do
    65  		// not include it.
    66  		outProb = probs.ServerInternal(msg)
    67  	}
    68  
    69  	if len(err.SubErrors) > 0 {
    70  		var subProbs []probs.SubProblemDetails
    71  		for _, subErr := range err.SubErrors {
    72  			subProbs = append(subProbs, subProblemDetailsForSubError(subErr, msg))
    73  		}
    74  		return outProb.WithSubProblems(subProbs)
    75  	}
    76  
    77  	return outProb
    78  }
    79  
    80  // ProblemDetailsForError turns an error into a ProblemDetails. If the error is
    81  // of an type unknown to ProblemDetailsForError, it will return a ServerInternal
    82  // ProblemDetails.
    83  func ProblemDetailsForError(err error, msg string) *probs.ProblemDetails {
    84  	var bErr *berrors.BoulderError
    85  	if errors.As(err, &bErr) {
    86  		return problemDetailsForBoulderError(bErr, msg)
    87  	} else {
    88  		// Internal server error messages may include sensitive data, so we do
    89  		// not include it.
    90  		return probs.ServerInternal(msg)
    91  	}
    92  }
    93  
    94  // subProblemDetailsForSubError converts a SubBoulderError into
    95  // a SubProblemDetails using problemDetailsForBoulderError.
    96  func subProblemDetailsForSubError(subErr berrors.SubBoulderError, msg string) probs.SubProblemDetails {
    97  	return probs.SubProblemDetails{
    98  		Identifier:     subErr.Identifier,
    99  		ProblemDetails: *problemDetailsForBoulderError(subErr.BoulderError, msg),
   100  	}
   101  }