Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

doc: provisioning: Add documentation #11704

Merged
merged 1 commit into from
Aug 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
166 changes: 166 additions & 0 deletions doc/nrf/libraries/networking/nrf_provisioning.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
.. _lib_nrf_provisioning:

nRF Device provisioning
#######################

.. contents::
:local:
:depth: 2

The nRF Device provisioning library enables a device to connect to nRF Cloud Provisioning Service, part of nRF Cloud Security Services.
It abstracts and hides the details of the transport and encoding scheme that are used for the payload.
The current implementation supports the following technologies:

* AT-command based provisioning commands
* Writing key-value pair based settings to the :ref:`settings_api` storage
* TLS-secured HTTP as the communication protocol
* Client authentication with attestation token
* Client authentication with JWT token
* CBOR as the data format

Configuration
*************

To enable the library, set the :kconfig:option:`CONFIG_NRF_PROVISIONING` Kconfig option to ``y``.

Configuration options for transport protocol
============================================

Currently, HTTP is the only supported transport protocol.

* :kconfig:option:`CONFIG_NRF_PROVISIONING_SYS_INIT` - Initializes the client in the system initialization phase
* :kconfig:option:`CONFIG_NRF_PROVISIONING_ROOT_CA_SEC_TAG` - Root CA security tag for the Provisioning Service
* :kconfig:option:`CONFIG_NRF_PROVISIONING_HTTP_HOSTNAME` - HTTP API hostname for the Provisioning Service
* :kconfig:option:`CONFIG_NRF_PROVISIONING_HTTP_PORT` - Port number for the Provisioning Service
* :kconfig:option:`CONFIG_NRF_PROVISIONING_HTTP_TIMEOUT_MS` - Timeout in milliseconds for HTTP connection of the Provisioning Service
* :kconfig:option:`CONFIG_NRF_PROVISIONING_HTTP_RX_BUF_SZ` - HTTP response payload buffer size
* :kconfig:option:`CONFIG_NRF_PROVISIONING_HTTP_TX_BUF_SZ` - HTTP request body size
* :kconfig:option:`CONFIG_NRF_PROVISIONING_HTTP_JWT` - Chooses JWT token for client authentication
* :kconfig:option:`CONFIG_NRF_PROVISIONING_HTTP_ATTESTTOKEN` - Chooses attestation token for client authentication

.. _lib_nrf_provisioning_start:

Usage
*****

The usage of the nRF Device provisioning library is described in the following sections.

Initialization
==============

Once initialized, the provisioning client runs on its own in the background.
The provisioning client can be initialized in one of the following ways:

* The application calls :c:func:`nrf_provisioning_init`, which starts the client.
* Set the client to initialize during Zephyr's system initialization phase.
In this case, it is assumed that a network connection has been established in the same phase.

The function uses the following arguments:

* A pointer to a callback function, which is called when the modem state changes.
* A pointer that must be called once provisioning is done.

If you provide ``null`` as a callback function address argument, a corresponding default callback is used.
Subsequent calls to the initialization function will only change the callback functions.
This behavior is beneficial when the client has been initialized during the system initialization phase, but the application wants to register its own callback functions afterwards.

Provisioning
============

By default, when provisioning is done after receiving the ``FINISHED`` command, the device is rebooted.
The behavior can be overwritten by providing a unique callback function for the initialization function.

If anything is written to the modem's non-volatile memory, the modem needs to be set in offline mode.
This is because the modem cannot be connected while any data is being written to its storage area.
Once the memory write is complete, the aforementioned callback function must be called again to set the modem to the desired state.
To use the default implementation, ``NULL`` can be passed as an argument to the :c:func:`nrf_provisioning_init` function.
Copy and modify the default callback function as necessary.

The library starts provisioning when it initializes, then according to the configured interval.
The interval is read from the storage settings and can be updated with a provisioning command like any other key-value pair.

During provisioning, the library first tries to establish the transport for communicating with the service.
This procedure involves a TLS handshake where the client establishes the correct server.
The server uses the attestation token or JWT generated by the device to authenticate the client.
See :ref:`lib_modem_attest_token` and :ref:`lib_modem_jwt` for more information on client authentication.

The TLS handshake happens twice:

* Before requesting commands.
* After the execution of the commands, to report the results.

If you are using `AT commands <AT Commands Reference Guide_>`_, the library shuts down the modem for writing data to the modem's non-volatile memory.
Once the memory writes are complete, the connection is re-established to report the results back to the server.
The results are reported back to the server when either all the commands succeed or when an error occurs.
If an error occurs, the results of all the commands that are successfully executed before the error and the erroneous result are reported back to the server.
All successfully executed commands will be removed from the server-side queue, but if any errors occur, the erroneous command and all the remaining unexecuted commands are removed from the server-side queue.
The log contains more information about the issue.

Immediate provisioning can be requested by calling the :c:func:`nrf_provisioning_trigger_manually` function.
Otherwise, the library attempts provisioning according to the set interval.
To trigger immediate provisioning, the library must be initialized first.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Passive voice (be initialized) makes it unclear if this is something that I can automate, or if I need to initialize it manually.


The following message sequence chart shows a successful provisioning sequence:

.. msc::
hscale = "1.5";
Owner,Server,Device;
Owner>>Server [label="Provision: cmd1, cmd2, finished"];
Server<<Device [label="Get commands"];
Server>>Device [label="Return commands"];
Device box Device [label="Decode commands"];
Device box Device [label="Set modem offline"];
Device box Device [label="Write to non-volatile memory"];
Device box Device [label="Restore modem state"];
Server<<Device [label="cmd1,cmd2, finished succeeded"];

The following message sequence chart shows a failing provisioning sequence:

.. msc::
hscale = "1.5";
Owner,Server,Device;
Owner>>Server [label="Provision: cmd1, cmd2, cmd3, finished"];
Server<<Device [label="Get commands"];
Server>>Device [label="Return commands"];
Device box Device [label="Decode commands"];
Device box Device [label="Set modem offline"];
Device box Device [label="cmd1: Write to non-volatile memory"];
Device box Device [label="cmd2: Fails"];
Device box Device [label="Restore modem state"];
Server<<Device [label="cmd1 success, cmd2 failed"];
Server>>Server [label="Empty the command queue"];
Server>>Owner [label="cmd2 failed"];

.. _nrf_provisioning_shell:

nRF Provisioning shell
**********************

To test the client, you can enable Zephyr's shell and provisioning command, which allow you to control the client over UART.
The feature is enabled by selecting :kconfig:option:`CONFIG_NRF_PROVISIONING_SHELL`.

.. note::
The shell is meant for testing.
Do not enable it in production.

.. code-block:: console

uart:~$ nrf_provisioning
nrf_provisioning - nRF Provisioning commands
Subcommands:
init :Start the client
now :Do provisioning now
token :Get the attestation token
uuid :Get device UUID

.. _nrf_provisioning_api:

API documentation
*****************

| Header file: :file:`include/net/nrf_provisioning.h`
| Source files: :file:`subsys/net/lib/nrf_provisioning/src/`

.. doxygengroup:: nrf_provisioning
:project: nrf
:members:
1 change: 1 addition & 0 deletions doc/nrf/links.txt
Original file line number Diff line number Diff line change
Expand Up @@ -959,6 +959,7 @@
.. _`nRF Cloud MQTT FOTA`: https://docs.nrfcloud.com/Devices/FirmwareUpdate/FOTAOverview.html#mqtt-job-execution-notifications
.. _`nRF Cloud Getting Started FOTA documentation`: https://docs.nrfcloud.com/Devices/FirmwareUpdate/FOTATutorial.html
.. _`Securely generating credentials on the nRF9160`: https://docs.nrfcloud.com/Devices/Security/Credentials.html
.. _`nRF Cloud provisioning configuration`: https://docs.nrfcloud.com/SecurityServices/ProvisioningService/ProvisioningConfiguration/ProvisioningConfigurationPortal.html
.. _`nRF Cloud REST API`:
.. _`nRF Connect for Cloud REST API`: https://docs.nrfcloud.com/APIs/REST/RESTOverview.html
.. _`nRF Cloud Location Services documentation`: https://docs.nrfcloud.com/LocationServices/LSOverview.html
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,10 @@ Cellular samples (renamed from nRF9160 samples)

* Renamed nRF9160 samples to cellular samples and are now found in the :file:`samples/cellular` folder.

* Added the :ref:`battery` sample to show how to use the :ref:`modem_battery_readme` library.
* Added:

* The :ref:`battery` sample to show how to use the :ref:`modem_battery_readme` library.
* The :ref:`nrf_provisioning_sample` sample that demonstrates how to use the :ref:`lib_nrf_provisioning` service.

* :ref:`nrf_cloud_mqtt_multi_service` sample:

Expand Down Expand Up @@ -513,6 +516,10 @@ Modem libraries
Libraries for networking
------------------------

* Added

* The :ref:`lib_nrf_provisioning` library for device provisioning.

* Multicell location library:

* This library is now removed and relevant functionality is available through the :ref:`lib_location` library.
Expand Down
141 changes: 141 additions & 0 deletions samples/cellular/nrf_provisioning/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
.. _nrf_provisioning_sample:

Cellular: nRF Device provisioning
#################################

.. contents::
:local:
:depth: 2

This sample demonstrates how to use the :ref:`lib_nrf_provisioning` service on your device.

Requirements
************

The sample supports the following development kits:

.. table-from-rows:: /includes/sample_board_rows.txt
:header: heading
:rows: nrf9161dk_nrf9161_ns

.. include:: /includes/tfm.txt

The sample requires that the device's private key is installed on the device and the associated device UUID is obtained from the Identity Service.

.. note::
This sample requires modem firmware v2.0.0 or later.

Overview
********

The sample shows how the device performs the following actions:

* Connects to nRF Cloud Provisioning Service.
* Fetches available device-specific provisioning configuration.
* Decodes the commands.
* Acts on any AT commands, if available.
* Reports the results back to the server.
In the case of an error, stops processing the commands at the first error and reports it back to server.
* Sends ``FINISHED`` response if all the previous commands are executed without errors provided and ``FINISHED`` is one of the set provisioning commands.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what 'without errors provided and FINISHED is one of the set provisioning commands' means. Possible values for the command status in the Provisioning Service are PENDING, FAILED, IN_PROGRESS, SUCCEEDED, and SKIPPED. Does this refer to the command status or the status of something in the sample, which has different values?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FINISHED refers to the provisioning command which tells to the device that provisioning process has been finished.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK. So this refers specifically to something in the sample, and not the Provisioning Service.


User interface
**************

Device side interaction is not required.
You must define the provisioning configuration at the server side.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See `nRF Cloud provisioning configuration`_.

Configuration
*************

|config|

Configuration options
=====================

Check and configure the following configuration options for the sample:

.. _CONFIG_NRF_PROVISIONING_ROOT_CA_SEC_TAG:

CONFIG_NRF_PROVISIONING_ROOT_CA_SEC_TAG
Root CA security tag for the nRF Cloud Provisioning Service.
Needs to be set explicitly and if not, the compilation fails.

.. _CONFIG_NRF_PROVISIONING_HTTP_HOSTNAME:

CONFIG_NRF_PROVISIONING_HTTP_HOSTNAME
Configures the hostname of the nRF Device provisioning service.

.. _CONFIG_NRF_PROVISIONING_HTTP_PORT:

CONFIG_NRF_PROVISIONING_HTTP_PORT
Configures the HTTP port of the nRF Device provisioning service.

.. _CONFIG_NRF_PROVISIONING_HTTP_TIMEOUT_MS:

CONFIG_NRF_PROVISIONING_HTTP_TIMEOUT_MS
Configures the HTTP timeout.

.. _CONFIG_RF_PROVISIONING_HTTP_RX_BUF_S:

CONFIG_RF_PROVISIONING_HTTP_RX_BUF_S
Configures the response payload buffer size.

.. _CONFIG_NRF_PROVISIONING_HTTP_TX_BUF_SZ:

CONFIG_NRF_PROVISIONING_HTTP_TX_BUF_SZ
Configures the command request body size.

Building and running
********************

.. |sample path| replace:: :file:`samples/cellular/nrf_provisioning`

.. include:: /includes/build_and_run_ns.txt

Testing
=======

|test_sample|

#. |connect_kit|
#. |connect_terminal|
#. Add a provisioning configuration using the nRF Cloud Provisioning Service.
See `nRF Cloud provisioning configuration`.
#. Power on or reset your device.
#. Observe that the sample starts and connects to the LTE network.
#. Observe that provisioning pauses and resumes while fetching and executing provisioning commands.

Sample output
=============

The following is an example output of the sample when there is no provisioning configuration on the server side:

.. code-block:: console

<inf> nrf_provisioning_sample: Establishing LTE link ...
<inf> nrf_provisioning_http: Connected
<inf> nrf_provisioning_http: No more commands to process on server side

The following is an example output when the sample is processing commands from the server:

.. code-block:: console

<inf> nrf_provisioning_sample: Establishing LTE link ...
<inf> nrf_provisioning_http: Connected
<inf> nrf_provisioning: Disconnected from network - provisioning paused
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume between "Disconnected" and "Connected" on the next line, some actual provisioning is happening?

It might be nice to say so (obviously that requires a change to the code itself, not just this documentation).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I'll create a new PR for this.

<inf> nrf_provisioning: Connected; home network - provisioning resumed
<inf> nrf_provisioning_sample: Modem connection restored
<inf> nrf_provisioning_sample: Waiting for modem to acquire network time...
<inf> nrf_provisioning_sample: Network time obtained
<inf> nrf_provisioning_http: Connected
<inf> nrf_provisioning_http: No more commands to process on server side

Dependencies
************

This sample uses the following |NCS| libraries:

* :ref:`lte_lc_readme`
* :ref:`modem_info_readme`
* :ref:`lib_nrf_provisioning`
Loading