{"id":18835971,"url":"https://github.com/nscuro/dtapac","last_synced_at":"2025-08-21T07:09:56.559Z","repository":{"id":38103885,"uuid":"482009961","full_name":"nscuro/dtapac","owner":"nscuro","description":"Audit Dependency-Track findings and policy violations via policy as code","archived":false,"fork":false,"pushed_at":"2024-11-07T11:43:10.000Z","size":3400,"stargazers_count":32,"open_issues_count":8,"forks_count":4,"subscribers_count":6,"default_branch":"main","last_synced_at":"2024-11-07T12:34:18.952Z","etag":null,"topics":["dependency-track","dtrack","go","golang","opa","open-policy-agent","owasp","policy-as-code"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nscuro.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-04-15T15:56:50.000Z","updated_at":"2024-10-08T10:13:25.000Z","dependencies_parsed_at":"2023-10-02T20:24:52.164Z","dependency_job_id":"8375cb75-14f2-42d4-a2ed-013606f49a6f","html_url":"https://github.com/nscuro/dtapac","commit_stats":null,"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nscuro%2Fdtapac","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nscuro%2Fdtapac/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nscuro%2Fdtapac/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nscuro%2Fdtapac/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nscuro","download_url":"https://codeload.github.com/nscuro/dtapac/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223619616,"owners_count":17174445,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dependency-track","dtrack","go","golang","opa","open-policy-agent","owasp","policy-as-code"],"created_at":"2024-11-08T02:17:44.441Z","updated_at":"2024-11-08T02:17:44.955Z","avatar_url":"https://github.com/nscuro.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# dtapac\n\n[![Build Status](https://github.com/nscuro/dtapac/actions/workflows/ci.yml/badge.svg)](https://github.com/nscuro/dtapac/actions/workflows/ci.yml)\n[![Latest GitHub release](https://img.shields.io/github/v/release/nscuro/dtapac?sort=semver)](https://github.com/nscuro/dtapac/releases/latest)\n[![License](https://img.shields.io/badge/license-Apache%202.0-brightgreen.svg)](LICENSE)\n\n*Audit Dependency-Track findings and policy violations via policy as code*\n\n\u003e Consider this project to be a proof-of-concept. It is not very sophisticated, but it gets the job done.\n\u003e Try it in a test environment first. **Do not skip this step, do not run it in production without prior testing**!\n\n## Introduction\n\n[Dependency-Track](https://dependencytrack.org/) offers a fairly sophisticated auditing workflow for vulnerabilities \nand policy violations. However, this workflow is scoped to individual findings or policy violations right now.\n\nI often found myself wanting a mechanism that lets me make more generalized audit decisions that would affect\nmultiple (and sometimes even *all*) projects in my portfolio. While the most common use case for something like this\nis definitely suppressing false positives, there are times when other audit actions are desirable as well.\nA [suppression file](https://jeremylong.github.io/DependencyCheck/general/suppression.html) as seen in projects like \n[Dependency-Check](https://jeremylong.github.io/DependencyCheck/) simply won't cut it.\n\nUsing scripts to mass-apply analyses works, but then you're stuck with re-running that script everytime the thing\nyou analysed pops up in another project or project version. Not cool. Individual scripts also don't scale well,\nsharing with team members is tedious.\n\nI've written a fair share of tools that provide the desired functionality based on some kind of configuration file, \nbut I quickly came to the realization that configuration files are too limiting for my needs. \nNot only are they not a good fit for dynamic decisions, they are also a pain to test.\n\nIt turns out that you can have your cake and eat it too using *policy as code*. The most popular implementation of PaC \nprobably being [Open Policy Agent](https://www.openpolicyagent.org/) (OPA). \n\nThink of *dtapac* as a bridge between Dependency-Track and OPA.\n\n![Overview](./.github/images/overview.png)\n\n\u003e Note that *dtapac* as it stands now is **not** intended for performing all auditing through it.\n\u003e It's not a complete replacement for manual auditing. Use it for decisions that are likely to affect larger\n\u003e parts of your portfolio. Check the [example policies](./examples/policies) to get an idea of what *dtapac*\n\u003e can be used for.\n\n## How it works\n\n### Ad-hoc auditing through notifications\n\nThe main way that *dtapac* uses to integrate with Dependency-Track is by consuming \n[notifications](https://docs.dependencytrack.org/integrations/notifications/) (aka alerts). \nWhen receiving a `NEW_VULNERABILITY` or `POLICY_VIOLATION` notification, *dtapac* will immediately \nquery OPA for an analysis decision. \n\n```mermaid\nsequenceDiagram\n    autonumber\n    actor Client\n    Client-\u003e\u003eDependency-Track: Upload BOM\n    Dependency-Track-\u003e\u003eDependency-Track: Analyze BOM\n    alt New Vulnerability identified\n        Dependency-Track-\u003e\u003edtapac: NEW_VULNERABILITY notification\n    else Policy Violation identified\n        Dependency-Track-\u003e\u003edtapac: POLICY_VIOLATION notification\n    end\n    dtapac-\u003e\u003eOPA: Query analysis decision\n    OPA-\u003e\u003eOPA: Evaluate policy\n    OPA-\u003e\u003edtapac: Analysis decision\n    dtapac-\u003e\u003eDependency-Track: Query existing analysis\n    Dependency-Track-\u003e\u003edtapac: Analysis\n    dtapac-\u003e\u003edtapac: Compare analyses\n    opt Analysis has changed\n        dtapac-\u003e\u003eDependency-Track: Update analysis\n    end\n```\n\n*dtapac* will only submit the resulting analysis if it differs from what's already recorded in Dependency-Track. \nThis ensures that the audit trail won't be cluttered with redundant information, even if *dtapac* receives multiple \nnotifications for the same finding or policy violation.\n\nNote that this also means that if you make changes to an analysis that *dtapac* applied for you in Dependency-Track,\n*dtapac* will override it during its next execution. This is by design.\n\n### Portfolio auditing on policy change\n\nIf configured, *dtapac* can listen for [status updates](https://www.openpolicyagent.org/docs/latest/management-status/) \nfrom OPA. *dtapac* will keep track of the revision of the policy bundle, and trigger a portfolio-wide analysis when it \nchanges.\n\n```mermaid\nsequenceDiagram\n    autonumber\n    loop Periodically\n        OPA-\u003e\u003eNginx: Pull Bundle\n        Nginx-\u003e\u003eOPA: archive\n    end\n    loop Periodically\n        OPA-\u003e\u003edtapac: Status\n        dtapac-\u003e\u003edtapac: Compare reported bundle revision with last-known\n        opt Bundle revision changed\n            dtapac-\u003e\u003eDependency-Track: Fetch all projects\n            Dependency-Track-\u003e\u003edtapac: Projects\n            loop For each project\n                dtapac-\u003e\u003eDependency-Track: Fetch all findings \u0026 policy violations\n                Dependency-Track-\u003e\u003edtapac: Findings \u0026 policy violations\n                loop For each finding \u0026 policy violation\n                    dtapac-\u003e\u003eOPA: Query analysis decision\n                    OPA-\u003e\u003eOPA: Evaluate policy\n                    OPA-\u003e\u003edtapac: Analysis decision\n                    dtapac-\u003e\u003eDependency-Track: Query existing analysis\n                    Dependency-Track-\u003e\u003edtapac: Analysis\n                    dtapac-\u003e\u003edtapac: Compare analyses\n                    opt Analysis has changed\n                        dtapac-\u003e\u003eDependency-Track: Update analysis\n                    end\n                end\n            end\n        end\n    end\n```\n\nThis makes it possible to have new policies applied to the entire portfolio shortly after publishing them, without the\nneed to restart any service or edit files on any server.\n\n### Shortcomings\n\nSome limitations of *dtapac* that you should be aware of before using it:\n\n* **No retries**. If an analysis decision could not be submitted to Dependency-Track for any reason, it won't be retried.\n* **No persistence**. If you stop *dtapac* while it's still processing something, that something is gone.\n* **No access control**. *dtapac* trusts that whatever is inside the notifications it receives is valid. Notifications can be forged. Expose *dtapac* to an internal network or use a service mesh.\n  * [Webhook authentication](https://github.com/DependencyTrack/dependency-track/issues/1555) is a planned feature in Dependency-Track.\n\n## Usage\n\n```\nUSAGE\n  dtapac [FLAGS...]\n\nAudit Dependency-Track findings and policy violations via policy as code.\n\nFLAGS\n  -config ...                 Path to config file\n  -dry-run=false              Only log analyses but don't apply them\n  -dtrack-apikey ...          Dependency-Track API key\n  -dtrack-url ...             Dependency-Track API server URL\n  -finding-policy-path ...    Policy path for finding analysis\n  -host 0.0.0.0               Host to listen on\n  -log-json=false             Output log in JSON format\n  -log-level info             Log level\n  -opa-url ...                Open Policy Agent URL\n  -port 8080                  Port to listen on\n  -violation-policy-path ...  Policy path for violation analysis\n  -watch-bundle ...           OPA bundle to watch\n```\n\nAll options can alternatively be provided via configuration file and environment variables.\n\n## Writing Policies\n\nThe basic idea is that a policy receives a finding or policy violation as input and returns an analysis.\n\n![Policy Overview](./.github/images/policy_overview.png)\n\nOPA's policy language is powerful yet concise and is a perfect fit for our use case.\n\nPlease take a moment to read a little about [OPA](https://www.openpolicyagent.org/docs/latest/) and\n[Rego](https://www.openpolicyagent.org/docs/latest/policy-language/). I can also recommend\nthe [Rego style guide](https://github.com/StyraInc/rego-style-guide) for a little more hands-on advice.\n\n### Structure\n\nPolicies written in Rego are designed to return either one or multiple results. If a policy is written in a way\nthat only allows for a single result, OPA will fail when multiple rules match the given input. If a policy allows\nfor multiple results, OPA (per default) makes no guarantees regarding the order in which results are returned.\n\nThis behavior is problematic for *dtapac* for the following reasons:\n\n* For any given finding or violation, there should always be *exactly one* analysis, or none at all\n  * Multiple analyses for the same finding make no sense\n* It is inevitable that multiple policy rules match\n  * If one rule matches on vulnerability V, and another on component C, both will match an alert about C being affected by V\n* If multiple rules match, which one should be applied?\n  * Auditing should be deterministic. If the output of results has no guaranteed order, what's the correct result?\n\nLuckily, OPA provides a way to indicate that the first matching rule should take precedence over others: [`else`](https://www.openpolicyagent.org/docs/latest/faq/#statement-order).\nPolicies for *dtapac* thus must be more or less a single if-else-statement (refer to the [example policies](./examples/policies) \nto see how that looks like).\n\nYou as policy author have to ensure that you define your rules in an order that fits your requirements.\nFor example, ordering them by applicability from broad to specific:\n\n![Policy Structure](./.github/images/policy_structure.png)\n\n### Guidelines\n\nPolicies for *dtapac* must adhere to the following guidelines:\n\n1. Result MUST be named `analysis`\n2. Result MUST be an object\n3. There MUST be exactly one result named `analysis`\n    * In case of conflicting rules, use [`else`](https://www.openpolicyagent.org/docs/latest/faq/#statement-order)\n    * [Incremental definitions](https://www.openpolicyagent.org/docs/latest/policy-language/#incremental-definitions) are NOT supported\n4. If no rule is matched, an empty object MUST be returned\n    * Use `default analysis = {}` for this\n5. Policies for findings and violations MUST be in separate packages\n    * For example, use `package dtapac.finding` for findings and `package dtapac.violation` for violations\n\nHave a look at the example policies at [`./examples/policies`](./examples/policies) if you need inspiration.\n\n### Inputs\n\n#### Finding\n\nFor findings, the `input` document is structured as follows:\n\n```json\n{\n  \"component\": {},\n  \"project\": {},\n  \"vulnerability\": {}\n}\n```\n\nThe available properties of those fields are documented here:\n\n* [`component`](https://pkg.go.dev/github.com/DependencyTrack/client-go#Component)\n* [`project`](https://pkg.go.dev/github.com/DependencyTrack/client-go#Project)\n* [`vulnerability`](https://pkg.go.dev/github.com/DependencyTrack/client-go#Vulnerability)\n\nObviously not all properties are always available.\n\n##### Example\n\n```json\n{\n  \"component\": {\n    \"group\": \"com.h2database\",\n    \"isInternal\": false,\n    \"md5\": \"18c05829a03b92c0880f22a3c4d1d11d\",\n    \"name\": \"h2\",\n    \"purl\": \"pkg:maven/com.h2database/h2@1.4.200?type=jar\",\n    \"sha1\": \"f7533fe7cb8e99c87a43d325a77b4b678ad9031a\",\n    \"sha256\": \"3ad9ac4b6aae9cd9d3ac1c447465e1ed06019b851b893dd6a8d76ddb6d85bca6\",\n    \"sha512\": \"d1ed996ff57ac22ab10cfcd1831633de20be80982f127f8ab4fdd59bef37457c0882c67ae825d8070c4d9599de93e80ff3860ae9ab66f1102f3b9e8eddb4d883\",\n    \"uuid\": \"f1f6fd0a-6dbb-4aab-a1f4-9b0c21754ee8\",\n    \"version\": \"1.4.200\"\n  },\n  \"project\": {\n    \"name\": \"acme-app\",\n    \"tags\": [\n      {\n        \"name\": \"env/production\"\n      }\n    ],\n    \"uuid\": \"8f8203ab-42e0-4d86-a452-a219f5c68daf\",\n    \"version\": \"1.2.3\"\n  },\n  \"vulnerability\": {\n    \"cvssV2BaseScore\": 10,\n    \"cvssV3BaseScore\": 9.8,\n    \"description\": \"H2 Console before 2.1.210 allows remote attackers to execute arbitrary code via a jdbc:h2:mem JDBC URL containing the IGNORE_UNKNOWN_SETTINGS=TRUE;FORBID_CREATION=FALSE;INIT=RUNSCRIPT substring, a different vulnerability than CVE-2021-42392.\",\n    \"source\": \"NVD\",\n    \"uuid\": \"21d0e27a-c05f-40b8-a986-0e1c19fb288e\",\n    \"vulnId\": \"CVE-2022-23221\"\n  }\n}\n```\n\n#### Violation\n\nFor policy violations, the `input` document is structured as follows:\n\n```json\n{\n  \"component\": {},\n  \"project\": {},\n  \"policyViolation\": {}\n}\n```\n\nThe available properties of those fields are documented here:\n\n* [`component`](https://pkg.go.dev/github.com/DependencyTrack/client-go#Component)\n* [`project`](https://pkg.go.dev/github.com/DependencyTrack/client-go#Project)\n* [`policyViolation`](https://pkg.go.dev/github.com/DependencyTrack/client-go#PolicyViolation)\n\n##### Example\n\n```json\n{\n  \"component\": {\n    \"group\": \"com.h2database\",\n    \"isInternal\": false,\n    \"md5\": \"18c05829a03b92c0880f22a3c4d1d11d\",\n    \"name\": \"h2\",\n    \"purl\": \"pkg:maven/com.h2database/h2@1.4.200?type=jar\",\n    \"sha1\": \"f7533fe7cb8e99c87a43d325a77b4b678ad9031a\",\n    \"sha256\": \"3ad9ac4b6aae9cd9d3ac1c447465e1ed06019b851b893dd6a8d76ddb6d85bca6\",\n    \"sha512\": \"d1ed996ff57ac22ab10cfcd1831633de20be80982f127f8ab4fdd59bef37457c0882c67ae825d8070c4d9599de93e80ff3860ae9ab66f1102f3b9e8eddb4d883\",\n    \"uuid\": \"f1f6fd0a-6dbb-4aab-a1f4-9b0c21754ee8\",\n    \"version\": \"1.4.200\"\n  },\n  \"policyViolation\": {\n    \"uuid\": \"9e3330f7-40f6-4121-a5f2-13fc67c4e36d\",\n    \"type\": \"OPERATIONAL\",\n    \"policyCondition\": {\n      \"uuid\": \"6159e278-26f1-490c-921b-e6d3adf0ee4b\",\n      \"operator\": \"MATCHES\",\n      \"subject\": \"COORDINATES\",\n      \"value\": \"{\\\"group\\\":\\\"*\\\",\\\"name\\\":\\\"h2\\\",\\\"version\\\":\\\"*\\\"}\",\n      \"policy\": {\n        \"uuid\": \"8fc2b2fd-2535-4e45-8d73-ffc1cce0ff13\",\n        \"name\": \"ACME Policy\",\n        \"violationState\": \"FAIL\"\n      }\n    }\n  },\n  \"project\": {\n    \"name\": \"acme-app\",\n    \"tags\": [\n      {\n        \"name\": \"env/production\"\n      }\n    ],\n    \"uuid\": \"8f8203ab-42e0-4d86-a452-a219f5c68daf\",\n    \"version\": \"1.2.3\"\n  }\n}\n```\n\n### Results\n\n#### Finding\n\nA finding analysis has the same fields as in the Dependency-Track UI:\n\n```json\n{\n  \"state\": \"\",\n  \"justification\": \"\",\n  \"response\": \"\",\n  \"details\": \"\",\n  \"comment\": \"\",\n  \"suppress\": false\n}\n```\n\nYou can set all fields, or none. No field is strictly required, but it's good practice to at least provide\na `state`, and a `comment` or `justification`. \n\n##### Example\n\n```json\n{\n  \"state\": \"EXPLOITABLE\",\n  \"details\": \"Exploitable because I say so.\"\n}\n```\n\n#### Violation\n\nA violation analysis has the same fields as in the Dependency-Track UI:\n\n```json\n{\n   \"state\": \"\",\n   \"comment\": \"\",\n   \"suppress\": false\n}\n```\n\n##### Example\n\n```json\n{\n   \"state\": \"APPROVED\",\n   \"comment\": \"Bill paid me to approve all his violations.\",\n   \"suppress\": true\n}\n```\n\n## Policy Management\n\nIt is generally a good idea to keep your policies in their own Git repository.\nTreat it just like any other code in your SDLC:\n\n* Write tests\n* Create pull requests\n* Perform code reviews\n* Have a CI pipeline\n\nIn your policy CI pipeline, you should:\n\n* [Check](https://www.openpolicyagent.org/docs/latest/cli/#opa-check) your policies using [strict mode](https://www.openpolicyagent.org/docs/latest/strict/) and [schemas](https://www.openpolicyagent.org/docs/latest/schemas/)\n    * You can use the input schemas in [`./examples/schemas`](./examples/policies)\n    * If you want to write your own schemas, be aware of the [limitations](https://www.openpolicyagent.org/docs/latest/schemas/#limitations)\n* [Test](https://www.openpolicyagent.org/docs/latest/policy-testing/) your policies\n* Package your policies into a [bundle](https://www.openpolicyagent.org/docs/latest/management-bundles/#bundle-file-format)\n    * Always set a `revision` (using the Git commit hash makes sense)\n* (Optional) Push the bundle to a server [compatible](https://www.openpolicyagent.org/docs/latest/management-bundles/#implementations) with OPA's bundle API\n\nCheck out the [Policy CI](./.github/workflows/policy-ci.yml) workflow if you need some inspiration.\n\n## Deployment\n\nA quick walk through for how to deploy *dtapac* with OPA and NGINX as bundle server.\nWe're going to use Docker Compose with [`examples/deployment/with-bundleserver/docker-compose.yml`](./examples/deployment/with-bundleserver/docker-compose.yml) \nhere. Adapt to your existing Dependency-Track deployment as necessary.\n\n### Preparation\n\nPull images for Dependency-Track, OPA and NGINX, and build the *dtapac* image:\n\n```shell\ndocker-compose -f ./examples/deployment/with-bundleserver/docker-compose.yml pull\ndocker-compose -f ./examples/deployment/with-bundleserver/docker-compose.yml build --pull\n```\n\nLaunch Dependency-Track:\n\n```shell\ndocker-compose -f ./examples/deployment/with-bundleserver/docker-compose.yml up -d dtrack\n```\n\nNavigate to `http://localhost:8080` and perform the usual setup.\n\n### Get an API key\n\nFor *dtapac* to be able to use the Dependency-Track API, it needs an API key\nwith the following permissions:\n\n| Permission                  | Reason                              |\n|:----------------------------|:------------------------------------|\n| `VIEW_PORTFOLIO`            | Fetch project + component info      |\n| `VIEW_VULNERABILITY`        | Fetch findings + vulnerability info |\n| `VULNERABILITY_ANALYSIS`    | Apply analyses to findings          |\n| `VULNERABILITY_MANAGEMENT`  | Fetch vulnerability info            |\n| `VIEW_POLICY_VIOLATION`     | Fetch policy violations             |\n| `POLICY_VIOLATION_ANALYSIS` | Apply analyses to policy violations |\n\nIt's recommended to create a dedicated team for *dtapac*, like so:\n\n![Team Permissions](./.github/images/deploy_team.png)\n\n### Setup dtapac\n\nProvide the API key to *dtapac* via `DTRACK_APIKEY` environment variable:\n\n```yaml\n# docker-compose.yml\n\nservices:\n  # ...\n  dtapac:\n    # ...\n    environment:\n      # ...\n      DTRACK_APIKEY: \"apiKeyFromAbove\"\n```\n\nLaunch *dtapac*:\n\n```shell\ndocker-compose -f ./examples/deployment/with-bundleserver/docker-compose.yml up -d dtapac\n```\n\n### Setup OPA\n\nCreate a policy bundle from the [example policies](./examples/policies):\n\n```shell\nmake build-example-bundle\n```\n\nThe bundle will be created in [`examples/bundles`](./examples/bundles) as `dtapac.tar.gz`.\nThe `bundles` directory is mounted into the NGINX container, so that it can be served to OPA.\n\nLaunch OPA and NGINX:\n\n```shell\ndocker-compose -f ./examples/deployment/with-bundleserver/docker-compose.yml up -d opa\n```\n\nVerify that OPA successfully fetched the bundle by inspecting its logs:\n\n```shell\ndocker-compose -f ./examples/deployment/with-bundleserver/docker-compose.yml logs opa\n```\n\nYou should see a log entry that says something along the lines of:\n\n```json\n{\"level\":\"info\",\"msg\":\"Bundle loaded and activated successfully. Etag updated to \\\"628fc22c-31b\\\".\",\"name\":\"dtapac\",\"plugin\":\"bundle\",\"time\":\"2022-06-22T20:48:56Z\"}\n```\n\nStarting OPA should've also triggered a portfolio analysis in *dtapac*. Verify by inspecting its logs:\n\n```shell\ndocker-compose -f ./examples/deployment/with-bundleserver/docker-compose.yml logs -f dtapac\n```\n\nYou should see something along the lines of:\n\n```\nwith-bundleserver-dtapac-1  | 8:54PM INF bundle update detected bundle=dtapac revision=1f96e28d4d3f81e3e89889cafff81a06a074c644 svc=bundleWatcher\nwith-bundleserver-dtapac-1  | 8:54PM INF starting portfolio analysis svc=portfolioAnalyzer\nwith-bundleserver-dtapac-1  | 8:54PM DBG fetching projects svc=portfolioAnalyzer\n...\n```\n\n### Set up a webhook\n\nCreate a new alert with scope `Portfolio` and publisher `Outbound Webhook`:\n\n![Create Alert](./.github/images/deploy_create-alert.png)\n\nPoint the destination to *dtapac*'s `/api/v1/dtrack/notification` endpoint and enable the\n`NEW_VULNERABILITY` and `POLICY_VIOLATION` groups:\n\n![Configure Alert](./.github/images/deploy_alert.png)\n\nGoes without saying that you should use a domain or hostname that is reach- and resolvable by\nyour Dependency-Track instance.\n\n### Testing\n\nThe example policy for findings contains a rule that will suppress all [h2](https://h2database.com/html/main.html) \nvulnerabilities for projects with name `Flux Capacitor` or `Mr. Robot`. So let's test that, shall we?\n\nDependency-Track v4.4.2 ships with a vulnerable h2 version.\n\n1. Download the BOM from [here](https://github.com/DependencyTrack/dependency-track/releases/download/4.4.2/bom.json)\n2. In Dependency-Track, create a new project named `Flux Capacitor`, version doesn't matter\n3. Upload the BOM you just downloaded\n4. In a terminal, follow the logs of *dtapac*\n5. Wait for a moment until Dependency-Track finishes its BOM analysis\n\n*dtapac*'s logs should indicate that analyses for h2 related vulnerabilities have been applied, while others\nare not covered by the policy:\n\n```\nwith-bundleserver-dtapac-1  | 9:12PM DBG auditing finding finding={\"component\":\"8dad0438-00b7-4250-8409-d8e1008e37bc\",\"project\":\"21790356-27e4-4ffb-837f-a25afdfdf0ff\",\"vulnerability\":\"e10e283b-8ade-4e86-8697-3687e3af8b92\"} svc=auditor\nwith-bundleserver-dtapac-1  | 9:12PM DBG auditing finding finding={\"component\":\"8dad0438-00b7-4250-8409-d8e1008e37bc\",\"project\":\"21790356-27e4-4ffb-837f-a25afdfdf0ff\",\"vulnerability\":\"9b93e587-e438-4cc1-aa16-f70618e6f839\"} svc=auditor\nwith-bundleserver-dtapac-1  | 9:12PM DBG received finding analysis analysis={\"comment\":\"\",\"details\":\"h2 is only used in unit tests.\",\"justification\":\"CODE_NOT_REACHABLE\",\"response\":\"\",\"state\":\"NOT_AFFECTED\",\"suppress\":true} svc=auditor\nwith-bundleserver-dtapac-1  | 9:12PM DBG received finding analysis analysis={\"comment\":\"\",\"details\":\"h2 is only used in unit tests.\",\"justification\":\"CODE_NOT_REACHABLE\",\"response\":\"\",\"state\":\"NOT_AFFECTED\",\"suppress\":true} svc=auditor\nwith-bundleserver-dtapac-1  | 9:12PM INF applying analysis component=8dad0438-00b7-4250-8409-d8e1008e37bc project=21790356-27e4-4ffb-837f-a25afdfdf0ff svc=applier vulnerability=e10e283b-8ade-4e86-8697-3687e3af8b92\nwith-bundleserver-dtapac-1  | 9:12PM DBG auditing finding finding={\"component\":\"64623e22-0bad-4dff-8105-dca956745b38\",\"project\":\"21790356-27e4-4ffb-837f-a25afdfdf0ff\",\"vulnerability\":\"c61e52b1-30ca-4f5c-9ec1-b7fd116d4b2c\"} svc=auditor\nwith-bundleserver-dtapac-1  | 9:12PM DBG finding is not covered by policy finding={\"component\":\"64623e22-0bad-4dff-8105-dca956745b38\",\"project\":\"21790356-27e4-4ffb-837f-a25afdfdf0ff\",\"vulnerability\":\"c61e52b1-30ca-4f5c-9ec1-b7fd116d4b2c\"} svc=auditor\nwith-bundleserver-dtapac-1  | 9:12PM INF applying analysis component=8dad0438-00b7-4250-8409-d8e1008e37bc project=21790356-27e4-4ffb-837f-a25afdfdf0ff svc=applier vulnerability=9b93e587-e438-4cc1-aa16-f70618e6f839\n```\n\nVerify by inspecting the project's findings in the Dependency-Track UI (✅ the *Show suppressed findings* box):\n\n![Applied Analyses in Dependency-Track](./.github/images/test_analyses.png)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnscuro%2Fdtapac","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnscuro%2Fdtapac","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnscuro%2Fdtapac/lists"}