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 @@ -15,6 +15,7 @@
package org.eclipse.edc.virtualized.dataplane.cert.api;

import com.fasterxml.jackson.core.type.TypeReference;
import com.nimbusds.jwt.SignedJWT;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.HeaderParam;
import jakarta.ws.rs.POST;
Expand All @@ -26,11 +27,13 @@
import org.eclipse.edc.connector.dataplane.spi.iam.DataPlaneAuthorizationService;
import org.eclipse.edc.spi.query.QuerySpec;
import org.eclipse.edc.transaction.spi.TransactionContext;
import org.eclipse.edc.virtualized.dataplane.cert.model.ActivityItem;
import org.eclipse.edc.virtualized.dataplane.cert.model.CertMetadata;
import org.eclipse.edc.virtualized.dataplane.cert.store.CertStore;
import org.jetbrains.annotations.NotNull;

import java.io.InputStream;
import java.time.Instant;
import java.util.List;
import java.util.Map;

Expand All @@ -56,41 +59,61 @@ public CertExchangePublicController(DataPlaneAuthorizationService authorizationS
public List<CertMetadata> queryCertificates(@HeaderParam(AUTHORIZATION) String token, QuerySpec querySpec) {
return transactionContext.execute(() -> {
checkAuth(token);
return certStore.queryMetadata(querySpec);
return certStore.queryMetadata(querySpec)
// strip out the history for public API
.stream().map(ct -> new CertMetadata(ct.id(), ct.contentType(), ct.properties())).toList();
});
}

@GET
@Path("/{id}")
public Response certificateDownload(@HeaderParam(AUTHORIZATION) String token, @PathParam("id") String id) {
return transactionContext.execute(() -> {
checkAuth(token);
var subject = checkAuth(token);
var metadata = certStore.getMetadata(id);
if (metadata == null) {
return Response.status(Response.Status.NOT_FOUND).build();
}
metadata.history().add(new ActivityItem(subject, Instant.now().getEpochSecond(), "DOWNLOAD"));
certStore.updateMetadata(id, metadata);
StreamingOutput stream = output -> {
try (InputStream is = certStore.retrieve(id)) {
is.transferTo(output);
}
};


return Response.ok(stream)
.header("Content-Type", metadata.contentType())
.build();
});
}

private void checkAuth(String token) {
private String checkAuth(String token) {
if (token == null) {
throw new WebApplicationException(UNAUTHORIZED);
}

// assuming "token" is a JWT, lets parse it and extract the `sub` claim
var subject = parseJwt(token);


var sourceDataAddress = authorizationService.authorize(token, Map.of());
if (sourceDataAddress.failed()) {
throw new WebApplicationException(FORBIDDEN);

}

return subject;
}

private String parseJwt(String token) {
try {
var signedJwt = SignedJWT.parse(token);
return String.join(",", signedJwt.getJWTClaimsSet().getAudience());
} catch (Exception e) {
return null;
}
}

@NotNull
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* Copyright (c) 2026 Metaform Systems, Inc.
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Metaform Systems, Inc. - initial API and implementation
*
*/

package org.eclipse.edc.virtualized.dataplane.cert.model;

public record ActivityItem(String counterParty, Long timestampEpoch, String action) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,12 @@

package org.eclipse.edc.virtualized.dataplane.cert.model;

import java.util.List;
import java.util.Map;

public record CertMetadata(String id, String contentType, Map<String, Object> properties) {
public record CertMetadata(String id, String contentType, Map<String, Object> properties, List<ActivityItem> history) {

public CertMetadata(String id, String contentType, Map<String, Object> properties) {
this(id, contentType, properties, List.of());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,9 @@ public interface CertStore {
* @return the input stream of the certificate data
*/
InputStream retrieve(String id);

/**
* Overwrites the metadata for a given certificate with the provided metadata.
*/
void updateMetadata(String id, CertMetadata metadata);
}
Original file line number Diff line number Diff line change
Expand Up @@ -111,4 +111,16 @@ public InputStream retrieve(String id) {
}
});
}

@Override
public void updateMetadata(String id, CertMetadata metadata) {
transactionContext.execute(() -> {
try (var connection = getConnection()) {
var stmt = "UPDATE edc_certs SET metadata = ?::jsonb WHERE id = ?";
queryExecutor.execute(connection, stmt, toJson(metadata), id);
} catch (SQLException e) {
throw new EdcException(e);
}
});
}
}