AWS Config advanced query to limit results based on relationship congigurations - amazon-web-services

Not sure if it is possible to do, but I am trying to retrieve a list of default VPCs and the respective accounts from AWS Config advanced queries.
I have the following query that gives me the result of all the accounts if they have default VPC and the resources that are attached to those default VPCs
SELECT
accountId,
awsRegion,
configuration.vpcId,
relationships
WHERE
resourceType = 'AWS::EC2::VPC'
AND configuration.isDefault = TRUE
AND relationships.resourceType IN (
'AWS::EC2::Instance',
'AWS::EC2::InternetGateway',
'AWS::EC2::NetworkACL',
'AWS::EC2::RouteTable',
'AWS::EC2::Subnet',
'AWS::EC2::SecurityGroup'
)
What I want to achieve further is that the result set should be filtered more based on the properties of relationships.
For example I only want to return a VPC record if the resource 'AWS::EC2::Subnet' has property defaultForAz set to true
Another example is to limit records where the 'AWS::EC2::RouteTable' has configuration configuration.associations.main is set to true.
Right now it selects all default VPCs from organisation member accounts.
I am also happy to know any other better approach

Related

Filter to find the non-main route table in AWS VPC with Terraform

What specific syntax must be used in order for the Terraform aws_route_table data source below to successfully return the route table that is NOT designated the main route table in the VPC?
data "aws_route_table" "rt" {
vpc_id = var.vpcId
filter {
name = "association.main"
values = [false]
}
}
There is only one non-main route table in the VPC. Therefore, filtering for main=false should identify it if the filter syntax is correct.
The error currently produced by the above code is:
Error: Your query returned no results. Please change your search criteria and try again
I did some tests on my own, and here are some of my findings. aws_route_tables rather then aws_route_table should be used to return multiple RTs:
data "aws_route_tables" "rt" {
vpc_id = var.vpcId
filter {
name = "association.main"
values = [false]
}
}
However, there are few things to know about:
RTs that are not associated with any subnet will not be returned.
If Main route table is associated with a subnet, it will be returned nevertheless. Basicily if a main route table is associated with a subnet it will be considered as both main and not main at the same time.
So basically, the usefulness of the above filter highly depends on how your VPC and RTs are organized.
Below is AWS CLI that I also used to double check some of these findings:
aws ec2 describe-route-tables --filters Name=vpc-id,Values=vpc-0a347b77b8c0109b6 Name=association.main,Values=false

How to specify a default VPC for private hosted zone in a CloudFormation template?

In order to create a private hosted zone I have to associate it with one or more VPCs. I want to use a default VPC in the specific region. How can I specify it in the CloudFormation template without introducing the VPC id as a parameter?
You can't exactly do this
In the template you can say something like
"Parameters" : {
myVpc:
Description: "vpc id",
Type: "List<AWS::EC2::VPC::Id>"
}
And the console will prepopulate the drop down with valid values
However the CLI can't do something like get the prepopulation and then pick the first one
I would guess to do this from a CLI first run soemthing like
aws ec2 describe-vpcs --query 'Vpcs[*].[VpcId]'
Then edit the desired vpc (for instance the first on the list) into the CF template

Cloud Formation: How to get VPC from Subnet Id

I have a Cloud Formation to set up an EC2 instance. I'm currently using the Parameters to specify the Subnet Id for the EC2 instance as well as the VPC Id for the Security Group (to be used in turn by the EC2 instance).
In my situation the Subnet Id specified is required to be part of the VPC and I'd like to only have to specify the Subnet Id in the Parameters. But I can't find a way to derive the VPC from the Subnet Id (http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-subnet.html)
I see the GetAtt function can be used to return resource attributes. Is there something equivalent to return resource properties?
From the documentation Fn:GetAtt, you can only retrieve AvailabilityZone and Ipv6CidrBlocks details of the Subnet. There is no inbuilt support to get VpcId of the given subnet in CFn Templates.
There is a work-around though. If you are using the aws-cli documentation, you can use the describe-subnets method to fetch the VpcId of the required subnet and pass it as input to the Cloudformation template create_stack call.
This method works even if you are using any SDK. for example, in Java.
//pseudo code only!
DescribeSubnetsRequest request = new DescribeSubnetsRequest();
request.withSubnetIds("subnet-abcdefgh");
DescribeSubnetsResult result = awsClient.describeSubnets(request);
String myVpc = result.getSubnets().get(0).getVpcId();
// add the above VPC Id to the parameters of your Cloud formation template create stack request.
Hope this helps.
I created a small project called cli2cloudformation. Using that you're able to execute cli commands inside your cloudformation stack and use the results of the commands.
Just check it here. I hope it helps you.

filtering ec2 instances by associated IAM role with boto

I have a few instances on AWS that are associated with the same IAM Role. I'm looking to write a code that returns these instances.
Based from this document: http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeInstances.html, I see that there is an available filter iam-instance-profile.arn. I'm just not sure how I would go about using that or if that is what I should be using.
This is an example where instances are filtered by tags.
conn = boto.ec2.connect_to_region('ap-southeast-1')
reservations = conn.get_all_instances(filters={"tag:Name": "my-instance-1"});
for reservation in reservations:
instance = reservation.instances[0]
I'd like to do something similar except with an IAM Role as the filter.
Another thing - the example above conn.get_all_instances(filters={"tag:Name": "my-instance-1"});returns reservations. I'd like to get the instances without having to get them through reservations. For example: conn.get_only_instances(instance_ids=['i-cc186913']) returns me the instance.
What is the best way where I could have a filter (IAM Role) and return ONLY instances (not getting them through reservations)?
Pass your instance profile ARN for that role (which you can get from IAM dashboard or you can construct it). Example:
conn.get_only_instances(filters={"iam-instance-profile.arn": "arn:aws:iam::<your-account-number>:instance-profile/<your-role-name>"})
It will return a list of instance and you can loop through it.
>>> conn.get_only_instances(filters={"iam-instance-profile.arn":"arn:aws:iam::123456781221:instance-profile/stackoverflowRole"})
[Instance:i-8ba223ab]

How to use default AWS VPC resources when created via Terraform

Trying to learn to use Terraform (v 0.3.7) with Amazon Web Services.
When I create a VPC using Terraform via the following:
resource "aws_vpc" "test-vpc" {
cidr_block = "${var.vpc_cidr}"
enable_dns_hostnames = true
tags {
Name = "test-vpc"
}
}
The VPC will have a main routing table and a "default" security group automatically created (I assume by AWS, rather than Terraform); these can be identified by the attributes on the created VPC: main_route_table_id and default_security_group_id.
While following this tutorial it talks about creating your own default security group and routing table - it makes no mention of the default ones that will get created (even if you create your own routing table, the "main" one created by default will just remain sitting there, associated with no subnets or anything).
Shouldn't we be using the default resource that created with a VPC? Especially the routing table, will there be any effects because of not using the "main" routing table?
And if I should be using the default resources, how do I do that with Terraform?
I couldn't see anything in the Terraform documentation about these default resources, and if I try to override them (for example by telling Terraform to create a security group with name default, I get errors).
AWS creates these default routing tables and sec groups. If you don't use them ( I know we don't) they are fine to get deleted.
Terraform throws errors if you require it to create default sec group as probably the group is already there or maybe this sec group name is reserved.
You can create one new resource "aws_security_group" ( https://terraform.io/docs/providers/aws/r/security_group.html )and have a dependency listed on the resource with
depends_on = ["aws_instance.instance-name-from-resource"]
for the instance thus sec group will be created first and then assign sec groups to the instance with "security_groups"