Skip to content

Commit

Permalink
feat: store claims on additionalProperties (#4000)
Browse files Browse the repository at this point in the history
  • Loading branch information
paullatzelsperger authored Mar 13, 2024
1 parent b1bb675 commit 0717897
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public String name() {
@Provider(isDefault = true)
public DataPlaneAccessControlService defaultAccessControlService(ServiceExtensionContext context) {
context.getMonitor().debug("DataPlane Access Control: default implementation is used, will always return Result.success()");
return (claimToken, address, requestData) -> Result.success();
return (claimToken, address, requestData, additionalData) -> Result.success();
}

@Provider(isDefault = true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,11 @@
import static org.eclipse.edc.spi.result.Result.success;

public class DataPlaneAuthorizationServiceImpl implements DataPlaneAuthorizationService {
public static final String CLAIM_AGREEMENT_ID = "agreement_id";
public static final String CLAIM_ASSET_ID = "asset_id";
public static final String CLAIM_PROCESS_ID = "process_id";
public static final String CLAIM_FLOW_TYPE = "flow_type";
public static final String PROPERTY_AGREEMENT_ID = "agreement_id";
public static final String PROPERTY_ASSET_ID = "asset_id";
public static final String PROPERTY_PROCESS_ID = "process_id";
public static final String PROPERTY_FLOW_TYPE = "flow_type";
private static final String PROPERTY_PARTICIPANT_ID = "participant_id";
private final DataPlaneAccessTokenService accessTokenService;
private final PublicEndpointGeneratorService endpointGenerator;
private final DataPlaneAccessControlService accessControlService;
Expand All @@ -61,7 +62,13 @@ public Result<DataAddress> createEndpointDataReference(DataFlowStartMessage mess
var endpoint = endpointGenerator.generateFor(message.getSourceDataAddress());

var additionalProperties = message.getProperties().entrySet().stream().collect(toMap(Map.Entry::getKey, entry -> (Object) entry.getValue()));


additionalProperties.put(PROPERTY_AGREEMENT_ID, message.getAgreementId());
additionalProperties.put(PROPERTY_ASSET_ID, message.getAssetId());
additionalProperties.put(PROPERTY_PROCESS_ID, message.getProcessId());
additionalProperties.put(PROPERTY_FLOW_TYPE, message.getFlowType().toString());
additionalProperties.put(PROPERTY_PARTICIPANT_ID, message.getParticipantId());

return endpoint.compose(e -> accessTokenService.obtainToken(createTokenParams(message), message.getSourceDataAddress(), additionalProperties))
.compose(tokenRepresentation -> createDataAddress(tokenRepresentation, endpoint.getContent()));
}
Expand All @@ -71,7 +78,7 @@ public Result<DataAddress> authorize(String token, Map<String, Object> requestDa
var accessTokenDataResult = accessTokenService.resolve(token);

return accessTokenDataResult
.compose(atd -> accessControlService.checkAccess(atd.claimToken(), atd.dataAddress(), requestData))
.compose(atd -> accessControlService.checkAccess(atd.claimToken(), atd.dataAddress(), atd.additionalProperties(), requestData))
.map(u -> accessTokenDataResult.getContent().dataAddress());
}

Expand All @@ -94,10 +101,6 @@ private TokenParameters createTokenParams(DataFlowStartMessage message) {
.claims(JwtRegisteredClaimNames.ISSUER, ownParticipantId)
.claims(JwtRegisteredClaimNames.SUBJECT, ownParticipantId)
.claims(JwtRegisteredClaimNames.ISSUED_AT, clock.instant().toEpochMilli()) // todo: milli or second?
.claims(CLAIM_AGREEMENT_ID, message.getAgreementId())
.claims(CLAIM_ASSET_ID, message.getAssetId())
.claims(CLAIM_PROCESS_ID, message.getProcessId())
.claims(CLAIM_FLOW_TYPE, message.getFlowType().toString())
.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.SUBJECT;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyMap;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
Expand Down Expand Up @@ -76,14 +77,19 @@ void createEndpointDataReference() {
assertThat(da.getStringProperty("authorization")).isEqualTo("footoken");
});

var requiredClaims = Set.of(JWT_ID, AUDIENCE, ISSUER, SUBJECT, ISSUED_AT, "asset_id", "agreement_id", "process_id");
var requiredClaims = Set.of(JWT_ID, AUDIENCE, ISSUER, SUBJECT, ISSUED_AT);
verify(accessTokenService).obtainToken(ArgumentMatchers.assertArg(tp -> {
assertThat(tp.getClaims().keySet()).containsAll(requiredClaims);
assertThat(tp.getStringClaim(AUDIENCE)).isEqualTo(startMsg.getParticipantId());
assertThat(tp.getStringClaim(ISSUER)).isEqualTo(OWN_PARTICIPANT_ID);
assertThat(tp.getStringClaim(SUBJECT)).isEqualTo(OWN_PARTICIPANT_ID);
assertThat(tp.getClaims().get(ISSUED_AT)).isNotNull();
}), any(), anyMap());
}), any(), argThat(m ->
m.containsKey("agreement_id") &&
m.containsKey("participant_id") &&
m.containsKey("asset_id") &&
m.containsKey("process_id") &&
m.containsKey("flow_type")));
}


Expand Down Expand Up @@ -121,11 +127,11 @@ void authorize() {
when(accessTokenService.resolve(eq("foo-token"))).thenReturn(Result.success(new AccessTokenData("test-id",
claimToken,
address)));
when(accessControlService.checkAccess(eq(claimToken), eq(address), any())).thenReturn(Result.success());
when(accessControlService.checkAccess(eq(claimToken), eq(address), any(), anyMap())).thenReturn(Result.success());

assertThat(authorizationService.authorize("foo-token", Map.of())).isSucceeded();
verify(accessTokenService).resolve(eq("foo-token"));
verify(accessControlService).checkAccess(eq(claimToken), eq(address), any());
verify(accessControlService).checkAccess(eq(claimToken), eq(address), any(), anyMap());
verifyNoMoreInteractions(accessTokenService, accessControlService);
}

Expand All @@ -146,12 +152,12 @@ void authorize_accessNotGranted() {
when(accessTokenService.resolve(eq("foo-token"))).thenReturn(Result.success(new AccessTokenData("test-id",
claimToken,
address)));
when(accessControlService.checkAccess(eq(claimToken), eq(address), any())).thenReturn(Result.failure("not granted"));
when(accessControlService.checkAccess(eq(claimToken), eq(address), any(), anyMap())).thenReturn(Result.failure("not granted"));

assertThat(authorizationService.authorize("foo-token", Map.of())).isFailed()
.detail().isEqualTo("not granted");
verify(accessTokenService).resolve(eq("foo-token"));
verify(accessControlService).checkAccess(eq(claimToken), eq(address), any());
verify(accessControlService).checkAccess(eq(claimToken), eq(address), any(), anyMap());
verifyNoMoreInteractions(accessTokenService, accessControlService);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,11 @@ public interface DataPlaneAccessControlService {
* detail to the requestor for security reasons.
* <p>
*
* @param claimToken The credential that was attached to the data request received by the data plane
* @param address The resource address of the data that is being requested
* @param requestData Additional information about the request, e.g. URL pattern, additional headers, query params, etc.
* @param claimToken The credential that was attached to the data request received by the data plane
* @param address The resource address of the data that is being requested
* @param requestData Additional information about the request, e.g. URL pattern, additional headers, query params, etc.
* @param additionalData Additional information about the claim token, such as participant ID, agreement ID, transfer process ID etc.
* @return success if access to the resource is granted, a failure otherwise.
*/
Result<Void> checkAccess(ClaimToken claimToken, DataAddress address, Map<String, Object> requestData);
Result<Void> checkAccess(ClaimToken claimToken, DataAddress address, Map<String, Object> requestData, Map<String, Object> additionalData);
}

0 comments on commit 0717897

Please sign in to comment.