forked from duo-labs/cloudmapper
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request duo-labs#4 from duo-labs/master
refresh from master fork
- Loading branch information
Showing
24 changed files
with
648 additions
and
80 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
from __future__ import print_function | ||
import json | ||
|
||
from shared.common import parse_arguments | ||
from shared.find_unused import find_unused_resources | ||
|
||
|
||
__description__ = "Find unused resources in accounts" | ||
|
||
def run(arguments): | ||
_, accounts, config = parse_arguments(arguments) | ||
unused_resources = find_unused_resources(accounts) | ||
|
||
print(json.dumps(unused_resources, indent=2, sort_keys=True)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
import pyjq | ||
|
||
from shared.common import query_aws, get_regions | ||
from shared.nodes import Account, Region | ||
|
||
|
||
def find_unused_security_groups(region): | ||
# Get the defined security groups, then find all the Security Groups associated with the | ||
# ENIs. Then diff these to find the unused Security Groups. | ||
used_sgs = set() | ||
|
||
defined_sgs = query_aws(region.account, "ec2-describe-security-groups", region) | ||
|
||
network_interfaces = query_aws( | ||
region.account, "ec2-describe-network-interfaces", region | ||
) | ||
|
||
defined_sg_set = {} | ||
|
||
for sg in pyjq.all(".SecurityGroups[]", defined_sgs): | ||
defined_sg_set[sg["GroupId"]] = sg | ||
|
||
for used_sg in pyjq.all( | ||
".NetworkInterfaces[].Groups[].GroupId", network_interfaces | ||
): | ||
used_sgs.add(used_sg) | ||
|
||
unused_sg_ids = set(defined_sg_set) - used_sgs | ||
unused_sgs = [] | ||
for sg_id in unused_sg_ids: | ||
unused_sgs.append( | ||
{ | ||
"id": sg_id, | ||
"name": defined_sg_set[sg_id]["GroupName"], | ||
"description": defined_sg_set[sg_id].get("Description", ""), | ||
} | ||
) | ||
return unused_sgs | ||
|
||
|
||
def find_unused_volumes(region): | ||
unused_volumes = [] | ||
volumes = query_aws(region.account, "ec2-describe-volumes", region) | ||
for volume in pyjq.all('.Volumes[]|select(.State=="available")', volumes): | ||
unused_volumes.append({"id": volume["VolumeId"]}) | ||
|
||
return unused_volumes | ||
|
||
|
||
def find_unused_elastic_ips(region): | ||
unused_ips = [] | ||
ips = query_aws(region.account, "ec2-describe-addresses", region) | ||
for ip in pyjq.all(".Addresses[] | select(.AssociationId == null)", ips): | ||
unused_ips.append({"id": ip["AllocationId"], "ip": ip["PublicIp"]}) | ||
|
||
return unused_ips | ||
|
||
|
||
def find_unused_network_interfaces(region): | ||
unused_network_interfaces = [] | ||
network_interfaces = query_aws( | ||
region.account, "ec2-describe-network-interfaces", region | ||
) | ||
for network_interface in pyjq.all( | ||
'.NetworkInterfaces[]|select(.Status=="available")', network_interfaces | ||
): | ||
unused_network_interfaces.append( | ||
{"id": network_interface["NetworkInterfaceId"]} | ||
) | ||
|
||
return unused_network_interfaces | ||
|
||
|
||
def add_if_exists(dictionary, key, value): | ||
if value: | ||
dictionary[key] = value | ||
|
||
|
||
def find_unused_resources(accounts): | ||
unused_resources = [] | ||
for account in accounts: | ||
unused_resources_for_account = [] | ||
for region_json in get_regions(Account(None, account)): | ||
region = Region(Account(None, account), region_json) | ||
|
||
unused_resources_for_region = {} | ||
|
||
add_if_exists( | ||
unused_resources_for_region, | ||
"security_groups", | ||
find_unused_security_groups(region), | ||
) | ||
add_if_exists( | ||
unused_resources_for_region, "volumes", find_unused_volumes(region) | ||
) | ||
add_if_exists( | ||
unused_resources_for_region, | ||
"elastic_ips", | ||
find_unused_elastic_ips(region), | ||
) | ||
add_if_exists( | ||
unused_resources_for_region, | ||
"network_interfaces", | ||
find_unused_network_interfaces(region), | ||
) | ||
|
||
unused_resources_for_account.append( | ||
{ | ||
"region": region_json["RegionName"], | ||
"unused_resources": unused_resources_for_region, | ||
} | ||
) | ||
unused_resources.append( | ||
{ | ||
"account": {"id": account["id"], "name": account["name"]}, | ||
"regions": unused_resources_for_account, | ||
} | ||
) | ||
return unused_resources |
Oops, something went wrong.