Repository: getmoto/moto

Issue:
Lambda "add_permission" fails when specified function name is "function_arn"
### how to reproduce the issue
* Start moto server: `moto_server`
* Then execute the following code in a python console
```python
    iam_client = boto3.client("iam", region_name="eu-west-1", endpoint_url="http://localhost:5000")
    role = iam_client.create_role(
        RoleName=faker.word(), AssumeRolePolicyDocument=POLICY_DOCUMENT
    )

    lambda_client = boto3.client("lambda", region_name="eu-west-1", endpoint_url="http://localhost:5000")
    caller_arn = lambda_client.create_function(
        FunctionName=f"CALLER",
        Code={"ZipFile": "Hello".encode("utf-8")},
        Role=role.get("Role").get("Arn"),
        Runtime="python3.8",
        Handler="HandlerFunction",
    )["FunctionArn"]

    called_arn = lambda_client.create_function(
        FunctionName=f"CALLED",
        Code={"ZipFile": "World".encode("utf-8")},
        Role=role.get("Role").get("Arn"),
        Runtime="python3.8",
        Handler="HandlerFunction",
    )["FunctionArn"]

    lambda_client.add_permission(
        Action="lambda:InvokeFunction",
        FunctionName=called_arn,
        Principal="lambda.amazonaws.com",
        SourceAccount="123456789012",
        SourceArn=caller_arn,
        StatementId="1"
    )
```

### what you expected to happen
Following [boto3 documentation](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/lambda.html#Lambda.Client.add_permission), `FunctionName` argument can contain the function ARN (used for cross-account). Thus, the operation should succeed.

### what actually happens
* `add_permission` invocation returns the following error:
```python
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
../../../venv/lib/python3.8/site-packages/botocore/client.py:316: in _api_call
    return self._make_api_call(operation_name, kwargs)
        args       = ()
        kwargs     = {'Action': 'lambda:InvokeFunction',
 'FunctionName': 'arn:aws:lambda:eu-west-1:123456789012:function:CALLED',
 'Principal': 'lambda.amazonaws.com',
 'SourceAccount': '123456789012',
 'SourceArn': 'arn:aws:lambda:eu-west-1:123456789012:function:CALLER',
 'StatementId': '1'}
        operation_name = 'AddPermission'
        py_operation_name = 'add_permission'
        self       = <botocore.client.Lambda object at 0x10c21b460>
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <botocore.client.Lambda object at 0x10c21b460>
operation_name = 'AddPermission'
api_params = {'Action': 'lambda:InvokeFunction', 'FunctionName': 'arn:aws:lambda:eu-west-1:123456789012:function:CALLED', 'Principal': 'lambda.amazonaws.com', 'SourceAccount': '123456789012', ...}

    def _make_api_call(self, operation_name, api_params):
        operation_model = self._service_model.operation_model(operation_name)
        service_name = self._service_model.service_name
        history_recorder.record('API_CALL', {
            'service': service_name,
            'operation': operation_name,
            'params': api_params,
        })
        if operation_model.deprecated:
            logger.debug('Warning: %s.%s() is deprecated',
                         service_name, operation_name)
        request_context = {
            'client_region': self.meta.region_name,
            'client_config': self.meta.config,
            'has_streaming_input': operation_model.has_streaming_input,
            'auth_type': operation_model.auth_type,
        }
        request_dict = self._convert_to_request_dict(
            api_params, operation_model, context=request_context)
    
        service_id = self._service_model.service_id.hyphenize()
        handler, event_response = self.meta.events.emit_until_response(
            'before-call.{service_id}.{operation_name}'.format(
                service_id=service_id,
                operation_name=operation_name),
            model=operation_model, params=request_dict,
            request_signer=self._request_signer, context=request_context)
    
        if event_response is not None:
            http, parsed_response = event_response
        else:
            http, parsed_response = self._make_request(
                operation_model, request_dict, request_context)
    
        self.meta.events.emit(
            'after-call.{service_id}.{operation_name}'.format(
                service_id=service_id,
                operation_name=operation_name),
            http_response=http, parsed=parsed_response,
            model=operation_model, context=request_context
        )
    
        if http.status_code >= 300:
            error_code = parsed_response.get("Error", {}).get("Code")
            error_class = self.exceptions.from_code(error_code)
>           raise error_class(parsed_response, operation_name)
E           botocore.exceptions.ClientError: An error occurred (404) when calling the AddPermission operation: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
E           <title>404 Not Found</title>
E           <h1>Not Found</h1>
E           <p>The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.</p>

api_params = {'Action': 'lambda:InvokeFunction',
 'FunctionName': 'arn:aws:lambda:eu-west-1:123456789012:function:CALLED',
 'Principal': 'lambda.amazonaws.com',
 'SourceAccount': '123456789012',
 'SourceArn': 'arn:aws:lambda:eu-west-1:123456789012:function:CALLER',
 'StatementId': '1'}
error_class = <class 'botocore.exceptions.ClientError'>
error_code = '404'
event_response = None
handler    = <function inject_api_version_header_if_needed at 0x107d79940>
http       = <botocore.awsrequest.AWSResponse object at 0x10c544ee0>
operation_model = OperationModel(name=AddPermission)
operation_name = 'AddPermission'
parsed_response = {'Error': {'Code': '404',
           'Message': '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 '
                      'Final//EN">\n'
                      '<title>404 Not Found</title>\n'
                      '<h1>Not Found</h1>\n'
                      '<p>The requested URL was not found on the server. If '
                      'you entered the URL manually please check your spelling '
                      'and try again.</p>\n'},
 'ResponseMetadata': {'HTTPHeaders': {'access-control-allow-origin': '*',
                                      'content-length': '232',
                                      'content-type': 'text/html; '
                                                      'charset=utf-8',
                                      'date': 'Fri, 12 Feb 2021 10:31:58 GMT',
                                      'server': 'Werkzeug/1.0.1 Python/3.8.2'},
                      'HTTPStatusCode': 404,
                      'RetryAttempts': 0}}
request_context = {'auth_type': None,
 'client_config': <botocore.config.Config object at 0x10c5259a0>,
 'client_region': 'eu-west-1',
 'has_streaming_input': False,
 'timestamp': '20210212T103158Z'}
request_dict = {'body': b'{"Action": "lambda:InvokeFunction", "Principal": "lambda.amazonaws.c'
         b'om", "SourceAccount": "123456789012", "SourceArn": "arn:aws:lambda:e'
         b'u-west-1:123456789012:function:CALLER", "StatementId": "1"}',
 'context': {'auth_type': None,
             'client_config': <botocore.config.Config object at 0x10c5259a0>,
             'client_region': 'eu-west-1',
             'has_streaming_input': False,
             'timestamp': '20210212T103158Z'},
 'headers': {'User-Agent': 'Boto3/1.14.40 Python/3.8.2 Darwin/18.7.0 '
                           'Botocore/1.17.40'},
 'method': 'POST',
 'query_string': {},
 'url': 'http://localhost:5000/2015-03-31/functions/arn%3Aaws%3Alambda%3Aeu-west-1%3A123456789012%3Afunction%3ACALLED/policy',
 'url_path': '/2015-03-31/functions/arn%3Aaws%3Alambda%3Aeu-west-1%3A123456789012%3Afunction%3ACALLED/policy'}
self       = <botocore.client.Lambda object at 0x10c21b460>
service_id = 'lambda'
service_name = 'lambda'

../../../venv/lib/python3.8/site-packages/botocore/client.py:635: ClientError
```

* `moto_server` reports the following output:
```
127.0.0.1 - - [12/Feb/2021 11:31:54] "POST / HTTP/1.1" 200 -
127.0.0.1 - - [12/Feb/2021 11:31:54] "POST / HTTP/1.1" 200 -
127.0.0.1 - - [12/Feb/2021 11:31:58] "POST / HTTP/1.1" 200 -
127.0.0.1 - - [12/Feb/2021 11:31:58] "POST /2015-03-31/functions HTTP/1.1" 201 -
127.0.0.1 - - [12/Feb/2021 11:31:58] "POST /2015-03-31/functions HTTP/1.1" 201 -
127.0.0.1 - - [12/Feb/2021 11:31:58] "POST /2015-03-31/functions/arn%3Aaws%3Alambda%3Aeu-west-1%3A123456789012%3Afunction%3ACALLED/policy HTTP/1.1" 404 -
```

**what version of Moto you're using**
Version: 1.3.17.dev256, with standalone server


Discussion:
Thanks for raising this @pedro-dlfa - marking it as an bug.

FYI: I believe this would be fixed by the solution in this PR: https://github.com/spulec/moto/pull/2668

Resolving patch:
diff --git a/moto/awslambda/models.py b/moto/awslambda/models.py
--- a/moto/awslambda/models.py
+++ b/moto/awslambda/models.py
@@ -970,7 +970,9 @@ def put_function(self, fn):
         fn.policy = Policy(fn)
         self._arns[fn.function_arn] = fn
 
-    def publish_function(self, name):
+    def publish_function(self, name_or_arn):
+        function = self.get_function_by_name_or_arn(name_or_arn)
+        name = function.function_name
         if name not in self._functions:
             return None
         if not self._functions[name]["latest"]:
diff --git a/moto/awslambda/responses.py b/moto/awslambda/responses.py
--- a/moto/awslambda/responses.py
+++ b/moto/awslambda/responses.py
@@ -170,7 +170,7 @@ def function_concurrency(self, request, full_url, headers):
 
     def _add_policy(self, request, full_url, headers):
         path = request.path if hasattr(request, "path") else path_url(request.url)
-        function_name = path.split("/")[-2]
+        function_name = unquote(path.split("/")[-2])
         if self.lambda_backend.get_function(function_name):
             statement = self.body
             self.lambda_backend.add_permission(function_name, statement)
@@ -180,7 +180,7 @@ def _add_policy(self, request, full_url, headers):
 
     def _get_policy(self, request, full_url, headers):
         path = request.path if hasattr(request, "path") else path_url(request.url)
-        function_name = path.split("/")[-2]
+        function_name = unquote(path.split("/")[-2])
         if self.lambda_backend.get_function(function_name):
             out = self.lambda_backend.get_policy_wire_format(function_name)
             return 200, {}, out
@@ -189,7 +189,7 @@ def _get_policy(self, request, full_url, headers):
 
     def _del_policy(self, request, full_url, headers, querystring):
         path = request.path if hasattr(request, "path") else path_url(request.url)
-        function_name = path.split("/")[-3]
+        function_name = unquote(path.split("/")[-3])
         statement_id = path.split("/")[-1].split("?")[0]
         revision = querystring.get("RevisionId", "")
         if self.lambda_backend.get_function(function_name):
@@ -225,7 +225,7 @@ def _invoke(self, request, full_url):
     def _invoke_async(self, request, full_url):
         response_headers = {}
 
-        function_name = self.path.rsplit("/", 3)[-3]
+        function_name = unquote(self.path.rsplit("/", 3)[-3])
 
         fn = self.lambda_backend.get_function(function_name, None)
         if fn:
@@ -386,7 +386,7 @@ def _untag_resource(self, request, full_url):
             return 404, {}, "{}"
 
     def _put_configuration(self, request):
-        function_name = self.path.rsplit("/", 2)[-2]
+        function_name = unquote(self.path.rsplit("/", 2)[-2])
         qualifier = self._get_param("Qualifier", None)
         resp = self.lambda_backend.update_function_configuration(
             function_name, qualifier, body=self.json_body
@@ -398,7 +398,7 @@ def _put_configuration(self, request):
             return 404, {}, "{}"
 
     def _put_code(self):
-        function_name = self.path.rsplit("/", 2)[-2]
+        function_name = unquote(self.path.rsplit("/", 2)[-2])
         qualifier = self._get_param("Qualifier", None)
         resp = self.lambda_backend.update_function_code(
             function_name, qualifier, body=self.json_body
@@ -410,7 +410,7 @@ def _put_code(self):
             return 404, {}, "{}"
 
     def _get_function_concurrency(self, request):
-        path_function_name = self.path.rsplit("/", 2)[-2]
+        path_function_name = unquote(self.path.rsplit("/", 2)[-2])
         function_name = self.lambda_backend.get_function(path_function_name)
 
         if function_name is None:
@@ -420,7 +420,7 @@ def _get_function_concurrency(self, request):
         return 200, {}, json.dumps({"ReservedConcurrentExecutions": resp})
 
     def _delete_function_concurrency(self, request):
-        path_function_name = self.path.rsplit("/", 2)[-2]
+        path_function_name = unquote(self.path.rsplit("/", 2)[-2])
         function_name = self.lambda_backend.get_function(path_function_name)
 
         if function_name is None:
@@ -431,7 +431,7 @@ def _delete_function_concurrency(self, request):
         return 204, {}, "{}"
 
     def _put_function_concurrency(self, request):
-        path_function_name = self.path.rsplit("/", 2)[-2]
+        path_function_name = unquote(self.path.rsplit("/", 2)[-2])
         function = self.lambda_backend.get_function(path_function_name)
 
         if function is None:
diff --git a/moto/awslambda/urls.py b/moto/awslambda/urls.py
--- a/moto/awslambda/urls.py
+++ b/moto/awslambda/urls.py
@@ -13,13 +13,13 @@
     r"{0}/(?P<api_version>[^/]+)/event-source-mappings/(?P<UUID>[\w_-]+)/?$": response.event_source_mapping,
     r"{0}/(?P<api_version>[^/]+)/functions/(?P<function_name>[\w_-]+)/invocations/?$": response.invoke,
     r"{0}/(?P<api_version>[^/]+)/functions/(?P<resource_arn>.+)/invocations/?$": response.invoke,
-    r"{0}/(?P<api_version>[^/]+)/functions/(?P<function_name>[\w_-]+)/invoke-async/?$": response.invoke_async,
+    r"{0}/(?P<api_version>[^/]+)/functions/(?P<function_name>[\w_:%-]+)/invoke-async/?$": response.invoke_async,
     r"{0}/(?P<api_version>[^/]+)/tags/(?P<resource_arn>.+)": response.tag,
-    r"{0}/(?P<api_version>[^/]+)/functions/(?P<function_name>[\w_-]+)/policy/(?P<statement_id>[\w_-]+)$": response.policy,
-    r"{0}/(?P<api_version>[^/]+)/functions/(?P<function_name>[\w_-]+)/policy/?$": response.policy,
-    r"{0}/(?P<api_version>[^/]+)/functions/(?P<function_name>[\w_-]+)/configuration/?$": response.configuration,
-    r"{0}/(?P<api_version>[^/]+)/functions/(?P<function_name>[\w_-]+)/code/?$": response.code,
-    r"{0}/(?P<api_version>[^/]+)/functions/(?P<function_name>[\w_-]+)/concurrency/?$": response.function_concurrency,
+    r"{0}/(?P<api_version>[^/]+)/functions/(?P<function_name>[\w_:%-]+)/policy/(?P<statement_id>[\w_-]+)$": response.policy,
+    r"{0}/(?P<api_version>[^/]+)/functions/(?P<function_name>[\w_:%-]+)/policy/?$": response.policy,
+    r"{0}/(?P<api_version>[^/]+)/functions/(?P<function_name>[\w_:%-]+)/configuration/?$": response.configuration,
+    r"{0}/(?P<api_version>[^/]+)/functions/(?P<function_name>[\w_:%-]+)/code/?$": response.code,
+    r"{0}/(?P<api_version>[^/]+)/functions/(?P<function_name>[\w_:%-]+)/concurrency/?$": response.function_concurrency,
     r"{0}/(?P<api_version>[^/]+)/layers/?$": response.list_layers,
     r"{0}/(?P<api_version>[^/]+)/layers/(?P<layer_name>[\w_-]+)/versions/?$": response.layers_versions,
 }


Test patch:
diff --git a/tests/test_awslambda/test_lambda.py b/tests/test_awslambda/test_lambda.py
--- a/tests/test_awslambda/test_lambda.py
+++ b/tests/test_awslambda/test_lambda.py
@@ -127,10 +127,11 @@ def test_list_functions():
 
 @pytest.mark.network
 @pytest.mark.parametrize("invocation_type", [None, "RequestResponse"])
+@pytest.mark.parametrize("key", ["FunctionName", "FunctionArn"])
 @mock_lambda
-def test_invoke_requestresponse_function(invocation_type):
+def test_invoke_requestresponse_function(invocation_type, key):
     conn = boto3.client("lambda", _lambda_region)
-    conn.create_function(
+    fxn = conn.create_function(
         FunctionName="testFunction",
         Runtime="python2.7",
         Role=get_role_name(),
@@ -141,6 +142,7 @@ def test_invoke_requestresponse_function(invocation_type):
         MemorySize=128,
         Publish=True,
     )
+    name_or_arn = fxn[key]
 
     # Only add invocation-type keyword-argument when provided, otherwise the request
     # fails to be validated
@@ -150,7 +152,7 @@ def test_invoke_requestresponse_function(invocation_type):
 
     in_data = {"msg": "So long and thanks for all the fish"}
     success_result = conn.invoke(
-        FunctionName="testFunction", Payload=json.dumps(in_data), LogType="Tail", **kw
+        FunctionName=name_or_arn, Payload=json.dumps(in_data), LogType="Tail", **kw
     )
 
     if "FunctionError" in success_result:
@@ -171,7 +173,7 @@ def test_invoke_requestresponse_function(invocation_type):
 
     # Logs should not be returned by default, only when the LogType-param is supplied
     success_result = conn.invoke(
-        FunctionName="testFunction", Payload=json.dumps(in_data), **kw
+        FunctionName=name_or_arn, Payload=json.dumps(in_data), **kw
     )
 
     success_result["StatusCode"].should.equal(200)
@@ -181,39 +183,6 @@ def test_invoke_requestresponse_function(invocation_type):
     assert "LogResult" not in success_result
 
 
-@pytest.mark.network
-@mock_lambda
-def test_invoke_requestresponse_function_with_arn():
-    from moto.awslambda.models import ACCOUNT_ID
-
-    conn = boto3.client("lambda", "us-west-2")
-    conn.create_function(
-        FunctionName="testFunction",
-        Runtime="python2.7",
-        Role=get_role_name(),
-        Handler="lambda_function.lambda_handler",
-        Code={"ZipFile": get_test_zip_file1()},
-        Description="test lambda function",
-        Timeout=3,
-        MemorySize=128,
-        Publish=True,
-    )
-
-    in_data = {"msg": "So long and thanks for all the fish"}
-    success_result = conn.invoke(
-        FunctionName="arn:aws:lambda:us-west-2:{}:function:testFunction".format(
-            ACCOUNT_ID
-        ),
-        InvocationType="RequestResponse",
-        Payload=json.dumps(in_data),
-    )
-
-    success_result["StatusCode"].should.equal(200)
-
-    payload = success_result["Payload"].read().decode("utf-8")
-    json.loads(payload).should.equal(in_data)
-
-
 @pytest.mark.network
 @mock_lambda
 def test_invoke_event_function():
@@ -576,10 +545,11 @@ def test_get_function():
         conn.get_function(FunctionName="junk", Qualifier="$LATEST")
 
 
+@pytest.mark.parametrize("key", ["FunctionName", "FunctionArn"])
 @mock_lambda
 @mock_s3
 @freeze_time("2015-01-01 00:00:00")
-def test_get_function_configuration():
+def test_get_function_configuration(key):
     s3_conn = boto3.client("s3", _lambda_region)
     s3_conn.create_bucket(
         Bucket="test-bucket",
@@ -590,7 +560,7 @@ def test_get_function_configuration():
     s3_conn.put_object(Bucket="test-bucket", Key="test.zip", Body=zip_content)
     conn = boto3.client("lambda", _lambda_region)
 
-    conn.create_function(
+    fxn = conn.create_function(
         FunctionName="testFunction",
         Runtime="python2.7",
         Role=get_role_name(),
@@ -602,8 +572,9 @@ def test_get_function_configuration():
         Publish=True,
         Environment={"Variables": {"test_variable": "test_value"}},
     )
+    name_or_arn = fxn[key]
 
-    result = conn.get_function_configuration(FunctionName="testFunction")
+    result = conn.get_function_configuration(FunctionName=name_or_arn)
 
     result["CodeSha256"].should.equal(hashlib.sha256(zip_content).hexdigest())
     result["CodeSize"].should.equal(len(zip_content))
@@ -623,7 +594,7 @@ def test_get_function_configuration():
 
     # Test get function with qualifier
     result = conn.get_function_configuration(
-        FunctionName="testFunction", Qualifier="$LATEST"
+        FunctionName=name_or_arn, Qualifier="$LATEST"
     )
     result["Version"].should.equal("$LATEST")
     result["FunctionArn"].should.equal(
@@ -983,10 +954,11 @@ def test_tags_not_found():
 
 
 @pytest.mark.network
+@pytest.mark.parametrize("key", ["FunctionName", "FunctionArn"])
 @mock_lambda
-def test_invoke_async_function():
+def test_invoke_async_function(key):
     conn = boto3.client("lambda", _lambda_region)
-    conn.create_function(
+    fxn = conn.create_function(
         FunctionName="testFunction",
         Runtime="python2.7",
         Role=get_role_name(),
@@ -997,9 +969,10 @@ def test_invoke_async_function():
         MemorySize=128,
         Publish=True,
     )
+    name_or_arn = fxn[key]
 
     success_result = conn.invoke_async(
-        FunctionName="testFunction", InvokeArgs=json.dumps({"test": "event"})
+        FunctionName=name_or_arn, InvokeArgs=json.dumps({"test": "event"})
     )
 
     success_result["Status"].should.equal(202)
@@ -1053,11 +1026,15 @@ def test_get_function_created_with_zipfile():
     )
 
 
+@pytest.mark.parametrize("key", ["FunctionName", "FunctionArn"])
 @mock_lambda
-def test_add_function_permission():
+def test_add_function_permission(key):
+    """
+    Parametrized to ensure that we can add permission by using the FunctionName and the FunctionArn
+    """
     conn = boto3.client("lambda", _lambda_region)
     zip_content = get_test_zip_file1()
-    conn.create_function(
+    f = conn.create_function(
         FunctionName="testFunction",
         Runtime="python2.7",
         Role=(get_role_name()),
@@ -1068,9 +1045,10 @@ def test_add_function_permission():
         MemorySize=128,
         Publish=True,
     )
+    name_or_arn = f[key]
 
     response = conn.add_permission(
-        FunctionName="testFunction",
+        FunctionName=name_or_arn,
         StatementId="1",
         Action="lambda:InvokeFunction",
         Principal="432143214321",
@@ -1084,11 +1062,12 @@ def test_add_function_permission():
     assert res["Action"] == "lambda:InvokeFunction"
 
 
+@pytest.mark.parametrize("key", ["FunctionName", "FunctionArn"])
 @mock_lambda
-def test_get_function_policy():
+def test_get_function_policy(key):
     conn = boto3.client("lambda", _lambda_region)
     zip_content = get_test_zip_file1()
-    conn.create_function(
+    f = conn.create_function(
         FunctionName="testFunction",
         Runtime="python2.7",
         Role=get_role_name(),
@@ -1099,9 +1078,10 @@ def test_get_function_policy():
         MemorySize=128,
         Publish=True,
     )
+    name_or_arn = f[key]
 
-    response = conn.add_permission(
-        FunctionName="testFunction",
+    conn.add_permission(
+        FunctionName=name_or_arn,
         StatementId="1",
         Action="lambda:InvokeFunction",
         Principal="432143214321",
@@ -1111,7 +1091,7 @@ def test_get_function_policy():
         Qualifier="2",
     )
 
-    response = conn.get_policy(FunctionName="testFunction")
+    response = conn.get_policy(FunctionName=name_or_arn)
 
     assert "Policy" in response
     res = json.loads(response["Policy"])
@@ -1256,10 +1236,11 @@ def test_create_event_source_mapping():
 
 
 @pytest.mark.network
+@pytest.mark.parametrize("key", ["FunctionName", "FunctionArn"])
 @mock_logs
 @mock_lambda
 @mock_sqs
-def test_invoke_function_from_sqs():
+def test_invoke_function_from_sqs(key):
     sqs = boto3.resource("sqs", region_name="us-east-1")
     queue = sqs.create_queue(QueueName="test-sqs-queue1")
 
@@ -1275,9 +1256,10 @@ def test_invoke_function_from_sqs():
         MemorySize=128,
         Publish=True,
     )
+    name_or_arn = func[key]
 
     response = conn.create_event_source_mapping(
-        EventSourceArn=queue.attributes["QueueArn"], FunctionName=func["FunctionArn"]
+        EventSourceArn=queue.attributes["QueueArn"], FunctionName=name_or_arn
     )
 
     assert response["EventSourceArn"] == queue.attributes["QueueArn"]
@@ -1631,9 +1613,10 @@ def test_delete_event_source_mapping():
     )
 
 
+@pytest.mark.parametrize("key", ["FunctionName", "FunctionArn"])
 @mock_lambda
 @mock_s3
-def test_update_configuration():
+def test_update_configuration(key):
     s3_conn = boto3.client("s3", _lambda_region)
     s3_conn.create_bucket(
         Bucket="test-bucket",
@@ -1656,6 +1639,7 @@ def test_update_configuration():
         Publish=True,
         Environment={"Variables": {"test_old_environment": "test_old_value"}},
     )
+    name_or_arn = fxn[key]
 
     assert fxn["Description"] == "test lambda function"
     assert fxn["Handler"] == "lambda_function.lambda_handler"
@@ -1664,7 +1648,7 @@ def test_update_configuration():
     assert fxn["Timeout"] == 3
 
     updated_config = conn.update_function_configuration(
-        FunctionName="testFunction",
+        FunctionName=name_or_arn,
         Description="updated test lambda function",
         Handler="lambda_function.new_lambda_handler",
         Runtime="python3.6",
@@ -1689,8 +1673,9 @@ def test_update_configuration():
     }
 
 
+@pytest.mark.parametrize("key", ["FunctionName", "FunctionArn"])
 @mock_lambda
-def test_update_function_zip():
+def test_update_function_zip(key):
     conn = boto3.client("lambda", _lambda_region)
 
     zip_content_one = get_test_zip_file1()
@@ -1706,11 +1691,12 @@ def test_update_function_zip():
         MemorySize=128,
         Publish=True,
     )
+    name_or_arn = fxn[key]
 
     zip_content_two = get_test_zip_file2()
 
-    fxn_updated = conn.update_function_code(
-        FunctionName="testFunctionZip", ZipFile=zip_content_two, Publish=True
+    conn.update_function_code(
+        FunctionName=name_or_arn, ZipFile=zip_content_two, Publish=True
     )
 
     response = conn.get_function(FunctionName="testFunctionZip", Qualifier="2")
@@ -1837,11 +1823,12 @@ def test_create_function_with_unknown_arn():
     )
 
 
+@pytest.mark.parametrize("key", ["FunctionName", "FunctionArn"])
 @mock_lambda
-def test_remove_function_permission():
+def test_remove_function_permission(key):
     conn = boto3.client("lambda", _lambda_region)
     zip_content = get_test_zip_file1()
-    conn.create_function(
+    f = conn.create_function(
         FunctionName="testFunction",
         Runtime="python2.7",
         Role=(get_role_name()),
@@ -1852,9 +1839,10 @@ def test_remove_function_permission():
         MemorySize=128,
         Publish=True,
     )
+    name_or_arn = f[key]
 
     conn.add_permission(
-        FunctionName="testFunction",
+        FunctionName=name_or_arn,
         StatementId="1",
         Action="lambda:InvokeFunction",
         Principal="432143214321",
@@ -1865,21 +1853,22 @@ def test_remove_function_permission():
     )
 
     remove = conn.remove_permission(
-        FunctionName="testFunction", StatementId="1", Qualifier="2",
+        FunctionName=name_or_arn, StatementId="1", Qualifier="2",
     )
     remove["ResponseMetadata"]["HTTPStatusCode"].should.equal(204)
-    policy = conn.get_policy(FunctionName="testFunction", Qualifier="2")["Policy"]
+    policy = conn.get_policy(FunctionName=name_or_arn, Qualifier="2")["Policy"]
     policy = json.loads(policy)
     policy["Statement"].should.equal([])
 
 
+@pytest.mark.parametrize("key", ["FunctionName", "FunctionArn"])
 @mock_lambda
-def test_put_function_concurrency():
+def test_put_function_concurrency(key):
     expected_concurrency = 15
     function_name = "test"
 
     conn = boto3.client("lambda", _lambda_region)
-    conn.create_function(
+    f = conn.create_function(
         FunctionName=function_name,
         Runtime="python3.8",
         Role=(get_role_name()),
@@ -1890,19 +1879,21 @@ def test_put_function_concurrency():
         MemorySize=128,
         Publish=True,
     )
+    name_or_arn = f[key]
     result = conn.put_function_concurrency(
-        FunctionName=function_name, ReservedConcurrentExecutions=expected_concurrency
+        FunctionName=name_or_arn, ReservedConcurrentExecutions=expected_concurrency
     )
 
     result["ReservedConcurrentExecutions"].should.equal(expected_concurrency)
 
 
+@pytest.mark.parametrize("key", ["FunctionName", "FunctionArn"])
 @mock_lambda
-def test_delete_function_concurrency():
+def test_delete_function_concurrency(key):
     function_name = "test"
 
     conn = boto3.client("lambda", _lambda_region)
-    conn.create_function(
+    f = conn.create_function(
         FunctionName=function_name,
         Runtime="python3.8",
         Role=(get_role_name()),
@@ -1913,23 +1904,25 @@ def test_delete_function_concurrency():
         MemorySize=128,
         Publish=True,
     )
+    name_or_arn = f[key]
     conn.put_function_concurrency(
-        FunctionName=function_name, ReservedConcurrentExecutions=15
+        FunctionName=name_or_arn, ReservedConcurrentExecutions=15
     )
 
-    conn.delete_function_concurrency(FunctionName=function_name)
+    conn.delete_function_concurrency(FunctionName=name_or_arn)
     result = conn.get_function(FunctionName=function_name)
 
     result.doesnt.have.key("Concurrency")
 
 
+@pytest.mark.parametrize("key", ["FunctionName", "FunctionArn"])
 @mock_lambda
-def test_get_function_concurrency():
+def test_get_function_concurrency(key):
     expected_concurrency = 15
     function_name = "test"
 
     conn = boto3.client("lambda", _lambda_region)
-    conn.create_function(
+    f = conn.create_function(
         FunctionName=function_name,
         Runtime="python3.8",
         Role=(get_role_name()),
@@ -1940,11 +1933,12 @@ def test_get_function_concurrency():
         MemorySize=128,
         Publish=True,
     )
+    name_or_arn = f[key]
     conn.put_function_concurrency(
-        FunctionName=function_name, ReservedConcurrentExecutions=expected_concurrency
+        FunctionName=name_or_arn, ReservedConcurrentExecutions=expected_concurrency
     )
 
-    result = conn.get_function_concurrency(FunctionName=function_name)
+    result = conn.get_function_concurrency(FunctionName=name_or_arn)
 
     result["ReservedConcurrentExecutions"].should.equal(expected_concurrency)