mirror of
https://github.com/mulgadc/spinifex.git
synced 2026-10-15 09:01:31 +00:00
fix: return InvalidParameterValue for a missing RDS master password
ValidateMasterUserPassword built the empty-password error with a bare errors.New carrying the code only in its text, which awserrors does not resolve, so CreateDBInstance without MasterUserPassword returned HTTP 500 ServerInternal. Build it with awserrors.Errorf like the other branches so the gateway returns 400 InvalidParameterValue, and cover the full gateway to RDS service path with a regression test.
This commit is contained in:
@@ -9,10 +9,13 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go/service/rds"
|
||||
"github.com/mulgadc/spinifex/internal/testkit"
|
||||
"github.com/mulgadc/spinifex/spinifex/foundation/aws/errors"
|
||||
natsmsg "github.com/mulgadc/spinifex/spinifex/foundation/messaging/nats"
|
||||
handlers_iam "github.com/mulgadc/spinifex/spinifex/handlers/iam"
|
||||
handlers_rds "github.com/mulgadc/spinifex/spinifex/handlers/rds"
|
||||
"github.com/nats-io/nats.go"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
@@ -361,3 +364,31 @@ func TestRDSErrorHandler_UsesRDSUnsupportedActionWording(t *testing.T) {
|
||||
}
|
||||
|
||||
var errNotImplementedForTest = errors.New(awserrors.ErrorNotImplemented)
|
||||
|
||||
// TestRDSRequest_CreateDBInstance_EmptyMasterUserPasswordReturns400 runs the real public path:
|
||||
// a CreateDBInstance query request through RDS_Request, over NATS, into the production
|
||||
// handlers_rds.Service, and the resulting error through ErrorHandler's HTTP/XML rendering. AWS
|
||||
// returns 400 InvalidParameterValue for a create with no MasterUserPassword.
|
||||
func TestRDSRequest_CreateDBInstance_EmptyMasterUserPasswordReturns400(t *testing.T) {
|
||||
_, nc, _ := testutil.StartTestJetStream(t)
|
||||
svc := handlers_rds.NewService(nc, "ap-southeast-2")
|
||||
sub, err := nc.Subscribe(handlers_rds.SubjectCreateDBInstance, func(msg *nats.Msg) {
|
||||
natsmsg.ServeNATSRequestCtx(msg, func(ctx context.Context, in *rds.CreateDBInstanceInput) (*rds.CreateDBInstanceOutput, error) {
|
||||
return svc.CreateDBInstance(ctx, in, natsmsg.AccountIDFromMsg(msg))
|
||||
})
|
||||
})
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() { _ = sub.Unsubscribe() })
|
||||
|
||||
gw := &GatewayConfig{DisableLogging: true, NATSConn: nc, IAMService: allowAllIAMService()}
|
||||
req := setupRDSRequest("Action=CreateDBInstance&DBInstanceIdentifier=orders-db&Engine=postgres&" +
|
||||
"DBInstanceClass=db.t3.medium&AllocatedStorage=20&MasterUsername=appuser&DBName=orders")
|
||||
|
||||
reqErr := gw.RDS_Request(httptest.NewRecorder(), req)
|
||||
require.Error(t, reqErr)
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
gw.ErrorHandler(w, req, reqErr)
|
||||
assert.Equal(t, http.StatusBadRequest, w.Code)
|
||||
assert.Contains(t, w.Body.String(), "<Code>"+awserrors.ErrorInvalidParameterValue+"</Code>")
|
||||
}
|
||||
|
||||
@@ -255,7 +255,7 @@ func validateIdentifier(field, value string, maxLen int, allowEmpty bool) error
|
||||
func ValidateMasterUserPassword(password string) error {
|
||||
switch {
|
||||
case password == "":
|
||||
return errors.New(awserrors.ErrorInvalidParameterValue + ": MasterUserPassword is required")
|
||||
return awserrors.Errorf(awserrors.ErrorInvalidParameterValue, "MasterUserPassword is required")
|
||||
case len(password) < minMasterPasswordLen || len(password) > maxMasterPasswordLen:
|
||||
return awserrors.Errorf(awserrors.ErrorInvalidParameterValue,
|
||||
"MasterUserPassword must be between %d and %d characters", minMasterPasswordLen, maxMasterPasswordLen)
|
||||
|
||||
@@ -56,21 +56,15 @@ func TestEngineValidateVersion_UnsupportedVersionCarriesExactCode(t *testing.T)
|
||||
assert.Equal(t, awserrors.ErrorInvalidParameterValue, awserrors.ValidErrorCodeFromError(err))
|
||||
}
|
||||
|
||||
// ValidateMasterUserPassword's three rejections are built two different ways
|
||||
// today: the length and character checks go through awserrors.Errorf, whose
|
||||
// wrapped code resolves through ValidErrorCodeFromError; the empty-password
|
||||
// check is a bare errors.New with the code only prefixed into the message
|
||||
// text, which ValidErrorCodeFromError's exact-match lookup does not resolve.
|
||||
// This pins that divergence rather than papering over it.
|
||||
// ValidateMasterUserPassword's three rejections all go through awserrors.Errorf,
|
||||
// so each one resolves through ValidErrorCodeFromError to the same code.
|
||||
func TestValidateMasterUserPassword_ExactCodesAndMessages(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
empty := ValidateMasterUserPassword("")
|
||||
require.Error(t, empty)
|
||||
assert.Equal(t, "InvalidParameterValue: MasterUserPassword is required", empty.Error())
|
||||
assert.Equal(t, awserrors.ErrorServerInternal, awserrors.ValidErrorCodeFromError(empty),
|
||||
"today this does NOT resolve to InvalidParameterValue: the code is only prefixed into the "+
|
||||
"message text, not carried as a wrapped codedError, so the helper's exact-match lookup misses it")
|
||||
assert.Equal(t, "MasterUserPassword is required: InvalidParameterValue", empty.Error())
|
||||
assert.Equal(t, awserrors.ErrorInvalidParameterValue, awserrors.ValidErrorCodeFromError(empty))
|
||||
|
||||
tooShort := ValidateMasterUserPassword("short1")
|
||||
require.Error(t, tooShort)
|
||||
|
||||
Reference in New Issue
Block a user