diff --git a/diagram.js b/diagram.js index ab8c44f..d869109 100644 --- a/diagram.js +++ b/diagram.js @@ -149,6 +149,16 @@ const cy = cytoscape({ 'text-halign': 'left', 'text-opacity': 0 /* hide built-in labels; we render HTML labels */ }}, + { selector: 'node[type = "account"]', style: { + 'background-color': '#0b1220', + 'background-opacity': 0.45, + 'border-color': 'data(color)', + 'border-width': 2, + 'padding': '90px', + 'shape': 'round-rectangle', + 'text-opacity': 0, + 'z-compound-depth': 'bottom' + }}, { selector: 'node[lx]', style: { 'text-margin-x': 'data(lx)' }}, { selector: 'node[ly]', style: { 'text-margin-y': 'data(ly)' }}, { selector: 'node[label]', style: { 'label': 'data(label)' }}, @@ -234,6 +244,38 @@ async function loadGraphAndBuildElements(region = 'us-west-1') { const g = (graph.regions && graph.regions[region]) || {}; const elements = []; + const accountPalette = ['#7c3aed','#0ea5e9','#f97316','#10b981','#facc15','#f472b6']; + const accountMeta = new Map(); + function canonicalAccountId(value, fallbackIndex){ + const raw = (value ?? '').toString().trim(); + return raw ? raw.replace(/\s+/g,'-') : `account-${fallbackIndex}`; + } + function pickAccountColor(index){ + return accountPalette[index % accountPalette.length]; + } + function registerAccount(rawId, label, color, alias){ + const info = { id: rawId, label, color, nodeId: `account:${rawId}`, alias: alias || null }; + accountMeta.set(rawId, info); + elements.push({ data: { id: info.nodeId, type:'account', label, color, rawId, alias: info.alias } }); + return info; + } + // Accounts are optional; gather them from the top-level array and from any + // `accountId` fields present on VPC records so multiple AWS accounts can share one canvas. + const accounts = Array.isArray(graph.accounts) ? graph.accounts : []; + accounts.forEach((acct, index) => { + const rawId = canonicalAccountId(acct.id || acct.accountId || acct.alias, index + 1); + const color = acct.color || acct.colour || acct.accent || pickAccountColor(index); + const label = acct.label || acct.name || rawId; + const alias = acct.alias || acct.accountAlias || null; + registerAccount(rawId, label, color, alias); + }); + function ensureAccount(raw){ + if (raw == null) return null; + const canonical = canonicalAccountId(raw, accountMeta.size + 1); + if (accountMeta.has(canonical)) return accountMeta.get(canonical); + return registerAccount(canonical, canonical, pickAccountColor(accountMeta.size), null); + } + const vpcs = g.vpcs || []; const subnets = g.subnets || []; const sgs = g.sgs || []; @@ -241,22 +283,34 @@ async function loadGraphAndBuildElements(region = 'us-west-1') { const rds = g.rds || []; const lbs = g.lbs || []; + const vpcAccountMeta = new Map(); + const subnetAccountMeta = new Map(); + const sgById = Object.fromEntries(sgs.map(s => [s.id, s])); // VPCs for (const v of vpcs) { - elements.push({ data: { id: v.id, type: 'vpc', label: `${v.name}\n${v.cidr}`, cidr: v.cidr, name: v.name } }); + const acctInfo = ensureAccount(v.accountId || v.account || v.account_id || null); + if (acctInfo) vpcAccountMeta.set(v.id, acctInfo); + const parent = acctInfo ? acctInfo.nodeId : undefined; + elements.push({ data: { id: v.id, type: 'vpc', label: `${v.name}\n${v.cidr}`, cidr: v.cidr, name: v.name, accountId: acctInfo ? acctInfo.id : null, accountLabel: acctInfo ? acctInfo.label : null, parent } }); } // Subnets for (const s of subnets) { const label = `${(s.name||s.id)}\n${s.cidr}\n${s.az}`; - elements.push({ data: { id: s.id, type: 'subnet', label, cidr: s.cidr, az: s.az, public: !!s.public, parent: s.vpc } }); + const fallbackAcct = vpcAccountMeta.get(s.vpc || '') || null; + const acctInfo = ensureAccount(s.accountId || (fallbackAcct && fallbackAcct.id) || null) || fallbackAcct; + if (acctInfo) subnetAccountMeta.set(s.id, acctInfo); + elements.push({ data: { id: s.id, type: 'subnet', label, cidr: s.cidr, az: s.az, public: !!s.public, parent: s.vpc, accountId: acctInfo ? acctInfo.id : null } }); } // SGs for (const sg of sgs) { const rin = sg.rules_in || [], rout = sg.rules_out || []; const label = `${sg.name || sg.id}\ningress: ${(rin[0]||'—')}${rin.length>1?'…':''}`; - elements.push({ data: { id: sg.id, type: 'sg', label, rules: { in: rin, out: rout } } }); + const fallbackAcct = vpcAccountMeta.get(sg.vpc || '') || null; + const acctInfo = ensureAccount(sg.accountId || (fallbackAcct && fallbackAcct.id) || null) || fallbackAcct; + const parent = acctInfo ? acctInfo.nodeId : undefined; + elements.push({ data: { id: sg.id, type: 'sg', label, rules: { in: rin, out: rout }, parent, accountId: acctInfo ? acctInfo.id : null, vpc: sg.vpc || null } }); } // SG<->SG edges based on rules referencing other SGs function parseSgRef(rule){ @@ -287,16 +341,20 @@ async function loadGraphAndBuildElements(region = 'us-west-1') { // EC2 for (const i of ec2s) { const label = `${i.name || i.id}\n${i.id}\n${i.type || ''}\n${i.privateIp ? ('Private IP: ' + i.privateIp) : ''}`; + const fallbackAcct = subnetAccountMeta.get(i.subnet || '') || vpcAccountMeta.get(i.vpc || '') || null; + const acctInfo = ensureAccount(i.accountId || (fallbackAcct && fallbackAcct.id) || null) || fallbackAcct; elements.push({ data: { id: i.id, type: 'ec2', label, name: i.name, instanceId: i.id, privateIp: i.privateIp, - publicIp: i.publicIp, state: i.state, parent: i.subnet, sgs: i.sgs || [] } }); + publicIp: i.publicIp, state: i.state, parent: i.subnet, sgs: i.sgs || [], accountId: acctInfo ? acctInfo.id : null, vpc: i.vpc || null } }); for (const sgid of (i.sgs || [])) if (sgById[sgid]) elements.push({ data: { id:`sg-${sgid}->${i.id}`, source: sgid, target: i.id, label:'attached', class:'sg-attach' }}); } // RDS for (const db of rds) { const parentSubnet = (db.subnetGroup && db.subnetGroup[0]) || null; const label = `${db.engine}\n${db.port}\n${db.publiclyAccessible?'public':'private'}`; - elements.push({ data: { id: db.id, type:'rds', label, engine:db.engine, port:db.port, publiclyAccessible:!!db.publiclyAccessible, parent: parentSubnet, sgs: db.sgs || [] }}); + const fallbackAcct = subnetAccountMeta.get(parentSubnet || '') || null; + const acctInfo = ensureAccount(db.accountId || (fallbackAcct && fallbackAcct.id) || null) || fallbackAcct; + elements.push({ data: { id: db.id, type:'rds', label, engine:db.engine, port:db.port, publiclyAccessible:!!db.publiclyAccessible, parent: parentSubnet, sgs: db.sgs || [], accountId: acctInfo ? acctInfo.id : null } }); for (const sgid of (db.sgs || [])) if (sgById[sgid]) elements.push({ data: { id:`sg-${sgid}->${db.id}`, source: sgid, target: db.id, label:'attached', class:'sg-attach' }}); } // LBs @@ -304,7 +362,9 @@ async function loadGraphAndBuildElements(region = 'us-west-1') { const parent = (lb.subnets && lb.subnets[0]) || (subnets[0] && subnets[0].id) || null; const lstText = (lb.listeners || []).map(L => L.port).join(','); const label = `${lb.id}\nlisteners: ${lstText || '—'}\n${lb.scheme}`; - elements.push({ data: { id: lb.id, type: (lb.type==='network'?'nlb':'alb'), label, scheme: lb.scheme, listeners: lb.listeners || [], parent, sgs: lb.securityGroups || [], dns: lb.dns } }); + const fallbackAcct = subnetAccountMeta.get(parent || '') || null; + const acctInfo = ensureAccount(lb.accountId || (fallbackAcct && fallbackAcct.id) || null) || fallbackAcct; + elements.push({ data: { id: lb.id, type: (lb.type==='network'?'nlb':'alb'), label, scheme: lb.scheme, listeners: lb.listeners || [], parent, sgs: lb.securityGroups || [], dns: lb.dns, accountId: acctInfo ? acctInfo.id : null } }); for (const sgid of (lb.securityGroups || [])) if (sgById[sgid]) elements.push({ data: { id:`sg-${sgid}->${lb.id}`, source: sgid, target: lb.id, label:'attached', class:'sg-attach' }}); const tgs = lb.targetGroups || []; const targetToPort = {}; for (const tg of tgs) for (const t of (tg.targets || [])) targetToPort[t] = tg.port || targetToPort[t] || ''; @@ -335,17 +395,41 @@ async function loadGraphAndBuildElements(region = 'us-west-1') { default: return ''; } } - function vpnBadge(name){ return (name && /vpn/i.test(name)) ? 'VPN' : ''; } + function vpnBadge(name){ return (name && /vpn/i.test(name)) ? 'VPN' : ''; } + function typeBadge(type){ + switch(type){ + case 'nat': return 'NAT'; + case 'igw': return 'IGW'; + case 'endpoint': + case 'vpce': + case 'gateway-endpoint': + return 'VPCE'; + case 'sg': return 'SG'; + default: return ''; + } + } function statusDot(state){ const cls=(state==='running')?'run':(state==='stopped'?'stop':'unk'); const txt=state||'unknown'; return `${escapeHtml(txt)}`; } function sgRuleCount(d){ const rin=(d.rules&&d.rules.in)?d.rules.in.length:0; const rout=(d.rules&&d.rules.out)?d.rules.out.length:0; return rin+rout; } - // Attach HTML labels for SG/ALB/NLB/RDS/EC2 centered inside nodes and Subnet at top-left - if (cy.nodeHtmlLabel) { - cy.nodeHtmlLabel([ - { - query:'node[type = "sg"], node[type = "alb"], node[type = "nlb"], node[type = "rds"], node[type = "ec2"]', - halign:'center', valign:'center', halignBox:'center', valignBox:'center', - tpl: function(d){ + // Attach HTML labels for SG/ALB/NLB/RDS/EC2 centered inside nodes and Subnet at top-left + if (cy.nodeHtmlLabel) { + cy.nodeHtmlLabel([ + { + query:'node[type = "account"]', + halign:'left', valign:'top', halignBox:'left', valignBox:'top', + tpl: function(d){ + const accent=d.color||'#38bdf8'; + const name=d.label||(d.rawId||d.id||'account'); + return `
+ + ${escapeHtml(name)} +
`; + } + }, + { + query:'node[type = "sg"], node[type = "alb"], node[type = "nlb"], node[type = "rds"], node[type = "ec2"]', + halign:'center', valign:'center', halignBox:'center', valignBox:'center', + tpl: function(d){ const type=d.type; const name=d.name||(d.label||'').split('\n')[0]||d.id; const pub=d.publicIp||d.publicIpAddress||d.public_ip||d.dns||''; const priv=d.privateIp||d.private_ip||''; @@ -361,17 +445,78 @@ async function loadGraphAndBuildElements(region = 'us-west-1') { if (priv) lines.push(`
Private IP: ${escapeHtml(priv)}
`); if (pub) lines.push(`
Public: ${escapeHtml(pub)}
`); } - const badge=vpnBadge(name); + const badges=[]; + const vpnChip=vpnBadge(name); if (vpnChip) badges.push(vpnChip); + const typeChip=typeBadge(type); if (typeChip) badges.push(typeChip); + const badgeHtml=badges.join(''); return `
-
${escapeHtml(name)}${badge}
+
${iconSvg(type)}${escapeHtml(name)}${badgeHtml}
${lines.join('')}
`; } }, - { - query:'node[type = "subnet"]', - halign:'left', valign:'top', halignBox:'left', valignBox:'top', - tpl: function(d){ + { + query:'node[type = "alb"], node[type = "nlb"]', + halign:'center', valign:'center', halignBox:'center', valignBox:'center', + tpl: function(d){ + const icon = iconSvg(d.type === 'nlb' ? 'nlb' : 'alb'); + const name = (d.label || '').split('\n')[0] || d.id; + const dns = d.dns ? `
${escapeHtml(d.dns)}
` : ''; + const listeners = Array.isArray(d.listeners) ? d.listeners.map(L => L.port).join(', ') : ''; + const listenerLine = listeners ? `
listeners: ${escapeHtml(listeners)}
` : ''; + const badges=[]; + const typeChip=typeBadge(d.type); + if (typeChip) badges.push(typeChip); + const badgeHtml=badges.join(''); + return `
+
+ ${icon} + ${escapeHtml(name)}${badgeHtml} +
+ ${dns} + ${listenerLine} +
`; + } + }, + { + query:'node[type = "sg"]', + halign:'center', valign:'center', halignBox:'center', valignBox:'center', + tpl: function(d){ + const rules = sgRuleCount(d); + const badges=[]; + const typeChip=typeBadge('sg'); if (typeChip) badges.push(typeChip); + const badgeHtml=badges.join(''); + return `
+
+ ${iconSvg('sg')} + ${escapeHtml(d.name || d.label || d.id)}${badgeHtml} +
+
${escapeHtml(`${rules} rule${rules===1?'':'s'}`)}
+
`; + } + }, + { + query:'node[type = "nat"], node[type = "igw"], node[type = "vpn"]', + halign:'center', valign:'center', halignBox:'center', valignBox:'center', + tpl: function(d){ + const name=d.name||(d.label||'').split('\n')[0]||d.id; + const icon = iconSvg(d.type); + const badges=[]; + const vpnChip=vpnBadge(name); if (vpnChip) badges.push(vpnChip); + const typeChip=typeBadge(d.type); if (typeChip) badges.push(typeChip); + const badgeHtml=badges.join(''); + return `
+
+ ${icon} + ${escapeHtml(name)}${badgeHtml} +
+
`; + } + }, + { + query:'node[type = "subnet"]', + halign:'left', valign:'top', halignBox:'left', valignBox:'top', + tpl: function(d){ const name=(d.name||(d.label||'').split('\n')[0]||d.id); const cidr=d.cidr||''; const az=d.az||''; @@ -496,12 +641,13 @@ async function loadGraphAndBuildElements(region = 'us-west-1') { if(!ele){ $details.textContent=''; return; } const d=ele.data(); const base={ id:d.id, type:d.type, label:d.label }; let extra={}; switch(d.type){ - case 'vpc': extra={ cidr:d.cidr, name:d.name }; break; + case 'vpc': extra={ cidr:d.cidr, name:d.name, accountId:d.accountId, accountLabel:d.accountLabel }; break; + case 'account': extra={ label:d.label, color:d.color, rawId:d.rawId, alias:d.alias }; break; case 'subnet': extra={ cidr:d.cidr, az:d.az, public:d.public }; break; - case 'alb': extra={ scheme:d.scheme, dns:d.dns, listeners:d.listeners, sgs:d.sgs }; break; - case 'ec2': extra={ name:d.name, instanceId:d.instanceId, privateIp:d.privateIp, publicIp:d.publicIp, state:d.state, sgs:d.sgs }; break; - case 'rds': extra={ engine:d.engine, port:d.port, publiclyAccessible:d.publiclyAccessible, sgs:d.sgs }; break; - case 'sg': extra={ inbound_sorted: sortRules(d.rules && d.rules.in), outbound_sorted: sortRules(d.rules && d.rules.out) }; break; + case 'alb': extra={ scheme:d.scheme, dns:d.dns, listeners:d.listeners, sgs:d.sgs, accountId:d.accountId }; break; + case 'ec2': extra={ name:d.name, instanceId:d.instanceId, privateIp:d.privateIp, publicIp:d.publicIp, state:d.state, sgs:d.sgs, accountId:d.accountId }; break; + case 'rds': extra={ engine:d.engine, port:d.port, publiclyAccessible:d.publiclyAccessible, sgs:d.sgs, accountId:d.accountId }; break; + case 'sg': extra={ inbound_sorted: sortRules(d.rules && d.rules.in), outbound_sorted: sortRules(d.rules && d.rules.out), accountId: d.accountId }; break; default: extra=d; break; } $details.textContent=JSON.stringify({ ...base, ...extra }, null, 2); diff --git a/gather.py b/gather.py index 2d96e10..c9a3945 100755 --- a/gather.py +++ b/gather.py @@ -1,114 +1,277 @@ #!/usr/bin/env python3 -import boto3, json, os, sys +""" +Fetch AWS VPC-related metadata and emit a Cytoscape-friendly `graph.json` file. -def name_tag(tags): - return next((t['Value'] for t in (tags or []) if t['Key']=='Name'), None) +Adds support for multiple AWS accounts by letting you specify one or more AWS CLI +profiles. Each account is tagged in the output so the front-end can group VPCs +per account. +""" +import argparse +import json +from collections import defaultdict -def collect(region): - s = boto3.Session(region_name=region) - ec2, elb, rds = s.client('ec2'), s.client('elbv2'), s.client('rds') - out = {k:[] for k in ['vpcs','subnets','sgs','enis','ec2','lbs','rds','exposures']} +import boto3 +from botocore.exceptions import ClientError + +RESOURCE_KEYS = ['vpcs', 'subnets', 'sgs', 'enis', 'ec2', 'lbs', 'rds', 'exposures'] +ACCOUNT_COLORS = ['#7c3aed', '#0ea5e9', '#f97316', '#10b981', '#facc15', '#f472b6'] + + +def name_tag(tags): + return next((t['Value'] for t in (tags or []) if t['Key'] == 'Name'), None) + + +def empty_region(): + return {k: [] for k in RESOURCE_KEYS} + + +def resolve_account(session, profile_hint=None): + sts = session.client('sts') + identity = sts.get_caller_identity() + account_id = identity['Account'] + + alias = None + try: + iam = session.client('iam') + aliases = iam.list_account_aliases().get('AccountAliases', []) + alias = aliases[0] if aliases else None + except ClientError: + alias = None + + label = alias or profile_hint or account_id + return {'id': account_id, 'label': label, 'alias': alias} + + +def collect(session, account): + region = session.region_name + out = empty_region() + + ec2 = session.client('ec2') + elb = session.client('elbv2') + rds = session.client('rds') - # VPCs, Subnets, SGs, ENIs, Instances vpcs = ec2.describe_vpcs()['Vpcs'] subnets = ec2.describe_subnets()['Subnets'] sgs = ec2.describe_security_groups()['SecurityGroups'] enis = ec2.describe_network_interfaces()['NetworkInterfaces'] - resv = ec2.describe_instances()['Reservations'] + reservations = ec2.describe_instances()['Reservations'] for v in vpcs: - out['vpcs'].append({'id':v['VpcId'],'cidr':v['CidrBlock'],'name':name_tag(v.get('Tags')) or v['VpcId']}) + out['vpcs'].append({ + 'id': v['VpcId'], + 'cidr': v['CidrBlock'], + 'name': name_tag(v.get('Tags')) or v['VpcId'], + 'accountId': account['id'] + }) + for sn in subnets: out['subnets'].append({ - 'id':sn['SubnetId'],'vpc':sn['VpcId'],'cidr':sn['CidrBlock'], - 'az':sn['AvailabilityZone'],'public':sn.get('MapPublicIpOnLaunch',False) + 'id': sn['SubnetId'], + 'vpc': sn['VpcId'], + 'cidr': sn['CidrBlock'], + 'az': sn['AvailabilityZone'], + 'public': sn.get('MapPublicIpOnLaunch', False), + 'accountId': account['id'] }) + + def flatten_rules(perms): + rules = [] + for perm in perms: + proto = perm.get('IpProtocol') + frm = perm.get('FromPort') + to = perm.get('ToPort') + if frm is None: + port = 'all' + elif frm == to: + port = f"{frm}" + else: + port = f"{frm}-{to}" + for ipr in perm.get('IpRanges', []) + perm.get('Ipv6Ranges', []): + cidr = ipr.get('CidrIp') or ipr.get('CidrIpv6') + rules.append(f"{proto} {port} from {cidr}") + for sgr in perm.get('UserIdGroupPairs', []): + rules.append(f"{proto} {port} from {sgr['GroupId']}") + return rules + for g in sgs: - def flatten(perms): - r=[] - for p in perms: - proto=p.get('IpProtocol'); frm=p.get('FromPort'); to=p.get('ToPort') - port = f"{frm}" if frm==to else f"{frm}-{to}" if frm is not None else "all" - for ipr in p.get('IpRanges',[]) + p.get('Ipv6Ranges',[]): - cidr = ipr.get('CidrIp') or ipr.get('CidrIpv6') - r.append(f"{proto} {port} from {cidr}") - for sgr in p.get('UserIdGroupPairs',[]): - r.append(f"{proto} {port} from {sgr['GroupId']}") - return r - out['sgs'].append({'id':g['GroupId'],'name':g.get('GroupName'), - 'rules_in':flatten(g.get('IpPermissions',[])), - 'rules_out':flatten(g.get('IpPermissionsEgress',[]))}) - for ni in enis: - assoc = ni.get('Association',{}) - out['enis'].append({ - 'id':ni['NetworkInterfaceId'],'subnet':ni['SubnetId'], - 'sgs':[sg['GroupId'] for sg in ni.get('Groups',[])], - 'privateIp':ni.get('PrivateIpAddress'), - 'publicIp':assoc.get('PublicIp') + out['sgs'].append({ + 'id': g['GroupId'], + 'name': g.get('GroupName'), + 'vpc': g.get('VpcId'), + 'accountId': account['id'], + 'rules_in': flatten_rules(g.get('IpPermissions', [])), + 'rules_out': flatten_rules(g.get('IpPermissionsEgress', [])) }) - for r in resv: - for i in r['Instances']: - n = name_tag(i.get('Tags')) or i['InstanceId'] - eni = (i.get('NetworkInterfaces') or [{}])[0] + + for ni in enis: + assoc = ni.get('Association', {}) + out['enis'].append({ + 'id': ni['NetworkInterfaceId'], + 'subnet': ni['SubnetId'], + 'vpc': ni.get('VpcId'), + 'sgs': [sg['GroupId'] for sg in ni.get('Groups', [])], + 'privateIp': ni.get('PrivateIpAddress'), + 'publicIp': assoc.get('PublicIp'), + 'accountId': account['id'] + }) + + for reservation in reservations: + for inst in reservation['Instances']: + inst_name = name_tag(inst.get('Tags')) or inst['InstanceId'] out['ec2'].append({ - 'id': i['InstanceId'], - 'name': n, - 'type': i['InstanceType'], - 'privateIp': i.get('PrivateIpAddress'), - 'publicIp': i.get('PublicIpAddress'), # shows on label - 'state': i.get('State', {}).get('Name', 'unknown'), # running/stopped - 'sgs': [g['GroupId'] for g in i.get('SecurityGroups',[])], - 'subnet': i.get('SubnetId') + 'id': inst['InstanceId'], + 'name': inst_name, + 'type': inst['InstanceType'], + 'privateIp': inst.get('PrivateIpAddress'), + 'publicIp': inst.get('PublicIpAddress'), + 'state': inst.get('State', {}).get('Name', 'unknown'), + 'sgs': [g['GroupId'] for g in inst.get('SecurityGroups', [])], + 'subnet': inst.get('SubnetId'), + 'vpc': inst.get('VpcId'), + 'accountId': account['id'] }) - # Load balancers (ALB/NLB), listeners, target groups/targets try: lbs = elb.describe_load_balancers()['LoadBalancers'] - except elb.exceptions.UnsupportedFeatureException: + except (ClientError, elb.exceptions.UnsupportedFeatureException): lbs = [] + for lb in lbs: - lbid = lb['LoadBalancerName'] - listeners = elb.describe_listeners(LoadBalancerArn=lb['LoadBalancerArn'])['Listeners'] - lst = [{'proto':L['Protocol'],'port':L['Port']} for L in listeners] - tgs = elb.describe_target_groups(LoadBalancerArn=lb['LoadBalancerArn'])['TargetGroups'] - tga=[] + lb_id = lb['LoadBalancerName'] + try: + listeners = elb.describe_listeners(LoadBalancerArn=lb['LoadBalancerArn'])['Listeners'] + except ClientError: + listeners = [] + listener_meta = [{'proto': L['Protocol'], 'port': L['Port']} for L in listeners] + + try: + tgs = elb.describe_target_groups(LoadBalancerArn=lb['LoadBalancerArn'])['TargetGroups'] + except ClientError: + tgs = [] + + target_groups = [] + all_targets = [] for tg in tgs: - th = elb.describe_target_health(TargetGroupArn=tg['TargetGroupArn'])['TargetHealthDescriptions'] - targets=[thd['Target']['Id'] for thd in th] - tga.append({'port':tg.get('Port'),'targets':targets}) + try: + health = elb.describe_target_health(TargetGroupArn=tg['TargetGroupArn'])['TargetHealthDescriptions'] + except ClientError: + health = [] + targets = [desc['Target']['Id'] for desc in health] + target_groups.append({'port': tg.get('Port'), 'targets': targets}) + all_targets.extend(targets) + out['lbs'].append({ - 'id': lbid, + 'id': lb_id, 'scheme': lb['Scheme'], 'type': lb['Type'], - 'dns': lb.get('DNSName'), # add me (handy on the label) - 'subnets': [z['SubnetId'] for z in lb.get('AvailabilityZones',[])], - 'securityGroups': lb.get('SecurityGroups',[]), - 'listeners': lst, 'targetGroups': tga - }) - # Simple exposure: internet-facing LB listeners are public surfaces - if lb['Scheme']=='internet-facing': - for L in lst: - out['exposures'].append({'surface':f"{lbid}:{L['port']}", - 'world_open':True,'via':lb['Type'].upper(), - 'to': [f"{t}:{next((tg['port'] for tg in tga if t in tg['targets']),None)}" for t in sum([tg['targets'] for tg in tga],[])]}) + 'dns': lb.get('DNSName'), + 'subnets': [az['SubnetId'] for az in lb.get('AvailabilityZones', [])], + 'securityGroups': lb.get('SecurityGroups', []), + 'listeners': listener_meta, + 'targetGroups': target_groups, + 'accountId': account['id'] + }) + + if lb['Scheme'] == 'internet-facing': + for listener in listener_meta: + out['exposures'].append({ + 'surface': f"{lb_id}:{listener['port']}", + 'world_open': True, + 'via': lb['Type'].upper(), + 'to': [ + f"{t}:{next((tg['port'] for tg in target_groups if t in tg['targets']), None)}" + for t in all_targets + ], + 'accountId': account['id'], + 'region': region + }) - # RDS for db in rds.describe_db_instances()['DBInstances']: out['rds'].append({ - 'id':db['DBInstanceIdentifier'],'engine':db['Engine'], - 'port':db['DbInstancePort'] if 'DbInstancePort' in db else db.get('Endpoint',{}).get('Port'), - 'publiclyAccessible':db.get('PubliclyAccessible',False), - 'sgs':[v['VpcSecurityGroupId'] for v in db.get('VpcSecurityGroups',[])], - 'subnetGroup':[s['SubnetIdentifier'] for s in db.get('DBSubnetGroup',{}).get('Subnets',[])] + 'id': db['DBInstanceIdentifier'], + 'engine': db['Engine'], + 'port': db.get('DbInstancePort') or db.get('Endpoint', {}).get('Port'), + 'publiclyAccessible': db.get('PubliclyAccessible', False), + 'sgs': [sg['VpcSecurityGroupId'] for sg in db.get('VpcSecurityGroups', [])], + 'subnetGroup': [s['SubnetIdentifier'] for s in db.get('DBSubnetGroup', {}).get('Subnets', [])], + 'accountId': account['id'] }) + return out -def main(): - regions = sys.argv[1:] or [boto3.Session().region_name or 'us-west-1'] - graph = {'regions':{}} - for r in regions: - graph['regions'][r] = collect(r) - with open('graph.json','w') as f: json.dump(graph, f, indent=2) - print('Wrote graph.json for regions:', ', '.join(regions)) -if __name__=='__main__': main() +def parse_args(): + parser = argparse.ArgumentParser(description='Gather AWS VPC graph data into graph.json') + parser.add_argument('regions', nargs='*', help='AWS regions to scan (defaults to your configured region)') + parser.add_argument('-r', '--region', dest='regions_opt', action='append', help='Additional region to scan (repeatable)') + parser.add_argument('-p', '--profile', dest='profiles', action='append', help='AWS CLI profile to use (repeatable)') + parser.add_argument('--account-label', dest='account_labels', action='append', help='Friendly label per profile (matches order of --profile)') + parser.add_argument('-o', '--output', default='graph.json', help='Output file (default: graph.json)') + return parser + + +def main(): + parser = parse_args() + args = parser.parse_args() + + regions = [] + if args.regions: + regions.extend(args.regions) + if args.regions_opt: + regions.extend(args.regions_opt) + + if not regions: + default_region = boto3.Session().region_name + if not default_region: + parser.error('No regions specified and no default region configured.') + regions = [default_region] + + regions = sorted(set(regions)) + + profiles = args.profiles or [None] + account_label_overrides = args.account_labels or [] + + graph_accounts = [] + account_index = {} + region_data = defaultdict(empty_region) + + for idx, profile in enumerate(profiles): + profile_label_hint = account_label_overrides[idx] if idx < len(account_label_overrides) else profile + for region in regions: + session = boto3.Session(profile_name=profile, region_name=region) + account = resolve_account(session, profile_label_hint) + account_id = account['id'] + if account_id not in account_index: + color = ACCOUNT_COLORS[len(account_index) % len(ACCOUNT_COLORS)] + entry = { + 'id': account_id, + 'label': account['label'], + 'alias': account['alias'], + 'profile': profile, + 'color': color + } + graph_accounts.append(entry) + account_index[account_id] = entry + else: + entry = account_index[account_id] + + data = collect(session, entry) + bucket = region_data[region] + for key in RESOURCE_KEYS: + bucket[key].extend(data[key]) + + graph = { + 'accounts': graph_accounts, + 'regions': {region: bucket for region, bucket in region_data.items()} + } + + with open(args.output, 'w') as f: + json.dump(graph, f, indent=2) + + region_list = ', '.join(regions) + profile_list = ', '.join(p or 'default' for p in profiles) + print(f"Wrote {args.output} for regions: {region_list} (profiles: {profile_list})") + + +if __name__ == '__main__': + main() diff --git a/graph.json b/graph.json index bd99770..7e38ebc 100644 --- a/graph.json +++ b/graph.json @@ -1,935 +1,1094 @@ -{ - "regions": { - "us-west-1": { - "vpcs": [ - { - "id": "vpc-87832de2", - "cidr": "10.4.0.0/16", - "name": "vault.vpc.01" - }, - { - "id": "vpc-c84eabad", - "cidr": "172.31.0.0/16", - "name": "vpc-c84eabad" - }, - { - "id": "vpc-331ad056", - "cidr": "10.3.0.0/16", - "name": "efw.vpc.02" - }, - { - "id": "vpc-afe722ca", - "cidr": "10.2.0.0/16", - "name": "efw.vpc.01" - }, - { - "id": "vpc-03f799f47b766798c", - "cidr": "10.10.0.0/16", - "name": "ALB-VPC" - } - ], - "subnets": [ - { - "id": "subnet-260ee27f", - "vpc": "vpc-331ad056", - "cidr": "10.3.0.0/24", - "az": "us-west-1b", - "public": false - }, - { - "id": "subnet-f73afeae", - "vpc": "vpc-331ad056", - "cidr": "10.3.1.0/24", - "az": "us-west-1b", - "public": false - }, - { - "id": "subnet-ebc4188e", - "vpc": "vpc-afe722ca", - "cidr": "10.2.1.0/24", - "az": "us-west-1c", - "public": false - }, - { - "id": "subnet-005bfd58e719e031f", - "vpc": "vpc-87832de2", - "cidr": "10.4.11.0/24", - "az": "us-west-1c", - "public": false - }, - { - "id": "subnet-035f81142068bf961", - "vpc": "vpc-03f799f47b766798c", - "cidr": "10.10.2.0/24", - "az": "us-west-1b", - "public": false - }, - { - "id": "subnet-d137fd88", - "vpc": "vpc-87832de2", - "cidr": "10.4.0.0/24", - "az": "us-west-1b", - "public": false - }, - { - "id": "subnet-e98e088c", - "vpc": "vpc-331ad056", - "cidr": "10.3.2.0/24", - "az": "us-west-1c", - "public": false - }, - { - "id": "subnet-08e40dcdc103438b8", - "vpc": "vpc-87832de2", - "cidr": "10.4.2.0/24", - "az": "us-west-1c", - "public": false - }, - { - "id": "subnet-0cb2aa7457413f5fe", - "vpc": "vpc-03f799f47b766798c", - "cidr": "10.10.3.0/24", - "az": "us-west-1c", - "public": true - }, - { - "id": "subnet-247a9341", - "vpc": "vpc-c84eabad", - "cidr": "172.31.16.0/20", - "az": "us-west-1c", - "public": true - }, - { - "id": "subnet-34173f72", - "vpc": "vpc-c84eabad", - "cidr": "172.31.0.0/20", - "az": "us-west-1b", - "public": true - }, - { - "id": "subnet-05b5dcdc91a8d3da2", - "vpc": "vpc-87832de2", - "cidr": "10.4.10.0/24", - "az": "us-west-1b", - "public": false - }, - { - "id": "subnet-16594550", - "vpc": "vpc-afe722ca", - "cidr": "10.2.2.0/24", - "az": "us-west-1b", - "public": false - }, - { - "id": "subnet-051f6d705e415834d", - "vpc": "vpc-03f799f47b766798c", - "cidr": "10.10.1.0/24", - "az": "us-west-1b", - "public": true - } - ], - "sgs": [ - { - "id": "sg-642cf701", - "name": "efw.vpc.01-securitygroup-web01", - "rules_in": [ - "tcp 80 from 0.0.0.0/0", - "-1 None from sg-da75adbf", - "icmp 0--1 from 0.0.0.0/0", - "tcp 12489 from 64.71.160.96/27", - "tcp 5666 from 64.71.160.96/27", - "tcp 3389 from 76.126.204.87/32", - "tcp 3389 from 64.71.160.98/32", - "tcp 3389 from 50.156.113.43/32", - "tcp 3389 from 162.222.31.254/32", - "tcp 3389 from 173.164.212.89/32", - "tcp 3389 from 174.85.92.60/32", - "tcp 443 from 0.0.0.0/0", - "tcp 8172 from 173.10.69.6/32", - "tcp 8172 from 173.164.212.89/32", - "icmp 8--1 from 0.0.0.0/0" - ], - "rules_out": [ - "-1 None from 0.0.0.0/0" - ] - }, - { - "id": "sg-00600deefd8e47cd0", - "name": "efw.vpc.02-securitygroup-rds", - "rules_in": [ - "tcp 3306 from 173.164.212.89/32" - ], - "rules_out": [ - "-1 None from 0.0.0.0/0" - ] - }, - { - "id": "sg-da75adbf", - "name": "default", - "rules_in": [ - "-1 None from sg-da75adbf", - "tcp 22 from 0.0.0.0/0", - "tcp 22 from sg-4235ee27", - "udp 11094 from 0.0.0.0/0", - "tcp 3389 from sg-4235ee27", - "icmp -1 from sg-4235ee27" - ], - "rules_out": [ - "-1 None from 0.0.0.0/0" - ] - }, - { - "id": "sg-c05a2ba5", - "name": "default", - "rules_in": [ - "-1 None from sg-c05a2ba5" - ], - "rules_out": [ - "-1 None from 0.0.0.0/0" - ] - }, - { - "id": "sg-0c00315bbb744b876", - "name": "default", - "rules_in": [ - "-1 None from sg-0c00315bbb744b876" - ], - "rules_out": [ - "-1 None from 0.0.0.0/0" - ] - }, - { - "id": "sg-495ab32c", - "name": "default", - "rules_in": [ - "-1 None from sg-495ab32c", - "tcp 3306 from 54.85.48.0/24", - "tcp 3306 from 173.164.212.89/32" - ], - "rules_out": [ - "-1 None from 0.0.0.0/0" - ] - }, - { - "id": "sg-0f2465c4421c2d5c2", - "name": "x-to-pdf-AppSG-4DM5CX7D35LE", - "rules_in": [ - "-1 None from sg-0f2465c4421c2d5c2", - "tcp 1-65000 from sg-b45a2bd1" - ], - "rules_out": [ - "-1 None from 0.0.0.0/0" - ] - }, - { - "id": "sg-8b746aec", - "name": "launch-wizard-1", - "rules_in": [ - "tcp 80 from 47.208.245.238/32", - "tcp 22 from 47.208.245.238/32", - "tcp 22 from 64.71.160.98/32", - "tcp 443 from 47.208.245.238/32", - "icmp 8--1 from 47.208.245.238/32" - ], - "rules_out": [ - "-1 None from 0.0.0.0/0" - ] - }, - { - "id": "sg-0a872ac3a6d9132a6", - "name": "node-app-alb-stack-AppAccessSG-DLeS5dz4pWwk", - "rules_in": [ - "tcp 22 from 0.0.0.0/0", - "tcp 11094 from 0.0.0.0/0", - "udp 11094 from 0.0.0.0/0" - ], - "rules_out": [ - "-1 None from 0.0.0.0/0" - ] - }, - { - "id": "sg-076d2ea1df0054074", - "name": "node-app-alb-stack-LoadBalancerSG-LgFQ2PFaob27", - "rules_in": [ - "tcp 80 from 0.0.0.0/0", - "tcp 443 from 0.0.0.0/0" - ], - "rules_out": [ - "-1 None from 0.0.0.0/0" - ] - }, - { - "id": "sg-b45a2bd1", - "name": "vault.vpc.01-securitygroup", - "rules_in": [ - "tcp 80 from 0.0.0.0/0", - "tcp 8080 from 76.246.46.113/32", - "icmp 0--1 from 0.0.0.0/0", - "icmp 0--1 from ::/0", - "tcp 22 from 73.90.210.219/32", - "tcp 22 from 73.90.209.115/32", - "tcp 22 from 47.208.245.238/32", - "tcp 22 from 73.90.211.68/32", - "tcp 22 from 166.170.37.145/32", - "tcp 22 from 135.26.148.110/32", - "tcp 22 from 108.82.46.156/32", - "tcp 22 from 47.208.247.13/32", - "tcp 22 from 98.150.190.32/32", - "tcp 22 from 64.71.160.0/24", - "tcp 22 from 76.126.204.87/32", - "tcp 22 from 13.52.6.112/29", - "tcp 22 from 174.85.92.60/32", - "tcp 22 from 45.28.138.65/32", - "tcp 5666 from 64.71.160.96/27", - "udp 11094 from 0.0.0.0/0", - "tcp 443 from 0.0.0.0/0", - "icmp 8--1 from 0.0.0.0/0" - ], - "rules_out": [ - "-1 None from 0.0.0.0/0" - ] - }, - { - "id": "sg-4235ee27", - "name": "efw.vpc.01-securitygroup-db01", - "rules_in": [ - "tcp 1433 from 10.2.2.0/24", - "-1 None from sg-da75adbf" - ], - "rules_out": [ - "-1 None from 0.0.0.0/0" - ] - }, - { - "id": "sg-04167d2e18ba15e45", - "name": "node-app-alb-stack-AppSG-tYWl4C0wtvl6", - "rules_in": [ - "tcp 8080 from sg-076d2ea1df0054074" - ], - "rules_out": [ - "-1 None from 0.0.0.0/0" - ] - }, - { - "id": "sg-06348763", - "name": "default", - "rules_in": [ - "tcp 1433 from 173.164.212.89/32", - "tcp 1433 from 72.173.157.190/32", - "tcp 1433 from 75.101.48.86/32", - "tcp 1433 from 107.3.172.143/32", - "tcp 1433 from 10.3.0.0/16", - "tcp 80 from 0.0.0.0/0", - "tcp 5432 from 10.3.0.157/32", - "tcp 5432 from 67.139.78.162/32", - "tcp 5432 from 209.210.190.204/32", - "tcp 5432 from 10.3.0.232/32", - "tcp 5432 from 10.3.0.247/32", - "tcp 5432 from sg-08fb4b412f90d5913", - "tcp 4021 from 173.164.212.89/32", - "tcp 5666 from 64.71.160.121/32", - "tcp 4020 from 173.164.212.89/32", - "tcp 3389 from 76.126.204.87/32", - "tcp 3389 from 64.71.160.98/32", - "tcp 3389 from 173.164.212.89/32", - "tcp 3389 from 72.173.157.190/32", - "tcp 3389 from 10.3.0.0/16", - "tcp 445 from 10.3.0.0/16", - "tcp 443 from 0.0.0.0/0", - "tcp 4026 from 173.164.212.89/32", - "tcp 4026 from 10.3.0.0/16", - "tcp 8172 from 173.164.212.89/32", - "tcp 8172 from 10.3.0.0/16", - "icmp 0--1 from 0.0.0.0/0", - "icmp 0--1 from 173.164.212.89/32", - "tcp 22 from 0.0.0.0/0", - "udp 1194 from 0.0.0.0/0", - "tcp 4024 from 173.164.212.89/32", - "tcp 1194 from 0.0.0.0/0", - "tcp 12489 from 64.71.160.121/32", - "tcp 4027 from 10.3.0.0/16", - "udp 11094 from 0.0.0.0/0", - "icmp 8--1 from 0.0.0.0/0" - ], - "rules_out": [ - "-1 None from 0.0.0.0/0" - ] - }, - { - "id": "sg-08fb4b412f90d5913", - "name": "eco.lambda.securitygroup", - "rules_in": [], - "rules_out": [ - "-1 None from 0.0.0.0/0" - ] - }, - { - "id": "sg-09621eafa81d9554d", - "name": "vault.vpc.01.securitygroup-rds-pvt", - "rules_in": [ - "tcp 3306 from 173.164.212.89/32", - "tcp 3306 from sg-b45a2bd1" - ], - "rules_out": [ - "-1 None from 0.0.0.0/0" - ] - } - ], - "enis": [ - { - "id": "eni-03cb7e3c6efba4fe6", - "subnet": "subnet-260ee27f", - "sgs": [ - "sg-06348763" - ], - "privateIp": "10.3.0.216", - "publicIp": "52.8.79.80" - }, - { - "id": "eni-0c6e3761c14140e52", - "subnet": "subnet-051f6d705e415834d", - "sgs": [ - "sg-076d2ea1df0054074" - ], - "privateIp": "10.10.1.212", - "publicIp": "50.18.175.227" - }, - { - "id": "eni-6a099b32", - "subnet": "subnet-260ee27f", - "sgs": [ - "sg-06348763" - ], - "privateIp": "10.3.0.207", - "publicIp": null - }, - { - "id": "eni-072ff2545f56240a7", - "subnet": "subnet-16594550", - "sgs": [ - "sg-4235ee27" - ], - "privateIp": "10.2.2.16", - "publicIp": null - }, - { - "id": "eni-064252b93ca105b7c", - "subnet": "subnet-05b5dcdc91a8d3da2", - "sgs": [ - "sg-b45a2bd1" - ], - "privateIp": "10.4.10.82", - "publicIp": null - }, - { - "id": "eni-08d57de7981ae0020", - "subnet": "subnet-035f81142068bf961", - "sgs": [ - "sg-04167d2e18ba15e45", - "sg-0a872ac3a6d9132a6" - ], - "privateIp": "10.10.2.106", - "publicIp": null - }, - { - "id": "eni-00feca9ca48c7ae0c", - "subnet": "subnet-05b5dcdc91a8d3da2", - "sgs": [ - "sg-b45a2bd1" - ], - "privateIp": "10.4.10.141", - "publicIp": null - }, - { - "id": "eni-8041e3da", - "subnet": "subnet-260ee27f", - "sgs": [ - "sg-06348763" - ], - "privateIp": "10.3.0.201", - "publicIp": null - }, - { - "id": "eni-9d73dbc7", - "subnet": "subnet-260ee27f", - "sgs": [ - "sg-06348763" - ], - "privateIp": "10.3.0.98", - "publicIp": null - }, - { - "id": "eni-04237833786a67013", - "subnet": "subnet-051f6d705e415834d", - "sgs": [ - "sg-0a872ac3a6d9132a6" - ], - "privateIp": "10.10.1.166", - "publicIp": "52.53.243.75" - }, - { - "id": "eni-084002309358bb545", - "subnet": "subnet-f73afeae", - "sgs": [ - "sg-06348763" - ], - "privateIp": "10.3.1.134", - "publicIp": null - }, - { - "id": "eni-0827085d571dccab7", - "subnet": "subnet-d137fd88", - "sgs": [ - "sg-b45a2bd1" - ], - "privateIp": "10.4.0.221", - "publicIp": "52.53.117.111" - }, - { - "id": "eni-0e844b9d718f3daa0", - "subnet": "subnet-16594550", - "sgs": [ - "sg-642cf701" - ], - "privateIp": "10.2.2.226", - "publicIp": "52.8.26.159" - }, - { - "id": "eni-0d6f412450d0e082b", - "subnet": "subnet-260ee27f", - "sgs": [ - "sg-06348763" - ], - "privateIp": "10.3.0.63", - "publicIp": "52.8.7.0" - }, - { - "id": "eni-05788a45421ce580f", - "subnet": "subnet-d137fd88", - "sgs": [ - "sg-b45a2bd1" - ], - "privateIp": "10.4.0.197", - "publicIp": "52.8.75.57" - }, - { - "id": "eni-0775830b9669fa479", - "subnet": "subnet-16594550", - "sgs": [ - "sg-642cf701" - ], - "privateIp": "10.2.2.18", - "publicIp": "54.153.101.192" - }, - { - "id": "eni-0f54a2ee3a5237ae1", - "subnet": "subnet-260ee27f", - "sgs": [ - "sg-06348763" - ], - "privateIp": "10.3.0.111", - "publicIp": "54.153.3.41" - }, - { - "id": "eni-08eb3a38264ccd212", - "subnet": "subnet-260ee27f", - "sgs": [ - "sg-06348763" - ], - "privateIp": "10.3.0.73", - "publicIp": null - }, - { - "id": "eni-0afbe7eb22dd6e8e3", - "subnet": "subnet-260ee27f", - "sgs": [ - "sg-06348763" - ], - "privateIp": "10.3.0.112", - "publicIp": "13.52.49.251" - }, - { - "id": "eni-018923614c623ef74", - "subnet": "subnet-260ee27f", - "sgs": [ - "sg-06348763" - ], - "privateIp": "10.3.0.122", - "publicIp": "52.8.85.37" - }, - { - "id": "eni-0f310dd2e36654ed7", - "subnet": "subnet-260ee27f", - "sgs": [ - "sg-06348763" - ], - "privateIp": "10.3.0.120", - "publicIp": null - }, - { - "id": "eni-00172626263229e1a", - "subnet": "subnet-051f6d705e415834d", - "sgs": [], - "privateIp": "10.10.1.37", - "publicIp": "13.57.111.5" - }, - { - "id": "eni-0893189c99a73d4f2", - "subnet": "subnet-260ee27f", - "sgs": [ - "sg-06348763" - ], - "privateIp": "10.3.0.167", - "publicIp": null - }, - { - "id": "eni-0d0b9801f1e66ec76", - "subnet": "subnet-d137fd88", - "sgs": [], - "privateIp": "10.4.0.246", - "publicIp": "184.169.224.203" - }, - { - "id": "eni-b574dcef", - "subnet": "subnet-16594550", - "sgs": [ - "sg-642cf701" - ], - "privateIp": "10.2.2.48", - "publicIp": null - }, - { - "id": "eni-0080f66b73a68d1d1", - "subnet": "subnet-d137fd88", - "sgs": [ - "sg-b45a2bd1" - ], - "privateIp": "10.4.0.117", - "publicIp": "52.8.219.246" - }, - { - "id": "eni-02075fc7f6b5ed6f3", - "subnet": "subnet-260ee27f", - "sgs": [ - "sg-06348763" - ], - "privateIp": "10.3.0.211", - "publicIp": "13.57.152.11" - }, - { - "id": "eni-026ab4825bc4dfb8b", - "subnet": "subnet-260ee27f", - "sgs": [ - "sg-06348763" - ], - "privateIp": "10.3.0.154", - "publicIp": null - }, - { - "id": "eni-0ac39f75ad7dc0709", - "subnet": "subnet-0cb2aa7457413f5fe", - "sgs": [ - "sg-076d2ea1df0054074" - ], - "privateIp": "10.10.3.88", - "publicIp": "52.52.1.145" - }, - { - "id": "eni-0015cacdc10d467e8", - "subnet": "subnet-005bfd58e719e031f", - "sgs": [ - "sg-09621eafa81d9554d" - ], - "privateIp": "10.4.11.198", - "publicIp": null - }, - { - "id": "eni-039a605986c15dabf", - "subnet": "subnet-005bfd58e719e031f", - "sgs": [ - "sg-b45a2bd1" - ], - "privateIp": "10.4.11.166", - "publicIp": null - }, - { - "id": "eni-01f9242eb64928de8", - "subnet": "subnet-005bfd58e719e031f", - "sgs": [ - "sg-09621eafa81d9554d" - ], - "privateIp": "10.4.11.139", - "publicIp": null - }, - { - "id": "eni-09a54855abf31a012", - "subnet": "subnet-005bfd58e719e031f", - "sgs": [ - "sg-b45a2bd1" - ], - "privateIp": "10.4.11.69", - "publicIp": null - }, - { - "id": "eni-0787462fd9a1d1b6d", - "subnet": "subnet-ebc4188e", - "sgs": [ - "sg-da75adbf" - ], - "privateIp": "10.2.1.156", - "publicIp": "54.241.122.239" - } - ], - "ec2": [ - { - "id": "i-0dc281f8d162602c8", - "name": "efw.web.06b public-site", - "type": "r5.xlarge", - "privateIp": "10.3.0.211", - "publicIp": "13.57.152.11", - "sgs": [ - "sg-06348763" - ], - "subnet": "subnet-260ee27f" - }, - { - "id": "i-0997a73b08f6e5862", - "name": "efw.web.03b logon", - "type": "t3.medium", - "privateIp": "10.2.2.18", - "publicIp": "54.153.101.192", - "sgs": [ - "sg-642cf701" - ], - "subnet": "subnet-16594550" - }, - { - "id": "i-0c8100e3460fa8fd0", - "name": "vpn-default-vpc-02-001", - "type": "t4g.nano", - "privateIp": "10.3.0.112", - "publicIp": "13.52.49.251", - "sgs": [ - "sg-06348763" - ], - "subnet": "subnet-260ee27f" - }, - { - "id": "i-041021cd89e15282c", - "name": "vpn-vpc-01", - "type": "t4g.nano", - "privateIp": "10.2.1.156", - "publicIp": "54.241.122.239", - "sgs": [ - "sg-da75adbf" - ], - "subnet": "subnet-ebc4188e" - }, - { - "id": "i-073b97cbda2b200c3", - "name": "vault.staging.05", - "type": "t3a.medium", - "privateIp": "10.4.0.117", - "publicIp": "52.8.219.246", - "sgs": [ - "sg-b45a2bd1" - ], - "subnet": "subnet-d137fd88" - }, - { - "id": "i-0669f35ab2d0fc444", - "name": "vault.production.02", - "type": "t3a.medium", - "privateIp": "10.4.0.197", - "publicIp": "52.8.75.57", - "sgs": [ - "sg-b45a2bd1" - ], - "subnet": "subnet-d137fd88" - }, - { - "id": "i-01b3f3cd57976bdf3", - "name": "efw-vpn-default-vault-vpn-01", - "type": "t4g.nano", - "privateIp": "10.4.0.221", - "publicIp": "52.53.117.111", - "sgs": [ - "sg-b45a2bd1" - ], - "subnet": "subnet-d137fd88" - }, - { - "id": "i-0272763b46610ac1b", - "name": "efw.web.04d edit-site", - "type": "m7i.xlarge", - "privateIp": "10.3.0.122", - "publicIp": "52.8.85.37", - "sgs": [ - "sg-06348763" - ], - "subnet": "subnet-260ee27f" - }, - { - "id": "i-0c82adf476c7c5e32", - "name": "efw.web.06d public-site", - "type": "m7i.xlarge", - "privateIp": "10.3.0.63", - "publicIp": "52.8.7.0", - "sgs": [ - "sg-06348763" - ], - "subnet": "subnet-260ee27f" - }, - { - "id": "i-0636fd0b033c9b32a", - "name": "efw.acmetest", - "type": "t3.medium", - "privateIp": "10.3.0.73", - "publicIp": null, - "sgs": [ - "sg-06348763" - ], - "subnet": "subnet-260ee27f" - }, - { - "id": "i-09241599c2590b66a", - "name": "efw.acmetest2.linux", - "type": "t3.micro", - "privateIp": "10.3.0.167", - "publicIp": null, - "sgs": [ - "sg-06348763" - ], - "subnet": "subnet-260ee27f" - }, - { - "id": "i-0d7f643cb9d960645", - "name": "efw.vpn10.acmetest", - "type": "t4g.nano", - "privateIp": "10.10.1.166", - "publicIp": "52.53.243.75", - "sgs": [ - "sg-0a872ac3a6d9132a6" - ], - "subnet": "subnet-051f6d705e415834d" - }, - { - "id": "i-082b27477bbe6d8b5", - "name": "efw.acmetest3.linux", - "type": "t3.micro", - "privateIp": "10.10.2.106", - "publicIp": null, - "sgs": [ - "sg-04167d2e18ba15e45", - "sg-0a872ac3a6d9132a6" - ], - "subnet": "subnet-035f81142068bf961" - } - ], - "lbs": [ - { - "id": "NodeAppALB", - "scheme": "internet-facing", - "type": "application", - "subnets": [ - "subnet-051f6d705e415834d", - "subnet-0cb2aa7457413f5fe" - ], - "securityGroups": [ - "sg-076d2ea1df0054074" - ], - "listeners": [ - { - "proto": "HTTP", - "port": 80 - }, - { - "proto": "HTTPS", - "port": 443 - } - ], - "targetGroups": [ - { - "port": 8080, - "targets": [ - "i-082b27477bbe6d8b5" - ] - } - ] - } - ], - "rds": [ - { - "id": "f8-db-01", - "engine": "sqlserver-web", - "port": 0, - "publiclyAccessible": false, - "sgs": [ - "sg-06348763" - ], - "subnetGroup": [ - "subnet-e98e088c", - "subnet-f73afeae" - ] - }, - { - "id": "logon-db-02", - "engine": "sqlserver-web", - "port": 0, - "publiclyAccessible": false, - "sgs": [ - "sg-4235ee27" - ], - "subnetGroup": [ - "subnet-16594550", - "subnet-ebc4188e" - ] - }, - { - "id": "vault-db-production-v2", - "engine": "aurora-mysql", - "port": 0, - "publiclyAccessible": false, - "sgs": [ - "sg-09621eafa81d9554d" - ], - "subnetGroup": [ - "subnet-005bfd58e719e031f", - "subnet-05b5dcdc91a8d3da2" - ] - }, - { - "id": "vault-db-staging-v2", - "engine": "aurora-mysql", - "port": 0, - "publiclyAccessible": false, - "sgs": [ - "sg-09621eafa81d9554d" - ], - "subnetGroup": [ - "subnet-005bfd58e719e031f", - "subnet-05b5dcdc91a8d3da2" - ] - } - ], - "exposures": [ - { - "surface": "NodeAppALB:80", - "world_open": true, - "via": "APPLICATION", - "to": [ - "i-082b27477bbe6d8b5:8080" - ] - }, - { - "surface": "NodeAppALB:443", - "world_open": true, - "via": "APPLICATION", - "to": [ - "i-082b27477bbe6d8b5:8080" - ] - } - ] - } - } +{ + "accounts": [ + { + "id": "acct-shared", + "label": "Shared Services", + "color": "#7c3aed" + }, + { + "id": "acct-prod", + "label": "Production Apps", + "color": "#0ea5e9" + } + ], + "regions": { + "us-west-1": { + "vpcs": [ + { + "id": "vpc-87832de2", + "cidr": "10.4.0.0/16", + "name": "vault.vpc.01", + "accountId": "acct-shared" + }, + { + "id": "vpc-c84eabad", + "cidr": "172.31.0.0/16", + "name": "vpc-c84eabad", + "accountId": "acct-prod" + }, + { + "id": "vpc-331ad056", + "cidr": "10.3.0.0/16", + "name": "efw.vpc.02", + "accountId": "acct-prod" + }, + { + "id": "vpc-afe722ca", + "cidr": "10.2.0.0/16", + "name": "efw.vpc.01", + "accountId": "acct-prod" + }, + { + "id": "vpc-03f799f47b766798c", + "cidr": "10.10.0.0/16", + "name": "ALB-VPC", + "accountId": "acct-shared" + } + ], + "subnets": [ + { + "id": "subnet-260ee27f", + "vpc": "vpc-331ad056", + "cidr": "10.3.0.0/24", + "az": "us-west-1b", + "public": false, + "accountId": "acct-prod" + }, + { + "id": "subnet-f73afeae", + "vpc": "vpc-331ad056", + "cidr": "10.3.1.0/24", + "az": "us-west-1b", + "public": false, + "accountId": "acct-prod" + }, + { + "id": "subnet-ebc4188e", + "vpc": "vpc-afe722ca", + "cidr": "10.2.1.0/24", + "az": "us-west-1c", + "public": false, + "accountId": "acct-prod" + }, + { + "id": "subnet-005bfd58e719e031f", + "vpc": "vpc-87832de2", + "cidr": "10.4.11.0/24", + "az": "us-west-1c", + "public": false, + "accountId": "acct-shared" + }, + { + "id": "subnet-035f81142068bf961", + "vpc": "vpc-03f799f47b766798c", + "cidr": "10.10.2.0/24", + "az": "us-west-1b", + "public": false, + "accountId": "acct-shared" + }, + { + "id": "subnet-d137fd88", + "vpc": "vpc-87832de2", + "cidr": "10.4.0.0/24", + "az": "us-west-1b", + "public": false, + "accountId": "acct-shared" + }, + { + "id": "subnet-e98e088c", + "vpc": "vpc-331ad056", + "cidr": "10.3.2.0/24", + "az": "us-west-1c", + "public": false, + "accountId": "acct-prod" + }, + { + "id": "subnet-08e40dcdc103438b8", + "vpc": "vpc-87832de2", + "cidr": "10.4.2.0/24", + "az": "us-west-1c", + "public": false, + "accountId": "acct-shared" + }, + { + "id": "subnet-0cb2aa7457413f5fe", + "vpc": "vpc-03f799f47b766798c", + "cidr": "10.10.3.0/24", + "az": "us-west-1c", + "public": true, + "accountId": "acct-shared" + }, + { + "id": "subnet-247a9341", + "vpc": "vpc-c84eabad", + "cidr": "172.31.16.0/20", + "az": "us-west-1c", + "public": true, + "accountId": "acct-prod" + }, + { + "id": "subnet-34173f72", + "vpc": "vpc-c84eabad", + "cidr": "172.31.0.0/20", + "az": "us-west-1b", + "public": true, + "accountId": "acct-prod" + }, + { + "id": "subnet-05b5dcdc91a8d3da2", + "vpc": "vpc-87832de2", + "cidr": "10.4.10.0/24", + "az": "us-west-1b", + "public": false, + "accountId": "acct-shared" + }, + { + "id": "subnet-16594550", + "vpc": "vpc-afe722ca", + "cidr": "10.2.2.0/24", + "az": "us-west-1b", + "public": false, + "accountId": "acct-prod" + }, + { + "id": "subnet-051f6d705e415834d", + "vpc": "vpc-03f799f47b766798c", + "cidr": "10.10.1.0/24", + "az": "us-west-1b", + "public": true, + "accountId": "acct-shared" + } + ], + "sgs": [ + { + "id": "sg-642cf701", + "name": "efw.vpc.01-securitygroup-web01", + "rules_in": [ + "tcp 80 from 0.0.0.0/0", + "-1 None from sg-da75adbf", + "icmp 0--1 from 0.0.0.0/0", + "tcp 12489 from 64.71.160.96/27", + "tcp 5666 from 64.71.160.96/27", + "tcp 3389 from 76.126.204.87/32", + "tcp 3389 from 64.71.160.98/32", + "tcp 3389 from 50.156.113.43/32", + "tcp 3389 from 162.222.31.254/32", + "tcp 3389 from 173.164.212.89/32", + "tcp 3389 from 174.85.92.60/32", + "tcp 443 from 0.0.0.0/0", + "tcp 8172 from 173.10.69.6/32", + "tcp 8172 from 173.164.212.89/32", + "icmp 8--1 from 0.0.0.0/0" + ], + "rules_out": [ + "-1 None from 0.0.0.0/0" + ], + "vpc": "vpc-afe722ca", + "accountId": "acct-prod" + }, + { + "id": "sg-00600deefd8e47cd0", + "name": "efw.vpc.02-securitygroup-rds", + "rules_in": [ + "tcp 3306 from 173.164.212.89/32" + ], + "rules_out": [ + "-1 None from 0.0.0.0/0" + ], + "accountId": "acct-shared" + }, + { + "id": "sg-da75adbf", + "name": "default", + "rules_in": [ + "-1 None from sg-da75adbf", + "tcp 22 from 0.0.0.0/0", + "tcp 22 from sg-4235ee27", + "udp 11094 from 0.0.0.0/0", + "tcp 3389 from sg-4235ee27", + "icmp -1 from sg-4235ee27" + ], + "rules_out": [ + "-1 None from 0.0.0.0/0" + ], + "vpc": "vpc-afe722ca", + "accountId": "acct-prod" + }, + { + "id": "sg-c05a2ba5", + "name": "default", + "rules_in": [ + "-1 None from sg-c05a2ba5" + ], + "rules_out": [ + "-1 None from 0.0.0.0/0" + ], + "accountId": "acct-shared" + }, + { + "id": "sg-0c00315bbb744b876", + "name": "default", + "rules_in": [ + "-1 None from sg-0c00315bbb744b876" + ], + "rules_out": [ + "-1 None from 0.0.0.0/0" + ], + "accountId": "acct-shared" + }, + { + "id": "sg-495ab32c", + "name": "default", + "rules_in": [ + "-1 None from sg-495ab32c", + "tcp 3306 from 54.85.48.0/24", + "tcp 3306 from 173.164.212.89/32" + ], + "rules_out": [ + "-1 None from 0.0.0.0/0" + ], + "accountId": "acct-shared" + }, + { + "id": "sg-0f2465c4421c2d5c2", + "name": "x-to-pdf-AppSG-4DM5CX7D35LE", + "rules_in": [ + "-1 None from sg-0f2465c4421c2d5c2", + "tcp 1-65000 from sg-b45a2bd1" + ], + "rules_out": [ + "-1 None from 0.0.0.0/0" + ], + "accountId": "acct-shared" + }, + { + "id": "sg-8b746aec", + "name": "launch-wizard-1", + "rules_in": [ + "tcp 80 from 47.208.245.238/32", + "tcp 22 from 47.208.245.238/32", + "tcp 22 from 64.71.160.98/32", + "tcp 443 from 47.208.245.238/32", + "icmp 8--1 from 47.208.245.238/32" + ], + "rules_out": [ + "-1 None from 0.0.0.0/0" + ], + "accountId": "acct-shared" + }, + { + "id": "sg-0a872ac3a6d9132a6", + "name": "node-app-alb-stack-AppAccessSG-DLeS5dz4pWwk", + "rules_in": [ + "tcp 22 from 0.0.0.0/0", + "tcp 11094 from 0.0.0.0/0", + "udp 11094 from 0.0.0.0/0" + ], + "rules_out": [ + "-1 None from 0.0.0.0/0" + ], + "vpc": "vpc-03f799f47b766798c", + "accountId": "acct-shared" + }, + { + "id": "sg-076d2ea1df0054074", + "name": "node-app-alb-stack-LoadBalancerSG-LgFQ2PFaob27", + "rules_in": [ + "tcp 80 from 0.0.0.0/0", + "tcp 443 from 0.0.0.0/0" + ], + "rules_out": [ + "-1 None from 0.0.0.0/0" + ], + "vpc": "vpc-03f799f47b766798c", + "accountId": "acct-shared" + }, + { + "id": "sg-b45a2bd1", + "name": "vault.vpc.01-securitygroup", + "rules_in": [ + "tcp 80 from 0.0.0.0/0", + "tcp 8080 from 76.246.46.113/32", + "icmp 0--1 from 0.0.0.0/0", + "icmp 0--1 from ::/0", + "tcp 22 from 73.90.210.219/32", + "tcp 22 from 73.90.209.115/32", + "tcp 22 from 47.208.245.238/32", + "tcp 22 from 73.90.211.68/32", + "tcp 22 from 166.170.37.145/32", + "tcp 22 from 135.26.148.110/32", + "tcp 22 from 108.82.46.156/32", + "tcp 22 from 47.208.247.13/32", + "tcp 22 from 98.150.190.32/32", + "tcp 22 from 64.71.160.0/24", + "tcp 22 from 76.126.204.87/32", + "tcp 22 from 13.52.6.112/29", + "tcp 22 from 174.85.92.60/32", + "tcp 22 from 45.28.138.65/32", + "tcp 5666 from 64.71.160.96/27", + "udp 11094 from 0.0.0.0/0", + "tcp 443 from 0.0.0.0/0", + "icmp 8--1 from 0.0.0.0/0" + ], + "rules_out": [ + "-1 None from 0.0.0.0/0" + ], + "vpc": "vpc-87832de2", + "accountId": "acct-shared" + }, + { + "id": "sg-4235ee27", + "name": "efw.vpc.01-securitygroup-db01", + "rules_in": [ + "tcp 1433 from 10.2.2.0/24", + "-1 None from sg-da75adbf" + ], + "rules_out": [ + "-1 None from 0.0.0.0/0" + ], + "vpc": "vpc-afe722ca", + "accountId": "acct-prod" + }, + { + "id": "sg-04167d2e18ba15e45", + "name": "node-app-alb-stack-AppSG-tYWl4C0wtvl6", + "rules_in": [ + "tcp 8080 from sg-076d2ea1df0054074" + ], + "rules_out": [ + "-1 None from 0.0.0.0/0" + ], + "vpc": "vpc-03f799f47b766798c", + "accountId": "acct-shared" + }, + { + "id": "sg-06348763", + "name": "default", + "rules_in": [ + "tcp 1433 from 173.164.212.89/32", + "tcp 1433 from 72.173.157.190/32", + "tcp 1433 from 75.101.48.86/32", + "tcp 1433 from 107.3.172.143/32", + "tcp 1433 from 10.3.0.0/16", + "tcp 80 from 0.0.0.0/0", + "tcp 5432 from 10.3.0.157/32", + "tcp 5432 from 67.139.78.162/32", + "tcp 5432 from 209.210.190.204/32", + "tcp 5432 from 10.3.0.232/32", + "tcp 5432 from 10.3.0.247/32", + "tcp 5432 from sg-08fb4b412f90d5913", + "tcp 4021 from 173.164.212.89/32", + "tcp 5666 from 64.71.160.121/32", + "tcp 4020 from 173.164.212.89/32", + "tcp 3389 from 76.126.204.87/32", + "tcp 3389 from 64.71.160.98/32", + "tcp 3389 from 173.164.212.89/32", + "tcp 3389 from 72.173.157.190/32", + "tcp 3389 from 10.3.0.0/16", + "tcp 445 from 10.3.0.0/16", + "tcp 443 from 0.0.0.0/0", + "tcp 4026 from 173.164.212.89/32", + "tcp 4026 from 10.3.0.0/16", + "tcp 8172 from 173.164.212.89/32", + "tcp 8172 from 10.3.0.0/16", + "icmp 0--1 from 0.0.0.0/0", + "icmp 0--1 from 173.164.212.89/32", + "tcp 22 from 0.0.0.0/0", + "udp 1194 from 0.0.0.0/0", + "tcp 4024 from 173.164.212.89/32", + "tcp 1194 from 0.0.0.0/0", + "tcp 12489 from 64.71.160.121/32", + "tcp 4027 from 10.3.0.0/16", + "udp 11094 from 0.0.0.0/0", + "icmp 8--1 from 0.0.0.0/0" + ], + "rules_out": [ + "-1 None from 0.0.0.0/0" + ], + "vpc": "vpc-331ad056", + "accountId": "acct-prod" + }, + { + "id": "sg-08fb4b412f90d5913", + "name": "eco.lambda.securitygroup", + "rules_in": [], + "rules_out": [ + "-1 None from 0.0.0.0/0" + ], + "accountId": "acct-prod" + }, + { + "id": "sg-09621eafa81d9554d", + "name": "vault.vpc.01.securitygroup-rds-pvt", + "rules_in": [ + "tcp 3306 from 173.164.212.89/32", + "tcp 3306 from sg-b45a2bd1" + ], + "rules_out": [ + "-1 None from 0.0.0.0/0" + ], + "vpc": "vpc-87832de2", + "accountId": "acct-shared" + } + ], + "enis": [ + { + "id": "eni-03cb7e3c6efba4fe6", + "subnet": "subnet-260ee27f", + "sgs": [ + "sg-06348763" + ], + "privateIp": "10.3.0.216", + "publicIp": "52.8.79.80", + "vpc": "vpc-331ad056", + "accountId": "acct-prod" + }, + { + "id": "eni-0c6e3761c14140e52", + "subnet": "subnet-051f6d705e415834d", + "sgs": [ + "sg-076d2ea1df0054074" + ], + "privateIp": "10.10.1.212", + "publicIp": "50.18.175.227", + "vpc": "vpc-03f799f47b766798c", + "accountId": "acct-shared" + }, + { + "id": "eni-6a099b32", + "subnet": "subnet-260ee27f", + "sgs": [ + "sg-06348763" + ], + "privateIp": "10.3.0.207", + "publicIp": null, + "vpc": "vpc-331ad056", + "accountId": "acct-prod" + }, + { + "id": "eni-072ff2545f56240a7", + "subnet": "subnet-16594550", + "sgs": [ + "sg-4235ee27" + ], + "privateIp": "10.2.2.16", + "publicIp": null, + "vpc": "vpc-afe722ca", + "accountId": "acct-prod" + }, + { + "id": "eni-064252b93ca105b7c", + "subnet": "subnet-05b5dcdc91a8d3da2", + "sgs": [ + "sg-b45a2bd1" + ], + "privateIp": "10.4.10.82", + "publicIp": null, + "vpc": "vpc-87832de2", + "accountId": "acct-shared" + }, + { + "id": "eni-08d57de7981ae0020", + "subnet": "subnet-035f81142068bf961", + "sgs": [ + "sg-04167d2e18ba15e45", + "sg-0a872ac3a6d9132a6" + ], + "privateIp": "10.10.2.106", + "publicIp": null, + "vpc": "vpc-03f799f47b766798c", + "accountId": "acct-shared" + }, + { + "id": "eni-00feca9ca48c7ae0c", + "subnet": "subnet-05b5dcdc91a8d3da2", + "sgs": [ + "sg-b45a2bd1" + ], + "privateIp": "10.4.10.141", + "publicIp": null, + "vpc": "vpc-87832de2", + "accountId": "acct-shared" + }, + { + "id": "eni-8041e3da", + "subnet": "subnet-260ee27f", + "sgs": [ + "sg-06348763" + ], + "privateIp": "10.3.0.201", + "publicIp": null, + "vpc": "vpc-331ad056", + "accountId": "acct-prod" + }, + { + "id": "eni-9d73dbc7", + "subnet": "subnet-260ee27f", + "sgs": [ + "sg-06348763" + ], + "privateIp": "10.3.0.98", + "publicIp": null, + "vpc": "vpc-331ad056", + "accountId": "acct-prod" + }, + { + "id": "eni-04237833786a67013", + "subnet": "subnet-051f6d705e415834d", + "sgs": [ + "sg-0a872ac3a6d9132a6" + ], + "privateIp": "10.10.1.166", + "publicIp": "52.53.243.75", + "vpc": "vpc-03f799f47b766798c", + "accountId": "acct-shared" + }, + { + "id": "eni-084002309358bb545", + "subnet": "subnet-f73afeae", + "sgs": [ + "sg-06348763" + ], + "privateIp": "10.3.1.134", + "publicIp": null, + "vpc": "vpc-331ad056", + "accountId": "acct-prod" + }, + { + "id": "eni-0827085d571dccab7", + "subnet": "subnet-d137fd88", + "sgs": [ + "sg-b45a2bd1" + ], + "privateIp": "10.4.0.221", + "publicIp": "52.53.117.111", + "vpc": "vpc-87832de2", + "accountId": "acct-shared" + }, + { + "id": "eni-0e844b9d718f3daa0", + "subnet": "subnet-16594550", + "sgs": [ + "sg-642cf701" + ], + "privateIp": "10.2.2.226", + "publicIp": "52.8.26.159", + "vpc": "vpc-afe722ca", + "accountId": "acct-prod" + }, + { + "id": "eni-0d6f412450d0e082b", + "subnet": "subnet-260ee27f", + "sgs": [ + "sg-06348763" + ], + "privateIp": "10.3.0.63", + "publicIp": "52.8.7.0", + "vpc": "vpc-331ad056", + "accountId": "acct-prod" + }, + { + "id": "eni-05788a45421ce580f", + "subnet": "subnet-d137fd88", + "sgs": [ + "sg-b45a2bd1" + ], + "privateIp": "10.4.0.197", + "publicIp": "52.8.75.57", + "vpc": "vpc-87832de2", + "accountId": "acct-shared" + }, + { + "id": "eni-0775830b9669fa479", + "subnet": "subnet-16594550", + "sgs": [ + "sg-642cf701" + ], + "privateIp": "10.2.2.18", + "publicIp": "54.153.101.192", + "vpc": "vpc-afe722ca", + "accountId": "acct-prod" + }, + { + "id": "eni-0f54a2ee3a5237ae1", + "subnet": "subnet-260ee27f", + "sgs": [ + "sg-06348763" + ], + "privateIp": "10.3.0.111", + "publicIp": "54.153.3.41", + "vpc": "vpc-331ad056", + "accountId": "acct-prod" + }, + { + "id": "eni-08eb3a38264ccd212", + "subnet": "subnet-260ee27f", + "sgs": [ + "sg-06348763" + ], + "privateIp": "10.3.0.73", + "publicIp": null, + "vpc": "vpc-331ad056", + "accountId": "acct-prod" + }, + { + "id": "eni-0afbe7eb22dd6e8e3", + "subnet": "subnet-260ee27f", + "sgs": [ + "sg-06348763" + ], + "privateIp": "10.3.0.112", + "publicIp": "13.52.49.251", + "vpc": "vpc-331ad056", + "accountId": "acct-prod" + }, + { + "id": "eni-018923614c623ef74", + "subnet": "subnet-260ee27f", + "sgs": [ + "sg-06348763" + ], + "privateIp": "10.3.0.122", + "publicIp": "52.8.85.37", + "vpc": "vpc-331ad056", + "accountId": "acct-prod" + }, + { + "id": "eni-0f310dd2e36654ed7", + "subnet": "subnet-260ee27f", + "sgs": [ + "sg-06348763" + ], + "privateIp": "10.3.0.120", + "publicIp": null, + "vpc": "vpc-331ad056", + "accountId": "acct-prod" + }, + { + "id": "eni-00172626263229e1a", + "subnet": "subnet-051f6d705e415834d", + "sgs": [], + "privateIp": "10.10.1.37", + "publicIp": "13.57.111.5", + "vpc": "vpc-03f799f47b766798c", + "accountId": "acct-shared" + }, + { + "id": "eni-0893189c99a73d4f2", + "subnet": "subnet-260ee27f", + "sgs": [ + "sg-06348763" + ], + "privateIp": "10.3.0.167", + "publicIp": null, + "vpc": "vpc-331ad056", + "accountId": "acct-prod" + }, + { + "id": "eni-0d0b9801f1e66ec76", + "subnet": "subnet-d137fd88", + "sgs": [], + "privateIp": "10.4.0.246", + "publicIp": "184.169.224.203", + "vpc": "vpc-87832de2", + "accountId": "acct-shared" + }, + { + "id": "eni-b574dcef", + "subnet": "subnet-16594550", + "sgs": [ + "sg-642cf701" + ], + "privateIp": "10.2.2.48", + "publicIp": null, + "vpc": "vpc-afe722ca", + "accountId": "acct-prod" + }, + { + "id": "eni-0080f66b73a68d1d1", + "subnet": "subnet-d137fd88", + "sgs": [ + "sg-b45a2bd1" + ], + "privateIp": "10.4.0.117", + "publicIp": "52.8.219.246", + "vpc": "vpc-87832de2", + "accountId": "acct-shared" + }, + { + "id": "eni-02075fc7f6b5ed6f3", + "subnet": "subnet-260ee27f", + "sgs": [ + "sg-06348763" + ], + "privateIp": "10.3.0.211", + "publicIp": "13.57.152.11", + "vpc": "vpc-331ad056", + "accountId": "acct-prod" + }, + { + "id": "eni-026ab4825bc4dfb8b", + "subnet": "subnet-260ee27f", + "sgs": [ + "sg-06348763" + ], + "privateIp": "10.3.0.154", + "publicIp": null, + "vpc": "vpc-331ad056", + "accountId": "acct-prod" + }, + { + "id": "eni-0ac39f75ad7dc0709", + "subnet": "subnet-0cb2aa7457413f5fe", + "sgs": [ + "sg-076d2ea1df0054074" + ], + "privateIp": "10.10.3.88", + "publicIp": "52.52.1.145", + "vpc": "vpc-03f799f47b766798c", + "accountId": "acct-shared" + }, + { + "id": "eni-0015cacdc10d467e8", + "subnet": "subnet-005bfd58e719e031f", + "sgs": [ + "sg-09621eafa81d9554d" + ], + "privateIp": "10.4.11.198", + "publicIp": null, + "vpc": "vpc-87832de2", + "accountId": "acct-shared" + }, + { + "id": "eni-039a605986c15dabf", + "subnet": "subnet-005bfd58e719e031f", + "sgs": [ + "sg-b45a2bd1" + ], + "privateIp": "10.4.11.166", + "publicIp": null, + "vpc": "vpc-87832de2", + "accountId": "acct-shared" + }, + { + "id": "eni-01f9242eb64928de8", + "subnet": "subnet-005bfd58e719e031f", + "sgs": [ + "sg-09621eafa81d9554d" + ], + "privateIp": "10.4.11.139", + "publicIp": null, + "vpc": "vpc-87832de2", + "accountId": "acct-shared" + }, + { + "id": "eni-09a54855abf31a012", + "subnet": "subnet-005bfd58e719e031f", + "sgs": [ + "sg-b45a2bd1" + ], + "privateIp": "10.4.11.69", + "publicIp": null, + "vpc": "vpc-87832de2", + "accountId": "acct-shared" + }, + { + "id": "eni-0787462fd9a1d1b6d", + "subnet": "subnet-ebc4188e", + "sgs": [ + "sg-da75adbf" + ], + "privateIp": "10.2.1.156", + "publicIp": "54.241.122.239", + "vpc": "vpc-afe722ca", + "accountId": "acct-prod" + } + ], + "ec2": [ + { + "id": "i-0dc281f8d162602c8", + "name": "efw.web.06b public-site", + "type": "r5.xlarge", + "privateIp": "10.3.0.211", + "publicIp": "13.57.152.11", + "sgs": [ + "sg-06348763" + ], + "subnet": "subnet-260ee27f", + "vpc": "vpc-331ad056", + "accountId": "acct-prod" + }, + { + "id": "i-0997a73b08f6e5862", + "name": "efw.web.03b logon", + "type": "t3.medium", + "privateIp": "10.2.2.18", + "publicIp": "54.153.101.192", + "sgs": [ + "sg-642cf701" + ], + "subnet": "subnet-16594550", + "vpc": "vpc-afe722ca", + "accountId": "acct-prod" + }, + { + "id": "i-0c8100e3460fa8fd0", + "name": "vpn-default-vpc-02-001", + "type": "t4g.nano", + "privateIp": "10.3.0.112", + "publicIp": "13.52.49.251", + "sgs": [ + "sg-06348763" + ], + "subnet": "subnet-260ee27f", + "vpc": "vpc-331ad056", + "accountId": "acct-prod" + }, + { + "id": "i-041021cd89e15282c", + "name": "vpn-vpc-01", + "type": "t4g.nano", + "privateIp": "10.2.1.156", + "publicIp": "54.241.122.239", + "sgs": [ + "sg-da75adbf" + ], + "subnet": "subnet-ebc4188e", + "vpc": "vpc-afe722ca", + "accountId": "acct-prod" + }, + { + "id": "i-073b97cbda2b200c3", + "name": "vault.staging.05", + "type": "t3a.medium", + "privateIp": "10.4.0.117", + "publicIp": "52.8.219.246", + "sgs": [ + "sg-b45a2bd1" + ], + "subnet": "subnet-d137fd88", + "vpc": "vpc-87832de2", + "accountId": "acct-shared" + }, + { + "id": "i-0669f35ab2d0fc444", + "name": "vault.production.02", + "type": "t3a.medium", + "privateIp": "10.4.0.197", + "publicIp": "52.8.75.57", + "sgs": [ + "sg-b45a2bd1" + ], + "subnet": "subnet-d137fd88", + "vpc": "vpc-87832de2", + "accountId": "acct-shared" + }, + { + "id": "i-01b3f3cd57976bdf3", + "name": "efw-vpn-default-vault-vpn-01", + "type": "t4g.nano", + "privateIp": "10.4.0.221", + "publicIp": "52.53.117.111", + "sgs": [ + "sg-b45a2bd1" + ], + "subnet": "subnet-d137fd88", + "vpc": "vpc-87832de2", + "accountId": "acct-shared" + }, + { + "id": "i-0272763b46610ac1b", + "name": "efw.web.04d edit-site", + "type": "m7i.xlarge", + "privateIp": "10.3.0.122", + "publicIp": "52.8.85.37", + "sgs": [ + "sg-06348763" + ], + "subnet": "subnet-260ee27f", + "vpc": "vpc-331ad056", + "accountId": "acct-prod" + }, + { + "id": "i-0c82adf476c7c5e32", + "name": "efw.web.06d public-site", + "type": "m7i.xlarge", + "privateIp": "10.3.0.63", + "publicIp": "52.8.7.0", + "sgs": [ + "sg-06348763" + ], + "subnet": "subnet-260ee27f", + "vpc": "vpc-331ad056", + "accountId": "acct-prod" + }, + { + "id": "i-0636fd0b033c9b32a", + "name": "efw.acmetest", + "type": "t3.medium", + "privateIp": "10.3.0.73", + "publicIp": null, + "sgs": [ + "sg-06348763" + ], + "subnet": "subnet-260ee27f", + "vpc": "vpc-331ad056", + "accountId": "acct-prod" + }, + { + "id": "i-09241599c2590b66a", + "name": "efw.acmetest2.linux", + "type": "t3.micro", + "privateIp": "10.3.0.167", + "publicIp": null, + "sgs": [ + "sg-06348763" + ], + "subnet": "subnet-260ee27f", + "vpc": "vpc-331ad056", + "accountId": "acct-prod" + }, + { + "id": "i-0d7f643cb9d960645", + "name": "efw.vpn10.acmetest", + "type": "t4g.nano", + "privateIp": "10.10.1.166", + "publicIp": "52.53.243.75", + "sgs": [ + "sg-0a872ac3a6d9132a6" + ], + "subnet": "subnet-051f6d705e415834d", + "vpc": "vpc-03f799f47b766798c", + "accountId": "acct-shared" + }, + { + "id": "i-082b27477bbe6d8b5", + "name": "efw.acmetest3.linux", + "type": "t3.micro", + "privateIp": "10.10.2.106", + "publicIp": null, + "sgs": [ + "sg-04167d2e18ba15e45", + "sg-0a872ac3a6d9132a6" + ], + "subnet": "subnet-035f81142068bf961", + "vpc": "vpc-03f799f47b766798c", + "accountId": "acct-shared" + } + ], + "lbs": [ + { + "id": "NodeAppALB", + "scheme": "internet-facing", + "type": "application", + "subnets": [ + "subnet-051f6d705e415834d", + "subnet-0cb2aa7457413f5fe" + ], + "securityGroups": [ + "sg-076d2ea1df0054074" + ], + "listeners": [ + { + "proto": "HTTP", + "port": 80 + }, + { + "proto": "HTTPS", + "port": 443 + } + ], + "targetGroups": [ + { + "port": 8080, + "targets": [ + "i-082b27477bbe6d8b5" + ] + } + ], + "accountId": "acct-shared" + } + ], + "rds": [ + { + "id": "f8-db-01", + "engine": "sqlserver-web", + "port": 0, + "publiclyAccessible": false, + "sgs": [ + "sg-06348763" + ], + "subnetGroup": [ + "subnet-e98e088c", + "subnet-f73afeae" + ], + "accountId": "acct-prod" + }, + { + "id": "logon-db-02", + "engine": "sqlserver-web", + "port": 0, + "publiclyAccessible": false, + "sgs": [ + "sg-4235ee27" + ], + "subnetGroup": [ + "subnet-16594550", + "subnet-ebc4188e" + ], + "accountId": "acct-prod" + }, + { + "id": "vault-db-production-v2", + "engine": "aurora-mysql", + "port": 0, + "publiclyAccessible": false, + "sgs": [ + "sg-09621eafa81d9554d" + ], + "subnetGroup": [ + "subnet-005bfd58e719e031f", + "subnet-05b5dcdc91a8d3da2" + ], + "accountId": "acct-shared" + }, + { + "id": "vault-db-staging-v2", + "engine": "aurora-mysql", + "port": 0, + "publiclyAccessible": false, + "sgs": [ + "sg-09621eafa81d9554d" + ], + "subnetGroup": [ + "subnet-005bfd58e719e031f", + "subnet-05b5dcdc91a8d3da2" + ], + "accountId": "acct-shared" + } + ], + "exposures": [ + { + "surface": "NodeAppALB:80", + "world_open": true, + "via": "APPLICATION", + "to": [ + "i-082b27477bbe6d8b5:8080" + ], + "accountId": "acct-shared", + "region": "us-west-1" + }, + { + "surface": "NodeAppALB:443", + "world_open": true, + "via": "APPLICATION", + "to": [ + "i-082b27477bbe6d8b5:8080" + ], + "accountId": "acct-shared", + "region": "us-west-1" + } + ] + } + } } \ No newline at end of file diff --git a/layout.json b/layout.json index 7da99b0..709490e 100755 --- a/layout.json +++ b/layout.json @@ -1,161 +1,177 @@ { "nodes": { + "account:acct-shared": { + "position": { + "x": 2383.6718307806645, + "y": 1142.0623550975815 + }, + "lx": 0, + "ly": 0 + }, + "account:acct-prod": { + "position": { + "x": -1257.3436368163789, + "y": 1751.2282249012555 + }, + "lx": 0, + "ly": 0 + }, "vpc-87832de2": { "position": { - "x": 756.8840099911947, - "y": 1038.4416407451458 + "x": 2622.379364533625, + "y": 792.8749925626238 }, "lx": 77.51854351992131, "ly": 139.5230395934425 }, "vpc-c84eabad": { "position": { - "x": -922.864188724591, - "y": 204.9358257138463 + "x": -1422.5355956832366, + "y": 280.0140805664038 }, "lx": 0, "ly": 0 }, "vpc-331ad056": { "position": { - "x": -967.090481563079, - "y": 1291.3678057051704 + "x": -1435.3398750652455, + "y": 1386.2361491698744 }, "lx": -134.22057243218103, "ly": 551.6318031828098 }, "vpc-afe722ca": { "position": { - "x": 593.7116051419532, - "y": 2085.060815603146 + "x": -541.0511214212669, + "y": 3010.339213373424 }, "lx": 0, "ly": 0 }, "vpc-03f799f47b766798c": { "position": { - "x": -326.8836182123258, - "y": 2966.579150844579 + "x": 2417.1718307806645, + "y": 1690.0755318155339 }, "lx": 0, "ly": 0 }, "subnet-260ee27f": { "position": { - "x": -921.340481563079, - "y": 1121.1067694739904 + "x": -1389.5898750652455, + "y": 1215.9751129386946 }, "lx": 0, "ly": 0 }, "subnet-f73afeae": { "position": { - "x": -963.9358574966905, - "y": 1846.410916593678 + "x": -1432.185250998857, + "y": 1941.279260058381 }, "lx": 0, "ly": 0 }, "subnet-ebc4188e": { "position": { - "x": 642.7195008673785, - "y": 1787.9702751209763 + "x": -492.04322569584144, + "y": 2713.2486728912545 }, "lx": 0, "ly": 0 }, "subnet-005bfd58e719e031f": { "position": { - "x": 954.3699608755894, - "y": 767.1904595742493 + "x": 2795.865315418019, + "y": 521.623811391727 }, "lx": 0, "ly": 0 }, "subnet-035f81142068bf961": { "position": { - "x": -727.9701282543923, - "y": 2945.1772029052686 + "x": 2015.8700930454238, + "y": 1673.9235838762236 }, "lx": 0, "ly": 0 }, "subnet-d137fd88": { "position": { - "x": 1035.1966337030872, - "y": 1260.4186551195244 + "x": 2876.691988245517, + "y": 1014.8520069370023 }, "lx": -95.54884268669878, "ly": -183.7839139599664 }, "subnet-e98e088c": { "position": { - "x": -556.0376711165936, - "y": 1846.2285577580044 + "x": -1024.2870646187603, + "y": 1941.0969012227074 }, "lx": 0, "ly": 0 }, "subnet-08e40dcdc103438b8": { "position": { - "x": 549.0070924119668, - "y": 1405.912770994567 + "x": 2390.5024469543973, + "y": 1160.3461228120448 }, "lx": 0, "ly": 0 }, "subnet-0cb2aa7457413f5fe": { "position": { - "x": -806.65058364074, - "y": 3191.268048237053 + "x": 1937.1896376590757, + "y": 1920.0144292080076 }, "lx": 0, "ly": 0 }, "subnet-247a9341": { "position": { - "x": -675.3228356289688, - "y": 122.98852970650637 + "x": -1205.4162560440936, + "y": 178.27669594691727 }, "lx": 0, "ly": 0 }, "subnet-34173f72": { "position": { - "x": -1080.405541820213, - "y": 323.3831217211862 + "x": -1548.6549353223795, + "y": 418.2514651858903 }, "lx": 0, "ly": 0 }, "subnet-05b5dcdc91a8d3da2": { "position": { - "x": 550.3010345611413, - "y": 1208.7638869426428 + "x": 2391.7963891035715, + "y": 963.1972387601206 }, "lx": -56.280967047329966, "ly": 12.354358620145604 }, "subnet-16594550": { "position": { - "x": 638.2037094165278, - "y": 2341.8441019824586 + "x": -496.5590171466923, + "y": 3267.122499752737 }, "lx": 0, "ly": 0 }, "subnet-051f6d705e415834d": { "position": { - "x": 108.34330910685321, - "y": 2965.3802332565056 + "x": 2852.1835304066703, + "y": 1694.1266142274605 }, "lx": 0, "ly": 0 }, "sg-642cf701": { "position": { - "x": 1368.280952213551, - "y": 1732.122796782028 + "x": -128.87428508740095, + "y": 3207.5801320931114 }, "lx": 0, "ly": 0 @@ -170,8 +186,8 @@ }, "sg-da75adbf": { "position": { - "x": 1654.4153990786074, - "y": 1502.4913097934757 + "x": 271.174147224467, + "y": 2826.0633311754773 }, "lx": 0, "ly": 0 @@ -202,224 +218,224 @@ }, "sg-0f2465c4421c2d5c2": { "position": { - "x": 1501.4220287756627, - "y": 1088.2588218739315 + "x": 3737.1319279567347, + "y": 1416.6180986742713 }, "lx": 0, "ly": 0 }, "sg-8b746aec": { "position": { - "x": 11.800399713295008, - "y": 754.3055340378875 + "x": -57.46491042921801, + "y": 798.8332334152173 }, "lx": -46.67202145388339, "ly": 75.49885823422312 }, "sg-0a872ac3a6d9132a6": { "position": { - "x": -273.8173000765115, - "y": 2531.372427285566 + "x": 2449.2004574581915, + "y": 2220.1301602993412 }, "lx": 0, "ly": 0 }, "sg-076d2ea1df0054074": { "position": { - "x": 297.4040219907455, - "y": 2392.000439156539 + "x": 3020.7762653398454, + "y": 2403.6912205594213 }, "lx": 0, "ly": 0 }, "sg-b45a2bd1": { "position": { - "x": 1496.2207074206092, - "y": 700.5423557214449 + "x": 3732.2813094098105, + "y": 823.5446930393971 }, "lx": 0, "ly": 0 }, "sg-4235ee27": { "position": { - "x": 1642.8599868444235, - "y": 2133.250105847895 + "x": 134.85579854853708, + "y": 3695.499049118454 }, "lx": 0, "ly": 0 }, "sg-04167d2e18ba15e45": { "position": { - "x": -660.0058544043945, - "y": 2397.5181639300217 + "x": 2115.6486154236227, + "y": 2405.8871924989144 }, "lx": 0, "ly": 0 }, "sg-06348763": { "position": { - "x": 23.18530161221225, - "y": 976.1080421357864 + "x": -770.8920039501696, + "y": 953.8441924471215 }, "lx": 0, "ly": 0 }, "sg-08fb4b412f90d5913": { "position": { - "x": 57.433554297476746, - "y": 1529.3600510391416 + "x": -729.2224680353501, + "y": 1385.8819086010787 }, "lx": 0, "ly": 0 }, "sg-09621eafa81d9554d": { "position": { - "x": 1492.9199816248513, - "y": 472.53158920519866 + "x": 3699.811020652474, + "y": 413.5355291862605 }, "lx": 0, "ly": 0 }, "i-0dc281f8d162602c8": { "position": { - "x": -1201.9240820025686, - "y": 1170.4054563966229 + "x": -1670.173475504735, + "y": 1265.2737998613272 }, "lx": 0, "ly": 0 }, "i-0997a73b08f6e5862": { "position": { - "x": 696.9537094165278, - "y": 2289.286847879602 + "x": -437.8090171466923, + "y": 3214.5652456498806 }, "lx": 0, "ly": 0 }, "i-0c8100e3460fa8fd0": { "position": { - "x": -530.5097131980381, - "y": 1487.4564852956444 + "x": -998.7591067002047, + "y": 1582.324828760348 }, "lx": 0, "ly": 0 }, "i-041021cd89e15282c": { "position": { - "x": 702.4695008673785, - "y": 1812.2202751209763 + "x": -432.29322569584144, + "y": 2737.4986728912545 }, "lx": 0, "ly": 0 }, "i-073b97cbda2b200c3": { "position": { - "x": 1032.1453149375961, - "y": 1118.630957918435 + "x": 2873.640669480026, + "y": 873.0643097359127 }, "lx": 0, "ly": 0 }, "i-0669f35ab2d0fc444": { "position": { - "x": 1029.7295075033508, - "y": 1292.025634730957 + "x": 2871.2248620457804, + "y": 1046.458986548435 }, "lx": 0, "ly": 0 }, "i-01b3f3cd57976bdf3": { "position": { - "x": 1157.7479524685782, - "y": 1450.706352320614 + "x": 2999.2433070110083, + "y": 1205.139704138092 }, "lx": 0, "ly": 0 }, "i-0272763b46610ac1b": { "position": { - "x": -1204.2644686266099, - "y": 853.4607536515473 + "x": -1672.5138621287765, + "y": 948.3290971162517 }, "lx": 238.46757499625102, "ly": -50.2036999992107 }, "i-0c82adf476c7c5e32": { "position": { - "x": -1193.7978959064258, - "y": 1010.1880963959779 + "x": -1662.0472894085924, + "y": 1105.0564398606823 }, "lx": 0, "ly": 0 }, "i-0636fd0b033c9b32a": { "position": { - "x": -515.2568811235894, - "y": 1298.8022809002794 + "x": -983.5062746257561, + "y": 1393.6706243649835 }, "lx": 0, "ly": 0 }, "i-09241599c2590b66a": { "position": { - "x": -555.6056787872835, - "y": 886.9481918477713 + "x": -1023.8550722894502, + "y": 981.8165353124757 }, "lx": 0, "ly": 0 }, "i-0d7f643cb9d960645": { "position": { - "x": 57.30327099761796, - "y": 2832.8902534521053 + "x": 2801.1434922974354, + "y": 1561.6366344230603 }, "lx": 0, "ly": 0 }, "i-082b27477bbe6d8b5": { "position": { - "x": -666.2201282543923, - "y": 2969.4272029052686 + "x": 2077.620093045424, + "y": 1698.1735838762236 }, "lx": 0, "ly": 0 }, "f8-db-01": { "position": { - "x": -518.2876711165936, - "y": 1864.4785577580044 + "x": -986.5370646187603, + "y": 1959.3469012227074 }, "lx": 0, "ly": 0 }, "logon-db-02": { "position": { - "x": 694.8906262727602, - "y": 2442.9013560853155 + "x": -439.8721002904598, + "y": 3368.179753855594 }, "lx": 0, "ly": 0 }, "vault-db-production-v2": { "position": { - "x": 991.0522677808019, - "y": 699.176929169678 + "x": 2832.5476223232313, + "y": 453.61028098715565 }, "lx": 0, "ly": 0 }, "vault-db-staging-v2": { "position": { - "x": 989.1876539703769, - "y": 871.7039899788206 + "x": 2830.6830085128063, + "y": 626.1373417962984 }, "lx": 0, "ly": 0 }, "NodeAppALB": { "position": { - "x": 282.38334721608845, - "y": 3145.8702130609063 + "x": 3026.2235685159053, + "y": 1874.6165940318608 }, "lx": 0, "ly": 0