Skip to content

S3BucketConfig

Bases: BaseModel, NameValidationMixin

Configuration model for S3 bucket creation.

Comprehensive configuration model that defines all aspects of an S3 bucket including encryption settings, versioning, cross-account access, and optimization for specific use cases like log storage.

This model validates bucket configuration parameters, ensures proper naming conventions, and enforces organizational standards for S3 deployments including security settings and cross-account integration patterns.

Attributes:

Name Type Description
use_kms_key bool

Enable KMS encryption for enhanced security compliance

versioned bool

Enable object versioning for data protection and recovery

is_for_logs bool

Optimize bucket configuration for log file storage patterns

bucket_base_name str

Base identifier for the bucket following naming conventions

cross_account_role str

IAM role name in target account for cross-account deployments

target_env_name str

Environment name for cross-account role resolution

include_dummy_index bool

Create placeholder index.html file during bucket creation

use_foundation_key bool

Use organizational KMS key from foundation infrastructure

folder_structure Optional[Dict[str, List[str]]]

Initial folders structure for the S3 bucket

Source code in mare_aws_common_lib/models/s3_bucket_config.py
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
class S3BucketConfig(BaseModel, NameValidationMixin):
    """Configuration model for S3 bucket creation.

    Comprehensive configuration model that defines all aspects of an S3 bucket
    including encryption settings, versioning, cross-account access, and
    optimization for specific use cases like log storage.

    This model validates bucket configuration parameters, ensures proper naming
    conventions, and enforces organizational standards for S3 deployments
    including security settings and cross-account integration patterns.

    Attributes:
        use_kms_key: Enable KMS encryption for enhanced security compliance
        versioned: Enable object versioning for data protection and recovery
        is_for_logs: Optimize bucket configuration for log file storage patterns
        bucket_base_name: Base identifier for the bucket following naming conventions
        cross_account_role: IAM role name in target account for cross-account deployments
        target_env_name: Environment name for cross-account role resolution
        include_dummy_index: Create placeholder index.html file during bucket creation
        use_foundation_key: Use organizational KMS key from foundation infrastructure
        folder_structure: Initial folders structure for the S3 bucket
    """
    model_config = ConfigDict(extra="forbid")

    use_kms_key: bool = Field(default=False, description="Whether to use KMS encryption")
    versioned: bool = Field(default=False, description="Whether to enable versioning")
    is_for_logs: bool = Field(default=False, description="Whether the bucket is for log storage")
    bucket_base_name: str = Field(..., min_length=1, description="Base name for the bucket")
    cross_account_role: str = Field(None, description="The cross account cloudformation deployer role name")
    target_env_name: str = Field(None, description="The target environment name to be used with the deployer role")
    include_dummy_index: bool = Field(default=False, description="whether to create a dummy index file at the bucket creation time")
    use_foundation_key: bool = Field(default=True, description="Whether to use the KMS SNC key from the foundation")
    folder_structure: Optional[Dict[str, List[str]]] = Field(
        default=None,
        description="Dictionary mapping parent folders to lists of subfolders. Use empty list [] for top-level folders."
    )
    lifecycle_rule: Optional[Dict[str, int]] = Field(
        default=None,
        description="Simple lifecycle configuration with expiration_days and/or abort_incomplete_multipart_upload_days"
    )

    @field_validator('bucket_base_name')
    @classmethod
    def validate_bucket_name(cls, value: str) -> str:
        """Validate the bucket base name.

        Applies validation rules to bucket naming to ensure the 
        name meets AWS requirements and organizational standards.

        Args:
            value: Raw bucket base name from configuration

        Returns:
            Validated bucket base name

        Raises:
            ValueError: If the bucket name fails validation rules
        """
        return cls.validate_name(value)

    @model_validator(mode="after")
    def validate_cross_account_and_env(self) -> 'S3BucketConfig':
        """
        Validate consistency between `cross_account_role` and `target_env_name`.

        Both fields must either be provided together or both omitted.

        Raises:
            ValueError: If exactly one of `cross_account_role` or `target_env_name` is None.

        Returns:
            The validated model instance with unchanged values.
        """
        if (self.cross_account_role is None) ^ (self.target_env_name is None):
            raise ValueError("cross_account_role and target_env_name must both be provided or both be None.")
        return self

    @field_validator('folder_structure')
    @classmethod
    def validate_folder_structure(cls, value: Optional[Dict[str, List[str]]]) -> Optional[Dict[str, List[str]]]:
        """Validate folder structure dictionary.

        Ensures parent folder keys are properly formatted and subfolder values are lists.
        Empty lists are allowed to create top-level folders without subfolders.

        Args:
            value: Dictionary mapping parent folders to subfolders (can be empty list)

        Returns:
            Validated folder structure dictionary

        Raises:
            ValueError: If folder structure format is invalid
        """
        if value is None:
            return None

        for parent, subfolders in value.items():
            if not isinstance(subfolders, list):
                raise ValueError(f"Subfolders for '{parent}' must be a list (use [] for top-level folders)")

        return value

    @field_validator('lifecycle_rule')
    @classmethod
    def validate_lifecycle_rule(cls, value: Optional[Dict[str, int]]) -> Optional[Dict[str, int]]:
        """Validate lifecycle rules dictionary.

        Accepts a simple dict with:
        - expiration_days: int (days until objects expire)
        - abort_incomplete_multipart_upload_days: int (days until incomplete uploads abort)

        At least one must be provided if lifecycle_rule is not None.
        """
        if value is None:
            return None

        valid_keys = {"expiration_days", "abort_incomplete_multipart_upload_days"}

        # Check for unknown keys
        unknown_keys = set(value.keys()) - valid_keys
        if unknown_keys:
            raise ValueError(f"Unknown lifecycle rule keys: {unknown_keys}. Valid keys are: {valid_keys}")

        # Check that at least one valid key is present
        if not any(key in value for key in valid_keys):
            raise ValueError(f"lifecycle_rules must contain at least one of: {valid_keys}")

        # Validate values are positive integers
        for key, days in value.items():
            if not isinstance(days, int) or days <= 0:
                raise ValueError(f"{key} must be a positive integer, got: {days}")

        return value

validate_bucket_name(value) classmethod

Validate the bucket base name.

Applies validation rules to bucket naming to ensure the name meets AWS requirements and organizational standards.

Parameters:

Name Type Description Default
value str

Raw bucket base name from configuration

required

Returns:

Type Description
str

Validated bucket base name

Raises:

Type Description
ValueError

If the bucket name fails validation rules

Source code in mare_aws_common_lib/models/s3_bucket_config.py
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
@field_validator('bucket_base_name')
@classmethod
def validate_bucket_name(cls, value: str) -> str:
    """Validate the bucket base name.

    Applies validation rules to bucket naming to ensure the 
    name meets AWS requirements and organizational standards.

    Args:
        value: Raw bucket base name from configuration

    Returns:
        Validated bucket base name

    Raises:
        ValueError: If the bucket name fails validation rules
    """
    return cls.validate_name(value)

validate_cross_account_and_env()

Validate consistency between cross_account_role and target_env_name.

Both fields must either be provided together or both omitted.

Raises:

Type Description
ValueError

If exactly one of cross_account_role or target_env_name is None.

Returns:

Type Description
S3BucketConfig

The validated model instance with unchanged values.

Source code in mare_aws_common_lib/models/s3_bucket_config.py
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
@model_validator(mode="after")
def validate_cross_account_and_env(self) -> 'S3BucketConfig':
    """
    Validate consistency between `cross_account_role` and `target_env_name`.

    Both fields must either be provided together or both omitted.

    Raises:
        ValueError: If exactly one of `cross_account_role` or `target_env_name` is None.

    Returns:
        The validated model instance with unchanged values.
    """
    if (self.cross_account_role is None) ^ (self.target_env_name is None):
        raise ValueError("cross_account_role and target_env_name must both be provided or both be None.")
    return self

validate_folder_structure(value) classmethod

Validate folder structure dictionary.

Ensures parent folder keys are properly formatted and subfolder values are lists. Empty lists are allowed to create top-level folders without subfolders.

Parameters:

Name Type Description Default
value Optional[Dict[str, List[str]]]

Dictionary mapping parent folders to subfolders (can be empty list)

required

Returns:

Type Description
Optional[Dict[str, List[str]]]

Validated folder structure dictionary

Raises:

Type Description
ValueError

If folder structure format is invalid

Source code in mare_aws_common_lib/models/s3_bucket_config.py
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
@field_validator('folder_structure')
@classmethod
def validate_folder_structure(cls, value: Optional[Dict[str, List[str]]]) -> Optional[Dict[str, List[str]]]:
    """Validate folder structure dictionary.

    Ensures parent folder keys are properly formatted and subfolder values are lists.
    Empty lists are allowed to create top-level folders without subfolders.

    Args:
        value: Dictionary mapping parent folders to subfolders (can be empty list)

    Returns:
        Validated folder structure dictionary

    Raises:
        ValueError: If folder structure format is invalid
    """
    if value is None:
        return None

    for parent, subfolders in value.items():
        if not isinstance(subfolders, list):
            raise ValueError(f"Subfolders for '{parent}' must be a list (use [] for top-level folders)")

    return value

validate_lifecycle_rule(value) classmethod

Validate lifecycle rules dictionary.

Accepts a simple dict with: - expiration_days: int (days until objects expire) - abort_incomplete_multipart_upload_days: int (days until incomplete uploads abort)

At least one must be provided if lifecycle_rule is not None.

Source code in mare_aws_common_lib/models/s3_bucket_config.py
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
@field_validator('lifecycle_rule')
@classmethod
def validate_lifecycle_rule(cls, value: Optional[Dict[str, int]]) -> Optional[Dict[str, int]]:
    """Validate lifecycle rules dictionary.

    Accepts a simple dict with:
    - expiration_days: int (days until objects expire)
    - abort_incomplete_multipart_upload_days: int (days until incomplete uploads abort)

    At least one must be provided if lifecycle_rule is not None.
    """
    if value is None:
        return None

    valid_keys = {"expiration_days", "abort_incomplete_multipart_upload_days"}

    # Check for unknown keys
    unknown_keys = set(value.keys()) - valid_keys
    if unknown_keys:
        raise ValueError(f"Unknown lifecycle rule keys: {unknown_keys}. Valid keys are: {valid_keys}")

    # Check that at least one valid key is present
    if not any(key in value for key in valid_keys):
        raise ValueError(f"lifecycle_rules must contain at least one of: {valid_keys}")

    # Validate values are positive integers
    for key, days in value.items():
        if not isinstance(days, int) or days <= 0:
            raise ValueError(f"{key} must be a positive integer, got: {days}")

    return value
Example
from mare_aws_common_lib.models import S3BucketConfig

config = S3BucketConfig(
    bucket_base_name="my-data",
    versioned=True,
    use_kms_key=True,
    is_for_logs=False,
    folder_structure={
        "my_empty_folder": [],
        "other_folder": ["sub-folder-1", "sub-folder-2"]
    },
    lifecycle_rule={
        "expiration_days": 1,
        "abort_incomplete_multipart_upload_days": 1
    }
)