How to change RDS Security Group using boto3? - amazon-ec2

I am restoring (=creating a new instance) an RDS MySQL Snapshot using boto3. Unfortunately the Security Group does not get copied over instead it gets assigned the default Security Group which is has no limitations on incoming traffic.
Looking at the source RDS instance I can see the correct Security Group (sg-a247eec5) attached to the RDS instance. This Security Group is visible under EC2 - Security Groups and VPC - Security Groups but not under RDS - Security Groups.
I am using restore_db_instance_from_db_snapshot but I can't see where I would attach that Security Group to the new instance.
I can easily attach the correct Security Group by using the AWS UI (modifying my RDS Instance).
There is modify_instance_attribute on the EC2 client which can change Security Groups, but it requires an InstanceId which I don't get from my RDS instance. The only thing I can find is DBInstanceIdentifier.
Trying to set the correct IAM permissions confuses me too. I have an RDS ARN: arn:aws:rds:ap-southeast-2:<account_id>:db:<db_instance_name> but ModifyInstanceAttribute is listed under Amazon EC2. Selecting both in the policy editor gives me an error saying the ARN is invalid (which makes sense).

Whenever you use restore_db_instance_from_db_snapshot api, the default behavior is to apply default security group and default parameter group. The same is documented in RDS API reference.
The target database is created from the source database restore point
with the most of original configuration with the default security
group and the default DB parameter group.
The workaround is to use modify_db_instance api once the restore is complete.
DBInstanceIdentifier is to an RDS instance, what an InstanceId is to an EC2 instance.
Pass the same DBInstanceIdentifier which you used above, as an input to this api.
response = client.modify_db_instance(
DBInstanceIdentifier='string',
DBSecurityGroups=[
'string',
], /* If you are using ec2 security groups then remove this and use VpcSecurityGroupIds. */
VpcSecurityGroupIds=[
'string',
],
DBParameterGroupName='string',
ApplyImmediately=True,
)
I believe you need to change both the security-group as well as parameter-group(unless you are fine with the default one). If you are changing the parameter-group, then you need to reboot the db instance as well for the settings to take effect.
response = client.reboot_db_instance(
DBInstanceIdentifier='string',
)
Also, you need the role performing the above db operations to have the below policy permissions.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1507879517000",
"Effect": "Allow",
"Action": [
"rds:CreateDBInstance",
"rds:ModifyDBInstance",
"rds:RebootDBInstance",
"rds:RestoreDBInstanceFromDBSnapshot"
],
"Resource": [
"arn:aws:rds:*:XXXXXXXXXX:db:*"
]
}
]
}

Related

Laravel in vpc, access sqs without programatic access

I have a Laravel app running on an ec2 instance inside a VPC. Now I want to connect to an SQS from the app. Using programmatic access seems to work but I want to use the SQS endpoint, without having to use the key and the secret.
Technically speaking this should be possible with the AWS resources being linked together. Any idea how to set this up in Laravel?
Sounds like you need to use an IAM role (basically a set of policies) which you attach to your EC2 instance. The policies you include would have a section for access to your SQS queue (or at least certain actions on it in SQS). This effectively allows temporary credentials to be given to the instance without having to have them in code.
The role might look something like this:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"sqs:ReceiveMessage",
"sqs:DeleteMessage",
"sqs:GetQueueAttributes"
...<any other actions>
],
"Resource": <SQS Queue ARN>
}
]
}
You attach this role to your EC2 instance in the EC2 console - select instance, go to Instance Settings > Attach/Replace IAM Role

AWS IAM policy issues

So I'm having issues with AWS's IAM policies. I essentialy have a "management" compartment for multiple things. I want to be able to restrict user access to everything, filtered on VPC. So a user can only do things in the VPC that is assigned to their policy.
My IAM policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1549549655017",
"Action": "*",
"Effect": "Deny",
"Resource": "*",
"Condition": {
"StringEquals": {
"aws:SourceVpc": "vpc-########"
}
}
}
]
}
I apply this policy to a user, yet they can still start/stop ec2 instances, or add security groups for something in that VPC.
I thought it might have been because the user was admin, so I removed this and gave them access to specific, but this still allowed them access.
Suggestions?
The aws:SourceVpc condition is only available for services that support traffic over a VPC endpoint. A call to the EC2 service does not support VPC endpoints so this condition will not apply. Refer to https://docs.aws.amazon.com/IAM/latest/UserGuide/list_amazonec2.html for conditions that may be applied to the various ec2 actions and resources.
I am not sure what the use case for this is -- but I would humbly suggest that a VPC is not the correct solution for isolating management concerns. You should have that in separate account so that your blast radius from user error is limited to one concern i.e management or user-application not both.
Try replacing this code in the condition section. It should work
"StringEquals": {
"ec2:Vpc": "arn:aws:ec2:region:account:vpc/vpc-1a2b3c4d"
}
Here the in the other section you can specify all the api’s that you require access to. This will make sure that you can access those api’s within the vpc.

How to assign a new permission to a running EC2 instance

I am performing some tests with EC2, and I want to limit the permissions to an already running instance, to only describe other instances (for example, if it requests the creation of a new one, that request should be denied).
I created an IAM Role with the following policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Action": [
"ec2:DescribeInstances",
"ec2:DescribeImages",
"ec2:DescribeKeyPairs",
"ec2:DescribeSecurityGroups",
"ec2:DescribeAvailabilityZones",
"ec2:RunInstances",
"ec2:TerminateInstances",
"ec2:StopInstances",
"ec2:StartInstances"
],
"Resource": "*"
}
]
}
This theoretically should prevent me from creating new instances when I am logged on the already running instance, but it does not (I am using boto library for the test, with ec2.run_instances()).
Any help would be much appreciated.
The policy attached to an IAM Instance Role only affects requests made using the instance role credentials. It doesn't have any impact on requests made using other credentials (such as the access key id and secret of an IAM user), even though the requests come from code running on the instance.
In the case, here, where unexpected privileges are available, the likely explanation is that another set of credentials is stored on the instance, and the code is using those without the developer realizing it.
This is perhaps a good illustration of one reason why it's considered a best practice to only use role credentials in code running on EC2, and not store other credentials on the instance.

Is there a way to limit IAM access from within EC2 instance

First and foremost, I am aware of IAM roles and know that they would provide this feature. However, I have a requirement for a key attached to a IAM user.
Is there a way to limit access to resources from within EC2 instances (only allow if the origin of the request matches ec2 instances).
For example:
Using credentials from developer's laptop: denied
Using credentials from EC2 instance: allowed
We want to make sure that if these keys ever get leaked for whatever reason, no one will be able to control resources from outside our AWS environment.
Thanks
It's possible, but the level of granularity you want may result in more IAM management than you desire. It's possible to add conditions to IAM statements that restrict based on IP address, so you can create a statement like the one below that lists the IPs of your instances:
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Deny",
"Action": "*",
"Resource": "*",
"Condition": {"NotIpAddress": {"aws:SourceIp": [
"192.0.2.0/24",
"203.0.113.0/24"
]}}
}
}
However unless you use Elastic IPs for all your instances then their IPs can change over time, so you'd need some way of keeping these IAM statements properly updated.

How to start a private instance in EC2 using IAM

How can I start an EC2 instance by user A.
and the started instance by user A is unable to be seen by user B.
Can I do this with IAM?
I tried this set:
{
"Statement": [
{
"Sid": "Stmt1341824399883",
"Action": [
"ec2:DescribeInstanceAttribute",
"ec2:DescribeInstanceStatus",
"ec2:DescribeInstances"
],
"Effect": "Deny",
"Resource": [
"*"
]
}
]
}
but it hides everything including the instances started by user A
Unfortunately there are no Amazon Resource Names(ARNs) for Amazon EC2: you can't write a policy that applies only to certain EC2 instances.
If you require isolation between the two, the only way I know of is to create a separate AWS account. You can use consolidated billing so that billing is aggregated with your other account, and you can share some things like EBS snapshots between accounts. Most things however can't be shared between accounts.

Resources