# Object Model Ownership
By default, when we create information model objects, they are unowned. It means that anyone who has proper RBAC access to a given object may manage it. Ownership is a concept which limits object management to a specified principal, most often a directly connected device (i.e., an Ability Edge device). For devices, ownership means that only the device (principal) that owns the corresponding object model can modify the object model properties or emit telemetry for the object model, or upload files connected to the object model. Method invocations targeting this object model will be routed to this device. This is done to avoid multiple principals using the same resources - only the owner should be able to perform resource modifying operations. Non-owners should only be able to read resources or subscribe to their changes.
Any information model object may become owned by associating it with a selected principal (i.e., a device) using an HTTP PUT endpoint. Until the ownership gets removed (using an HTTP DELETE Endpoint) only the selected principal is able to manage the object. When using Ability Edge, this process is done in the background by the Ability Edge framework. Any child device of Ability Edge is an owned device - its owner is the Ability Edge device identity.
References
Although it may seem like references of information model is a similar concept, it is a completely separate feature from ownership. A tree of references serves only for organizational purposes allowing you to easily identify any physical or logical connections between your objects (which is especially useful using DSL queries). An object that is referenced by another one in an child-parent relationship may be owned by a completely different object that is not connected to it by any reference! With that in mind, note that it is also possible (and often seen) to have matching reference and ownership realtionships. I.e., in Ability Edge framework the Edge is an owner of its modules. At the same time, there is a reference established between them, where Edge device acts as a parent of all of its modules. Thanks to such setup:
- Edge device is the only one that can manage modules' information model objects (thanks to ownership)
- it's very easy to query edge and its modules via DSL queries (thanks to references)
# Definitions
# General
Principal - an entity which has an identity and is allowed to access resources.
Ability Platform supports three distinct principal types:
- application
- user
- device
Identity - allows the principal to be identified. The Identity of a principal can be managed either by an identity provider or by its parent.
Identity provider - an external identity that can manage the identity of a principal.
WARNING
Identity and identity provider definitions as concepts are not the same as identity property and identity provider property of a principal in Principal Manager.
A principal's access to specific resources is determined and scoped via a set of assigned grants.
A principal is said to own an object model if it is declared as an owner of this object model.
# Specific to the Application Principal
The Identity of an application principal is always managed by an identity provider, which currently is always an Azure Active Directory.
# Specific to the User Principal
The Identity of a user principal is always managed by an identity provider. Azure Active Directory and other providers are supported.
# Specific to the Device Principal
The Device Principal is the only principal that has connectivity.
Device principals are hierarchical - a child device principal has exactly one parent device principal.
# Identity
The device principal may be assigned with an identity provider, which is always a certificate.
The Identity of a device principal can be managed either by an identity provider or by its parent.
The Parent of a principal is acting as identity provider. A parent chain of a given principal always ends with a principal with identity provider.
# Connectivity
Connectivity determines the addressability of a given device, that is an ability to communicate with a given device for a specific purpose, for example, to invoke a method or to deliver an event.
The Connectivity provider provides connectivity to a given device. It also specifies which communication capabilities it supports, such as method invocations and events. Only principals with an identity provider can be connected to a connectivity provider. Currently, only the IoT Hub is supported.
The Connectivity of a device principal can be managed either by a connectivity provider or by its parent.
The Parent of a principal acts as the connectivity provider. A parent chain of a given principal always ends with a principal with an external identity, which may or may not be connected to a connectivity provider.
Directly connected device - a device (principal) that is connected to a connectivity provider.
Indirectly connected device - a device (principal) which has either a directly connected device or another indirectly connected device as its parent.
A connected device is either a directly connected device or an indirectly connected device.
# Examples
Here is an example depicting a Connected Devices Structure:
Here is an example Edge Structure:
# Data Structure and Relations
# Principal Manager
The Principal Manager is used to store and configure principals.
Every principal in the Principal Manager always consists of the following properties:
- id property - GUID, which uniquely identifies given principal in Principal Manager. Also known as principal id
- principalType - app, user, or device
# Specific to the Application Principal
The application principal can act on its own, or on behalf of users or devices (user delegation and device delegation respectively).
The application principal also contains the following properties:
- delegation property - user or device. If provided, the application acts on behalf of a user/device.
Azure Active Directory is always the Identity provider. The Identity of an application principal is represented by the application id.
# Specific to the User Principal
The user principal also contains the following properties:
- identity - String. External identity
- identity provider - Guid. External entity that manages this identity
The identity provider can be Azure Active Directory, but other providers are also supported. The identity of a user principal is represented by the identity property.
# Specific to the Device Principal
Note: For a device principal, id property is also known as device id in Principal Manager.
# Directly Connected Device Principal
Directly connected device principal also contains following properties:
- identity - String. External identity. Equals device id in IoT Hub
- identity provider - Guid. External entity that manages this identity
- connectivity provider - External entity that provides connectivity (currently only IoT Hub is supported)
Identity provider is always a certificate. Identity of a directly connected device principal is represented by identity property.
# Indirectly Connected Device Principal
Indirectly connected device principal also contains following properties:
- identity - String, which uniquely identifies given principal across its parent children. For indirectly connected devices can be any string. For Edge modules it is equal to module name
- parent - Guid. Parent principal that manages this identity and provides connectivity
The Identity of an indirectly connected device principal is represented by a path.
# Paths
TIP
Paths is a concept that is applicable only for device principals.
Device principals' hierarchy represents the business level logic structure of specified device(s) - their identity and connectivity hierarchy.
This hierarchy can be represented by a full path and a relative path.
A full path to a device principal consists of device principal identities separated by a forward slash.
A relative path to an indirectly connected device principal consists of device principal identities separated by a forward slash, omitting the directly connected device identity.
Path examples:
For any directly connected device:
- full path = '{directly connected device identity}'
- relative path is empty
For any indirectly connected device:
- full path = '{directly connected device identity}/{first level indirectly connected device identity}/../{n-th level indirectly connected device identity}'
- relative path = '{first level indirectly connected device identity}/../{n-th level indirectly connected device identity}'
In case of an Edge, the following principals are defined:
- Edge principal, which is the only directly connected device principal:
- full path = '{device id in IoT Hub}'
- relative path is empty
- Module principals, which have the Edge principal as a parent:
- full path = '{device id in IoT Hub}/{module identity}'
- relative path = '{module identity}'
- Principals for connected devices under modules, which have a module
principal or another connected device as a parent:
- full path = '{device id in IoT Hub}/{module identity}/{first level indirectly connected device identity}/../{n-th level indirectly connected device identity}'
- relative path = '{module identity}/{first level indirectly connected device identity}/../{n-th level indirectly connected device identity}'
- Edge principal, which is the only directly connected device principal:
Note: Paths are always empty for application and user principals mentioned.
# Examples
Example Connected Devices Structure with principal data and actions:
Example Edge Structure with principal data and actions:
# Information Model
Each object model in the Ability Platform can (but is not required to) have an associated owner. A principal is declared as an owner of an object model using ownerId and path properties. An object model can be owned by a maximum of one principal at a time. Object model can be owned by any principal type - application, user, or device.
# Application Principal specific
For any object model owned by application principal:
- ownerId property - always contains application principal id
- path property - is always empty
# User Principal specific
For any object model owned by user principal:
- ownerId property - always contains user principal id
- path property - is always empty
# Device Principal specific
For any object model owned by device principal:
- ownerId property - always contains directly connected device principal id
- path property - if present, contains relative path from directly connected device principal to owning indirectly connected device principal (see chapter "Principal Manager" for path examples)
# Examples
Example Connected Devices Structure with principal data and actions, and object model data and actions:
Example Edge Structure with principal data and actions, and object model data and actions:
# Device API Usage
To make use of ownership, first a principal must be created and then object model's ownership can be claimed by the principal.
# Management of Principals
# Create Principal
Principals can be created (or updated) via Device API by using 'identity.create' action.
Only indirectly connected devices (i.e. Edge modules) can be created via Device API.
Directly connected device (i.e. Edge) principal cannot be created via Device API. This principal must be created directly in Principal Manager API and it must contain proper identity provider and connectivity provider.
When directly connected device principal exists, it may be updated via Device API by using 'identity.create' or 'identity.update' action.
# Update Principal
Principals can be updated via Device API by using 'identity.create'. or 'identity.update' action.
Both directly connected devices (i.e. Edges) and indirectly connected devices (i.e. Edge modules) can be freely updated.
# Delete Principal
Principals can be deleted via Device API by using 'identity.delete' action.
# Ownership
# Claim Ownership
For an object model that has no owner, a device principal can claim ownership on the model during first 'model.create' action. Following 'model.create' actions on the same model will not change model's ownership. 'model.update' actions on the same model also cannot change model's ownership.
# Remove Ownership
Ownership can be removed from a model via Device API using 'owner.remove' action.
# Change Ownership
Currently ownership of a model can only be changed purely via Device API in a following way:
- First, remove model's owner using 'owner.remove' action. This has to be performed by the current (old) owner
- Second, make an ownership claim of the model with a new owner
# Sources of truth
The entity who assembles the information and who is the owner of information is
considered as a source of truth.
For Device API, there can be two sources of truth - the device and the cloud.
Additionally, Edge can work as additional state persistance layer inbetween.
# Device
Device is the source of truth for models owned by device, i.e. 'abb.ability.device' models
- Device is the source of truth, since the device knows how the model should look like and what is the last known state
- Cloud should not update object models owned by device
- Cloud has to be kept up-to-date by the device
- Edge can be used to persist state of the models in two ways:
- MQTT topics - here 'request-response' notifications are needed to
maintain state
- Note: This way is currently is not recommended - it will be deprecated in future
- Volumes - here 'request-response' notifications are not needed
- MQTT topics - here 'request-response' notifications are needed to
maintain state
# Use cases (Ability Edge based)
- The user has the state of all owned models available locally on the module,
the models do not have any default values, state persistence is not needed
- The cloud is kept up-to-date by sending
'model.create',
'model.update',
and
'model.delete'
actions from module
- Only acknowledgements are needed to be sent back, to know that actions were successfully processed
- Edge is not used to persist state of the models:
- There is no need for requesting 'request-response' notifications because state persistance on MQTT topics is not used
- The cloud is kept up-to-date by sending
'model.create',
'model.update',
and
'model.delete'
actions from module
In this use case we disregard sending of 'request-response' notifications to reduce c2d usage - lower costs and faster operation.
- The user does not have the state of all owned models available locally on the
module, the models do not have any default values, state persistence is
needed.
- The cloud is kept up-to-date by sending
'model.create',
'model.update',
and
'model.delete'
actions from module
- Only acknowledgements are needed to be sent back, to know that actions were successfully processed
- Edge is used to persist state of the models via Volumes:
- User is responsible to create/update/delete last known state of owned models on Volumes
- There is no need for requesting 'request-response' notifications because state persistance on MQTT topics is not used
- The cloud is kept up-to-date by sending
'model.create',
'model.update',
and
'model.delete'
actions from module
In this use case we also disregard sending of 'request-response' notifications to reduce c2d usage - lower costs and faster operation. The implementation of Volumes is additional work on the user side.
- (Not recommended - will be deprecated in future) The user does not have
the state of all owned models available locally on the module, the models
have default values, state persistence is needed.
- The cloud is kept up-to-date by sending
'model.create',
'model.update',
and
'model.delete'
actions from module
- Acknowledgements are needed to be sent back, to know that actions were successfully processed
- Edge is used to persist state of the models via MQTT topics:
- There is a need for requesting 'request-response' notifications (with additional 'model.query' actions), so that default values are propagated back to module
- User is responsible to maintain last known state of owned models via
MQTT topics
When creating/updating models, user is responsible to send 'model.query' after each 'model.create', 'model.update', or 'model.patch' action, so that 'request-response' notifications are stored on MQTT topic.
Send multiple files at once using batch.execute
'model.create', 'model.update', 'model.patch', and 'model.query' actions can be sent in one 'batch.execute' message
When deleting models, user is responsible to clean up MQTT topic after 'model.delete' action completed successfully.
- The cloud is kept up-to-date by sending
'model.create',
'model.update',
and
'model.delete'
actions from module
# Cloud
Cloud is the source of truth for unowned models, i.e. 'abb.ability.configuration' models
- Cloud is the source of truth, since the cloud knows how the model should look like and what is the last known state
- Device should not update unowned models or models owned by another device
- The device can be kept up-to-date by subscribing to models it is interested in
(unowned models or models owned by another device)
- Cloud will send 'publish-subscribe' notifications to the device
- Edge will persist state of the models on MQTT topics
# Use case
The user listens to changes of models it is interested in, state persistence is needed.
- User subscribes to the models it is interested in (unowned models or
models owned by another device)
WARNING
Currently Subscription Manager is not yet fully implemented. There are only implicit subscriptions to 'abb.ability.configuration' models
- Whenever subscribed model is created/updated/deleted in the cloud, 'publish-subscribe' notification (ObjectModel.Created/Updated/Deleted) is sent to device
- Edge is used to persist state of the models on MQTT topics