Skip to content
Snippets Groups Projects
Commit 24d6af98 authored by Ahmed Osman's avatar Ahmed Osman
Browse files

add waldbesitzer to demo

parent 65180cf1
No related branches found
No related tags found
No related merge requests found
Pipeline #313315 passed
......@@ -42,14 +42,14 @@ s3ib_to_rest = {"getValueRequest": "READ", "setValueRequest": "WRITE", "createAt
class S3IBServer:
def __init__(self, access_token: str, provider: api.ModelProvider, id: str,
loop, security_id: str = None, security_enabled = False):
loop, security_id: str = None, security_enabled = False, opa_server_url="http://localhost:8181"):
self.id = id
self.provider = provider
self.loop = loop
self.broker = BrokerAMQP(access_token, "s3ibs://" + self.id, self.callback, loop)
self.serializer = AASToJsonEncoder()
self.deserializer = AASFromJsonDecoder()
self.opa = opa_api.Opa()
self.opa = opa_api.Opa(opa_server_url)
self.security_id = base64.urlsafe_b64encode(security_id.encode()).decode()
self.security_enabled = security_enabled
self.callables: dict[str, Callable] = {}
......@@ -205,6 +205,7 @@ class S3IBAsyncClient:
self.broker.create_event_queue()
self.channel_open = self.loop.create_future()
self.requests: dict[str, asyncio.Future] = {}
self.conditionals: dict[asyncio.Future, dict[str, str]] = {}
self.deserializer = AASFromJsonDecoder()
self.serializer = AASToJsonEncoder()
self.broker.connect()
......@@ -230,6 +231,14 @@ class S3IBAsyncClient:
timestamp = msg.base_msg.get("timestamp")
logger.info(f"[Event] [{topic}] [{datetime.fromtimestamp(timestamp)}] {content}")
self.requests[topic].set_result(content)
elif not self.requests.get(msg_id):
for future, attributes in self.conditionals.items():
cond = True
for attr, value in attributes.items():
if msg.base_msg.get(attr) != value:
cond = False
if cond:
future.set_result(msg.base_msg)
else:
future: asyncio.Future = self.requests.get(msg_id)
if future:
......@@ -335,4 +344,28 @@ class S3IBAsyncClient:
await reply
return reply.result()
async def sendUserMessage(self, receiver_id: str, endpoint: str, subject: str, text: str):
if not self.channel_open.done():
await self.channel_open
msg = broker_message.UserMessage()
receiver_endpoint = endpoint
my_endpoint = "s3ibs://" + self.id
msg_id = "s3i:" + str(uuid4())
msg.fillUserMessage(
sender=self.id,
receivers=[receiver_id],
message_id=msg_id,
reply_to_endpoint=my_endpoint,
subject=subject,
text=text
)
self.broker.send([receiver_endpoint], json.dumps(msg.base_msg))
return
async def awaitMessage(self, attributes: 'dict[str, str]'):
future = self.loop.create_future()
self.conditionals[future] = attributes
await future
return future.result()
......@@ -23,8 +23,8 @@ logger = logging.getLogger("broker_api")
logger.setLevel(logging.INFO)
# These are our HMI's credentials
forestmanager_hmi_id = "s3i:e8ef672c-109b-4c36-8999-f4ababa0bffc"
forestmanager_hmi_secret = "cfs2YMj2bzPIS3kDWpHYFyUKzCorAQuV"
forestmanager_hmi_id = "s3i:8a8ee1ab-63d2-42ea-92d1-1ae682a55e7a"
forestmanager_hmi_secret = "U9AkkeEXbOZNNFUYQvH5hb3WhbBGaw9a"
# The id of forstify's HMI and dz_wald is known beforehand
forstify_hmi_id = "s3i:8a8ee1ab-63d2-42ea-92d1-1ae682a55e7a"
......@@ -54,6 +54,9 @@ async def main():
# use async client to access AAS and its submodels through their REST API asynchronously
client = broker_api.S3IBAsyncClient(access_token, forestmanager_hmi_id, loop)
# await access grant from waldbesitzer
await client.awaitMessage({"text": "Authorized"})
# Speichern einer Beobachtung
beobachtung_submodel = create_beobachtung()
beobachtung_id_encoded = base64.urlsafe_b64encode(beobachtung_submodel.id.encode()).decode()
......
from basyx.aas import model
from s3i import IdentityProvider, TokenType, Directory
import asyncio
import logging
import os, sys, inspect
import base64
import broker_api
import helpers
currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
parentdir = os.path.dirname(currentdir)
sys.path.insert(0, parentdir)
sys.path.insert(0, os.path.dirname(parentdir))
from model import enums, security, utils
# print info logs to console
logger = logging.getLogger("broker_api")
logger.setLevel(logging.INFO)
# These are our HMI's credentials
forestmanager_waldbesitzer_id = "s3i:3f23c856-d252-42c9-a590-0b87d87478d4"
forestmanager_waldbesitzer_secret = "14jXsgYN3JlE31QRniN4ruMFBoVN0Uin"
# The id of forstify's HMI and dz_wald is known beforehand
forstify_hmi_id = "s3i:8a8ee1ab-63d2-42ea-92d1-1ae682a55e7a"
dzwald_id = "s3i:bc30c279-02c5-4918-a2ad-761e927214dd"
def authenticate():
idp = IdentityProvider(
grant_type="client_credentials",
client_id=forestmanager_waldbesitzer_id,
client_secret=forestmanager_waldbesitzer_secret,
)
return idp
async def main():
idp = authenticate()
access_token = idp.get_token(TokenType.ACCESS_TOKEN)
# obtain dzwald's endpoint by checking its entry within the S3I-Directory
s3i_dir = Directory("https://dir.s3i.vswf.dev/api/2/", access_token)
dzwald_dir_entry = s3i_dir.queryThingIDBased(dzwald_id)
s3ib_endpoints = [i for i in dzwald_dir_entry["attributes"]["allEndpoints"] if
i.startswith('s3ib')]
dzwald_endpoint = s3ib_endpoints[0]
# use async client to access AAS and its submodels through their REST API asynchronously
client = broker_api.S3IBAsyncClient(access_token, forestmanager_waldbesitzer_id, loop)
resource_path = "aas"
permission_receiver = forstify_hmi_id
security_sm: model.Submodel = await client.getValue(dzwald_id, dzwald_endpoint,
f"/aas/submodels/{helpers.encode_id('https://www.company.com/security')}/submodel")
access_control: model.SubmodelElementList = security_sm.get_referable("AccessControl")
new_rules = [security.AccessPermissionRule(permission_receiver,
security.PermissionKind.ALLOW,
security.Permission.READ),
security.AccessPermissionRule(permission_receiver,
security.PermissionKind.ALLOW,
security.Permission.WRITE)]
for apc in access_control:
target: model.ReferenceElement = apc.get_referable("Target")
target_path = helpers.id_short_path_from_ref(target.value)
if target_path == resource_path:
rules: model.SubmodelElementList = apc.get_referable("Rules")
for rule in rules:
user: model.Property = rule.get_referable("User")
if user.value == permission_receiver:
rules.remove_referable(rule.id_short)
utils.add_items_to_se_list(rules, new_rules)
await client.sendUserMessage(forstify_hmi_id, "s3ibs://" + forstify_hmi_id, "Authorized", "Authorized")
if __name__ == "__main__":
loop = asyncio.get_event_loop()
try:
loop.run_until_complete(main())
except KeyboardInterrupt:
loop.stop()
......@@ -3,8 +3,7 @@ import json
from enum import Enum, IntEnum
from typing import Iterable, Optional
from basyx.aas import model
from basyx.aas.model import base
from basyx.aas.model.submodel import SubmodelElement
from basyx.aas.model import Submodel, SubmodelElementCollection, SubmodelElementList
from model import utils
......@@ -20,7 +19,7 @@ class Permission(str, Enum):
WRITE = "WRITE"
class AccessPermissionRule(model.SubmodelElementCollection):
class AccessPermissionRule(SubmodelElementCollection):
def __init__(self,
user_id: str,
......@@ -28,11 +27,11 @@ class AccessPermissionRule(model.SubmodelElementCollection):
permission: Permission):
super().__init__(id_short="AccessPermissionRule")
self.add_referable(model.Property(id_short="User", value_type=model.datatypes.String, value=user_id))
self.add_referable(model.Property(id_short="PermissionKind", value_type=model.datatypes.Integer, value=permission_kind))
self.add_referable(model.Property(id_short="Permission", value_type=model.datatypes.String, value=permission))
self.add_referable(model.Property(id_short="PermissionKind", value_type=model.datatypes.Integer, value=permission_kind.value))
self.add_referable(model.Property(id_short="Permission", value_type=model.datatypes.String, value=permission.value))
class AccessPermissionCollection(model.SubmodelElementCollection):
class AccessPermissionCollection(SubmodelElementCollection):
def __init__(self,
target: model.ModelReference,
......@@ -41,7 +40,7 @@ class AccessPermissionCollection(model.SubmodelElementCollection):
id_short="AccessPermissionCollection",
)
self.add_referable(model.ReferenceElement(id_short="Target", value=target))
rules_se_list = model.SubmodelElementList(id_short="Rules", type_value_list_element=AccessPermissionRule)
rules_se_list = model.SubmodelElementList(id_short="Rules", type_value_list_element=SubmodelElementCollection)
utils.add_items_to_se_list(rules_se_list, rules)
self.add_referable(rules_se_list)
......@@ -52,14 +51,15 @@ class AccessPermissionCollection(model.SubmodelElementCollection):
rules_se_list.add_referable(i)
class AccessControl(model.SubmodelElementList):
class AccessControl(SubmodelElementList):
def __init__(self,
permissions: Optional[Iterable[AccessPermissionCollection]] = None):
super().__init__(id_short="AccessControl", type_value_list_element=AccessPermissionCollection)
super().__init__(id_short="AccessControl", type_value_list_element=SubmodelElementCollection)
utils.add_items_to_se_list(self, permissions)
class Security(model.Submodel):
class Security(Submodel):
def __init__(self,
id: model.Identifier,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment