Skip to content

Commit

Permalink
feature: eclipse-tractusx/traceability-foss#639 rework handling of ex…
Browse files Browse the repository at this point in the history
…pired policies
  • Loading branch information
ds-lcapellino committed Jun 11, 2024
1 parent a9077f0 commit 8ecc473
Show file tree
Hide file tree
Showing 14 changed files with 168 additions and 37 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ _**For better traceability add the corresponding GitHub issue number in each cha
- Added missing @context values in edc asset creation. eclipse-tractusx/traceability-foss#978
- Switch to `dct:type` `https://w3id.org/catenax/taxonomy#` for notification asset creation. eclipse-tractusx/traceability-foss#978
- Shells in Job response will contain all submodel descriptors returned by provider, instead filtered by aspect-type parameter. #510
- Handling of expired policies when approving a notification eclipse-tractusx/traceability-foss#639

## Added

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
import org.eclipse.tractusx.irs.data.JsonParseException;
import org.eclipse.tractusx.irs.edc.client.EdcSubmodelFacade;
import org.eclipse.tractusx.irs.edc.client.exceptions.EdcClientException;
import org.eclipse.tractusx.irs.edc.client.exceptions.UsagePolicyException;
import org.eclipse.tractusx.irs.edc.client.exceptions.UsagePolicyPermissionException;
import org.eclipse.tractusx.irs.edc.client.relationships.RelationshipAspect;
import org.eclipse.tractusx.irs.registryclient.discovery.ConnectorEndpointsService;
import org.eclipse.tractusx.irs.util.JsonUtil;
Expand Down Expand Up @@ -114,7 +114,7 @@ private void processEndpoint(final Endpoint endpoint, final RelationshipAspect r
aasTransferProcess.addIdsToProcess(idsToProcess);
itemContainerBuilder.relationships(relationships);
itemContainerBuilder.bpns(getBpnsFrom(relationships));
} catch (final UsagePolicyException e) {
} catch (final UsagePolicyPermissionException e) {
log.info("Encountered usage policy exception: {}. Creating Tombstone.", e.getMessage());
itemContainerBuilder.tombstone(
Tombstone.from(itemId.getGlobalAssetId(), endpoint.getProtocolInformation().getHref(), e, 0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
import org.eclipse.tractusx.irs.data.JsonParseException;
import org.eclipse.tractusx.irs.edc.client.EdcSubmodelFacade;
import org.eclipse.tractusx.irs.edc.client.exceptions.EdcClientException;
import org.eclipse.tractusx.irs.edc.client.exceptions.UsagePolicyException;
import org.eclipse.tractusx.irs.edc.client.exceptions.UsagePolicyPermissionException;
import org.eclipse.tractusx.irs.registryclient.discovery.ConnectorEndpointsService;
import org.eclipse.tractusx.irs.semanticshub.SemanticsHubFacade;
import org.eclipse.tractusx.irs.services.validation.InvalidSchemaException;
Expand Down Expand Up @@ -142,7 +142,7 @@ private List<Submodel> getSubmodels(final SubmodelDescriptor submodelDescriptor,
itemContainerBuilder.tombstone(Tombstone.from(itemId, endpoint.getProtocolInformation().getHref(), e, 0,
ProcessStep.SCHEMA_REQUEST));
log.info("Cannot load JSON schema for validation. Creating Tombstone.");
} catch (final UsagePolicyException e) {
} catch (final UsagePolicyPermissionException e) {
log.info("Encountered usage policy exception: {}. Creating Tombstone.", e.getMessage());
itemContainerBuilder.tombstone(Tombstone.from(itemId, endpoint.getProtocolInformation().getHref(), e, 0,
ProcessStep.USAGE_POLICY_VALIDATION, e.getBusinessPartnerNumber(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
import org.eclipse.tractusx.irs.component.enums.ProcessStep;
import org.eclipse.tractusx.irs.edc.client.EdcSubmodelFacade;
import org.eclipse.tractusx.irs.edc.client.exceptions.EdcClientException;
import org.eclipse.tractusx.irs.edc.client.exceptions.UsagePolicyException;
import org.eclipse.tractusx.irs.edc.client.exceptions.UsagePolicyPermissionException;
import org.eclipse.tractusx.irs.edc.client.model.SubmodelDescriptor;
import org.eclipse.tractusx.irs.registryclient.discovery.ConnectorEndpointsService;
import org.eclipse.tractusx.irs.util.JsonUtil;
Expand Down Expand Up @@ -391,7 +391,7 @@ void shouldCatchUsagePolicyExceptionAndPutTombstone() throws EdcClientException

// when
when(submodelFacade.getSubmodelPayload(any(), any(), any(), any())).thenThrow(
new UsagePolicyException("itemId", null, businessPartnerNumber));
new UsagePolicyPermissionException("itemId", null, businessPartnerNumber));
when(connectorEndpointsService.fetchConnectorEndpoints(any())).thenReturn(List.of("connector.endpoint.nl"));
final ItemContainer result = relationshipDelegate.process(itemContainerWithShell, jobParameter(),
new AASTransferProcess(), createKey());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@
package org.eclipse.tractusx.irs.aaswrapper.job.delegate;

import static org.assertj.core.api.Assertions.assertThat;
import static org.eclipse.tractusx.irs.SemanticModelNames.SERIAL_PART_3_0_0;
import static org.eclipse.tractusx.irs.SemanticModelNames.SINGLE_LEVEL_BOM_AS_BUILT_3_0_0;
import static org.eclipse.tractusx.irs.util.TestMother.jobParameterCollectAspects;
import static org.eclipse.tractusx.irs.util.TestMother.jobParameterFilter;
import static org.eclipse.tractusx.irs.SemanticModelNames.SERIAL_PART_3_0_0;
import static org.eclipse.tractusx.irs.util.TestMother.shell;
import static org.eclipse.tractusx.irs.util.TestMother.shellDescriptor;
import static org.eclipse.tractusx.irs.SemanticModelNames.SINGLE_LEVEL_BOM_AS_BUILT_3_0_0;
import static org.eclipse.tractusx.irs.util.TestMother.submodelDescriptor;
import static org.eclipse.tractusx.irs.util.TestMother.submodelDescriptorWithDspEndpoint;
import static org.mockito.ArgumentMatchers.any;
Expand All @@ -46,7 +46,7 @@
import org.eclipse.tractusx.irs.edc.client.EdcSubmodelFacade;
import org.eclipse.tractusx.irs.edc.client.ItemNotFoundInCatalogException;
import org.eclipse.tractusx.irs.edc.client.exceptions.EdcClientException;
import org.eclipse.tractusx.irs.edc.client.exceptions.UsagePolicyException;
import org.eclipse.tractusx.irs.edc.client.exceptions.UsagePolicyPermissionException;
import org.eclipse.tractusx.irs.edc.client.model.SubmodelDescriptor;
import org.eclipse.tractusx.irs.registryclient.discovery.ConnectorEndpointsService;
import org.eclipse.tractusx.irs.semanticshub.SemanticsHubFacade;
Expand Down Expand Up @@ -152,7 +152,8 @@ void shouldCatchUsagePolicyExceptionAndPutTombstone() throws EdcClientException
"testSingleLevelBomAsBuiltEndpoint")))));

// when
when(submodelFacade.getSubmodelPayload(any(), any(), any(), any())).thenThrow(new UsagePolicyException("itemId", null, businessPartnerNumber));
when(submodelFacade.getSubmodelPayload(any(), any(), any(), any())).thenThrow(
new UsagePolicyPermissionException("itemId", null, businessPartnerNumber));
when(connectorEndpointsService.fetchConnectorEndpoints(any())).thenReturn(List.of("connector.endpoint.nl"));
final ItemContainer result = submodelDelegate.process(itemContainerShellWithTwoSubmodels,
jobParameterCollectAspects(), new AASTransferProcess(), createKey());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@
import org.eclipse.tractusx.irs.edc.client.cache.endpointdatareference.EndpointDataReferenceStatus;
import org.eclipse.tractusx.irs.edc.client.exceptions.ContractNegotiationException;
import org.eclipse.tractusx.irs.edc.client.exceptions.TransferProcessException;
import org.eclipse.tractusx.irs.edc.client.exceptions.UsagePolicyException;
import org.eclipse.tractusx.irs.edc.client.exceptions.UsagePolicyExpiredException;
import org.eclipse.tractusx.irs.edc.client.exceptions.UsagePolicyPermissionException;
import org.eclipse.tractusx.irs.edc.client.model.CatalogItem;
import org.eclipse.tractusx.irs.edc.client.model.ContractOffer;
import org.eclipse.tractusx.irs.edc.client.model.NegotiationRequest;
Expand Down Expand Up @@ -70,7 +71,8 @@ public class ContractNegotiationService {

public NegotiationResponse negotiate(final String providerConnectorUrl, final CatalogItem catalogItem,
final EndpointDataReferenceStatus endpointDataReferenceStatus, final String bpn)
throws ContractNegotiationException, UsagePolicyException, TransferProcessException {
throws ContractNegotiationException, UsagePolicyPermissionException, TransferProcessException,
UsagePolicyExpiredException {

EndpointDataReferenceStatus resultEndpointDataReferenceStatus;

Expand Down Expand Up @@ -119,12 +121,19 @@ public NegotiationResponse negotiate(final String providerConnectorUrl, final Ca
}

private CompletableFuture<NegotiationResponse> startNewNegotiation(final String providerConnectorUrl,
final CatalogItem catalogItem, final String bpn) throws UsagePolicyException {
final CatalogItem catalogItem, final String bpn)
throws UsagePolicyPermissionException, UsagePolicyExpiredException {
log.info("Staring new contract negotiation.");

if (!policyCheckerService.isValid(catalogItem.getPolicy(), bpn)) {
log.info("Policy was not allowed, canceling negotiation.");
throw new UsagePolicyException(catalogItem.getItemId(), catalogItem.getPolicy(),
log.warn("Policy was not allowed, canceling negotiation.");
throw new UsagePolicyPermissionException(catalogItem.getItemId(), catalogItem.getPolicy(),
catalogItem.getConnectorId());
}

if (policyCheckerService.isExpired(catalogItem.getPolicy(), bpn)) {
log.warn("Policy is expired, canceling negotiation.");
throw new UsagePolicyExpiredException(catalogItem.getItemId(), catalogItem.getPolicy(),
catalogItem.getConnectorId());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@
import org.eclipse.tractusx.irs.edc.client.exceptions.ContractNegotiationException;
import org.eclipse.tractusx.irs.edc.client.exceptions.EdcClientException;
import org.eclipse.tractusx.irs.edc.client.exceptions.TransferProcessException;
import org.eclipse.tractusx.irs.edc.client.exceptions.UsagePolicyException;
import org.eclipse.tractusx.irs.edc.client.exceptions.UsagePolicyExpiredException;
import org.eclipse.tractusx.irs.edc.client.exceptions.UsagePolicyPermissionException;
import org.eclipse.tractusx.irs.edc.client.model.CatalogItem;
import org.eclipse.tractusx.irs.edc.client.model.NegotiationResponse;
import org.eclipse.tractusx.irs.edc.client.model.SubmodelDescriptor;
Expand Down Expand Up @@ -318,7 +319,8 @@ private NegotiationResponse negotiateContract(final EndpointDataReferenceStatus
try {
response = contractNegotiationService.negotiate(providerWithSuffix, catalogItem,
endpointDataReferenceStatus, bpn);
} catch (TransferProcessException | UsagePolicyException | ContractNegotiationException e) {
} catch (TransferProcessException | UsagePolicyPermissionException | UsagePolicyExpiredException |
ContractNegotiationException e) {
throw new EdcClientException(("Negotiation failed for endpoint '%s', " + "tokenStatus '%s', "
+ "providerWithSuffix '%s', catalogItem '%s'").formatted(
endpointDataReferenceStatus.endpointDataReference(), endpointDataReferenceStatus.tokenStatus(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/********************************************************************************
* Copyright (c) 2022,2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
* Copyright (c) 2021,2024 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* 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.
*
* 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
********************************************************************************/
package org.eclipse.tractusx.irs.edc.client.exceptions;

import lombok.Getter;
import org.eclipse.edc.policy.model.Policy;

/**
* Usage Policy Expired Exception errors in the contract negotiation.
*/
@Getter
public class UsagePolicyExpiredException extends EdcClientException {

private final transient Policy policy;
private final String businessPartnerNumber;

public UsagePolicyExpiredException(final String itemId, final Policy policy, final String businessPartnerNumber) {
super("Consumption of asset '" + itemId
+ "' is not permitted as the required catalog offer policies are expired.");
this.policy = policy;
this.businessPartnerNumber = businessPartnerNumber;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,18 @@
import org.eclipse.edc.policy.model.Policy;

/**
* Usage Policy Exception errors in the contract negotiation.
* Usage Policy Permission Exception errors in the contract negotiation.
*/
@Getter
public class UsagePolicyException extends EdcClientException {
public class UsagePolicyPermissionException extends EdcClientException {

private final transient Policy policy;
private final String businessPartnerNumber;

public UsagePolicyException(final String itemId, final Policy policy, final String businessPartnerNumber) {
public UsagePolicyPermissionException(final String itemId, final Policy policy,
final String businessPartnerNumber) {
super("Consumption of asset '" + itemId
+ "' is not permitted as the required catalog offer policies do not comply with defined IRS policies.");
+ "' is not permitted as the required catalog offer policies do not comply with defined policies.");
this.policy = policy;
this.businessPartnerNumber = businessPartnerNumber;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,20 +44,34 @@ public class PolicyCheckerService {
private final ConstraintCheckerService constraintCheckerService;

public boolean isValid(final Policy policy, final String bpn) {
return policy.getPermissions().stream().allMatch(permission -> isValid(permission, getValidStoredPolicies(bpn)));
final List<AcceptedPolicy> validStoredPolicies = getValidStoredPolicies(bpn);
return policy.getPermissions()
.stream()
.allMatch(permission -> hasValidConstraints(permission, validStoredPolicies));
}

private boolean isValid(final Permission permission, final List<AcceptedPolicy> validStoredPolicies) {
private boolean hasValidConstraints(final Permission permission, final List<AcceptedPolicy> validStoredPolicies) {
return validStoredPolicies.stream()
.anyMatch(acceptedPolicy -> constraintCheckerService.hasAllConstraint(
acceptedPolicy.policy(), permission.getConstraints()));
}

public boolean isExpired(final Policy policy, final String bpn) {
return policy.getPermissions()
.stream()
.allMatch(permission -> hasExpiredConstraint(permission, getValidStoredPolicies(bpn)));
}

private boolean hasExpiredConstraint(final Permission permission, final List<AcceptedPolicy> validStoredPolicies) {
return validStoredPolicies.stream()
.filter(acceptedPolicy -> constraintCheckerService.hasAllConstraint(
acceptedPolicy.policy(), permission.getConstraints()))
.allMatch(
acceptedPolicy -> acceptedPolicy.validUntil().isBefore(OffsetDateTime.now()));
}

private List<AcceptedPolicy> getValidStoredPolicies(final String bpn) {
return policyStore.getAcceptedPolicies(bpn)
.stream()
.filter(p -> p.validUntil().isAfter(OffsetDateTime.now()))
.toList();
return policyStore.getAcceptedPolicies(bpn).stream().toList();
}

}
Loading

0 comments on commit 8ecc473

Please sign in to comment.