.. include:: vars.rst

.. _section-sec-HO2:

Hands-On 2: Defining Your System's Security Requirements
========================================================

In this Hands-On, we will define the security requirements for
your project, expressing them in the form of a **Governance Document**.
We will sign this |GovernanceDoc| with the provided Permissions CA.
Lastly, we will tell your secure participants where to find the
new |GovernanceDoc| and we will see how the new security requirements
are applied to your system.

.. note::

   We will use the **OpenSSL CLI** to perform the security operations in the
   generation of the security artifacts. Make sure to include in the path your
   OpenSSL binary directory [#openssl_lm_path]_. The installation process is
   described in the |SP_IG_LINK|.

   Note that the |RTI_SP_PRODUCT| do not depend on OpenSSL to generate these artifacts; you
   can use the security toolkit of your choice. With that said, we recommend
   using |OpenSSL| to make sure that the certificates are in the right format.

.. _section-sec-HO2-specifying-security-requirements:

Specifying the Security Requirements
------------------------------------

If you completed :ref:`section-sec-HO1`, you should have two
applications using |RTI_SP_PRODUCT| to communicate securely. But what does
"securely" actually mean? What kind or what level of security is
being applied? As mentioned in :ref:`section-sec-intro`,
the answers to these questions are in the |GovernanceDoc|, which
defines the security rules that every |DP| in your
|SecDomain| needs to follow. We will now focus on writing a
|GovernanceDoc| to specify your project's security requirements.

|GovernanceDocs| define two levels of rules that can be configured:

* **Domain-level rules**, which affect participants in the |DOMAIN|;
* **Topic-level rules**, which affect |EPs| (|DRs| and |DWs|) for that |TOPIC|.

You will find a description of the currently available
rules in the tables below. For more information, see
these sections in the |SP_UM|:

* :link_connext_dds_secure_um:`Related Governance Rules for Authentication
  <p2_core/authentication.html#related-governance-rules>`
* :link_connext_dds_secure_um:`Related Governance Rules for Access Control
  <p2_core/access_control.html#related-governance-rules>`
* :link_connext_dds_secure_um:`Related Governance Rules for Cryptography
  <p2_core/cryptography.html#related-governance-rules>`

.. list-table:: Domain-Level Rules
   :name: DomainLevelRules
   :widths: 30 40 30
   :header-rows: 1
   :class: longtable

   * - Rule
     - Description
     - Possible values

   * - :xmltag:`allow_unauthenticated_participants`
     - Determines if a secure |DP| is allowed to match a
       participant that is not able to successfully complete the
       authentication process. By disallowing unauthenticated participants,
       we prevent them from publishing or subscribing to |TOPICs| in our
       |SecDomain|. [#]_
     - :xmlval:`TRUE` or :xmlval:`FALSE`
   * - :xmltag:`enable_join_access_control`
     - Determines if the participant-level permissions configured in the
       |PermissionsDoc| are enforced for remote participants.
     - :xmlval:`TRUE` or :xmlval:`FALSE`
   * - :xmltag:`discovery_protection_kind`
     - Configures the |DiscoveryProtection|, determining what level of
       protection is applied to the
       :link_connext_dds_secure_um:`Builtin Secure Discovery Topics
       <p2_core/elements_dds_secure_system.html#builtin-secure-discovery-topics>`.
     - :xmlval:`ENCRYPT`, :xmlval:`ENCRYPT_WITH_ORIGIN_AUTHENTICATION`,
       :xmlval:`SIGN`, :xmlval:`SIGN_WITH_ORIGIN_AUTHENTICATION`, :xmlval:`NONE`
   * - :xmltag:`liveliness_protection_kind`
     - Configures the |LivelinessProtection|, determining what level of
       protection is applied to the
       :link_connext_dds_secure_um:`Builtin Secure Liveliness Topic
       <p2_core/elements_dds_secure_system.html#builtin-secure-liveliness-topic>`.
     - :xmlval:`ENCRYPT`, :xmlval:`ENCRYPT_WITH_ORIGIN_AUTHENTICATION`,
       :xmlval:`SIGN`, :xmlval:`SIGN_WITH_ORIGIN_AUTHENTICATION`, :xmlval:`NONE`
   * - :xmltag:`rtps_protection_kind`
     - Configures the :link_connext_dds_secure_um:`RTPS Protection
       <p2_core/cryptography.html#rtps-protection>`,
       determining what level of protection is applied to RTPS messages.
     - :xmlval:`ENCRYPT`, :xmlval:`ENCRYPT_WITH_ORIGIN_AUTHENTICATION`,
       :xmlval:`SIGN`, :xmlval:`SIGN_WITH_ORIGIN_AUTHENTICATION`, :xmlval:`NONE`
   * - :xmltag:`rtps_psk_protection_kind`
     - Determines how to protect RTPS bootstrapping messages. Read section
       :link_connext_dds_secure_um:`Domain-Level Rules
       <p2_core/elements_dds_secure_system.html#domain-level-rules>` in the
       |SP_UM| for more information.
     - :xmlval:`ENCRYPT`, :xmlval:`SIGN`, :xmlval:`NONE`
   * - :xmltag:`allowed_security_algorithms`
     - Determines the cryptographic algorithms that are allowed in your system.
     - The values are a list of algorithms that depend on whether they are used
       for :xmltag:`digital_signature`, :xmltag:`digital_signature_identity_trust_chain`,
       :xmltag:`key_establishment`, or :xmltag:`symmetric_cipher`. For more
       information read section :link_connext_dds_secure_um:`Domain-Level Rules
       <p2_core/elements_dds_secure_system.html#domain-level-rules>` in the |SP_UM|.

.. list-table:: Topic-Level Rules
   :name: TopicLevelRules
   :widths: 30 40 30
   :header-rows: 1
   :class: longtable

   * - Rule
     - Description
     - Possible values
   * - :xmltag:`enable_discovery_protection`
     - Determines if discovery information updates related to |EPs|
       from this |TOPIC| will be sent with the level of security defined
       in the :xmltag:`discovery_protection_kind` domain-level rule.
     - :xmlval:`TRUE` or :xmlval:`FALSE`
   * - :xmltag:`enable_liveliness_protection`
     - Determines if liveliness updates related to |EPs| from this
       |TOPIC| will be sent with the level of security defined in the
       :xmltag:`liveliness_protection_kind` domain-level rule.
     - :xmlval:`TRUE` or :xmlval:`FALSE`
   * - :xmltag:`enable_read_access_control`
     - Determines if endpoint-level permissions configured in the
       |PermissionsDoc| are enforced for local and remote |DRs|.
     - :xmlval:`TRUE` or :xmlval:`FALSE`
   * - :xmltag:`enable_write_access_control`
     - Determines if endpoint-level permissions configured in the
       |PermissionsDoc| are enforced for local and remote |DWs|.
     - :xmlval:`TRUE` or :xmlval:`FALSE`
   * - :xmltag:`metadata_protection_kind`
     - Configures the :link_connext_dds_secure_um:`Submessage Protection
       <p2_core/cryptography.html#submessage-protection>`,
       determining what level of protection is applied to RTPS submessages from
       |EPs| of the associated |TOPIC|.
     - :xmlval:`ENCRYPT`, :xmlval:`ENCRYPT_WITH_ORIGIN_AUTHENTICATION`,
       :xmlval:`SIGN`, :xmlval:`SIGN_WITH_ORIGIN_AUTHENTICATION`, :xmlval:`NONE`
   * - :xmltag:`data_protection_kind`
     - Configures the :link_connext_dds_secure_um:`Serialized Data Protection
       <p2_core/cryptography.html#serialized-data-protection>`,
       determining what level of protection is applied to the serialized
       payload from |DWs| of the associated |TOPIC|.
     - :xmlval:`ENCRYPT`, :xmlval:`SIGN`, :xmlval:`NONE`

.. [#] A system may allow unauthenticated participants as a way of
   combining older, unsecured applications with newer secure
   applications (not recommended, see
   :link_connext_dds_secure_um:`Using Separate Domains for Secure and Unsecure Participants
   <p3_advanced/best_practices.html#using-separate-domains-for-secure-and-unsecure-participants>`
   in the |SP_UM|).

.. _section-sec-HO2-composing-governance-file-security-requirements:

.. _section-composing-governance-security-requirements:

Composing a Governance Document with the Security Requirements
--------------------------------------------------------------

As the DDS Security expert at Patient Monitoring Innovations (PMI), you are
going to specify the security requirements of your system in a file called
:file:`pmiGovernance.xml`.

Create :file:`pmiGovernance.xml` in the :file:`xml` directory (along with the
XML files we copied from the |CONNEXT| examples) and add the following content:

.. literalinclude:: snippets/pmiGovernance.xml
   :language: xml
   :caption: Sample |GovernanceDoc| that applies to all the |DOMAINs|.
             Different Topics will have a different kind of protection.

Note: The following references to (1), (2), etc. correspond to comments
in the above XML.

This |GovernanceDoc| defines just one configuration, to be applied to any
|DOMAIN| in the system (1). Consequently, all the |DOMAINs| and |TOPICs| in the
system are protected in the same way. In particular, the following rules
are defined (2):

.. tabularcolumns:: |\X{40}{100}|\X{25}{100}|\X{35}{100}|

.. list-table::
    :name: TableDomainRules1
    :widths: 30 10 60
    :header-rows: 1

    * - Domain rule (:xmltag:`domain_rule`)
      - Value
      - Security implications
    * - :xmltag:`allow_unauthenticated_participants`
      - :xmlval:`TRUE`
      - Non-authenticated participants are allowed to publish/subscribe
        unprotected |TOPICs|
    * - :xmltag:`enable_join_access_control`
      - :xmlval:`FALSE`
      - Remote participant-level permissions are not checked
    * - :xmltag:`discovery_protection_kind`
      - :xmlval:`ENCRYPT`
      - Endpoint Discovery will be protected with encryption for |TOPICs|
        setting :xmltag:`enable_discovery_protection` to :xmlval:`TRUE` [#]_
    * - :xmltag:`liveliness_protection_kind`
      - :xmlval:`ENCRYPT`
      - Liveliness assertions will be protected with encryption for |TOPICs|
        setting :xmltag:`enable_liveliness_assertion` to :xmlval:`TRUE` [#]_
    * - :xmltag:`rtps_protection_kind`
      - :xmlval:`NONE`
      - RTPS messages are sent without any additional protection
        (required to allow unauthenticated participants)

Then we can define different levels of protection depending on the |TOPIC|
to protect (3). This Governance specifies a single rule that applies to every
|TOPIC| and protects the user's data with encryption (3.1). We will define the
protection of the *PatientMonitoring* |TOPIC| (3.2) as part of a later exercise.

.. [#] Enabling |DiscoveryProtection| has further implications, as described in
   :link_connext_dds_secure_um:`discovery_protection_kind (domain_rule)
   <p2_core/cryptography.html#discovery-protection-kind-domain-rule>`.

.. [#] Enabling |LivelinessProtection| has further implications, as described in
   :link_connext_dds_secure_um:`discovery_protection_kind (domain_rule)
   <p2_core/cryptography.html#liveliness-protection-kind-domain-rule>`.


.. _section-sec-HO2-signing-governance-file:

Signing the Governance Document
-------------------------------

As mentioned in :ref:`section-sec-securing-domain`, both
Governance and Permissions Documents must be signed by the Permissions CA.
This way, all |DPs| trusting that Permissions CA can make
sure that the |GovernanceDoc| was not forged by an attacker.

We will use the provided Permissions CA's certificate and key to sign the
|GovernanceDoc| that we composed. [#]_

Run the command below to create the signed |GovernanceDoc|
(with PKCS#7 format) named :file:`xml/signed/signed_pmiGovernance.p7s`:

.. tabs::

   .. group-tab:: Linux

      .. code-block:: console

         $ openssl cms -sign -in xml/pmiGovernance.xml -text -out xml/signed/signed_pmiGovernance.p7s -signer cert/ecdsa01/ca/ecdsa01RootCaCert.pem -inkey cert/ecdsa01/ca/private/ecdsa01RootCaKey.pem

   .. group-tab:: macOS

      .. code-block:: console

         $ openssl cms -sign -in xml/pmiGovernance.xml -text -out xml/signed/signed_pmiGovernance.p7s -signer cert/ecdsa01/ca/ecdsa01RootCaCert.pem -inkey cert/ecdsa01/ca/private/ecdsa01RootCaKey.pem
 
   .. group-tab:: Windows

      .. code-block:: doscon

         > openssl cms -sign -in xml\pmiGovernance.xml -text -out xml\signed\signed_pmiGovernance.p7s -signer cert\ecdsa01\ca\ecdsa01RootCaCert.pem -inkey cert\ecdsa01\ca\private\ecdsa01RootCaKey.pem

.. [#] In this example, we have control of the Permissions CA.
   This is not always the case and we may be required to send the
   |GovernanceDoc| to an external entity to get it signed.

.. _section-sec-HO2-updating-qos-profiles-your-project:

Updating the QoS Profiles in Your Project
-----------------------------------------

Now we need to update :file:`USER_QOS_PROFILES.xml` to make your
|DPs| load the new |GovernanceDoc|. Replace the value of
the :property:`dds.sec.access.governance` property as follows:

.. code-block:: xml

    ...
    <!-- Signed Governance and Permissions Documents -->
    <element>
        <name>dds.sec.access.governance</name>
        <value>file:./xml/signed/signed_pmiGovernance.p7s</value>
    </element>
    ...

Here, the ``file:`` prefix means that the signed |GovernanceDoc| will be
loaded from the specified path in the file system. Note that the path is
relative to the working directory from which you run your application
(unless you specify an absolute path).

Another option is to set the value of the
:property:`dds.sec.access.governance` property to the contents of the
|GovernanceDoc|. You can do that by using the ``data:,`` prefix. This is useful
when your application does not have access to a file system. For details, see
:link_connext_dds_secure_um:`DDS Security Properties for Configuring Access Control
<p2_core/access_control.html#properties-for-configuring-access-control>` in the |SP_UM|.


.. _section-sec-HO2-checking-specified-security-rules-applied:

Checking that the Specified Security Rules Are Applied
------------------------------------------------------

It's time to see the changes in your security requirements! We will start
by verifying that your |DPs| can communicate when they load
the new |GovernanceDoc|.

Verifying Communication
^^^^^^^^^^^^^^^^^^^^^^^

#. Run your publisher and subscriber as explained in
   :ref:`section-sec-HO1-running-applications`.

   Note that building the applications is not required, but you still may
   have to set up your environment. |br| |br|

#. You should see the message "Received data" on the
   subscriber side, which indicates that it received samples from the
   publisher.

   .. 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: """


Checking the New Security Rules
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

So far, your |GovernanceDoc| protects the privacy of the user's data by
encrypting the messages' payload. However, it does not protect discovery data,
allowing unauthenticated participants to receive this information. To verify
that these rules are applied, we'll try to subscribe to the *PatientMonitoring*
|TOPIC| with |RTI_ADMINCONSOLE|.

#. 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>`.)

   .. 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>`.)

   Your secure participants should show up in the :guilabel:`DDS Logical View` window. |br| |br|

#. Right-click on the *Example PatientMonitoring* |TOPIC| and select :guilabel:`Subscribe…`. |br| |br|

#. A dialog will prompt you to select the data type; click :guilabel:`OK`. |br| |br|

#. Go to the :guilabel:`Data Visualization` perspective — by default, a
   dialog will give you the option to switch perspectives. |br| |br|

#. Notice that |ADMINCONSOLE|'s subscriber is unable to receive any data
   samples, while your secure subscriber is receiving them.

At this point, you can be sure [#]_ that your applications are using the security
rules you have defined. Congratulations!

.. [#] In :ref:`section-sec-HO5` we will use Wireshark to verify that the
   messages from the publisher application are encrypted on the network.

.. _section-sec-HO2-further-exercises:

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

The |GovernanceDoc| we defined allows unauthenticated participants to
join the |SecDomains| and to receive discovery data. This may be
acceptable for some |TOPICs| or some systems. However, you may have more
restrictive security requirements and want to prevent unauthenticated
participants from communicating at all. Perhaps your security requirements
may vary from one |TOPIC| to another. We will address these two issues in
the following exercises.

.. note::

   Defining the security requirements for a real system is not a trivial
   task. If you plan to deploy a secure system, your organization will
   need an in-house security expert to define the security requirements
   your system needs.

Protecting the Domain
^^^^^^^^^^^^^^^^^^^^^

Now, we want to disallow unauthenticated participants from performing any
kind of communication in your |SecDomains|.

To do so, modify your |GovernanceDoc| to meet the following domain-level rules:

.. list-table::
    :name: TableDomainRules2
    :widths: 30 10 60
    :header-rows: 1

    * - Domain rule (:xmltag:`domain_rule`)
      - Value
      - Security implications
    * - :xmltag:`allow_unauthenticated_participants`
      - :xmlval:`FALSE`
      - Only authenticated participants are allowed in the system
    * - :xmltag:`enable_join_access_control`
      - :xmlval:`TRUE`
      - Permissions are checked for any discovered |DP|
    * - :xmltag:`rtps_protection_kind`
      - :xmlval:`SIGN`
      - All RTPS messages in the system are signed

Make sure the Permissions CA signs the modified |GovernanceDoc|
(see :ref:`section-sec-HO2-signing-governance-file`); otherwise the
changes will not be applied.

After applying this configuration, only authenticated and authorized
participants will be allowed to join the system. Since RTPS messages
are signed, only authenticated and authorized participants will be
allowed to write messages to the system.

.. _section-adding-topic-rule-PatientMonitoring:

Adding a Topic Rule for the PatientMonitoring Topic
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Your Governance may define different levels of protection, depending on
the |TOPIC| to be protected.

Write a second |TOPIC| rule (:xmltag:`topic_rule`) to
protect the *Example PatientMonitoring* |TOPIC| as follows:

.. list-table::
   :name: TableDomainRules3
   :widths: 30 10 60
   :header-rows: 1

   * - Topic rule (:xmltag:`topic_rule`)
     - Value
     - Security implications
   * - :xmltag:`enable_discovery_protection`
     - :xmlval:`TRUE`
     - Endpoint discovery data is protected (encrypted, as
       specified by :xmltag:`discovery_protection_kind`)
   * - :xmltag:`enable_liveliness_protection`
     - :xmlval:`TRUE`
     - Liveliness assertions are protected [#]_ (encrypted, as
       specified by :xmltag:`liveliness_protection_kind`)
   * - :xmltag:`enable_read_access_control`
     - :xmlval:`TRUE`
     - Enforce local endpoint-level permissions on locally created |DRs|;
       enforce remote endpoint-level permissions on remotely discovered |DRs|
   * - :xmltag:`enable_write_access_control`
     - :xmlval:`TRUE`
     - Enforce local endpoint-level permissions on locally created |DWs|;
       enforce remote endpoint-level permissions on remotely discovered |DWs|
   * - :xmltag:`metadata_protection_kind`
     - :xmlval:`ENCRYPT`
     - |DWs|' and |DRs|'s outgoing submessages are encrypted [#]_
   * - :xmltag:`data_protection_kind`
     - :xmlval:`ENCRYPT`
     - Payloads are encrypted

The |GovernanceDoc| is parsed from top to bottom (for more information, see
:link_connext_dds_secure_um:`How the Governance Document is Interpreted
<p2_core/elements_dds_secure_system.html#how-the-governance-document-is-interpreted>`
in the |SP_UM|.
Therefore, you must add your new :xmltag:`topic_rule` before the wildcard rule
that matches all topics (the one with a :xmltag:`topic_expression` value of
:xmlval:`*`).

After applying the configuration, *PatientMonitoring* updates are exchanged
encrypted, so an eavesdropper will not be able to have access to that data.
Make sure the Permissions CA signs the modified |GovernanceDoc|
(see :ref:`section-sec-HO2-signing-governance-file`); otherwise the
changes will not be applied.

.. [#] The value of this attribute matters only if the |DW|'s LIVELINESS
   QosPolicy is :xmlval:`AUTOMATIC` or :xmlval:`MANUAL_BY_PARTICIPANT`. See
   :link_connext_dds_secure_um:`enable_liveliness_protection (topic_rule)
   <p2_core/cryptography.html#enable-liveliness-protection-topic-rule>`
   in the |SP_UM|.

.. [#] These submessages include, but are not limited to, :submsg:`DATA`,
   :submsg:`HEARTBEAT`, :submsg:`ACKNACK`, and :submsg:`GAP`. For more
   information, see :link_connext_dds_secure_um:`Submessage Protection
   <p2_core/cryptography.html#submessage-protection>` in the |SP_UM|.

.. [#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>``.

.. _section-sec-HO2-troubleshooting:

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

* When I run :command:`openssl cms`, I get this error:

  .. code-block:: text

     WARNING: can't open config file: <default openssl builtin path>/openssl.cnf

  Set the environment variable ``OPENSSL_CONF`` to :file:`./cert/openssl.cnf`.
