|
33 | 33 | LambdaAlias,
|
34 | 34 | LambdaLayerVersion,
|
35 | 35 | LambdaEventInvokeConfig,
|
| 36 | + LambdaUrl, |
| 37 | + LambdaPermission, |
36 | 38 | )
|
37 | 39 | from samtranslator.model.types import dict_of, is_str, is_type, list_of, one_of, any_type
|
38 | 40 | from samtranslator.translator import logical_id_generator
|
@@ -93,6 +95,7 @@ class SamFunction(SamResourceMacro):
|
93 | 95 | "ImageConfig": PropertyType(False, is_type(dict)),
|
94 | 96 | "CodeSigningConfigArn": PropertyType(False, is_str()),
|
95 | 97 | "Architectures": PropertyType(False, list_of(one_of(is_str(), is_type(dict)))),
|
| 98 | + "FunctionUrlConfig": PropertyType(False, is_type(dict)), |
96 | 99 | }
|
97 | 100 | event_resolver = ResourceTypeResolver(
|
98 | 101 | samtranslator.model.eventsources,
|
@@ -169,6 +172,13 @@ def to_cloudformation(self, **kwargs):
|
169 | 172 | resources.append(lambda_version)
|
170 | 173 | resources.append(lambda_alias)
|
171 | 174 |
|
| 175 | + if self.FunctionUrlConfig: |
| 176 | + lambda_url = self._construct_function_url(lambda_function, lambda_alias) |
| 177 | + resources.append(lambda_url) |
| 178 | + url_permission = self._construct_url_permission(lambda_function) |
| 179 | + if url_permission: |
| 180 | + resources.append(url_permission) |
| 181 | + |
172 | 182 | if self.DeploymentPreference:
|
173 | 183 | self._validate_deployment_preference_and_add_update_policy(
|
174 | 184 | kwargs.get("deployment_preference_collection", None),
|
@@ -850,6 +860,116 @@ def _validate_deployment_preference_and_add_update_policy(
|
850 | 860 | "UpdatePolicy", deployment_preference_collection.update_policy(self.logical_id).to_dict()
|
851 | 861 | )
|
852 | 862 |
|
| 863 | + def _construct_function_url(self, lambda_function, lambda_alias): |
| 864 | + """ |
| 865 | + This method is used to construct a lambda url resource |
| 866 | +
|
| 867 | + Parameters |
| 868 | + ---------- |
| 869 | + lambda_function : LambdaFunction |
| 870 | + Lambda Function resource |
| 871 | + lambda_alias : LambdaAlias |
| 872 | + Lambda Alias resource |
| 873 | +
|
| 874 | + Returns |
| 875 | + ------- |
| 876 | + LambdaUrl |
| 877 | + Lambda Url resource |
| 878 | + """ |
| 879 | + self._validate_function_url_params(lambda_function) |
| 880 | + |
| 881 | + logical_id = f"{lambda_function.logical_id}Url" |
| 882 | + lambda_url = LambdaUrl(logical_id=logical_id) |
| 883 | + |
| 884 | + cors = self.FunctionUrlConfig.get("Cors") |
| 885 | + if cors: |
| 886 | + lambda_url.Cors = cors |
| 887 | + lambda_url.AuthType = self.FunctionUrlConfig.get("AuthType") |
| 888 | + lambda_url.TargetFunctionArn = ( |
| 889 | + lambda_alias.get_runtime_attr("arn") if lambda_alias else lambda_function.get_runtime_attr("name") |
| 890 | + ) |
| 891 | + return lambda_url |
| 892 | + |
| 893 | + def _validate_function_url_params(self, lambda_function): |
| 894 | + """ |
| 895 | + Validate parameters provided to configure Lambda Urls |
| 896 | + """ |
| 897 | + self._validate_url_auth_type(lambda_function) |
| 898 | + self._validate_cors_config_parameter(lambda_function) |
| 899 | + |
| 900 | + def _validate_url_auth_type(self, lambda_function): |
| 901 | + if is_intrinsic(self.FunctionUrlConfig): |
| 902 | + return |
| 903 | + |
| 904 | + auth_type = self.FunctionUrlConfig.get("AuthType") |
| 905 | + if auth_type and is_intrinsic(auth_type): |
| 906 | + return |
| 907 | + |
| 908 | + if not auth_type or auth_type not in ["AWS_IAM", "NONE"]: |
| 909 | + raise InvalidResourceException( |
| 910 | + lambda_function.logical_id, |
| 911 | + "AuthType is required to configure function property `FunctionUrlConfig`. Please provide either AWS_IAM or NONE.", |
| 912 | + ) |
| 913 | + |
| 914 | + def _validate_cors_config_parameter(self, lambda_function): |
| 915 | + if is_intrinsic(self.FunctionUrlConfig): |
| 916 | + return |
| 917 | + |
| 918 | + cors_property_data_type = { |
| 919 | + "AllowOrigins": list, |
| 920 | + "AllowMethods": list, |
| 921 | + "AllowCredentials": bool, |
| 922 | + "AllowHeaders": list, |
| 923 | + "ExposeHeaders": list, |
| 924 | + "MaxAge": int, |
| 925 | + } |
| 926 | + |
| 927 | + cors = self.FunctionUrlConfig.get("Cors") |
| 928 | + |
| 929 | + if not cors or is_intrinsic(cors): |
| 930 | + return |
| 931 | + |
| 932 | + for prop_name, prop_value in cors.items(): |
| 933 | + if prop_name not in cors_property_data_type: |
| 934 | + raise InvalidResourceException( |
| 935 | + lambda_function.logical_id, |
| 936 | + "{} is not a valid property for configuring Cors.".format(prop_name), |
| 937 | + ) |
| 938 | + prop_type = cors_property_data_type.get(prop_name) |
| 939 | + if not is_intrinsic(prop_value) and not isinstance(prop_value, prop_type): |
| 940 | + raise InvalidResourceException( |
| 941 | + lambda_function.logical_id, |
| 942 | + "{} must be of type {}.".format(prop_name, str(prop_type).split("'")[1]), |
| 943 | + ) |
| 944 | + |
| 945 | + def _construct_url_permission(self, lambda_function): |
| 946 | + """ |
| 947 | + Construct the lambda permission associated with the function url resource in a case |
| 948 | + for public access when AuthType is NONE |
| 949 | +
|
| 950 | + Parameters |
| 951 | + ---------- |
| 952 | + lambda_function : LambdaUrl |
| 953 | + Lambda Function resource |
| 954 | +
|
| 955 | + Returns |
| 956 | + ------- |
| 957 | + LambdaPermission |
| 958 | + The lambda permission appended to a function url resource with public access |
| 959 | + """ |
| 960 | + auth_type = self.FunctionUrlConfig.get("AuthType") |
| 961 | + |
| 962 | + if auth_type not in ["NONE"] or is_intrinsic(self.FunctionUrlConfig): |
| 963 | + return None |
| 964 | + |
| 965 | + logical_id = f"{lambda_function.logical_id}UrlPublicPermissions" |
| 966 | + lambda_permission = LambdaPermission(logical_id=logical_id) |
| 967 | + lambda_permission.Action = "lambda:InvokeFunctionUrl" |
| 968 | + lambda_permission.FunctionName = lambda_function.get_runtime_attr("name") |
| 969 | + lambda_permission.Principal = "*" |
| 970 | + lambda_permission.FunctionUrlAuthType = auth_type |
| 971 | + return lambda_permission |
| 972 | + |
853 | 973 |
|
854 | 974 | class SamApi(SamResourceMacro):
|
855 | 975 | """SAM rest API macro."""
|
|
0 commit comments