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
9 changes: 8 additions & 1 deletion .github/workflows/_meta-build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,20 @@ jobs:
mvn -B -Pquick -Dservices.bom.merge.skip=false package

- name: Upload Artifacts
uses: actions/upload-artifact@v4.6.2
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # tag=v4.6.2
with:
name: assembled-wars
path: |-
apiserver/target/*.jar
apiserver/target/bom.json

- name: Upload OpenAPI Spec
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # tag=v4.6.2
with:
name: openapi-spec
path: |-
api/target/classes/**/openapi.yaml

build-container:
runs-on: ubuntu-latest
timeout-minutes: 5
Expand Down
69 changes: 69 additions & 0 deletions .github/workflows/ci-openapi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# This file is part of Dependency-Track.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
# Copyright (c) OWASP Foundation. All Rights Reserved.
name: OpenAPI

on:
pull_request:
paths:
- api/src/main/openapi/**
- api/src/main/spectral/**

concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true

permissions: { }

jobs:
lint:
name: Lint
runs-on: ubuntu-latest
permissions:
checks: write
timeout-minutes: 5
steps:
- name: Checkout Repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # tag=v4.2.2
- name: Lint OpenAPI Spec
uses: stoplightio/spectral-action@577bade2d6e0eeb50528c94182a5588bf961ae8f # tag=v0.8.12
with:
spectral_ruleset: "api/src/main/spectral/ruleset.yaml"
file_glob: "api/src/main/openapi/openapi.yaml"

# TODO: Uncomment after the OpenAPI Spec is present in main.
# breaking-changes:
# name: Breaking Changes
# runs-on: ubuntu-latest
# timeout-minutes: 5
# steps:
# - name: Checkout Repository
# uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # tag=v4.2.2
# with:
# fetch-depth: 0
# - name: Prepare OpenAPI Spec Comparison
# run: |-
# cd api/src/main/resources/org/dependencytrack/api/v2
# mv openapi.yaml openapi-after.yaml
#
# git checkout ${{ github.event.pull_request.base.sha }} -- openapi.yaml
# mv openapi.yaml openapi-before.yaml
# - name: Detect Breaking Changes in OpenAPI Spec
# run: |-
# docker run -i --rm \
# -v "$(pwd)/api/src/main/resources/org/dependencytrack/api/v2:/work:ro" \
# pb33f/openapi-changes summary --no-color --no-logo \
# openapi-before.yaml openapi-after.yaml
2 changes: 1 addition & 1 deletion .mvn/maven-build-cache-config.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
</configuration>
<input>
<global>
<glob>{*.java,*.properties,*.proto,*.sql,*.xml}</glob>
<glob>{*.java,*.properties,*.proto,*.sql,*.xml,*.yaml}</glob>
<includes>
<include>src/</include>
</includes>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,24 @@

import alpine.common.logging.Logger;
import alpine.model.ApiKey;
import alpine.server.auth.ApiKeyAuthenticationService;
import alpine.server.auth.AllowApiKeyInQueryParameter;
import alpine.server.auth.ApiKeyAuthenticationService;
import alpine.server.auth.JwtAuthenticationService;
import org.glassfish.jersey.server.ContainerRequest;
import org.owasp.security.logging.SecurityMarkers;
import org.slf4j.MDC;

import jakarta.annotation.Priority;
import jakarta.ws.rs.HttpMethod;
import jakarta.ws.rs.NotAuthorizedException;
import jakarta.ws.rs.Priorities;
import jakarta.ws.rs.container.ContainerRequestContext;
import jakarta.ws.rs.container.ContainerRequestFilter;
import jakarta.ws.rs.container.ContainerResponseContext;
import jakarta.ws.rs.container.ContainerResponseFilter;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.container.ResourceInfo;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.Response;
import javax.naming.AuthenticationException;
import java.io.IOException;
import java.security.Principal;
Expand Down Expand Up @@ -79,8 +80,7 @@ public void filter(ContainerRequestContext requestContext) {
}
} catch (AuthenticationException e) {
LOGGER.info(SecurityMarkers.SECURITY_FAILURE, "Invalid API key asserted");
requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).build());
return;
throw new NotAuthorizedException(Response.status(Response.Status.UNAUTHORIZED).build());
Comment thread
sahibamittal marked this conversation as resolved.
}
}

Expand All @@ -90,13 +90,12 @@ public void filter(ContainerRequestContext requestContext) {
principal = jwtAuthService.authenticate();
} catch (AuthenticationException e) {
LOGGER.info(SecurityMarkers.SECURITY_FAILURE, "Invalid JWT asserted");
requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).build());
return;
throw new NotAuthorizedException(Response.status(Response.Status.UNAUTHORIZED).build());
}
}

if (principal == null) {
requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).build());
throw new NotAuthorizedException(Response.status(Response.Status.UNAUTHORIZED).build());
} else {
requestContext.setProperty("Principal", principal);
MDC.put("principal", principal.getName());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import org.owasp.security.logging.SecurityMarkers;

import jakarta.annotation.Priority;
import jakarta.ws.rs.ForbiddenException;
import jakarta.ws.rs.Priorities;
import jakarta.ws.rs.container.ContainerRequestContext;
import jakarta.ws.rs.container.ContainerRequestFilter;
Expand Down Expand Up @@ -62,8 +63,7 @@ public void filter(ContainerRequestContext requestContext) {
final Principal principal = (Principal) requestContext.getProperty("Principal");
if (principal == null) {
LOGGER.info(SecurityMarkers.SECURITY_FAILURE, "A request was made without the assertion of a valid user principal");
requestContext.abortWith(Response.status(Response.Status.FORBIDDEN).build());
return;
throw new ForbiddenException(Response.status(Response.Status.FORBIDDEN).build());
}

final Set<String> effectivePermissions;
Expand Down Expand Up @@ -97,7 +97,7 @@ public void filter(ContainerRequestContext requestContext) {
LOGGER.info(SecurityMarkers.SECURITY_FAILURE, "Unauthorized access attempt made by %s to %s"
.formatted(requestPrincipal, requestUri));

requestContext.abortWith(Response.status(Response.Status.FORBIDDEN).build());
throw new ForbiddenException(Response.status(Response.Status.FORBIDDEN).build());
} else {
requestContext.setProperty(EFFECTIVE_PERMISSIONS_PROPERTY, effectivePermissions);
}
Expand Down
15 changes: 15 additions & 0 deletions api/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# api

Definition of Dependency-Track's REST API, in [OpenAPI v3.0] format.

The API draws inspiration from [Zalando's RESTful API Guidelines].

Conformance to API guidelines is enforced with [spectral] in CI.
Validation may be performed locally using [`openapi-lint.sh`](../dev/scripts/openapi-lint.sh).

Interfaces and model classes are generated as part of the build using [openapi-generator].

[OpenAPI v3.0]: https://spec.openapis.org/oas/v3.0.3.html
[Zalando's RESTful API Guidelines]: https://opensource.zalando.com/restful-api-guidelines/
[openapi-generator]: https://github.com/OpenAPITools/openapi-generator
[spectral]: https://github.com/stoplightio/spectral
113 changes: 113 additions & 0 deletions api/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ This file is part of Dependency-Track.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
~
~ SPDX-License-Identifier: Apache-2.0
~ Copyright (c) OWASP Foundation. All Rights Reserved.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.dependencytrack</groupId>
<artifactId>dependency-track-parent</artifactId>
<version>5.6.0-SNAPSHOT</version>
</parent>

<artifactId>api</artifactId>
<packaging>jar</packaging>

<properties>
<project.parentBaseDir>${project.basedir}/..</project.parentBaseDir>
<checkstyle.skip>true</checkstyle.skip>
</properties>

<dependencies>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jakarta.ws.rs</groupId>
<artifactId>jakarta.ws.rs-api</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<version>7.13.0</version>
<executions>
<execution>
<id>generate-api-v2</id>
<phase>generate-sources</phase>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<addCompileSourceRoot>true</addCompileSourceRoot>
<inputSpec>${basedir}/src/main/openapi/openapi.yaml</inputSpec>
<collapsedSpec>${project.build.directory}/classes/org/dependencytrack/api/v2/openapi</collapsedSpec>
<generatorName>jaxrs-spec</generatorName>
<generateApiTests>false</generateApiTests>
<generateSupportingFiles>false</generateSupportingFiles>
<generateModelTests>false</generateModelTests>
<enablePostProcessFile>true</enablePostProcessFile>
<openapiNormalizer>REF_AS_PARENT_IN_ALLOF=true</openapiNormalizer>
<configOptions>
<apiPackage>org.dependencytrack.api.v2</apiPackage>
<modelPackage>org.dependencytrack.api.v2.model</modelPackage>
<interfaceOnly>true</interfaceOnly>
<returnResponse>true</returnResponse>
<useJakartaEe>true</useJakartaEe>
<useTags>true</useTags>
<dateLibrary>java8</dateLibrary>
<useSwaggerAnnotations>false</useSwaggerAnnotations>
<generateBuilders>true</generateBuilders>
<generatePom>false</generatePom>
<sourceFolder>.</sourceFolder>
<additionalModelTypeAnnotations>
@com.fasterxml.jackson.annotation.JsonInclude(com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL)
</additionalModelTypeAnnotations>
</configOptions>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

</project>
21 changes: 21 additions & 0 deletions api/src/main/openapi/components/parameters/page-token.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# This file is part of Dependency-Track.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
# Copyright (c) OWASP Foundation. All Rights Reserved.
name: page_token
description: Opaque token pointing to a specific position in a collection
in: query
schema:
type: string
25 changes: 25 additions & 0 deletions api/src/main/openapi/components/parameters/pagination-limit.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# This file is part of Dependency-Track.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
# Copyright (c) OWASP Foundation. All Rights Reserved.
name: limit
description: Maximum number of items to retrieve from the collection
in: query
schema:
type: integer
format: int32
minimum: 1
maximum: 1000
default: 100
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# This file is part of Dependency-Track.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
# Copyright (c) OWASP Foundation. All Rights Reserved.
description: Forbidden
content:
application/problem+json:
schema:
$ref: "../schemas/problem-details.yaml"
example:
type: about:blank
status: 409
title: Conflict
detail: The resource already exists.
Loading
Loading