Perform semantic extension config validation in Java#1683
Conversation
This makes JSON schemas easier to evolve and validation logic easier to modify. Signed-off-by: nscuro <nscuro@protonmail.com>
There was a problem hiding this comment.
Pull request overview
This PR introduces a semantic validation layer for extension runtime configurations in Java, complementing existing JSON-schema validation and wiring it through data sources, notification publishers, and the extensions API. It also relaxes some schema strictness to move configuration semantics into Java, and updates OpenAPI docs and tests to reflect the new error shapes.
Changes:
- Add a
RuntimeConfigValidatorAPI andInvalidRuntimeConfigExceptionhierarchy, integrate them intoRuntimeConfigSpecandRuntimeConfigMapper, and updateConfigRegistry/ConfigRegistryImpl/MockConfigRegistryto use optional runtime configs and semantic validation. - Introduce Java-based semantic validators for OSV, NVD, and GitHub vuln data source configs (e.g., enforcing required URLs and ecosystems when enabled) and wire these into both factory specs and API config update/test flows, with new 400 responses mapped via
InvalidRuntimeConfigExceptionMapper. - Adjust JSON schemas and OpenAPI for extension config endpoints to separate JSON schema errors from semantic validation errors, and extend tests (including
ExtensionsResourceTestand vuln data source factory tests) to cover the new behavior.
Reviewed changes
Copilot reviewed 31 out of 31 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| vuln-data-source/osv/src/test/java/org/dependencytrack/vulndatasource/osv/OsvVulnDataSourceTest.java | Switch OSV test WireMock server to dynamic port to avoid clashes while exercising ecosystem ZIP download behavior. |
| vuln-data-source/osv/src/main/resources/org/dependencytrack/vulndatasource/osv/OsvVulnDataSourceConfig.schema.json | Relax OSV schema (no minItems/required for ecosystems, add existingJavaType for enabled) so semantic requirements move into Java. |
| vuln-data-source/osv/src/main/java/org/dependencytrack/vulndatasource/osv/OsvVulnDataSourceFactory.java | Use RuntimeConfigSpec.of with validator enforcing dataUrl and non-empty ecosystems when enabled; switch to isEnabled() accessor. |
| vuln-data-source/nvd/src/main/resources/org/dependencytrack/vulndatasource/nvd/NvdVulnDataSourceConfig.schema.json | Relax NVD schema required fields to only enabled and annotate enabled with existingJavaType. |
| vuln-data-source/nvd/src/main/java/org/dependencytrack/vulndatasource/nvd/NvdVulnDataSourceFactory.java | Add semantic validator requiring cveFeedsUrl when enabled; add defensive null checks on injected dependencies; update enabled checks to isEnabled(). |
| vuln-data-source/github/src/main/resources/org/dependencytrack/vulndatasource/github/GitHubVulnDataSourceConfig.schema.json | Relax GitHub schema required fields to only enabled and drop schema-level then/if for apiToken; annotate enabled with existingJavaType. |
| vuln-data-source/github/src/main/java/org/dependencytrack/vulndatasource/github/GitHubVulnDataSourceFactory.java | Add semantic validator enforcing apiUrl and apiToken when enabled and switch enabled checks from getEnabled() to isEnabled(). |
| plugin/testing/src/main/java/org/dependencytrack/plugin/testing/MockConfigRegistry.java | Update mock registry to the new optional runtime-config API and to run JSON schema + semantic validation on setRuntimeConfig. |
| plugin/runtime/src/test/java/org/dependencytrack/plugin/runtime/config/RuntimeConfigMapperTest.java | Adapt tests to RuntimeConfigSpec.of and the new RuntimeConfigSchemaValidationException, and drop tests for the removed deserialize method. |
| plugin/runtime/src/main/java/org/dependencytrack/plugin/runtime/config/RuntimeConfigSchemaValidationException.java | Rename and refactor schema validation exception to extend InvalidRuntimeConfigException and carry validation messages. |
| plugin/runtime/src/main/java/org/dependencytrack/plugin/runtime/config/RuntimeConfigMapper.java | Remove JSON-string deserialize, route validation failures through RuntimeConfigSchemaValidationException, and invoke any configured RuntimeConfigValidator after schema validation. |
| plugin/api/src/main/java/org/dependencytrack/plugin/api/config/RuntimeConfigValidator.java | New SPI interface to plug in semantic validators that run after JSON schema validation. |
| plugin/api/src/main/java/org/dependencytrack/plugin/api/config/RuntimeConfigSpec.java | Extend spec to hold an optional RuntimeConfigValidator and provide of(...) factories to bind default config, schema source, and validator. |
| plugin/api/src/main/java/org/dependencytrack/plugin/api/config/InvalidRuntimeConfigException.java | New base exception for semantically invalid runtime configs, used by schema and custom validators. |
| plugin/api/src/main/java/org/dependencytrack/plugin/api/config/ConfigRegistry.java | Replace nullable runtime-config access with Optional-based APIs and provide a throwing getRuntimeConfig(Class<T>) convenience. |
| notification/publishing/src/main/java/org/dependencytrack/notification/publishing/webhook/WebhookNotificationPublisherFactory.java | Switch rule config spec construction to RuntimeConfigSpec.of(defaultConfig) to use the new API. |
| notification/publishing/src/main/java/org/dependencytrack/notification/publishing/webex/WebexNotificationPublisherFactory.java | Same as webhook: migrate rule config spec creation to RuntimeConfigSpec.of. |
| notification/publishing/src/main/java/org/dependencytrack/notification/publishing/slack/SlackNotificationPublisherFactory.java | Same as webhook: use RuntimeConfigSpec.of for rule config spec. |
| notification/publishing/src/main/java/org/dependencytrack/notification/publishing/msteams/MsTeamsNotificationPublisherFactory.java | Same as webhook: use RuntimeConfigSpec.of for rule config spec. |
| notification/publishing/src/main/java/org/dependencytrack/notification/publishing/mattermost/MattermostNotificationPublisherFactory.java | Same as webhook: use RuntimeConfigSpec.of for rule config spec. |
| notification/publishing/src/main/java/org/dependencytrack/notification/publishing/kafka/KafkaNotificationPublisherFactory.java | Same as webhook: use RuntimeConfigSpec.of for rule config spec. |
| notification/publishing/src/main/java/org/dependencytrack/notification/publishing/jira/JiraNotificationPublisherFactory.java | Same as webhook: use RuntimeConfigSpec.of for rule config spec. |
| notification/publishing/src/main/java/org/dependencytrack/notification/publishing/email/EmailNotificationPublisherFactory.java | Same as webhook: use RuntimeConfigSpec.of for rule config spec. |
| apiserver/src/test/java/org/dependencytrack/resources/v2/ExtensionsResourceTest.java | Extend tests to cover semantic validation failures (via InvalidRuntimeConfigException) on both config update and extension test endpoints, and adapt to RuntimeConfigSpec.of. |
| apiserver/src/test/java/org/dependencytrack/event/kafka/processor/VulnerabilityScanResultProcessorTest.java | Update vuln source config manipulation to use optional runtime config accessors and immutable-style withEnabled/withApiToken methods. |
| apiserver/src/main/java/org/dependencytrack/resources/v2/exception/RuntimeConfigSchemaValidationExceptionMapper.java | Point mapper at the renamed RuntimeConfigSchemaValidationException while preserving JSON-schema problem-details response shape. |
| apiserver/src/main/java/org/dependencytrack/resources/v2/exception/InvalidRuntimeConfigExceptionMapper.java | New mapper turning InvalidRuntimeConfigException (non-schema semantic failures) into generic 400 ProblemDetails responses. |
| apiserver/src/main/java/org/dependencytrack/resources/v2/ExtensionsResource.java | After schema + secret resolution, convert configs to typed objects and invoke any registered semantic validators on update and test operations. |
| apiserver/src/main/java/org/dependencytrack/plugin/PluginManager.java | Use the new optional runtime-config API when deciding whether to create default extension configs. |
| apiserver/src/main/java/org/dependencytrack/plugin/ConfigRegistryImpl.java | Implement getOptionalRuntimeConfig() using JSON schema validation, secret resolution, conversion, and optional semantic validation before returning a typed config. |
| api/src/main/openapi/paths/extension-points__name__extensions__name__config.yaml | Broaden 400 response schema for the config endpoint to allow either JSON-schema validation problem details or generic problem details, matching the new exception mappers. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Coverage summary from CodacySee diff coverage on Codacy
Coverage variation details
Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch: Diff coverage details
Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified: See your quality gate settings Change summary preferences |
Description
Performs semantic extension config validation in Java.
This makes JSON schemas easier to evolve and validation logic easier to modify.
Addressed Issue
N/A
Additional Details
N/A
Checklist
This PR fixes a defect, and I have provided tests to verify that the fix is effectiveThis PR introduces changes to the database model, and I have updated the migration changelog accordinglyThis PR introduces new or alters existing behavior, and I have updated the documentation accordingly