Overview

By default, MYDATA does not have access to any information besides information that has been supplied by an incoming event or specified in the policy (e.g., using constants). However, there are a lot of examples where this is not enough and additional information is required for a security decision. Examples might be:

  • Context: Is the user currently in his office, or traveling?

  • Directory Information: Which role does a user have?

  • Settings: Did the user enable certain privacy settings?

  • Weather: Is it currently sunny?

To solve this issue, you can register so-called Policy Information Points (PIPs). PIPs extends MYDATA by the possibility to retrieve information that are independent from the current event.

The PIP component is responsible for providing additional information to a PDP to support the decision making process. The diagram below shows how a PDP requests information from a PIP component.

pip
Figure 1. Communication between PDP and PIP

Writing your own PIP is straight-forward and follows three steps:

  • Implement the functionality you need. To this regard, a PIP can be considered as a simple function (input: function name and parameters, output: result).

  • Make your service available via a REST API so that we can use it.

  • Register it at the PMP, so that we know what it offers and where to reach it.

While you have to do the first thing on your own, the MYDATA SDK supports you in the second two steps. Depending on whether you are using Spring (Boot) or not, you have two options.

Developing a PIP without our SDK

We highly recommend to use our SDK or Spring SDK to develop PIPs. However, if you do not want to use our SDK, you can implement against your REST APIs.

REST Interface

The first thing you need to do is to provide a POST REST endpoint that takes a Json serialized PipRequest (basically containting a name and a key-value list). The content type is application/json for both request and response.

Example request

$ curl 'http://www.my-pip-example.com/mypip' -i -X POST -H 'Accept: application/json' -d '{
  "name": "getName",
  "defaultValue": {
    "value": "unknown",
    "type": "java.lang.String",
    "isComplex": false
  },
  "parameters": [
    {
      "name": "id",
      "value": {
        "value": "s123",
        "type": "java.lang.String",
        "isComplex": false
      }
    }
  ]
}'

Example response

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 12

"Hans Meyer"

Registration

Afterwards, you have to register the PIP at our management service. You can do by POST ing a Component to our Management Service. The content type is application/json for both request and response. Please note that full authentication is required, as described here. If the registration was successful, the Manganagement Service returns "true". In this case, your PIP should appear in the component overview of the Management Service.

Example request

$ curl 'https://management.ind2uce.de/ws/component' -i -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -d '{
  "id": {
    "componentType": "PIP",
    "identifier": "pipDummy1"
  },
  "urls": [
    "http://www.my-pip-example.com/mypip"
  ],
  "componentInterfaces": [
    {
      "type": "InterfaceDescription",
      "methodName": "getName",
      "returnType": "java.lang.String",
      "description": "Name magic",
      "parameters": [
        {
          "name": "id",
          "description": "Id of employee",
          "type": "java.lang.String",
          "mandatory": true
        }
      ]
    }
  ]
}'

Example response

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 4

true

Implement a PIP

You can now start to implement the functionality of the REST endpoint. However, you should make sure that the implementation is consistent with the registration step (e.g,. parameter names).

Developing a PIP with our SDK

Dependencies

    <!-- The basic IND2UCE SDK -->
    <dependency>
        <groupId>de.fraunhofer.iese.ind2uce</groupId>
        <artifactId>sdk</artifactId>
        <version>${ind2uce.version}</version>
    </dependency>

    <!-- Connectors that are used to encapsulate communication with the Managemnet Service -->
    <dependency>
        <groupId>de.fraunhofer.iese.ind2uce</groupId>
        <artifactId>connectors.rest</artifactId>
        <version>${ind2uce.version}</version>
    </dependency>

Registration

    MethodInterfaceDescription pipInterface = new MethodInterfaceDescription("getName", String.class, "Name magic", new InputParameterDescription("id", "Id of employee", String.class));
    Component c = new Component(new ComponentId("urn:component:cs4:pip:pipDummy1"), Collections.singletonList(URI.create("http://www.my-pip-example.com/mypip")), pipInterface);
    IPolicyManagementPoint managementService = ConnectorFactory.getPmpClient(URI.create("https://management.ind2uce.de"), new OAuthCredentials("cs4", "<password>", URI.create("https://management.ind2uce.de/oauth/token")));
    managementService.registerComponent(c);

Developing a PIP with our Spring SDK

If you are using Spring / Spring Boot, much of the above-mentioned is automated. Using simple annotations, our Spring SDK automatically creates REST endpoints and register them at our management service. You can follow the following tutorial to create your own PIP in minutes.

Dependencies

In addition to spring-boot-starter-web dependencies, the following dependencies have to be included in the pom.xml or gradle file.

    <!-- The basic IND2UCE SDK -->
    <dependency>
        <groupId>de.fraunhofer.iese.ind2uce</groupId>
        <artifactId>sdk</artifactId>
        <version>${ind2uce.version}</version>
    </dependency>

    <!-- The IND2UCE SDK with Spring Support-->
    <dependency>
        <groupId>de.fraunhofer.iese.ind2uce</groupId>
        <artifactId>sdk.spring</artifactId>
        <version>${ind2uce.version}</version>
    </dependency>

    <!-- Connectors that are used to encapsulate communication with the Managemnet Service -->
    <dependency>
        <groupId>de.fraunhofer.iese.ind2uce</groupId>
        <artifactId>connectors.rest</artifactId>
        <version>${ind2uce.version}</version>
    </dependency>

Basic Configuration

MYDATA uses the default spring autoconfiguration support to configure the PIP registration. Therefore, the following properties must be declared in the application.properties (or application.yml respectively).

ind2uce.pmpUri= https://management.ind2uce.de/ws
ind2uce.externalServerUrl= https://my-service-example.com
ind2uce.component.path= ind2uce
ind2uce.es-id= urn:es:cs4
ind2uce.es-type= urn:es-type:cs4
endpoints.enabled=false

Each property is described in the table below :

Table 1. application properties

ind2uce.component.path

The common url-path used in RestController which is serving PIP requests.

ind2uce.pmpUri

The URI of the PolicyManagementPoint to connect to.

ind2uce.es-id

Id of the enforcement scope this PIP belongs to.

ind2uce.es-type

Enforcement Type

ind2uce.externalServerUrl

URL used to reach the PIP from PMP Service. This URL can be used if PIP and PMP have been deployed to different domains/subnets.

endpoints.enabled

As this SDK uses the Health.class provided by the Spring Framework, the actuator package is used. It is enabled by default and creates various mappings. If not needed, it should be disabled.

Enable Spring AutoConfiguration

In order to tell Spring that it shall scan the beans for PIPServices, the Spring Boot Application class or a Configuration class of the PIP should be annotated with

@EnableAutoConfiguration
@SpringBootApplication
@EnablePolicyInformationPoint
public class Application extends SpringBootServletInitializer {
...
}

The annotation @EnablePolicyInformationPoint loads the configuration to discover Beans with @PIPService.

Implement a PIP

The PIP actions can be implemented in a Spring Bean that is annotated with @PIPService. As @PIPService is a sub-annotation of @Component, Spring will handle this class as a spring bean. For each PIPService class a developer has annotated, he has to specify the following:

  • componentId which is a unique id at the PMP; the prefix should be "urn:component:<scope>:pip:<id>", such as "urn:component:cs4:pip:authority"

  • path which is the path a PDP will use to call back the PIP, e.g., authority, which will yield {ind2uce.externalServerUrl}/{ind2uce.component.path}/pip/authority

The PIPService class contains the actions the PDP should be able to call during policy evaluation. Action methods are annotated with @ActionDescription, which has the following information specified:

  • return type (mandatory)

  • methodName (only required if the method name is not the same as the name used during policy specification

  • description (optional) of the purpose of the PIP method

  • for each parameter annotated by @ActionParameterDescription, the following information is specified:

    • name (As Java drops the parameter names per default, this could not be introspected by the registration discovery)

    • description (optional) of the purpose of the parameter.

    • pattern (optional): This input should match the regex-pattern

    • mandatory (default false) if the parameter is mandatory to use this PIP. Be aware when setting parameters with primitive datatypes as optional. In that case the default value of the datatype is assigned when the function is called. Better use wrapper datatypes as Boolean for example.

Here is an example for a PIP Action Method in an PIPService:

@PIPService(componentId = "urn:component:cs4:pip:authority", path = "authority")
public class AuthorityPip {

  @Autowired
  private Repository repository;

  @ActionDescription(description = "Retrieves the authority (role) of a user")
  public String getAuthority(
        @ActionParameterDescription(name = "username", description = "The user the authority should be evaluated for.", mandatory = true) String username) {
    return repository.getRole(username);
  }
}

Providing health status data

Every PIP is able to provide data regarding its health status to the PMP. This is done by providing a method with the signature String getHealth() within the PIP implementation.

The value returned by this method should be a String containing either

  • a boolean value like "true" or "false"

  • or the JSON representation of a Spring Health.class object, that can contain much more detailed information.

This health information is exposed as a JSON response of the Spring Health.class when calling the /health method of a PIPService.

Here is an example for a PIP health status method in a PIPService:

@PIPService(componentId = "urn:component:cs4:pip:authority", path = "authority")
public class AuthorityPip {

  @Autowired
  private Repository repository;

  @ActionDescription(description = "Retrieves the authority (role) of a user")
  public String getAuthority(
        @ActionParameterDescription(name = "username", description = "The user the authority should be evaluated for.", mandatory = true) String username) {
    return repository.getRole(username);
  }

  public String getHealth() {
    return new Gson().toJson(Health.up().build());
    // or: return "true";
  }
}