Cloud Edge Provisioning#

Introduction#

What you’ll learn

In this module, you’ll use a Connext Cloud Edge Provisioning Service to secure a Connext system without generating or distributing a single certificate by hand.

You will do the following:

  • Run an edge Connext system without security enabled and see how a simulated attacker can read its data

  • Create a Connext Cloud Edge Provisioning Service

  • Provision each DomainParticipant with its security artifacts and enable the Security Plugins

  • Revoke one DomainParticipant from the cloud and watch it lose access

By default, a Connext domain is not encrypted. Any application on the same network that speaks DDS can discover your Topics and read your data, without any credentials.

An attacker reading data from an unsecured Connext domain

On an unsecured domain, an attacker can eavesdrop on the data.#

The RTI Security Plugins solve this issue, but they require a set of security artifacts. Some artifacts are unique to each secured DomainParticipant: its Identity Certificate, Private Key, and Permissions Document. Others are shared across the system: the Identity CA and Permissions CA certificates, Governance Document, Pre-Shared Key, and Certificate Revocation List. While not every system requires all of these artifacts, you’ll configure each one in this module.

Manually generating, distributing, and renewing these files before they expire is traditionally a challenge. An Edge Provisioning Service does these tasks for you: an agent on each node automatically requests its required artifacts and keeps them up to date.

An agent on each edge node requests its security artifacts from an Edge Provisioning Service in Connext Cloud, which delivers and renews them automatically

Each node runs an agent that requests its security artifacts from the Edge Provisioning Service and keeps them up to date.#

The commands in this module use the home automation publisher and subscriber from the Publish-Subscribe module, but the same steps apply to any Connext system.

How to complete this module#

To complete this module, you’ll need the following:

  • A free Connext Cloud account.

  • An rticloud CLI installation. Remember to run rticloud configure and choose us-east-2.

  • A Connext 7.7.0 or newer installation on the edge machine. If Connext is not installed, the rticloud gateway can help you install it. You can also follow the Installation guide.

  • A clone of the rticonnextdds-examples GitHub repository on the edge machine.

Cloning the GitHub repository

Clone the GitHub repository with the following command:

$ git clone --recurse-submodule https://github.com/rticommunity/rticonnextdds-examples.git

The code for this module is located in the tutorials/publish_subscribe directory. See the README.md files for additional instructions.

This guide is designed for Connext 7.7.0 or newer. For Connext 7.3.1, checkout the branch release/7.3.1.

It’s recommended to have completed the Publish-Subscribe module, but not required.

1. Run the edge applications#

Start a Connext system on the edge machine you want to secure. This edge machine can be your own computer.

You will run two applications, and each one needs its own directory: later in this module, every application gets its own security artifacts and QoS profile. Set up one directory named window-01 for the publisher and another named alert-system for the subscriber. The examples use domain ID 0 by default.

Install the Connext Python package with pip install rti.connext if you haven’t already. See Python installation.

Create one directory per application:

$ cd rticonnextdds-examples/tutorials/publish_subscribe
$ cp -r py window-01
$ cp -r py alert-system

In the first terminal, run the subscriber (the alert system):

$ cd alert-system
$ python home_automation_subscriber.py

In the second terminal, run the publisher (the window sensor):

$ cd window-01
$ python home_automation_publisher.py Window-01 LivingRoom

Build the applications, then create one directory per application:

$ cd rticonnextdds-examples/tutorials/publish_subscribe/c++11
$ mkdir -p build
$ cd build
$ cmake -DBUILD_SHARED_LIBS=ON ..
$ cmake --build .
$ cd ..
$ cp -r build window-01
$ cp -r build alert-system

In the first terminal, run the subscriber (the alert system):

$ cd alert-system
$ ./home_automation_subscriber

In the second terminal, run the publisher (the window sensor):

$ cd window-01
$ ./home_automation_publisher Window-01 LivingRoom

The full instructions, including other programming languages, are in the Publish-Subscribe module.

The subscriber should print warnings like this:

WARNING: Window-01 in LivingRoom is open!

Keep both applications running for the rest of this module.

Now play the attacker. In a third terminal, run RTI DDS Spy, a tool included with your Connext installation that subscribes to everything it finds on the domain:

$ rtiddsspy -mode USER

DDS Spy prints the “WindowStatus” data as it is published:

RTI DDS Spy built with RTI Connext version: 7.7.0
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
rtiddsspy is listening for data, press CTRL+C to stop it.

16:54:41 New data          from 172.22.81.6    : topic="WindowStatus" type="DeviceStatus"
sensor_name: "Window-01"
room_name: "LivingRoom"
is_open: false

16:54:43 Modified instance from 172.22.81.6    : topic="WindowStatus" type="DeviceStatus"
sensor_name: "Window-01"
room_name: "LivingRoom"
is_open: true

Nothing stopped the attack; a process that you never authorized is reading your data. Stop DDS Spy with CTRL+C and let’s fix that.

2. Create an Edge Provisioning Service#

Create the Edge Provisioning Service in the Connext Cloud dashboard:

  1. Open the Connext Cloud dashboard.

  2. Go to Edge Provisioning.

  3. Select Create Edge Provisioning.

  4. Name the service home-automation-eps.

  5. Keep the default settings.

  6. Review the settings and create the service.

Wait until the service shows the Active status before continuing.

3. Secure the domain#

The Edge Provisioning Service issues a set of security artifacts for each DomainParticipant. Once you configure the participants to use them, the domain is authenticated and encrypted, and the attacker is locked out.

Applications provisioned by the *Edge Provisioning Service* communicating securely within a Connext domain

Each DomainParticipant gets its security artifacts from the Edge Provisioning Service and communicates securely within the domain.#

Start the edge-sync agent#

The rticloud edge-sync agent command enrolls a DomainParticipant with the service, downloads its security artifacts, and renews them before they expire.

Open a new terminal in the window-01 directory and another one in the alert-system directory, then start one agent in each terminal:

# In the window-01 directory
$ rticloud edge-sync agent --deployment-name window-01 --connext-dir connext-artifacts
# In the alert-system directory
$ rticloud edge-sync agent --deployment-name alert-system --connext-dir connext-artifacts

Follow the interactive prompts:

  1. Select My Connext Cloud account (operator login).

  2. Select home-automation-eps if you are asked for a service.

The agent enrolls with the identity you passed in --deployment-name and picks the default domain ID 0 and the default participant template. It then downloads the artifacts into the connext-artifacts directory and shows them in a terminal UI, where you can also renew any of them manually.

Note

Keep both agents running while you continue the tutorial. If you stop an agent, run rticloud edge-sync agent again from the same directory to restart it. Use rticloud edge-sync agent reset to reset the configuration if you want to start over.

Enable the Security Plugins in the QoS profile#

Now we have the security artifacts, but they aren’t being used yet. Point each DomainParticipant at its own artifacts by editing its USER_QOS_PROFILES.xml. In window-01/USER_QOS_PROFILES.xml and alert-system/USER_QOS_PROFILES.xml, replace this block:

<base_name>
    <element>BuiltinQosLib::Generic.StrictReliable</element>
</base_name>

with the following configuration. The only difference between the two files is the deployment name in the last three paths, so use the tab that matches the directory you are editing:

<base_name>
    <element>BuiltinQosSnippetLib::Feature.Security.Enable</element>
</base_name>
<participant_factory_qos>
    <monitoring>
        <enable>false</enable>
    </monitoring>
</participant_factory_qos>
<domain_participant_qos>
    <property>
        <value>
            <element>
                <name>dds.sec.auth.identity_ca</name>
                <value>file:connext-artifacts/0/identity_ca.crt</value>
            </element>
            <element>
                <name>dds.sec.access.permissions_ca</name>
                <value>file:connext-artifacts/0/permissions_ca.crt</value>
            </element>
            <element>
                <name>dds.sec.crypto.rtps_psk_secret_passphrase</name>
                <value>file:connext-artifacts/0/psk_secret.key</value>
            </element>
            <element>
                <name>dds.sec.crypto.rtps_psk_secret_passphrase_extra</name>
                <value>file:connext-artifacts/0/psk_secret_extra.key</value>
            </element>
            <element>
                <name>dds.sec.auth.crl</name>
                <value>file:connext-artifacts/0/crl.pem</value>
            </element>
            <element>
                <name>dds.sec.access.governance</name>
                <value>file:connext-artifacts/0/governance.p7s</value>
            </element>
            <element>
                <name>dds.sec.auth.identity_certificate</name>
                <value>file:connext-artifacts/0/window-01/default-participant-template/identity.crt</value>
            </element>
            <element>
                <name>dds.sec.auth.private_key</name>
                <value>file:connext-artifacts/0/window-01/default-participant-template/identity.key</value>
            </element>
            <element>
                <name>dds.sec.access.permissions</name>
                <value>file:connext-artifacts/0/window-01/default-participant-template/permissions.p7s</value>
            </element>
        </value>
    </property>
</domain_participant_qos>
<base_name>
    <element>BuiltinQosSnippetLib::Feature.Security.Enable</element>
</base_name>
<participant_factory_qos>
    <monitoring>
        <enable>false</enable>
    </monitoring>
</participant_factory_qos>
<domain_participant_qos>
    <property>
        <value>
            <element>
                <name>dds.sec.auth.identity_ca</name>
                <value>file:connext-artifacts/0/identity_ca.crt</value>
            </element>
            <element>
                <name>dds.sec.access.permissions_ca</name>
                <value>file:connext-artifacts/0/permissions_ca.crt</value>
            </element>
            <element>
                <name>dds.sec.crypto.rtps_psk_secret_passphrase</name>
                <value>file:connext-artifacts/0/psk_secret.key</value>
            </element>
            <element>
                <name>dds.sec.crypto.rtps_psk_secret_passphrase_extra</name>
                <value>file:connext-artifacts/0/psk_secret_extra.key</value>
            </element>
            <element>
                <name>dds.sec.auth.crl</name>
                <value>file:connext-artifacts/0/crl.pem</value>
            </element>
            <element>
                <name>dds.sec.access.governance</name>
                <value>file:connext-artifacts/0/governance.p7s</value>
            </element>
            <element>
                <name>dds.sec.auth.identity_certificate</name>
                <value>file:connext-artifacts/0/alert-system/default-participant-template/identity.crt</value>
            </element>
            <element>
                <name>dds.sec.auth.private_key</name>
                <value>file:connext-artifacts/0/alert-system/default-participant-template/identity.key</value>
            </element>
            <element>
                <name>dds.sec.access.permissions</name>
                <value>file:connext-artifacts/0/alert-system/default-participant-template/permissions.p7s</value>
            </element>
        </value>
    </property>
</domain_participant_qos>

Here is what you just configured:

  • BuiltinQosSnippetLib::Feature.Security.Enable loads the Security Plugins into the DomainParticipant.

  • The identity_ca (Identity CA) and permissions_ca (Permissions CA) certificates are the trust anchors: a DomainParticipant only talks to peers whose credentials were issued by these authorities.

  • The identity_certificate and private_key are this DomainParticipant’s own Identity Certificate and Private Key. These artifacts enable window-01 to verify its identity.

  • The Permissions Document (permissions) states which Topics this DomainParticipant is allowed to publish and subscribe to, and the Governance Document (governance) defines the protection rules for the Domain and its Topics (what gets signed and encrypted).

  • The crl is the Certificate Revocation List (CRL), the list of credentials that are no longer trusted. You’ll use it in the next section.

  • The two rtps_psk_secret_passphrase properties enable RTPS Pre-Shared Key (PSK) protection, which encrypts RTPS traffic, including discovery, so an outsider can’t even see which Topics exist. The _extra property holds a second passphrase, which lets you rotate keys without interrupting communication.

For the full reference on these properties, see the Security Plugins User’s Manual .

Run the applications on a secured domain#

Stop the publisher and subscriber with CTRL+C. Then restart them from their respective directories, following the same procedure as in step 1.

In the alert system terminal:

$ python home_automation_subscriber.py

In the window sensor terminal:

$ python home_automation_publisher.py Window-01 LivingRoom

In the alert system terminal:

$ ./home_automation_subscriber

In the window sensor terminal:

$ ./home_automation_publisher Window-01 LivingRoom

The applications continue communicating as before, and the alert system still prints its warnings.

Now run the simulated attacker again:

$ rtiddsspy -mode USER

This time it prints nothing. DDS Spy has no Identity Certificate and no PSK passphrase, so it can’t even discover the applications, let alone read their data.

4. Revoke an application#

Suppose you discover that one of your nodes has been compromised and you want to cut it off. You don’t need to touch the edge machine: revoke it from the cloud.

window-01 revoked from Connext Cloud and rejected by the alert system

Revoking window-01 adds its certificate to the revocation list, which the alert-system agent downloads and applies.#

  1. Open the Connext Cloud dashboard and go to Edge Provisioning.

  2. Open home-automation-eps.

  3. Go to the Fleet tab and the Participants sub-tab.

  4. Find the window-01 row and select at the end of the row to open its actions menu.

  5. Select Revoke Participant.

Look at the alert system: it may still be receiving data from window-01. This is expected. Revocation takes effect once the other applications download the updated CRL, which the agent does automatically on its own schedule.

To see it right away, switch to the terminal UI of the alert-system agent, select the crl row, and press ENTER to renew it.

The alert system stops printing warnings and logs a security error instead:

ERROR [...|VALIDATE REMOTE PARTICIPANT IDENTITY|CHECK STATUS|LC:Security]
RTI_Security_CertHelper_verifyCertificate: ...
"m":"X509_verify_cert returned 0 with error 23: certificate revoked
subject name: /O=ces-home-automation-eps-.../DC=0/OU=default-participant-template/CN=window-01

ERROR [...|VALIDATE REMOTE PARTICIPANT IDENTITY|CHECK STATUS|LC:Security]
RTI_Security_Authentication_validateCertificateChain: ...
"m":"Identity verification failed. Make sure it was signed by the right authority."

This error is the expected result, not a problem with your setup. Reading it from the inside out:

  • CN=window-01 in the subject name identifies the DomainParticipant being rejected.

  • error 23: certificate revoked is the reason the check failed.

  • VALIDATE REMOTE PARTICIPANT IDENTITY means the alert system is rejecting a remote DomainParticipant, not complaining about its own credentials.

window-01 is still running and still writing samples, but nothing on the domain authenticates it anymore, so its data goes nowhere. The alert system logs this error each time window-01 retries authentication.

Switch to the terminal UI of the window-01 agent and try to renew any artifact. The renewal fails: the agent shows a message indicating that this DomainParticipant has been revoked and its credentials are rejected by the server.

Congratulations! You secured a Connext domain with artifacts provisioned from the cloud, and you revoked a compromised application without touching the edge machine.

Learn more#

This module used the default domain and participant templates and enrolled each DomainParticipant with your operator login. For a real fleet, you would define your own governance and permissions templates and enroll DomainParticipants with enrollment tokens instead of operator credentials, so no human has to log in on each node.

Next Steps

To learn what the Security Plugins do under the hood, and to configure authentication, access control, and cryptography yourself, see the Securing your applications module.

More information about Security Plugins:

Was this page helpful?

Back to Learn