diff --git a/auth/bucket_policy_actions.go b/auth/bucket_policy_actions.go index 59b8935..5d9694c 100644 --- a/auth/bucket_policy_actions.go +++ b/auth/bucket_policy_actions.go @@ -76,6 +76,8 @@ const ( GetBucketRequestPaymentAction Action = "s3:GetBucketRequestPayment" PutMetricsConfigurationAction Action = "s3:PutMetricsConfiguration" GetMetricsConfigurationAction Action = "s3:GetMetricsConfiguration" + PutReplicationConfigurationAction Action = "s3:PutReplicationConfiguration" + GetReplicationConfigurationAction Action = "s3:GetReplicationConfiguration" AllActions Action = "s3:*" ) @@ -135,6 +137,8 @@ var supportedActionList = map[Action]struct{}{ GetBucketRequestPaymentAction: {}, PutMetricsConfigurationAction: {}, GetMetricsConfigurationAction: {}, + PutReplicationConfigurationAction: {}, + GetReplicationConfigurationAction: {}, AllActions: {}, } diff --git a/metrics/actions.go b/metrics/actions.go index 2fe6362..82ed7a6 100644 --- a/metrics/actions.go +++ b/metrics/actions.go @@ -82,7 +82,7 @@ var ( ActionDeleteBucketAnalyticsConfiguration = "s3_DeleteBucketAnalyticsConfiguration" ActionPutBucketEncryption = "s3_PutBucketEncryption" ActionGetBucketEncryption = "s3_GetBucketEncryption" - ActionDeleteBucketEncryption = "s3_DeleteBucketEcryption" + ActionDeleteBucketEncryption = "s3_DeleteBucketEncryption" ActionPutBucketIntelligentTieringConfiguration = "s3_PutBucketIntelligentTieringConfiguration" ActionGetBucketIntelligentTieringConfiguration = "s3_GetBucketIntelligentTieringConfiguration" ActionListBucketIntelligentTieringConfigurations = "s3_ListBucketIntelligentTieringConfigurations" @@ -102,6 +102,9 @@ var ( ActionGetBucketMetricsConfiguration = "s3_GetBucketMetricsConfiguration" ActionListBucketMetricsConfigurations = "s3_ListBucketMetricsConfigurations" ActionDeleteBucketMetricsConfiguration = "s3_DeleteBucketMetricsConfiguration" + ActionPutBucketReplication = "s3_PutBucketReplication" + ActionGetBucketReplication = "s3_GetBucketReplication" + ActionDeleteBucketReplication = "s3_DeleteBucketReplication" // Admin actions ActionAdminCreateUser = "admin_CreateUser" @@ -308,4 +311,136 @@ func init() { Name: "DeleteBucketCors", Service: "s3", } + ActionMap[ActionPutBucketOwnershipControls] = Action{ + Name: "PutBucketOwnershipControls", + Service: "s3", + } + ActionMap[ActionGetBucketOwnershipControls] = Action{ + Name: "GetBucketOwnershipControls", + Service: "s3", + } + ActionMap[ActionDeleteBucketOwnershipControls] = Action{ + Name: "DeleteBucketOwnershipControls", + Service: "s3", + } + ActionMap[ActionOptions] = Action{ + Name: "Options", + Service: "s3", + } + ActionMap[ActionPutBucketAnalyticsConfiguration] = Action{ + Name: "PutBucketAnalyticsConfiguration", + Service: "s3", + } + ActionMap[ActionGetBucketAnalyticsConfiguration] = Action{ + Name: "GetBucketAnalyticsConfiguration", + Service: "s3", + } + ActionMap[ActionListBucketAnalyticsConfigurations] = Action{ + Name: "ListBucketAnalyticsConfigurations", + Service: "s3", + } + ActionMap[ActionDeleteBucketAnalyticsConfiguration] = Action{ + Name: "DeleteBucketAnalyticsConfiguration", + Service: "s3", + } + ActionMap[ActionPutBucketEncryption] = Action{ + Name: "PutBucketEncryption", + Service: "s3", + } + ActionMap[ActionGetBucketEncryption] = Action{ + Name: "GetBucketEncryption", + Service: "s3", + } + ActionMap[ActionDeleteBucketEncryption] = Action{ + Name: "DeleteBucketEncryption", + Service: "s3", + } + ActionMap[ActionPutBucketIntelligentTieringConfiguration] = Action{ + Name: "PutBucketIntelligentTieringConfiguration", + Service: "s3", + } + ActionMap[ActionGetBucketIntelligentTieringConfiguration] = Action{ + Name: "GetBucketIntelligentTieringConfiguration", + Service: "s3", + } + ActionMap[ActionListBucketIntelligentTieringConfigurations] = Action{ + Name: "ListBucketIntelligentTieringConfigurations", + Service: "s3", + } + ActionMap[ActionDeleteBucketIntelligentTieringConfiguration] = Action{ + Name: "DeleteBucketIntelligentTieringConfiguration", + Service: "s3", + } + ActionMap[ActionPutBucketInventoryConfiguration] = Action{ + Name: "PutBucketInventoryConfiguration", + Service: "s3", + } + ActionMap[ActionGetBucketInventoryConfiguration] = Action{ + Name: "GetBucketInventoryConfiguration", + Service: "s3", + } + ActionMap[ActionListBucketInventoryConfigurations] = Action{ + Name: "ListBucketInventoryConfigurations", + Service: "s3", + } + ActionMap[ActionDeleteBucketInventoryConfiguration] = Action{ + Name: "DeleteBucketInventoryConfiguration", + Service: "s3", + } + ActionMap[ActionPutBucketLifecycleConfiguration] = Action{ + Name: "PutBucketLifecycleConfiguration", + Service: "s3", + } + ActionMap[ActionGetBucketLifecycleConfiguration] = Action{ + Name: "GetBucketLifecycleConfiguration", + Service: "s3", + } + ActionMap[ActionDeleteBucketLifecycle] = Action{ + Name: "DeleteBucketLifecycle", + Service: "s3", + } + ActionMap[ActionPutBucketLogging] = Action{ + Name: "PutBucketLogging", + Service: "s3", + } + ActionMap[ActionGetBucketLogging] = Action{ + Name: "GetBucketLogging", + Service: "s3", + } + ActionMap[ActionPutBucketRequestPayment] = Action{ + Name: "PutBucketRequestPayment", + Service: "s3", + } + ActionMap[ActionGetBucketRequestPayment] = Action{ + Name: "GetBucketRequestPayment", + Service: "s3", + } + ActionMap[ActionPutBucketMetricsConfiguration] = Action{ + Name: "PutBucketMetricsConfiguration", + Service: "s3", + } + ActionMap[ActionGetBucketMetricsConfiguration] = Action{ + Name: "GetBucketMetricsConfiguration", + Service: "s3", + } + ActionMap[ActionListBucketMetricsConfigurations] = Action{ + Name: "ListBucketMetricsConfigurations", + Service: "s3", + } + ActionMap[ActionDeleteBucketMetricsConfiguration] = Action{ + Name: "DeleteBucketMetricsConfiguration", + Service: "s3", + } + ActionMap[ActionPutBucketReplication] = Action{ + Name: "PutBucketReplication", + Service: "s3", + } + ActionMap[ActionGetBucketReplication] = Action{ + Name: "GetBucketReplication", + Service: "s3", + } + ActionMap[ActionDeleteBucketReplication] = Action{ + Name: "DeleteBucketReplication", + Service: "s3", + } } diff --git a/s3api/router.go b/s3api/router.go index e02cbc3..a7a9c0c 100644 --- a/s3api/router.go +++ b/s3api/router.go @@ -314,6 +314,20 @@ func (sa *S3ApiRouter) Init(app *fiber.App, be backend.Backend, iam auth.IAMServ middlewares.ParseAcl(be), ), ) + bucketRouter.Put("", + middlewares.MatchQueryArgs("replication"), + controllers.ProcessHandlers( + ctrl.HandleErrorRoute(s3err.GetAPIError(s3err.ErrNotImplemented)), + metrics.ActionPutBucketReplication, + services, + middlewares.BucketObjectNameValidator(), + middlewares.AuthorizePublicBucketAccess(be, metrics.ActionPutBucketReplication, auth.PutReplicationConfigurationAction, auth.PermissionWrite), + middlewares.VerifyPresignedV4Signature(root, iam, region, debug), + middlewares.VerifyV4Signature(root, iam, region, debug), + middlewares.VerifyMD5Body(), + middlewares.ParseAcl(be), + ), + ) bucketRouter.Put("", controllers.ProcessHandlers( ctrl.CreateBucket, @@ -484,6 +498,20 @@ func (sa *S3ApiRouter) Init(app *fiber.App, be backend.Backend, iam auth.IAMServ middlewares.ParseAcl(be), ), ) + bucketRouter.Delete("", + middlewares.MatchQueryArgs("replication"), + controllers.ProcessHandlers( + ctrl.HandleErrorRoute(s3err.GetAPIError(s3err.ErrNotImplemented)), + metrics.ActionDeleteBucketReplication, + services, + middlewares.BucketObjectNameValidator(), + middlewares.AuthorizePublicBucketAccess(be, metrics.ActionDeleteBucketReplication, auth.PutReplicationConfigurationAction, auth.PermissionWrite), + middlewares.VerifyPresignedV4Signature(root, iam, region, debug), + middlewares.VerifyV4Signature(root, iam, region, debug), + middlewares.VerifyMD5Body(), + middlewares.ParseAcl(be), + ), + ) bucketRouter.Delete("", controllers.ProcessHandlers( ctrl.DeleteBucket, @@ -793,6 +821,20 @@ func (sa *S3ApiRouter) Init(app *fiber.App, be backend.Backend, iam auth.IAMServ middlewares.ParseAcl(be), ), ) + bucketRouter.Get("", + middlewares.MatchQueryArgs("replication"), + controllers.ProcessHandlers( + ctrl.HandleErrorRoute(s3err.GetAPIError(s3err.ErrNotImplemented)), + metrics.ActionGetBucketReplication, + services, + middlewares.BucketObjectNameValidator(), + middlewares.AuthorizePublicBucketAccess(be, metrics.ActionGetBucketReplication, auth.GetReplicationConfigurationAction, auth.PermissionRead), + middlewares.VerifyPresignedV4Signature(root, iam, region, debug), + middlewares.VerifyV4Signature(root, iam, region, debug), + middlewares.VerifyMD5Body(), + middlewares.ParseAcl(be), + ), + ) bucketRouter.Get("", middlewares.MatchQueryArgWithValue("list-type", "2"), controllers.ProcessHandlers( diff --git a/tests/integration/group-tests.go b/tests/integration/group-tests.go index 816187a..eb8bbc1 100644 --- a/tests/integration/group-tests.go +++ b/tests/integration/group-tests.go @@ -655,6 +655,10 @@ func TestNotImplementedActions(s *S3Conf) { GetBucketMetricsConfiguration_not_implemented(s) ListBucketMetricsConfigurations_not_implemented(s) DeleteBucketMetricsConfiguration_not_implemented(s) + // bucket replication actions + PutBucketReplication_not_implemented(s) + GetBucketReplication_not_implemented(s) + DeleteBucketReplication_not_implemented(s) } func TestWORMProtection(s *S3Conf) { @@ -1414,6 +1418,9 @@ func GetIntTests() IntTests { "GetBucketMetricsConfiguration_not_implemented": GetBucketMetricsConfiguration_not_implemented, "ListBucketMetricsConfigurations_not_implemented": ListBucketMetricsConfigurations_not_implemented, "DeleteBucketMetricsConfiguration_not_implemented": DeleteBucketMetricsConfiguration_not_implemented, + "PutBucketReplication_not_implemented": PutBucketReplication_not_implemented, + "GetBucketReplication_not_implemented": GetBucketReplication_not_implemented, + "DeleteBucketReplication_not_implemented": DeleteBucketReplication_not_implemented, "WORMProtection_bucket_object_lock_configuration_compliance_mode": WORMProtection_bucket_object_lock_configuration_compliance_mode, "WORMProtection_bucket_object_lock_configuration_governance_mode": WORMProtection_bucket_object_lock_configuration_governance_mode, "WORMProtection_bucket_object_lock_governance_bypass_delete": WORMProtection_bucket_object_lock_governance_bypass_delete, diff --git a/tests/integration/tests.go b/tests/integration/tests.go index 643a3ce..d8c8e9e 100644 --- a/tests/integration/tests.go +++ b/tests/integration/tests.go @@ -15832,6 +15832,63 @@ func DeleteBucketMetricsConfiguration_not_implemented(s *S3Conf) error { }) } +func PutBucketReplication_not_implemented(s *S3Conf) error { + testName := "PutBucketReplication_not_implemented" + return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error { + ctx, cancel := context.WithTimeout(context.Background(), shortTimeout) + _, err := s3client.PutBucketReplication(ctx, + &s3.PutBucketReplicationInput{ + Bucket: &bucket, + ReplicationConfiguration: &types.ReplicationConfiguration{ + Role: getPtr("arn:aws:iam::35667example:role/CrossRegionReplicationRoleForS3"), + Rules: []types.ReplicationRule{ + { + Destination: &types.Destination{ + Bucket: &bucket, + AccessControlTranslation: &types.AccessControlTranslation{ + Owner: types.OwnerOverrideDestination, + }, + Account: getPtr("grt1"), + }, + Status: types.ReplicationRuleStatusEnabled, + }, + }, + }, + }) + cancel() + + return checkApiErr(err, s3err.GetAPIError(s3err.ErrNotImplemented)) + }) +} + +func GetBucketReplication_not_implemented(s *S3Conf) error { + testName := "GetBucketReplication_not_implemented" + return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error { + ctx, cancel := context.WithTimeout(context.Background(), shortTimeout) + _, err := s3client.GetBucketReplication(ctx, + &s3.GetBucketReplicationInput{ + Bucket: &bucket, + }) + cancel() + + return checkApiErr(err, s3err.GetAPIError(s3err.ErrNotImplemented)) + }) +} + +func DeleteBucketReplication_not_implemented(s *S3Conf) error { + testName := "DeleteBucketReplication_not_implemented" + return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error { + ctx, cancel := context.WithTimeout(context.Background(), shortTimeout) + _, err := s3client.DeleteBucketReplication(ctx, + &s3.DeleteBucketReplicationInput{ + Bucket: &bucket, + }) + cancel() + + return checkApiErr(err, s3err.GetAPIError(s3err.ErrNotImplemented)) + }) +} + func WORMProtection_bucket_object_lock_configuration_compliance_mode(s *S3Conf) error { testName := "WORMProtection_bucket_object_lock_configuration_compliance_mode" return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {