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

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,10 @@ public ServiceResult<ParticipantAgent> verify(ParticipantContext participantCont
var id = Optional.of(message.getProtocol())
.map(dataspaceProfileContextRegistry::getIdExtractionFunction)
.map(extractor -> extractor.apply(claimToken))
.orElseGet(() -> {
monitor.debug(() -> "Unauthorized: Cannot extract id on protocol [%s] from claims: %s.".formatted(message.getProtocol(), claimToken.getClaims()));
return null;
});
.orElse(null);

if (id == null) {
monitor.debug(() -> "Unauthorized: Cannot extract id on protocol [%s] from claims: %s.".formatted(message.getProtocol(), claimToken.getClaims()));
return ServiceResult.unauthorized("Unauthorized");
}

Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -41,31 +41,33 @@ public ConsumerOfferResolverImpl(ContractDefinitionStore contractDefinitionStore

if (parsedResult.failed()) {
return ServiceResult.badRequest(parsedResult.getFailureMessages());
} else {
var definitionId = parsedResult.getContent().definitionPart();
var contractDefinition = contractDefinitionStore.findById(definitionId);
if (contractDefinition == null) {
return ServiceResult.notFound(format("Contract definition with id %s not found", definitionId));
}

var accessPolicy = policyDefinitionStore.findById(contractDefinition.getAccessPolicyId());
if (accessPolicy == null) {
return ServiceResult.notFound(format("Policy with id %s not found", contractDefinition.getAccessPolicyId()));
}

var contractPolicy = policyDefinitionStore.findById(contractDefinition.getContractPolicyId());
if (contractPolicy == null) {
return ServiceResult.notFound(format("Policy with id %s not found", contractDefinition.getContractPolicyId()));
}

return ServiceResult.success(ValidatableConsumerOffer.Builder.newInstance()
.contractDefinition(contractDefinition)
.accessPolicy(accessPolicy.getPolicy())
.contractPolicy(contractPolicy.getPolicy())
.offerId(parsedResult.getContent())
.build());
}

var parsedOfferId = parsedResult.getContent();
var definitionId = parsedOfferId.definitionPart();
var contractDefinition = contractDefinitionStore.findById(definitionId);
if (contractDefinition == null) {
return ServiceResult.notFound(format("Contract definition with id %s not found", definitionId));
}

var accessPolicy = policyDefinitionStore.findById(contractDefinition.getAccessPolicyId());
if (accessPolicy == null) {
return ServiceResult.notFound(format("Policy with id %s not found", contractDefinition.getAccessPolicyId()));
}

var contractPolicy = policyDefinitionStore.findById(contractDefinition.getContractPolicyId());
if (contractPolicy == null) {
return ServiceResult.notFound(format("Policy with id %s not found", contractDefinition.getContractPolicyId()));
}

return ServiceResult.success(ValidatableConsumerOffer.Builder.newInstance()
.contractDefinition(contractDefinition)
.accessPolicy(accessPolicy.getPolicy())
.contractPolicy(contractPolicy.getPolicy())
.offerId(parsedOfferId)
.build());


}

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,16 @@
import org.eclipse.edc.connector.controlplane.asset.spi.index.AssetIndex;
import org.eclipse.edc.connector.controlplane.catalog.spi.policy.CatalogPolicyContext;
import org.eclipse.edc.connector.controlplane.contract.policy.PolicyEquality;
import org.eclipse.edc.connector.controlplane.contract.spi.ContractOfferId;
import org.eclipse.edc.connector.controlplane.contract.spi.policy.ContractNegotiationPolicyContext;
import org.eclipse.edc.connector.controlplane.contract.spi.policy.TransferProcessPolicyContext;
import org.eclipse.edc.connector.controlplane.contract.spi.types.agreement.ContractAgreement;
import org.eclipse.edc.connector.controlplane.contract.spi.types.negotiation.ContractNegotiation;
import org.eclipse.edc.connector.controlplane.contract.spi.types.offer.ContractOffer;
import org.eclipse.edc.connector.controlplane.contract.spi.validation.ContractValidationService;
import org.eclipse.edc.connector.controlplane.contract.spi.validation.ValidatableConsumerOffer;
import org.eclipse.edc.connector.controlplane.contract.spi.validation.ValidatedConsumerOffer;
import org.eclipse.edc.participant.spi.ParticipantAgent;
import org.eclipse.edc.policy.engine.spi.PolicyEngine;
import org.eclipse.edc.policy.model.Policy;
import org.eclipse.edc.policy.model.PolicyType;
import org.eclipse.edc.spi.query.Criterion;
import org.eclipse.edc.spi.result.Result;
import org.jetbrains.annotations.NotNull;
Expand Down Expand Up @@ -63,10 +60,36 @@ public ContractValidationServiceImpl(AssetIndex assetIndex,
}

@Override
public @NotNull Result<ValidatedConsumerOffer> validateInitialOffer(ParticipantAgent agent, ValidatableConsumerOffer consumerOffer) {
return validateInitialOffer(consumerOffer, agent)
.compose(policy -> createContractOffer(policy, consumerOffer.getOfferId()))
.map(contractOffer -> new ValidatedConsumerOffer(agent.getIdentity(), contractOffer));
public @NotNull Result<Void> validateInitialOffer(ParticipantAgent agent, ValidatableConsumerOffer consumerOffer) {
var accessPolicyResult = policyEngine.evaluate(consumerOffer.getAccessPolicy(), new CatalogPolicyContext(agent));
if (accessPolicyResult.failed()) {
return accessPolicyResult.mapFailure();
}

var target = consumerOffer.getOfferId().assetIdPart();
if (assetIndex.findById(target) == null) {
return failure("Invalid target: " + target);
}

// verify that the asset in the offer is actually in the contract definition
var testCriteria = new ArrayList<>(consumerOffer.getContractDefinition().getAssetsSelector());
testCriteria.add(new Criterion(Asset.PROPERTY_ID, "=", target));
if (assetIndex.countAssets(testCriteria) <= 0) {
return failure("Asset ID from the ContractOffer is not included in the ContractDefinition");
}

var contractOfferId = consumerOffer.getOfferId();
if (!contractOfferId.assetIdPart().equals(target)) {
return failure("Policy target %s does not match the asset ID in the contract offer %s".formatted(target, contractOfferId.assetIdPart()));
}

var contractPolicy = consumerOffer.getTargetedContractPolicy();
var contractPolicyResult = policyEngine.evaluate(contractPolicy, new ContractNegotiationPolicyContext(agent));
if (contractPolicyResult.failed()) {
return contractPolicyResult.mapFailure();
}

return Result.success();
}

@Override
Expand Down Expand Up @@ -130,34 +153,27 @@ private Result<Policy> validateInitialOffer(ValidatableConsumerOffer consumerOff
}

// verify the target asset exists
var targetAsset = assetIndex.findById(consumerOffer.getOfferId().assetIdPart());
var target = consumerOffer.getOfferId().assetIdPart();
var targetAsset = assetIndex.findById(target);
if (targetAsset == null) {
return failure("Invalid target: " + consumerOffer.getOfferId().assetIdPart());
return failure("Invalid target: " + target);
}

// verify that the asset in the offer is actually in the contract definition
var testCriteria = new ArrayList<>(consumerOffer.getContractDefinition().getAssetsSelector());
testCriteria.add(new Criterion(Asset.PROPERTY_ID, "=", consumerOffer.getOfferId().assetIdPart()));
testCriteria.add(new Criterion(Asset.PROPERTY_ID, "=", target));
if (assetIndex.countAssets(testCriteria) <= 0) {
return failure("Asset ID from the ContractOffer is not included in the ContractDefinition");
}

var contractPolicy = consumerOffer.getContractPolicy().withTarget(consumerOffer.getOfferId().assetIdPart());
var contractOfferId = consumerOffer.getOfferId();
if (!contractOfferId.assetIdPart().equals(target)) {
return failure("Policy target %s does not match the asset ID in the contract offer %s".formatted(target, contractOfferId.assetIdPart()));
}

var contractPolicy = consumerOffer.getContractPolicy().withTarget(target);
return policyEngine.evaluate(contractPolicy, new ContractNegotiationPolicyContext(agent))
.map(v -> contractPolicy);
}

@NotNull
private Result<ContractOffer> createContractOffer(Policy policy, ContractOfferId contractOfferId) {
if (!contractOfferId.assetIdPart().equals(policy.getTarget())) {
return Result.failure("Policy target %s does not match the asset ID in the contract offer %s".formatted(policy.getTarget(), contractOfferId.assetIdPart()));
}
return Result.success(ContractOffer.Builder.newInstance()
.id(contractOfferId.toString())
// we copy the policy and enforce it to be of type OFFER
.policy(policy.toBuilder().type(PolicyType.OFFER).build())
.assetId(contractOfferId.assetIdPart())
.build());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@

class ConsumerOfferResolverImplTest {

private final PolicyDefinitionStore policyStore = mock(PolicyDefinitionStore.class);
private final ContractDefinitionStore definitionStore = mock(ContractDefinitionStore.class);
private final PolicyDefinitionStore policyStore = mock();
private final ContractDefinitionStore definitionStore = mock();
private ConsumerOfferResolverImpl validatableConsumerOfferResolver;

@BeforeEach
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
import org.eclipse.edc.policy.engine.spi.PolicyContext;
import org.eclipse.edc.policy.engine.spi.PolicyEngine;
import org.eclipse.edc.policy.model.Policy;
import org.eclipse.edc.policy.model.PolicyType;
import org.eclipse.edc.spi.result.Result;
import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.BeforeEach;
Expand Down Expand Up @@ -105,12 +104,6 @@ void verifyContractOfferValidation() {
var result = validationService.validateInitialOffer(participantAgent, validatableOffer);

assertThat(result.succeeded()).isTrue();
var validatedOffer = result.getContent().getOffer();
assertThat(validatedOffer.getPolicy()).isNotSameAs(originalPolicy); // verify the returned policy is the sanitized one
assertThat(validatedOffer.getPolicy().getType()).isEqualTo(PolicyType.OFFER); // verify the returned policy is of type OFFER
assertThat(validatedOffer.getAssetId()).isEqualTo(asset.getId());

assertThat(result.getContent().getConsumerIdentity()).isEqualTo(CONSUMER_ID); // verify the returned policy has the consumer id set, essential for later validation checks

verify(assetIndex).findById("1");
verify(policyEngine).evaluate(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ public interface ContractValidationService {
*
* @param agent The {@link ParticipantAgent} of the consumer
* @param consumerOffer The initial {@link ValidatableConsumerOffer} id to validate
* @return The referenced {@link ValidatedConsumerOffer}.
* @return the validation result.
*/
@NotNull
Result<ValidatedConsumerOffer> validateInitialOffer(ParticipantAgent agent, ValidatableConsumerOffer consumerOffer);
Result<Void> validateInitialOffer(ParticipantAgent agent, ValidatableConsumerOffer consumerOffer);

/**
* Validates the contract agreement that the consumer referenced in its transfer request.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ public ContractDefinition getContractDefinition() {
return contractDefinition;
}

public Policy getTargetedContractPolicy() {
return contractPolicy.withTarget(offerId.assetIdPart());
}

public static final class Builder {

private final ValidatableConsumerOffer consumerOffer;
Expand Down

This file was deleted.

Loading