.. include:: vars.rst

.. _section-sec-HO1:

Hands-On 1: Securing Connext DDS Applications
=============================================

Suppose you are the cybersecurity expert in a company called
Patient Monitoring Innovations (PMI). In this exercise, we will
secure a |CONNEXT| project created with |RTI_CODEGEN|
(:command:`rtiddsgen`).

.. only:: cpp98

   .. tip::
     For a brief introduction to |RTI_CODEGEN|, see
     :link_connext_dds_pro_gsg_cpp98:`Run Code Generator, in the Introduction to
     Publish/Subscribe <intro_pubsub_cpp.html#run-code-generator>`.
     Full details are in the :link_codegen_um:`RTI Code Generator
     User's Manual <>`.

.. only:: cpp11

   .. tip::
     For a brief introduction to |RTI_CODEGEN|, see
     :link_connext_dds_pro_gsg_cpp11:`Run Code Generator, in the Introduction to
     Publish/Subscribe <intro_pubsub_cpp.html#run-code-generator>`.
     Full details are in the :link_codegen_um:`RTI Code Generator
     User's Manual <>`.

As a first step, we will use some security artifacts provided with
|CONNEXT|. The applications in your project will use these artifacts
to provide the required configuration and credentials to the |RTI_SP_PRODUCT|,
including the identity and permissions of the |DPs|.
Then we will run the applications to check that we have communication.
Finally, we will verify that eavesdropping is not possible with the
configured level of security.

.. _section-sec-HO1-generating-connext-project:

Generating a Connext DDS Project
--------------------------------
#. Run :command:`rtisetenv_<architecture>` in a new command prompt window, to avoid
   issues with paths and licensing.

   Where :command:`<architecture>` depends on your target machine (where you
   will deploy your completed application). Architecture strings are listed in
   the :link_connext_dds_pro_pn:`RTI Connext DDS Core Libraries Platform Notes <>`.
   Examples are :command:`x64Win64VS2017` and :command:`x64Linux4gcc8.5.0`.

   .. only:: cpp98

      (See :link_connext_dds_pro_gsg_cpp98:`Set Up Environment Variables, in Introduction to
      Publish/Subscribe
      <intro_pubsub_cpp.html#set-up-environment-variables-rtisetenv>`.) |br|
      |br|

   .. only:: cpp11

      (See :link_connext_dds_pro_gsg_cpp11:`Set Up Environment Variables, in Introduction to
      Publish/Subscribe
      <intro_pubsub_cpp.html#set-up-environment-variables-rtisetenv>`.) |br|
      |br|

#. Generate an example from an IDL file. You may want to use the 
   following type definition for this example project:

   .. code-block:: IDL
      :caption: Sample contents of PatientMonitoring.idl

      struct PatientMonitoring {
          string<128> patient_condition;
      };


#. Put the IDL file in a directory called :file:`patient_monitoring_project`.  |br| |br|

#. Run |RTI_CODEGEN| (:command:`rtiddsgen`) from that directory:

   .. only:: cpp98

      .. tabs::

         .. group-tab:: Linux

            .. code-block:: console

               $ cd patient_monitoring_project
               $ rtiddsgen -example <architecture> -language C++ PatientMonitoring.idl

         .. group-tab:: macOS

            .. code-block:: console

               $ cd patient_monitoring_project
               $ rtiddsgen -example <architecture> -language C++ PatientMonitoring.idl

         .. group-tab:: Windows 

            .. code-block:: doscon

               > cd patient_monitoring_project
               > rtiddsgen -example <architecture> -language C++ -ppDisable PatientMonitoring.idl

   .. only:: cpp11

      .. tabs::

         .. group-tab:: Linux

            .. code-block:: console

               $ cd patient_monitoring_project
               $ rtiddsgen -example <architecture> -language C++11 PatientMonitoring.idl

         .. group-tab:: macOS

            .. code-block:: console

               $ cd patient_monitoring_project
               $ rtiddsgen -example <architecture> -language C++11 PatientMonitoring.idl

         .. group-tab:: Windows

            .. code-block:: doscon

               > cd patient_monitoring_project
               > rtiddsgen -example <architecture> -language C++11 -ppDisable PatientMonitoring.idl

.. note::

   We'll use :file:`patient_monitoring_project` as the working directory. Unless
   otherwise indicated, we'll run all commands from this directory.

The generated example will be composed of the following files:

.. only:: cpp98

   .. tabularcolumns:: |\X{50}{100}|\X{50}{100}|

   .. list-table:: Generated Files
      :name: TableGeneratedFilesCpp
      :widths: 20 80
      :header-rows: 1
      :class: longtable

      * - Files
        - Description
      * - :file:`PatientMonitoring.cxx`
          |br|
          :file:`PatientMonitoring.h`
          |br|
          :file:`PatientMonitoringPlugin.cxx`
          |br|
          :file:`PatientMonitoringPlugin.h`
          |br|
          :file:`PatientMonitoringSupport.cxx`
          |br|
          :file:`PatientMonitoringSupport.h`
        - Support for your types in C++
      * - :file:`PatientMonitoring_publisher.cxx`
          |br|
          :file:`PatientMonitoring_subscriber.cxx`
        - Example publisher/subscriber application.
          |br| |br|
          Contains a |DP| with a single
          |DW|/|DR| for the last type
          defined in :file:`PatientMonitoring.idl`.
      * - Makefiles and |br|
          Visual Studio® project files (for Windows applications)
        - Architecture-dependent build files
      * - :file:`USER_QOS_PROFILES.xml`
        - QoS profiles
      * - :file:`README_<architecture>.txt`
        - See this README for instructions on how to open and modify the files.

.. only:: cpp11

   .. tabularcolumns:: |\X{50}{100}|\X{50}{100}|

   .. list-table:: Generated Files
      :name: TableGeneratedFilesCpp11
      :widths: 20 80
      :header-rows: 1
      :class: longtable

      * - Files
        - Description
      * - :file:`PatientMonitoring.cxx`
          |br|
          :file:`PatientMonitoring.hpp`
          |br|
          :file:`PatientMonitoringPlugin.cxx`
          |br|
          :file:`PatientMonitoringPlugin.hpp`
          |br|
        - Support for your types in C++
      * - :file:`PatientMonitoring_publisher.cxx`
          |br|
          :file:`PatientMonitoring_subscriber.cxx`
        - Example publisher/subscriber application.
          |br| |br|
          Contains a |DP| with a single
          |DW|/|DR| for the first type
          defined in :file:`PatientMonitoring.idl`.
      * - Makefiles and |br|
          Visual Studio® project files (for Windows applications)
        - Architecture-dependent build files
      * - :file:`USER_QOS_PROFILES.xml`
        - QoS profiles
      * - :file:`README_<architecture>.txt`
        - See this README for instructions on how to open and modify the files.

Our goal is to secure the generated publisher and subscriber
applications (Alice and Bob, respectively, using the example from
the previous sections).

.. _section-sec-HO1-adding-security-artifacts:

Adding Security Artifacts to Your Project
-----------------------------------------

We'll rely on some files from the :file:`examples` directory in
:file:`rti_workspace` to define the security setup (see
:ref:`section-sec-intro-paths`).
These files will provide the applications you'll build with
the security configuration and credentials required by the |RTI_SP_PRODUCT|.

For convenience, copy these files into your project's top level:

.. tabs::

   .. group-tab:: Linux

      .. code-block:: console

         $ cp -r <path to examples>/dds_security/* ./

      Alternatively, copy/paste all the directories in
      :file:`<path to examples>/dds_security/` to
      :file:`patient_monitoring_project` (the working directory).

   .. group-tab:: macOS

      .. code-block:: console

         $ cp -r <path to examples>/dds_security/* ./

      Alternatively, copy/paste all the directories in
      :file:`<path to examples>/dds_security/` to
      :file:`patient_monitoring_project` (the working directory).

   .. group-tab:: Windows

      .. code-block:: doscon

         > robocopy /E <path to examples>\dds_security\ .

      Alternatively, copy/paste all the directories in
      :file:`<path to examples>\dds_security\` to
      :file:`patient_monitoring_project` (the working directory).

.. note:: 
   
   These certificates and configuration XML files are provided only as 
   examples and should not be used in production. These files are different 
   between host platforms. If you are trying to communicate examples using 
   different host platforms (e.g., Linux and Windows), you would need to copy 
   over the files from one platform to the other so they are the same. 

.. _section-sec-HO1-enabling-security-your-qos-profiles:

Enabling Security in Your QoS Profiles
--------------------------------------

Now modify the QoS profiles (XML) so that the applications will
load the security libraries and the required security artifacts.
To do so, define a profile named **Alice** in your :file:`USER_QOS_PROFILES.xml`
by replacing the existing default profile with the following sample profile:

.. code-block:: xml
   :caption: Sample QoS profile with security enabled.

    <qos_profile name="Alice" base_name="BuiltinQosLib::Generic.Security" is_default_qos="true">
        <domain_participant_qos>
            <property>
                <value>
                    <!-- Certificate Authorities -->
                    <element>
                        <name>dds.sec.auth.identity_ca</name>
                        <value>file:./cert/ecdsa01/ca/ecdsa01RootCaCert.pem</value>
                    </element>
                    <element>
                        <name>dds.sec.access.permissions_ca</name>
                        <value>file:./cert/ecdsa01/ca/ecdsa01RootCaCert.pem</value>
                    </element>
                    <!-- Participant Public Certificate and Private Key -->
                    <element>
                        <name>dds.sec.auth.identity_certificate</name>
                        <value>file:./cert/ecdsa01/identities/ecdsa01Peer01Cert.pem</value>
                    </element>
                    <element>
                        <name>dds.sec.auth.private_key</name>
                        <value>file:./cert/ecdsa01/identities/ecdsa01Peer01Key.pem</value>
                    </element>
                    <!-- Signed Governance and Permissions Documents -->
                    <element>
                        <name>dds.sec.access.governance</name>
                        <value>file:./xml/signed/signed_Governance.p7s</value>
                    </element>
                    <element>
                        <name>dds.sec.access.permissions</name>
                        <value>file:./xml/signed/signed_PermissionsA.p7s</value>
                    </element>
                </value>
            </property>
        </domain_participant_qos>
    </qos_profile>

This profile inherits from the builtin ``BuiltinQosLib::Generic.Security``
profile. It tells your |DP| to use the |SP_BUILTIN| from the
|RTI_SP_PRODUCT_TM|. (For further details, see :link_connext_dds_secure_um:`Properties for
Enabling Security <p2_core/building_apps.html#properties-for-enabling-security>`
in the |SP_UM|.)
Note that not indicating a Security Plugins library will result in a working but
unsecure application.

The profile also configures the following properties:

   * :property:`dds.sec.auth.identity_ca` |br|
     Configures the Identity CA certificate, used to verify that |IdentityCerts|
     from other |DPs| are legitimate.
     Usually, all the participants in your secure system will load the
     same Identity CA certificate. [#]_
   * :property:`dds.sec.access.permissions_ca` |br|
     Configures the Permissions CA certificate, used to verify that the
     Governance and Permissions Documents are legitimate. All the participants
     in your secure system must load the same Permissions CA certificate. [#]_
   * :property:`dds.sec.auth.identity_certificate` |br|
     Configures the |IdentityCert| for the local |DP|.
     Every secure participant should have its own unique |IdentityCert|,
     signed by the Identity CA.
   * :property:`dds.sec.auth.private_key` |br|
     Configures the Private Key for the local |DP|, used
     during the authentication process. Every secure participant should
     have its own unique Private Key, only known to the local participant.
   * :property:`dds.sec.access.governance` |br|
     Configures the |GovernanceDoc|, which defines how your system is
     protected. All the participants in your secure system must load the
     same |GovernanceDoc| [#]_, signed by the Permissions CA.
   * :property:`dds.sec.access.permissions` |br|
     Configures the |PermissionsDoc| for the local |DP|,
     which specifies what it is allowed to do in every |SecDomain|.
     Every secure participant should have its own |PermissionsDoc|, signed
     by the Permissions CA.

.. important::

   A participant that is not configured to use a Security Plugins library will
   omit any security-related properties, resulting in a working but unsecure
   |DP|. Make sure your QoS profile inherits from the builtin
   ``BuiltinQosLib::Generic.Security`` profile or refer to
   :link_connext_dds_secure_um:`Building and Running Security Plugins-Based Applications
   <p2_core/building_apps.html>` in the |SP_UM|.

In later hands-on exercises, you will learn how to generate all
the files listed above. For now, we'll use the example files you
copied in the previous step.


.. [#] Depending on your use case, different |DPs| may trust a different
  Identity CA, for example, when several intermediate CAs exist in your PKI.
  For further details, see :link_connext_dds_secure_um:`Alternative CAs
  <p2_core/elements_dds_secure_system.html#alternative-cas>` in the |SP_UM|.

.. [#] In systems where multiple Permissions Certificate Authorities may exist,
  you can use the
  :property:`access_control.alternative_permissions_cas` property to specify
  alternative Permissions CA certificates. For further details, see
  :link_connext_dds_secure_um:`Governance and Permissions
  <p2_core/elements_dds_secure_system.html#governance-and-permissions>`
  in the |SP_UM|.

.. [#] If not the same, at least |GovernanceDocs| loaded by different
  |DPs| need to be compatible. For further information, see
  :link_connext_dds_secure_um:`Governance Document
  <p2_core/elements_dds_secure_system.html#governance-document>` in the |SP_UM|.

.. _section-sec-HO1-linking-your-applications:

Linking Your Applications Against |RTI_SP_PRODUCT_HEADING| and OpenSSL Libraries
--------------------------------------------------------------------------------

So far, you have generated a |CONNEXT| project and configured its QoS
profiles to load the required security artifacts and enable the |RTI_SP_PRODUCT|.
Now we will build the applications, so you can see them in action.
For convenience, we will link the applications dynamically to both
|CONNEXT| and the OpenSSL libraries (for other linking options, see
:link_connext_dds_secure_um:`Building and Running Security Plugins-Based Applications
<p2_core/building_apps.html>` in the |SP_UM|.

.. note::

   We use ``NDDSHOME`` to refer to the path where the
   |CONNEXT| bundle is installed in your system (in |CONNEXT|
   |CONNEXT_CURRENT_VERSION|, ``NDDSHOME`` is the path to
   rti_connext_dds-|CONNEXT_CURRENT_VERSION|). The installation process is described in
   the |SP_IG_LINK| [#openssl_lm_path]_.

.. _section-sec-HO1-building-application:

Building the Application
^^^^^^^^^^^^^^^^^^^^^^^^

.. tabs::

   .. group-tab:: Linux

      Use the generated Makefile with the ``SHAREDLIB`` variable set
      to ``1`` to force dynamic linking; set ``DEBUG=1`` to build in debug mode:

      .. code-block:: console 

         $ make -f makefile_PatientMonitoring_<architecture> SHAREDLIB=1 DEBUG=1

   .. group-tab:: macOS

      Use the generated Makefile with the ``SHAREDLIB`` variable set
      to ``1`` to force dynamic linking; set ``DEBUG=1`` to build in debug mode:

      .. code-block:: console 

         $ make -f makefile_PatientMonitoring_<architecture> SHAREDLIB=1 DEBUG=1

   .. group-tab:: Windows

      We will build the solution generated by |RTI_CODEGEN|
      with the Debug DLL configuration. You can do this by using the
      :command:`msbuild` command-line tool provided with Visual Studio.
      To do this, open a Visual Studio command prompt and change to the
      :file:`patient_monitoring_project` directory (``cd
      patient_monitoring_project``).
      Then build the Debug DLL solution, which is configured for dynamic
      linking:

      .. code-block:: doscon

         > msbuild /property:Configuration="Debug DLL" PatientMonitoring-<architecture>.sln

      Alternatively, you can open :file:`PatientMonitoring-<architecture>.sln`
      with Visual Studio, as shown in the following screenshot. If you
      choose this method, select the **Debug DLL** option in the
      :guilabel:`Solution Configurations` dropdown menu (1), then select
      **Build** for both **PatientMonitoring_publisher** and
      **PatientMonitoring_subscriber** (2).

      .. figure:: static/HandsOn2.png
          :align: center

          Building the application with Visual Studio 2015.

.. _section-sec-HO1-running-applications:

Running the Applications
------------------------

It's time to see your secure publisher and subscriber working together!
Open two command prompts and configure the environment in both to point
to the location of the dynamic libraries, as explained below.

.. _section-sec-HO1-configuring-environment:

Configuring the Environment in Both Command Prompts
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#. Configure the environment for |CONNEXT| by running
   :command:`rtisetenv_<architecture>` from the |CONNEXT| installation path.

   .. only:: cpp98

      For details, see
      :link_connext_dds_pro_gsg_cpp98:`Set Up Environment Variables, in Introduction to
      Publish/Subscribe
      <intro_pubsub_cpp.html#set-up-environment-variables-rtisetenv>`.

   .. only:: cpp11

      For details, see
      :link_connext_dds_pro_gsg_cpp11:`Set Up Environment Variables, in Introduction to
      Publish/Subscribe
      <intro_pubsub_cpp.html#set-up-environment-variables-rtisetenv>`.
 
   This will update your **PATH** to include the location of
   the |CONNEXT| binaries. |br| |br|

#. Update the shared library environment variable to include the
   directory where the OpenSSL libraries reside. For this example, you
   may want to use OpenSSL debug libraries.

   .. tabs::

      .. group-tab:: Linux

         .. parsed-literal::

            $ export LD_LIBRARY_PATH=$NDDSHOME/third_party/openssl-\ |OPENSSLVERSION|\ /<architecture>/debug/lib:$LD_LIBRARY_PATH

      .. group-tab:: macOS

         .. parsed-literal::

            $ export DYLD_LIBRARY_PATH=$NDDSHOME/third_party/openssl-\ |OPENSSLVERSION|\ /<architecture>/debug/lib:$DYLD_LIBRARY_PATH

      .. group-tab:: Windows

         .. parsed-literal::

           > set PATH=%NDDSHOME%\\third_party\\openssl-\ |OPENSSLVERSION|\ \\<architecture>\\debug\\bin;%PATH%

         If you run the applications from within Visual Studio, you need to set
         up the environment before opening the solution in Visual Studio.

.. tip:: Make sure you set the environment in *both* command prompts.

Checking Communication
^^^^^^^^^^^^^^^^^^^^^^

#. Run the publisher in one of the command prompts and the subscriber in the
   other.

   Do not provide any arguments to the applications, so that they
   communicate in |DOMAIN| *0*. This will be your |SecDomain|. |br| |br|

#. You should see the message **Received data** in the subscriber's command
   prompt, which indicates successful communication:

   .. only:: cpp98

      .. tabs::

         .. group-tab:: Linux

            Publisher:

            .. literalinclude:: snippets/snippets.py
               :language: console
               :start-after: snippet_console_publisher_cpp98_ok
               :end-before: """

            Subscriber:

            .. literalinclude:: snippets/snippets.py
               :language: console
               :start-after: snippet_console_subscriber_cpp98_ok
               :end-before: """

         .. group-tab:: macOS

            Publisher:

            .. literalinclude:: snippets/snippets.py
               :language: console
               :start-after: snippet_console_publisher_cpp98_ok
               :end-before: """

            Subscriber:

            .. literalinclude:: snippets/snippets.py
               :language: console
               :start-after: snippet_console_subscriber_cpp98_ok
               :end-before: """

         .. group-tab:: Windows

            Publisher:

            .. literalinclude:: snippets/snippets.py
               :language: doscon
               :start-after: snippet_doscon_publisher_cpp98_ok
               :end-before: """

            Subscriber:

            .. literalinclude:: snippets/snippets.py
               :language: doscon
               :start-after: snippet_doscon_subscriber_cpp98_ok
               :end-before: """

   .. only:: cpp11

      .. tabs::

         .. group-tab:: Linux

            Publisher:

            .. literalinclude:: snippets/snippets.py
               :language: console
               :start-after: snippet_console_publisher_cpp11_ok
               :end-before: """

            Subscriber:

            .. literalinclude:: snippets/snippets.py
               :language: console
               :start-after: snippet_console_subscriber_cpp11_ok
               :end-before: """

         .. group-tab:: macOS

            Publisher:

            .. literalinclude:: snippets/snippets.py
               :language: console
               :start-after: snippet_console_publisher_cpp11_ok
               :end-before: """

            Subscriber:

            .. literalinclude:: snippets/snippets.py
               :language: console
               :start-after: snippet_console_subscriber_cpp11_ok
               :end-before: """

         .. group-tab:: Windows

            Publisher:

            .. literalinclude:: snippets/snippets.py
               :language: doscon
               :start-after: snippet_doscon_publisher_cpp11_ok
               :end-before: """

            Subscriber:

            .. literalinclude:: snippets/snippets.py
               :language: doscon
               :start-after: snippet_doscon_subscriber_cpp11_ok
               :end-before: """

Congratulations! You have added |RTI_SP_PRODUCT| to your applications.


.. _section-sec-HO1-checking-applications-communicate-securely:

Checking that Your Applications Communicate Securely 
----------------------------------------------------

To check that communication is actually secure, now let's have a
non-secure |CONNEXT| application try to subscribe to the
*PatientMonitoring* |TOPIC|. For convenience, we will use |RTI_ADMINCONSOLE|
as the non-secure subscriber.

Verifying that Eavesdropping Attempts are Frustrated
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

#. Open |ADMINCONSOLE| and join |DOMAIN| *0*.

   .. only:: cpp98

      (For details on using |ADMINCONSOLE|, see
      :link_connext_dds_pro_gsg_cpp98:`Viewing Your Data, in Introduction to Publish/Subscribe
      <intro_pubsub_cpp.html#hands-on-2-viewing-your-data>`. |br| |br|

   .. only:: cpp11

      (For details on using |ADMINCONSOLE|, see
      :link_connext_dds_pro_gsg_cpp11:`Viewing Your Data, in Introduction to Publish/Subscribe
      <intro_pubsub_cpp.html#hands-on-2-viewing-your-data>`.) |br| |br|


#. Notice that your secure |DPs| do not show up in |ADMINCONSOLE|.

   The security configuration of your |SecDomains| requires
   |DPs| to authenticate in order to join the |DOMAIN|.
   Any participant with wrong or no credentials will fail to
   authenticate and will be disallowed from communicating in the |DOMAIN|.
   In this example, the |GovernanceDoc| you copied into the project
   (and added to Alice's XML QoS configuration) protects the endpoint
   discovery with encryption. As a result, intruders and eavesdroppers
   will not have any information regarding the |TOPICs| in your secure
   system. We will show the configuration values to force authentication
   and to enable encryption in :ref:`section-sec-HO2`.

Detecting Eavesdropping Attempts
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

When |ADMINCONSOLE| runs in |DOMAIN| *0*, it sends discovery information
to all other |DPs| in the same |DOMAIN|. When your secure
participants receive this information, they will require |ADMINCONSOLE|
to authenticate. However, |ADMINCONSOLE| does not hold a valid
credential and cannot authenticate, making discovery fail and
preventing further communication.

You might want to detect that an unauthorized |DP| tried
to communicate in your secure system. To do this:

#. Modify your QoS profile to increase the verbosity of the |LoggingPlugin|:

   .. code-block:: xml

       <qos_profile name="Alice" base_name="BuiltinQosLib::Generic.Security" is_default_qos="true">
           <domain_participant_qos>
               <property>
                   <value>
                       <!-- Logging Plugin setup -->
                       <element>
                           <name>com.rti.serv.secure.logging.verbosity</name>
                           <value>WARNING</value>
                       </element>
                       ...

#. Rerun your secure publisher or/and subscriber.

   A message like this should show up in its command prompt:

   .. code-block:: text

      PRESParticipant_getRemoteParticipantInitialSecurityState:unauthenticated remote participant 1018db2.74f9482c.2712840d denied

   This message indicates a failure during the authentication of a
   remote |DP|. It will be logged every time an unauthenticated participant
   attempts to join a |SecDomain| where
   :xmltag:`allow_unauthenticated_participants` is set to :xmlval:`FALSE`.


.. _section-sec-HO1-further-exercises:

Further Exercises
-----------------

So far, we have defined a single QoS profile named Alice to enable the
|RTI_SP_PRODUCT|. Since this profile has the attribute ``is_default_qos=true``, any
|CONNEXT| application loading :file:`USER_QOS_PROFILES.xml` will have the
same security artifacts. This makes it convenient to load the same
|GovernanceDoc| and CA certificates in an example. However, all your
applications will have the same identity and permissions, which is
strongly discouraged. Please note that the authentication succeeds in
this situation since the |DPs| still have valid
credentials, i.e., the Identity CA has issued all the identities.
Also note that the |PermissionsDoc| the publisher and the subscriber
are loading gives them permission to publish and subscribe to any
|TOPIC|, making communication possible.

Give Different Credentials to Each Application in Your System
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

#. To maximize security, different applications should always have different
   identities and permissions. Write a second QoS profile for your project
   in the same XML QoS file. You should end up with the following:

   * A profile called ``Alice`` for the publisher application
   * A profile called ``Bob`` for the subscriber application

   .. tip::

      You may want to have Bob's profile inherit from Alice's, with
      ``base_name="Alice"``. This way, you don't need to specify the
      CA certificates and the |GovernanceDoc| twice in
      :file:`USER_QOS_PROFILES.xml`.

#. Modify Bob's identity and permissions.

   For example, use :file:`ecdsa01Peer02Cert.pem`, :file:`ecdsa01Peer02Key.pem`, and
   :file:`signed_PermissionsB.p7s`.

   Note that :file:`ecdsa01Peer02Key.pem` is password-protected, so use the
   :property:`dds.sec.auth.password` property to specify the password in Bob's
   QoS profile:

   .. code-block:: xml 

      <qos_profile name="Bob" base_name="Alice">
          <domain_participant_qos>
              <property>
                  <value>
                      <!-- Participant Public Certificate and Private Key -->
                      <element>
                          <name>dds.sec.auth.identity_certificate</name>
                          <value>file:./cert/ecdsa01/identities/ecdsa01Peer02Cert.pem</value>
                      </element>
                      <element>
                          <name>dds.sec.auth.private_key</name>
                          <value>file:./cert/ecdsa01/identities/ecdsa01Peer02Key.pem</value>
                      </element>
                      <element>
                          <name>dds.sec.auth.password</name>
                          <value>VG9tQjEy</value>
                      </element>
                      <!-- Signed Permissions Document -->
                      <element>
                          <name>dds.sec.access.permissions</name>
                          <value>file:./xml/signed/signed_PermissionsB.p7s</value>
                      </element>
                  </value>
              </property>
          </domain_participant_qos>
      </qos_profile>

#. Modify the applications' source code in
   :file:`PatientMonitoring_publisher.cxx` and
   :file:`PatientMonitoring_subscriber.cxx` to use these QoS profiles. The
   publisher's |DP| should use the ``Alice`` QoS profile, and the subscriber's
   |DP| should use the ``Bob`` QoS profile.

   .. only:: cpp98

      To do so, you can create your |DPs| with
      ``DDSDomainParticipantFactory::create_participant_with_profile`` (see
      :link_connext_dds_api_cpp:`DomainParticipantFactory in the Traditional C++ API
      Reference <classDDSDomainParticipantFactory.html>`). |br| |br|

   .. only:: cpp11

      To do so, use the default ``QosProvider`` to make your
      |DPs| load their corresponding profiles (see
      :link_connext_dds_api_cpp2:`QosProvider in the Modern C++ API Reference
      <classdds_1_1core_1_1QosProvider.html>`).
      Note that you will need to include :file:`ddscore.hpp`.

      .. code-block:: C++

         #include <dds/core/ddscore.hpp>
         ...

         // Load Bob's QoS
         dds::domain::qos::DomainParticipantQos bob_qos =
              dds::core::QosProvider::Default().participant_qos("PatientMonitoring_Library::Bob");

         // Create a DomainParticipant with Bob's QoS
         dds::domain::DomainParticipant participant(
              domain_id,
              bob_qos);


#. Rebuild your project and run your publisher and subscriber applications.
   You should see communication.


.. _section-sec-HO1-troubleshooting: 

Troubleshooting
---------------

* When I try to run |CODEGEN| (:command:`rtiddsgen`), my system does not
  recognize or find the command.

  Make sure |CONNEXT| is installed correctly.

  .. only:: cpp98

    Also make sure you've correctly set the **PATH** environment variable
    (your **PATH** should include :file:`<NDDSHOME>/bin`). You can run
    :command:`rtisetenv_<architecture>` to add the location of the |CONNEXT|
    binaries to your **PATH** (see
    :link_connext_dds_pro_gsg_cpp98:`Set Up Environment Variables, in Introduction to
    Publish/Subscribe
    <intro_pubsub_cpp.html#set-up-environment-variables-rtisetenv>`). |br| |br|

  .. only:: cpp11

    Also make sure you've correctly set the **PATH** environment variable
    (your **PATH** should include :file:`<NDDSHOME>/bin`). You can run
    :command:`rtisetenv_<architecture>` to add the location of the |CONNEXT|
    binaries to your **PATH** (see
    :link_connext_dds_pro_gsg_cpp11:`Set Up Environment Variables, in Introduction to
    Publish/Subscribe
    <intro_pubsub_cpp.html#set-up-environment-variables-rtisetenv>`). |br| |br|

* When I run |CODEGEN| (:command:`rtiddsgen`), I get this error:

  .. code-block:: text

     The preprocessor 'CL.EXE' cannot be found in your path.

  Make sure your toolchain's preprocessor is available.
  If you are using Visual Studio, make sure you are using a
  Visual Studio command prompt.
  Alternatively, run :command:`rtiddsgen` with the :command:`-ppDisable` option.
  |br| |br|

* When I run |CODEGEN| (:command:`rtiddsgen`), I get warnings stating:

  .. code-block:: text

     File exists and will not be overwritten

  Some files that would normally be generated already
  exist and will not be overwritten. These errors are expected. |br| |br|

* When I run the publisher/subscriber, I get this error:

  .. code-block:: text

     error while loading shared libraries: libnddscpp.so

  Make sure the shared library environment variable includes the
  directory where the |CONNEXT| libraries reside. See
  :ref:`section-sec-HO1-configuring-environment`
  for a solution. |br| |br|

* When I run the publisher/subscriber, I get this error:

  .. code-block:: text

     !open library=libnddssecurity.so

  * Make sure the OpenSSL target bundle provided by RTI
    is installed correctly. [#openssl_lm_path]_ |br| |br|
  * Make sure the shared library environment variable includes the
    directory where OpenSSL libraries reside. See
    :ref:`section-sec-HO1-configuring-environment` for a solution. |br| |br|
  * Make sure your environment is pointing to the correct version of
    the OpenSSL libraries. |br| |br|

* When I run the publisher and subscriber, communication does not occur.

  * Make sure you run both applications from the
    :file:`patient_monitoring_project` directory, so they load the same
    :file:`USER_QOS_PROFILES.xml` file. Note: If the project file for your
    IDE was auto-generated and you are running from within your IDE,
    it should run from that directory automatically. |br| |br|
  * Make sure your applications are loading the right security artifacts or
    artifacts combinations (that is, you don't get a
    ``!certificate verify fail`` error). |br| |br|
  * Be careful with Bob's QoS profile depending on Alice's — you may be
    changing properties in Alice's profile and loading Bob's, or the
    opposite. |br| |br|

* When I run the publisher/subscriber, I get this error:

  .. code-block:: text

     !certificate verify fail

  Make sure your applications are loading the right security artifacts or
  artifacts combinations.


.. [#openssl_lm_path] In the :link_connext_dds_secure_ig:`free <#security_plugins/installation_guide/install_evaluation.html>`
   version (with ``lm`` in the bundle name), OpenSSL is installed automatically 
   when you install the |CONNEXT| host bundle. After installation, OpenSSL will 
   be in ``<installdir>/third_party/openssl-<version>``.
