Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ export const loadAllOrganizationDomainStatuses =
${domainFilters}
FILTER d.wildcardSibling ${comparison} true
`
} else if (filterValue === 'scan-pending') {
domainFilters = aql`${domainFilters}`
} else if (filterValue === 'has-entrust-certificate') {
domainFilters = aql`
${domainFilters}
Expand Down Expand Up @@ -102,6 +104,17 @@ export const loadAllOrganizationDomainStatuses =
FOR webScan, webScanE IN 1 OUTBOUND web._id webToWebScans
RETURN webScan.ipAddress
)
LET vulnerabilities = (
FOR finding IN additionalFindings
FILTER finding.domain == d._id
LIMIT 1
RETURN UNIQUE(
FOR wc IN finding.webComponents
FILTER LENGTH(wc.WebComponentCves) > 0
FOR vuln IN wc.WebComponentCves
RETURN vuln.Cve
)
)[0]
RETURN {
"domain": d.domain,
"ipAddresses": ipAddresses,
Expand All @@ -118,7 +131,7 @@ export const loadAllOrganizationDomainStatuses =
"blocked": d.blocked,
"wildcardSibling": d.wildcardSibling,
"hasEntrustCertificate": d.hasEntrustCertificate,
"hasTop25Vulnerability": d.cveDetected
"top25Vulnerabilities": vulnerabilities
}
`
).all()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ export const loadOrganizationDomainStatuses =
${domainFilters}
FILTER v.cveDetected ${comparison} true
`
} else if (filterValue === 'scan-pending') {
domainFilters = aql`${domainFilters}`
} else {
domainFilters = aql`
${domainFilters}
Expand Down Expand Up @@ -119,6 +121,17 @@ export const loadOrganizationDomainStatuses =
FOR webScan, webScanE IN 1 OUTBOUND web._id webToWebScans
RETURN webScan.ipAddress
)
LET vulnerabilities = (
FOR finding IN additionalFindings
FILTER finding.domain == v._id
LIMIT 1
RETURN UNIQUE(
FOR wc IN finding.webComponents
FILTER LENGTH(wc.WebComponentCves) > 0
FOR vuln IN wc.WebComponentCves
RETURN vuln.Cve
)
)[0]
RETURN {
domain: v.domain,
ipAddresses: ipAddresses,
Expand All @@ -129,7 +142,7 @@ export const loadOrganizationDomainStatuses =
blocked: v.blocked,
wildcardSibling: v.wildcardSibling,
hasEntrustCertificate: v.hasEntrustCertificate,
cveDetected: v.cveDetected
top25Vulnerabilities: vulnerabilities
}
`
).all()
Expand Down
7 changes: 4 additions & 3 deletions api/src/organization/objects/organization.js
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ export const organizationType = new GraphQLObjectType({
'blocked',
'wildcardSibling',
'hasEntrustCertificate',
'top25VulnerabilityDetected',
'top25Vulnerabilities',
]
let csvOutput = headers.join(',')
domains.forEach(
Expand All @@ -189,16 +189,17 @@ export const organizationType = new GraphQLObjectType({
blocked,
wildcardSibling,
hasEntrustCertificate,
cveDetected,
...rest
}) => {
const vulns = rest?.top25Vulnerabilities || []
let csvLine = `${domain}`
csvLine += `,${ipAddresses.join('|')}`
csvLine += headers.slice(2, 11).reduce((previousValue, currentHeader) => {
return `${previousValue},${status[currentHeader]}`
}, '')
csvLine += `,${tags.join(
'|',
)},${assetState},${rcode},${blocked},${wildcardSibling},${hasEntrustCertificate},${cveDetected}`
)},${assetState},${rcode},${blocked},${wildcardSibling},${hasEntrustCertificate},${vulns.join('|')}`
csvOutput += `\n${csvLine}`
},
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,9 +247,9 @@ describe('given getAllOrganizationDomainStatuses', () => {

const expectedResponse = {
data: {
getAllOrganizationDomainStatuses: `domain,ipAddresses,https,hsts,certificates,ciphers,curves,protocols,spf,dkim,dmarc,rcode,blocked,wildcardSibling,hasEntrustCertificate,hasTop25Vulnerability
"domain.one",,"fail","pass","pass","pass","pass","pass","pass","pass","pass","NOERROR","false","false","false","false"
"domain.two",,"pass","fail","pass","fail","pass","fail","pass","pass","fail","NOERROR","false","false","false","false"`,
getAllOrganizationDomainStatuses: `domain,ipAddresses,https,hsts,certificates,ciphers,curves,protocols,spf,dkim,dmarc,rcode,blocked,wildcardSibling,hasEntrustCertificate,top25Vulnerabilities
"domain.one",,"fail","pass","pass","pass","pass","pass","pass","pass","pass","NOERROR","false","false","false",
"domain.two",,"pass","fail","pass","fail","pass","fail","pass","pass","fail","NOERROR","false","false","false",`,
},
}

Expand Down Expand Up @@ -364,9 +364,9 @@ describe('given getAllOrganizationDomainStatuses', () => {
})
const expectedResponse = {
data: {
getAllOrganizationDomainStatuses: `domain,ipAddresses,https,hsts,certificates,ciphers,curves,protocols,spf,dkim,dmarc,rcode,blocked,wildcardSibling,hasEntrustCertificate,hasTop25Vulnerability
"domain.one",,"fail","pass","pass","pass","pass","pass","pass","pass","pass","NOERROR","false","false","false","false"
"domain.two",,"pass","fail","pass","fail","pass","fail","pass","pass","fail","NOERROR","false","false","false","false"`,
getAllOrganizationDomainStatuses: `domain,ipAddresses,https,hsts,certificates,ciphers,curves,protocols,spf,dkim,dmarc,rcode,blocked,wildcardSibling,hasEntrustCertificate,top25Vulnerabilities
"domain.one",,"fail","pass","pass","pass","pass","pass","pass","pass","pass","NOERROR","false","false","false",
"domain.two",,"pass","fail","pass","fail","pass","fail","pass","pass","fail","NOERROR","false","false","false",`,
},
}
expect(response).toEqual(expectedResponse)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,14 @@ export const getAllOrganizationDomainStatuses = {
'blocked',
'wildcardSibling',
'hasEntrustCertificate',
'hasTop25Vulnerability',
'top25Vulnerabilities',
]
let csvOutput = headers.join(',')
domainStatuses.forEach((domainStatus) => {
const csvLine = headers
.map((header) => {
if (header === 'ipAddresses') {
return domainStatus[header].join('|')
if (['ipAddresses', 'top25Vulnerabilities'].includes(header)) {
return domainStatus[header]?.join('|') || []
}
return `"${domainStatus[header]}"`
})
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from azure.kusto.data import KustoClient, KustoConnectionStringBuilder
from azure.kusto.data.helpers import dataframe_from_result_table

from datetime import datetime, date, timedelta
import logging
import os
from dotenv import load_dotenv
Expand All @@ -25,12 +25,22 @@
KUSTO_CLIENT = KustoClient(KCSB_DATA)


def filter_recent_data(data_list, last_seen_key, start_date):
return [
x
for x in data_list
if datetime.strptime(x[last_seen_key].split("T")[0], "%Y-%m-%d").date()
>= start_date
]


def get_web_components_by_asset(asset):
query = f"""
declare query_parameters(asset_name:string = '{asset}');
EasmAssetWebComponent
| where AssetName == asset_name
| where TimeGeneratedValue > ago(24h)
| where WebComponentLastSeen > ago(30d)
| summarize arg_max(TimeGeneratedValue, WebComponentCves, WebComponentPorts) by WebComponentName, WebComponentCategory, WebComponentVersion, WebComponentFirstSeen, WebComponentLastSeen
| project WebComponentName, WebComponentCategory, WebComponentVersion, WebComponentFirstSeen, WebComponentLastSeen, WebComponentCves, WebComponentPorts
"""
Expand All @@ -54,6 +64,7 @@ def get_web_components_by_asset(asset):


def get_additional_findings_by_asset(asset):
thirty_days_ago = date.today() - timedelta(days=30)
query = f"""
declare query_parameters(asset_name:string = '{asset}');
EasmHostAsset
Expand All @@ -67,4 +78,12 @@ def get_additional_findings_by_asset(asset):
data = dataframe_from_result_table(response.primary_results[0]).to_dict(
orient="records"
)[0]

data["Ports"] = filter_recent_data(
data["Ports"], "PortStateLastSeen", thirty_days_ago
)
data["Locations"] = filter_recent_data(
data["Locations"], "LastSeen", thirty_days_ago
)

return data
2 changes: 1 addition & 1 deletion frontend/src/guidance/AdditionalFindings.js
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ export function AdditionalFindings({ domain }) {
>
External Attack Surface Management
</Link>{' '}
tool. Updates to these findings occur weekly.
tool. Updates to these findings occur daily.
</Trans>
</ModalBody>
<ModalFooter />
Expand Down
8 changes: 6 additions & 2 deletions frontend/src/locales/en.po
Original file line number Diff line number Diff line change
Expand Up @@ -4263,8 +4263,12 @@ msgid "The user's role has been successfully updated"
msgstr "The user's role has been successfully updated"

#: src/guidance/AdditionalFindings.js:357
msgid "These findings are imported from Microsoft's <0>External Attack Surface Management</0> tool. Updates to these findings occur weekly."
msgstr "These findings are imported from Microsoft's <0>External Attack Surface Management</0> tool. Updates to these findings occur weekly."
msgid "These findings are imported from Microsoft's <0>External Attack Surface Management</0> tool. Updates to these findings occur daily."
msgstr "These findings are imported from Microsoft's <0>External Attack Surface Management</0> tool. Updates to these findings occur daily."

#: src/guidance/AdditionalFindings.js:357
#~ msgid "These findings are imported from Microsoft's <0>External Attack Surface Management</0> tool. Updates to these findings occur weekly."
#~ msgstr "These findings are imported from Microsoft's <0>External Attack Surface Management</0> tool. Updates to these findings occur weekly."

#: src/app/ReadGuidancePage.js:154
msgid "These metrics are an important first step in securing your services and should be treated as minimum requirements. Further metrics are available in your organization's domain list."
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/locales/fr.po
Original file line number Diff line number Diff line change
Expand Up @@ -4205,8 +4205,8 @@ msgid "The user's role has been successfully updated"
msgstr "Le rôle de l'utilisateur a été mis à jour avec succès"

#: src/guidance/AdditionalFindings.js:357
msgid "These findings are imported from Microsoft's <0>External Attack Surface Management</0> tool. Updates to these findings occur weekly."
msgstr "Ces résultats sont importés de l'outil <0>External Attack Surface Management</0> de Microsoft. Ces résultats sont mis à jour chaque semaine."
msgid "These findings are imported from Microsoft's <0>External Attack Surface Management</0> tool. Updates to these findings occur daily."
msgstr "Ces résultats sont importés de l'outil <0>External Attack Surface Management</0> de Microsoft. Ces résultats sont mis à jour quotidiennement."

#: src/app/ReadGuidancePage.js:154
msgid "These metrics are an important first step in securing your services and should be treated as minimum requirements. Further metrics are available in your organization's domain list."
Expand Down