Jobs from specific AWS Batch permissions - amazon-web-services

How to allow only jobs from a certain AWS Batch queue (and based on a specific job description) to publish to the specific SNS topic?
I though about attaching to jobs IAM policy with the statement:
{
"Effect": "Allow",
"Action": "sns:Publish",
"Resource": ["<arn of the specific SNS topic"]
"Condition": {"ArnEquals": {"aws:SourceArn": "arn:aws:???"}}
}
But what should be the source ARN? ARN of the job queue, ARN of the job definition? Or maybe this should be set up completely differently?

I had a similar experience when worked with AWS Batch jobs executed in Fargate containers which follow the same principles as ECS in scope of assigning roles and permissions.
If you are going to publish messages into specific topic from the code executed inside of your container, then you should create a role with necessary permissions and then use its ARN in the JobRoleArn property of your job definition.
For example (there can be minor mistakes in the code below, but I am just trying to explain the concept here):
Role cloudformation:
"roleresourceID": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"AWS": "*"
}
}
],
"Version": "2012-10-17"
},
"RoleName": "your-job-role"
}
}
Policy attached to the role:
"policyresourceid": {
"Type": "AWS::IAM::Policy",
"Properties": {
"PolicyDocument": {
"Statement": [
{
"Action": "sns:Publish",
"Effect": "Allow",
"Resource": "<arn of the specific SNS topic>"
}
],
"Version": "2012-10-17"
},
"PolicyName": "your-job-role-policy",
"Roles": [
{
"Ref": "roleresourceID"
}
]
}
}
And finally attach role to the Job Definition:
....other job definition properties
"JobRoleArn": {
"Fn::GetAtt": [
"roleresourceID",
"Arn"
]
}
Of course you may structure and format roles and policies in way you like, the main idea of this explanation is that you need to attach proper role using JobRoleArn property of your job definition.

Related

AWS Service:ecs-tasks.amazonaws.com conditions keys not working

I am trying to create assume role policy for an IAM role which will be assumed by ECS TASK. I want to put a condition that only ECS Container with specific Arn should be able to assume role.
Here is my policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ecs-tasks.amazonaws.com"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringLike": {
"ecs:cluster": "ECS cluster Arn"
}
}
}
]
}
The above policy is not working and even not letting the ECS Cluster mentioned above to assume the role. So, is there any other way we can do this? Any help would be appreciated.

Lambda call fails with no permission error

I have a custom resource in cloudformation template that references a lambda function . Inside the lambda function , I have written code to push items into a DynamoDB table . However , the operation is failing when the cloudformation stack is being created . The error is as follows :
User: arn:aws:sts::551250655555:assumed-role/custom-resource-stack-CustomResourceLambdaExecutio-1OX3T8494LEP5/custom-resource-stack-CustomResourceFunction-1GLEDE3BEPWDP is not authorized to perform: dynamodb:DescribeTable on resource: arn:aws:dynamodb:us-east-1:551250655555:table/MasterTable1
My lambda function name is : custom-resource-stack-CustomResourceFunction-1GLEDE3BEPWDP
and my custom role created is : custom-resource-stack-CustomResourceLambdaExecutio-1OX3T8494LEP5
However , in my serverless template file , I have provided the following permissions :
"CustomResourceLambdaExecutionPolicy": {
"DependsOn": ["CustomResourceLambdaExecutionRole"],
"Type": "AWS::IAM::Policy",
"Properties": {
"PolicyName": "CustomResourceLambdaExecutionPolicyDocument",
"Roles": [{
"Ref": "CustomResourceLambdaExecutionRole"
}],
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [{
"Sid": "DynamoDBAccess",
"Action": "dynamodb:*",
"Effect": "Allow",
"Resource": "*"
},
{
"Sid": "CloudwatchLogGroupAccess",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Effect": "Allow",
"Resource": "*"
}
]
}
}
}
which gives access to all dynamodb operations and tables . Any ideas on what I am doing wrong here .
You are experiencing a race condition.
The Lambda function depends on the IAM role but not on the policy. Thus the function is invoked before the IAM policy is attached to the role.
If you add the policy to the role as part of the IAM role definition that should fix it.
You can also make the Lambda function depend on the IAM policy.

CloudFormation: The role defined for the function cannot be assumed by Lambda

I've been searching for this error and nothing really answers how I can fix it with my CloudFormation template. From the events log, I can see that the role was created before the Lambda functions.
Could you please help?
You are probably missing an AssumeRolePolicyDocument allowing Lambda (lambda.amazonaws.com) to assume your IAM role.
Example:
...
"LambdaRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {"Service" : "lambda.amazonaws.com"},
"Action": ["sts:AssumeRole"]
}]
},
"Path": "/",
"Policies": [...]
}
}
...

AWS IAM Instance Profile to Administer EC2 Instances With that Profile

I have an IAM user that launches a CloudFormation stack containing an
- EC2 Instance with an
- IAM Instance Profile associated with an
- IAM Role
in the AWS::CloudFormation::Init block, the EC2 instance performs some actions that require it to call some ec2:* API actions. However, this instance should ONLY be able to call these actions for that instance itself.
The user that launches the stack has the permission to attach only a set of predefined policies and to create roles. Something like this
"CloudFormationStackLauncher": {
"Type": "AWS::IAM::ManagedPolicy",
"Properties": {
"Description": "Allows attached entity to attach and detach required policies from roles it creates.",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"iam:AttachRolePolicy",
"iam:DetachRolePolicy"
],
"Resource": "*",
"Condition": {
"ArnEquals": {
"iam:PolicyArn": [
"arn:aws:iam:::policy/InstanceThatCanManageItself",
]
}
}
},
{
"Effect": "Allow",
"Action": [
"iam:CreateRole"
],
"Resource": "*"
}
]
}
}
}
So I need a definition for the policy InstanceThatCanManageItself (which needs to be defined ahead of time by a user with full admin permissions). Ideally, it would look something like:
{
"Effect": "Allow",
"Action": [
"ec2:*"
],
"Resource": [
"${ec2:SourceInstanceARN}"
]
}
But it says this policy isn't valid because the policy variable ec2:SourceInstanceARN isn't in the format of a valid ARN. I've tried using tags on the EC2 instance and adding Conditions to the policy, but it doesn't seem to work when the condition is dynamic, like this:
{
"Effect": "Allow",
"Action": [
"ec2:*"
],
"Resource": [
"*"
],
"Condition": {
"StringLike": {
"ec2:ResourceTag/role" : "${aws:userid}"
}
}
}
in the above, I'm dynamically adding a tag to the launched EC2 instance with the format "RoleId:InstanceId" as defined for the value specified for {aws:userid}, based on the description here: http://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_variables.html. This approach validates, but doesn't work...either because it's dynamic...or because the action types aren't supports for the ResourceTag context key maybe...
Is there any way to accomplish this?
Thanks.
Resource tag-based authorizations will work only for certain operations. See, for example: EC2 Supported IAM actions. For example, all Describe operations are not supported and would have to be permissioned via a separate policy statement.
As an example of operations that support resource tags, attaching/detaching volumes (see same link above for supported operations and their requirements), so the following policy would work:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:AttachVolume",
"ec2:DetachVolume"
],
"Resource": "*",
"Condition": {
"StringLike": {
"ec2:ResourceTag/policyuser": "${aws:userid}"
}
}
}
]
}
, provided both the volume and ec2 instance are tagged with tag 'policyuser' and value equal to role-id:ec2-instance-id (see IAM User Guide Reference Policy Variables), where role-id is the unique identifier of the role, obtained via e.g.
aws iam get-role --role-name rolename

AWS Policy Limited Administrator

I want to create a policy that allows an IAM user or role to create a set of resources (for example EC2 instances) and then manage (delete, update, etc) ONLY those resources. I hope I can accomplish this using IAM variables, wildcards, and/or conditions, but I'm not sure how.
My policy would look something like this ideally
{
"Effect": "Allow",
"Action": [
"ec2:*"
],
"Condition": [
{ "Created_By_The_Instance_Profile_In_The_CFN_Stack_That_Created_The_EC2Instance}" }
]
}
Further, what if I want to grant the EC2 instance profile to do ssm:CreateAssociation for an SSM document that was created in the same stack as the EC2 instance itself? In other words, I have a stack with an EC2 instance, and IAM Instance Profile, an IAM Role, and an SSM document and I want the EC2 instance to CreateAssociation on startup, via UserData. The user that launches the stack should have access to create these resources, but NOT to create new policies (effectively making them an administrator). I want to create a Role + Policy ahead of time and grant the stack creator the ability to attach this Role to the IAM Instance Profile Role it creates.
So, ahead of time, I (the admin), create a policy and role as such
"DeployerRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"ec2.amazonaws.com",
"lambda.amazonaws.com"
],
"AWS": "*"
},
"Action": [
"sts:AssumeRole"
]
}
]
}
}
},
"PolicyManagerPolicy": {
"Type": "AWS::IAM::ManagedPolicy",
"Properties": {
"Description": "Allows CFN deployer to attach and detach required policies.",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"iam:AttachRolePolicy",
"iam:DetachRolePolicy"
],
"Resource": "*",
"Condition": {
"ArnEquals": {
"iam:PolicyArn": [
"The_Policy_Arn_I_Want_To_Create"
]
}
}
},
{
"Effect": "Allow",
"Action": [
"iam:CreateRole"
],
"Resource": "*"
}
]
},
"Roles": [ { "Ref": "DeployerRole" } ]
}
}
The "limited administrator" deployer (an IAM user in the DeployerRole) should be able to launch a stack containing an:
EC2 Instance
IAM Instance Profile
IAM Role
SSM Document
I need The_Policy_Arn_I_Want_To_Create to:
Allow ONLY the EC2 Instance created by the stack to be able to CreateAssociation ONLY with the SSM Document created by the stack. Using tags is fine, but since the Resource for the SSM document would not be able to use tags, how can I do this?
ec2 does not know about the account who created the instance (you might have that if you enable CloudTrail), a possibility will be to tag the ec2 instance when you create it with the user account and then read that from your policy as
"Condition": {"StringEquals": {"ec2:ResourceTag/<tag where the username will be>": "${aws:username}"