I am creating a lambda function that will send emails (nothing new). I am having issues with the policy that I am creating. TFSec busted me with a the Resource meta-attribute and indicated that "*" isn't allowed. So all I am trying to do is limit my policy to my lambda function. I figured I could dynamically create the ARN as i have done in the past. Well, the only way I found that it works is leveraging the "condition" meta-attribute BUT..., when I used the condition, I get this error:
│ Error: error creating Lambda Function (1):
InvalidParameterValueException: The provided execution role does not
have permissions to call CreateNetworkInterface on EC2
│ { │ RespMetadata: { │ StatusCode: 400, │ RequestID:
"3b8fc1dd-21d8-xxxx-xxx-xxxxxxx" │ }, │ Message_: "The provided
execution role does not have permissions to call
CreateNetworkInterface on EC2", │ Type: "User" │ }
Whats killing me is that the permission is set in my policy, see below:
resource "aws_iam_role_policy" "lambda_sendmail_policy" {
name = "lambda-sendmail"
role = aws_iam_role.lambda_sendmail_role.id
policy = jsonencode({
"Version" : "2012-10-17",
"Statement" : [
{
"Sid" : "Stmt163546987325",
"Effect" : "Allow",
"Action" : [
"ec2:DescribeInstances",
"ec2:CreateNetworkInterface",
"ec2:AttachNetworkInterface",
"ec2:DescribeNetworkInterfaces",
"ec2:DeleteNetworkInterface",
"autoscaling:CompleteLifecycleAction"
],
"Resource" : "*",
"Condition" : {
"StringEquals" : {
"lambda:FunctionArn" : "arn:aws:lambda:us-east-1:${local.accountid}:function:${var.appenv}-${var.lambda_appname}"
}
}
},
{
"Effect" : "Allow",
"Action" : [
"logs:PutLogEvents",
"logs:CreateLogStream"
],
"Resource" : [
"arn:aws:logs:us-east-1:${local.accountid}:log-group:/aws/lambda/*"
]
},
{
"Effect" : "Allow",
"Action" : [
"xray:PutTraceSegments",
"xray:PutTelemetryRecords"
],
"Resource" : "*"
}
]
})
}
Clearly the permission is there but I am passing the Lambda ARN incorrectly need some help here.
If I remove the condition it works but TFSEC catches me telling me that I need to specify the resource.
I am not sure if Lambda is supported by the condition attribute but any help here woudl be great.
You can't put this condition for the ec2 actions mentioned:
"Condition" : {
"StringEquals" : {
"lambda:FunctionArn" : "arn:aws:lambda:us-east-1:${local.accountid}:function:${var.appenv}-${var.lambda_appname}"
}
}
The condition to use for most of those ec2:* actions is...
"Condition": {
"ArnLikeIfExists": {
"ec2:Vpc": "your_vpc_arn"
}
}
This block limits the permission to the vpc shared by the function and fails to true for certain lambda actions like creation/update where the api calls don't include the vpc arn. This is about as tight as you can get this policy.
I'd move autoscaling to it's own block also, because you can definitely tighten that up.
Related
I created a secret in AWS Secrets Manager. I want one IAM user and a federated user to be able to list, describe and retrieve the secret. I defined the following policy:
{
"Version" : "2012-10-17",
"Statement" : [ {
"Effect" : "Allow",
"Principal" : {
"AWS" : [
"arn:aws:iam::123456789:user/IAMUser1",
"arn:aws:iam::123456789:role/UAT-Developer/dev_user1#mycompany.com"
]
},
"Action" : [ "secretsmanager:GetSecretValue", "secretsmanager:DescribeSecret", "secretsmanager:ListSecretVersionIds", "secretsmanager:ListSecrets" ],
"Resource" : "*"
} ]
}
but it is throwing This resource policy contains an unsupported principal.
I also tried the below syntax for Principal but did not work.
"Principal" : {
"AWS" : "arn:aws:iam::123456789:user/IAMUser1",
"AWS" : "arn:aws:iam::123456789:role/UAT-Developer/dev_user1#mycompany.com"
}
Please help me get this correct.
I got it. We have to put assumed-role instead of just role.
arn:aws:iam::123456789:assumed-role/UAT-Developer/dev_user1#mycompany.com
I want to make my IAM policy conditional, to allow it to work with an EC2 instance that has definite assumed role. The following syntax works great if I know the id of that instance, sasying it's i-1111111111111111:
{
"Version" : "2012-10-17",
"Statement" : [ {
"Effect" : "Allow",
"Principal" : {
"AWS": "arn:aws:sts::111122223333:assumed-role/MyRole/i-1111111111111111"
},
"Action" : "secretsmanager:GetSecretValue",
"Resource" : "*"
} ]
}
However I want to allow this access for any future EC2 instance with the same role. As wildcards do not work in Principal field, I try to specify a wildcarded condition:
"Principal" : "*",
"Condition": {
"StringLike": {
"aws:PrincipalArn": "arn:aws:sts::111122223333:assumed-role/MyRole/*"
}
},
but this does not grant access.
What the correct syntax should be for wildcarded principal?
I have the following statement in my IAM policy:
{
"Sid" : "AllowDetachingAWSManagedPolicies",
"Effect" : "Allow",
"Action" : [
"organizations:DetachPolicy"
],
"Resource" : "*",
"Condition" : {
"StringEquals" : {
"organizations:PolicyType" : "SERVICE_CONTROL_POLICY"
}
}
}
However, when I try to detach the FullAWSAccess policy from an AWS Organizations account, I get AccessDenied, as if my IAM policy wasn't sufficient. I have made sure that there is another SCP in addition to FullAWSAccess, so the issue is not that there would remain no SCPs attached to the account.
What is going wrong?
Strangely enough, the AWS-managed FullAWSAccess policy does not count as a SERVICE_CONTROL_POLICY even though it is listed as such on the AWS Organizations Policies page.
When I removed the condition, I no longer got AccessDenied errors:
{
"Sid" : "AllowDetachingAWSManagedPolicies",
"Effect" : "Allow",
"Action" : [
"organizations:DetachPolicy"
],
"Resource" : "*"
}
Another thing I tried to do was to specify a resource that matched FullAWSAccess:
"Resource": "arn:aws:organizations::aws:policy/service_control_policy/p-*"
But that similarly resulted in an AccessDenied error. So I left it as:
"Resource": "*"
I am attempting to deploy a CloudFormation template that pulls in some parameters from SSM using the method described in this blog-post: https://aws.amazon.com/blogs/mt/integrating-aws-cloudformation-with-aws-systems-manager-parameter-store/
The relevant excerpt from the Parameters section of the CF template is:
"ZoneName" : {
"Type" : "AWS::SSM::Parameter::Value<String>",
"Description" : "DNS Hostname Zone",
"Default" : "/Deimos/ZoneName"
},
"ZoneId" : {
"Type" : "AWS::SSM::Parameter::Value<String>",
"Description" : "DNS Hostname Zone",
"Default" : "/Deimos/ZoneId"
},
However, I'm getting the following error when I attempt to deploy it (via CodePipeline):
Action execution failed
AccessDenied. User doesn't have permission to call ssm:GetParameters (Service: AmazonCloudFormation; Status Code: 400; Error Code: ValidationError; Request ID: d6756fbe-fd41-4ac5-93bd-56e5b397445e)
I've got a Role and Policy setup for CloudFormation that includes the following section to grant access to some parameter namespaces within SSM:
{
"Sid": "XonoticCFFetchParameters",
"Effect": "Allow",
"Action": [
"ssm:GetParameters",
"ssm:GetParameter"
],
"Resource": [
"arn:aws:ssm:*:<aws account #>:parameter/Deimos/*",
"arn:aws:ssm:*:<aws account #>:parameter/Installers/*",
"arn:aws:ssm:*:<aws account #>:parameter/Xonotic/*"
]
},
These seem to have been applied just fine, based on the use of
aws iam simulate-principal-policy --policy-source-arn "arn:aws:iam::<aws account #>:role/Xonotic-CloudFormationDeploy" --action-names "ssm:getParameters" --resource-arns "arn:aws:ssm:*:<aws account #>:parameter/Deimos/ZoneName"
{
"EvaluationResults": [
{
"EvalActionName": "ssm:getParameters",
"EvalResourceName": "arn:aws:ssm:*:<aws account #>:parameter/Deimos/ZoneName",
"EvalDecision": "allowed",
"MatchedStatements": [
{
"SourcePolicyId": "Xonotic-Deployment",
"StartPosition": {
"Line": 3,
"Column": 19
},
"EndPosition": {
"Line": 16,
"Column": 10
}
}
],
"MissingContextValues": []
}
]
}
So, the Role I'm using should have the access needed to fetch the parameter in question, but it's not working and I'm out of things to check.
Ok - so in this case it turns out there was a JSON parameters file that was part of the build pipeline that was overriding one of my parameters with an invalid value (it was putting the actual zone name in ZoneName).
Fixed that and parameters are now being passed to my build process just fine.
I've two AWS Cloudformation stacks, one for IAM roles and the second to create an AWS service and import the respective roles into it using Cloudformation.
When 10+ services are deployed the following error appears randomly on 1 or 2 of the services -
AWS::ECS::Service service Unable to assume role and validate the
listeners configured on your load balancer. Please verify that the ECS
service role being passed has the proper permissions.
If all the services are torn down and the services redployed to the ECS cluster, the error appears but for different services.
The AWS fix for this can be seen here
If the 1 or 2 broken services are torn down and redeployed the services deploy without issue. So the problem appears to only occur when many services are deployed at the same time - this indicates it may be an IAM propagation timing issue within Cloudformation.
I've tried adding depends on in the service definition -
"service" : {
"Type" : "AWS::ECS::Service",
"DependsOn" : [
"taskdefinition",
"ECSServiceRole"
],
"Properties" : {
"Cluster" : { "Ref": "ECSCluster"},
"Role" : {"Ref" : "ECSServiceRole"},
etc...
}
}
But this doesn't work.
As you can note, I've also removed the IAM import value for the ECSServiceRole and replaced it with an inline resource policy seen here -
"ECSServiceRole" : {
"Type" : "AWS::IAM::Role",
"Properties" : {
"AssumeRolePolicyDocument" : {
"Statement" : [
{
"Sid": "",
"Effect" : "Allow",
"Principal" : {
"Service" : [
"ecs.amazonaws.com"
]
},
"Action" : [
"sts:AssumeRole"
]
}
]
},
"Path" : "/",
"Policies" : [
{
"PolicyName" : "ecs-service",
"PolicyDocument" : {
"Statement" : [
{
"Effect" : "Allow",
"Action" : [
"ec2:Describe*",
"ec2:AuthorizeSecurityGroupIngress",
"elasticloadbalancing:DeregisterInstancesFromLoadBalancer",
"elasticloadbalancing:DeregisterTargets",
"elasticloadbalancing:Describe*",
"elasticloadbalancing:RegisterInstancesWithLoadBalancer",
"elasticloadbalancing:RegisterTargets",
"sns:*"
],
"Resource" : "*"
}
]
}
}
]
}
}
But again - the inline policy doesn't fix the issue either.
Any ideas or pointers would be much appreciated!
In reply to answer 1.
Thank you - I wasn't aware of this improvment.
Is this the correct way to associate the service linked role for ECS?
"ECSServiceRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": [
"ecs.amazonaws.com"
]
},
"Action": [
"sts:AssumeRole"
]
}
]
},
"Path": "/",
"Policies": [
{
"PolicyName": "CreateServiceLinkedRoleForECS",
"PolicyDocument": {
"Statement": [
{
"Effect": "Allow",
"Action": [
"iam:CreateServiceLinkedRole",
"iam:PutRolePolicy",
"iam:UpdateRoleDescription",
"iam:DeleteServiceLinkedRole",
"iam:GetServiceLinkedRoleDeletionStatus"
],
"Resource": "arn:aws:iam::*:role/aws-service-role/ecs.amazonaws.com/AWSServiceRoleForECS*",
"Condition": {
"StringLike": {
"iam:AWSServiceName": "ecs.amazonaws.com"
}
}
}
]
}
}
]
}
}
Final Answer
After months of intermittent on-going issues with AWS regarding this matter AWS came back to say they were throttling us in the background, on the ELB. This is why the random and varied issues were appearing when deploying 3+ docker services via Cloudformation at the same time. The solution was nothing to do with IAM permissions, rather it was to increase the rate limit on the ELB via the "AWS Service Team".
So the fix was to continue using the two stack approach in Cloudformation, one with the IAM roles, which in turn were imported into the service layer stack. The fix was to add a depends on in the service definition for all of the other stack resources in the service layer script. By doing this it allows sufficient time for the IAM roles to be imported and executed by the service, thus this was a Cloudformation resource creation timing issue.
"service" : {
"Type" : "AWS::ECS::Service",
"DependsOn" : [
"TaskDefinition",
"EcsElasticLoadBalancer",
"DnsRecord"
],
"Properties" : {
etc...
}
}
UPDATE:
As of July 19th 2018, it is now possible to create a IAM Service-Linked Roles using CloudFormation https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-servicelinkedrole.html.
EcsServiceLinkedRole:
Type: "AWS::IAM::ServiceLinkedRole"
Properties:
AWSServiceName: "ecs.amazonaws.com"
Description: "Role to enable Amazon ECS to manage your cluster."
OLD ANSWER:
Creating your own ECSServiceRole is no longer required. By not specifying a role for your service, AWS will default on using the ECS Service-Linked role. If your AWS account is recent enough, or you have already created a cluster via the console you don't have to do anything for this to work. If not, run the following command to create the role: aws iam create-service-linked-role --aws-service-name ecs.amazonaws.com.