Skip to content
Open
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
15 changes: 15 additions & 0 deletions api/http/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,21 @@ func EncodeError(_ context.Context, err error, w http.ResponseWriter) {
return
}

switch retErr := err.(type) {
case errors.RequestError:
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(retErr); err != nil {
w.WriteHeader(http.StatusInternalServerError)
}
return
case errors.AuthNError, errors.AuthZError:
w.WriteHeader(http.StatusUnauthorized)
if err := json.NewEncoder(w).Encode(retErr); err != nil {
w.WriteHeader(http.StatusInternalServerError)
}
return
}

Comment on lines +187 to +201
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will this type switch replace the big switch case defined below?

var wrapper error
if errors.Contains(err, apiutil.ErrValidation) {
wrapper, err = errors.Unwrap(err)
Expand Down
48 changes: 24 additions & 24 deletions api/http/util/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,10 @@ var (
ErrInvalidIDFormat = errors.New("invalid id format provided")

// ErrNameSize indicates that name size exceeds the max.
ErrNameSize = errors.New("invalid name size")
ErrNameSize = errors.NewRequestError("invalid name size")

// ErrEmailSize indicates that email size exceeds the max.
ErrEmailSize = errors.New("invalid email size")
ErrEmailSize = errors.NewRequestError("invalid email size")

// ErrInvalidRole indicates that an invalid role.
ErrInvalidRole = errors.New("invalid client role")
Expand Down Expand Up @@ -124,7 +124,7 @@ var (
ErrInvalidContact = errors.New("invalid Subscription contact")

// ErrMissingEmail indicates missing email.
ErrMissingEmail = errors.New("missing email")
ErrMissingEmail = errors.NewRequestError("missing email")

// ErrInvalidEmail indicates missing email.
ErrInvalidEmail = errors.New("invalid email")
Expand Down Expand Up @@ -169,16 +169,16 @@ var (
ErrMissingIdentity = errors.New("missing entity identity")

// ErrMissingSecret indicates missing secret.
ErrMissingSecret = errors.New("missing secret")
ErrMissingSecret = errors.NewRequestError("missing secret")

// ErrPasswordFormat indicates weak password.
ErrPasswordFormat = errors.New("password does not meet the requirements")
ErrPasswordFormat = errors.NewRequestError("password does not meet the requirements")

// ErrMissingName indicates missing identity name.
ErrMissingName = errors.New("missing identity name")
ErrMissingName = errors.NewRequestError("missing identity name")

// ErrMissingRoute indicates missing route.
ErrMissingRoute = errors.New("missing route")
ErrMissingRoute = errors.NewRequestError("missing route")

// ErrInvalidLevel indicates an invalid group level.
ErrInvalidLevel = errors.New("invalid group level (should be between 0 and 5)")
Expand Down Expand Up @@ -211,37 +211,37 @@ var (
ErrMissingTo = errors.New("missing to time value")

// ErrEmptyMessage indicates empty message.
ErrEmptyMessage = errors.New("empty message")
ErrEmptyMessage = errors.NewRequestError("empty message")

// ErrMissingEntityType indicates missing entity type.
ErrMissingEntityType = errors.New("missing entity type")
ErrMissingEntityType = errors.NewRequestError("missing entity type")

// ErrInvalidEntityType indicates invalid entity type.
ErrInvalidEntityType = errors.New("invalid entity type")
ErrInvalidEntityType = errors.NewRequestError("invalid entity type")

// ErrInvalidTimeFormat indicates invalid time format i.e not unix time.
ErrInvalidTimeFormat = errors.New("invalid time format use unix time")
ErrInvalidTimeFormat = errors.NewRequestError("invalid time format use unix time")

// ErrEmptySearchQuery indicates search query should not be empty.
ErrEmptySearchQuery = errors.New("search query must not be empty")
ErrEmptySearchQuery = errors.NewRequestError("search query must not be empty")

// ErrLenSearchQuery indicates search query length.
ErrLenSearchQuery = errors.New("search query must be at least 3 characters")
ErrLenSearchQuery = errors.NewRequestError("search query must be at least 3 characters")

// ErrMissingDomainID indicates missing domainID.
ErrMissingDomainID = errors.New("missing domainID")
ErrMissingDomainID = errors.NewRequestError("missing domainID")

// ErrMissingUsername indicates missing user name.
ErrMissingUsername = errors.New("missing username")
ErrMissingUsername = errors.NewRequestError("missing username")

// ErrInvalidUsername indicates invalid user name.
ErrInvalidUsername = errors.New("invalid username")
ErrInvalidUsername = errors.NewRequestError("invalid username")

// ErrMissingFirstName indicates missing first name.
ErrMissingFirstName = errors.New("missing first name")
ErrMissingFirstName = errors.NewRequestError("missing first name")

// ErrMissingLastName indicates missing last name.
ErrMissingLastName = errors.New("missing last name")
ErrMissingLastName = errors.NewRequestError("missing last name")

// ErrInvalidProfilePictureURL indicates that the profile picture url is invalid.
ErrInvalidProfilePictureURL = errors.New("invalid profile picture url")
Expand All @@ -255,23 +255,23 @@ var (
ErrUnsupportedTokenType = errors.New("unsupported content token type")

// ErrMissingUserID indicates missing user ID.
ErrMissingUserID = errors.New("missing user id")
ErrMissingUserID = errors.NewRequestError("missing user id")

// ErrMissingPATID indicates missing pat ID.
ErrMissingPATID = errors.New("missing pat id")

// ErrInvalidNameFormat indicates invalid name format.
ErrInvalidNameFormat = errors.New("invalid name format")
ErrInvalidNameFormat = errors.NewRequestError("invalid name format")

// ErrInvalidRouteFormat indicates invalid route format.
ErrInvalidRouteFormat = errors.New("invalid route format")
ErrInvalidRouteFormat = errors.NewRequestError("invalid route format")

// ErrMissingUsernameEmail indicates missing user name / email.
ErrMissingUsernameEmail = errors.New("missing username / email")
ErrMissingUsernameEmail = errors.NewRequestError("missing username / email")

// ErrInvalidVerification indicates invalid email verification.
ErrInvalidVerification = errors.New("invalid verification")
ErrInvalidVerification = errors.NewRequestError("invalid verification")

// ErrEmailNotVerified indicates invalid email not verified.
ErrEmailNotVerified = errors.New("email not verified")
ErrEmailNotVerified = errors.NewRequestError("email not verified")
)
8 changes: 7 additions & 1 deletion docker/addons/certs/openbao-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,10 @@ if [ ! -f /opt/openbao/data/configured ]; then
key_usage=\"DigitalSignature,KeyEncipherment,KeyAgreement\" \
ext_key_usage=\"ServerAuth,ClientAuth,OCSPSigning\" \
use_csr_common_name=true \
use_csr_sans=false \
use_csr_sans=true \
copy_extensions=true \
allowed_extensions=\"*\" \
basic_constraints_valid_for_non_ca=true \
max_ttl=720h \
ttl=720h"

Expand All @@ -284,6 +287,9 @@ path "pki_int/issue/${AM_CERTS_OPENBAO_PKI_ROLE}" {
path "pki_int/sign/${AM_CERTS_OPENBAO_PKI_ROLE}" {
capabilities = ["create", "update"]
}
path "pki_int/sign-verbatim/${AM_CERTS_OPENBAO_PKI_ROLE}" {
capabilities = ["create", "update"]
}
path "pki_int/certs" {
capabilities = ["list"]
}
Expand Down
5 changes: 5 additions & 0 deletions pkg/errors/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@ func Wrap(wrapper, err error) error {
if wrapper == nil || err == nil {
return wrapper
}

if ne, ok := err.(NewError); ok {
return ne.Wrap(wrapper)
}

if w, ok := wrapper.(Error); ok {
return &customError{
msg: w.Msg(),
Expand Down
138 changes: 138 additions & 0 deletions pkg/errors/errortypes.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0

package errors

import (
"encoding/json"
"errors"
)

type NewError interface {
// Error implements the error interface.
Error() string

// Msg returns error message.
Msg() string

// Err returns wrapped error.
Unwrap() error

Wrap(e error) error

// MarshalJSON returns a marshaled error.
MarshalJSON() ([]byte, error)
}

// NewError specifies an that request could be processed and error which should be addressed by user.
type newError struct {
Err error // Contains other internal details and errors as wrapped error
Message string // Message for end users returned by API layer or other end layer
}

func (e newError) Error() string {
if e.Err == nil {
return e.Message
}
return e.Message + " : " + e.Err.Error()
}

func (e newError) Unwrap() error {
return e.Err
}

func (e newError) Msg() string {
return e.Message
}

func (e newError) MarshalJSON() ([]byte, error) {
return json.Marshal(&struct {
Err string `json:"error"`
}{
Err: e.Message,
})
}

var _ NewError = (*RequestError)(nil)

type RequestError struct {
newError
}

func (e RequestError) Wrap(err error) error {
e.Err = errors.Join(err, e.Err)
return e
}

func NewRequestError(message string) error {
return RequestError{
newError: newError{
Message: message,
},
}
}

func NewRequestErrorWithErr(message string, err error) error {
return RequestError{
newError: newError{
Message: message,
Err: err,
},
}
}

var _ NewError = (*AuthNError)(nil)

type AuthNError struct {
newError
}

func (e AuthNError) Wrap(err error) error {
e.Err = errors.Join(err, e.Err)
return e
}

func NewAuthNError(message string) error {
return AuthNError{
newError: newError{
Message: message,
},
}
}

func NewAuthNErrorWithErr(message string, err error) error {
return AuthNError{
newError: newError{
Message: message,
Err: err,
},
}
}

var _ NewError = (*AuthZError)(nil)

type AuthZError struct {
newError
}

func (e AuthZError) Wrap(err error) error {
e.Err = errors.Join(err, e.Err)
return e
}

func NewAuthZError(message string) error {
return AuthZError{
newError: newError{
Message: message,
},
}
}

func NewAuthZErrorWithErr(message string, err error) error {
return AuthZError{
newError: newError{
Message: message,
Err: err,
},
}
}
14 changes: 14 additions & 0 deletions pkg/errors/handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0

package errors

type Mapper interface {
GetError(key string) (error, bool)
}

type Handler interface {
HandleError(wrapper, err error) error
}

type HandlerOption func(*Handler)
7 changes: 5 additions & 2 deletions pkg/errors/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,13 @@ var (
ErrRollbackTx = errors.New("failed to rollback transaction")

// ErrAuthentication indicates failure occurred while authenticating the entity.
ErrAuthentication = errors.New("failed to perform authentication over the entity")
ErrAuthentication = NewAuthNError("failed to perform authentication over the entity")

// ErrAuthorization indicates failure occurred while authorizing the entity.
ErrAuthorization = errors.New("failed to perform authorization over the entity")
ErrAuthorization = NewAuthZError("failed to perform authorization over the entity")

// ErrDomainAuthorization indicates failure occurred while authorizing the domain.
ErrDomainAuthorization = NewAuthZError("failed to perform authorization over the domain")

// ErrMissingDomainMember indicates member is not part of a domain.
ErrMissingDomainMember = errors.New("member id is not member of domain")
Expand Down
Loading
Loading