Skip to content

Commit

Permalink
Device Provisioning Service (DPS) Integration
Browse files Browse the repository at this point in the history
This pull request introduces a comprehensive Device Provisioning Service
(DPS) to IoTivity-Lite, enabling devices to securely and efficiently connect
to cloud services with minimal manual intervention. DPS automates the
provisioning process, managing device credentials, ownership, and cloud
configurations seamlessly.

Key Features:

1. Automatic Device Provisioning

- Ownership Management: Automates the transfer and assignment of
device ownership, ensuring that devices are securely owned and managed.
- Credential Handling: Manages the generation, validation, renewal, and
replacement of device certificates necessary for secure communication.
- Cloud Configuration: Automatically retrieves and applies cloud
configurations, including access tokens and server details.

2. Secure PKI Implementation

- Certificate Validation: Validates certificates against expiration and
validity periods to maintain secure connections.
- Renewal Mechanism: Includes automatic renewal processes for
expiring certificates to prevent communication disruptions.
- Trust Chain Management: Handles root and intermediate certificates
to establish a trusted connection hierarchy.

3. Robust Retry Mechanism

- Configurable Retries: Implements a retry mechanism with customizable
intervals and limits to handle transient network or service errors.
- Failure Handling: Provides mechanisms to reset and retry provisioning
steps upon failures, enhancing reliability.

4. Extensive Logging and Debugging Support

- Customizable Log Levels: Offers different log levels (error, warning, info,
debug) to suit development and production needs.
- Component-Specific Logging: Includes a new log component
`OC_LOG_COMPONENT_DEVICE_PROVISIONING` for DPS-specific logs.
- Debugging Aids: Facilitates easier troubleshooting with detailed log
messages and optional debug output.

5. Comprehensive Testing Suite

- Unit Tests: Introduces extensive unit tests for all major components of
the DPS, ensuring reliability and correctness.
- Test Coverage: Covers scenarios including certificate management,
provisioning steps, retry logic, and error handling.
  • Loading branch information
Danielius1922 authored Sep 16, 2024
1 parent 14f27b8 commit e707e62
Show file tree
Hide file tree
Showing 93 changed files with 16,194 additions and 123 deletions.
5 changes: 4 additions & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
.github/
.clang-format
.clang-tidy
**/*.o
**/*.gcno
**/*.gcda
sonar-project.properties
Dockerfile.*
build/
build*/
images/
port/esp32/build/
port/esp32/esp-idf/
Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/cmake-linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,16 @@ jobs:
- args: "-DOC_IPV4_ENABLED=ON -DOC_TCP_ENABLED=ON"
# ipv4 on, tcp on, pki off
- args: "-DOC_IPV4_ENABLED=ON -DOC_TCP_ENABLED=ON -DOC_PKI_ENABLED=OFF"
# cloud on (ipv4+tcp on), dynamic allocation off
- args: "-DOC_CLOUD_ENABLED=ON -DOC_DYNAMIC_ALLOCATION_ENABLED=OFF"
# cloud on (ipv4+tcp on), dynamic allocation off, push notifications off
- args: "-DOC_CLOUD_ENABLED=ON -DOC_DYNAMIC_ALLOCATION_ENABLED=OFF -DOC_PUSH_ENABLED=OFF"
# cloud on (ipv4+tcp on), collections create on
- args: "-DOC_CLOUD_ENABLED=ON -DOC_COLLECTIONS_IF_CREATE_ENABLED=ON"
# cloud on (ipv4+tcp on), collections create on, custom message buffer size, custom message buffer pool size, custom app data buffer size, custom app data buffer pool size
- args: "-DOC_CLOUD_ENABLED=ON -DOC_COLLECTIONS_IF_CREATE_ENABLED=ON -DOC_INOUT_BUFFER_SIZE=2048 -DOC_INOUT_BUFFER_POOL=4 -DOC_APP_DATA_BUFFER_SIZE=2048 -DOC_APP_DATA_BUFFER_POOL=4"
# debug on
- args: "-DOC_DEBUG_ENABLED=ON"
# debug on, cloud on (ipv4+tcp on)
- args: "-DOC_CLOUD_ENABLED=ON -DOC_DEBUG_ENABLED=ON"
# debug on, cloud on (ipv4+tcp on), plgd time off
- args: "-DOC_CLOUD_ENABLED=ON -DPLGD_DEV_TIME_ENABLED=OFF -DOC_DEBUG_ENABLED=ON"
# secure off, tcp on
- args: "-DOC_SECURITY_ENABLED=OFF -DOC_TCP_ENABLED=ON"
# secure off, ipv4 on, tcp on
Expand Down Expand Up @@ -138,7 +138,7 @@ jobs:
# install_faketime: true
uses: ./.github/workflows/unit-test-with-cfg.yml
with:
build_args: -DOC_LOG_MAXIMUM_LOG_LEVEL=INFO -DOC_CLOUD_ENABLED=ON -DOC_COLLECTIONS_IF_CREATE_ENABLED=ON -DOC_MNT_ENABLED=ON -DOC_WKCORE_ENABLED=ON -DOC_SOFTWARE_UPDATE_ENABLED=ON -DOC_DISCOVERY_RESOURCE_OBSERVABLE_ENABLED=ON -DOC_PUSH_ENABLED=ON -DOC_RESOURCE_ACCESS_IN_RFOTM_ENABLED=ON -DPLGD_DEV_TIME_ENABLED=ON -DOC_ETAG_ENABLED=ON ${{ matrix.args }}
build_args: -DOC_LOG_MAXIMUM_LOG_LEVEL=INFO -DOC_CLOUD_ENABLED=ON -DOC_COLLECTIONS_IF_CREATE_ENABLED=ON -DOC_MNT_ENABLED=ON -DOC_WKCORE_ENABLED=ON -DOC_SOFTWARE_UPDATE_ENABLED=ON -DOC_DISCOVERY_RESOURCE_OBSERVABLE_ENABLED=ON -DOC_PUSH_ENABLED=ON -DOC_RESOURCE_ACCESS_IN_RFOTM_ENABLED=ON -DPLGD_DEV_TIME_ENABLED=ON -DOC_ETAG_ENABLED=ON -DPLGD_DEV_DEVICE_PROVISIONING_ENABLED=ON -DPLGD_DEV_DEVICE_PROVISIONING_TEST_PROPERTIES_ENABLED=ON ${{ matrix.args }}
build_type: ${{ (github.event_name == 'workflow_dispatch' && inputs.build_type) || 'Debug' }}
clang: ${{ ((github.event_name == 'workflow_dispatch' && inputs.clang) || matrix.clang) || false }}
coverage: false
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/docker-build-publish-with-cfg.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,5 +80,5 @@ jobs:
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-args: |
BUILD_ARGS=-DOC_DEBUG_ENABLED=ON -DOC_COLLECTIONS_IF_CREATE_ENABLED=ON -DOC_MNT_ENABLED=ON -DOC_OSCORE_ENABLED=OFF -DOC_RESOURCE_ACCESS_IN_RFOTM_ENABLED=ON -DPLGD_DEV_TIME_ENABLED=ON -DOC_ETAG_ENABLED=ON -DOC_SOFTWARE_UPDATE_ENABLED=ON ${{ inputs.build_args }}
BUILD_ARGS=${{ inputs.build_args }}
BUILD_TYPE=${{ inputs.build_type }}
31 changes: 24 additions & 7 deletions .github/workflows/docker-build-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,6 @@ on:
- master
workflow_dispatch:

env:
REGISTRY: ghcr.io

jobs:
build-and-push-images:
strategy:
Expand All @@ -31,21 +28,41 @@ jobs:
include:
- name: cloud-server
build_type: Release
build_args: ""
build_args:
file: docker/apps/Dockerfile.cloud-server
- name: cloud-server-debug
build_type: Debug
build_args: ""
build_args:
file: docker/apps/Dockerfile.cloud-server-debug
- name: cloud-server-discovery-resource-observable
build_type: Release
build_args: "-DOC_DISCOVERY_RESOURCE_OBSERVABLE_ENABLED=ON"
build_args: -DOC_DISCOVERY_RESOURCE_OBSERVABLE_ENABLED=ON
file: docker/apps/Dockerfile.cloud-server
- name: cloud-server-discovery-resource-observable-debug
build_type: Debug
build_args: "-DOC_DISCOVERY_RESOURCE_OBSERVABLE_ENABLED=ON"
build_args: -DOC_DISCOVERY_RESOURCE_OBSERVABLE_ENABLED=ON
file: docker/apps/Dockerfile.cloud-server-debug
uses: ./.github/workflows/docker-build-publish-with-cfg.yml
with:
name: ${{ matrix.name }}
build_type: ${{ matrix.build_type }}
build_args: -DOC_DEBUG_ENABLED=ON -DOC_COLLECTIONS_IF_CREATE_ENABLED=ON -DOC_MNT_ENABLED=ON -DOC_OSCORE_ENABLED=OFF -DOC_RESOURCE_ACCESS_IN_RFOTM_ENABLED=ON -DPLGD_DEV_TIME_ENABLED=ON -DOC_ETAG_ENABLED=ON -DOC_SOFTWARE_UPDATE_ENABLED=ON ${{ matrix.build_args }}
file: ${{ matrix.file }}

build-and-push-dps-images:
strategy:
fail-fast: false
matrix:
include:
- name: dps-cloud-server
build_type: Release
build_args:
file: docker/apps/Dockerfile.dps-cloud-server
- name: dps-cloud-server-debug
build_type: Debug
build_args: -DOC_DEBUG_ENABLED=ON -DOC_LOG_MAXIMUM_LOG_LEVEL=DEBUG -DPLGD_DEV_DEVICE_PROVISIONING_TEST_PROPERTIES_ENABLED=ON
file: docker/apps/Dockerfile.dps-cloud-server
uses: ./.github/workflows/docker-build-publish-with-cfg.yml
with:
name: ${{ matrix.name }}
build_type: ${{ matrix.build_type }}
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/ghcr-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ on:
- cloud-server-debug
- cloud-server-discovery-resource-observable
- cloud-server-discovery-resource-observable-debug
- dps-cloud-server
- dps-cloud-server-debug
jobs:
check_package:
name: Check released packages
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/plgd-device-test-with-cfg.yml
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ jobs:
if: ${{ inputs.coverage }}
id: coverage
run: |
SUFFIX=`echo "-DCMAKE_BUILD_TYPE=${{ inputs.build_type }} ${{ inputs.build_args }} ${{ inputs.name }} -DBUILD_TESTING=ON" | sha1sum | cut -f 1 -d ' '`
SUFFIX=$(echo "-DCMAKE_BUILD_TYPE=${{ inputs.build_type }} ${{ inputs.build_args }} ${{ inputs.name }} -DBUILD_TESTING=ON" | sha1sum | cut -f 1 -d ' ')
echo "filename=coverage-plgd-device-${SUFFIX}.json" >> $GITHUB_OUTPUT
echo "artifact=plgd-device-${SUFFIX}-coverage" >> $GITHUB_OUTPUT
Expand Down
176 changes: 176 additions & 0 deletions .github/workflows/plgd-dps-test-with-cfg.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.

name: Run plgd/hub/dps tests with dps_cloud_server and a single configuration

on:
workflow_call:
inputs:
args:
description: arguments forwarded to the dps_cloud_server binary
type: string
required: false
default: ""
build_args:
description: build arguments forwarded to CMake in docker/apps/Dockerfile.cloud-server-debug
type: string
required: false
default: ""
build_type:
type: string
required: false
default: Debug
coverage:
description: gather and upload coverage data
type: boolean
required: false
default: false
docker_file:
description: Dockerfile used to build the dps_cloud_server container
type: string
required: false
default: docker/apps/Dockerfile.dps-cloud-server-debug
skip:
description: Skip this run of the job
type: boolean
required: false
default: false
env:
TEST_DPS_IMAGE: ghcr.io/plgd-dev/hub/test-device-provisioning-service:latest

jobs:
plgd-hub-test-with-cfg:
if: ${{ !inputs.skip }}
runs-on: ubuntu-22.04
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
submodules: "true"

- name: Configure vm.mmap_rnd_bits for sanitizers
if: contains(inputs.build_args, 'OC_ASAN_ENABLED') || contains(inputs.build_args, 'OC_LSAN_ENABLED') || contains(inputs.build_args, 'OC_TSAN_ENABLED') || contains(inputs.build_args, 'OC_UBSAN_ENABLED')
run: |
sudo sysctl vm.mmap_rnd_bits
sudo sysctl -w vm.mmap_rnd_bits=28
- name: Build dps-cloudserver docker image
uses: docker/build-push-action@v5
with:
context: .
push: false
build-args: |
BUILD_ARGS=${{ inputs.build_args }}
BUILD_TYPE=${{ inputs.build_type }}
file: ${{ inputs.docker_file }}
tags: dps-dbg:latest

- name: Pull device-provisioning-service tests image
run: docker pull ${{ env.TEST_DPS_IMAGE }}

- name: Prepare test environment
run: >
mkdir -p "/tmp/data/certs/device";
chmod -R 0777 "/tmp/data";
docker run --rm --log-driver local --network=host
-e PREPARE_ENV=true
-e RUN=false
-v /tmp/data:/data
-v /var/run/docker.sock:/var/run/docker.sock
${{ env.TEST_DPS_IMAGE }}
- name: Run dps cloud server docker image
run: >
mkdir -p "/tmp/data/coverage";
chmod -R 0777 "/tmp/data/coverage";
docker run --privileged -d --network=host --log-driver local
-v /tmp/data/certs/device:/dps/pki_certs
-v /tmp/data/coverage:/data/coverage
--name dps-devsim
dps-dbg:latest
--create-conf-resource
--no-verify-ca
--cloud-observer-max-retry 10
--expiration-limit 10
--retry-configuration 5
--oc-log-level="info"
--log-level="debug"
--wait-for-reset
"dps-devsim-$(hostname)"
- name: Run dps cloud server docker image for onboarding
run: >
docker run --privileged -d --network=host --log-driver local
-v /tmp/data/certs/device:/dps/pki_certs
-v /tmp/data/coverage:/data/coverage
--name dps-devsim-obt
dps-dbg:latest
--create-conf-resource
--cloud-observer-max-retry 10
--expiration-limit 10
--retry-configuration 5
--oc-log-level="info"
--log-level="debug"
${{ inputs.args }}
"dps-devsim-obt-$(hostname)" ""
- name: Run device-provisioning-service tests image
run: >
docker run --rm --log-driver local --network=host --hostname="$(hostname)"
-e PREPARE_ENV=false
-e RUN=true
-v /tmp/data:/data
-v /var/run/docker.sock:/var/run/docker.sock
--name dps-tests
${{ env.TEST_DPS_IMAGE }}
- name: Generate file name and artifact name
if: ${{ inputs.coverage }}
id: coverage
run: |
SUFFIX=$(echo "-DCMAKE_BUILD_TYPE=${{ inputs.build_type }} ${{ inputs.build_args }} -DBUILD_TESTING=ON ${{ inputs.args }}" | sha1sum | cut -f 1 -d ' ')
echo "filename=coverage-plgd-dps-${SUFFIX}.json" >> $GITHUB_OUTPUT
echo "filename_obt=coverage-plgd-dps-obt-${SUFFIX}.json" >> $GITHUB_OUTPUT
echo "artifact=plgd-dps-${SUFFIX}-coverage" >> $GITHUB_OUTPUT
- name: Gather coverage data
if: ${{ inputs.coverage }}
run: |
# stop to generate .gcda files
docker stop dps-devsim
# restart to generate report from the .gcda files
docker start dps-devsim
docker exec --workdir "/device-provisioning-client/tools" dps-devsim /bin/bash -c "./collect-coverage.sh --output /data/coverage/${{ steps.coverage.outputs.filename }}"
docker stop dps-devsim
# stop to generate .gcda files
docker stop dps-devsim-obt
# restart to generate report from the .gcda files
docker start dps-devsim-obt
docker exec --workdir "/device-provisioning-client/tools" dps-devsim-obt /bin/bash -c "./collect-coverage.sh --output /data/coverage/${{ steps.coverage.outputs.filename_obt }}"
docker stop dps-devsim-obt
- name: Upload coverage data
if: ${{ inputs.coverage }}
uses: actions/upload-artifact@v4
with:
name: ${{ steps.coverage.outputs.artifact }}
path: /tmp/data/coverage/coverage-plgd-dps-*.json
if-no-files-found: error
retention-days: 1

- name: Collect dps cloud server logs when the test fails
if: ${{ failure() }}
run: |
docker stop dps-devsim
docker logs dps-devsim
- name: Collect dps cloud server (obt) logs when the test fails
if: ${{ failure() }}
run: |
docker stop dps-devsim-obt
docker logs dps-devsim-obt
59 changes: 59 additions & 0 deletions .github/workflows/plgd-dps-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.

name: Run plgd/hub/dps tests with dps_cloud_server

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref_name != 'master' }}

on:
# Triggers the workflow on push or pull request events but only for the master branch
push:
branches: [master]
pull_request:
branches: [master]

# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
inputs:
build_type:
description: "Type of the build"
type: string
default: "Debug"

jobs:
plgd-hub-test:
strategy:
fail-fast: false
matrix:
include:
- name: dps-cloud-server
# same configuration as "plgd-dps-tests" in the SonarCloud scan job, skip for events that trigger both jobs
skip: ${{ github.event_name != 'workflow_dispatch' }}
build_args: ""
- name: dps-cloud-server-asan
build_args: "-DOC_ASAN_ENABLED=ON"
docker_file: docker/apps/Dockerfile.dps-cloud-server
- name: dps-cloud-server-tsan
build_args: "-DOC_TSAN_ENABLED=ON -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang"
docker_file: docker/apps/Dockerfile.dps-cloud-server
- name: dps-cloud-server-tsan
build_args: "-DOC_UBSAN_ENABLED=ON"
docker_file: docker/apps/Dockerfile.dps-cloud-server
- name: dps-cloud-server-faketime-system-time
args: --set-system-time
build_args: "-DPLGD_DPS_FAKETIME_ENABLED=ON"
docker_file: docker/apps/Dockerfile.dps-cloud-server-debug
- name: dps-cloud-server-faketime-mbedtls-time
build_args: "-DPLGD_DPS_FAKETIME_ENABLED=ON"
docker_file: docker/apps/Dockerfile.dps-cloud-server-debug
uses: ./.github/workflows/plgd-dps-test-with-cfg.yml
with:
args: ${{ matrix.args || '' }}
build_args: -DOC_DEBUG_ENABLED=ON -DPLGD_DPS_MAXIMUM_LOG_LEVEL=TRACE -DPLGD_DPS_CLOUD_SERVER_DBG_ENABLED=ON ${{ matrix.build_args }}
build_type: ${{ (github.event_name == 'workflow_dispatch' && inputs.build_type) || 'Debug' }}
docker_file: ${{ matrix.docker_file || 'docker/apps/Dockerfile.dps-cloud-server-debug' }}
skip: ${{ matrix.skip || false }}
2 changes: 1 addition & 1 deletion .github/workflows/plgd-hub-test-with-cfg.yml
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ jobs:
if: ${{ inputs.coverage }}
id: coverage
run: |
SUFFIX=`echo "-DCMAKE_BUILD_TYPE=${{ inputs.build_type }} ${{ inputs.build_args }} ${{ inputs.args }} ${{ inputs.docker_args }} ${{ inputs.hub_args }} ${{ inputs.name }} -DBUILD_TESTING=ON" | sha1sum | cut -f 1 -d ' '`
SUFFIX=$(echo "-DCMAKE_BUILD_TYPE=${{ inputs.build_type }} ${{ inputs.build_args }} ${{ inputs.args }} ${{ inputs.docker_args }} ${{ inputs.hub_args }} ${{ inputs.name }} -DBUILD_TESTING=ON" | sha1sum | cut -f 1 -d ' ')
echo "filename=coverage-plgd-hub-${SUFFIX}.json" >> $GITHUB_OUTPUT
echo "artifact=plgd-hub-${SUFFIX}-coverage" >> $GITHUB_OUTPUT
Expand Down
Loading

0 comments on commit e707e62

Please sign in to comment.