StackHawk
In this example, you are going to create a webhook integration between StackHawk and Port, which will ingest application vulnerabilities into Port. This integration will involve setting up a webhook to receive notifications from StackHawk whenever an application is scanned for vulnerabilities, allowing Port to ingest and process the vulnerability entities accordingly.
Prerequisites
Create the following blueprint definitions and webhook configuration:
StackHawk vulnerability blueprint
{
"identifier": "stackHawkVulnerability",
"description": "This blueprint represents a StackHawk vulnerability in our software catalog",
"title": "StackHawk Vulnerability",
"icon": "StackHawk",
"schema": {
"properties": {
"severity": {
"type": "string",
"title": "Severity",
"description": "The criticality of the finding",
"enum": ["Low", "Medium", "High"],
"enumColors": {
"Low": "green",
"Medium": "yellow",
"High": "red"
}
},
"host": {
"type": "string",
"format": "url",
"title": "Host",
"description": "The web application host that was scanned"
},
"category": {
"type": "string",
"title": "Category",
"description": "What vulnerability category this corresponds to"
},
"url": {
"type": "string",
"format": "url",
"title": "Finding URL",
"description": "Link to the StackHawk Platform for this finding's overview"
},
"totalCount": {
"type": "number",
"title": "Total Count",
"description": "How many scanned paths correspond with this finding"
},
"tags": {
"type": "array",
"title": "Tags"
}
},
"required": []
},
"mirrorProperties": {},
"calculationProperties": {},
"relations": {}
}
StackHawk webhook configuration
Remember to update the WEBHOOK_SECRET
and AUTH_SIGNATURE_HEADER
with the real secret and header value you provided when subscribing to the webhook in StackHawk.
{
"identifier": "stackHawkMapper",
"title": "StackHawk Mapper",
"description": "A webhook configuration to map StackHawk vulnerability to Port",
"icon": "StackHawk",
"mappings": [
{
"blueprint": "stackHawkVulnerability",
"itemsToParse": ".body.scanCompleted.findings",
"entity": {
"identifier": ".body.scanCompleted.scan.application + \"-\" + .item.pluginId | gsub(\"[^a-zA-Z0-9@_.:\\/=-]\"; \"-\") | tostring",
"title": ".item.pluginName",
"properties": {
"severity": ".item.severity",
"host": ".item.host",
"totalCount": ".item.totalCount",
"category": ".item.category",
"url": ".item.findingURL",
"tags": ".body.scanCompleted.scan.tags"
}
}
}
],
"enabled": true,
"security": {
"secret": "WEBHOOK_SECRET",
"signatureHeaderName": "AUTH_SIGNATURE_HEADER",
"signatureAlgorithm": "plain",
"signaturePrefix": ""
}
}
Create the StackHawk webhook
- Go to StackHawk and select the account you want to configure the webhook for.
- Navigate to Integrations in the left navigation bar and click on Generic Webhook.
- Click on Add Webhook and provide the following information:
Name
- enter a name for your webhook.Description
- provide a detailed description for your webhook.Scan Data For
- choose the application(s) you want to receive webhook events for or chooseSelect All
if you want to configure a global webhook for all your applications.Scan Events
- chooseScan Completed
event type.Webhook Endpoint URL
- enter the value of theurl
key you received after creating the webhook configuration.Auth Header Name
- enter the name of the HTTP header that will contain your auth token/key. For example, you can enterX-StackHawk-Port-Webhook
.Auth Header Value
- enter the secret authentication token that will be added to your webhook payload.
- Click Create and Test to create your webhook.
In order to view the different events available in StackHawk webhooks, look here
Done! Any changes that happen to your applications in StackHawk will trigger a webhook event to the webhook URL provided by Port. Port will parse the events according to the mapping and update the catalog entities accordingly.
Test the webhook
This section includes a sample webhook event sent from StackHawk when an application is scanned. In addition, it also includes the entity created from the event based on the webhook configuration provided in the previous section.
Payload
Here is an example of the payload structure sent to the webhook URL when an application is scanned:
Webhook event payload
{
"service": "StackHawk",
"scanCompleted": {
"scan": {
"id": "c30e848d-35a7-4357-a113-35ce3392e967",
"hawkscanVersion": "3.1.0",
"env": "Development",
"status": "COMPLETED",
"application": "Python App",
"startedTimestamp": "2023-06-23T11:01:18.273Z",
"scanURL": "https://app.stackhawk.com/scans/c30e848d-35a7-4357-a113-35ce3392e967",
"tags": ["test-application"]
},
"scanDuration": "72",
"spiderDuration": "49",
"completedScanStats": {
"urlsCount": "2",
"duration": "121",
"scanResultsStats": {
"totalCount": "5",
"lowCount": "7",
"mediumCount": "4",
"highCount": "0",
"lowTriagedCount": "0",
"mediumTriagedCount": "0",
"highTriagedCount": "0"
}
},
"findings": [
{
"pluginId": "10021",
"pluginName": "X-Content-Type-Options Header Missing",
"severity": "Low",
"host": "https://example.com",
"paths": [
{
"path": "",
"method": "GET",
"status": "NEW",
"pathURL": "https://app.stackhawk.com/scans/c30e848d-35a7-4357-a113-35ce3392e967/finding/10021/path/769898/message/4"
}
],
"pathStats": [
{
"status": "NEW",
"count": 1
}
],
"totalCount": "1",
"category": "Information Leakage",
"findingURL": "https://app.stackhawk.com/scans/c30e848d-35a7-4357-a113-35ce3392e967/finding/10021"
},
{
"pluginId": "10035",
"pluginName": "Strict-Transport-Security Header Not Set",
"severity": "Low",
"host": "https://example.com",
"paths": [
{
"path": "/robots.txt",
"method": "GET",
"status": "NEW",
"pathURL": "https://app.stackhawk.com/scans/c30e848d-35a7-4357-a113-35ce3392e967/finding/10035/path/769897/message/7"
},
{
"path": "/sitemap.xml",
"method": "GET",
"status": "NEW",
"pathURL": "https://app.stackhawk.com/scans/c30e848d-35a7-4357-a113-35ce3392e967/finding/10035/path/769896/message/6"
},
{
"path": "",
"method": "GET",
"status": "NEW",
"pathURL": "https://app.stackhawk.com/scans/c30e848d-35a7-4357-a113-35ce3392e967/finding/10035/path/769898/message/4"
}
],
"pathStats": [
{
"status": "NEW",
"count": 3
}
],
"totalCount": "3",
"category": "Information Leakage",
"findingURL": "https://app.stackhawk.com/scans/c30e848d-35a7-4357-a113-35ce3392e967/finding/10035"
}
]
}
}
Mapping result
The combination of the sample payload and the webhook configuration generates the following Port entities (in the sample above, multiple entities will be generated because the findings
array contains multiple objects):
{
"identifier": "Python-App-10020-1",
"title": "Missing Anti-clickjacking Header",
"blueprint": "stackHawkVulnerability",
"properties": {
"severity": "Medium",
"host": "https://example.com",
"totalCount": 1,
"category": "Information Leakage",
"url": "https://app.stackhawk.com/scans/c30e848d-35a7-4357-a113-35ce3392e967/finding/10020-1",
"tags": ["test-application"]
},
"relations": {}
}