Execute ssm.send_command to EC2 from Lambda. IAM problems - python-2.7

I have problems with execution command on Windows machine from Lambda function using ssm.send_command in Python. This Lambda functions should execute simple command on windows machine:
import boto3
ssm = boto3.client('ssm')
region = 'us-east-1'
instances = ['i-XXXXXXXXXXXXX']
def lambda_handler(event, context):
response = ssm.send_command(
InstanceIds=instances,
DocumentName='AWS-RunPowerShellScript',
DocumentVersion='$DEFAULT',
DocumentHash='2142e42a19e0955cc09e43600bf2e633df1917b69d2be9693737dfd62e0fdf61',
DocumentHashType='Sha256',
TimeoutSeconds=123,
Comment='string',
Parameters={
'commands': [
# 'query user'
'mkdir test-dir'
]
},
MaxErrors='1',
CloudWatchOutputConfig={
'CloudWatchLogGroupName': 'WindowsLogs',
'CloudWatchOutputEnabled': True
}
)
print response
Execution role for this L-functions is
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ssm:SendCommand"
],
"Resource": [
"arn:aws:ssm:*:*:document/*"
]
},
{
"Effect": "Allow",
"Action": [
"ssm:SendCommand"
],
"Resource": [
"arn:aws:ec2:*:*:instance/*",
"arn:aws:ec2:*:*:*"
]
},
{
"Action": [
"iam:PassRole"
],
"Effect": "Allow",
"Resource": "*"
}
]
}
Also I added policies:
AmazonEC2FullAccess
AmazonEC2RoleforSSM
AmazonSSMManagedInstanceCore
CloudWatchLogsFullAccess
AmazonSSMFullAccess
AmazonSSMAutomationRole
AmazonSSMMaintenanceWindowRole
For EC2 no roles were assigned
Problem: I don't see that folder "test-dir' was created on Windows server. Please can you help me to determine what is missing, or how can I configure Lambda function for executing command and send results to CloudWatch.
Thank you.

You need to assign the AmazonSSMFullAccess policy to the instance, otherwise it won't work.
Make sure to restart the instance after the change.
If that doesn't work:
Add try and except blocks to your code to check what's the error.
Check that you have the SSMAgent installed on your instance (connect to it, open PowerShell and execute Restart-Service AmazonSSMAgent).

Thank you #fsinis90 for your recommendations.
I tried them and also I added such policies to my instance's role:
AWSHealthFullAccess
AmazonEC2RoleforSSM
AWSConfigUserAccess
AmazonSSMFullAccess
CloudWatchReadOnlyAccess
And it helps.

Related

Adding custom cidr to ingress security group using Lambda without default vpc

First of all I have been searching stackflow and the internet for this but I didn't find exactly where the issue is.
Basically I am trying to add custom cidr ips to a security group via lambda function. I have given all the appropriate permissions (as far as i can tell) [REMOVED]and also tried attaching the vpc (which is non-default) to the lambda function to access the security group[REMOVED].
But I am getting "An error occurred (VPCIdNotSpecified) when calling the AuthorizeSecurityGroupIngress operation: No default VPC for this user"
Policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"ec2:RevokeSecurityGroupIngress",
"ec2:CreateNetworkInterface",
"ec2:AuthorizeSecurityGroupIngress",
"ec2:DescribeNetworkInterfaces",
"ec2:DescribeVpcs",
"ec2:DeleteNetworkInterface",
"ec2:DescribeSubnets",
"ec2:DescribeSecurityGroups"
],
"Resource": "*"
},
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": [
"logs:CreateLogStream",
"wafv2:GetIPSet",
"logs:CreateLogGroup",
"wafv2:UpdateIPSet"
],
"Resource": [
"arn:aws:logs:us-west-2:xxxx:log-group:xxx:log-stream:*",
"arn:aws:wafv2:us-west-2:xxx:*/ipset/*/*"
]
}
]
}
Lambda function:
#!/usr/bin/python3.9
import boto3
ec2 = boto3.client('ec2')
def lambda_handler(event, context):
response = ec2.authorize_security_group_ingress(
GroupId='sg-xxxxxxx'
IpPermissions=[
{
'FromPort': 443,
'IpProtocol': 'tcp',
'IpRanges': [
{
'CidrIp': '1x.1x.x.1x/32',
'Description': 'adding test cidr using lambda'
},
],
'ToPort': 443
}
],
DryRun=True
)
return response
Could someone point me to the right direction? VPC is non-default. All I need is the add ingress rule to existing security group within non-default vpc
Thanks
Found the solution: Initially it was syntax error but after googling i thought it requires vpc so I added VPC to the Lambda configuration which was not required for this purpose.
For anyone having the same issue (only want to update security group with the cidr): below is the correct function and permissions (function isnt complete as depending on the solution u may want to delete old rules too):
Lambda function:
#!/usr/bin/python3.9
import boto3
ec2 = boto3.client('ec2')
def lambda_handler(event, context):
response = ec2.authorize_security_group_ingress(
DryRun=False,
GroupId='sg-0123456789',
IpPermissions=[
{
'FromPort': 443,
'IpProtocol': 'tcp',
'IpRanges': [
{
'CidrIp': '1x.2x.3x.4x/32',
'Description': 'Security group updated via lambda'
}
],
'ToPort': 443
}
]
)
return response
IAM Policy on lambda execution role:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"ec2:AuthorizeSecurityGroupIngress",
"ec2:ModifySecurityGroupRules",
"ec2:UpdateSecurityGroupRuleDescriptionsIngress"
],
"Resource": "arn or all"
}
]
}

what permissions I need for aws ec2 wait

-bash-4.2$ aws ec2 wait instance-running $ARG
Waiter InstanceRunning failed: You are not authorized to perform this operation.
Now you go to IAM and see a Huge list of permissions, none with wait word..., so you look into https://docs.aws.amazon.com/cli/latest/reference/ec2/wait/index.html#cli-aws-ec2-wait and find no list of needed permissions...
So: what permissions I need for aws ec2 wait?..
purely by trying and failing I found those, that worked for me :
{
"Version": "1980-09-19",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"ec2:StartInstances",
"ec2:StopInstances"
],
"Resource": "arn:aws:ec2:us-east-1:00000000:instance/i-abababababab"
},
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": [
"ec2:DescribeInstances",
"ec2:ReportInstanceStatus"
],
"Resource": "*"
}
]
}
I assume you don't need start and stop to just wait, but I included them, because you use wait in pair with either of them...
so in short those are: DescribeInstances and ReportInstanceStatus
WaiterInstanceRunning needs ec2:DescribeInstanceStatus - ReportInstanceStatus reports the status of an instance back to AWS (when an instance has an unexpected status)
Seems like also "ec2:DescribeInstanceStatus" is needed for below command
aws ec2 wait instance-status-ok --region eu-west-1 --instance-ids

AWS Integration on Kubernetes

I'm having problems setting up AWS Integration on a Kubernetes Cluster. I've already set the kubernetes.io/cluster/clustername = owned tag on all Instances, Subnets, VPC, and in a Single SG. I've also passed the --cloud-provider=aws flag to both API Server and Controller Manager, but the Controller Manager does not start.
Controller Manager Logs:
I0411 21:03:48.360194 1 aws.go:1026] Building AWS cloudprovider
I0411 21:03:48.360237 1 aws.go:988] Zone not specified in configuration file; querying AWS metadata service
F0411 21:03:48.363067 1 controllermanager.go:159] error building controller context: cloud provider could not be initialized: could not init cloud provider "aws": error finding instance i-0442e20b4a28b2274: "error listing AWS instances: \"NoCredentialProviders: no valid providers in chain. Deprecated.\\n\\tFor verbose messaging see aws.Config.CredentialsChainVerboseErrors\""
The Policy Attached to the Master Nodes is:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [ "ec2:*" ],
"Resource": [ "*" ]
},
{
"Effect": "Allow",
"Action": [ "elasticloadbalancing:*" ],
"Resource": [ "*" ]
},
{
"Effect": "Allow",
"Action": [ "route53:*" ],
"Resource": [ "*" ]
}
]
}
Querying the AWS Metadata Service from a master via cURL returns proper credentials
Any help will be much appreciated!
P.S: I'm not using Kops or anything of that kind. I've set up the control components plane by myself.
I was able to fix this by passing the --cloud-provider=aws flag to the kubelets. I thought that wasn't needed on Master nodes.
Thanks!

AWS IAM customized policy at instance level for EC2 doesn't work

Created an AWS IAM policy for a user to give permission for only stopping and starting instance but if I give a particular instance ARN resource then it doesn’t work. Default EC2 Read only permission has been given to the user to describe EC2 instances and on top of that added customized sample policy as follows:
Sample policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"ec2:Describe*",
"ec2:StopInstances",
"ec2:RunInstances",
"ec2:StartInstances"
],
"Effect": "Allow",
"Resource": "*"
This works
"Resource": "arn:aws:ec2:<region>:<account id>:instance/<instance id>"
"Resource": "arn:aws:ec2:<region>:<account id>:instance/*"
"Resource": "arn:aws:ec2:<region>::instance/*"
"Resource": "arn:aws:ec2:::instance/*"
"Resource": "arn:aws:ec2:::*"
These doesn’t work
}
]
}
Edited on 23rd January (To Show what exactly I have done)
Objective: Start and stop instance permission on a single EC2 instance to a user.
Tested different combo policies but none of them worked except "Resource": "*":
Logged in: admin_user (Full access)
Created an instance as follows:
Region: Oregon
Availability zone: us-west-2c
Instance Id: i-xxx3dxxx32xxxxxxe
Owner: xxx23xxx11
Created a user: testec2_user
Permissions given to the user:
EC2 read only (available policy)
Customized policy to permit only stop and start i-xxx38xxx32xx45 instance as follows:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"ec2:Describe*",
"ec2:RunInstances"
],
"Effect": "Allow",
"Resource": "*"
},
{
"Action": [
"ec2:StopInstances",
"ec2:StartInstances"
],
"Effect": "Allow",
"Resource": "arn:aws:ec2:us-west-2c:xxx23xxx11:instance/i-xxx3dxxx32xxxxxxe"
}
] }
Logged in as testec2_user and tried starting up the stopped instance and received following error:
You are not authorized to perform this operation. Encoded authorization failure message
I have a plan for decoding the message received using sts decode authorization message of AWS.
DescribeInstances does not support resource-level permissions. (See Unsupported Resource-Level Permissions).
If an Amazon EC2 API action does not support resource-level
permissions, you can grant users permission to use the action, but you
have to specify a * for the resource element of your policy statement.
Read more
So, you could re-write your policy as:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"ec2:Describe*",
"ec2:RunInstances"
],
"Effect": "Allow",
"Resource": "*"
},
{
"Action": [
"ec2:StopInstances",
"ec2:StartInstances"
],
"Effect": "Allow",
"Resource": "arn:aws:ec2:<region>:<account>:instance/<instance-id>"
}
]
}
EDIT
RunInstances needs access to several resource types besides Instance (Such as Image, Key pair, Network interface, Placement group, Security group, Snapshot, Subnet and Volume) and accepts a specific ARN format for each resource type. So, arn:aws:ec2:<region>:<account id>:instance/* would not be enough and you'll get an UnauthorizedOperation error. The "Resource" element should either be:
"Resource": "*"
Which is the easiest way, or:
"Resource": [
"arn:aws:ec2:<region>:<account>:instance/*",
"arn:aws:ec2:<region>::image/*",
"arn:aws:ec2:<region>:<account>:key-pair/*",
"arn:aws:ec2:<region>:<account>:network-interface/*",
"arn:aws:ec2:<region>:<account>:placement-group/*",
"arn:aws:ec2:<region>:<account>:security-group/*",
"arn:aws:ec2:<region>::snapshot/*",
"arn:aws:ec2:<region>:<account>:subnet/*",
"arn:aws:ec2:<region>:<account>:volume/*"
]
Which is more complex but provides fine-grained control on each resource. For example, you can allow RunInstances execution for a specific EC2 image ID or subnet ID only. For more details, see the RunInstances section here.
Additional note on PassRole Permission
When executing RunInstances, if the EC2 instance should include an instance profile, the user who launches the EC2 instance must also have the IAM PassRole permission in order to associate a role with the instance during launch. For example:
{
"Version": "2012-10-17",
"Statement": [
...
{
"Action": "iam:PassRole",
"Effect": "Allow",
"Resource":"arn:aws:iam::<account>:role/<role-name>"
}
]
}
This way, you make sure that a user doesn't pass a role to an EC2 instance where the role has more permissions than you want the user to have.
For more info on granting permission to launch EC2 instances with IAM roles, see this AWS blog article.
This is how you specify multiple resources:
…
"Effect": "Allow",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::BUCKET-NAME/home/${aws:username}",
"arn:aws:s3:::BUCKET-NAME/home/${aws:username}/*"
]
}
]
}
Source:
http://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_examples.html
EDIT:
You can also use Conditions if you want to filter out instead of including all the required resources manually.

Why does the AWS OpsWorks "register" command require these permissions to run?

Why does the aws opsworks register command require these permissions to run?:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"opsworks:AssignInstance",
"opsworks:CreateStack",
"opsworks:CreateLayer",
"opsworks:DeregisterInstance",
"opsworks:DescribeInstances",
"opsworks:DescribeStackProvisioningParameters",
"opsworks:DescribeStacks",
"opsworks:UnassignInstance"
],
"Resource": [
"*"
]
},
{
"Effect": "Allow",
"Action": [
"ec2:DescribeInstances"
],
"Resource": [
"*"
]
},
{
"Effect": "Allow",
"Action": [
"iam:AddUserToGroup",
"iam:CreateAccessKey",
"iam:CreateGroup",
"iam:CreateUser",
"iam:ListInstanceProfiles",
"iam:PassRole",
"iam:PutUserPolicy"
],
"Resource": [
"*"
]
}
]
}
Perhaps I am being over-cautious, but it seems to me that any policy that grants full permissions to iam:CreateUser and iam:PutUserPolicy would basically be a huge security hole, as this level of access would give you the rights to create an admin user at any time.
Am I missing something? Or can the above policy be made more secure and still work with OpsWorks?
Those IAM permissions are used to create an IAM user for the instance, and those permissions only used once for aws opsworks register command.
It's a little bit oeverkill to have all those permission just for one command once but it's more for simplify the instance registration configuration. If you have concern about the permissions, you could register instance from your workstation instead of inside instance with instance profile, something like aws opsworks register --infrastructure-class ec2 --region us-east-1 --stack-id ac95d52c-3f4d-4452-b134-b44f6b4c4f02 --ssh-username [username] --ssh-private-key [key-path] i-050e2a8c. In this way, only your workstation need such IAM permissions.