Example #1
0
def generate(name, num_of_instances):
    with Diagram(name, direction='TB', show=True):
        with Cluster('Auto Scaling Group'):
            app_group = [EC2Instance('App') for _ in range(num_of_instances)]
        rds_master = RDS('DB (Master)')
        rds_standby = RDS('DB (Standby)')
        Users('Users') >> Route53('Route 53') >> ALB('ALB') >> app_group >> rds_master
        rds_master - rds_standby
Example #2
0
}

node_attr = {
    "width": "1",
    "height": "1",
    "fontsize": "8",
    "fontname": "IBM Plex Mono",
    "fontcolor": "grey"
}

with Diagram("Setup a blog on k3s",
             show=False,
             graph_attr=graph_attr,
             node_attr=node_attr,
             direction="TB"):
    users = Users("Users")
    with Cluster("LetsEncrypt API Servers", graph_attr=graph_attr):
        letsencrypt = LetsEncrypt("LE SSL Certificate")
    with Cluster("BareMetal Server", graph_attr=graph_attr):
        with Cluster("K8S Cluster", graph_attr=graph_attr):
            with Cluster("NS Cert-Manager", graph_attr=graph_attr):
                certificate_request = CertManager("mywebsite.com")
            with Cluster("NS www", graph_attr=graph_attr):
                website_secret = Secret("mywebsite.com")
                with Cluster("Ingress", graph_attr=graph_attr):
                    ingress = Ingress("https")
                with Cluster("Pods", graph_attr=graph_attr):
                    pod = Pod('website')
                with Cluster("Deployment", graph_attr=graph_attr):
                    pod_deploy = Deployment("website")
                with Cluster("RS", graph_attr=graph_attr):
Example #3
0
""" An example use of the diagrams module to create an architecture diagram
similar to 'Reference Architecture: Cross Account AWS CodePipeline':

https://github.com/awslabs/aws-refarch-cross-account-pipeline
"""

from diagrams import Cluster, Diagram, Edge
from diagrams.aws.compute import Lambda
from diagrams.aws.devtools import Codebuild, Codecommit, Codepipeline
from diagrams.aws.general import Users
from diagrams.aws.management import Cloudformation
from diagrams.aws.mobile import APIGateway
from diagrams.aws.storage import S3

with Diagram(None, filename="aws-cross-account-pipeline", show=False):
    developers = Users("Developers")

    with Cluster("Developer Account"):
        source_code = Codecommit("CodeCommit")
        source_code << Edge(label="merge pr") << developers

    with Cluster("Shared Services Account"):
        with Cluster("Pipeline"):
            pipeline = Codepipeline("CodePipeline")
            build = Codebuild("Codebuild")
        artifacts = S3("Build Artifacts")
        source_code >> Edge(label="trigger") >> pipeline
        developers >> Edge(label="manual approval") >> pipeline
        pipeline >> build >> Edge(label="yaml file") >> artifacts

    with Cluster("Test Workload Account"):
Example #4
0
# diagram.py
from diagrams import Cluster, Diagram
from diagrams.aws.general import Users
from diagrams.aws.storage import S3
from diagrams.aws.network import CF, ELB
from diagrams.aws.compute import EC2

with Diagram("Terrascan Website", show=False, filename="01-s3-public-bucket"):
    users = Users("users")
    with Cluster("Internet Exposed"):
        s3 = S3("static-assets")

    users >> s3

with Diagram("Terrascan Website",
             show=False,
             filename="02-s3-block-public-access"):
    users = Users("users")
    with Cluster("Private Only"):
        s3 = S3("static-assets")

with Diagram("Terrascan Website",
             show=False,
             filename="03-s3-behind-cloudfront"):
    users = Users("users")
    with Cluster("Internet Exposed"):
        cf = CF("CDN")
    with Cluster("Private Only"):
        s3 = S3("static-assets")

    users >> cf >> s3
Example #5
0
    def build_arch_diag(self, account_dict, account_refs_dict):
        with Diagram(account_dict['account_alias'], show=True, direction="TB"):
            ## TIER 1: EXTERNAL TO AWS CLUSTERLESS
            ## Contains: Users, DNS, WAF, CloudFront, Cross Account VPC Peering (happens out of order)
            ## -------------------------------------------------------------------------------

            ## Users
            users = Users('Actors')
            self.ingress.append(users)
            ## DNS
            if account_dict['dns']['name'] == 'Route53':
                dns = Route53('Route53')
            else:
                dns = TradicionalServer('External DNS')
            self.ingress.append(dns)
            ## WAF
            try:
                if account_dict['waf']['cloudfront']:
                    waf = WAF('WAF - CloudFront')
            except KeyError:
                waf = None
            ## CloudFront
            if self.check_key(account_dict, 'cf'):
                cloudfront = CloudFront('CloudFront')
                self.ingress.append(cloudfront)
                cf_check = True
            ## CAVP
            cross_accounts = self.check_cross_account_refs(account_dict)

            ## TIER 2:  ACCOUNT CLUSTER
            ## Contains: CAVP Accounts, Account ID, Account Alias, Global S3 Buckets
            ## -------------------------------------------------------------------------------

            ## CAVP Accounts
            for x_account in cross_accounts:
                ## Since x_account is the key value for the account dict -
                xaccount_dict = cross_accounts['{}'.format(x_account)]
                ## Next with Accepter Accounts/VPC's/Nodes
                try:
                    if xaccount_dict['xacc_account']:
                        alias = self.get_account_refs(
                            xaccount_dict['xacc_account'], account_refs_dict)
                        with Cluster('Account: {}'.format(alias),
                                     graph_attr={
                                         'margin': '50',
                                         'bgcolor': 'white',
                                         'penwidth': '5'
                                     }):
                            ## Make the cross account VPC
                            with Cluster(xaccount_dict['xacc_vpc'],
                                         graph_attr={'bgcolor': 'white'}):
                                ## Create the accuester node and add it to the dictionary with the
                                ## Connection ID for diagram connection later.
                                xacc_node = VPCPeering(
                                    'VPC Peering - Accepter')
                                cross_accounts['{}'.format(
                                    x_account)]['xacc_node'] = xacc_node
                except KeyError:
                    try:
                        if xaccount_dict['xreq_account']:
                            alias = self.get_account_refs(
                                xaccount_dict['xreq_account'],
                                account_refs_dict)
                            with Cluster('Account: {}'.format(alias),
                                         graph_attr={
                                             'margin': '50',
                                             'bgcolor': 'white',
                                             'penwidth': '5'
                                         }):
                                ## Make the cross account VPC
                                with Cluster(xaccount_dict['xreq_vpc'],
                                             graph_attr={'bgcolor': 'white'}):
                                    ## Create the Requester node and add it to the dictionary with the
                                    ## Connection ID for diagram connection later.
                                    xreq_node = VPCPeering(
                                        'VPC Peering - Requester')
                                    cross_accounts['{}'.format(
                                        x_account)]['xreq_node'] = xreq_node
                    except KeyError:
                        continue

            ## Account ID and Alias
            with Cluster('Account: {}'.format(account_dict['account_alias']),
                         graph_attr={
                             'margin': '150',
                             'bgcolor': 'white',
                             'penwidth': '5'
                         }):

                ## Global S3 Buckets
                s3_overflow = {}
                ## Diagram S3's in alternate Regions
                for s3 in account_dict['s3']:
                    if s3['region'] == None:
                        s3_node = SimpleStorageServiceS3(s3['Name'])
                    else:
                        ## If the S3 bucket isn't in one of our known AZ's,
                        ## append to a list for the new region
                        if s3['region'] in s3_overflow.keys():
                            s3_overflow[s3['region']].append(s3)
                        else:
                            ## If the S3 in a region that doesn't have an existing AZ,
                            ## create a new key for the region and put the nodes in it
                            for az in account_dict['az']:
                                if az['RegionName'] != s3['region']:
                                    s3_overflow[s3['region']] = []
                                    s3_overflow[s3['region']].append(s3)

                ## Create new cluster for each region in s3_overflow
                for region in account_dict['regions']:
                    if region in s3_overflow.keys():
                        with Cluster(region,
                                     graph_attr={
                                         'bgcolor': 'white',
                                         'style': 'dashed',
                                         'pencolor': 'blue'
                                     }):
                            for s3 in s3_overflow[region]:
                                s3_node = SimpleStorageServiceS3(s3['Name'])

                ## TIER 3:  VPC CLUSTER
                ## Contains: VPC, CAVP, VPC Peering, Internet Gateways, Load balancers, S3 buckets
                ## -------------------------------------------------------------------------------

                ## VPC
                for v in range(len(account_dict['vpc'])):
                    ## Dynamically add contents of VPC Cluster
                    with Cluster(account_dict['vpc'][v]['VpcId'],
                                 graph_attr={'bgcolor': 'white'}):

                        ## CAVP and VPC Peering
                        account_dict['vpc'][v]['RequestNodes'] = []
                        account_dict['vpc'][v]['AcceptNodes'] = []

                        ## Create VPC Peering nodes, but connections can only be made once
                        ## all Requester and Accepter nodes have been created.  Store the nodes
                        ## in a list for later reference, as dynamically created nodes can't be
                        ## referred to uniquely and will need to be iterated upon later.
                        for req in account_dict['vpc'][v]['PeerRequest']:
                            if req['RequesterVpcInfo'][
                                    'OwnerId'] == account_dict['account_id']:
                                req_node = VPCPeering(
                                    'VPC Peering - Requester')
                                cross_accounts[req['VpcPeeringConnectionId']][
                                    'req_node'] = req_node

                        for acc in account_dict['vpc'][v]['PeerAccept']:
                            if acc['AccepterVpcInfo'][
                                    'OwnerId'] == account_dict['account_id']:
                                acc_node = VPCPeering('VPC Peering - Accepter')
                                cross_accounts[acc['VpcPeeringConnectionId']][
                                    'acc_node'] = acc_node

                        ## Internet Gateway
                        try:
                            ## Check if Internet Gateway exists
                            if account_dict['igw']:
                                for igw in account_dict['igw']:
                                    for attach in igw['Attachments']:
                                        ## If the IGW is attached to the VPC and available
                                        ## add it to igws list, which we will attach the
                                        ## previous ingress point to
                                        if attach['VpcId'] == account_dict[
                                                'vpc'][v]['VpcId'] and attach[
                                                    'State'] == 'attached':
                                            internet_gw = InternetGateway(
                                                igw['InternetGatewayId'])
                                            igws.append(internet_gw)
                                            ig_check = True
                            if len(igws) > 0:
                                ## Append igws list to ingress list as the next connection point
                                self.ingress.append(igws)
                        except KeyError:
                            ig_check = False

                        ## Load Balancer
                        try:
                            for elb in account_dict['elb']:
                                ## Check if a WAF is associated with the Load Balancer
                                #waf_check = check_key(elb)
                                elastic_lb = ElasticLoadBalancing(
                                    '{} ({})'.format(elb['DNSName'],
                                                     elb['Scheme']))
                                for az in elb['AvailabilityZones']:
                                    elb_tuple = elastic_lb, az['SubnetId']
                                    self.elb_subnets.append(elb_tuple)
                                if elb['Scheme'] == 'internet-facing' and elb[
                                        'State'] == 'active':
                                    ## If the Load Balancer is internet-facing, a WAF should be put in place
                                    self.ingress.append(elastic_lb)
                                    elb_check = True
                        except KeyError:
                            elb_check = False

                        ## TIER 4:  REGION CLUSTER
                        ## Contains: S3 buckets, WAF Regional, DynamoDB
                        ## -------------------------------------------------------------------------------
                        region_list = self.kill_dupes(account_dict['regions'])

                        for r in range(len(region_list)):
                            for a in range(len(account_dict['az'])):
                                if account_dict['az'][a][
                                        'RegionName'] == region_list[r]:
                                    with Cluster(region_list[r],
                                                 graph_attr=self.region_sheet):

                                        for s3 in account_dict['s3']:
                                            if s3['region'] == region_list[r]:
                                                s3_node = SimpleStorageServiceS3(
                                                    s3['Name'])
                                        ## WAF Regional
                                        ## PLACEHOLDER
                                        ## DynamoDB
                                        for ddb in account_dict['ddb']:
                                            ddb_region = account_dict['ddb'][
                                                ddb]['TableArn'].split(':')[3]
                                            if ddb_region == region_list[r]:
                                                ddb_node = Dynamodb(
                                                    account_dict['ddb'][ddb]
                                                    ['TableName'])

                                        ## TIER 5:  AVAILABILITY ZONE (AZ) CLUSTER
                                        ## Contains: RDS
                                        ## -------------------------------------------------------------------------------
                                        with Cluster(account_dict['az'][a]
                                                     ['ZoneName'],
                                                     graph_attr={
                                                         'bgcolor': 'white',
                                                         'style': 'dashed',
                                                         'pencolor': 'orange'
                                                     }):

                                            ## Dynamically add RDS
                                            for rds in account_dict['rds']:
                                                if rds['AvailabilityZone'] == account_dict[
                                                        'az'][a]['ZoneName']:
                                                    rds_node = RDS(
                                                        rds['DBName'])

                                            ## TIER 6:  SUBNET CLUSTER
                                            ## Contains: Security Groups, EC2 Instances
                                            ## -------------------------------------------------------------------------------
                                            for s in range(
                                                    len(account_dict['az'][a]
                                                        ['Subnets'])):
                                                with Cluster(account_dict['az']
                                                             [a]['Subnets'][s]
                                                             ['SubnetId']):
                                                    for rezzie in account_dict[
                                                            'az'][a][
                                                                'Subnets'][s][
                                                                    'ec2']:
                                                        for instance in rezzie[
                                                                'Instances']:
                                                            ec2_name = self.get_name_tag(
                                                                instance,
                                                                'EC2')
                                                            ec2_instance = EC2(
                                                                '{} ({})'.
                                                                format(
                                                                    ec2_name,
                                                                    instance[
                                                                        'InstanceType']
                                                                ))
                                                            self.ec2_instances.append(
                                                                ec2_instance)
                                                            ## If there is a load balancer, and the load balancer connects
                                                            ## to the subnet of the EC2 instance, connect the ELB to the
                                                            ## EC2 instance in the diagram
                                                            for elb_tuple in self.elb_subnets:
                                                                if account_dict['az'][
                                                                        a]['Subnets'][
                                                                            s]['SubnetId'] == elb_tuple[
                                                                                1]:
                                                                    self.ingress[
                                                                        -1] >> elb_tuple[
                                                                            0] >> ec2_instance

            for i in range(len(self.ingress)):
                try:
                    self.ingress[i] >> self.ingress[i + 1]
                except IndexError:
                    error = "Dead end, baby."

            for conn in cross_accounts:
                try:
                    req_node = cross_accounts[conn]['xreq_node']
                    acc_node = cross_accounts[conn]['acc_node']
                    req_node >> acc_node
                except KeyError:
                    continue