Merge pull request #2547 from bblommers/feature/2546
AWS Lambda: Add Role validation when creating functions
This commit is contained in:
commit
66dd1a0dff
31
moto/awslambda/exceptions.py
Normal file
31
moto/awslambda/exceptions.py
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
from botocore.client import ClientError
|
||||||
|
|
||||||
|
|
||||||
|
class LambdaClientError(ClientError):
|
||||||
|
def __init__(self, error, message):
|
||||||
|
error_response = {"Error": {"Code": error, "Message": message}}
|
||||||
|
super(LambdaClientError, self).__init__(error_response, None)
|
||||||
|
|
||||||
|
|
||||||
|
class CrossAccountNotAllowed(LambdaClientError):
|
||||||
|
def __init__(self):
|
||||||
|
super(CrossAccountNotAllowed, self).__init__(
|
||||||
|
"AccessDeniedException", "Cross-account pass role is not allowed."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidParameterValueException(LambdaClientError):
|
||||||
|
def __init__(self, message):
|
||||||
|
super(InvalidParameterValueException, self).__init__(
|
||||||
|
"InvalidParameterValueException", message
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidRoleFormat(LambdaClientError):
|
||||||
|
pattern = r"arn:(aws[a-zA-Z-]*)?:iam::(\d{12}):role/?[a-zA-Z_0-9+=,.@\-_/]+"
|
||||||
|
|
||||||
|
def __init__(self, role):
|
||||||
|
message = "1 validation error detected: Value '{0}' at 'role' failed to satisfy constraint: Member must satisfy regular expression pattern: {1}".format(
|
||||||
|
role, InvalidRoleFormat.pattern
|
||||||
|
)
|
||||||
|
super(InvalidRoleFormat, self).__init__("ValidationException", message)
|
@ -26,11 +26,18 @@ import requests.adapters
|
|||||||
import boto.awslambda
|
import boto.awslambda
|
||||||
from moto.core import BaseBackend, BaseModel
|
from moto.core import BaseBackend, BaseModel
|
||||||
from moto.core.exceptions import RESTError
|
from moto.core.exceptions import RESTError
|
||||||
|
from moto.iam.models import iam_backend
|
||||||
|
from moto.iam.exceptions import IAMNotFoundException
|
||||||
from moto.core.utils import unix_time_millis
|
from moto.core.utils import unix_time_millis
|
||||||
from moto.s3.models import s3_backend
|
from moto.s3.models import s3_backend
|
||||||
from moto.logs.models import logs_backends
|
from moto.logs.models import logs_backends
|
||||||
from moto.s3.exceptions import MissingBucket, MissingKey
|
from moto.s3.exceptions import MissingBucket, MissingKey
|
||||||
from moto import settings
|
from moto import settings
|
||||||
|
from .exceptions import (
|
||||||
|
CrossAccountNotAllowed,
|
||||||
|
InvalidRoleFormat,
|
||||||
|
InvalidParameterValueException,
|
||||||
|
)
|
||||||
from .utils import make_function_arn, make_function_ver_arn
|
from .utils import make_function_arn, make_function_ver_arn
|
||||||
from moto.sqs import sqs_backends
|
from moto.sqs import sqs_backends
|
||||||
from moto.dynamodb2 import dynamodb_backends2
|
from moto.dynamodb2 import dynamodb_backends2
|
||||||
@ -214,9 +221,8 @@ class LambdaFunction(BaseModel):
|
|||||||
key = s3_backend.get_key(self.code["S3Bucket"], self.code["S3Key"])
|
key = s3_backend.get_key(self.code["S3Bucket"], self.code["S3Key"])
|
||||||
except MissingBucket:
|
except MissingBucket:
|
||||||
if do_validate_s3():
|
if do_validate_s3():
|
||||||
raise ValueError(
|
raise InvalidParameterValueException(
|
||||||
"InvalidParameterValueException",
|
"Error occurred while GetObject. S3 Error Code: NoSuchBucket. S3 Error Message: The specified bucket does not exist"
|
||||||
"Error occurred while GetObject. S3 Error Code: NoSuchBucket. S3 Error Message: The specified bucket does not exist",
|
|
||||||
)
|
)
|
||||||
except MissingKey:
|
except MissingKey:
|
||||||
if do_validate_s3():
|
if do_validate_s3():
|
||||||
@ -668,6 +674,19 @@ class LambdaStorage(object):
|
|||||||
:param fn: Function
|
:param fn: Function
|
||||||
:type fn: LambdaFunction
|
:type fn: LambdaFunction
|
||||||
"""
|
"""
|
||||||
|
valid_role = re.match(InvalidRoleFormat.pattern, fn.role)
|
||||||
|
if valid_role:
|
||||||
|
account = valid_role.group(2)
|
||||||
|
if account != ACCOUNT_ID:
|
||||||
|
raise CrossAccountNotAllowed()
|
||||||
|
try:
|
||||||
|
iam_backend.get_role_by_arn(fn.role)
|
||||||
|
except IAMNotFoundException:
|
||||||
|
raise InvalidParameterValueException(
|
||||||
|
"The role defined for the function cannot be assumed by Lambda."
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
raise InvalidRoleFormat(fn.role)
|
||||||
if fn.function_name in self._functions:
|
if fn.function_name in self._functions:
|
||||||
self._functions[fn.function_name]["latest"] = fn
|
self._functions[fn.function_name]["latest"] = fn
|
||||||
else:
|
else:
|
||||||
|
@ -211,30 +211,14 @@ class LambdaResponse(BaseResponse):
|
|||||||
return 200, {}, json.dumps(result)
|
return 200, {}, json.dumps(result)
|
||||||
|
|
||||||
def _create_function(self, request, full_url, headers):
|
def _create_function(self, request, full_url, headers):
|
||||||
try:
|
fn = self.lambda_backend.create_function(self.json_body)
|
||||||
fn = self.lambda_backend.create_function(self.json_body)
|
config = fn.get_configuration()
|
||||||
except ValueError as e:
|
return 201, {}, json.dumps(config)
|
||||||
return (
|
|
||||||
400,
|
|
||||||
{},
|
|
||||||
json.dumps({"Error": {"Code": e.args[0], "Message": e.args[1]}}),
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
config = fn.get_configuration()
|
|
||||||
return 201, {}, json.dumps(config)
|
|
||||||
|
|
||||||
def _create_event_source_mapping(self, request, full_url, headers):
|
def _create_event_source_mapping(self, request, full_url, headers):
|
||||||
try:
|
fn = self.lambda_backend.create_event_source_mapping(self.json_body)
|
||||||
fn = self.lambda_backend.create_event_source_mapping(self.json_body)
|
config = fn.get_configuration()
|
||||||
except ValueError as e:
|
return 201, {}, json.dumps(config)
|
||||||
return (
|
|
||||||
400,
|
|
||||||
{},
|
|
||||||
json.dumps({"Error": {"Code": e.args[0], "Message": e.args[1]}}),
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
config = fn.get_configuration()
|
|
||||||
return 201, {}, json.dumps(config)
|
|
||||||
|
|
||||||
def _list_event_source_mappings(self, event_source_arn, function_name):
|
def _list_event_source_mappings(self, event_source_arn, function_name):
|
||||||
esms = self.lambda_backend.list_event_source_mappings(
|
esms = self.lambda_backend.list_event_source_mappings(
|
||||||
|
@ -8,6 +8,7 @@ import random
|
|||||||
import re
|
import re
|
||||||
import six
|
import six
|
||||||
import string
|
import string
|
||||||
|
from botocore.exceptions import ClientError
|
||||||
from six.moves.urllib.parse import urlparse
|
from six.moves.urllib.parse import urlparse
|
||||||
|
|
||||||
|
|
||||||
@ -141,7 +142,10 @@ class convert_flask_to_httpretty_response(object):
|
|||||||
def __call__(self, args=None, **kwargs):
|
def __call__(self, args=None, **kwargs):
|
||||||
from flask import request, Response
|
from flask import request, Response
|
||||||
|
|
||||||
result = self.callback(request, request.url, {})
|
try:
|
||||||
|
result = self.callback(request, request.url, {})
|
||||||
|
except ClientError as exc:
|
||||||
|
result = 400, {}, exc.response["Error"]["Message"]
|
||||||
# result is a status, headers, response tuple
|
# result is a status, headers, response tuple
|
||||||
if len(result) == 3:
|
if len(result) == 3:
|
||||||
status, headers, content = result
|
status, headers, content = result
|
||||||
|
@ -371,7 +371,7 @@ class Role(BaseModel):
|
|||||||
from moto.cloudformation.exceptions import UnformattedGetAttTemplateException
|
from moto.cloudformation.exceptions import UnformattedGetAttTemplateException
|
||||||
|
|
||||||
if attribute_name == "Arn":
|
if attribute_name == "Arn":
|
||||||
raise NotImplementedError('"Fn::GetAtt" : [ "{0}" , "Arn" ]"')
|
return self.arn
|
||||||
raise UnformattedGetAttTemplateException()
|
raise UnformattedGetAttTemplateException()
|
||||||
|
|
||||||
def get_tags(self):
|
def get_tags(self):
|
||||||
|
@ -15,6 +15,7 @@ from freezegun import freeze_time
|
|||||||
from moto import (
|
from moto import (
|
||||||
mock_dynamodb2,
|
mock_dynamodb2,
|
||||||
mock_lambda,
|
mock_lambda,
|
||||||
|
mock_iam,
|
||||||
mock_s3,
|
mock_s3,
|
||||||
mock_ec2,
|
mock_ec2,
|
||||||
mock_sns,
|
mock_sns,
|
||||||
@ -22,6 +23,7 @@ from moto import (
|
|||||||
settings,
|
settings,
|
||||||
mock_sqs,
|
mock_sqs,
|
||||||
)
|
)
|
||||||
|
from moto.sts.models import ACCOUNT_ID
|
||||||
from nose.tools import assert_raises
|
from nose.tools import assert_raises
|
||||||
from botocore.exceptions import ClientError
|
from botocore.exceptions import ClientError
|
||||||
|
|
||||||
@ -96,7 +98,7 @@ def test_invoke_requestresponse_function():
|
|||||||
conn.create_function(
|
conn.create_function(
|
||||||
FunctionName="testFunction",
|
FunctionName="testFunction",
|
||||||
Runtime="python2.7",
|
Runtime="python2.7",
|
||||||
Role="test-iam-role",
|
Role=get_role_name(),
|
||||||
Handler="lambda_function.lambda_handler",
|
Handler="lambda_function.lambda_handler",
|
||||||
Code={"ZipFile": get_test_zip_file1()},
|
Code={"ZipFile": get_test_zip_file1()},
|
||||||
Description="test lambda function",
|
Description="test lambda function",
|
||||||
@ -129,7 +131,7 @@ def test_invoke_event_function():
|
|||||||
conn.create_function(
|
conn.create_function(
|
||||||
FunctionName="testFunction",
|
FunctionName="testFunction",
|
||||||
Runtime="python2.7",
|
Runtime="python2.7",
|
||||||
Role="test-iam-role",
|
Role=get_role_name(),
|
||||||
Handler="lambda_function.lambda_handler",
|
Handler="lambda_function.lambda_handler",
|
||||||
Code={"ZipFile": get_test_zip_file1()},
|
Code={"ZipFile": get_test_zip_file1()},
|
||||||
Description="test lambda function",
|
Description="test lambda function",
|
||||||
@ -163,7 +165,7 @@ if settings.TEST_SERVER_MODE:
|
|||||||
conn.create_function(
|
conn.create_function(
|
||||||
FunctionName="testFunction",
|
FunctionName="testFunction",
|
||||||
Runtime="python3.7",
|
Runtime="python3.7",
|
||||||
Role="test-iam-role",
|
Role=get_role_name(),
|
||||||
Handler="lambda_function.lambda_handler",
|
Handler="lambda_function.lambda_handler",
|
||||||
Code={"ZipFile": get_test_zip_file2()},
|
Code={"ZipFile": get_test_zip_file2()},
|
||||||
Description="test lambda function",
|
Description="test lambda function",
|
||||||
@ -218,7 +220,7 @@ def test_invoke_function_from_sns():
|
|||||||
result = conn.create_function(
|
result = conn.create_function(
|
||||||
FunctionName="testFunction",
|
FunctionName="testFunction",
|
||||||
Runtime="python2.7",
|
Runtime="python2.7",
|
||||||
Role="test-iam-role",
|
Role=get_role_name(),
|
||||||
Handler="lambda_function.lambda_handler",
|
Handler="lambda_function.lambda_handler",
|
||||||
Code={"ZipFile": get_test_zip_file3()},
|
Code={"ZipFile": get_test_zip_file3()},
|
||||||
Description="test lambda function",
|
Description="test lambda function",
|
||||||
@ -262,7 +264,7 @@ def test_create_based_on_s3_with_missing_bucket():
|
|||||||
conn.create_function.when.called_with(
|
conn.create_function.when.called_with(
|
||||||
FunctionName="testFunction",
|
FunctionName="testFunction",
|
||||||
Runtime="python2.7",
|
Runtime="python2.7",
|
||||||
Role="test-iam-role",
|
Role=get_role_name(),
|
||||||
Handler="lambda_function.lambda_handler",
|
Handler="lambda_function.lambda_handler",
|
||||||
Code={"S3Bucket": "this-bucket-does-not-exist", "S3Key": "test.zip"},
|
Code={"S3Bucket": "this-bucket-does-not-exist", "S3Key": "test.zip"},
|
||||||
Description="test lambda function",
|
Description="test lambda function",
|
||||||
@ -287,7 +289,7 @@ def test_create_function_from_aws_bucket():
|
|||||||
result = conn.create_function(
|
result = conn.create_function(
|
||||||
FunctionName="testFunction",
|
FunctionName="testFunction",
|
||||||
Runtime="python2.7",
|
Runtime="python2.7",
|
||||||
Role="test-iam-role",
|
Role=get_role_name(),
|
||||||
Handler="lambda_function.lambda_handler",
|
Handler="lambda_function.lambda_handler",
|
||||||
Code={"S3Bucket": "test-bucket", "S3Key": "test.zip"},
|
Code={"S3Bucket": "test-bucket", "S3Key": "test.zip"},
|
||||||
Description="test lambda function",
|
Description="test lambda function",
|
||||||
@ -308,7 +310,7 @@ def test_create_function_from_aws_bucket():
|
|||||||
_lambda_region
|
_lambda_region
|
||||||
),
|
),
|
||||||
"Runtime": "python2.7",
|
"Runtime": "python2.7",
|
||||||
"Role": "test-iam-role",
|
"Role": result["Role"],
|
||||||
"Handler": "lambda_function.lambda_handler",
|
"Handler": "lambda_function.lambda_handler",
|
||||||
"CodeSha256": hashlib.sha256(zip_content).hexdigest(),
|
"CodeSha256": hashlib.sha256(zip_content).hexdigest(),
|
||||||
"CodeSize": len(zip_content),
|
"CodeSize": len(zip_content),
|
||||||
@ -334,7 +336,7 @@ def test_create_function_from_zipfile():
|
|||||||
result = conn.create_function(
|
result = conn.create_function(
|
||||||
FunctionName="testFunction",
|
FunctionName="testFunction",
|
||||||
Runtime="python2.7",
|
Runtime="python2.7",
|
||||||
Role="test-iam-role",
|
Role=get_role_name(),
|
||||||
Handler="lambda_function.lambda_handler",
|
Handler="lambda_function.lambda_handler",
|
||||||
Code={"ZipFile": zip_content},
|
Code={"ZipFile": zip_content},
|
||||||
Description="test lambda function",
|
Description="test lambda function",
|
||||||
@ -355,7 +357,7 @@ def test_create_function_from_zipfile():
|
|||||||
_lambda_region
|
_lambda_region
|
||||||
),
|
),
|
||||||
"Runtime": "python2.7",
|
"Runtime": "python2.7",
|
||||||
"Role": "test-iam-role",
|
"Role": result["Role"],
|
||||||
"Handler": "lambda_function.lambda_handler",
|
"Handler": "lambda_function.lambda_handler",
|
||||||
"CodeSize": len(zip_content),
|
"CodeSize": len(zip_content),
|
||||||
"Description": "test lambda function",
|
"Description": "test lambda function",
|
||||||
@ -383,7 +385,7 @@ def test_get_function():
|
|||||||
conn.create_function(
|
conn.create_function(
|
||||||
FunctionName="testFunction",
|
FunctionName="testFunction",
|
||||||
Runtime="python2.7",
|
Runtime="python2.7",
|
||||||
Role="test-iam-role",
|
Role=get_role_name(),
|
||||||
Handler="lambda_function.lambda_handler",
|
Handler="lambda_function.lambda_handler",
|
||||||
Code={"S3Bucket": "test-bucket", "S3Key": "test.zip"},
|
Code={"S3Bucket": "test-bucket", "S3Key": "test.zip"},
|
||||||
Description="test lambda function",
|
Description="test lambda function",
|
||||||
@ -414,7 +416,7 @@ def test_get_function():
|
|||||||
result["Configuration"]["FunctionName"].should.equal("testFunction")
|
result["Configuration"]["FunctionName"].should.equal("testFunction")
|
||||||
result["Configuration"]["Handler"].should.equal("lambda_function.lambda_handler")
|
result["Configuration"]["Handler"].should.equal("lambda_function.lambda_handler")
|
||||||
result["Configuration"]["MemorySize"].should.equal(128)
|
result["Configuration"]["MemorySize"].should.equal(128)
|
||||||
result["Configuration"]["Role"].should.equal("test-iam-role")
|
result["Configuration"]["Role"].should.equal(get_role_name())
|
||||||
result["Configuration"]["Runtime"].should.equal("python2.7")
|
result["Configuration"]["Runtime"].should.equal("python2.7")
|
||||||
result["Configuration"]["Timeout"].should.equal(3)
|
result["Configuration"]["Timeout"].should.equal(3)
|
||||||
result["Configuration"]["Version"].should.equal("$LATEST")
|
result["Configuration"]["Version"].should.equal("$LATEST")
|
||||||
@ -451,7 +453,7 @@ def test_get_function_by_arn():
|
|||||||
fnc = conn.create_function(
|
fnc = conn.create_function(
|
||||||
FunctionName="testFunction",
|
FunctionName="testFunction",
|
||||||
Runtime="python2.7",
|
Runtime="python2.7",
|
||||||
Role="test-iam-role",
|
Role=get_role_name(),
|
||||||
Handler="lambda_function.lambda_handler",
|
Handler="lambda_function.lambda_handler",
|
||||||
Code={"S3Bucket": bucket_name, "S3Key": "test.zip"},
|
Code={"S3Bucket": bucket_name, "S3Key": "test.zip"},
|
||||||
Description="test lambda function",
|
Description="test lambda function",
|
||||||
@ -477,7 +479,7 @@ def test_delete_function():
|
|||||||
conn.create_function(
|
conn.create_function(
|
||||||
FunctionName="testFunction",
|
FunctionName="testFunction",
|
||||||
Runtime="python2.7",
|
Runtime="python2.7",
|
||||||
Role="test-iam-role",
|
Role=get_role_name(),
|
||||||
Handler="lambda_function.lambda_handler",
|
Handler="lambda_function.lambda_handler",
|
||||||
Code={"S3Bucket": "test-bucket", "S3Key": "test.zip"},
|
Code={"S3Bucket": "test-bucket", "S3Key": "test.zip"},
|
||||||
Description="test lambda function",
|
Description="test lambda function",
|
||||||
@ -512,7 +514,7 @@ def test_delete_function_by_arn():
|
|||||||
fnc = conn.create_function(
|
fnc = conn.create_function(
|
||||||
FunctionName="testFunction",
|
FunctionName="testFunction",
|
||||||
Runtime="python2.7",
|
Runtime="python2.7",
|
||||||
Role="test-iam-role",
|
Role=get_role_name(),
|
||||||
Handler="lambda_function.lambda_handler",
|
Handler="lambda_function.lambda_handler",
|
||||||
Code={"S3Bucket": bucket_name, "S3Key": "test.zip"},
|
Code={"S3Bucket": bucket_name, "S3Key": "test.zip"},
|
||||||
Description="test lambda function",
|
Description="test lambda function",
|
||||||
@ -547,7 +549,7 @@ def test_publish():
|
|||||||
conn.create_function(
|
conn.create_function(
|
||||||
FunctionName="testFunction",
|
FunctionName="testFunction",
|
||||||
Runtime="python2.7",
|
Runtime="python2.7",
|
||||||
Role="test-iam-role",
|
Role=get_role_name(),
|
||||||
Handler="lambda_function.lambda_handler",
|
Handler="lambda_function.lambda_handler",
|
||||||
Code={"S3Bucket": "test-bucket", "S3Key": "test.zip"},
|
Code={"S3Bucket": "test-bucket", "S3Key": "test.zip"},
|
||||||
Description="test lambda function",
|
Description="test lambda function",
|
||||||
@ -599,7 +601,7 @@ def test_list_create_list_get_delete_list():
|
|||||||
conn.create_function(
|
conn.create_function(
|
||||||
FunctionName="testFunction",
|
FunctionName="testFunction",
|
||||||
Runtime="python2.7",
|
Runtime="python2.7",
|
||||||
Role="test-iam-role",
|
Role=get_role_name(),
|
||||||
Handler="lambda_function.lambda_handler",
|
Handler="lambda_function.lambda_handler",
|
||||||
Code={"S3Bucket": "test-bucket", "S3Key": "test.zip"},
|
Code={"S3Bucket": "test-bucket", "S3Key": "test.zip"},
|
||||||
Description="test lambda function",
|
Description="test lambda function",
|
||||||
@ -624,7 +626,7 @@ def test_list_create_list_get_delete_list():
|
|||||||
"FunctionName": "testFunction",
|
"FunctionName": "testFunction",
|
||||||
"Handler": "lambda_function.lambda_handler",
|
"Handler": "lambda_function.lambda_handler",
|
||||||
"MemorySize": 128,
|
"MemorySize": 128,
|
||||||
"Role": "test-iam-role",
|
"Role": get_role_name(),
|
||||||
"Runtime": "python2.7",
|
"Runtime": "python2.7",
|
||||||
"Timeout": 3,
|
"Timeout": 3,
|
||||||
"Version": "$LATEST",
|
"Version": "$LATEST",
|
||||||
@ -665,7 +667,7 @@ def lambda_handler(event, context):
|
|||||||
client.create_function(
|
client.create_function(
|
||||||
FunctionName="test-lambda-fx",
|
FunctionName="test-lambda-fx",
|
||||||
Runtime="python2.7",
|
Runtime="python2.7",
|
||||||
Role="test-iam-role",
|
Role=get_role_name(),
|
||||||
Handler="lambda_function.lambda_handler",
|
Handler="lambda_function.lambda_handler",
|
||||||
Description="test lambda function",
|
Description="test lambda function",
|
||||||
Timeout=3,
|
Timeout=3,
|
||||||
@ -698,7 +700,7 @@ def test_tags():
|
|||||||
function = conn.create_function(
|
function = conn.create_function(
|
||||||
FunctionName="testFunction",
|
FunctionName="testFunction",
|
||||||
Runtime="python2.7",
|
Runtime="python2.7",
|
||||||
Role="test-iam-role",
|
Role=get_role_name(),
|
||||||
Handler="lambda_function.handler",
|
Handler="lambda_function.handler",
|
||||||
Code={"S3Bucket": "test-bucket", "S3Key": "test.zip"},
|
Code={"S3Bucket": "test-bucket", "S3Key": "test.zip"},
|
||||||
Description="test lambda function",
|
Description="test lambda function",
|
||||||
@ -766,7 +768,7 @@ def test_invoke_async_function():
|
|||||||
conn.create_function(
|
conn.create_function(
|
||||||
FunctionName="testFunction",
|
FunctionName="testFunction",
|
||||||
Runtime="python2.7",
|
Runtime="python2.7",
|
||||||
Role="test-iam-role",
|
Role=get_role_name(),
|
||||||
Handler="lambda_function.lambda_handler",
|
Handler="lambda_function.lambda_handler",
|
||||||
Code={"ZipFile": get_test_zip_file1()},
|
Code={"ZipFile": get_test_zip_file1()},
|
||||||
Description="test lambda function",
|
Description="test lambda function",
|
||||||
@ -790,7 +792,7 @@ def test_get_function_created_with_zipfile():
|
|||||||
result = conn.create_function(
|
result = conn.create_function(
|
||||||
FunctionName="testFunction",
|
FunctionName="testFunction",
|
||||||
Runtime="python2.7",
|
Runtime="python2.7",
|
||||||
Role="test-iam-role",
|
Role=get_role_name(),
|
||||||
Handler="lambda_function.handler",
|
Handler="lambda_function.handler",
|
||||||
Code={"ZipFile": zip_content},
|
Code={"ZipFile": zip_content},
|
||||||
Description="test lambda function",
|
Description="test lambda function",
|
||||||
@ -819,7 +821,7 @@ def test_get_function_created_with_zipfile():
|
|||||||
"FunctionName": "testFunction",
|
"FunctionName": "testFunction",
|
||||||
"Handler": "lambda_function.handler",
|
"Handler": "lambda_function.handler",
|
||||||
"MemorySize": 128,
|
"MemorySize": 128,
|
||||||
"Role": "test-iam-role",
|
"Role": get_role_name(),
|
||||||
"Runtime": "python2.7",
|
"Runtime": "python2.7",
|
||||||
"Timeout": 3,
|
"Timeout": 3,
|
||||||
"Version": "$LATEST",
|
"Version": "$LATEST",
|
||||||
@ -835,7 +837,7 @@ def test_add_function_permission():
|
|||||||
conn.create_function(
|
conn.create_function(
|
||||||
FunctionName="testFunction",
|
FunctionName="testFunction",
|
||||||
Runtime="python2.7",
|
Runtime="python2.7",
|
||||||
Role="test-iam-role",
|
Role=(get_role_name()),
|
||||||
Handler="lambda_function.handler",
|
Handler="lambda_function.handler",
|
||||||
Code={"ZipFile": zip_content},
|
Code={"ZipFile": zip_content},
|
||||||
Description="test lambda function",
|
Description="test lambda function",
|
||||||
@ -866,7 +868,7 @@ def test_get_function_policy():
|
|||||||
conn.create_function(
|
conn.create_function(
|
||||||
FunctionName="testFunction",
|
FunctionName="testFunction",
|
||||||
Runtime="python2.7",
|
Runtime="python2.7",
|
||||||
Role="test-iam-role",
|
Role=get_role_name(),
|
||||||
Handler="lambda_function.handler",
|
Handler="lambda_function.handler",
|
||||||
Code={"ZipFile": zip_content},
|
Code={"ZipFile": zip_content},
|
||||||
Description="test lambda function",
|
Description="test lambda function",
|
||||||
@ -906,7 +908,7 @@ def test_list_versions_by_function():
|
|||||||
conn.create_function(
|
conn.create_function(
|
||||||
FunctionName="testFunction",
|
FunctionName="testFunction",
|
||||||
Runtime="python2.7",
|
Runtime="python2.7",
|
||||||
Role="arn:aws:iam::123456789012:role/test-iam-role",
|
Role=get_role_name(),
|
||||||
Handler="lambda_function.lambda_handler",
|
Handler="lambda_function.lambda_handler",
|
||||||
Code={"S3Bucket": "test-bucket", "S3Key": "test.zip"},
|
Code={"S3Bucket": "test-bucket", "S3Key": "test.zip"},
|
||||||
Description="test lambda function",
|
Description="test lambda function",
|
||||||
@ -935,7 +937,7 @@ def test_list_versions_by_function():
|
|||||||
conn.create_function(
|
conn.create_function(
|
||||||
FunctionName="testFunction_2",
|
FunctionName="testFunction_2",
|
||||||
Runtime="python2.7",
|
Runtime="python2.7",
|
||||||
Role="arn:aws:iam::123456789012:role/test-iam-role",
|
Role=get_role_name(),
|
||||||
Handler="lambda_function.lambda_handler",
|
Handler="lambda_function.lambda_handler",
|
||||||
Code={"S3Bucket": "test-bucket", "S3Key": "test.zip"},
|
Code={"S3Bucket": "test-bucket", "S3Key": "test.zip"},
|
||||||
Description="test lambda function",
|
Description="test lambda function",
|
||||||
@ -964,7 +966,7 @@ def test_create_function_with_already_exists():
|
|||||||
conn.create_function(
|
conn.create_function(
|
||||||
FunctionName="testFunction",
|
FunctionName="testFunction",
|
||||||
Runtime="python2.7",
|
Runtime="python2.7",
|
||||||
Role="test-iam-role",
|
Role=get_role_name(),
|
||||||
Handler="lambda_function.lambda_handler",
|
Handler="lambda_function.lambda_handler",
|
||||||
Code={"S3Bucket": "test-bucket", "S3Key": "test.zip"},
|
Code={"S3Bucket": "test-bucket", "S3Key": "test.zip"},
|
||||||
Description="test lambda function",
|
Description="test lambda function",
|
||||||
@ -976,7 +978,7 @@ def test_create_function_with_already_exists():
|
|||||||
response = conn.create_function(
|
response = conn.create_function(
|
||||||
FunctionName="testFunction",
|
FunctionName="testFunction",
|
||||||
Runtime="python2.7",
|
Runtime="python2.7",
|
||||||
Role="test-iam-role",
|
Role=get_role_name(),
|
||||||
Handler="lambda_function.lambda_handler",
|
Handler="lambda_function.lambda_handler",
|
||||||
Code={"S3Bucket": "test-bucket", "S3Key": "test.zip"},
|
Code={"S3Bucket": "test-bucket", "S3Key": "test.zip"},
|
||||||
Description="test lambda function",
|
Description="test lambda function",
|
||||||
@ -1008,7 +1010,7 @@ def test_create_event_source_mapping():
|
|||||||
func = conn.create_function(
|
func = conn.create_function(
|
||||||
FunctionName="testFunction",
|
FunctionName="testFunction",
|
||||||
Runtime="python2.7",
|
Runtime="python2.7",
|
||||||
Role="test-iam-role",
|
Role=get_role_name(),
|
||||||
Handler="lambda_function.lambda_handler",
|
Handler="lambda_function.lambda_handler",
|
||||||
Code={"ZipFile": get_test_zip_file3()},
|
Code={"ZipFile": get_test_zip_file3()},
|
||||||
Description="test lambda function",
|
Description="test lambda function",
|
||||||
@ -1038,7 +1040,7 @@ def test_invoke_function_from_sqs():
|
|||||||
func = conn.create_function(
|
func = conn.create_function(
|
||||||
FunctionName="testFunction",
|
FunctionName="testFunction",
|
||||||
Runtime="python2.7",
|
Runtime="python2.7",
|
||||||
Role="test-iam-role",
|
Role=get_role_name(),
|
||||||
Handler="lambda_function.lambda_handler",
|
Handler="lambda_function.lambda_handler",
|
||||||
Code={"ZipFile": get_test_zip_file3()},
|
Code={"ZipFile": get_test_zip_file3()},
|
||||||
Description="test lambda function",
|
Description="test lambda function",
|
||||||
@ -1098,7 +1100,7 @@ def test_invoke_function_from_dynamodb():
|
|||||||
func = conn.create_function(
|
func = conn.create_function(
|
||||||
FunctionName="testFunction",
|
FunctionName="testFunction",
|
||||||
Runtime="python2.7",
|
Runtime="python2.7",
|
||||||
Role="test-iam-role",
|
Role=get_role_name(),
|
||||||
Handler="lambda_function.lambda_handler",
|
Handler="lambda_function.lambda_handler",
|
||||||
Code={"ZipFile": get_test_zip_file3()},
|
Code={"ZipFile": get_test_zip_file3()},
|
||||||
Description="test lambda function executed after a DynamoDB table is updated",
|
Description="test lambda function executed after a DynamoDB table is updated",
|
||||||
@ -1149,7 +1151,7 @@ def test_invoke_function_from_sqs_exception():
|
|||||||
func = conn.create_function(
|
func = conn.create_function(
|
||||||
FunctionName="testFunction",
|
FunctionName="testFunction",
|
||||||
Runtime="python2.7",
|
Runtime="python2.7",
|
||||||
Role="test-iam-role",
|
Role=get_role_name(),
|
||||||
Handler="lambda_function.lambda_handler",
|
Handler="lambda_function.lambda_handler",
|
||||||
Code={"ZipFile": get_test_zip_file4()},
|
Code={"ZipFile": get_test_zip_file4()},
|
||||||
Description="test lambda function",
|
Description="test lambda function",
|
||||||
@ -1208,7 +1210,7 @@ def test_list_event_source_mappings():
|
|||||||
func = conn.create_function(
|
func = conn.create_function(
|
||||||
FunctionName="testFunction",
|
FunctionName="testFunction",
|
||||||
Runtime="python2.7",
|
Runtime="python2.7",
|
||||||
Role="test-iam-role",
|
Role=get_role_name(),
|
||||||
Handler="lambda_function.lambda_handler",
|
Handler="lambda_function.lambda_handler",
|
||||||
Code={"ZipFile": get_test_zip_file3()},
|
Code={"ZipFile": get_test_zip_file3()},
|
||||||
Description="test lambda function",
|
Description="test lambda function",
|
||||||
@ -1240,7 +1242,7 @@ def test_get_event_source_mapping():
|
|||||||
func = conn.create_function(
|
func = conn.create_function(
|
||||||
FunctionName="testFunction",
|
FunctionName="testFunction",
|
||||||
Runtime="python2.7",
|
Runtime="python2.7",
|
||||||
Role="test-iam-role",
|
Role=get_role_name(),
|
||||||
Handler="lambda_function.lambda_handler",
|
Handler="lambda_function.lambda_handler",
|
||||||
Code={"ZipFile": get_test_zip_file3()},
|
Code={"ZipFile": get_test_zip_file3()},
|
||||||
Description="test lambda function",
|
Description="test lambda function",
|
||||||
@ -1270,7 +1272,7 @@ def test_update_event_source_mapping():
|
|||||||
func1 = conn.create_function(
|
func1 = conn.create_function(
|
||||||
FunctionName="testFunction",
|
FunctionName="testFunction",
|
||||||
Runtime="python2.7",
|
Runtime="python2.7",
|
||||||
Role="test-iam-role",
|
Role=get_role_name(),
|
||||||
Handler="lambda_function.lambda_handler",
|
Handler="lambda_function.lambda_handler",
|
||||||
Code={"ZipFile": get_test_zip_file3()},
|
Code={"ZipFile": get_test_zip_file3()},
|
||||||
Description="test lambda function",
|
Description="test lambda function",
|
||||||
@ -1281,7 +1283,7 @@ def test_update_event_source_mapping():
|
|||||||
func2 = conn.create_function(
|
func2 = conn.create_function(
|
||||||
FunctionName="testFunction2",
|
FunctionName="testFunction2",
|
||||||
Runtime="python2.7",
|
Runtime="python2.7",
|
||||||
Role="test-iam-role",
|
Role=get_role_name(),
|
||||||
Handler="lambda_function.lambda_handler",
|
Handler="lambda_function.lambda_handler",
|
||||||
Code={"ZipFile": get_test_zip_file3()},
|
Code={"ZipFile": get_test_zip_file3()},
|
||||||
Description="test lambda function",
|
Description="test lambda function",
|
||||||
@ -1314,7 +1316,7 @@ def test_delete_event_source_mapping():
|
|||||||
func1 = conn.create_function(
|
func1 = conn.create_function(
|
||||||
FunctionName="testFunction",
|
FunctionName="testFunction",
|
||||||
Runtime="python2.7",
|
Runtime="python2.7",
|
||||||
Role="test-iam-role",
|
Role=get_role_name(),
|
||||||
Handler="lambda_function.lambda_handler",
|
Handler="lambda_function.lambda_handler",
|
||||||
Code={"ZipFile": get_test_zip_file3()},
|
Code={"ZipFile": get_test_zip_file3()},
|
||||||
Description="test lambda function",
|
Description="test lambda function",
|
||||||
@ -1350,7 +1352,7 @@ def test_update_configuration():
|
|||||||
fxn = conn.create_function(
|
fxn = conn.create_function(
|
||||||
FunctionName="testFunction",
|
FunctionName="testFunction",
|
||||||
Runtime="python2.7",
|
Runtime="python2.7",
|
||||||
Role="test-iam-role",
|
Role=get_role_name(),
|
||||||
Handler="lambda_function.lambda_handler",
|
Handler="lambda_function.lambda_handler",
|
||||||
Code={"S3Bucket": "test-bucket", "S3Key": "test.zip"},
|
Code={"S3Bucket": "test-bucket", "S3Key": "test.zip"},
|
||||||
Description="test lambda function",
|
Description="test lambda function",
|
||||||
@ -1395,7 +1397,7 @@ def test_update_function_zip():
|
|||||||
fxn = conn.create_function(
|
fxn = conn.create_function(
|
||||||
FunctionName="testFunctionZip",
|
FunctionName="testFunctionZip",
|
||||||
Runtime="python2.7",
|
Runtime="python2.7",
|
||||||
Role="test-iam-role",
|
Role=get_role_name(),
|
||||||
Handler="lambda_function.lambda_handler",
|
Handler="lambda_function.lambda_handler",
|
||||||
Code={"ZipFile": zip_content_one},
|
Code={"ZipFile": zip_content_one},
|
||||||
Description="test lambda function",
|
Description="test lambda function",
|
||||||
@ -1430,7 +1432,7 @@ def test_update_function_zip():
|
|||||||
"FunctionName": "testFunctionZip",
|
"FunctionName": "testFunctionZip",
|
||||||
"Handler": "lambda_function.lambda_handler",
|
"Handler": "lambda_function.lambda_handler",
|
||||||
"MemorySize": 128,
|
"MemorySize": 128,
|
||||||
"Role": "test-iam-role",
|
"Role": fxn["Role"],
|
||||||
"Runtime": "python2.7",
|
"Runtime": "python2.7",
|
||||||
"Timeout": 3,
|
"Timeout": 3,
|
||||||
"Version": "2",
|
"Version": "2",
|
||||||
@ -1453,7 +1455,7 @@ def test_update_function_s3():
|
|||||||
fxn = conn.create_function(
|
fxn = conn.create_function(
|
||||||
FunctionName="testFunctionS3",
|
FunctionName="testFunctionS3",
|
||||||
Runtime="python2.7",
|
Runtime="python2.7",
|
||||||
Role="test-iam-role",
|
Role=get_role_name(),
|
||||||
Handler="lambda_function.lambda_handler",
|
Handler="lambda_function.lambda_handler",
|
||||||
Code={"S3Bucket": "test-bucket", "S3Key": "test.zip"},
|
Code={"S3Bucket": "test-bucket", "S3Key": "test.zip"},
|
||||||
Description="test lambda function",
|
Description="test lambda function",
|
||||||
@ -1492,10 +1494,67 @@ def test_update_function_s3():
|
|||||||
"FunctionName": "testFunctionS3",
|
"FunctionName": "testFunctionS3",
|
||||||
"Handler": "lambda_function.lambda_handler",
|
"Handler": "lambda_function.lambda_handler",
|
||||||
"MemorySize": 128,
|
"MemorySize": 128,
|
||||||
"Role": "test-iam-role",
|
"Role": fxn["Role"],
|
||||||
"Runtime": "python2.7",
|
"Runtime": "python2.7",
|
||||||
"Timeout": 3,
|
"Timeout": 3,
|
||||||
"Version": "2",
|
"Version": "2",
|
||||||
"VpcConfig": {"SecurityGroupIds": [], "SubnetIds": []},
|
"VpcConfig": {"SecurityGroupIds": [], "SubnetIds": []},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_lambda
|
||||||
|
def test_create_function_with_invalid_arn():
|
||||||
|
err = create_invalid_lambda("test-iam-role")
|
||||||
|
err.exception.response["Error"]["Message"].should.equal(
|
||||||
|
"1 validation error detected: Value 'test-iam-role' at 'role' failed to satisfy constraint: Member must satisfy regular expression pattern: arn:(aws[a-zA-Z-]*)?:iam::(\d{12}):role/?[a-zA-Z_0-9+=,.@\-_/]+"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_lambda
|
||||||
|
def test_create_function_with_arn_from_different_account():
|
||||||
|
err = create_invalid_lambda("arn:aws:iam::000000000000:role/example_role")
|
||||||
|
err.exception.response["Error"]["Message"].should.equal(
|
||||||
|
"Cross-account pass role is not allowed."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_lambda
|
||||||
|
def test_create_function_with_unknown_arn():
|
||||||
|
err = create_invalid_lambda(
|
||||||
|
"arn:aws:iam::" + str(ACCOUNT_ID) + ":role/service-role/unknown_role"
|
||||||
|
)
|
||||||
|
err.exception.response["Error"]["Message"].should.equal(
|
||||||
|
"The role defined for the function cannot be assumed by Lambda."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def create_invalid_lambda(role):
|
||||||
|
conn = boto3.client("lambda", "us-west-2")
|
||||||
|
zip_content = get_test_zip_file1()
|
||||||
|
with assert_raises(ClientError) as err:
|
||||||
|
conn.create_function(
|
||||||
|
FunctionName="testFunction",
|
||||||
|
Runtime="python2.7",
|
||||||
|
Role=role,
|
||||||
|
Handler="lambda_function.handler",
|
||||||
|
Code={"ZipFile": zip_content},
|
||||||
|
Description="test lambda function",
|
||||||
|
Timeout=3,
|
||||||
|
MemorySize=128,
|
||||||
|
Publish=True,
|
||||||
|
)
|
||||||
|
return err
|
||||||
|
|
||||||
|
|
||||||
|
def get_role_name():
|
||||||
|
with mock_iam():
|
||||||
|
iam = boto3.client("iam", region_name="us-west-2")
|
||||||
|
try:
|
||||||
|
return iam.get_role(RoleName="my-role")["Role"]["Arn"]
|
||||||
|
except ClientError:
|
||||||
|
return iam.create_role(
|
||||||
|
RoleName="my-role",
|
||||||
|
AssumeRolePolicyDocument="some policy",
|
||||||
|
Path="/my-path/",
|
||||||
|
)["Role"]["Arn"]
|
||||||
|
@ -4,6 +4,7 @@ import os
|
|||||||
import json
|
import json
|
||||||
|
|
||||||
import boto
|
import boto
|
||||||
|
import boto.iam
|
||||||
import boto.s3
|
import boto.s3
|
||||||
import boto.s3.key
|
import boto.s3.key
|
||||||
import boto.cloudformation
|
import boto.cloudformation
|
||||||
@ -18,6 +19,7 @@ from moto import (
|
|||||||
mock_cloudformation_deprecated,
|
mock_cloudformation_deprecated,
|
||||||
mock_s3_deprecated,
|
mock_s3_deprecated,
|
||||||
mock_route53_deprecated,
|
mock_route53_deprecated,
|
||||||
|
mock_iam_deprecated,
|
||||||
)
|
)
|
||||||
from moto.cloudformation import cloudformation_backends
|
from moto.cloudformation import cloudformation_backends
|
||||||
|
|
||||||
@ -516,7 +518,7 @@ def test_create_stack_lambda_and_dynamodb():
|
|||||||
"Code": {"S3Bucket": "bucket_123", "S3Key": "key_123"},
|
"Code": {"S3Bucket": "bucket_123", "S3Key": "key_123"},
|
||||||
"FunctionName": "func1",
|
"FunctionName": "func1",
|
||||||
"Handler": "handler.handler",
|
"Handler": "handler.handler",
|
||||||
"Role": "role1",
|
"Role": get_role_name(),
|
||||||
"Runtime": "python2.7",
|
"Runtime": "python2.7",
|
||||||
"Description": "descr",
|
"Description": "descr",
|
||||||
"MemorySize": 12345,
|
"MemorySize": 12345,
|
||||||
@ -591,3 +593,12 @@ def test_create_stack_kinesis():
|
|||||||
stack = conn.describe_stacks()[0]
|
stack = conn.describe_stacks()[0]
|
||||||
resources = stack.list_resources()
|
resources = stack.list_resources()
|
||||||
assert len(resources) == 1
|
assert len(resources) == 1
|
||||||
|
|
||||||
|
|
||||||
|
def get_role_name():
|
||||||
|
with mock_iam_deprecated():
|
||||||
|
iam = boto.connect_iam()
|
||||||
|
role = iam.create_role("my-role")["create_role_response"]["create_role_result"][
|
||||||
|
"role"
|
||||||
|
]["arn"]
|
||||||
|
return role
|
||||||
|
@ -1773,11 +1773,25 @@ def lambda_handler(event, context):
|
|||||||
"Handler": "lambda_function.handler",
|
"Handler": "lambda_function.handler",
|
||||||
"Description": "Test function",
|
"Description": "Test function",
|
||||||
"MemorySize": 128,
|
"MemorySize": 128,
|
||||||
"Role": "test-role",
|
"Role": {"Fn::GetAtt": ["MyRole", "Arn"]},
|
||||||
"Runtime": "python2.7",
|
"Runtime": "python2.7",
|
||||||
"Environment": {"Variables": {"TEST_ENV_KEY": "test-env-val"}},
|
"Environment": {"Variables": {"TEST_ENV_KEY": "test-env-val"}},
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
|
"MyRole": {
|
||||||
|
"Type": "AWS::IAM::Role",
|
||||||
|
"Properties": {
|
||||||
|
"AssumeRolePolicyDocument": {
|
||||||
|
"Statement": [
|
||||||
|
{
|
||||||
|
"Action": ["sts:AssumeRole"],
|
||||||
|
"Effect": "Allow",
|
||||||
|
"Principal": {"Service": ["ec2.amazonaws.com"]},
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1791,7 +1805,6 @@ def lambda_handler(event, context):
|
|||||||
result["Functions"][0]["Description"].should.equal("Test function")
|
result["Functions"][0]["Description"].should.equal("Test function")
|
||||||
result["Functions"][0]["Handler"].should.equal("lambda_function.handler")
|
result["Functions"][0]["Handler"].should.equal("lambda_function.handler")
|
||||||
result["Functions"][0]["MemorySize"].should.equal(128)
|
result["Functions"][0]["MemorySize"].should.equal(128)
|
||||||
result["Functions"][0]["Role"].should.equal("test-role")
|
|
||||||
result["Functions"][0]["Runtime"].should.equal("python2.7")
|
result["Functions"][0]["Runtime"].should.equal("python2.7")
|
||||||
result["Functions"][0]["Environment"].should.equal(
|
result["Functions"][0]["Environment"].should.equal(
|
||||||
{"Variables": {"TEST_ENV_KEY": "test-env-val"}}
|
{"Variables": {"TEST_ENV_KEY": "test-env-val"}}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user