pycfmodel 1.1.2__tar.gz → 1.1.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. {pycfmodel-1.1.2 → pycfmodel-1.1.3}/PKG-INFO +5 -1
  2. pycfmodel-1.1.3/pycfmodel/model/base.py +18 -0
  3. pycfmodel-1.1.3/pycfmodel/model/cf_model.py +141 -0
  4. pycfmodel-1.1.3/pycfmodel/model/generic.py +92 -0
  5. pycfmodel-1.1.3/pycfmodel/model/parameter.py +54 -0
  6. pycfmodel-1.1.3/pycfmodel/model/resources/ec2_vpc_endpoint_policy.py +53 -0
  7. pycfmodel-1.1.3/pycfmodel/model/resources/es_domain.py +61 -0
  8. pycfmodel-1.1.3/pycfmodel/model/resources/generic_resource.py +39 -0
  9. pycfmodel-1.1.3/pycfmodel/model/resources/iam_group.py +46 -0
  10. pycfmodel-1.1.3/pycfmodel/model/resources/iam_managed_policy.py +52 -0
  11. pycfmodel-1.1.3/pycfmodel/model/resources/iam_policy.py +48 -0
  12. pycfmodel-1.1.3/pycfmodel/model/resources/iam_role.py +68 -0
  13. pycfmodel-1.1.3/pycfmodel/model/resources/iam_user.py +63 -0
  14. pycfmodel-1.1.3/pycfmodel/model/resources/kms_key.py +50 -0
  15. pycfmodel-1.1.3/pycfmodel/model/resources/opensearch_domain.py +61 -0
  16. pycfmodel-1.1.3/pycfmodel/model/resources/properties/policy.py +17 -0
  17. pycfmodel-1.1.3/pycfmodel/model/resources/properties/policy_document.py +138 -0
  18. pycfmodel-1.1.3/pycfmodel/model/resources/properties/property.py +7 -0
  19. pycfmodel-1.1.3/pycfmodel/model/resources/properties/security_group_egress_prop.py +54 -0
  20. pycfmodel-1.1.3/pycfmodel/model/resources/properties/security_group_ingress_prop.py +78 -0
  21. pycfmodel-1.1.3/pycfmodel/model/resources/properties/statement.py +190 -0
  22. pycfmodel-1.1.3/pycfmodel/model/resources/properties/statement_condition.py +355 -0
  23. pycfmodel-1.1.3/pycfmodel/model/resources/properties/tag.py +22 -0
  24. pycfmodel-1.1.3/pycfmodel/model/resources/properties/types.py +19 -0
  25. pycfmodel-1.1.3/pycfmodel/model/resources/resource.py +90 -0
  26. pycfmodel-1.1.3/pycfmodel/model/resources/s3_bucket.py +70 -0
  27. pycfmodel-1.1.3/pycfmodel/model/resources/s3_bucket_policy.py +38 -0
  28. pycfmodel-1.1.3/pycfmodel/model/resources/security_group.py +73 -0
  29. pycfmodel-1.1.3/pycfmodel/model/resources/security_group_egress.py +44 -0
  30. pycfmodel-1.1.3/pycfmodel/model/resources/security_group_ingress.py +56 -0
  31. pycfmodel-1.1.3/pycfmodel/model/resources/sns_topic_policy.py +38 -0
  32. pycfmodel-1.1.3/pycfmodel/model/resources/sqs_queue_policy.py +38 -0
  33. pycfmodel-1.1.3/pycfmodel/model/resources/types.py +45 -0
  34. pycfmodel-1.1.3/pycfmodel/model/types.py +151 -0
  35. pycfmodel-1.1.3/pycfmodel/model/utils.py +10 -0
  36. {pycfmodel-1.1.2 → pycfmodel-1.1.3}/pycfmodel.egg-info/PKG-INFO +5 -1
  37. pycfmodel-1.1.3/pycfmodel.egg-info/SOURCES.txt +58 -0
  38. {pycfmodel-1.1.2 → pycfmodel-1.1.3}/pyproject.toml +6 -2
  39. pycfmodel-1.1.2/pycfmodel.egg-info/SOURCES.txt +0 -24
  40. {pycfmodel-1.1.2 → pycfmodel-1.1.3}/LICENSE.md +0 -0
  41. {pycfmodel-1.1.2 → pycfmodel-1.1.3}/README.md +0 -0
  42. {pycfmodel-1.1.2 → pycfmodel-1.1.3}/pycfmodel/__init__.py +0 -0
  43. {pycfmodel-1.1.2 → pycfmodel-1.1.3}/pycfmodel/action_expander.py +0 -0
  44. {pycfmodel-1.1.2 → pycfmodel-1.1.3}/pycfmodel/cloudformation_actions.py +0 -0
  45. {pycfmodel-1.1.2 → pycfmodel-1.1.3}/pycfmodel/constants.py +0 -0
  46. {pycfmodel-1.1.2 → pycfmodel-1.1.3}/pycfmodel/resolver.py +0 -0
  47. {pycfmodel-1.1.2 → pycfmodel-1.1.3}/pycfmodel/utils.py +0 -0
  48. {pycfmodel-1.1.2 → pycfmodel-1.1.3}/pycfmodel.egg-info/dependency_links.txt +0 -0
  49. {pycfmodel-1.1.2 → pycfmodel-1.1.3}/pycfmodel.egg-info/requires.txt +0 -0
  50. {pycfmodel-1.1.2 → pycfmodel-1.1.3}/pycfmodel.egg-info/top_level.txt +0 -0
  51. {pycfmodel-1.1.2 → pycfmodel-1.1.3}/setup.cfg +0 -0
  52. {pycfmodel-1.1.2 → pycfmodel-1.1.3}/tests/test_action_expander.py +0 -0
  53. {pycfmodel-1.1.2 → pycfmodel-1.1.3}/tests/test_cf_model.py +0 -0
  54. {pycfmodel-1.1.2 → pycfmodel-1.1.3}/tests/test_constants.py +0 -0
  55. {pycfmodel-1.1.2 → pycfmodel-1.1.3}/tests/test_generic.py +0 -0
  56. {pycfmodel-1.1.2 → pycfmodel-1.1.3}/tests/test_parameter.py +0 -0
  57. {pycfmodel-1.1.2 → pycfmodel-1.1.3}/tests/test_regexs.py +0 -0
  58. {pycfmodel-1.1.2 → pycfmodel-1.1.3}/tests/test_resolver.py +0 -0
  59. {pycfmodel-1.1.2 → pycfmodel-1.1.3}/tests/test_resource.py +0 -0
  60. {pycfmodel-1.1.2 → pycfmodel-1.1.3}/tests/test_types.py +0 -0
  61. {pycfmodel-1.1.2 → pycfmodel-1.1.3}/tests/test_utils.py +0 -0
@@ -1,9 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pycfmodel
3
- Version: 1.1.2
3
+ Version: 1.1.3
4
4
  Summary: A python model for Cloud Formation scripts
5
5
  Author-email: Skyscanner Security <security@skyscanner.net>
6
6
  Project-URL: Homepage, https://github.com/Skyscanner/pycfmodel
7
+ Project-URL: Repository, https://github.com/Skyscanner/pycfmodel
8
+ Project-URL: Bug Tracker, https://github.com/Skyscanner/pycfmodel/issues
9
+ Project-URL: Documentation, https://pycfmodel.readthedocs.io
10
+ Project-URL: Changelog, https://github.com/Skyscanner/pycfmodel/releases
7
11
  Requires-Python: >=3.9.0
8
12
  Description-Content-Type: text/markdown
9
13
  License-File: LICENSE.md
@@ -0,0 +1,18 @@
1
+ from pydantic import BaseModel, ConfigDict, model_validator
2
+
3
+ from pycfmodel.utils import is_resolvable_dict
4
+
5
+
6
+ class CustomModel(BaseModel):
7
+ model_config = ConfigDict(extra="forbid")
8
+
9
+
10
+ class FunctionDict(BaseModel):
11
+ model_config = ConfigDict(extra="allow")
12
+
13
+ @model_validator(mode="before")
14
+ @classmethod
15
+ def check_if_valid_function(cls, values):
16
+ if not is_resolvable_dict(values):
17
+ raise ValueError("FunctionDict should only have 1 key and be a function")
18
+ return values
@@ -0,0 +1,141 @@
1
+ from datetime import date
2
+ from typing import Any, ClassVar, Collection, Dict, List, Optional, Type, Union
3
+
4
+ from pydantic import Field
5
+ from typing_extensions import Annotated
6
+
7
+ from pycfmodel.action_expander import expand_actions
8
+ from pycfmodel.constants import AWS_NOVALUE
9
+ from pycfmodel.model.base import CustomModel
10
+ from pycfmodel.model.parameter import Parameter
11
+ from pycfmodel.model.resources.generic_resource import GenericResource
12
+ from pycfmodel.model.resources.resource import Resource
13
+ from pycfmodel.model.resources.types import ResourceModels
14
+ from pycfmodel.model.types import Resolvable
15
+ from pycfmodel.resolver import _extended_bool, resolve
16
+
17
+ AllResourcesType = Annotated[Union[ResourceModels, GenericResource], Field(union_mode="left_to_right")]
18
+
19
+
20
+ class CFModel(CustomModel):
21
+ """
22
+ Template that describes AWS infrastructure.
23
+
24
+ Properties:
25
+
26
+ - AWSTemplateFormatVersion
27
+ - Conditions: Conditions that control behaviour of the template.
28
+ - Description: Description for the template.
29
+ - Mappings: A 3 level mapping of keys and associated values.
30
+ - Metadata: Additional information about the template.
31
+ - Outputs: Output values of the template.
32
+ - Parameters: Parameters to the template.
33
+ - Resources: Stack resources and their properties.
34
+ - Rules
35
+ - Transform: For serverless applications, specifies the version of the AWS Serverless Application Model (AWS SAM) to use.
36
+
37
+ More info at [AWS Docs](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-anatomy.html)
38
+ """
39
+
40
+ AWSTemplateFormatVersion: Optional[date] = None
41
+ Conditions: Optional[Dict] = {}
42
+ Description: Optional[str] = None
43
+ Mappings: Optional[Dict[str, Dict[str, Dict[str, Any]]]] = {}
44
+ Metadata: Optional[Dict[str, Any]] = None
45
+ Outputs: Optional[Dict[str, Dict[str, Union[str, Dict]]]] = {}
46
+ Parameters: Optional[Dict[str, Parameter]] = {}
47
+ Resources: Dict[str, Resolvable[AllResourcesType]] = {}
48
+ Rules: Optional[Dict] = {}
49
+ Transform: Optional[Union[str, List[str]]] = None
50
+
51
+ PSEUDO_PARAMETERS: ClassVar[Dict[str, Union[str, List[str]]]] = {
52
+ # default pseudo parameters
53
+ "AWS::AccountId": "123456789012",
54
+ "AWS::NotificationARNs": [],
55
+ "AWS::NoValue": AWS_NOVALUE,
56
+ "AWS::Partition": "aws",
57
+ "AWS::Region": "eu-west-1",
58
+ "AWS::StackId": "",
59
+ "AWS::StackName": "",
60
+ "AWS::URLSuffix": "amazonaws.com",
61
+ }
62
+
63
+ def resolve(self, extra_params=None) -> "CFModel":
64
+ """
65
+ Resolve all intrinsic functions on the template.
66
+
67
+ Arguments:
68
+ extra_params: Values of parameters passed to the Cloudformation.
69
+
70
+ Returns:
71
+ A new CFModel.
72
+ """
73
+ extra_params = {} if extra_params is None else extra_params
74
+ # default parameters
75
+ params = {}
76
+ for key, parameter in self.Parameters.items():
77
+ passed_value = extra_params.pop(key, None)
78
+ ref_value = parameter.get_ref_value(passed_value)
79
+ if ref_value is not None:
80
+ params[key] = ref_value
81
+
82
+ extended_parameters = {**self.PSEUDO_PARAMETERS, **params, **extra_params}
83
+ dict_value = self.model_dump()
84
+
85
+ conditions = dict_value.pop("Conditions", {})
86
+ resolved_conditions = {}
87
+ for key, value in conditions.items():
88
+ resolved_conditions.update(
89
+ {key: _extended_bool(resolve(value, extended_parameters, self.Mappings, resolved_conditions))}
90
+ )
91
+
92
+ resources = dict_value.pop("Resources")
93
+ resolved_resources = {
94
+ key: resolve(value, extended_parameters, self.Mappings, resolved_conditions)
95
+ for key, value in resources.items()
96
+ if value.get("Condition") is None
97
+ or (value.get("Condition") is not None and resolved_conditions.get(value["Condition"], True))
98
+ }
99
+ return CFModel(**dict_value, Conditions=resolved_conditions, Resources=resolved_resources)
100
+
101
+ def expand_actions(self) -> "CFModel":
102
+ """
103
+ Returns a model which has expanded all wildcards (`*`) to get all implied actions for every resource.
104
+ For example:\n
105
+ - a model containing `s3:*` will be expanded to list all the possible S3 actions.
106
+ - a model containing `s3:Get*` will be expanded to all the `Get*` actions only.
107
+
108
+ This method can handle the cases of both `Action` and `NotAction`.
109
+
110
+ [Known AWS Actions](https://github.com/Skyscanner/pycfmodel/blob/master/pycfmodel/cloudformation_actions.py).
111
+ These known actions can be updated by executing:
112
+
113
+ ```
114
+ python3 scripts/generate_cloudformation_actions_file.py
115
+ ```
116
+ """
117
+ dict_value = self.model_dump()
118
+
119
+ resources = dict_value.pop("Resources")
120
+ expanded_resources = {key: expand_actions(value) for key, value in resources.items()}
121
+
122
+ return CFModel(**dict_value, Resources=expanded_resources)
123
+
124
+ def resources_filtered_by_type(
125
+ self, allowed_types: Collection[Union[str, Type[Resource]]]
126
+ ) -> Dict[str, Dict[str, Resource]]:
127
+ """
128
+ Filtered resources based on types.
129
+
130
+ Arguments:
131
+ allowed_types: Collection of desired types.
132
+
133
+ Returns:
134
+ Dictionary where key is the logical id and value is the resource.
135
+ """
136
+ result = {}
137
+ allowed_resource_classes = tuple(x for x in allowed_types if isinstance(x, type))
138
+ for resource_name, resource in self.Resources.items():
139
+ if isinstance(resource, allowed_resource_classes) or resource.Type in allowed_types:
140
+ result[resource_name] = resource
141
+ return result
@@ -0,0 +1,92 @@
1
+ import json
2
+ from contextlib import suppress
3
+ from typing import Union
4
+
5
+ from pydantic import BaseModel, ConfigDict, Field, ValidationError, field_validator, model_validator
6
+ from typing_extensions import Annotated
7
+
8
+ from pycfmodel.model.base import FunctionDict
9
+ from pycfmodel.model.resources.properties.types import Properties
10
+ from pycfmodel.model.types import (
11
+ InstanceOrListOf,
12
+ Resolvable,
13
+ ResolvableArnOrList,
14
+ ResolvableBoolOrList,
15
+ ResolvableDateOrList,
16
+ ResolvableDatetimeOrList,
17
+ ResolvableIntOrList,
18
+ ResolvableIPOrList,
19
+ ResolvableStrOrList,
20
+ )
21
+
22
+ AuxType = Annotated[
23
+ Union[
24
+ FunctionDict,
25
+ Properties,
26
+ ResolvableBoolOrList,
27
+ ResolvableIntOrList,
28
+ ResolvableDateOrList,
29
+ ResolvableDatetimeOrList, # Date can be parsed as Datetime in pydantic v2 so should be ordered accordingly
30
+ ResolvableIPOrList,
31
+ ResolvableArnOrList,
32
+ ResolvableStrOrList,
33
+ ],
34
+ Field(union_mode="left_to_right"),
35
+ ]
36
+
37
+
38
+ class _Auxiliar(BaseModel):
39
+ aux: AuxType
40
+
41
+ @field_validator("aux", mode="before")
42
+ @classmethod
43
+ def validate_string_property_formatted_as_json(cls, value):
44
+ """
45
+ We have detected some properties that are defined as String in CloudFormation but including a
46
+ PolicyDocument in them, such as:
47
+ https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-logs-resourcepolicy.html#cfn-logs-resourcepolicy-policydocument
48
+ For that, we try to parse them to a JSON to be evaluated then to a known property.
49
+ If we fail to parse it, it means the property is a String without a JSON in it, we return the property as it is.
50
+ """
51
+ if isinstance(value, str):
52
+ try:
53
+ return json.loads(value)
54
+ except Exception:
55
+ return value
56
+ return value
57
+
58
+ @classmethod
59
+ def cast(cls, value):
60
+ with suppress(ValidationError):
61
+ value = _Auxiliar(aux=value).aux
62
+
63
+ if isinstance(value, list):
64
+ auxiliar_list = []
65
+ for v in value:
66
+ v = _Auxiliar.cast(v)
67
+ if isinstance(v, dict):
68
+ v = Generic.model_validate(v)
69
+ auxiliar_list.append(v)
70
+ value = auxiliar_list
71
+
72
+ if isinstance(value, dict):
73
+ value = Generic.model_validate(value)
74
+
75
+ return value
76
+
77
+
78
+ class Generic(BaseModel):
79
+ """Any property under this class will be cast to an existing model of `pycfmodel` if possible."""
80
+
81
+ model_config = ConfigDict(extra="allow")
82
+
83
+ @model_validator(mode="before")
84
+ @classmethod
85
+ def casting(cls, values):
86
+ if isinstance(values, dict):
87
+ return {k: _Auxiliar.cast(v) for k, v in values.items()}
88
+ raise ValueError(f"Not supported type: {type(values)}")
89
+
90
+
91
+ ResolvableGeneric = Resolvable[Generic]
92
+ ResolvableGenericOrList = InstanceOrListOf[ResolvableGeneric]
@@ -0,0 +1,54 @@
1
+ from typing import Any, ClassVar, List, Optional
2
+
3
+ from pydantic import PositiveInt
4
+
5
+ from pycfmodel.model.base import CustomModel
6
+
7
+
8
+ class Parameter(CustomModel):
9
+ """
10
+ CloudFormation Parameter object representation
11
+ """
12
+
13
+ NO_ECHO_NO_DEFAULT: ClassVar[str] = "NO_ECHO_NO_DEFAULT"
14
+ NO_ECHO_WITH_DEFAULT: ClassVar[str] = "NO_ECHO_WITH_DEFAULT"
15
+ NO_ECHO_WITH_VALUE: ClassVar[str] = "NO_ECHO_WITH_VALUE"
16
+ AllowedPattern: Optional[str] = None
17
+ AllowedValues: Optional[List] = None
18
+ ConstraintDescription: Optional[str] = None
19
+ Default: Optional[Any] = None
20
+ Description: Optional[str] = None
21
+ MaxLength: Optional[PositiveInt] = None
22
+ MaxValue: Optional[PositiveInt] = None
23
+ MinLength: Optional[int] = None
24
+ MinValue: Optional[int] = None
25
+ NoEcho: Optional[bool] = None
26
+ Type: str
27
+
28
+ def get_ref_value(self, provided_value=None) -> Optional[str]:
29
+ """
30
+ Calculates the parameter value to be used in the template.
31
+
32
+ - If `NoEcho` property is set, it uses a constant value.
33
+ - If it is a list of numbers or a comma delimited list, returns the string version of each element in a list.
34
+ - Returns None if `provided_value` and `Default` are `None`.
35
+
36
+ Arguments:
37
+ provided_value: Value injected in the template
38
+
39
+ Returns:
40
+ The computed value.
41
+ """
42
+ value = provided_value if provided_value is not None else self.Default
43
+ if self.NoEcho:
44
+ if provided_value is not None:
45
+ return self.NO_ECHO_WITH_VALUE
46
+ elif self.Default:
47
+ return self.NO_ECHO_WITH_DEFAULT
48
+ else:
49
+ return self.NO_ECHO_NO_DEFAULT
50
+
51
+ elif self.Type in ["List<Number>", "CommaDelimitedList"]:
52
+ return value.split(",")
53
+
54
+ return value if value is None else str(value)
@@ -0,0 +1,53 @@
1
+ from typing import List, Literal, Optional
2
+
3
+ from pycfmodel.model.base import CustomModel
4
+ from pycfmodel.model.resources.properties.policy_document import PolicyDocument as resource_policy_document
5
+ from pycfmodel.model.resources.resource import Resource
6
+ from pycfmodel.model.types import Resolvable, ResolvableBool, ResolvableStr
7
+ from pycfmodel.model.utils import OptionallyNamedPolicyDocument
8
+
9
+
10
+ class EC2VpcEndpointPolicyProperties(CustomModel):
11
+ """
12
+ Properties:
13
+
14
+ - PolicyDocument: A [policy document][pycfmodel.model.resources.properties.policy_document.PolicyDocument] object.
15
+ - PrivateDnsEnabled: Indicate whether to associate a private hosted zone with the specified VPC.
16
+ - RouteTableIds: One or more route table IDs.
17
+ - SecurityGroupIds: The ID of one or more security groups to associate with the endpoint network interface.
18
+ - ServiceName: The service name.
19
+ - SubnetIds: The ID of one or more subnets in which to create an endpoint network interface.
20
+ - VpcEndpointType: The type of endpoint.
21
+ - VpcId: The ID of the VPC in which the endpoint will be used.
22
+
23
+ More info at [AWS Docs](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpcendpoint.html)
24
+ """
25
+
26
+ PolicyDocument: Optional[Resolvable[resource_policy_document]] = None
27
+ PrivateDnsEnabled: Optional[ResolvableBool] = None
28
+ RouteTableIds: Optional[Resolvable[List[ResolvableStr]]] = None
29
+ SecurityGroupIds: Optional[Resolvable[List[ResolvableStr]]] = None
30
+ ServiceName: ResolvableStr
31
+ SubnetIds: Optional[Resolvable[List[ResolvableStr]]] = None
32
+ VpcEndpointType: Optional[ResolvableStr] = None
33
+ VpcId: ResolvableStr
34
+
35
+
36
+ class EC2VpcEndpointPolicy(Resource):
37
+ """
38
+ Properties:
39
+
40
+ - Properties: An [EC2 VPC Policy Endpoint Properties][pycfmodel.model.resources.ec2_vpc_endpoint_policy.EC2VpcEndpointPolicyProperties]
41
+ object.
42
+
43
+ More info at [AWS Docs](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpcendpoint.html)
44
+ """
45
+
46
+ Type: Literal["AWS::EC2::VPCEndpoint"]
47
+ Properties: Resolvable[EC2VpcEndpointPolicyProperties]
48
+
49
+ @property
50
+ def policy_documents(self) -> List[OptionallyNamedPolicyDocument]:
51
+ if not self.Properties.PolicyDocument:
52
+ return []
53
+ return [OptionallyNamedPolicyDocument(name=None, policy_document=self.Properties.PolicyDocument)]
@@ -0,0 +1,61 @@
1
+ from typing import List, Literal, Optional
2
+
3
+ from pycfmodel.model.base import CustomModel
4
+ from pycfmodel.model.generic import ResolvableGeneric
5
+ from pycfmodel.model.resources.properties.policy_document import PolicyDocument
6
+ from pycfmodel.model.resources.properties.tag import Tag
7
+ from pycfmodel.model.resources.resource import Resource
8
+ from pycfmodel.model.types import Resolvable, ResolvableStr
9
+
10
+
11
+ class ESDomainProperties(CustomModel):
12
+ """
13
+ Properties:
14
+
15
+ - AccessPolicies: A [policy document][pycfmodel.model.resources.properties.policy_document.PolicyDocument] object.
16
+ - AdvancedOptions: Additional options to specify for the OpenSearch Service domain.
17
+ - AdvancedSecurityOptions: Specifies options for fine-grained access control.
18
+ - CognitoOptions: Configures OpenSearch Service to use Amazon Cognito authentication for OpenSearch Dashboards.
19
+ - DomainEndpointOptions: Specifies additional options for the domain endpoint, such as whether to require HTTPS for all traffic or whether to use a custom endpoint rather than the default endpoint.
20
+ - DomainName: A name for the OpenSearch Service domain.
21
+ - EBSOptions: The configurations of Amazon Elastic Block Store (Amazon EBS) volumes that are attached to data nodes in the OpenSearch Service domain.
22
+ - ElasticsearchClusterConfig: ElasticsearchClusterConfig is a property of the AWS::Elasticsearch::Domain resource that configures the cluster of an Amazon OpenSearch Service domain.
23
+ - ElasticsearchVersion: The version of Elasticsearch to use, such as 2.3. If not specified, 1.5 is used as the default.
24
+ - EncryptionAtRestOptions: Whether the domain should encrypt data at rest, and if so, the AWS Key Management Service key to use.
25
+ - LogPublishingOptions: An object with one or more of the following keys: SEARCH_SLOW_LOGS, ES_APPLICATION_LOGS, INDEX_SLOW_LOGS, AUDIT_LOGS, depending on the types of logs you want to publish. Each key needs a valid LogPublishingOption value.
26
+ - NodeToNodeEncryptionOptions: Specifies whether node-to-node encryption is enabled.
27
+ - SnapshotOptions: DEPRECATED. The automated snapshot configuration for the OpenSearch Service domain indices.
28
+ - Tags: An arbitrary set of tags (key–value pairs) to associate with the OpenSearch Service domain.
29
+ - VPCOptions: The virtual private cloud (VPC) configuration for the OpenSearch Service domain.
30
+
31
+ More info at [AWS Docs](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticsearch-domain.html)
32
+ """
33
+
34
+ AccessPolicies: Optional[Resolvable[PolicyDocument]] = None
35
+ AdvancedOptions: Optional[ResolvableGeneric] = None
36
+ AdvancedSecurityOptions: Optional[ResolvableGeneric] = None
37
+ CognitoOptions: Optional[ResolvableGeneric] = None
38
+ DomainEndpointOptions: Optional[ResolvableGeneric] = None
39
+ DomainName: Optional[ResolvableStr] = None
40
+ EBSOptions: Optional[ResolvableGeneric] = None
41
+ ElasticsearchClusterConfig: Optional[ResolvableGeneric] = None
42
+ ElasticsearchVersion: Optional[ResolvableStr] = None
43
+ EncryptionAtRestOptions: Optional[ResolvableGeneric] = None
44
+ LogPublishingOptions: Optional[ResolvableGeneric] = None
45
+ NodeToNodeEncryptionOptions: Optional[ResolvableGeneric] = None
46
+ SnapshotOptions: Optional[ResolvableGeneric] = None
47
+ Tags: Optional[Resolvable[List[Tag]]] = None
48
+ VPCOptions: Optional[ResolvableGeneric] = None
49
+
50
+
51
+ class ESDomain(Resource):
52
+ """
53
+ Properties:
54
+
55
+ - Properties: An [ESDomainProperties][pycfmodel.model.resources.es_domain.ESDomainProperties] object.
56
+
57
+ More info at [AWS Docs](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticsearch-domain.html)
58
+ """
59
+
60
+ Type: Literal["AWS::Elasticsearch::Domain"]
61
+ Properties: Resolvable[ESDomainProperties]
@@ -0,0 +1,39 @@
1
+ import logging
2
+ from typing import ClassVar, Optional
3
+
4
+ from pydantic import ConfigDict, field_validator
5
+
6
+ from pycfmodel.model.generic import Generic
7
+ from pycfmodel.model.resources.resource import Resource
8
+
9
+ logger = logging.getLogger(__name__)
10
+
11
+
12
+ class GenericResource(Resource):
13
+ """
14
+ This class is used for all resource types that don't have a dedicated class.
15
+ Setting _strict to False will allow creation of GenericResources that have an explicit model class,
16
+ this is very useful to work around incomplete model definitions or things that are not implemented yet
17
+ like AWS:NoValue. _strict defaults to True. In that case you can't instantiate GenericResources when
18
+ there's a model for that type of resource.
19
+ """
20
+
21
+ Type: Optional[str] = None # Optional to handle cases like "AWS::CloudFormation::Authentication"
22
+ Properties: Optional[Generic] = None
23
+
24
+ model_config = ConfigDict(extra="allow")
25
+ _strict: ClassVar[bool] = True
26
+
27
+ @field_validator("Type", mode="before")
28
+ @classmethod
29
+ def check_type(cls, value, values, **kwargs):
30
+ from pycfmodel.model.resources.types import ResourceModels
31
+
32
+ existing_resource_types = {
33
+ klass.model_fields["Type"].annotation.__args__[0] for klass in ResourceModels.__args__[0].__args__
34
+ }
35
+ if value in existing_resource_types and cls._strict:
36
+ raise ValueError(f"Instantiation of GenericResource from {value} in {values} not allowed")
37
+ else:
38
+ logger.warning(f"Instantiation of GenericResource from {value} in {values}")
39
+ return value
@@ -0,0 +1,46 @@
1
+ from typing import List, Literal, Optional
2
+
3
+ from pycfmodel.model.base import CustomModel
4
+ from pycfmodel.model.resources.properties.policy import Policy
5
+ from pycfmodel.model.resources.resource import Resource
6
+ from pycfmodel.model.types import Resolvable, ResolvableStr
7
+ from pycfmodel.model.utils import OptionallyNamedPolicyDocument
8
+
9
+
10
+ class IAMGroupProperties(CustomModel):
11
+ """
12
+ Properties:
13
+
14
+ - GroupName: Name of the group.
15
+ - ManagedPolicyArns: ARN of the IAM policies to attach.
16
+ - Path: Path to the group. See [IAM Identifiers](https://docs.aws.amazon.com/IAM/latest/UserGuide/Using_Identifiers.html).
17
+ - Policies: Inline policies embedded in the IAM group.
18
+
19
+ More info at [AWS Docs](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iam-group.html)
20
+ """
21
+
22
+ GroupName: Optional[ResolvableStr] = None
23
+ ManagedPolicyArns: Optional[Resolvable[List[ResolvableStr]]] = None
24
+ Path: Optional[ResolvableStr] = None
25
+ Policies: Optional[Resolvable[List[Resolvable[Policy]]]] = None
26
+
27
+
28
+ class IAMGroup(Resource):
29
+ """
30
+ Properties:
31
+
32
+ - Properties: A [IAM Group properties][pycfmodel.model.resources.iam_group.IAMGroupProperties] object.
33
+
34
+ More info at [AWS Docs](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iam-group.html)
35
+ """
36
+
37
+ Type: Literal["AWS::IAM::Group"]
38
+ Properties: Optional[Resolvable[IAMGroupProperties]] = None
39
+
40
+ @property
41
+ def policy_documents(self) -> List[OptionallyNamedPolicyDocument]:
42
+ result = []
43
+ policies = self.Properties.Policies if self.Properties and self.Properties.Policies else []
44
+ for policy in policies:
45
+ result.append(OptionallyNamedPolicyDocument(name=policy.PolicyName, policy_document=policy.PolicyDocument))
46
+ return result
@@ -0,0 +1,52 @@
1
+ from typing import List, Literal, Optional
2
+
3
+ from pycfmodel.model.base import CustomModel
4
+ from pycfmodel.model.resources.properties.policy_document import PolicyDocument
5
+ from pycfmodel.model.resources.resource import Resource
6
+ from pycfmodel.model.types import Resolvable, ResolvableStr
7
+ from pycfmodel.model.utils import OptionallyNamedPolicyDocument
8
+
9
+
10
+ class IAMManagedPolicyProperties(CustomModel):
11
+ """
12
+ Properties:
13
+
14
+ - Description: Description of the policy.
15
+ - Groups: Friendly name of the IAM groups to attach the policy to.
16
+ - ManagedPolicyName: Name of the policy.
17
+ - Path: Path to the policy.
18
+ - PolicyDocument: A [policy document][pycfmodel.model.resources.properties.policy_document.PolicyDocument] object.
19
+ - Roles: Friendly name of the IAM roles to attach the policy to.
20
+ - Users: Friendly name of the IAM users to attach the policy to.
21
+
22
+ More info at [AWS Docs](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-managedpolicy.html)
23
+ """
24
+
25
+ Description: Optional[ResolvableStr] = None
26
+ Groups: Optional[Resolvable[List[ResolvableStr]]] = None
27
+ ManagedPolicyName: Optional[ResolvableStr] = None
28
+ Path: Optional[ResolvableStr] = None
29
+ PolicyDocument: Resolvable[PolicyDocument]
30
+ Roles: Optional[Resolvable[List[ResolvableStr]]] = None
31
+ Users: Optional[Resolvable[List[ResolvableStr]]] = None
32
+
33
+
34
+ class IAMManagedPolicy(Resource):
35
+ """
36
+ Properties:
37
+
38
+ - Properties: A [IAM Managed Policy properties][pycfmodel.model.resources.iam_managed_policy.IAMManagedPolicyProperties] object.
39
+
40
+ More info at [AWS Docs](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-managedpolicy.html)
41
+ """
42
+
43
+ Type: Literal["AWS::IAM::ManagedPolicy"]
44
+ Properties: Resolvable[IAMManagedPolicyProperties]
45
+
46
+ @property
47
+ def policy_documents(self) -> List[OptionallyNamedPolicyDocument]:
48
+ return [
49
+ OptionallyNamedPolicyDocument(
50
+ name=self.Properties.ManagedPolicyName, policy_document=self.Properties.PolicyDocument
51
+ )
52
+ ]
@@ -0,0 +1,48 @@
1
+ from typing import List, Literal, Optional
2
+
3
+ from pycfmodel.model.base import CustomModel
4
+ from pycfmodel.model.resources.properties.policy_document import PolicyDocument
5
+ from pycfmodel.model.resources.resource import Resource
6
+ from pycfmodel.model.types import Resolvable, ResolvableStr, ResolvableStrOrList
7
+ from pycfmodel.model.utils import OptionallyNamedPolicyDocument
8
+
9
+
10
+ class IAMPolicyProperties(CustomModel):
11
+ """
12
+ Properties:
13
+
14
+ - Groups: Friendly name of the IAM groups to attach the policy to.
15
+ - PolicyDocument: A [policy document][pycfmodel.model.resources.properties.policy_document.PolicyDocument] object.
16
+ - PolicyName: Name of the policy.
17
+ - Roles: Friendly name of the IAM roles to attach the policy to.
18
+ - Users: Friendly name of the IAM users to attach the policy to.
19
+
20
+ More info at [AWS Docs](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-policy.html)
21
+ """
22
+
23
+ Groups: Optional[ResolvableStrOrList] = None
24
+ PolicyDocument: Resolvable[PolicyDocument]
25
+ PolicyName: ResolvableStr
26
+ Roles: Optional[ResolvableStrOrList] = None
27
+ Users: Optional[ResolvableStrOrList] = None
28
+
29
+
30
+ class IAMPolicy(Resource):
31
+ """
32
+ Properties:
33
+
34
+ - Properties: A [IAM Policy properties][pycfmodel.model.resources.iam_policy.IAMPolicyProperties] object.
35
+
36
+ More info at [AWS Docs](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-policy.html)
37
+ """
38
+
39
+ Type: Literal["AWS::IAM::Policy"]
40
+ Properties: Resolvable[IAMPolicyProperties]
41
+
42
+ @property
43
+ def policy_documents(self) -> List[OptionallyNamedPolicyDocument]:
44
+ return [
45
+ OptionallyNamedPolicyDocument(
46
+ name=self.Properties.PolicyName, policy_document=self.Properties.PolicyDocument
47
+ )
48
+ ]