Skip to content

Commit

Permalink
fix: make policy docs executable on jupyter environments
Browse files Browse the repository at this point in the history
The docs about policy only ran on pytest
  • Loading branch information
fczuardi committed Jan 29, 2025
1 parent 66cd9d5 commit d050a8b
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 13 deletions.
12 changes: 11 additions & 1 deletion docs/policies_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,20 @@
# que podem ser executadas em um bucket ou objeto, e por quais contas ("Principals"), seja para
# **conceder** mais acessos a determinados recursos, e para quais contas.

# + tags=["parameters"]
config = "../params/br-ne1.yaml"
# -

# + {"jupyter": {"source_hidden": true}}
import os
import pytest
import logging
from botocore.exceptions import ClientError
from s3_helpers import(
run_example,
change_policies_json,
)

config = os.getenv("CONFIG", config)
pytestmark = pytest.mark.policy
# -

Expand Down Expand Up @@ -107,6 +113,7 @@ def test_put_invalid_bucket_policy(s3_client, existing_bucket_name, input, expec
except ClientError as e:
# Assert the error code matches the expected one
assert e.response['Error']['Code'] == expected_error
run_example(__name__, "test_put_invalid_bucket_policy", config=config)


@pytest.mark.parametrize('policies_args', [
Expand All @@ -121,6 +128,7 @@ def test_setup_policies(s3_client, existing_bucket_name, policies_args):
policies = change_policies_json(existing_bucket_name, policies_args, "*")
response = s3_client.put_bucket_policy(Bucket=bucket_name, Policy=policies)
assert response['ResponseMetadata']['HTTPStatusCode'] == 204
run_example(__name__, "test_setup_policies", config=config)

# ## Negar operações específicas em objetos
#
Expand Down Expand Up @@ -155,6 +163,7 @@ def test_denied_policy_operations_by_owner(s3_client, bucket_with_one_object_pol
except ClientError as e:
logging.info(f"Method error response:{e.response}")
assert e.response['Error']['Code'] == 'AccessDeniedByBucketPolicy'
run_example(__name__, "test_denied_policy_operations_by_owner", config=config)

# ## Permitir operações específicas em objetos
#
Expand Down Expand Up @@ -184,3 +193,4 @@ def test_allow_policy_operations_by_owner(multiple_s3_clients, bucket_with_one_o
method = getattr(multiple_s3_clients[0], boto3_action)
response = method(**kwargs)
assert response['ResponseMetadata']['HTTPStatusCode'] == expected
run_example(__name__, "test_allow_policy_operations_by_owner", config=config)
26 changes: 21 additions & 5 deletions docs/profiles_policies_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,25 @@
# language_info:
# name: python
# ---

# # Bucket Policy (parte 2)
#
# Documentação complementar à `policies_test`.
# Testes similares aos dois últimos de lá, com a principal diferença sendo que o perfil que vai
# testar o efeito das políticas é um diferente do da dona do bucket (`s3_clients_list[1]`) nos
# exemplos abaixo:

# + tags=["parameters"]
config = "../params/br-ne1.yaml"
# -

# + {"jupyter": {"source_hidden": true}}
import os
import pytest
from botocore.exceptions import ClientError
from s3_helpers import(run_example)
config = os.getenv("CONFIG", config)
pytestmark = pytest.mark.policy

policy_dict_template = {
"Version": "2012-10-17",
Expand All @@ -21,11 +38,12 @@
]
}

# -

# Example of the list for actions, tenants, and methods
actions = ["s3:GetObject", "s3:PutObject", "s3:DeleteObject"]
number_clients = 2
methods = ["get_object", "put_object", "delete_object"]
pytestmark = pytest.mark.policy

@pytest.mark.parametrize(
'multiple_s3_clients, bucket_with_one_object_policy, boto3_action',
Expand All @@ -39,8 +57,6 @@
],
indirect=['bucket_with_one_object_policy', 'multiple_s3_clients'],
)


def test_denied_policy_operations(multiple_s3_clients, bucket_with_one_object_policy, boto3_action):
s3_clients_list = multiple_s3_clients

Expand All @@ -63,6 +79,7 @@ def test_denied_policy_operations(multiple_s3_clients, bucket_with_one_object_po
pytest.fail("Expected exception not raised")
except ClientError as e:
assert e.response['Error']['Code'] == 'AccessDeniedByBucketPolicy'
run_example(__name__, "test_denied_policy_operations", config=config)


expected = [200, 200, 204]
Expand All @@ -80,8 +97,6 @@ def test_denied_policy_operations(multiple_s3_clients, bucket_with_one_object_po
],
indirect=['bucket_with_one_object_policy', 'multiple_s3_clients'],
)


def test_allowed_policy_operations(multiple_s3_clients, bucket_with_one_object_policy, boto3_action, expected):
s3_clients_list = multiple_s3_clients
allowed_client = s3_clients_list[1] # not the bucket owner
Expand All @@ -102,4 +117,5 @@ def test_allowed_policy_operations(multiple_s3_clients, bucket_with_one_object_p
method = getattr(allowed_client, boto3_action)
response = method(**kwargs)
assert response['ResponseMetadata']['HTTPStatusCode'] == expected
run_example(__name__, "test_allowed_policy_operations", config=config)

27 changes: 20 additions & 7 deletions docs/s3_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ def run_example(dunder_name, test_name, config="../params.example.yaml"):
pytest.main([
"-qq",
"--color", "no",
"--pytest-durations", "0",
# "-s",
# "--log-cli-level", "INFO",
f"{get_spec_path()}::{test_name}"
Expand All @@ -52,8 +53,11 @@ def delete_bucket_and_wait(s3_client, bucket_name):
return

waiter = s3_client.get_waiter('bucket_not_exists')
waiter.wait(Bucket=bucket_name)
logging.info(f"Bucket '{bucket_name}' confirmed as deleted.")
try:
waiter.wait(Bucket=bucket_name)
logging.info(f"Bucket '{bucket_name}' confirmed as deleted.")
except Exception as e:
logging.info(f"delete bucket waiter errored with: {e}")

def create_bucket(s3_client, bucket_name):
# anything different than us-east-1 must have LocationConstraint on aws
Expand Down Expand Up @@ -85,7 +89,10 @@ def delete_object_and_wait(s3_client, bucket_name, object_key):
return

waiter = s3_client.get_waiter('object_not_exists')
waiter.wait(Bucket=bucket_name, Key=object_key)
try:
waiter.wait(Bucket=bucket_name, Key=object_key)
except Exception as e:
logging.error(f"delete waiter got error: {e}")
logging.info(f"Object '{object_key}' in bucket '{bucket_name}' confirmed as deleted.")

def delete_all_objects_and_wait(s3_client, bucket_name):
Expand All @@ -94,22 +101,28 @@ def delete_all_objects_and_wait(s3_client, bucket_name):
for obj in response['Contents']:
delete_object_and_wait(s3_client, bucket_name, obj['Key'])

def delete_policy_and_bucket_and_wait(s3_client, bucket_name, request):
def delete_policy_and_bucket_and_wait(s3_client, bucket_name, policy_wait_time, request):
retries = 3
sleeptime = 1
for _ in range(retries):
sleeptime = 5
for attempt_number in range(retries):
try:
change_policies_json(bucket_name, {"policy_dict": request.param['policy_dict'], "actions": ["s3:GetObjects", "*"], "effect": "Allow"}, tenants=["*"])
logging.info(f"deleting policy of bucket {bucket_name}...")
s3_client.delete_bucket_policy(Bucket=bucket_name)
break
except s3_client.exceptions.ClientError as e:
if e.response['Error']['Code'] == 'NoSuchBucketPolicy':
logging.info(f"No policy found for bucket '{bucket_name}'.")
break
else:
time.sleep(sleeptime)
time.sleep(sleeptime * attempt_number)
continue

logging.info(f"waiting for policy delete to propagate, {policy_wait_time} seconds")
time.sleep(policy_wait_time)
logging.info(f"deleting all objects...")
delete_all_objects_and_wait(s3_client, bucket_name)
logging.info(f"deleting bucket...")
delete_bucket_and_wait(s3_client, bucket_name)

def put_object_and_wait(s3_client, bucket_name, object_key, content):
Expand Down

0 comments on commit d050a8b

Please sign in to comment.