// Copyright 2024 RustFS Team // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //! Regression test for Issue #1423 //! Verifies that Bucket Policies are honored for Authenticated Users. use crate::common::{AdminTransport, RustFSTestEnvironment, admin_create_user_via, init_logging}; use aws_sdk_s3::Client; use aws_sdk_s3::error::ProvideErrorMetadata; use tracing::info; /// This suite deliberately drives the admin API through the external `awscurl` /// binary, so user creation pins `AdminTransport::Awscurl`. async fn create_user( env: &RustFSTestEnvironment, username: &str, password: &str, ) -> Result<(), Box> { admin_create_user_via(AdminTransport::Awscurl, &env.url, &env.access_key, &env.secret_key, username, password).await } fn create_user_client(env: &RustFSTestEnvironment, access_key: &str, secret_key: &str) -> Client { env.create_s3_client_with_credentials(access_key, secret_key) } #[tokio::test] async fn test_bucket_policy_authenticated_user() -> Result<(), Box> { init_logging(); info!("Starting test_bucket_policy_authenticated_user..."); let mut env = RustFSTestEnvironment::new().await?; env.start_rustfs_server(vec![]).await?; let admin_client = env.create_s3_client(); let bucket_name = "bucket-policy-auth-test"; let object_key = "test-object.txt"; let user_access = "testuser"; let user_secret = "testpassword"; // 1. Create Bucket (Admin) admin_client.create_bucket().bucket(bucket_name).send().await?; // 2. Create User (Admin API) create_user(&env, user_access, user_secret).await?; // 3. Create User Client let user_client = create_user_client(&env, user_access, user_secret); // 4. Verify Access Denied initially (No Policy) let denied = user_client .list_objects_v2() .bucket(bucket_name) .send() .await .expect_err("a user without a bucket policy must be denied"); assert_eq!(denied.raw_response().map(|response| response.status().as_u16()), Some(403)); assert_eq!(denied.as_service_error().and_then(ProvideErrorMetadata::code), Some("AccessDenied")); // 5. Apply Bucket Policy Allowed User let policy_json = serde_json::json!({ "Version": "2012-10-17", "Statement": [ { "Sid": "AllowTestUser", "Effect": "Allow", "Principal": { "AWS": [user_access] }, "Action": [ "s3:ListBucket", "s3:GetObject", "s3:PutObject", "s3:DeleteObject" ], "Resource": [ format!("arn:aws:s3:::{}", bucket_name), format!("arn:aws:s3:::{}/*", bucket_name) ] } ] }) .to_string(); admin_client .put_bucket_policy() .bucket(bucket_name) .policy(&policy_json) .send() .await?; // 6. Verify Access Allowed (With Bucket Policy) info!("Verifying PutObject..."); user_client .put_object() .bucket(bucket_name) .key(object_key) .body(aws_sdk_s3::primitives::ByteStream::from_static(b"hello world")) .send() .await .map_err(|e| format!("PutObject failed: {}", e))?; info!("Verifying ListObjects..."); let list_res = user_client .list_objects_v2() .bucket(bucket_name) .send() .await .map_err(|e| format!("ListObjects failed: {}", e))?; assert_eq!(list_res.contents().len(), 1); info!("Verifying GetObject..."); user_client .get_object() .bucket(bucket_name) .key(object_key) .send() .await .map_err(|e| format!("GetObject failed: {}", e))?; info!("Verifying DeleteObject..."); user_client .delete_object() .bucket(bucket_name) .key(object_key) .send() .await .map_err(|e| format!("DeleteObject failed: {}", e))?; info!("Test Passed!"); Ok(()) }