diff --git a/aws-rds-dbinstance/src/main/java/software/amazon/rds/dbinstance/BaseHandlerStd.java b/aws-rds-dbinstance/src/main/java/software/amazon/rds/dbinstance/BaseHandlerStd.java index 6ea67dc87..dc3428a68 100644 --- a/aws-rds-dbinstance/src/main/java/software/amazon/rds/dbinstance/BaseHandlerStd.java +++ b/aws-rds-dbinstance/src/main/java/software/amazon/rds/dbinstance/BaseHandlerStd.java @@ -112,6 +112,7 @@ import software.amazon.rds.dbinstance.status.OptionGroupStatus; import software.amazon.rds.dbinstance.status.ReadReplicaStatus; import software.amazon.rds.dbinstance.status.VPCSecurityGroupStatus; +import software.amazon.rds.dbinstance.util.ResourceModelHelper; public abstract class BaseHandlerStd extends BaseHandler { @@ -385,6 +386,9 @@ protected ApiVersionDispatcher getApiVersionDisp protected void validateRequest(final ResourceHandlerRequest request) throws RequestValidationException { Validations.validateSourceRegion(request.getDesiredResourceState().getSourceRegion()); + Validations.validateSourceRegion(request.getDesiredResourceState().getAutomaticBackupReplicationRegion()); + assertValidRegionFromArnOrIdentifier(request.getDesiredResourceState().getSourceDBInstanceIdentifier()); + assertValidRegionFromArnOrIdentifier(request.getDesiredResourceState().getSourceDBClusterIdentifier()); } protected abstract ProgressEvent handleRequest( @@ -671,6 +675,19 @@ private void assertNoTerminalStatus(final DBInstance dbInstance) throws CfnNotSt assertNoDomainMembershipTerminalStatus(dbInstance); } + /** + * There are fields in the request (e.g. SourceDBInstanceIdentifier and SourceDBClusterIdentifier) that accept 2 types + * of identifiers: InstanceId or ARN. In the case of containing an ARN, we need to validate that the region is correct, + * as it will be used to contract the client endpoint, and a malformed region would lead to both security issues + * and also would return misleading error to the customer. + */ + private static void assertValidRegionFromArnOrIdentifier(final String identifierOrArnField) throws RequestValidationException { + if (StringUtils.isNotBlank(identifierOrArnField) && ResourceModelHelper.isValidArn(identifierOrArnField)) { + final String sourceRegion = ResourceModelHelper.getRegionFromArn(identifierOrArnField); + Validations.validateSourceRegion(sourceRegion); + } + } + protected boolean isDBInstanceStabilizedAfterMutate( final ProxyClient rdsProxyClient, final ResourceModel model, diff --git a/aws-rds-dbinstance/src/test/java/software/amazon/rds/dbinstance/CreateHandlerTest.java b/aws-rds-dbinstance/src/test/java/software/amazon/rds/dbinstance/CreateHandlerTest.java index d0b2c1a6b..c529cf7b9 100644 --- a/aws-rds-dbinstance/src/test/java/software/amazon/rds/dbinstance/CreateHandlerTest.java +++ b/aws-rds-dbinstance/src/test/java/software/amazon/rds/dbinstance/CreateHandlerTest.java @@ -2258,4 +2258,84 @@ public void fetchEngineForUnknownScenario() { expectFailed(HandlerErrorCode.InvalidRequest) ); } + + @Test + public void invalidSourceRegion() { + expectServiceInvocation = false; + final CallbackContext context = new CallbackContext(); + context.setCreated(true); + context.setUpdated(true); + context.setRebooted(true); + context.setUpdatedRoles(true); + context.setAddTagsComplete(true); + + test_handleRequest_base( + context, + null, + () -> RESOURCE_MODEL_BAREBONE_BLDR() + .sourceRegion("clearlyNotAValidRegion") + .build(), + expectFailed(HandlerErrorCode.InvalidRequest) + ); + } + + @Test + public void invalidAutomaticBackupReplicationRegion() { + expectServiceInvocation = false; + final CallbackContext context = new CallbackContext(); + context.setCreated(true); + context.setUpdated(true); + context.setRebooted(true); + context.setUpdatedRoles(true); + context.setAddTagsComplete(true); + + test_handleRequest_base( + context, + null, + () -> RESOURCE_MODEL_BAREBONE_BLDR() + .automaticBackupReplicationRegion("clearlyNotAValidRegion") + .build(), + expectFailed(HandlerErrorCode.InvalidRequest) + ); + } + + @Test + public void invalidSourceDBInstanceIdentifierRegion() { + expectServiceInvocation = false; + final CallbackContext context = new CallbackContext(); + context.setCreated(true); + context.setUpdated(true); + context.setRebooted(true); + context.setUpdatedRoles(true); + context.setAddTagsComplete(true); + + test_handleRequest_base( + context, + null, + () -> RESOURCE_MODEL_BAREBONE_BLDR() + .sourceDBInstanceIdentifier("arn:aws:rds:clearlyNotAValidRegion:340834135580:db:databaseName") + .build(), + expectFailed(HandlerErrorCode.InvalidRequest) + ); + } + + @Test + public void invalidSourceDBClusterIdentifierRegion() { + expectServiceInvocation = false; + final CallbackContext context = new CallbackContext(); + context.setCreated(true); + context.setUpdated(true); + context.setRebooted(true); + context.setUpdatedRoles(true); + context.setAddTagsComplete(true); + + test_handleRequest_base( + context, + null, + () -> RESOURCE_MODEL_BAREBONE_BLDR() + .sourceDBClusterIdentifier("arn:aws:rds:clearlyNotAValidRegion:340834135580:cluster:clusterName") + .build(), + expectFailed(HandlerErrorCode.InvalidRequest) + ); + } }