Skip to content

Commit

Permalink
Merge pull request #22 from leandrodamascena/developer
Browse files Browse the repository at this point in the history
Developer to master
  • Loading branch information
leandrodamascena authored May 22, 2020
2 parents a0e21c6 + 40fd81b commit e3d4296
Show file tree
Hide file tree
Showing 13 changed files with 858 additions and 616 deletions.
47 changes: 26 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,32 @@ AWS Network Discovery helps you analyze what's resources are using a custom VPC.

Following services are integrated

- EC2
- IAM POLICY
- Lambda
- RDS
- EFS
- ELASTICACHE
- S3 POLICY
- ELASTICSEARCH
- DOCUMENTDB
- SQS QUEUE POLICY
- MSK
- NAT GATEWAY
- INTERNET GATEWAY (IGW)
- CLASSIC/NETWORK/APPLICATION LOAD BALANCING
- ROUTE TABLE
- SUBNET
- NACL
- SECURITY GROUP
- VPC PEERING
- VPC ENDPOINT
- EKS
- EC2
- IAM POLICY
- Lambda
- RDS
- EFS
- ELASTICACHE
- S3 POLICY
- ELASTICSEARCH
- DOCUMENTDB
- SQS QUEUE POLICY
- MSK
- NAT GATEWAY
- INTERNET GATEWAY (IGW)
- CLASSIC/NETWORK/APPLICATION LOAD BALANCING
- ROUTE TABLE
- SUBNET
- NACL
- SECURITY GROUP
- VPC PEERING
- VPC ENDPOINT
- EKS
- CLOUDFORMATION
- SYNTHETIC CANARIES
- EMR
- ECS
- AUTOSCALING

### News

Expand Down
8 changes: 6 additions & 2 deletions aws-network-discovery.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@

from commands.vpc import Vpc

__version__ = "0.6.0"
__version__ = "0.7.0"

AVAILABLE_LANGUAGES = ['en_US','pt_BR']

Expand Down Expand Up @@ -97,4 +97,8 @@ def main():


if __name__ == "__main__":
main()
try:
main()
except KeyboardInterrupt:
print('Finishing script...')
sys.exit(0)
13 changes: 12 additions & 1 deletion shared/awscommands.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
from shared.internal.security import IAM, IAMPOLICY
from shared.internal.network import VPC, IGW, NATGATEWAY, ELB, ELBV2, ROUTETABLE, SUBNET, NACL, SG, VPCPEERING
from shared.internal.network import VPCENDPOINT
from shared.internal.compute import LAMBDA, EC2, EKS
from shared.internal.compute import LAMBDA, EC2, EKS, EMR, ASG
from shared.internal.database import RDS, ELASTICACHE, DOCUMENTDB
from shared.internal.storage import EFS, S3POLICY
from shared.internal.analytics import ELASTICSEARCH, MSK
from shared.internal.application import SQSPOLICY
from shared.internal.management import CLOUDFORMATION, CANARIES
from shared.internal.containers import ECS


class AwsCommands(object):
Expand All @@ -24,6 +26,8 @@ def run(self):
EC2(self.vpc_options).run()
LAMBDA(self.vpc_options).run()
EKS(self.vpc_options).run()
EMR(self.vpc_options).run()
ASG(self.vpc_options).run()

""" Database resources """
RDS(self.vpc_options).run()
Expand Down Expand Up @@ -55,4 +59,11 @@ def run(self):
SG(self.vpc_options).run()
VPCPEERING(self.vpc_options).run()
VPCENDPOINT(self.vpc_options).run()

""" Management resources """
CLOUDFORMATION(self.vpc_options).run()
CANARIES(self.vpc_options).run()

""" Containers """
ECS(self.vpc_options).run()

16 changes: 16 additions & 0 deletions shared/error_handler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import functools
from shared.common import *

def exception(func):
"""
Decorator to catch exceptions and avoid stop script
"""
@functools.wraps(func)
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except Exception as e:
message = "\nError running check {}. Error message {}".format(func.__qualname__, str(e))
log_critical(message)
pass
return wrapper
119 changes: 59 additions & 60 deletions shared/internal/analytics.py
Original file line number Diff line number Diff line change
@@ -1,95 +1,94 @@
from shared.common import *
import json
from shared.error_handler import exception

class ELASTICSEARCH(object):

def __init__(self, vpc_options: VpcOptions):
self.vpc_options = vpc_options

@exception
def run(self):
try:
client = self.vpc_options.client('es')

response = client.list_domain_names()

message_handler("\nChecking ELASTICSEARCH DOMAINS...", "HEADER")

if len(response["DomainNames"]) == 0:
message_handler("Found 0 Elastic Search Domains in region {0}".format(self.vpc_options.region_name), "OKBLUE")
else:
found = 0
message = ""
for data in response["DomainNames"]:
client = self.vpc_options.client('es')

response = client.list_domain_names()

message_handler("\nChecking ELASTICSEARCH DOMAINS...", "HEADER")

elasticsearch_domain = client.describe_elasticsearch_domain(DomainName=data['DomainName'])
if len(response["DomainNames"]) == 0:
message_handler("Found 0 Elastic Search Domains in region {0}".format(self.vpc_options.region_name), "OKBLUE")
else:
found = 0
message = ""
for data in response["DomainNames"]:

documentpolicy = elasticsearch_domain['DomainStatus']['AccessPolicies']
elasticsearch_domain = client.describe_elasticsearch_domain(DomainName=data['DomainName'])

document = json.dumps(documentpolicy, default=datetime_to_string)
documentpolicy = elasticsearch_domain['DomainStatus']['AccessPolicies']

""" check either vpc_id or potencial subnet ip are found """
ipvpc_found = check_ipvpc_inpolicy(document=document, vpc_options=self.vpc_options)
document = json.dumps(documentpolicy, default=datetime_to_string)

""" elasticsearch uses accesspolicies too, so check both situation """
if elasticsearch_domain['DomainStatus']['VPCOptions']['VPCId'] == self.vpc_options.vpc_id \
or ipvpc_found is True:
found += 1
message = message + "\nDomainId: {0} - DomainName: {1} - VpcId {2}".format(
elasticsearch_domain['DomainStatus']['DomainId'],
elasticsearch_domain['DomainStatus']['DomainName'],
self.vpc_options.vpc_id
)
message_handler("Found {0} ElasticSearch Domains using VPC {1} {2}".format(str(found), self.vpc_options.vpc_id, message),'OKBLUE')

except Exception as e:
message = "Can't list ElasticSearch Domains\nError {0}".format(str(e))
exit_critical(message)
""" check either vpc_id or potencial subnet ip are found """
ipvpc_found = check_ipvpc_inpolicy(document=document, vpc_options=self.vpc_options)

""" elasticsearch uses accesspolicies too, so check both situation """
if elasticsearch_domain['DomainStatus']['VPCOptions']['VPCId'] == self.vpc_options.vpc_id \
or ipvpc_found is True:
found += 1
message = message + "\nDomainId: {0} - DomainName: {1} - VpcId {2}".format(
elasticsearch_domain['DomainStatus']['DomainId'],
elasticsearch_domain['DomainStatus']['DomainName'],
self.vpc_options.vpc_id
)
message_handler("Found {0} ElasticSearch Domains using VPC {1} {2}".format(str(found), self.vpc_options.vpc_id, message),'OKBLUE')

return True

class MSK(object):

def __init__(self, vpc_options: VpcOptions):
self.vpc_options = vpc_options

@exception
def run(self):
try:
client = self.vpc_options.client('kafka')

""" get all cache clusters """
response = client.list_clusters()
client = self.vpc_options.client('kafka')

""" get all cache clusters """
response = client.list_clusters()

message_handler("\nChecking MSK CLUSTERS...", "HEADER")
message_handler("\nChecking MSK CLUSTERS...", "HEADER")

if len(response['ClusterInfoList']) == 0:
message_handler("Found 0 MSK Clusters in region {0}".format(self.vpc_options.region_name), "OKBLUE")
else:
found = 0
message = ""
if len(response['ClusterInfoList']) == 0:
message_handler("Found 0 MSK Clusters in region {0}".format(self.vpc_options.region_name), "OKBLUE")
else:
found = 0
message = ""

""" iterate cache clusters to get subnet groups """
for data in response['ClusterInfoList']:
""" iterate cache clusters to get subnet groups """
for data in response['ClusterInfoList']:

msk_subnets = ", ".join(data['BrokerNodeGroupInfo']['ClientSubnets'])
msk_subnets = ", ".join(data['BrokerNodeGroupInfo']['ClientSubnets'])

ec2 = self.vpc_options.session.resource('ec2', region_name=self.vpc_options.region_name)
ec2 = self.vpc_options.session.resource('ec2', region_name=self.vpc_options.region_name)

filters = [{'Name':'vpc-id',
'Values':[self.vpc_options.vpc_id]}]
filters = [{'Name':'vpc-id',
'Values':[self.vpc_options.vpc_id]}]

subnets = ec2.subnets.filter(Filters=filters)
subnets = ec2.subnets.filter(Filters=filters)

for subnet in list(subnets):
for subnet in list(subnets):

if subnet.id in msk_subnets:
if subnet.id in msk_subnets:

found += 1
message = message + "\nClusterName: {0} - VpcId: {1}".format(
data['ClusterName'],
self.vpc_options.vpc_id
)
break
found += 1
message = message + "\nClusterName: {0} - VpcId: {1}".format(
data['ClusterName'],
self.vpc_options.vpc_id
)
break

message_handler("Found {0} MSK Clusters using VPC {1} {2}".format(str(found), self.vpc_options.vpc_id, message),'OKBLUE')
message_handler("Found {0} MSK Clusters using VPC {1} {2}".format(str(found), self.vpc_options.vpc_id, message),'OKBLUE')

except Exception as e:
message = "Can't list MSK Clusters\nError {0}".format(str(e))
exit_critical(message)
return True
57 changes: 29 additions & 28 deletions shared/internal/application.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from concurrent.futures.thread import ThreadPoolExecutor

from shared.error_handler import exception
from shared.common import *
import json

Expand All @@ -9,14 +9,13 @@ class SQSPOLICY(object):
def __init__(self, vpc_options: VpcOptions):
self.vpc_options = vpc_options

@exception
def run(self):
try:
client = self.vpc_options.client('sqs')
response = client.list_queues()
except Exception as e:
message = "Can't list SQS Queue Policy\nError {0}".format(str(e))
log_critical(message)
return

client = self.vpc_options.client('sqs')

response = client.list_queues()

message_handler("\nChecking SQS QUEUE POLICY...", "HEADER")

if "QueueUrls" not in response:
Expand All @@ -34,25 +33,27 @@ def run(self):
message += result[1]
message_handler("Found {0} SQS Queue Policy using VPC {1} {2}".format(str(found), self.vpc_options.vpc_id, message),'OKBLUE')

return True

@exception
def analyze_queues(self, client, queue):
try:
sqs_queue_policy = client.get_queue_attributes(QueueUrl=queue, AttributeNames=['Policy'])
if "Attributes" in sqs_queue_policy:

""" Not sure about boto3 return """

documentpolicy = sqs_queue_policy['Attributes']['Policy']
document = json.dumps(documentpolicy, default=datetime_to_string)

""" check either vpc_id or potencial subnet ip are found """
ipvpc_found = check_ipvpc_inpolicy(document=document, vpc_options=self.vpc_options)

if ipvpc_found is not False:
return True, "\nQueueUrl: {0} -> {1} -> VPC {2}".format(
queue,
ipvpc_found,
self.vpc_options.vpc_id
)
except Exception as e:
log_critical(str(e))

sqs_queue_policy = client.get_queue_attributes(QueueUrl=queue, AttributeNames=['Policy'])
if "Attributes" in sqs_queue_policy:

""" Not sure about boto3 return """

documentpolicy = sqs_queue_policy['Attributes']['Policy']
document = json.dumps(documentpolicy, default=datetime_to_string)

""" check either vpc_id or potencial subnet ip are found """
ipvpc_found = check_ipvpc_inpolicy(document=document, vpc_options=self.vpc_options)

if ipvpc_found is not False:
return True, "\nQueueUrl: {0} -> {1} -> VPC {2}".format(
queue,
ipvpc_found,
self.vpc_options.vpc_id
)

return False, None
Loading

0 comments on commit e3d4296

Please sign in to comment.