-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
14 changed files
with
972 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
|
||
name: push | ||
|
||
on: | ||
push: | ||
branches: [ "main" ] | ||
# Allows you to run this workflow manually from the Actions tab | ||
workflow_dispatch: | ||
|
||
permissions: | ||
contents: read | ||
|
||
jobs: | ||
deploy: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v2 | ||
- name: Set up Python | ||
uses: actions/setup-python@v2 | ||
with: | ||
python-version: '3.x' | ||
- name: Install dependencies | ||
run: | | ||
python -m pip install --upgrade pip | ||
pip install setuptools wheel twine | ||
- name: Build and publish | ||
env: | ||
TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }} | ||
TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} | ||
run: | | ||
python setup.py sdist bdist_wheel | ||
twine upload dist/* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
include LICENSE | ||
include README.md | ||
recursive-include *.py | ||
recursive-include *.json | ||
recursive-include *.yaml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,18 @@ | ||
# fx-python-sdk-cli | ||
# FX Python SDK with CLI | ||
|
||
Enter Provider / Consumer FX-Port details in the config files. | ||
|
||
Use CLI as provider: | ||
- Get own EDC Assets | ||
- Create EDC Asset for AAS Submodel | ||
- Create generic EDC Access policy | ||
- Create generic EDC Usage policy | ||
- Create generic EDC Contract for specific EDC Asset | ||
- Get EDC policies | ||
|
||
Use CLI as consumer: | ||
- Request EDC Assets from Provider | ||
- Request EDRS (after negotiation) | ||
- Request data (requires EDRS) | ||
- Negotiate | ||
- Get Negotiation State (to check after negotiating) |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
{ | ||
"@context": { | ||
"@vocab": "https://w3id.org/edc/v0.0.1/ns/" | ||
}, | ||
"@type": "QuerySpec", | ||
"filterExpression": [ | ||
{ | ||
"operandLeft": "assetId", | ||
"operator": "=", | ||
"operandRight": "sample_object_of_agreement" | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
{ | ||
"@context": { | ||
"@vocab": "https://w3id.org/edc/v0.0.1/ns/", | ||
"odrl": "http://www.w3.org/ns/odrl/2/", | ||
"cx-taxo": "https://w3id.org/catenax/taxonomy#" | ||
}, | ||
"@type": "CatalogRequest", | ||
"counterPartyId": "bpn_placeholder", | ||
"counterPartyAddress": "url_edc_provider_control_plane_base_placeholder", | ||
"protocol": "dataspace-protocol-http", | ||
"querySpec": { | ||
"@type": "QuerySpec", | ||
"filterExpression": [ | ||
{ | ||
"operandLeft": "'http://purl.org/dc/terms/type'.'@id'", | ||
"operator": "=", | ||
"operandRight": "https://w3id.org/catenax/taxonomy#Submodel" | ||
} | ||
] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
from consumer import * | ||
from provider import * | ||
|
||
def provider_interface(): | ||
while True: | ||
print("1: Get own EDC Assets") | ||
print("2: Create EDC Asset for AAS Submodel") | ||
print("3: Create generic EDC Access policy") | ||
print("4: Create generic EDC Usage policy") | ||
print("5: Create generic EDC Contract for specific EDC Asset") | ||
print("6: Get EDC policies") | ||
print("7: Return") | ||
choice = input("Enter your choice: ") | ||
if choice == "1": | ||
print("Getting assets...") | ||
request_own_assets() | ||
elif choice == "2": | ||
asset_id = input("Enter submodel uuid: ") | ||
print("Creating asset for...") | ||
create_edc_asset(asset_id) | ||
elif choice == "3": | ||
print("Creating access policy...") | ||
create_access_policy() | ||
elif choice == "4": | ||
print("Creating usage policy...") | ||
create_usage_policy() | ||
elif choice == "5": | ||
print("Creating contract...") | ||
edc_asset_id = input("Enter EDC asset id: ") | ||
create_contract(edc_asset_id) | ||
elif choice == "6": | ||
print("Getting policies...") | ||
get_policies() | ||
elif choice == "7": | ||
break | ||
else: | ||
print("Invalid choice. Please try again.") | ||
|
||
def client_interface(): | ||
while True: | ||
print("1: Request EDC Assets from Provider") | ||
print("2: Request EDRS (after negotiation)") | ||
print("3: Request data (requires EDRS)") | ||
print("4: Negotiate") | ||
print("5: Get Negotiation State (check after step 4)") | ||
print("6: Return") | ||
choice = input("Enter your choice: ") | ||
if choice == "1": | ||
print("Requesting assets...") | ||
request_assets_from_provider() | ||
elif choice == "2": | ||
object_of_agreement = input("Enter id of EDC asset: ") | ||
print("Requesting EDRS...") | ||
edrs = get_edrs_for_object(object_of_agreement) | ||
elif choice == "3": | ||
object_of_agreement = input("Enter id of EDC asset: ") | ||
print("Requesting data...") | ||
get_data(edrs) | ||
elif choice == "4": | ||
object_of_agreement = input("Enter id of EDC asset: ") | ||
print("Negotiating...") | ||
edr_negotation_id = negotiate(object_of_agreement) | ||
elif choice == "5": | ||
print("Getting state...") | ||
get_negotiation_state(edr_negotation_id) | ||
elif choice == "6": | ||
break | ||
else: | ||
print("Invalid choice. Please try again.") | ||
|
||
def main(): | ||
while True: | ||
print("1: Provider") | ||
print("2: Client") | ||
print("3: Exit") | ||
choice = input("Enter your choice: ") | ||
if choice == "1": | ||
provider_interface() | ||
elif choice == "2": | ||
client_interface() | ||
elif choice == "3": | ||
break | ||
else: | ||
print("Invalid choice. Please try again.") | ||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
import requests # Apache License 2.0 | ||
from requests.auth import HTTPBasicAuth | ||
|
||
import base64 # in python | ||
import yaml # MIT | ||
import json | ||
|
||
from utils import get_data_offer, offer2et, create_poc_ContractRequest_body | ||
from utils import str_edc_catalog | ||
|
||
# --- variables --- | ||
with open('consumer_cfg.yaml', 'r') as file: | ||
consumer_cfg = yaml.safe_load(file) | ||
|
||
# - control plane - | ||
url_edc_consumer_control_plane_base = consumer_cfg['consumer-edc-control-plane']['endpoint'] | ||
header_control_plane = consumer_cfg['consumer-edc-control-plane']['header'] # this contains secrets, so please use -at least- a secretsmanager instead | ||
|
||
# - "identities" - | ||
edc_provider_bpn = consumer_cfg['trusted-providers']['provider_A']['BPN'] # "{{EDCTX-10-1-BPN}}" | ||
url_edc_provider_control_plane_base = consumer_cfg['trusted-providers']['provider_A']['endpoint-control-plane'] | ||
# ------------------------------------------------------------------------------------------------------------------- | ||
object_of_agreement = 'MB-DSCS'#'simple_test' # we 'magically' know this due to the push notification | ||
|
||
def get_edrs_for_object(object_of_agreement): | ||
# see if there are some edrs which have been negotiated for | ||
# Load the JSON from the file | ||
with open('agreement_body.json', 'r') as f: | ||
loaded_agreement_body = json.load(f) | ||
|
||
# Replace the placeholder with the actual object of agreement | ||
loaded_agreement_body["filterExpression"][0]["operandRight"] = object_of_agreement | ||
|
||
res_catalog_agreement = requests.post(url=url_edc_consumer_control_plane_base + '/management/v2/edrs/request', headers=header_control_plane, json=loaded_agreement_body) | ||
#res_catalog_agreement | ||
res_offer, offer = get_data_offer(res_catalog_agreement.json()) | ||
print("Status Offer: "+ str(res_offer)) | ||
|
||
if res_offer == 0: | ||
res_et, et_dict = offer2et(offer, url_edc_consumer_control_plane_base, header_control_plane) | ||
if res_et == -2: | ||
print("Token Request Failed:" + str(et_dict)) | ||
else: | ||
print("Status Endpoint and Token: " + str(res_et)) | ||
return et_dict | ||
|
||
def get_data(et_dict): | ||
# obtain data: | ||
res_data_info = requests.get(url=et_dict['endpoint'], headers={'Authorization': et_dict['token']}) | ||
res_data_info | ||
res_data = requests.get(url=et_dict['endpoint'] + '/$value?extent=WithBlobValue', headers={'Authorization': et_dict['token']}) | ||
res_data | ||
element_id = res_data_info.json()['submodelElements'][0]['idShort'] | ||
value_enc = res_data.json()[element_id]['value'] | ||
val = res_data.json()[res_data_info.json()['submodelElements'][0]['idShort']]['value'] | ||
base64.b64decode(val).decode('utf-8') | ||
|
||
def request_assets_from_provider(): | ||
# obtain all offers from the data provider using a catalog request: | ||
# Load the JSON from the file | ||
with open('catalog_request_body', 'r') as f: | ||
loaded_catalog_request_body = json.load(f) | ||
# Replace the placeholders with actual values | ||
loaded_catalog_request_body["counterPartyId"] = edc_provider_bpn | ||
loaded_catalog_request_body["counterPartyAddress"] = url_edc_provider_control_plane_base + "/api/v1/dsp" | ||
# note: we query against our own EDC (the consumer EDC, who then will negotiate with the target EDC) | ||
res_catalog = requests.post(url=url_edc_consumer_control_plane_base + '/management/v2/catalog/request', headers=header_control_plane, json=loaded_catalog_request_body) | ||
print(str_edc_catalog(res_catalog)) | ||
return res_catalog | ||
|
||
def negotiate(object_of_agreement): | ||
### Negotiate for Asset | ||
res_catalog = request_assets_from_provider() | ||
# filter offer and endpoint | ||
for dcat_dataset in res_catalog.json()['dcat:dataset']: | ||
# look for the dataset with our id: | ||
if dcat_dataset['@id'] == object_of_agreement: | ||
asset_policy = dcat_dataset['odrl:hasPolicy'] | ||
offer_id = asset_policy['@id'] | ||
|
||
# get negotiation endpoint: dct_endpointUrl | ||
dct_endpointUrl = None | ||
for distribution_method in dcat_dataset['dcat:distribution']: | ||
if distribution_method['dct:format']['@id'] == 'HttpData-PULL': | ||
dct_endpointUrl = distribution_method['dcat:accessService']['dct:endpointUrl'] | ||
break | ||
# check if we actuall got the desired endpoint | ||
if dct_endpointUrl is not None: | ||
break | ||
|
||
# create request body for the EDR negotiate | ||
edr_negotiation_body = create_poc_ContractRequest_body(dct_endpointUrl, offer_id, edc_provider_bpn, object_of_agreement) | ||
res_edr_negotiation = requests.post(url=url_edc_consumer_control_plane_base + '/management/v2/edrs', headers=header_control_plane, json=edr_negotiation_body) | ||
#res_edr_negotiation | ||
edr_negotation_id = res_edr_negotiation.json()['@id'] | ||
return edr_negotation_id # <- necessary to get the state | ||
|
||
def get_negotiation_state(edr_negotation_id): | ||
# get the negotiation state: | ||
res_get_edr_negotiation_state = requests.get(url=url_edc_consumer_control_plane_base + '/management/v2/contractnegotiations/' + edr_negotation_id + '/state', headers=header_control_plane) | ||
res_get_edr_negotiation_state | ||
res_get_edr_negotiation_state.json() # <- this should say finalized |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
consumer-edc-control-plane: | ||
endpoint: https://your-edc-control-plane-endpoint | ||
header: | ||
Authorization: Bearer your-authorization-token | ||
|
||
trusted-providers: | ||
provider_A: | ||
BPN: your-provider-bpn | ||
endpoint-control-plane: https://your-provider-control-plane-endpoint |
Oops, something went wrong.