Skip to content

Commit

Permalink
Merge pull request #232 from FraunhoferISST/feat/checkframeworkpolicy
Browse files Browse the repository at this point in the history
Feat/checkframeworkpolicy
  • Loading branch information
tom-rm-meyer-ISST authored Feb 5, 2024
2 parents 5847ff6 + eb82283 commit 677b2eb
Show file tree
Hide file tree
Showing 2 changed files with 132 additions and 85 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,29 +27,21 @@ public enum DT_ApiMethodEnum {
/**
* API is used to perform a request (Request API).
*/
REQUEST("Asset to request stock information", "request",
"ItemStockRequestApi", "data.res.itemStockRequestApi", "Item Stock Request Status API Endpoint"),
REQUEST("ItemStockRequestApi", "data.res.itemStockRequestApi", "Item Stock Request Status API Endpoint"),

/**
* API is used to respond to a request (Response API).
*/
RESPONSE("Asset to receive stock information", "response",
"ItemStockResponseApi", "data.res.itemStockResponseApi", "Item Stock Response API Endpoint"),
RESPONSE("ItemStockResponseApi", "data.res.itemStockResponseApi", "Item Stock Response API Endpoint"),

STATUS_REQUEST("Asset to receive status requests regarding a previous request", "status-request",
"ItemStockRequestStatusApi", "data.res.itemStockRequestStatusApi", "Item Stock Request Status API Endpoint");
STATUS_REQUEST("ItemStockRequestStatusApi", "data.res.itemStockRequestStatusApi", "Item Stock Request Status API Endpoint");

private DT_ApiMethodEnum(String name, String purpose, String cxTaxo, String type, String description) {
this.NAME = name;
this.PURPOSE = purpose;
private DT_ApiMethodEnum(String cxTaxo, String type, String description) {
this.CX_TAXO = cxTaxo;
this.TYPE = type;
this.DESCRIPTION = description;
}


public final String NAME;
public final String PURPOSE;
public final String CX_TAXO;
public final String TYPE;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ public EdcAdapterService(ObjectMapper objectMapper) {
* Util method for issuing a GET request to the management api of your control plane.
* Any caller of this method has the responsibility to close
* the returned Response object after using it.
*
* @param pathSegments The path segments
* @return The response
* @throws IOException If the connection to your control plane fails
Expand All @@ -80,6 +81,7 @@ public Response sendGetRequest(List<String> pathSegments) throws IOException {
* Util method for issuing a POST request to the management api of your control plane.
* Any caller of this method has the responsibility to close
* the returned Response object after using it.
*
* @param requestBody The request body
* @param pathSegments The path segments
* @return The response from your control plane
Expand Down Expand Up @@ -113,9 +115,9 @@ public boolean registerAssetsInitially() {
log.info("Registration of item-stock request api successful " + (result = registerApiAsset(DT_ApiMethodEnum.REQUEST)));
if (!result) return false;
log.info("Registration of item-stock response api successful " + (result = registerApiAsset(DT_ApiMethodEnum.RESPONSE)));
if(!result) return false;
if (!result) return false;
log.info("Registration of item-stock status-request api successful " + (result = registerApiAsset(DT_ApiMethodEnum.STATUS_REQUEST)));
if(variablesService.isUseFrameworkPolicy()) {
if (variablesService.isUseFrameworkPolicy()) {
log.info("Registration of framework agreement policy successful " + (result = createFrameWorkPolicy()));
} else {
log.info("Skipping registration of framework agreement policy");
Expand All @@ -127,6 +129,7 @@ public boolean registerAssetsInitially() {
/**
* Utility method to register policy- and contract-definitions for both the
* REQUEST and the RESPONSE-Api specifically for the given partner.
*
* @param partner the partner
* @return true, if all registrations ran successfully
*/
Expand All @@ -143,7 +146,7 @@ public boolean createPolicyAndContractDefForPartner(Partner partner) {
* Prior to this method you must always have successfully completed the
* createPolicyDefinitionForPartner - method first.
*
* @param partner the partner
* @param partner the partner
* @param apiMethod the api method
* @return true, if registration ran successfully
*/
Expand All @@ -152,7 +155,7 @@ private boolean createContractDefinitionForPartner(Partner partner, DT_ApiMethod
try {
var response = sendPostRequest(body, List.of("v2", "contractdefinitions"));
boolean result = response.isSuccessful();
if(!result) {
if (!result) {
log.warn("Contract definition registration failed for partner " + partner.getBpnl() + " and "
+ apiMethod + "\n" + response.body().string());
}
Expand All @@ -175,7 +178,7 @@ private boolean createPolicyDefinitionForPartner(Partner partner) {
try {
var response = sendPostRequest(body, List.of("v2", "policydefinitions"));
boolean result = response.isSuccessful();
if(!result){
if (!result) {
log.warn("Policy Registration failed \n" + response.body().string());
}
response.body().close();
Expand All @@ -196,7 +199,7 @@ private boolean createFrameWorkPolicy() {
try {
var response = sendPostRequest(body, List.of("v2", "policydefinitions"));
boolean result = response.isSuccessful();
if(!result) {
if (!result) {
log.warn("Framework Policy Registration failed \n" + response.body().string());
}
response.body().close();
Expand Down Expand Up @@ -224,7 +227,7 @@ private boolean registerApiAsset(DT_ApiMethodEnum apiMethod) {
response.body().close();
return result;
} catch (Exception e) {
log.error("Failed to register api asset " + apiMethod.PURPOSE, e);
log.error("Failed to register api asset " + apiMethod.CX_TAXO, e);
return false;
}
}
Expand Down Expand Up @@ -391,89 +394,141 @@ public Response postProxyPullRequest(String url, String authKey, String authCode
* It will return a String array of length 4. The authKey is stored under index 0, the
* authCode under index 1, the endpoint under index 2 and the contractId under index 3.
*
* @param partner the partner
* @param apiMethod the api method
* @param partner the partner
* @param apiMethod the api method
* @return A String array or null, if negotiation or transfer have failed or the authCode did not arrive
*/
public String[] getContractForItemStockApi(Partner partner, DT_ApiMethodEnum apiMethod) {
try {
var responseNode = getCatalog(partner.getEdcUrl());
var catalogArray = responseNode.get("dcat:dataset");
// If there is exactly one asset, the catalogContent will be a JSON object.
// In all other cases catalogContent will be a JSON array.
// For the sake of uniformity we will embed a single object in an array.
if (catalogArray.isObject()) {
catalogArray = objectMapper.createArrayNode().add(catalogArray);
}
JsonNode targetCatalogEntry = null;
try {
var responseNode = getCatalog(partner.getEdcUrl());
var catalogArray = responseNode.get("dcat:dataset");
// If there is exactly one asset, the catalogContent will be a JSON object.
// In all other cases catalogContent will be a JSON array.
// For the sake of uniformity we will embed a single object in an array.
if (catalogArray.isObject()) {
catalogArray = objectMapper.createArrayNode().add(catalogArray);
}
JsonNode targetCatalogEntry = null;

for(var entry : catalogArray) {
var dctTypeObject = entry.get("dct:type");
if(dctTypeObject != null) {
if(("https://w3id.org/catenax/taxonomy#" + apiMethod.CX_TAXO).equals(dctTypeObject.get("@id").asText())) {
if(apiMethod.TYPE.equals(entry.get("asset:prop:type").asText())) {
if("1.0".equals(entry.get("https://w3id.org/catenax/ontology/common#version").asText())) {
if(targetCatalogEntry == null) {
targetCatalogEntry = entry;
for (var entry : catalogArray) {
var dctTypeObject = entry.get("dct:type");
if (dctTypeObject != null) {
if (("https://w3id.org/catenax/taxonomy#" + apiMethod.CX_TAXO).equals(dctTypeObject.get("@id").asText())) {
if (apiMethod.TYPE.equals(entry.get("asset:prop:type").asText())) {
if ("1.0".equals(entry.get("https://w3id.org/catenax/ontology/common#version").asText())) {
if (targetCatalogEntry == null) {
if (variablesService.isUseFrameworkPolicy()) {
if (testFrameworkAgreementConstraint(entry)) {
targetCatalogEntry = entry;
} else {
log.error("Contract Negotiation with partner " + partner.getBpnl() + " has " +
"been aborted. This partner's contract policy does not match the policy " +
"supported by this application. \n Supported Policy: " + variablesService.getPurisFrameworkAgreement() +
"\n Received offer from Partner: \n" + entry.toPrettyString());
break;
}
} else {
log.warn("Ambiguous catalog entries found! \n" + catalogArray.toPrettyString());
targetCatalogEntry = entry;
}
} else {
log.warn("Ambiguous catalog entries found! \n" + catalogArray.toPrettyString());
}
}
}
}
}
if(targetCatalogEntry == null) {
log.error("Could not find api asset " + apiMethod + " at partner " + partner.getBpnl() + " 's catalog");
return null;
}
String assetApiId = targetCatalogEntry.get("@id").asText();
JsonNode negotiationResponse = initiateNegotiation(partner, targetCatalogEntry);
String negotiationId = negotiationResponse.get("@id").asText();
// Await confirmation of contract and contractId
String contractId = null;
for (int i = 0; i < 100; i++) {
Thread.sleep(100);
var responseObject = getNegotiationState(negotiationId);
if ("FINALIZED".equals(responseObject.get("edc:state").asText())) {
contractId = responseObject.get("edc:contractAgreementId").asText();
break;
}
}
if (contractId == null) {
var negotiationState = getNegotiationState(negotiationId);
log.warn("no contract id, last negotiation state: \n" + negotiationState.toPrettyString());
log.error("Failed to obtain " + assetApiId + " from " + partner.getEdcUrl());
return null;
}
if (targetCatalogEntry == null) {
log.error("Could not find api asset " + apiMethod + " at partner " + partner.getBpnl() + " 's catalog");
return null;
}
String assetApiId = targetCatalogEntry.get("@id").asText();
JsonNode negotiationResponse = initiateNegotiation(partner, targetCatalogEntry);
String negotiationId = negotiationResponse.get("@id").asText();
// Await confirmation of contract and contractId
String contractId = null;
for (int i = 0; i < 100; i++) {
Thread.sleep(100);
var responseObject = getNegotiationState(negotiationId);
if ("FINALIZED".equals(responseObject.get("edc:state").asText())) {
contractId = responseObject.get("edc:contractAgreementId").asText();
break;
}
}
if (contractId == null) {
var negotiationState = getNegotiationState(negotiationId);
log.warn("no contract id, last negotiation state: \n" + negotiationState.toPrettyString());
log.error("Failed to obtain " + assetApiId + " from " + partner.getEdcUrl());
return null;
}

// Initiate transfer of edr
var transferResp = initiateProxyPullTransfer(partner, contractId, assetApiId);
String transferId = transferResp.get("@id").asText();
for (int i = 0; i < 100; i++) {
Thread.sleep(100);
transferResp = getTransferState(transferId);
if ("STARTED".equals(transferResp.get("edc:state").asText())) {
break;
}
// Initiate transfer of edr
var transferResp = initiateProxyPullTransfer(partner, contractId, assetApiId);
String transferId = transferResp.get("@id").asText();
for (int i = 0; i < 100; i++) {
Thread.sleep(100);
transferResp = getTransferState(transferId);
if ("STARTED".equals(transferResp.get("edc:state").asText())) {
break;
}
}

// Await arrival of edr
for (int i = 0; i < 100; i++) {
Thread.sleep(100);
EDR_Dto edr_Dto = edrService.findByTransferId(transferId);
if (edr_Dto != null) {
log.info("Successfully negotiated for " + assetApiId + " with " + partner.getEdcUrl());
return new String[]{edr_Dto.authKey(), edr_Dto.authCode(), edr_Dto.endpoint(), contractId};
}
// Await arrival of edr
for (int i = 0; i < 100; i++) {
Thread.sleep(100);
EDR_Dto edr_Dto = edrService.findByTransferId(transferId);
if (edr_Dto != null) {
log.info("Successfully negotiated for " + assetApiId + " with " + partner.getEdcUrl());
return new String[]{edr_Dto.authKey(), edr_Dto.authCode(), edr_Dto.endpoint(), contractId};
}
log.warn("did not receive authCode");
log.error("Failed to obtain " + assetApiId + " from " + partner.getEdcUrl());
return null;
}
log.warn("did not receive authCode");
log.error("Failed to obtain " + assetApiId + " from " + partner.getEdcUrl());
return null;

} catch (Exception e) {
log.error("Failed to get contract for " + apiMethod + " from " + partner.getBpnl(), e);
return null;
} catch (Exception e) {
log.error("Failed to get contract for " + apiMethod + " from " + partner.getBpnl(), e);
return null;
}
}

/**
* Helper method to check whether you and the contract offer from the other party have the
* same framework agreement policy.
*
* @param catalogEntry the catalog item containing the desired api asset
* @return true, if the policy matches yours, otherwise false
*/
private boolean testFrameworkAgreementConstraint(JsonNode catalogEntry) {
try {
var policyObject = catalogEntry.get("odrl:hasPolicy");
if (policyObject == null) {
return false;
}
var permissionObject = policyObject.get("odrl:permission");
if(permissionObject == null) {
return false;
}
var constraintObject = permissionObject.get("odrl:constraint");
if (constraintObject == null) {
return false;
}
var leftOperandObject = constraintObject.get("odrl:leftOperand");
if (!variablesService.getPurisFrameworkAgreement().equals(leftOperandObject.asText())) {
return false;
}
var operatorObject = constraintObject.get("odrl:operator");
if (!"odrl:eq".equals(operatorObject.get("@id").asText())) {
return false;
}
var rightOperandObject = constraintObject.get("odrl:rightOperand");
if (!"active".equals(rightOperandObject.asText())) {
return false;
}
} catch (Exception e) {
log.error("Failed in Framework Agreement Test ", e);
return false;
}
return true;
}
}

0 comments on commit 677b2eb

Please sign in to comment.