def test_registration_form():
    service = Service(
        'test_service',
        '/test/test/test',
        'HTTP-SECURE-JSON',
    )
    registration_form = forms.ServiceRegistrationForm(
        provided_service=service,
        provider_system=provider_system,
        secure='CERTIFICATE',
        metadata={'dummy': 'data'},
        end_of_validity='dummy-date',
        version=0,
    )

    valid_keys = {
        'serviceDefinition',
        'serviceUri',
        'providerSystem',
        'secure',
        'interfaces',
        'metadata',
        'version',
        'endOfValidity',
    }

    assert valid_keys == registration_form.dto.keys()
def handle_orchestration_response(service_orchestration_response: Mapping) \
        -> List[Tuple[Service, ArrowheadSystem]]:
    """ Turns orchestration response into list of services """
    orchestration_response_list = service_orchestration_response['response']

    extracted_data = []
    for orchestration_response in orchestration_response_list:
        service_dto = orchestration_response
        provider_dto = service_dto['provider']

        service_definition = service_dto['service']['serviceDefinition']
        service_uri = service_dto['serviceUri']
        interface = service_dto['interfaces'][0]['interfaceName']
        system_name = provider_dto['systemName']
        address = provider_dto['address']
        port = provider_dto['port']

        service = Service(
            service_definition,
            service_uri,
            interface,
        )

        system = ArrowheadSystem(system_name, address, port, '')

        extracted_data.append((service, system))

    return extracted_data
Beispiel #3
0
    def add_provided_service(self,
                             service_definition: str = '',
                             service_uri: str = '',
                             interface: str = '',
                             provided_service: Service = None,
                             http_method: str = '',
                             view_func: Optional[Callable] = None) -> None:
        """ Add service to provider system"""
        #TODO: This method does two thing at once. It adds a service from parameters,
        # and it adds an already created service. These functionalities should be
        # separated. Or maybe not?

        if not provided_service:
            provided_service = Service(
                    service_definition,
                    service_uri,
                    interface,)

        if provided_service.service_definition not in self.provided_services.keys() and \
            callable(view_func):
            # Register service with Flask app
            self.provided_services[provided_service.service_definition] = (provided_service, view_func)
            view_func = partial(view_func, request)
            self.app.add_url_rule(rule=f'/{provided_service.service_uri}',
                                  endpoint=provided_service.service_definition,
                                  methods=[http_method],
                                  view_func=view_func)
        else:
            # TODO: Add log message when service is trying to be overwritten
            pass
Beispiel #4
0
    def provided_service(
        self,
        service_definition: str,
        service_uri: str,
        protocol: str,
        method: str,
        payload_format: str,
        access_policy: str,
    ) -> Callable:
        """
        Decorator to add a provided provided_service to the provider.
        Useful during testing, because unlike the free :code:`provided_service` decorator this one does not require subclassing :code:`ArrowheadClient`.

        Args:
            service_definition: Service definition to be stored in the provided_service registry
            service_uri: The path to the provided_service
            protocol:
            method: HTTP method required to access the provided_service

        Example::

            provider = SomeClient.create(...)

            @provider.provided_service(
                    service_definition='list_reverser',
                    service_uri='reverse',
                    protocol='http',
                    method='POST',
                    payload_format='TEXT',
                    access_policy='NOT_SECURE',
            )
            async def reverse(input: List[str]):
                return list(reversed(input))
        """

        provided_service = Service(
            service_definition,
            service_uri,
            ServiceInterface.with_access_policy(
                protocol,
                access_policy,
                payload_format,
            ),
            access_policy,
        )

        def wrapped_func(func):
            self.registration_rules.store(
                RegistrationRule(
                    provided_service,
                    self.system,
                    method,
                    func,
                ))
            return func

        return wrapped_func
Beispiel #5
0
 def __init__(self, func: Callable):
     self.service_instance = Service.make(
         service_definition,
         service_uri,
         protocol,
         access_policy,
         payload_format,
     )
     self.method = method
     self.service_definition = service_definition
     self.func = func
Beispiel #6
0
    def query_result(self, query_response):
        query_data = query_response.read_json()['serviceQueryData'][0]
        service = Service(
            query_data['serviceDefinition']['serviceDefinition'],
            query_data['serviceUri'],
            query_data['interfaces'][0]['interfaceName'],
            query_data['secure'],
            query_data['metadata'],
            query_data['version'],
        )

        system = ArrowheadSystem.from_dto(query_data['provider'])

        return service, system
Beispiel #7
0
def _extract_rule(core_service_tuple: CoreConfig, config: Dict, secure: bool) -> OrchestrationRule:
    secure_string = constants.Security.SECURE if secure else constants.Security.INSECURE
    access_policy = constants.AccessPolicy.CERTIFICATE if secure else constants.AccessPolicy.UNRESTRICTED
    interface = ServiceInterface(core_service_tuple.protocol, secure_string, core_service_tuple.payload)
    core_system = ArrowheadSystem(**config[core_service_tuple.system])
    return OrchestrationRule(
            Service(
                    core_service_tuple.service_definition,
                    core_service_tuple.uri,
                    interface,
                    access_policy,
            ),
            core_system,
            core_service_tuple.method,
    )
Beispiel #8
0
    def add_orchestration_rule(
            self,
            service_definition: str,
            method: str,
            protocol: str = '',
            access_policy: str = '',
            payload_format: str = '',
            # TODO: Should **kwargs just be orchestration_flags and preferred_providers?
            orchestration_flags: OrchestrationFlags = OrchestrationFlags.OVERRIDE_STORE,
            **kwargs,
    ) -> None:
        """
        Add orchestration rule for provided_service definition

        Args:
            service_definition: Service definition that is looked up from the orchestrator.
            method: The HTTP method given in uppercase that is used to consume the provided_service.
            access_policy: Service access policy.
        """

        requested_service = Service(
                service_definition,
                interface=ServiceInterface.with_access_policy(
                        protocol,
                        access_policy,
                        payload_format,
                ),
                access_policy=access_policy
        )

        orchestration_form = forms.OrchestrationForm.make(
                self.system,
                requested_service,
                orchestration_flags,
                **kwargs
        )

        # TODO: Add an argument for arrowhead forms in consume_service, and one for the ssl-files
        orchestration_response = self.consume_service(
                CoreServices.ORCHESTRATION.service_definition,
                json=orchestration_form.dto(),
                cert=self.cert,
        )

        rules = responses.process_orchestration(orchestration_response, method)

        for rule in rules:
            self.orchestration_rules.store(rule)
Beispiel #9
0
    async def add_orchestration_rule(  # type: ignore
            self,
            service_definition: str,
            method: str,
            protocol: str = '',
            access_policy: str = '',
            payload_format: str = '',
            orchestration_flags: OrchestrationFlags = OrchestrationFlags.OVERRIDE_STORE,
            **kwargs,
    ):
        """
        Add orchestration rule for provided_service definition

        Args:
            service_definition: Service definition that is looked up from the orchestrator.
            method: The HTTP method given in uppercase that is used to consume the provided_service.
            access_policy: Service access policy.
        """

        requested_service = Service.make(
                service_definition,
                protocol=protocol,
                access_policy=access_policy,
                payload_format=payload_format,
        )

        orchestration_form = arrowhead_client.client.core_service_forms.client.OrchestrationForm.make(
                self.system,
                requested_service,
                orchestration_flags,
                **kwargs
        )

        # TODO: Add an argument for arrowhead forms in consume_service, and one for the ssl-files
        orchestration_response = await self.consume_service(
                CoreServices.ORCHESTRATION.service_definition,
                json=orchestration_form.dto(),
                # cert=self.cert,
        )

        rules = responses.process_orchestration(orchestration_response, method)

        for rule in rules:
            self.orchestration_rules.store(rule)
def access_policy_service(request):
    claims = request.param

    consumer_private_key, consumer_public_key = generate_keys()
    consumer_cert = generate_cert(claims['cid'], consumer_private_key, consumer_public_key)
    consumer_cert_string = consumer_cert.public_bytes(
            encoding=serialization.Encoding.PEM,
    ).decode()

    service_definition = claims['sid']
    service_interface = claims['iid']

    service = Service(
            service_definition,
            'pytest/access',
            service_interface,
    )

    return service, consumer_cert_string
Beispiel #11
0
 def _initialize_event_subscription(self) -> None:
     for event_type, rule in self.event_subscription_rules.items():
         fake_service = Service(
             service_definition=f'{event_type}-{rule.uuid}',
             service_uri=rule.notify_uri,
             interface=ServiceInterface.from_str('HTTP-SECURE-JSON'),
         )
         fake_access_policy = get_access_policy(
             policy_name=constants.AccessPolicy.CERTIFICATE,
             provided_service=fake_service,
             privatekey=self.keyfile,
             authorization_key=self.auth_authentication_info)
         fake_registration_rule = RegistrationRule(
             provided_service=fake_service,
             provider_system=rule.subscriber_system,
             method='POST',
             access_policy=fake_access_policy,
             func=rule.callback,
         )
         self.provider.add_provided_service(fake_registration_rule)
def _extract_service(
        query_data: client_forms.OrchestrationResponse) -> Service:
    """ Extracts provided_service data from test_core provided_service response """
    # TODO: this code guarded against different versions of OrchestrationResponse, not sure why
    '''
    if 'serviceDefinition' in query_data.dict():
        service_definition_base = 'serviceDefinition'
    elif 'service' in query_data.dict():
        service_definition_base = 'service'
    else:
        raise ValueError
    '''

    service = Service(
        query_data.service.service_definition,
        query_data.service_uri,
        ServiceInterface.from_str(query_data.interfaces[0].interface_name),
        query_data.secure,
        query_data.metadata,
        query_data.version,
    )

    return service
def process_service_query(
        query_response: Response) -> List[Tuple[Service, ArrowheadSystem]]:
    """ Handles provided_service query responses and returns a lists of services and systems """
    # TODO: Status 400 is general for all core systems and should be put in the handler.
    if query_response.status_code == 400:
        raise errors.CoreServiceInputError(
            query_response.read_json()[constants.Misc.ERROR_MESSAGE])

    query_response_ = client_forms.ServiceQueryResponse(
        **query_response.read_json())

    service_and_system = [(Service(
        service_definition=query_result.service_definition.service_definition,
        service_uri=query_result.service_uri,
        interface=ServiceInterface.from_str(
            query_result.interfaces[0].interface_name),
        access_policy='',
        metadata=query_result.metadata,
        version=query_result.version,
    ), ArrowheadSystem(**query_result.provider.dict())) for query_result in
                          query_response_.service_query_data]

    return service_and_system
Beispiel #14
0
    def provided_service(
        self,
        service_definition: str,
        service_uri: str,
        interface: str,
        method: str,
        *func_args,
        **func_kwargs,
    ):
        """
        Decorator to add a provided service to the provider.

        Args:
            service_definition: Service definition to be stored in the service registry
            service_uri: The path to the service
            interface: Arrowhead interface string(s)
            method: HTTP method required to access the service
        """
        provided_service = Service(
            service_definition,
            service_uri,
            interface,
        )

        def wrapped_func(func):
            self._provided_services[service_definition] = (provided_service,
                                                           func)
            self.provider.add_provided_service(service_definition,
                                               service_uri,
                                               method=method,
                                               func=func,
                                               *func_args,
                                               **func_kwargs)
            return func

        return wrapped_func
Beispiel #15
0
from typing import Dict
from arrowhead_client.service import Service

#TODO: The service definition is repeated, this dict should be a custom class
# where __getitem__() looks through a list of services. Or not, I'm not sure
services: Dict[str, Service] = {
    'register':
    Service(
        service_definition='register',
        service_uri='serviceregistry/register',
        interface='HTTP-SECURE-JSON',
    ),
    'query':
    Service(
        service_definition='query',
        service_uri='serviceregistry/query',
        interface='HTTP-SECURE-JSON',
    ),
    'unregister':
    Service(
        service_definition='unregister',
        service_uri='serviceregistry/unregister',
        interface='HTTP-SECURE-TEXT',
    )
}
setup_client = SyncClient.create(
        system_name='sysop',
        address='127.0.0.1',
        port=1337,
        keyfile='certificates/crypto/sysop.key',
        certfile='certificates/crypto/sysop.crt',
        cafile='certificates/crypto/sysop.ca'
)

print('Setting up local cloud')

setup_client.orchestration_rules.store(
        OrchestrationRule(
                Service(
                        'mgmt_register_service',
                        'serviceregistry/mgmt',
                        ServiceInterface.from_str('HTTP-SECURE-JSON'),
                ),
                ArrowheadSystem(
                        **default_config['service_registry']
                ),
                'POST',
        )
)

setup_client.orchestration_rules.store(
        OrchestrationRule(
                Service(
                        'mgmt_get_systems',
                        'serviceregistry/mgmt/systems',
                        ServiceInterface('HTTP', 'SECURE', 'JSON'),
Beispiel #17
0
from typing import Dict
from copy import deepcopy
from arrowhead_client.service import Service

_http_core_services: Dict[str, Service] = {
    'register': Service(
            service_definition='register',
            service_uri='serviceregistry/register',
            interface='HTTP-SECURE-JSON', ),
    'query': Service(
            service_definition='query',
            service_uri='serviceregistry/query',
            interface='HTTP-SECURE-JSON', ),
    'unregister': Service(
            service_definition='unregister',
            service_uri='serviceregistry/unregister',
            interface='HTTP-SECURE-TEXT', ),
    'orchestration-service': Service(
            service_definition='orchestration-service',
            service_uri='orchestrator/orchestration',
            interface='HTTP-SECURE-JSON', )
}


def core_service(service_defintion: str) -> Service:
    core_service_instance = deepcopy(_http_core_services.get(service_defintion, None))

    if not core_service_instance:
        raise ValueError(f'Core service \'{service_defintion}\' not found, '
                         f'available core services are {list(_http_core_services.keys())}')
Beispiel #18
0
from arrowhead_client.system import ArrowheadSystem
from arrowhead_client.service import Service, ServiceInterface
from arrowhead_client.rules import OrchestrationRule, OrchestrationRuleContainer

provider_system = ArrowheadSystem.make('test', '127.0.0.1', 1337, '')
consumed_service = Service(
    'test',
    'test',
    ServiceInterface('HTTP', 'SECURE', 'JSON'),
    metadata={'dummy': 'data'},
)
method = 'GET'
authorization_token = 'token.token.token'


def test_orchestration_rule():
    rule = OrchestrationRule(consumed_service, provider_system, method,
                             authorization_token)

    assert rule.service_definition == consumed_service.service_definition
    assert rule.protocol == consumed_service.interface.protocol
    assert rule.secure == consumed_service.interface.secure
    assert rule.payload_type == consumed_service.interface.payload
    assert rule.access_policy == consumed_service.access_policy
    assert rule.metadata == consumed_service.metadata
    assert rule.version == consumed_service.version
    assert rule.system_name == provider_system.system_name
    assert rule.endpoint == f'{provider_system.authority}/{consumed_service.service_uri}'
    assert rule.authentication_info == provider_system.authentication_info
    assert rule.method == method
    assert rule.authorization_token == authorization_token
Beispiel #19
0
from typing import Dict
from arrowhead_client.service import Service

services: Dict[str, Service] = {
    'orchestration-service':
    Service(
        service_definition='orchestration-service',
        service_uri='orchestrator/orchestration',
        interface='HTTP-SECURE-JSON',
    )
}
Beispiel #20
0
from arrowhead_client.system import ArrowheadSystem
from arrowhead_client.service import Service, ServiceInterface
from arrowhead_client.constants import OrchestrationFlags
import arrowhead_client.client.core_service_forms.client as forms

requester_system = ArrowheadSystem.make('test_system', 'localhost', 0)
provider_system = ArrowheadSystem.make('test_system', 'localhost', 0)
provided_service = Service(
    service_definition='test_service',
    service_uri='/test/test/test',
    interface=ServiceInterface('HTTP', 'SECURE', 'JSON'),
    access_policy='CERTIFICATE',
    metadata={'dummy': 'data'},
    version=0,
)


def test_registration_form():
    registration_form = forms.ServiceRegistrationForm.make(
        provided_service=provided_service,
        provider_system=provider_system,
        end_of_validity='dummy-date',
    )

    valid_keys = {
        'serviceDefinition',
        'serviceUri',
        'providerSystem',
        'secure',
        'interfaces',
        'metadata',