263 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
		
		
			
		
	
	
			263 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
|  | import boto3 | ||
|  | from botocore.client import ClientError | ||
|  | 
 | ||
|  | from moto.s3.responses import DEFAULT_REGION_NAME | ||
|  | import pytest | ||
|  | 
 | ||
|  | import sure  # noqa # pylint: disable=unused-import | ||
|  | 
 | ||
|  | from moto import mock_s3 | ||
|  | 
 | ||
|  | 
 | ||
|  | @mock_s3 | ||
|  | def test_put_bucket_logging(): | ||
|  |     s3 = boto3.client("s3", region_name=DEFAULT_REGION_NAME) | ||
|  |     bucket_name = "mybucket" | ||
|  |     log_bucket = "logbucket" | ||
|  |     wrong_region_bucket = "wrongregionlogbucket" | ||
|  |     s3.create_bucket(Bucket=bucket_name) | ||
|  |     s3.create_bucket(Bucket=log_bucket)  # Adding the ACL for log-delivery later... | ||
|  |     s3.create_bucket( | ||
|  |         Bucket=wrong_region_bucket, | ||
|  |         CreateBucketConfiguration={"LocationConstraint": "us-west-2"}, | ||
|  |     ) | ||
|  | 
 | ||
|  |     # No logging config: | ||
|  |     result = s3.get_bucket_logging(Bucket=bucket_name) | ||
|  |     assert not result.get("LoggingEnabled") | ||
|  | 
 | ||
|  |     # A log-bucket that doesn't exist: | ||
|  |     with pytest.raises(ClientError) as err: | ||
|  |         s3.put_bucket_logging( | ||
|  |             Bucket=bucket_name, | ||
|  |             BucketLoggingStatus={ | ||
|  |                 "LoggingEnabled": {"TargetBucket": "IAMNOTREAL", "TargetPrefix": ""} | ||
|  |             }, | ||
|  |         ) | ||
|  |     assert err.value.response["Error"]["Code"] == "InvalidTargetBucketForLogging" | ||
|  | 
 | ||
|  |     # A log-bucket that's missing the proper ACLs for LogDelivery: | ||
|  |     with pytest.raises(ClientError) as err: | ||
|  |         s3.put_bucket_logging( | ||
|  |             Bucket=bucket_name, | ||
|  |             BucketLoggingStatus={ | ||
|  |                 "LoggingEnabled": {"TargetBucket": log_bucket, "TargetPrefix": ""} | ||
|  |             }, | ||
|  |         ) | ||
|  |     assert err.value.response["Error"]["Code"] == "InvalidTargetBucketForLogging" | ||
|  |     assert "log-delivery" in err.value.response["Error"]["Message"] | ||
|  | 
 | ||
|  |     # Add the proper "log-delivery" ACL to the log buckets: | ||
|  |     bucket_owner = s3.get_bucket_acl(Bucket=log_bucket)["Owner"] | ||
|  |     for bucket in [log_bucket, wrong_region_bucket]: | ||
|  |         s3.put_bucket_acl( | ||
|  |             Bucket=bucket, | ||
|  |             AccessControlPolicy={ | ||
|  |                 "Grants": [ | ||
|  |                     { | ||
|  |                         "Grantee": { | ||
|  |                             "URI": "http://acs.amazonaws.com/groups/s3/LogDelivery", | ||
|  |                             "Type": "Group", | ||
|  |                         }, | ||
|  |                         "Permission": "WRITE", | ||
|  |                     }, | ||
|  |                     { | ||
|  |                         "Grantee": { | ||
|  |                             "URI": "http://acs.amazonaws.com/groups/s3/LogDelivery", | ||
|  |                             "Type": "Group", | ||
|  |                         }, | ||
|  |                         "Permission": "READ_ACP", | ||
|  |                     }, | ||
|  |                     { | ||
|  |                         "Grantee": {"Type": "CanonicalUser", "ID": bucket_owner["ID"]}, | ||
|  |                         "Permission": "FULL_CONTROL", | ||
|  |                     }, | ||
|  |                 ], | ||
|  |                 "Owner": bucket_owner, | ||
|  |             }, | ||
|  |         ) | ||
|  | 
 | ||
|  |     # A log-bucket that's in the wrong region: | ||
|  |     with pytest.raises(ClientError) as err: | ||
|  |         s3.put_bucket_logging( | ||
|  |             Bucket=bucket_name, | ||
|  |             BucketLoggingStatus={ | ||
|  |                 "LoggingEnabled": { | ||
|  |                     "TargetBucket": wrong_region_bucket, | ||
|  |                     "TargetPrefix": "", | ||
|  |                 } | ||
|  |             }, | ||
|  |         ) | ||
|  |     assert err.value.response["Error"]["Code"] == "CrossLocationLoggingProhibitted" | ||
|  | 
 | ||
|  |     # Correct logging: | ||
|  |     s3.put_bucket_logging( | ||
|  |         Bucket=bucket_name, | ||
|  |         BucketLoggingStatus={ | ||
|  |             "LoggingEnabled": { | ||
|  |                 "TargetBucket": log_bucket, | ||
|  |                 "TargetPrefix": f"{bucket_name}/", | ||
|  |             } | ||
|  |         }, | ||
|  |     ) | ||
|  |     result = s3.get_bucket_logging(Bucket=bucket_name) | ||
|  |     assert result["LoggingEnabled"]["TargetBucket"] == log_bucket | ||
|  |     assert result["LoggingEnabled"]["TargetPrefix"] == f"{bucket_name}/" | ||
|  |     assert not result["LoggingEnabled"].get("TargetGrants") | ||
|  | 
 | ||
|  |     # And disabling: | ||
|  |     s3.put_bucket_logging(Bucket=bucket_name, BucketLoggingStatus={}) | ||
|  |     assert not s3.get_bucket_logging(Bucket=bucket_name).get("LoggingEnabled") | ||
|  | 
 | ||
|  |     # And enabling with multiple target grants: | ||
|  |     s3.put_bucket_logging( | ||
|  |         Bucket=bucket_name, | ||
|  |         BucketLoggingStatus={ | ||
|  |             "LoggingEnabled": { | ||
|  |                 "TargetBucket": log_bucket, | ||
|  |                 "TargetPrefix": f"{bucket_name}/", | ||
|  |                 "TargetGrants": [ | ||
|  |                     { | ||
|  |                         "Grantee": { | ||
|  |                             "ID": "SOMEIDSTRINGHERE9238748923734823917498237489237409123840983274", | ||
|  |                             "Type": "CanonicalUser", | ||
|  |                         }, | ||
|  |                         "Permission": "READ", | ||
|  |                     }, | ||
|  |                     { | ||
|  |                         "Grantee": { | ||
|  |                             "ID": "SOMEIDSTRINGHERE9238748923734823917498237489237409123840983274", | ||
|  |                             "Type": "CanonicalUser", | ||
|  |                         }, | ||
|  |                         "Permission": "WRITE", | ||
|  |                     }, | ||
|  |                 ], | ||
|  |             } | ||
|  |         }, | ||
|  |     ) | ||
|  | 
 | ||
|  |     result = s3.get_bucket_logging(Bucket=bucket_name) | ||
|  |     assert len(result["LoggingEnabled"]["TargetGrants"]) == 2 | ||
|  |     assert ( | ||
|  |         result["LoggingEnabled"]["TargetGrants"][0]["Grantee"]["ID"] | ||
|  |         == "SOMEIDSTRINGHERE9238748923734823917498237489237409123840983274" | ||
|  |     ) | ||
|  | 
 | ||
|  |     # Test with just 1 grant: | ||
|  |     s3.put_bucket_logging( | ||
|  |         Bucket=bucket_name, | ||
|  |         BucketLoggingStatus={ | ||
|  |             "LoggingEnabled": { | ||
|  |                 "TargetBucket": log_bucket, | ||
|  |                 "TargetPrefix": f"{bucket_name}/", | ||
|  |                 "TargetGrants": [ | ||
|  |                     { | ||
|  |                         "Grantee": { | ||
|  |                             "ID": "SOMEIDSTRINGHERE9238748923734823917498237489237409123840983274", | ||
|  |                             "Type": "CanonicalUser", | ||
|  |                         }, | ||
|  |                         "Permission": "READ", | ||
|  |                     } | ||
|  |                 ], | ||
|  |             } | ||
|  |         }, | ||
|  |     ) | ||
|  |     result = s3.get_bucket_logging(Bucket=bucket_name) | ||
|  |     assert len(result["LoggingEnabled"]["TargetGrants"]) == 1 | ||
|  | 
 | ||
|  |     # With an invalid grant: | ||
|  |     with pytest.raises(ClientError) as err: | ||
|  |         s3.put_bucket_logging( | ||
|  |             Bucket=bucket_name, | ||
|  |             BucketLoggingStatus={ | ||
|  |                 "LoggingEnabled": { | ||
|  |                     "TargetBucket": log_bucket, | ||
|  |                     "TargetPrefix": f"{bucket_name}/", | ||
|  |                     "TargetGrants": [ | ||
|  |                         { | ||
|  |                             "Grantee": { | ||
|  |                                 "ID": "SOMEIDSTRINGHERE9238748923734823917498237489237409123840983274", | ||
|  |                                 "Type": "CanonicalUser", | ||
|  |                             }, | ||
|  |                             "Permission": "NOTAREALPERM", | ||
|  |                         } | ||
|  |                     ], | ||
|  |                 } | ||
|  |             }, | ||
|  |         ) | ||
|  |     assert err.value.response["Error"]["Code"] == "MalformedXML" | ||
|  | 
 | ||
|  | 
 | ||
|  | @mock_s3 | ||
|  | def test_log_file_is_created(): | ||
|  |     # Create necessary buckets | ||
|  |     s3 = boto3.client("s3", region_name=DEFAULT_REGION_NAME) | ||
|  |     bucket_name = "mybucket" | ||
|  |     log_bucket = "logbucket" | ||
|  |     s3.create_bucket(Bucket=bucket_name) | ||
|  |     s3.create_bucket(Bucket=log_bucket) | ||
|  | 
 | ||
|  |     # Enable logging | ||
|  |     bucket_owner = s3.get_bucket_acl(Bucket=log_bucket)["Owner"] | ||
|  |     s3.put_bucket_acl( | ||
|  |         Bucket=log_bucket, | ||
|  |         AccessControlPolicy={ | ||
|  |             "Grants": [ | ||
|  |                 { | ||
|  |                     "Grantee": { | ||
|  |                         "URI": "http://acs.amazonaws.com/groups/s3/LogDelivery", | ||
|  |                         "Type": "Group", | ||
|  |                     }, | ||
|  |                     "Permission": "WRITE", | ||
|  |                 }, | ||
|  |                 { | ||
|  |                     "Grantee": { | ||
|  |                         "URI": "http://acs.amazonaws.com/groups/s3/LogDelivery", | ||
|  |                         "Type": "Group", | ||
|  |                     }, | ||
|  |                     "Permission": "READ_ACP", | ||
|  |                 }, | ||
|  |                 { | ||
|  |                     "Grantee": {"Type": "CanonicalUser", "ID": bucket_owner["ID"]}, | ||
|  |                     "Permission": "FULL_CONTROL", | ||
|  |                 }, | ||
|  |             ], | ||
|  |             "Owner": bucket_owner, | ||
|  |         }, | ||
|  |     ) | ||
|  |     s3.put_bucket_logging( | ||
|  |         Bucket=bucket_name, | ||
|  |         BucketLoggingStatus={ | ||
|  |             "LoggingEnabled": { | ||
|  |                 "TargetBucket": log_bucket, | ||
|  |                 "TargetPrefix": f"{bucket_name}/", | ||
|  |             } | ||
|  |         }, | ||
|  |     ) | ||
|  | 
 | ||
|  |     # Make some requests against the source bucket | ||
|  |     s3.put_object(Bucket=bucket_name, Key="key1", Body=b"") | ||
|  |     s3.put_object(Bucket=bucket_name, Key="key2", Body=b"data") | ||
|  | 
 | ||
|  |     s3.put_bucket_logging( | ||
|  |         Bucket=bucket_name, | ||
|  |         BucketLoggingStatus={ | ||
|  |             "LoggingEnabled": {"TargetBucket": log_bucket, "TargetPrefix": ""} | ||
|  |         }, | ||
|  |     ) | ||
|  |     s3.list_objects_v2(Bucket=bucket_name) | ||
|  | 
 | ||
|  |     # Verify files are created in the target (logging) bucket | ||
|  |     keys = [k["Key"] for k in s3.list_objects_v2(Bucket=log_bucket)["Contents"]] | ||
|  |     [k for k in keys if k.startswith("mybucket/")].should.have.length_of(3) | ||
|  |     [k for k in keys if not k.startswith("mybucket/")].should.have.length_of(1) | ||
|  | 
 | ||
|  |     # Verify (roughly) files have the correct content | ||
|  |     contents = [ | ||
|  |         s3.get_object(Bucket=log_bucket, Key=key)["Body"].read().decode("utf-8") | ||
|  |         for key in keys | ||
|  |     ] | ||
|  |     assert any([c for c in contents if bucket_name in c]) | ||
|  |     assert any([c for c in contents if "REST.GET.BUCKET" in c]) | ||
|  |     assert any([c for c in contents if "REST.PUT.BUCKET" in c]) |