Everyware Software Framework Developer's Hub

Everyware Software Framework (ESF) is an enterprise-ready IoT Edge Framework distributed and supported by Eurotech. Based on Eclipse Kura, the open source Java/OSGi middleware for IoT gateways, ESF adds provisioning, advanced security, remote access, diagnostics monitoring. It supports ready-to-use field protocols (including Modbus, OPC-UA, S7), MQTT connectivity, and a web-based visual data flow programming to acquire data from the field, process it at the edge, and publish it to IoT Cloud Platforms. ESF features full remote device management through its integration with Everyware Cloud, Eurotech’s IoT Integration Platform.

Get Started

Security Policy File

The Security Policy File is an XML file that describes the behaviour of ESF in terms of bundles that can run in the framework, the resources available for every specific bundle and the development features available for debugging.

Definition

By default, the security policy file is located in this path: /opt/eurotech/esf/user/security/security.policy.

The following XML file shows the default security policy of a newly installed copy of ESF:

<?xml version="1.0" encoding="UTF-8"?>
<esf:security xmlns:esf="http://eurotech.com/esf/2.0" version="1">
  <esf:properties>
    <esf:property>
      <esf:name>permit-debug</esf:name>
      <esf:value>true</esf:value>
    </esf:property>
  </esf:properties>
  <esf:policies>
    <esf:policy>
      <esf:access>ALLOW</esf:access>
      <esf:permissions>
        <esf:permission>
          <esf:name>java.security.AllPermission</esf:name>
          <esf:values>
            <esf:value>
              *
            </esf:value>
            <esf:value>
              *
            </esf:value>
          </esf:values>
        </esf:permission>
      </esf:permissions>
      <esf:name>
        All permissions to everyone
      </esf:name>
    </esf:policy>
  </esf:policies>
</esf:security>

Various fields used to create a security policy are described in the sections that follow.

Properties Element

The properties element represents the node element where one or more property elements can be appended.

The property element is composed of a name and value element. The supported property element is shown below.

<esf:property>
  <esf:name>permit-debug</esf:name>
  <esf:value>true</esf:value>
</esf:property>

This property node contains a name string with a permit-debug value and a value element that can be one of the following:

  • true - specifies that ESF should be started in development mode

  • false - specifies that ESF should be started in production mode with all the security checks enabled

Policies Element

To be compliant with the ESF security policy definition, the policies element must contain one or more policy elements, as shown below.

<esf:policy>
  <esf:access>ALLOW</esf:access>
  <esf:permissions>
    <esf:permission>
      <esf:name>java.security.AllPermission</esf:name>
      <esf:values>
        <esf:value>
          *
        </esf:value>
        <esf:value>
          *
        </esf:value>
      </esf:values>
    </esf:permission>
  </esf:permissions>
  <esf:name>
    All permissions to everyone
  </esf:name>
</esf:policy>

Each policy element has to contain the following child elements:

  • access - required node
  • conditions - not mandatory node
  • permissions - required node
  • name - required node

Access Element

The access child element defines the access rule as ALLOW or DENY.

  • ALLOW - corresponds to the normal case of saying what is allowed
  • DENY - to say what isn’t allowed

Conditions Element

The conditions is a node that specifies the bounds of the rule: the security policy will be applied only to the bundles that match the contained condition. Each conditions node contains one or more condition elements that specify the effective condition.
The condition element contains two children elements:

  • name - specifies the name of the standard condition to be used. The OSGi standard specifies two conditions: BundleSignerCondition and BundleLocationCondition.
  • value - specifies the effective condition that has to be applied.

The BundleSignerCondition is satisfied when the related bundle is signed with a certificate that matches what in the value element.

The BundleLocationCondition matches the argument in the value element against the location of the bundle. Bundle location matching provides many of the advantages of signing without the overhead. However, using locations as the authenticator requires secure locations that cannot be spoofed.

An example of condition:

<esf:conditions>
	<esf:condition>
  	<esf:name>
    	BundleSignerCondition
    </esf:name>
    <esf:value>
    	"CN=Common Name, OU=Organization Unit, O=Organization, L=Ottawa, ST=Ontario, C=Country; CN=CA common name, OU=CA Organization Unit, O=CA Organization, C=US;-"
    </esf:value>
	</esf:condition>
</esf:conditions>

The value element is composed by two arguments: the first is a string that represents a matching Distinguished Name (DN). The second argument is optional, if used, it must be an exclamation mark (’!’). The exclamation mark indicates that the result for this condition must be reversed.

The DN value is used to match the one used to sign the bundles and can contain the description of the complete chain of certificates used to sign the bundle. Each certificate of the chain is separated from the others using a semicolon. The usage of wildcards is supported.

Order of certificates in the value element is important: reversing it indicates the opposite signing relationship.

Two wildcards are supported:

  • the star (*)
  • the hyphen (-)

The start wildcard can be used as part of the right-hand argument of an attribute, such as:

CN=*,O=Organization,C=IT

This matches all the certificates that have every common name (CN) and the correspondent Organization and Country value.

When used alone, the star wildcard matches at most one certificate. For example:

*;CN=Common Name,O=Organization,C=IT

The hyphen wildcard matches zero or more certificates.

Permissions Element

The permissions element contains one or more permission rules that are explicitly defined in the value element contained. The permission element can contain a java permission or an OSGi-related permission. This value must be provided without starting and ending parenthesis in a format that is similar to the default Java policy syntax.

Each permission requires a permission name (e.g., java.security.AllPermission) and one values node to be supplied. The values node may contain one or more value elements depending on the permission definition. Typically, the first value is named Target Name and specifies what the permission will allow or deny.

Another parameter may specify the operation (i.e., read, write, etc.) that will be permitted or denied by the rule.

Java supports several security checks that the developer can specify. Following, a list of them:

  • java.security.AllPermission
  • java.security.SecurityPermission
  • java.security.UnresolvedPermission
  • java.awt.AWTPermission
  • java.io.FilePermission
  • java.io.SerializablePermission
  • java.lang.reflect.ReflectPermission
  • java.lang.RuntimePermission
  • java.net.NetPermission
  • java.net.SocketPermission
  • java.sql.SQLPermission
  • java.util.PropertyPermission
  • java.util.logging.LoggingPermission
  • javax.net.ssl.SSLPermission
  • javax.security.auth.AuthPermission
  • javax.security.auth.PrivateCredentialPermission
  • javax.security.auth.kerberos.DelegationPermission
  • javax.security.auth.kerberos.ServicePermission
  • javax.sound.sampled.AudioPermission

More details about the Java security permissions are available here.

The OSGi specification defines a few custom permissions, that can be grouped into​ the layers of the OSGi framework.

Layer
Permission(s)

Module

PackagePermission - Controls which packages a bundle is allowed to import and/or export
BundlePermission - Controls which bundles a bundle is allowed to require

Lifecycle

AdminPermission - Controls which bundles are allowed to perform sensitive
lifecycle operations

Services

ServicePermission - Controls which services a bundle is allowed to publish and/or use

All the OSGi-specific permissions follow the same pattern of name and actions used by Java. For further details on the OSGi permissions, please refer to the official OSGi documentation.

Policy Generation

Prevent External Malicious Attacks

Custom security policies should be created in order to prevent external malicious attacks from unsigned bundles that can be installed on field devices. The policy should be as strict as possible in order to reduce the effects of malicious bundles on targeted system(s).

This Eurotech security policy example may be downloaded and used as a starting-point for the creation of custom policies:

Eurotech recommends creating security policies that only allow the execution of signed bundles.

Policy Change

The security policy file currently used by ESF is available at /opt/eurotech/esf/user/security/security.policy

To change the current security policy the steps to do are (with ESF running):

  • overwrite the current policy file at /opt/eurotech/esf/user/security/security.policy with the new security policy file;
  • using the ESF Gateway Administration Console, the policy file fingerprint must be reloaded (more info below). This feature is available by selecting the Settings option in the Systems area of the console and selecting the Security Options tab, and then clicking on the Reload fingerprint button provided in the Security Policy area;
  • stop and restart ESF.

A backup copy of the default security policy is available at /opt/eurotech/esf/.data/security_policy_backup/

The switch between framework execution modalities (from development to production mode or from production mode to development mode) requires the reload of both the Security Policy and Startup Command Line fingerprints

Consistency Check

During boot initialization, ESF validates the security policy file. In order to be accepted, the file must be compliant with the following XML Schema:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://eurotech.com/esf/2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="security">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="properties">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="property">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element type="xs:string" name="name"/>
                    <xs:element type="xs:string" name="value"/>
                  </xs:sequence>
                </xs:complexType>
              </xs:element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
        <xs:element name="policies">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="policy" maxOccurs="unbounded" minOccurs="0">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element type="xs:string" name="access"/>
                    <xs:element name="conditions" minOccurs="0">
                      <xs:complexType>
                        <xs:sequence>
                          <xs:element name="condition">
                            <xs:complexType>
                              <xs:sequence>
                                <xs:element type="xs:string" name="name"/>
                                <xs:element type="xs:string" name="value"/>
                              </xs:sequence>
                            </xs:complexType>
                          </xs:element>
                        </xs:sequence>
                      </xs:complexType>
                    </xs:element>
                    <xs:element name="permissions">
                      <xs:complexType>
                        <xs:sequence>
                          <xs:element name="permission" maxOccurs="unbounded" minOccurs="0">
                            <xs:complexType>
                              <xs:sequence>
                                <xs:element type="xs:string" name="name"/>
                                <xs:element name="values">
                                  <xs:complexType>
                                    <xs:sequence>
                                      <xs:element type="xs:string" name="value" maxOccurs="unbounded" minOccurs="0"/>
                                    </xs:sequence>
                                  </xs:complexType>
                                </xs:element>
                              </xs:sequence>
                            </xs:complexType>
                          </xs:element>
                        </xs:sequence>
                      </xs:complexType>
                    </xs:element>
                    <xs:element type="xs:string" name="name"/>
                  </xs:sequence>
                </xs:complexType>
              </xs:element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
      <xs:attribute type="xs:byte" name="version"/>
    </xs:complexType>
  </xs:element>
</xs:schema> 

If errors are detected, an exception is thrown and the framework shuts down.

It is recommended that the security policy file is verified against the provided XML Schema. Linux systems may use xmllint for this purpose as shown below.

xmllint --schema <xml schema>.xsd <security policy file>.xml