i have a cloudformation stack file on s3 which works just fine when I launch it from console. but when I trigger the same script using boto3 from AWS lambda, i get an encoded error message. Decoding it then gives me the following json output. (converted to yaml for readability)
---
allowed: false
explicitDeny: false
matchedStatements:
items: []
failures:
items: []
context:
principal:
id: AROA3H7OMTCQKOORZGNNY:Spawn-reward-service
arn: arn:aws:sts::773057xxxxxx:assumed-role/Spawn-reward-service-role-g0vgzj5h/Spawn-reward-service
action: ec2:RequestSpotFleet
resource: arn:aws:ec2:us-east-1:773057xxxxxx:subnet/subnet-e18921ca
conditions:
items:
- key: ec2:Vpc
values:
items:
- value: arn:aws:ec2:us-east-1:773057xxxxxx:vpc/vpc-aa2884c1
- key: aws:Resource
values:
items:
- value: subnet/subnet-e18921ca
- key: aws:Account
values:
items:
- value: '773057xxxxxx'
- key: ec2:AvailabilityZone
values:
items:
- value: us-east-1e
- key: ec2:ResourceTag/Name
values:
items:
- value: 1e subnet
- key: ec2:SubnetID
values:
items:
- value: subnet-e18921ca
- key: aws:Region
values:
items:
- value: us-east-1
- key: aws:Service
values:
items:
- value: ec2
- key: aws:Type
values:
items:
- value: subnet
- key: 773057xxxxxx:Name
values:
items:
- value: 1e subnet
- key: ec2:Region
values:
items:
- value: us-east-1
- key: aws:ARN
values:
items:
- value: arn:aws:ec2:us-east-1:773057xxxxxx:subnet/subnet-e18921ca
The Lambda role has AmazonEC2SpotFleetTaggingRole, NetworkAdministrator and AWSCloudFormationFullAccess policies attached. So not sure where the hangup is. Any help appreciated.
Here is the lambda function in full for reference.
import json, boto3
def lambda_handler(event, context):
cloudformation = boto3.client('cloudformation')
response = cloudformation.create_stack(
StackName='yj',
TemplateURL='https://s3.amazonaws.com/cf-templates-xxxxxxxxxxxx-us-east-1/reward-service-01-spot.yaml',
Parameters=[
{
'ParameterKey': 'InstanceType',
'ParameterValue': 't2.large'
}
]
)
return response
I am specifying the role in my template - Do you mean to say, it inherits the lambda role and overrides the role in my script? In any case, i added the AmazonEC2SpotFleetTaggingRole which allows request spot instances, but with no luck. I realized my json was truncated. updating my question and posting it as yaml in case it is hiding any clues.
I am not sure it has anything to do with VPCs though. I did try to move the lambda into a VPC, but that just causes the lambda to timeout and never trigger the stack even after a minute.
The "different role" I was talking about is passing the following to create_stack():
RoleARN (string) -- The Amazon Resource Name (ARN) of an Identity and Access Management (IAM) role that CloudFormation assumes to create the stack. CloudFormation uses the role's credentials to make calls on your behalf. CloudFormation always uses this role for all future operations on the stack. Provided that users have permission to operate on the stack, CloudFormation uses this role even if the users don't have permission to pass it. Ensure that the role grants least privilege. If you don't specify a value, CloudFormation uses the role that was previously associated with the stack. If no role is available, CloudFormation uses a temporary session that's generated from your user credentials.
As it looks like you're not providing a RoleARN, your Lambda's role will be used to execute all of CloudFormation's AWS API calls while creating the Stack.
i did try passing the role ARN using
unfortunately I get Role arn:aws:iam::773057xxxxxx:role/aws-ec2-spot-fleet-tagging-role is invalid or cannot be assumed". Since this is an AWS managed role, i cannot edit it, but it is setup to be assumed based on my reading of the policy.