Skip to content

Commit ba1d868

Browse files
authored
Fix Bugs and Add more dashboards (#118)
* lint * git-fix * git-fix * git-fix
1 parent a78cb6b commit ba1d868

File tree

9 files changed

+437
-82
lines changed

9 files changed

+437
-82
lines changed

lib/context/resources/AwsEc2Instance.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ def _describe_instance_security_groups(self):
112112
def _describe_instance_autoscaling_group(self):
113113
autoscaling_group = {}
114114
if self.instance:
115-
tags = self.instance.get("Tags")
115+
tags = self.instance.get("Tags", [])
116116
for tag in tags:
117117
if tag.get("Key") == "aws:autoscaling:groupName":
118118
asg_name = tag.get("Value")

lib/context/resources/AwsElbLoadBalancer.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,19 @@ def parse_finding(self, finding, drilled):
3434
self.account = finding["AwsAccountId"]
3535
self.partition = finding["Resources"][0]["Id"].split(":")[1]
3636
self.resource_type = finding["Resources"][0]["Type"]
37-
self.resource_id = (
38-
finding["Resources"][0]["Id"].split("/")[-1]
39-
if not drilled
40-
else drilled.split("/")[-11]
41-
)
37+
if not drilled:
38+
if (
39+
"app" in finding["Resources"][0]["Id"]
40+
or "net" in finding["Resources"][0]["Id"]
41+
):
42+
self.resource_id = finding["Resources"][0]["Id"].split("/")[-2]
43+
else:
44+
self.resource_id = finding["Resources"][0]["Id"].split("/")[-1]
45+
else:
46+
if "app" in drilled or "net" in drilled:
47+
self.resource_id = drilled.split("/")[-2]
48+
else:
49+
self.resource_id = drilled.split("/")[-1]
4250
self.resource_arn = finding["Resources"][0]["Id"] if not drilled else drilled
4351

4452
# Describe function

lib/outputs.py

Lines changed: 73 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -109,21 +109,27 @@ def generate_output_csv(self):
109109
for finding in values["findings"]:
110110
for f, v in finding.items():
111111
tag_column_values = [
112-
values.get("tags", {}).get(column, "")
113-
if values.get("tags")
114-
else ""
112+
(
113+
values.get("tags", {}).get(column, "")
114+
if values.get("tags")
115+
else ""
116+
)
115117
for column in self.__tag_columns
116118
]
117119
config_column_values = [
118-
values.get("config", {}).get(column, "")
119-
if values.get("config")
120-
else ""
120+
(
121+
values.get("config", {}).get(column, "")
122+
if values.get("config")
123+
else ""
124+
)
121125
for column in self.__config_columns
122126
]
123127
account_column_values = [
124-
values.get("account", {}).get(column, "")
125-
if values.get("account")
126-
else ""
128+
(
129+
values.get("account", {}).get(column, "")
130+
if values.get("account")
131+
else ""
132+
)
127133
for column in self.__account_columns
128134
]
129135
impact_column_values = [
@@ -206,21 +212,27 @@ def generate_output_xlsx(self):
206212
else:
207213
worksheet.write(current_line, 1, severity, low_format)
208214
tag_column_values = [
209-
values.get("tags", {}).get(column, "")
210-
if values.get("tags")
211-
else ""
215+
(
216+
values.get("tags", {}).get(column, "")
217+
if values.get("tags")
218+
else ""
219+
)
212220
for column in self.__tag_columns
213221
]
214222
config_column_values = [
215-
values.get("config", {}).get(column, "")
216-
if values.get("config")
217-
else ""
223+
(
224+
values.get("config", {}).get(column, "")
225+
if values.get("config")
226+
else ""
227+
)
218228
for column in self.__config_columns
219229
]
220230
account_column_values = [
221-
values.get("account", {}).get(column, "")
222-
if values.get("account")
223-
else ""
231+
(
232+
values.get("account", {}).get(column, "")
233+
if values.get("account")
234+
else ""
235+
)
224236
for column in self.__account_columns
225237
]
226238
impact_column_values = [
@@ -444,37 +456,55 @@ def create_table(cursor, table_definition):
444456
resource_findings_medium = findings["findings"]["MEDIUM"]
445457
resource_findings_low = findings["findings"]["LOW"]
446458
resource_findings_informational = findings["findings"]["INFORMATIONAL"]
447-
account_alias = data.get("account", {})["Alias"]
448-
account_organization = data.get("account", {}).get("Organizations", {})
449-
if account_organization:
450-
account_organization_id = account_organization.get("Id")
451-
account_organization_arn = account_organization.get("Arn")
452-
account_master_account_id = account_organization.get("MasterAccountId")
453-
account_master_account_email = account_organization.get(
454-
"MasterAccountEmail"
459+
if data.get("account", {}):
460+
account_alias = data.get("account", {})["Alias"]
461+
account_organization = data.get("account", {}).get("Organizations", {})
462+
if account_organization:
463+
account_organization_id = account_organization.get("Id")
464+
account_organization_arn = account_organization.get("Arn")
465+
account_master_account_id = account_organization.get(
466+
"MasterAccountId"
467+
)
468+
account_master_account_email = account_organization.get(
469+
"MasterAccountEmail"
470+
)
471+
else:
472+
account_organization_id = ""
473+
account_organization_arn = ""
474+
account_master_account_id = ""
475+
account_master_account_email = ""
476+
account_alternate_contact_type = (
477+
data.get("account", {})
478+
.get("AlternateContact", {})
479+
.get("AlternateContactType")
480+
)
481+
account_alternate_contact_name = (
482+
data.get("account", {}).get("AlternateContact", {}).get("Name")
483+
)
484+
account_alternate_contact_email = (
485+
data.get("account", {})
486+
.get("AlternateContact", {})
487+
.get("EmailAddress")
488+
)
489+
account_alternate_contact_phone = (
490+
data.get("account", {})
491+
.get("AlternateContact", {})
492+
.get("PhoneNumber")
493+
)
494+
account_alternate_contact_title = (
495+
data.get("account", {}).get("AlternateContact", {}).get("Title")
455496
)
456497
else:
498+
account_alias = ""
457499
account_organization_id = ""
458500
account_organization_arn = ""
459501
account_master_account_id = ""
460502
account_master_account_email = ""
461-
account_alternate_contact_type = (
462-
data.get("account", {})
463-
.get("AlternateContact", {})
464-
.get("AlternateContactType")
465-
)
466-
account_alternate_contact_name = (
467-
data.get("account", {}).get("AlternateContact", {}).get("Name")
468-
)
469-
account_alternate_contact_email = (
470-
data.get("account", {}).get("AlternateContact", {}).get("EmailAddress")
471-
)
472-
account_alternate_contact_phone = (
473-
data.get("account", {}).get("AlternateContact", {}).get("PhoneNumber")
474-
)
475-
account_alternate_contact_title = (
476-
data.get("account", {}).get("AlternateContact", {}).get("Title")
477-
)
503+
account_alternate_contact_type = ""
504+
account_alternate_contact_name = ""
505+
account_alternate_contact_email = ""
506+
account_alternate_contact_phone = ""
507+
account_alternate_contact_title = ""
478508
cursor.execute(
479509
INSERT_RESOURCES,
480510
(

lib/securityhub.py

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -189,17 +189,33 @@ def update_findings_meta(self, mh_findings):
189189

190190
def parse_finding(finding):
191191
"""Returns resource ARN and finding parsed for it"""
192-
findings = {
193-
finding["Title"]: {
194-
"SeverityLabel": finding.get("Severity").get("Label", "Unknown"),
195-
"Workflow": finding.get("Workflow", {"Status": "Unknown"}),
196-
"RecordState": finding.get("RecordState", "Unknown"),
197-
"Compliance": finding.get("Compliance", {"Status": "Unknown"}),
198-
"Id": finding.get("Id", "Unknown"),
199-
"ProductArn": finding.get("ProductArn", "Unknown"),
200-
},
201-
}
202-
return finding["Resources"][0]["Id"], findings
192+
# ASFF Finding:
193+
if "Title" in finding:
194+
resource_arn = finding["Resources"][0]["Id"]
195+
findings = {
196+
finding["Title"]: {
197+
"SeverityLabel": finding.get("Severity").get("Label", "Unknown"),
198+
"Workflow": finding.get("Workflow", {"Status": "Unknown"}),
199+
"RecordState": finding.get("RecordState", "Unknown"),
200+
"Compliance": finding.get("Compliance", {"Status": "Unknown"}),
201+
"Id": finding.get("Id", "Unknown"),
202+
"ProductArn": finding.get("ProductArn", "Unknown"),
203+
},
204+
}
205+
# OSCF Finding:
206+
if "metadata" in finding:
207+
resource_arn = finding.get("resources", {})[0].get("uid")
208+
findings = {
209+
finding.get("finding_info").get("title"): {
210+
"SeverityLabel": finding.get("severity", "Unknown"),
211+
"Workflow": {"Status": finding.get("status", "Unknown")},
212+
"RecordState": "Unknown",
213+
"Compliance": {"Status": finding.get("status_code", "Unknown")},
214+
"Id": finding.get("finding_info").get("uid", "Unknown"),
215+
"ProductArn": finding.get("finding_info").get("product_uid", "Unknown"),
216+
},
217+
}
218+
return resource_arn, findings
203219

204220

205221
def parse_region(resource_arn, finding):

powerpipe/access.pp

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
dashboard "access" {
2+
text {
3+
value = "## MetaHub: [Resources](${var.host}/metahub.dashboard.resources) | [Findings](${var.host}/metahub.dashboard.findings) | [Accounts](${var.host}/metahub.dashboard.accounts) | Access | [Exposure](${var.host}/metahub.dashboard.exposure)"
4+
}
5+
6+
container {
7+
card {
8+
query = query.count_access
9+
width = 3
10+
args = {
11+
access = "unrestricted"
12+
}
13+
href = "/metahub.dashboard.access?input.access=unrestricted"
14+
}
15+
card {
16+
query = query.count_access
17+
width = 3
18+
args = {
19+
access = "untrusted-principal"
20+
}
21+
href = "/metahub.dashboard.access?input.access=untrusted-principal"
22+
}
23+
card {
24+
query = query.count_access
25+
width = 3
26+
args = {
27+
access = "unrestricted-principal"
28+
}
29+
href = "/metahub.dashboard.access?input.access=unrestricted-principal"
30+
}
31+
card {
32+
query = query.count_access
33+
width = 3
34+
args = {
35+
access = "cross-account-principal"
36+
}
37+
href = "/metahub.dashboard.access?input.access=cross-account-principal"
38+
}
39+
card {
40+
query = query.count_access
41+
width = 3
42+
args = {
43+
access = "unrestricted-actions"
44+
}
45+
href = "/metahub.dashboard.access?input.access=unrestricted-actions"
46+
}
47+
card {
48+
query = query.count_access
49+
width = 3
50+
args = {
51+
access = "dangerous-actions"
52+
}
53+
href = "/metahub.dashboard.access?input.access=dangerous-actions"
54+
}
55+
card {
56+
query = query.count_access
57+
width = 2
58+
args = {
59+
access = "unrestricted-service"
60+
}
61+
href = "/metahub.dashboard.access?input.access=unrestricted-service"
62+
}
63+
card {
64+
query = query.count_access
65+
width = 2
66+
args = {
67+
access = "restricted"
68+
}
69+
href = "/metahub.dashboard.access?input.access=restricted"
70+
}
71+
card {
72+
query = query.count_access
73+
width = 2
74+
type = "ok"
75+
args = {
76+
access = "unknown"
77+
}
78+
href = "/metahub.dashboard.access?input.access=unknown"
79+
}
80+
}
81+
82+
container {
83+
input "exposure" {
84+
base = metahub.input.exposure
85+
}
86+
87+
input "access" {
88+
base = metahub.input.access
89+
}
90+
91+
input "encryption" {
92+
base = metahub.input.encryption
93+
}
94+
95+
input "status" {
96+
base = metahub.input.status
97+
}
98+
99+
input "severity" {
100+
base = metahub.input.severity
101+
}
102+
103+
input "environment" {
104+
base = metahub.input.environment
105+
}
106+
}
107+
108+
container {
109+
input "owner" {
110+
base = metahub.input.owner
111+
}
112+
113+
input "application" {
114+
base = metahub.input.application
115+
}
116+
117+
input "account" {
118+
base = metahub.input.account
119+
}
120+
121+
input "type" {
122+
base = metahub.input.type
123+
}
124+
125+
input "region" {
126+
base = metahub.input.region
127+
}
128+
129+
input "tags" {
130+
base = metahub.input.tags
131+
}
132+
}
133+
134+
container {
135+
table {
136+
query = query.resources
137+
args = {
138+
exposure = self.input.exposure.value
139+
access = self.input.access.value
140+
encryption = self.input.encryption.value
141+
status = self.input.status.value
142+
severity = self.input.severity.value
143+
environment = self.input.environment.value
144+
owner = self.input.owner.value
145+
application = self.input.application.value
146+
account = self.input.account.value
147+
type = self.input.type.value
148+
region = self.input.region.value
149+
tags = self.input.tags.value
150+
}
151+
column "name" {
152+
href = "${dashboard.findings.url_path}?input.resource_arn={{.'resource_arn' | @uri}}"
153+
}
154+
column "resource_arn" {
155+
href = "${dashboard.findings.url_path}?input.resource_arn={{.'resource_arn' | @uri}}"
156+
}
157+
}
158+
}
159+
}

0 commit comments

Comments
 (0)