.. include:: ../vars.rst

.. _chapter-elements-dds-secure-system:

*********************************************
Elements of a |RTI_SP_PRODUCT_HEADING| System
*********************************************

This chapter covers all the elements that you need to secure a Connext DDS application.

.. _section-sp-properties:

|RTI_SP_PRODUCT_HEADING| Properties
===================================

To enable and configure the |RTI_SP_PRODUCT|, we use properties defined in the |DP|'s PROPERTY QosPolicy (see :link_connext_dds_pro_um:`PROPERTY QosPolicy (DDS Extension) in the Core Libraries User’s Manual <#users_manual/PROPERTY_Qos.htm>`). You can set these properties in code (see :link_connext_dds_api_cpp:`RTI Connext C++ API: PROPERTY <group__DDSPropertyQosModule.html>`) or in XML, similar to how you would set transport properties (see :link_connext_dds_pro_um:`Transport Properties in the Core Libraries User’s Manual <#users_manual/Transport_Properties.htm>`).

.. note::

  You can include environment variables within XML tags and attributes by using the following notation:  ``$(MY_VARIABLE)``. See :link_connext_dds_pro_um:`Using Environment Variables in XML in the Core Libraries User's Manual <#users_manual/Using_Environment_Variables_in_XML.htm>`.


There are three kinds of properties to configure the |RTI_SP_PRODUCT| (you can use a combination of them):

#. Properties starting with :property:`dds.sec.` are defined in the DDS Security standard, and provide the functionality specified there. They allow you to configure features of specific plugins (authentication, access control, etc.).
#. Properties starting with :property:`com.rti.serv.secure.` (assuming you used :property:`com.rti.serv.secure` as the prefix to load the plugin, see :numref:`Properties for Enabling Security`) are implementation-specific. These properties are used for extra functionality or for parameters that can be configured according to the |SEC_SPEC| but where no configuration method is specified.
#. Properties containing :property:`trust_plugins.` are not exclusive to the
   shipped builtin security plugins; they affect custom security plugins as well. For
   example, there is a property that controls how much time to allow an
   authentication handshake to continue before aborting that handshake,
   independently of the loaded security plugins. The Authentication Plugin's
   implementation determines the detailed contents of the handshake messages,
   but when to send the handshake messages does not depend on the loaded
   security plugins.

.. note::

  For brevity, in this document we omit the :property:`com.rti.serv.secure.`
  prefix when referring to implementation-specific properties; we will still
  use the full name for properties defined by the DDS Security standard and
  properties affecting any loaded security plugins.

:ref:`p2_core/authentication:Authentication`,
:ref:`p2_core/access_control:Access Control`,
:ref:`p2_core/cryptography:Cryptography`, and
:ref:`p2_core/logging:Security Events and Logging` describe the properties to configure each of the plugins.
:ref:`section-elements-global-props` describe the
properties relevant for all plugins.
:ref:`p2_core/building_apps:Building and Running |RTI_SP_PRODUCT_HEADING|-Based Applications`
describes the properties for enabling the |RTI_SP_PRODUCT|. Alternatively, you
can make your profile inherit from the ``Generic.Security builtin`` profile
(which loads the security plugins dynamically).

All the |RTI_SP_PRODUCT| properties are validated when the |DP| and the plugin are created;
for more information, see
:link_connext_dds_pro_um:`Property validation in the Core Libraries User’s Manual <#users_manual/PROPERTY_Qos.htm#PropertyValidationUM>`.

In order to have a successful |RTI_SP_PRODUCT| properties validation, you cannot
add implementation-specific properties (e.g., properties starting with
:property:`com.rti.serv.secure.` [#f1]_) without first specifying the property
:property:`com.rti.serv.load_plugin`. In the same way, you cannot disable the
|RTI_SP_PRODUCT| by just removing the :property:`com.rti.serv.load_plugin`,
it is also necessary to remove the rest of the properties of the |RTI_SP_PRODUCT|.

Here are some examples:

* Correct scenario.

  .. code-block:: xml

    ...
    <property>
      <value>
        <element>
          <name>com.rti.serv.load_plugin</name>
          <value>com.rti.serv.secure</value>
        </element>
        <element>
          <name>com.rti.serv.secure.library</name>
          <value>nddssecurity</value>
        </element>
        <element>
          <name>com.rti.serv.secure.create_function</name>
          <value>RTI_Security_PluginSuite_create</value>
        </element>
      </value>
    </property>
    ...


* Incorrect scenario. The properties :property:`com.rti.serv.secure.create_function` and :property:`com.rti.serv.secure.library` will be considered invalid, and (by default) the participant creation will fail with an error.

  .. code-block:: xml

    ...
    <property>
      <value>
        <element>
          <name>com.rti.serv.secure.library</name>
          <value>nddssecurity</value>
        </element>
        <element>
          <name>com.rti.serv.secure.create_function</name>
          <value>RTI_Security_PluginSuite_create</value>
        </element>
      </value>
    </property>
    ...


For further details and configuration options that control the behavior of
property validation, see
:link_connext_dds_pro_um:`Property Validation in the RTI Connext DDS Core Libraries User's Manual <#users_manual/PROPERTY_Qos.htm#PropertyValidationUM>`.

.. note::

  You must set the security-related participant properties before you create a participant (see :numref:`Properties for Enabling Security`). You cannot create a participant without security and then call ``DomainParticipant::set_qos()`` with security properties, even if the participant has not yet been enabled.


.. _section-elements-global-props:

|RTI_SP_PRODUCT_HEADING| Global Properties
------------------------------------------

Each of the plugins in |RTI_SP_PRODUCT| processes properties independently.
This is why most properties are listed and described in a plugin-specific context.
However, the properties in
:numref:`DDS Security Properties for Configuring |RTI_SP_PRODUCT|` are relevant
for all |RTI_SP_PRODUCT|. The description notes if the property is available in
the |SP_BUILTIN|, the |LIGHT_SP_BUILTIN|, or both.

.. list-table:: DDS Security Properties for Configuring |RTI_SP_PRODUCT|
  :name: DDS Security Properties for Configuring |RTI_SP_PRODUCT|
  :widths: 40 60
  :header-rows: 1
  :class: longtable

  * - Property Name
    - Property Value Description

  * - :property:`dds.participant.trust_plugins.expiration_advance_notice_duration.sec`
    - :req:`Optional`

      **Available in:** |SP_BUILTIN|

      Controls how much time (in seconds) in advance the
      :link_connext_dds_api_cpp2:`on_invalid_local_status_advance_notice<classdds_1_1domain_1_1DomainParticipantListener.html>`
      *DomainParticipantListener* callback function should notify the user when
      a local |DP|'s security artifact (|IdentityCert| or |PermissionsDoc|)
      is about to expire. For more information, see
      :ref:`p2_core/authentication:Dynamic Certificate Expiration of the Local |DP|`.

      :type:`Integer`: :value:`[0, INT_MAX]`.

      Default: :value:`0`

  * - :property:`dds.participant.trust_plugins.expiration_advance_notice_reminder_period.sec`
    - :req:`Optional`

      **Available in:** |SP_BUILTIN|

      Once it's time to start the advance notifications of the local |DP|'s
      impending security artifact (|IdentityCert| or |PermissionsDoc|)
      expiration, this property controls how often these notifications happen.
      Notifications will happen at this period until the artifact finally
      expires or gets updated such that its expiration date is beyond the
      current time plus the advance notice duration.
      For more information, see
      :ref:`p2_core/authentication:Dynamic Certificate Expiration of the Local |DP|`.

      :type:`Integer`: :value:`[1, INT_MAX]`.

      Default: :value:`1`

  * - :property:`com.rti.serv.secure.files_poll_interval` [#f1]_
    - :req:`Optional`

      **Available in:** |SP_BUILTIN| and |LIGHT_SP_BUILTIN|

      The interval at which the |RTI_SP_PRODUCT| check for any changes in the
      files it tracks.
      The |RTI_SP_PRODUCT| can currently track CRL, |IdentityCert|,
      |PermissionsDoc|, and pre-shared key passphrase files (primary and extra),
      provided that each of them is configured with the prefix :value:`file:`
      (or no prefix) and is populated with valid data. A
      :property:`files_poll_interval` value of :value:`0` will disable tracking
      of any files.

      To track all the files, the |RTI_SP_PRODUCT| will create a separate thread dedicated to
      periodically checking if the contents of any of the files have changed.
      The :property:`files_poll_interval` property configures the length of this
      interval in seconds. If the contents have changed to other valid data,
      then the |RTI_SP_PRODUCT| will use this new data. In the context of the CRL file change,
      the newly-revoked |DPs| will be removed. If the file is deleted or the
      contents have changed to invalid content, then the |RTI_SP_PRODUCT| will continue using
      the previous data.

      This property is not mutable.

      :type:`Integer`: :value:`[0, INT_MAX]`

      Default: :value:`5`

.. [#f1] Assuming you used :property:`com.rti.serv.secure` as the prefix to load the plugin, see :numref:`Properties for Enabling Security`.


Public Key Infrastructure (PKI)
===============================

The |SP_BUILTIN| use public-key cryptography to establish a secure and authenticated
communication between |DPs|. This includes mutually authenticating the
participants, which involves validating their identities against the Identity
Certificate Authority (CA) and establishing a |SharedKey| between them. It also
includes validating the Governance and |PermissionsDocs| against a common
Permissions CA.


Identity Certificates
---------------------

To be correctly authenticated in the system, every secure |DP| needs an
Identity, consisting of two artifacts:

* The |IdentityCert| is a X.509 digital certificate (in PEM format) that
  includes a Public Key and binds it to the Distinguished Name (subject name)
  for that |DP|. The |IdentityCert| is signed by the issuer Certificate
  Authority (normally the Identity CA, but it can be an intermediate CA), who
  certifies that the Public Key corresponds to the entity whose information is
  in the certificate. To specify the |IdentityCert| to your |DP|, use the
  :property:`dds.sec.auth.identity_certificate` property (see
  :numref:`DDS Security Properties for Configuring Access Control`).
* The Private Key may be a 2048-bit RSA private key, or a 256-bit Elliptic Curve
  Key. The |RTI_SP_PRODUCT| for OpenSSL support standard and PSS padding RSA
  private keys. The |RTI_SP_PRODUCT| for wolfSSL support only standard padding
  RSA private keys.
  To provide the Private Key to your |DPs|, use the
  :property:`dds.sec.auth.private_key` property (see
  :numref:`DDS Security Properties for Configuring Authentication`).

To prevent attackers from forging their own identities, all the |IdentityCerts|
in your system must be signed by a common Identity CA. As part of the
authentication process, secure |DPs| will use the Identity CA certificate to
validate the identity of discovered peers. Alternatively, |IdentityCerts| can be
issued by subordinate CAs that chain up to the Identity CA, creating a chain of
trust (see :ref:`p2_core/authentication:Identity Certificate Chaining`). The
Identity CA certificate must be an X.509 certificate and it can be self-signed
if it is a root CA or signed by some other CA public key if it is a subordinate
CA. The Identity CA certificate is provided by the
:property:`dds.sec.auth.identity_ca` property.


The basicConstraints X.509 v3 extension
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

According to `RFC 5280, section 4.2.1.9 <https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.9>`_,
X.509 v3 CAs must have the ``basicConstraints`` v3 extension. An example is in `this configuration file <https://github.com/openssl/openssl/blob/openssl-3.5.5/apps/openssl.cnf#L149>`_:

.. code-block:: text

  [ req ]
  x509_extensions	= v3_ca	# The extensions to add to the self signed cert

  [ v3_ca ]
  # Extensions for a typical CA
  basicConstraints = critical,CA:true


When a certificate is X.509 v3, its text contains

.. code-block:: text

  Certificate:
      Data:
          Version: 3 (0x2)


When a certificate is X.509 v1, its text contains

.. code-block:: text

  Certificate:
      Data:
          Version: 1 (0x0)


.. warning::

    When using the |RTI_SP_PRODUCT| for OpenSSL, an X.509 v3 Identity CA must have ``basicConstraints = CA:true``. If it has
    ``basicConstraints = CA:false``, or if it has no ``basicConstraints`` at
    all, then |DP| creation will fail with the following error:

    .. code-block:: console

        X509_verify_cert returned 0 with error 79: invalid CA certificate
    
    An X.509 v1 Identity CA may have no ``basicConstraints`` at all. If an X.509 v1 Identity CA has ``basicConstraints = CA:false``, then |DP|
    creation will fail with the same error.


See also :ref:`p2_core/elements_dds_secure_system:Permissions CA and the basicConstraints X.509 v3 extension`.


Certificate Chaining
^^^^^^^^^^^^^^^^^^^^

If your |IdentityCerts| are not signed/issued by the Identity CA, you must provide your participants with the complete certificate chain by concatenating them in a single file. In other words, you need to concatenate the |IdentityCert|, its issuer CA, and every other intermediate CA that chains up to the Identity CA in a single file (or string). By specifying this file (or string) in the :property:`dds.sec.auth.identity_certificate` property, your participant will load the complete certificate chain that it will use to authenticate against remotely discovered participants. This way, participants in your system can validate the |IdentityCert| issued by subordinate CAs. (Note that all the |DPs| in your system should have access to a copy of the Identity CA certificate).

For details, see :ref:`p2_core/authentication:Identity Certificate Chaining`.


Alternative CAs
^^^^^^^^^^^^^^^

Depending on your use case, different |DPs| may trust a different Identity CA.
This can happen, for example, when several intermediate CAs exist in your PKI.
In this case, your |IdentityCert| should specify the full chain to the root CA
for the greatest compatibility.

There are use cases where you may also have different Root CAs with their own
PKIs and intermediate certificates issuing identities for your |DPs|. Therefore,
there’s no way for every |IdentityCert| to chain up to the same Identity CA. In
this case, you can use the :property:`authentication.alternative_identity_cas`
property to make your participants load alternative Identity CAs (see
:numref:`DDS Security Properties for Configuring Authentication`). When you do
so, your participant will use every alternative Identity CA (as well as the main
Identity CA) to validate the |IdentityCert| of remotely discovered participants.


Dynamic Certificate Status and Revocation
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

|CONNEXT| supports two methods of confirming certificate validity, which allows the
revocation of |IdentityCerts| before their scheduled expiration.

The first one is |CRL|, which is maintained by the Identity CA
(and any CA under it), with information about digital certificates that have been
revoked and should no longer be trusted. You can provide the CRL to your |DPs| by
setting :property:`authentication.crl` property (if you provide the CRL as a file,
it can be automatically tracked for changes; see :numref:`DDS Security Properties for Configuring Authentication`
for details). When provided, your |DP| will check the certificate against the revocation list.
For more information, see :ref:`p2_core/authentication:Identity Certificate Validation`.

The second method is |OCSP| stapling. If an |IdentityCert| contains an :value:`authorityInfoAccess`
field including the |OCSPResp| URL, |CONNEXT| will periodically validate its status by contacting the
|OCSPResp| at the provided address. The received |OCSPToken| is propagated in an authentication
handshake, and in periodic updates to all authenticated |DPs|. For more information see
:ref:`p2_core/authentication:Online Certificate Status Protocol`.

Multiple Certificate Revocation Lists
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The value of the :property:`authentication.crl` property may contain the concatenation of multiple CRLs (see :numref:`DDS Security Properties for Configuring Authentication`). For example, if a |DP| is configured to have a list of alternative CAs, each of those alternative CAs may have its own CRL included as part of the :property:`authentication.crl`.

During certificate verification, only the CRL associated with the involved CA will be used. That is, if an |IdentityCert| has been signed by the Identity CA, then only the Identity CA's CRL will be used when verifying the certificate. On the other hand, if an |IdentityCert| has been signed by an intermediate CA, then only the intermediate CA's CRL will be used when verifying the certificate.

The :property:`authentication.crl` may also contain CRLs from the intermediate CAs of an |IdentityCert| chain. If an element in the :property:`dds.sec.auth.identity_certificate` chain has not been revoked by its signer, then certificate verification will proceed as usual.


Governance and Permissions
--------------------------

To communicate securely, your participants need to follow the rules that you define through the |GovernanceDoc|, provided to your |DP| through the :property:`dds.sec.access.governance` property. Also, participants need access control policies specified for permission to join the system, to subscribe to |TOPICs|, etc. You give your participants permission through the |PermissionsDoc|, specified by the :property:`dds.sec.access.permissions` property. These properties are defined in :numref:`DDS Security Properties for Configuring Access Control`.

.. admonition:: Key Terms

  A |GovernanceDoc| defines *how* your system is protected, while |PermissionsDocs| define *who* can access what.

To prevent attackers from pretending to have permissions they do not have, or to communicate using different security parameters than the ones you defined for your system, both Governance and Permissions Documents are signed by the Permissions Certificate Authority (CA) using PKCS#7 signatures. The Permissions CA must be shared by all |DPs|, therefore any |DP| trusting that Permissions CA can verify whether another |DP| has the permissions it claims. You specify the Permissions CA to your participants through the :property:`dds.sec.access.permissions_ca` property (see :numref:`DDS Security Properties for Configuring Access Control`).

.. tip::

  The Permissions CA may be the same as the Identity CA, or it can be a different one, depending on your use case.


Different |DPs| may trust different Permissions CAs. In this case, you can use
the :property:`access_control.alternative_permissions_cas` property to make your
participants load alternative Permissions CAs (see
:numref:`DDS Security Properties for Configuring Access Control`). When you do
so, your participant will use every alternative Permissions CA (as well as the
main Permissions CA) to validate the |PermissionsDoc| of remotely discovered
participants.


Permissions CA and the basicConstraints X.509 v3 extension
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

According to `RFC 5280, section 4.2.1.9 <https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.9>`_,
X.509 v3 CAs must have the ``basicConstraints`` v3 extension if the CA is used
to validate digital signatures on certificates. This requirement does not apply
to CAs that are used to validate other things, such as the |GovernanceDoc| or
the |PermissionsDoc|. Therefore, the presence or absence of the
``basicConstraints`` v3 extension and the value of the ``CA`` boolean have no
influence on the outcome of the verification of the signed |GovernanceDoc| or
|PermissionsDoc|. In other words, you may use a Permissions CA with no
``basicConstraints``, with ``basicConstraints = CA:false``, or with
``basicConstraints = CA:true``.


Governance Document
===================

The |GovRules| specify which |DDS_DOMAINs| will be protected and the details of
the protection. The |GovRules| are specified in an XML file called the
|GovernanceDoc|. The |GovernanceDoc| defines two levels of configuration
properties: domain level, affecting participants in the |DOMAIN| (see
:ref:`p2_core/elements_dds_secure_system:Domain-level rules`); and topic level,
affecting |EPs| from that |TOPIC| (see
:ref:`p2_core/elements_dds_secure_system:Topic-level rules`). You can apply
these rules to a single |DOMAIN|, multiple |DOMAINs|, or ranges of |DOMAINs|
(see Specifying Domains).

The |GovernanceDoc| must be signed by the Permissions CA using a PKCS#7
signature. You need to specify the signed version of your |GovernanceDoc| using
the :property:`dds.sec.access.governance` property, as described in
:numref:`DDS Security Properties for Configuring Access Control`.

All the participants in your system need to load the same |GovernanceDoc|, or
compatible versions (see :ref:`p2_core/elements_dds_secure_system:Governance Compatibility Validation`).


Specifying Domains
------------------
The :xmltag:`domains` tag of the |GovernanceDoc| and the |PermissionsDoc|
restricts the |DPs| that the rules apply to, based on their domain ID and
domain tag. The |DPs| matching the :xmltag:`domains` requirements will be
protected accorded to the
:ref:`p2_core/elements_dds_secure_system:Domain-Level Rules`. Their |EPs|
will be protected according to the
:ref:`p2_core/elements_dds_secure_system:Topic-Level Rules` as long as they
match the :xmltag:`topic_expression`.

Domain IDs
^^^^^^^^^^
Both the |GovernanceDoc| and the |PermissionsDoc| require you to specify the
applicable domain IDs using the :xmltag:`domains` tag. You may use this tag to
specify individual domain IDs, domain ranges, open domain ranges, and
combinations thereof. You need to indicate domain IDs as non-negative decimal
numbers.

**Example**: Individual domain IDs. :math:`Domains_{protected} = \lbrace 0 \rbrace\cup\lbrace 1\rbrace`

.. code-block:: xml

  <domains>
    <!-- Domains 0 and 1 -->
    <id>0</id>
    <id>1</id>
  </domains>


**Example**: Domain ranges. :math:`Domains_{protected} = \lbrack 3, 10\rbrack`

.. code-block:: xml

  <domains>
    <!-- All domains between 3 and 10, inclusive -->
    <id_range>
        <min>3</min>
        <max>10</min>
    </id_range>
  </domains>


**Example**: Open domain ranges. :math:`Domains_{protected} =\lbrack 0, 5\rbrack\cup\lbrack 10, \mathtt{MAX\_VALID\_DOMAIN\_ID}\rbrack` [#f2]_

.. code-block:: xml

  <domains>
    <!-- Domain 10 and above -->
    <id_range>
        <min>10</min>
    </id_range>
    <!-- Domains from 0 to 5, inclusive -->
    <id_range>
        <max>5</max>
    </id_range>
  </domains>


**Example**: Combination of individual domain IDs and domain ranges. :math:`Domains_{protected} = \lbrace 3 \rbrace\cup\lbrace 7 \rbrace\cup\lbrack 10, 20 \rbrack\cup\lbrack50, \mathtt{MAX\_VALID\_DOMAIN\_ID}\rbrack`

.. code-block:: xml

  <domains>
    <!-- Domains 3 and 7 -->
    <id>3</id>
    <id>7</id>
    <!-- Domains from 10 to 20, inclusive -->
    <id_range>
        <min>10</min>
        <max>20</max>
    </id_range>
    <!-- Domain 50 and above -->
    <id_range>
        <min>50</min>
    </id_range>
  </domains>

.. [#f2] Domain IDs are 32-bit unsigned integers, typically between 0 and 232
   (or 167 on Windows platforms). This upper limit (``MAX_VALID_DOMAIN_ID``)
   comes from the limitations of the ``DDS_RtpsWellKnownPorts_t`` structure
   (see :link_connext_dds_pro_um:`Ports Used for Communication in the WIRE_PROTOCOL QoSPolicy
   section of the Connext DDS Core Libraries User's Manual
   <#users_manual/WIRE_PROTOCOL_Qos.htm#WireProtocolQoS_PortsUsedForDiscovery>`) and the
   transport's port mapping for discovery traffic (see
   :link_connext_dds_pro_um:`Ports Used for Communication in the "Getting Applications to Discover Each Other" part of the
   Connext DDS Core Libraries User's Manual <#users_manual/Ports_Used_for_Discovery.htm>`).
   For more information on the domain ID limit on Windows systems, see
   :link_connext_dds_pro_pn:`Domain ID Support in the Core Libraries Platform Notes
   <#platform_notes/Windows_Platforms.htm#WindowsPlatforms_DomainIDSupport>`.

Domain Tags
^^^^^^^^^^^
A |DDS_DOMAIN| can be subdivided using domain tags. Unlike domain IDs, which
are unsigned integers, domain tags are string values. You do not need to specify
a domain tag; the |SP_BUILTIN| will assume a default value for it. However, a
|GovernanceDoc| or |PermissionsDoc| rule will only apply if there is a match in
both the domain ID and the domain tag (with the |DP| values).

You can use the :xmltag:`tag` and :xmltag:`tag_expression` children of the
:xmltag:`domains` tag to define the applicable domain tags. :xmltag:`tag` is
for exact matches and :xmltag:`tag_expression` is for pattern matches (following
the syntax and rules of the POSIX ``fnmatch()`` function as specified in
POSIX 1003.2-1992, Section B.6).

**Example**: Match a single domain ID and tag.

.. code-block:: xml

  <domains>
    <!-- Domain 15 -->
    <id>15</id>
    <!-- Domain tag "Protected only if tag matches" -->
    <tag>Protected only if tag matches</tag>
  </domains>

**Example**: Match a domain range and all tags following a pattern.

.. code-block:: xml

  <domains>
    <!-- Domains from 15 to 18, inclusive -->
    <id_range>
        <min>15</min>
        <max>18</max>
    </id_range>
    <!-- All domain tags starting with "Protected" -->
    <tag_expression>Protected*</tag_expression>
  </domains>

The |GovernanceDoc| assumes the default empty string ("") domain tag when
the domain rule doesn't have any :xmltag:`tag` or :xmltag:`tag_expression`. It
will only match if the |DP| doesn't have any domain tags, or if it only has the
empty string domain tag. It is equivalent to specifying ``<tag></tag>`` in the
|GovernanceDoc|.

.. warning::

    The behavior of the |PermissionsDoc| is different for allow and deny rules
    that do not specify domain tags. The |SP_BUILTIN| assume the default empty
    string domain tag for allow rules in the |PermissionsDoc| that do not
    specify any domain tag (just like what happens for the |GovernanceDoc|).
    This means that you must be explicit when writing your allow rules. On the
    other hand, the |SP_BUILTIN| assume the
    ``<tag_expression>*</tag_expression>`` expression for deny rules that do not
    specify domain tags. Deny rules will be as inclusive as possible with
    respect to the domain tags.

Domain-Level Rules
------------------
Domain-level rules affect participants in the |DOMAIN|, taking effect at the
|DP| level. These rules will apply to every |DP| that has the domain tag and
is in the |DDS_DOMAIN| that you specify in the :xmltag:`domains` tag, as
described in :ref:`p2_core/elements_dds_secure_system:Specifying Domains`.

Domain-level rules fall under a :xmltag:`domain_rule` tag, as shown in
:ref:`p2_core/elements_dds_secure_system:Example Governance Document (XML)`.

#. :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|.
   For details, see
   :ref:`p2_core/authentication:allow_unauthenticated_participants
   (domain_rule)`.

#. :xmltag:`enable_join_access_control`: Determines if the participant-level
   permissions configured in the |PermissionsDoc| are enforced for remote
   participants. For details, see
   :ref:`p2_core/access_control:enable_join_access_control (within a
   domain_rule)`.

#. :xmltag:`enable_key_revision`: Determines if key revisions are enabled.
   Enabling them is a prerequisite for certificate and permissions mutability,
   banishing |DPs| and |OCSP|. It is :value:`TRUE` by default since |RTI_SP_PRODUCT|
   7.6.0 (:value:`FALSE` in older versions). It affects interoperability:
   two |DPs| will only communicate if their values are the same. For details, see
   :ref:`p2_core/cryptography:enable_key_revision (domain_rule)`.

#. :xmltag:`identity_credential_authority_validation`: It is a complex type
   that determines the applicability of two different identity credential
   authority mechanisms -- CRL and |OCSP|. This tag has two optional children tags
   called :xmltag:`crl` and :xmltag:`ocsp`, which allows for independent
   configuration of these mechanisms. Each child may take one of the possible
   values: :xmlval:`REQUIRED`, :xmlval:`AUTO` or :xmlval:`IGNORED`. For details,
   see :ref:`p2_core/authentication:identity_credential_authority_validation`.

#. :xmltag:`discovery_protection_kind` and
   :xmltag:`liveliness_protection_kind`: OMG DDS Security defines a set of
   secure endpoint discovery and secure participant liveliness builtin topics.
   These rules determine what level of protection is applied to those builtin
   topics. Possible values: :xmlval:`ENCRYPT`,
   :xmlval:`ENCRYPT_WITH_ORIGIN_AUTHENTICATION`, :xmlval:`SIGN`,
   :xmlval:`SIGN_WITH_ORIGIN_AUTHENTICATION`, :xmlval:`NONE`. For details, see
   :ref:`p2_core/cryptography:Domain-Level Rules`.

#. :xmltag:`monitoring_metrics_protection_kind` and
   :xmltag:`monitoring_logging_protection_kind`: Determines what level of
   protection is applied to the *RTI Connext Observability Framework* topics.
   Possible values: :xmlval:`ENCRYPT`,
   :xmlval:`ENCRYPT_WITH_ORIGIN_AUTHENTICATION`, :xmlval:`SIGN`,
   :xmlval:`SIGN_WITH_ORIGIN_AUTHENTICATION`, :xmlval:`NONE`.
   The first one is used to configure the protection level for event and
   periodic metrics. The second one, for logging messages. These tags are
   optional. If one of these tags is not present, the
   protection level for that data (metrics or logs) is inherited from
   :xmltag:`discovery_protection_kind`. See :ref:`chapter-observability-framework`
   for further details.

#. :xmltag:`service_request_protection_kind`: Determine what level of protection
   is applied to the Service Request topic.
   Possible values: :xmlval:`ENCRYPT`,
   :xmlval:`ENCRYPT_WITH_ORIGIN_AUTHENTICATION`, :xmlval:`SIGN`,
   :xmlval:`SIGN_WITH_ORIGIN_AUTHENTICATION`, :xmlval:`NONE`.
   This is an optional tag. If left unset the protection kind is inherited from
   :xmltag:`discovery_protection_kind`. For details, see
   :ref:`p2_core/cryptography:Domain-Level Rules`.

#. :xmltag:`instance_state_consistency_protection_kind`: Determine what level of
   protection is applied to the instance state consistency topics.
   Possible values: :xmlval:`ENCRYPT`,
   :xmlval:`ENCRYPT_WITH_ORIGIN_AUTHENTICATION`, :xmlval:`SIGN`,
   :xmlval:`SIGN_WITH_ORIGIN_AUTHENTICATION`, :xmlval:`NONE`.
   This is an optional tag. If left unset the protection kind is inherited from
   :xmltag:`discovery_protection_kind`. For details, see
   :ref:`p2_core/cryptography:Domain-Level Rules`.

#. :xmltag:`type_lookup_protection_kind`: Determine what level of
   protection is applied to the TypeLookup Service channels.
   Possible values: :xmlval:`ENCRYPT`,
   :xmlval:`ENCRYPT_WITH_ORIGIN_AUTHENTICATION`, :xmlval:`SIGN`,
   :xmlval:`SIGN_WITH_ORIGIN_AUTHENTICATION`, :xmlval:`NONE`.
   This is an optional tag. If left unset the protection kind defaults to
   :xmlval:`ENCRYPT`. For details, see
   :ref:`p2_core/cryptography:Domain-Level Rules`.

#. :xmltag:`rtps_protection_kind`: Determines what level of protection is
   applied to RTPS messages. Possible values: :xmlval:`ENCRYPT`,
   :xmlval:`ENCRYPT_WITH_ORIGIN_AUTHENTICATION`, :xmlval:`SIGN`,
   :xmlval:`SIGN_WITH_ORIGIN_AUTHENTICATION`, :xmlval:`NONE`. For details, see
   :ref:`p2_core/cryptography:Domain-Level Rules`.

#. :xmltag:`rtps_psk_protection_kind`: Determines what level of protection is
   applied to RTPS bootstrapping messages. Possible values:
   :xmlval:`ENCRYPT`, :xmlval:`SIGN`, :xmlval:`NONE`. For details, see
   :ref:`p2_core/cryptography:Domain-Level Rules`.

#. :xmltag:`allowed_security_algorithms`: Determines the cryptographic
   algorithms that a secure |DP| is allowed to use. This configuration affects
   |DP| and |EP| matching: two |DPs| will only match if their allowed security
   algorithms are compatible (same for |EPs|).
   Read :ref:`p2_core/cryptography:Domain-Level Rules` and
   :ref:`p2_core/cryptography:Discovery of a Remote Secure Entity` for details.

#. :xmltag:`enforce_proxy_permissions`: Determines what to do when the
   |PermissionsDoc| does not have an explicit allow or deny rule for a |DW|'s
   proxy permission. Read
   :ref:`p2_core/access_control:DataWriters Acting as a Proxy for other DataWriters`
   for details. You should not use this tag unless you are integrating with
   legacy systems where domain insider integrity and availability threats are
   not a concern.


Topic-Level Rules
-----------------
Topic-level rules affect |EPs| for a particular |TOPIC| or set of |TOPICs|. They
belong in a :xmltag:`topic_rule`, which identifies the |TOPIC| that the rule
applies to with the :xmltag:`topic_expression` attribute. All
:xmltag:`topic_rule` tags that apply to your |DOMAIN| or |DOMAIN| range fall
under the :xmltag:`topic_access_rules` tag, as shown in
:ref:`p2_core/elements_dds_secure_system:Example Governance Document (XML)`.

#. :xmltag:`enable_discovery_protection` / :xmltag:`enable_liveliness_protection`:
   Determines if discovery information and liveliness updates related to |EPs|
   from this |TOPIC| will be sent with the level of security defined in the
   domain-level :xmltag:`discovery_protection_kind` and
   :xmltag:`liveliness_protection_kind rules`. For details, see
   :ref:`p2_core/cryptography:Topic-Level Rules`.

#. :xmltag:`enable_read_access_control` / :xmltag:`enable_write_access_control`:
   Determines if endpoint-level permissions configured in the |PermissionsDoc|
   are enforced for local and remote |DR|/|DW|. For details, see
   :ref:`p2_core/cryptography:Topic-Level Rules`.

#. :xmltag:`metadata_protection_kind`: Determines what level of protection is
   applied to RTPS submessages from |EPs| of the associated |TOPIC|. Possible
   values: :xmlval:`ENCRYPT`, :xmlval:`ENCRYPT_WITH_ORIGIN_AUTHENTICATION`,
   :xmlval:`SIGN`, :xmlval:`SIGN_WITH_ORIGIN_AUTHENTICATION`, :xmlval:`NONE`.
   For details, see :ref:`p2_core/cryptography:Topic-Level Rules`.

#. :xmltag:`data_protection_kind`: Determines what level of protection is
   applied to the serialized payload from |EPs| of the associated topic.
   Possible values: :xmlval:`ENCRYPT`, :xmlval:`SIGN`, :xmlval:`NONE`. For
   details, see :ref:`p2_core/cryptography:Topic-Level Rules`.


Example Governance Document (XML)
---------------------------------
This is an example of what a |GovernanceDoc| looks like. You can find this
example document in :file:`rti_workspace/version/examples/dds_security/xml/Governance.xml`.
Use this file just as a reference, you will need to update its content, create
new files, and/or define or adapt the rules to match your system configuration
(|DOMAINs|, |TOPICs|, and used |IdentityCerts|) before signing the
|GovernanceDoc|.

.. literalinclude:: ../snippets/example_governance_file.xml
  :language: xml


The |GovernanceDoc| above defines just one configuration to be applied to any
|DOMAIN| in the system (as specified by the :xmltag:`domains` XML tag).
Consequently, all the |DOMAINs| and |TOPICs| in the system are protected in the
same way, in particular, see
:numref:`Domain-Level Rules in the Example Governance Document`:

.. list-table:: Domain-Level Rules in the Example |GovernanceDoc|
  :name: Domain-Level Rules in the Example Governance Document
  :widths: 40 10 50
  :header-rows: 1
  :class: longtable

  * - Domain-level 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 matched and authenticated remote participant

  * - :xmltag:`discovery_protection_kind`
    - :xmlval:`ENCRYPT`
    - The integrity and confidentiality of the Builtin Secure Discovery Topics are protected

  * - :xmltag:`liveliness_protection_kind`
    - :xmlval:`ENCRYPT`
    - The integrity and confidentiality of the Builtin Secure Liveliness Topic are protected

  * - :xmltag:`rtps_protection_kind`
    - :xmlval:`SIGN`
    - The integrity of RTPS messages is protected

Then, this |GovernanceDoc| defines two topic-level rules, as analyzed in :numref:`Topic-Level Rules for Topics Starting with Sq` and :numref:`Topic-Level Rules for the Other Topics`.

.. list-table:: Topic-Level Rules for |TOPICs| Starting with "Sq" (:xmltag:`topic_expression` is :xmlval:`Sq*`)
  :name: Topic-Level Rules for Topics Starting with Sq
  :widths: 40 10 50
  :header-rows: 1
  :class: longtable

  * - Topic-level rule (:xmltag:`topic_rule`)
    - Value
    - Security implications

  * - :xmltag:`enable_discovery_protection`
    - :xmlval:`FALSE`
    - Endpoint discovery data for these |TOPICs| is not protected

  * - :xmltag:`enable_liveliness_protection`
    - :xmlval:`FALSE`
    - Liveliness assertions for these |TOPICs| are not protected

  * - :xmltag:`enable_read_access_control`
    - :xmlval:`FALSE`
    - Neither local or remote permissions are checked for |DRs| of these |TOPICs|

  * - :xmltag:`enable_write_access_control`
    - :xmlval:`false`
    - Neither local or remote permissions are checked for |DWs| of these |TOPICs|

  * - :xmltag:`metadata_protection_kind`
    - :xmlval:`NONE`
    - These |TOPICs| are not protected at the Submessage level

  * - :xmltag:`data_protection_kind`
    - :xmlval:`NONE`
    - These |TOPICs| are not protected at the Serialized Data level.


.. list-table:: Topic-Level Rules for the Other |TOPICs| (:xmltag:`topic_expression` is :xmlval:`*`)
  :name: Topic-Level Rules for the Other Topics
  :widths: 40 10 50
  :header-rows: 1
  :class: longtable

  * - Topic-level rule (:xmltag:`topic_rule`)
    - Value
    - Security implications
  * - :xmltag:`enable_discovery_protection`
    - :xmlval:`true`
    - Endpoint discovery data for the rest of the |TOPICs| is protected (encrypted, as specified by :xmltag:`discovery_protection_kind`)
  * - :xmltag:`enable_liveliness_protection`
    - :xmlval:`true`
    - Liveliness assertions for the rest of the |TOPICs| are protected (encrypted, as specified by :xmltag:`liveliness_protection_kind`)
  * - :xmltag:`enable_read_access_control`
    - :xmlval:`true`
    - Permissions are checked for locally created and remotely discovered |DRs|
  * - :xmltag:`enable_write_access_control`
    - :xmlval:`true`
    - Permissions are checked for locally created and remotely discovered |DWs|
  * - :xmltag:`metadata_protection_kind`
    - :xmlval:`ENCRYPT`
    - The integrity and confidentiality of RTPS Submessages are protected for the rest of the |TOPICs|
  * - :xmltag:`data_protection_kind`
    - :xmlval:`ENCRYPT`
    - The integrity and confidentiality of Serialized Data are protected for the rest of the |TOPICs|


How the Governance Document is Interpreted
----------------------------------------------
The rules that compose the |GovernanceDoc| specify how your system is
protected. All the |DPs| in your secure system need to load the same or a
compatible |GovernanceDoc|, either by having a copy of it or by accessing a
single |GovernanceDoc| from a shared location (see
:ref:`p2_core/elements_dds_secure_system:Governance Compatibility Validation`
for more details).

As defined by the |SEC_SPEC|, the |GovernanceDoc| is parsed
from top to bottom. The first :xmltag:`domain_rule` matching the participant's
Domain ID will apply to this participant. This means that your |GovernanceDoc|
could potentially define other :xmltag:`domain_rules` for that Domain ID that
will not be used.

Note that a |DP| joining a |SecDomain| must have compatible domain-level rules.
This means that :xmltag:`rtps_protection_kind`,
:xmltag:`discovery_protection_kind`, and :xmltag:`liveliness_protection_kind`
must match. They must also have compatible cryptographic algorithms
(:xmltag:`allowed_security_algorithms`).
Otherwise, secure participants will not be able to communicate in the
|SecDomain|. For details, see
:ref:`p2_core/elements_dds_secure_system:Governance Compatibility Validation`.

Then, inside a :xmltag:`domain_rule` section, the topic-level rules will also
be parsed from top to bottom. The first :xmltag:`topic_rule` with a
:xmltag:`topic_expression` matching the topic name will apply, as defined by
the |SEC_SPEC|. This means that you can have overlapping
patterns with wildcards, and only the first one matching your topic name will
apply.

Note that matching |SecDWs| and |SecDRs| need to have compatible topic-level
rules. This means that :xmltag:`data_protection_kind`,
:xmltag:`metadata_protection_kind`, :xmltag:`enable_discovery_protection`,
:xmltag:`enable_liveliness_protection`, :xmltag:`enable_read_access_control`
and :xmltag:`enable_write_access_control` must match. Otherwise, |SecEPs| will
not be able to communicate. For details, see
:ref:`p2_core/elements_dds_secure_system:Governance Compatibility Validation`.

.. note::

  |GovernanceDocs| support the ``must_interpret`` attribute to allow for
  extensibility of the |GovernanceDoc| without breaking interoperability
  between different versions of the builtin plugins. You can set this attribute
  to :xmlval:`FALSE` when an XML tag is not supported across all the |DPs| in
  your system. These elements will not trigger a validation failure in the XML
  parser for those |DPs| that do not understand them.

  A typical scenario where the ``must_interpret`` attribute shines is when an
  XML element is introduced in a new |CONNEXT| version.  A system running the
  new |CONNEXT| version together with previous ones, can use a global
  |GovernanceDoc| if the new XML tag has the ``must_interpret`` attribute set
  to :xmlval:`FALSE`. Old |DPs| that are not able to understand the new XML tag
  will skip it, so they won't consider either the new XML tag or its children
  when validating the |GovernanceDoc| (see
  :ref:`p2_core/elements_dds_secure_system:Governance Compatibility Validation`).

  Read :link_connext_dds_pro_um:`How the XML is Validated in the Core Libraries
  User's Manual <#users_manual/How_the_XML_is_Validated.htm>` for more
  information on the ``must_interpret`` attribute.

XML Validation in the Governance Document
------------------------------------------
The XSD definition of the |GovernanceDoc| is in
``<NDDSHOME>/resource/schema/dds_security_governance.xsd``.

.. literalinclude:: /../../resource/schema/dds_security_governance.xsd
  :language: xml


Governance Compatibility Validation
-----------------------------------
|GovernanceDocs| loaded by different |DPs| need to be compatible. The |RTI_SP_PRODUCT|
check Governance compatibility by means of two parameters that are sent during
discovery, namely the ``PID_PARTICIPANT_SECURITY_INFO``, to check the
participant security attributes, and the ``PID_ENDPOINT_SECURITY_INFO``, to
check the endpoint security attributes. These parameters allow a |DP| to make
matching decisions upon discovering a remote peer or endpoint.

**At the participant level**, Governance compatibility involves having the same
values for the following domain-level rules:

* |RTPSProtection| (configured with the :xmltag:`rtps_protection_kind`
  domain-level rule)
* |DiscoveryProtection| (configured with the
  :xmltag:`discovery_protection_kind` domain-level rule)
* |LivelinessProtection| (configured with the
  :xmltag:`liveliness_protection_kind` domain-level rule)

If local and remote |GovernanceDocs| are not compatible, the discovery of the
remote participant will fail.

In order to communicate, **two matching endpoints** need to have a compatible
configuration for the endpoint security attributes. A compatible configuration
involves having the same |GovRules| for the topic of the |SecEPs|:

* |DataProtection| (configured with the :xmltag:`data_protection_kind`
  topic-level rule)
* |SubmsgProtection| (configured with the :xmltag:`metadata_protection_kind`
  topic-level rule)
* |DiscoveryProtection| (configured with the
  :xmltag:`enable_discovery_protection` topic-level rule)
* |LivelinessProtection| (configured with the
  :xmltag:`enable_liveliness_protection` topic-level rule)
* Access Control Enforcements (configured with the
  :xmltag:`enable_read_access_control` and
  :xmltag:`enable_write_access_control` topic-level rules).

|DPs| and |EPs| also need to have **compatible security algorithms** in order
to match. This depends on:

* The algorithms the |DP| supports: The list of supported algorithms is
  configured with the :xmltag:`allowed_security_algorithms` domain-level rule.
  For more information, read section
  :ref:`p2_core/cryptography:Domain-Level Rules`.
* The algorithms the |DP| and the |EP| use: The used algorithms depend on the
  |DP|'s |IdentityCert|, and the value of the
  :property:`dds.sec.crypto.symmetric_cipher_algorithm` (see
  :numref:`Properties for Configuring Cryptography Affecting Any Cryptography Plugin`)
  and :property:`dds.sec.auth.key_establishment_algorithm`
  (see :numref:`|RTI_SP_PRODUCT_HEADING| Properties for Configuring Authentication`) properties.

Permissions Document
====================

The |PermissionsDoc| specifies what actions a |DP| is allowed to take in a
*DDS* |SecDomain|. For example, it determines whether the |DP| can join the
|DOMAIN|, whether it can publish or subscribe to particular |TOPICs|, etc.

|PermissionsDocs| go beyond many traditional methods of security, where an
application that is allowed to communicate within a secure system is generally
assumed to be safe, and may be able to access data that it should not. The use
of |PermissionsDocs| locks down the specific access that trusted applications
have, so if one becomes compromised, the damage to the system is limited.

The |PermissionsDoc| contains a set of grants, which in turn contain a set of
:xmltag:`allow_rule` and :xmltag:`deny_rule` sections. These rules define what
your |DP| is allowed to do in a specific |DOMAIN| (or range of |DOMAINs|, as
defined in :ref:`p2_core/elements_dds_secure_system:Specifying Domains`).

Grants are bound to the |DP| identity. In other words, the
:xmltag:`subject_name` section of the grant identifies the specific |DP| to
which the permissions apply. The contents of the :xmltag:`subject_name` tag
need to match the subject name in the participant’s |IdentityCert|, with the
format being the string representation of the X.509 certificate subject name as
defined in IETF RFC 4514. Note that the subject name attribute order doesn't
matter and that you may use "S" or "ST" as the `stateOrProvinceName`.
See :link_connext_dds_secure_gsg:`Hands-on 4
<cpp11/hands_on_4.html#updating-permissions-files-with-new-credentials>` in the
|SP_GSG| for an
example openssl command to extract a correctly-formatted subject name.

Each |PermissionsDoc| must be signed by the Permissions CA using a PKCS#7
signature. You need to specify the signed version of your |PermissionsDoc|
using the :property:`dds.sec.access.permissions` property, as described in
:numref:`DDS Security Properties for Configuring Access Control`. Note that the
contents of your |PermissionsDocs| are sent in the clear during participant
authentication (right after Participant Discovery). Therefore, to reduce your
network usage each of your |PermissionsDocs| should only contain a grant for
the participant loading it. For further details, see
:ref:`p3_advanced/design_considerations:Contents of Your Permissions Documents`.


Example Permissions Document (XML)
----------------------------------

This is an example of what a |PermissionsDoc| looks like. You can find example documents in :file:`rti_workspace/version/examples/dds_security/xml/Permissions_*.xml`. Use these files just as a reference, you will need to update their contents or create new files, defining or adapting the rules to match your system configuration (|DOMAINs|, |TOPICs|, and referenced |IdentityCerts|) before signing the |PermissionsDocs|.

.. literalinclude:: ../snippets/example_permissions_file.xml
  :language: xml


This |PermissionsDoc| configures a single grant, which are analyzed in :numref:`Permissions Defined by Grant in Sample Permissions Document`.

.. list-table:: Permissions Defined by Grant in Sample |PermissionsDoc|
  :name: Permissions Defined by Grant in Sample Permissions Document
  :widths: 45 55
  :header-rows: 1
  :class: longtable

  * - XML Attribute
    - Security Implications

  * - .. literalinclude:: ../snippets/example_permissions_file.xml
        :language: xml
        :class: break-lines
        :start-at: <subject_name>
        :end-at: </subject_name>

    - This grant applies to the participant loading the |IdentityCert|, with the subject being:

        * Country: ``US``
        * State: ``CA``
        * Organization: ``Real Time Innovations``
        * email address: ``ecdsa01Peer01@rti.com``
        * Common Name: ``RTI ECDSA01 (p256) PEER01``

  * - .. literalinclude:: ../snippets/example_permissions_file.xml
        :language: xml
        :class: break-lines
        :start-at: <not_before>
        :end-at: </not_before>

    - This grant can only be used after June 30, 2020 at 1:00 pm (GMT).

  * - .. literalinclude:: ../snippets/example_permissions_file.xml
        :language: xml
        :class: break-lines
        :start-at: <not_after>
        :end-at: </not_after>

    - This grant can only be used before June 30, 2030 at 1:00 pm (GMT).


This grant then defines an :xmltag:`allow_rule`, which determines everything
that the participants using this grant will be allowed to do. This includes
joining |DOMAINs| (participant-level rules) and publishing/subscribing to
|TOPICs| (endpoint-level rules).
:numref:`Actions Allowed by Grant in Sample Permissions Document` analyzes this
grant.

.. list-table:: Actions Allowed by Grant in Sample |PermissionsDoc|
  :name: Actions Allowed by Grant in Sample Permissions Document
  :widths: 45 55
  :header-rows: 1
  :class: longtable

  * - XML Attribute
    - Security Implications

  * - .. literalinclude:: ../snippets/example_permissions_file.xml
        :language: xml
        :class: break-lines
        :start-at: <domains>
        :end-at: </domains>

    - The participant using this grant can only join domain 0 and domain 2.

      The |PermissionsDoc| also has the :xmltag:`partitions` element as a child
      of :xmltag:`domains`. :xmltag:`partitions` is a valid child of
      :xmltag:`domains` only in 7.4.0 and later releases, so the XML parser from
      previous |CONNEXT| versions will fail during validation of the
      |PermissionsDoc|. However, since :xmltag:`partitions` is marked as
      ``must_interpret="false"``, this is not the case for |CONNEXT| versions
      7.0.0 and higher, which support the ``must_interpret`` attribute to allow
      |PermissionsDoc| extensibility while keeping compatibility across
      different versions of the |SP_BUILTIN|. Read
      :ref:`p2_core/elements_dds_secure_system:How the Permissions are Interpreted`
      for more information.

  * - .. literalinclude:: ../snippets/example_permissions_file.xml
        :language: xml
        :class: break-lines
        :start-at: <publish>
        :end-at: </publish>

    - The participant using this grant is only allowed to publish topics starting with ``Cir`` and only in partitions starting with ``P1``.

  * - .. literalinclude:: ../snippets/example_permissions_file.xml
        :language: xml
        :class: break-lines
        :start-at: <subscribe>
        :end-at: </subscribe>

    - The participant using this grant is allowed to subscribe to |TOPICs| containing ``Sq`` in the topic name and only in partition ``P2``.

      Moreover, to subscribe to the aforementioned topics, the participant must use readers that either do not announce any data tag, or they announce the :xmlval:`Title` data tag with a value containing :xmlval:`Software`.

  * - .. literalinclude:: ../snippets/example_permissions_file.xml
        :language: xml
        :class: break-lines
        :start-at: <subscribe> <!-- a simpler rule -->
        :end-at: </subscribe>

    - The participant using this grant is also allowed to subscribe to the |TOPIC| ``Triangle`` in the "empty string" partition.

      The |DR| created by the participant to subscribe to the ``Triangle`` |TOPIC| must not announce any data tag.

  * - .. literalinclude:: ../snippets/example_permissions_file.xml
        :language: xml
        :class: break-lines
        :start-at: <proxy must_interpret="false">
        :end-at: </proxy>

    - The participant using this grant is allowed to act as a proxy (on behalf
      of |DWs| from other participants) for |TOPICs| starting with ``Circle``
      and only in partitions starting with ``P1``.

      Given the previous ``<publish>`` rule, a |DW| for |TOPIC|
      ``Circumvention`` may only write samples whose
      :link_connext_dds_api_cpp2:`SampleInfo::original_publication_virtual_guid<classdds_1_1sub_1_1SampleInfo.html>`
      (which corresponds to
      :link_connext_dds_api_cpp2:`WriteParams::identity.writer_guid<classrti_1_1pub_1_1WriteParams.html>`)
      and
      :link_connext_dds_api_cpp2:`SampleInfo::source_guid<classdds_1_1sub_1_1SampleInfo.html>`
      (which corresponds to :link_connext_dds_api_cpp2:`WriteParams::source_guid<classrti_1_1pub_1_1WriteParams.html>`)
      correspond to the same |DP| as the one in
      :link_connext_dds_api_cpp2:`SampleInfo::publication_handle<classdds_1_1sub_1_1SampleInfo.html>`.
      If this |DW| violates this restriction, the |DR| will drop the sample. A
      |DW| for |TOPIC| ``Circle1`` does not have this restriction.


Finally, this grant denies any other action, as explained in :numref:`Default Permissions Defined by Grant in Sample Permissions Document`.

.. list-table:: Default Permissions Defined by Grant in Sample |PermissionsDoc|
  :name: Default Permissions Defined by Grant in Sample Permissions Document
  :widths: 45 55
  :header-rows: 1
  :class: longtable

  * - XML Attribute
    - Security Implications

  * - .. literalinclude:: ../snippets/example_permissions_file.xml
        :language: xml
        :class: break-lines
        :start-at: <default>
        :end-at: </default>
    - Any action not explicitly allowed in an :xmltag:`allow_rule` will be denied.


How the Permissions are Interpreted
-----------------------------------

Permissions for |DDS_Entities| in a |DP| are associated with the subject in the
|DP|’s |IdentityCert|. When a |DP| loads a |PermissionsDoc|, it looks for a
grant with a :xmltag:`subject_name` matching its identity. Likewise, when a
|DP| receives a remote |DP|'s |PermissionsDoc|, it looks for a grant with a
:xmltag:`subject_name` matching the remote’s identity. In other words, the
:xmltag:`subject_name` identifies the |DP| to which the grant’s permissions
apply.

.. note::

  The contents of the :xmltag:`subject_name` tag must be the X.509 subject name
  for the |DP|, as given in the Subject field of its |IdentityCert|.

The |PermissionsDoc| is parsed from top to bottom. In other words, the first
rule that matches the operation being attempted will apply, as defined by the
|SEC_SPEC|. If a rule's criteria match the Domain ID (either
by :xmltag:`id` being an exact match or by :xmltag:`id_range` containing the
Domain ID) and the publish, subscribe, or proxy operation, then the corresponding
allow or deny decision is applied. If the criteria for a rule does not match
the attempted operation, the evaluation proceeds to the next rule. If no rule
is defined for the attempted operation, then the decision specified by the
:xmltag:`default` rule is applied.

The |PermissionsDoc| loaded by your |DP| needs to contain exactly one grant for
this |DP|. Otherwise, the participant creation will fail. Also, the grant needs
to be valid for the current date. The |AccessControlPlugin| checks the
:xmltag:`validity` tag to determine this. If the grant is not valid for the
current date, the participant creation will fail. Note that you are not required
to have the same validity dates in the |PermissionsDoc| and the |IdentityCert|
(upon creation, your |DP| will independently verify that the |IdentityCert| and
the grant in your |PermissionsDoc| are valid for the current date).

You can give a participant permission to join a |DOMAIN| by including that
Domain ID in the :xmltag:`domain` tag of an :xmltag:`allow_rule`. Alternatively,
if you set the :xmltag:`default` to :xmlval:`ALLOW`, the participant will have
access to all |DOMAINs| that are not included in a :xmltag:`deny_rule`. If a
participant attempts to join a Domain ID it is not authorized to join, the
participant creation will fail. Note that if a :xmltag:`deny_rule` has any
:xmltag:`publish`, :xmltag:`subscribe`, or :xmltag:`proxy` tags, then the
:xmltag:`deny_rule` will not prevent a |DP| from being created; it will only
prevent certain |TOPICs|, |DWs|, and |DRs| from being created.

|DPs| will only be allowed to perform publish operations for |TOPICs|,
partitions and tags that explicitly appear under an :xmltag:`allow_rules`
section, unless the default is set to :xmlval:`ALLOW`. The same applies to
subscribe and proxy operations. In the case where the default is
:xmlval:`ALLOW`, the publish/subscribe/proxy operation will only be denied if
it appears inside a :xmltag:`deny_rules` section. You can also combine allow
and deny rules to adapt your system to complex scenarios, as shown in the
following example, where your participant is allowed to publish on any topic
and in any partition except partition "A" in |DOMAIN| 0.

.. literalinclude:: ../snippets/elements_dds_secure_system.xml
  :language: xml
  :start-after: Complex Grant
  :end-before: EOF


For further information on how each rule is interpreted, refer to
:ref:`p2_core/access_control:Permissions Document`.

We mentioned in :ref:`p2_core/elements_dds_secure_system:How the Governance Document is Interpreted`
that |GovernanceDocs| support the ``must_interpret`` attribute to avoid
breaking interoperability between different versions of the builtin plugins.
|PermissionsDocs| also support the ``must_interpret`` attribute. Setting this
attribute to :xmlval:`FALSE` is necessary when a modern |DP| wants to
communicate with a |DP| that doesn't support some of the XML tags in the
|PermissionsDoc|. Read :link_connext_dds_pro_um:`How the XML is
Validated in the Core Libraries User's Manual <#users_manual/How_the_XML_is_Validated.htm>`
for more information on the ``must_interpret`` attribute.

XML Validation in the Permissions Document
------------------------------------------

The XSD definition of the |PermissionsDoc| is in
:file:`<NDDSHOME>/resource/schema/dds_security_permissions.xsd`.

.. literalinclude:: /../../resource/schema/dds_security_permissions.xsd
  :language: xml


Security Builtin Topics
=======================

To perform some of the security operations (such as mutual authentication) between |DPs|, the |RTI_SP_PRODUCT| need to be able to send messages to each other with specific protection kinds or QoS parameters. The mechanisms provided by unsecure DDS builtin |TOPIC| entities are not adequate for this purpose. For this reason, the |SEC_SPEC| introduces new builtin |TOPICs| and corresponding builtin |DR| and |DW| entities to read and write the |TOPICs|. The |RTI_SP_PRODUCT| implement these |TOPICs| using the parameters defined by the |SEC_SPEC|. The following sections describe the most important features and parameters of the security-specific builtin |TOPICs|.

Note that some of the security parameters used by these |TOPICs| are defined in the |SEC_SPEC|, while others can be tuned through the |GovernanceDoc| (see details below).


Authentication Builtin Topic (ParticipantStatelessMessage)
----------------------------------------------------------

The Authentication Builtin Topic is used to perform mutual authentication and allows exchanging directed messages through an unsecure communication channel. It is a best-effort stateless |TOPIC|, which prevents the sequence-number prediction vulnerability that is present in unsecure reliable protocols. For details, see :ref:`p2_core/authentication:Authentication Builtin Topic (ParticipantStatelessMessage)`.

.. list-table:: Non-default QoS Policies for Authentication Stateless |DW| and |DR| (not configurable)
  :name: Non-default QoS Policies for Authentication Stateless DataWriter and DataReader
  :widths: auto
  :width: 60%
  :align: center
  :header-rows: 1
  :class: longtable

  * - Policy
    - Kind
  * - :xmltag:`RELIABILITY`
    - :xmlval:`BEST_EFFORT`


Secure Key Exchange Builtin Topic (ParticipantVolatileMessageSecure)
--------------------------------------------------------------------

|DPs| use the |SecKeyExchangeT| to exchange the symmetric keys that secure entities need to communicate securely. This |TOPIC| allows |DPs| to exchange directed messages to each other using a reliable secure channel. To prevent sending data to unauthorized late joiners, this |TOPIC| sets the DURABILITY QoS to kind VOLATILE -- because the exchanged messages are directed to specific Participants, there is no need to keep historical samples for late joiners. The |SecKeyExchangeT| uses |SubmsgProtection| to encrypt the RTPS submessages that include the exchanged keys. For details, see :ref:`p2_core/cryptography:Secure Key Exchange Channel (ParticipantVolatileMessageSecure topic)`.

The following tables show the security parameters and QoS settings used by the |SecKeyExchangeT|.

.. list-table:: Endpoint Security Attributes for Key Exchange |DW| and |DR| (not configurable)
  :name: Endpoint Security Attributes for Key Exchange DataWriter and DataReader
  :widths: auto
  :width: 60%
  :align: center
  :header-rows: 1
  :class: longtable

  * - Topic-Level Rule
    - Value
  * - :xmltag:`enable_discovery_protection`
    - :xmlval:`FALSE`
  * - :xmltag:`enable_liveliness_protection`
    - :xmlval:`FALSE`
  * - :xmltag:`enable_read_access_control`
    - :xmlval:`FALSE`
  * - :xmltag:`enable_write_access_control`
    - :xmlval:`FALSE`
  * - :xmltag:`metadata_protection_kind`
    - :xmlval:`ENCRYPT`
  * - :xmltag:`data_protection_kind`
    - :xmlval:`NONE`


.. list-table:: Non-default QoS Policies for Key Exchange |DW| and |DR| (not configurable)
  :name: Non-default QoS Policies for Key Exchange DataWriter and DataReader
  :widths: auto
  :width: 60%
  :align: center
  :header-rows: 1
  :class: longtable

  * - Policy
    - Kind
  * - :xmltag:`RELIABILITY`
    - :xmlval:`RELIABLE`
  * - :xmltag:`HISTORY`
    - :xmlval:`KEEP_ALL`
  * - :xmltag:`DURABILITY`
    - :xmlval:`VOLATILE`


Builtin Secure Logging Topic
----------------------------

You can distribute the security logging information over DDS. If you decide to
do so, your |DP| will publish this information to the |LoggingT|, as defined in
the |SEC_SPEC|.

In the case of the |SP_BUILTIN|, the topic name for the |LoggingT| is
|LoggingTName|. The following table shows the security parameters used by the
|LoggingT| in the |SP_BUILTIN| library.

.. list-table:: Security Attributes for the Builtin Secure Logging |EPs| in the  |SP_BUILTIN| library (not configurable)
  :name: Security Attributes for the Builtin Secure Logging Endpoints in the Builtin Security Plugins Library
  :widths: auto
  :width: 60%
  :align: center
  :header-rows: 1
  :class: longtable

  * - Topic-Level Rule
    - Value
  * - :xmltag:`enable_discovery_protection`
    - :xmlval:`FALSE`
  * - :xmltag:`enable_liveliness_protection`
    - :xmlval:`FALSE`
  * - :xmltag:`enable_read_access_control`
    - :xmlval:`TRUE`
  * - :xmltag:`enable_write_access_control`
    - :xmlval:`FALSE`
  * - :xmltag:`metadata_protection_kind`
    - :xmlval:`SIGN` [#]_
  * - :xmltag:`data_protection_kind`
    - :xmlval:`ENCRYPT`


.. [#] In |CONNEXT| 5.3.0, the |LoggingT| did not use |SubmsgProtection| (which
   did not comply with the |SEC_SPEC|). For backward compatibility, you can
   choose to disable |SubmsgProtection| in this |TOPIC| with the
   :property:`access_control.use_530_logging_protection` property (see
   :numref:`Additional |RTI_SP_PRODUCT_HEADING| Properties for Configuring Logging Distributed over DDS`).

In the case of the |LIGHT_SP_BUILTIN|, the topic name for the
|LoggingT| is |LoggingLwTName|. The following table shows the security
parameters used by the |LoggingT| in the |LIGHT_SP_BUILTIN| library. You can see
that the |LIGHT_SP_BUILTIN| do no protect the |LoggingT| at the topic level.
Instead, the |LIGHT_SP_BUILTIN| protect the |LoggingT| at the level of the RTPS
message with |PSKProtection|.

.. list-table:: Security Attributes for the Builtin Secure Logging |EPs| in the  |LIGHT_SP_BUILTIN| library (not configurable)
  :name: Security Attributes for the Builtin Secure Logging Endpoints in the Lightweight Builtin Security Plugins Library
  :widths: auto
  :width: 60%
  :align: center
  :header-rows: 1
  :class: longtable

  * - Topic-Level Rule
    - Value
  * - :xmltag:`enable_discovery_protection`
    - :xmlval:`FALSE`
  * - :xmltag:`enable_liveliness_protection`
    - :xmlval:`FALSE`
  * - :xmltag:`enable_read_access_control`
    - :xmlval:`FALSE`
  * - :xmltag:`enable_write_access_control`
    - :xmlval:`FALSE`
  * - :xmltag:`metadata_protection_kind`
    - :xmlval:`NONE`
  * - :xmltag:`data_protection_kind`
    - :xmlval:`NONE`

For more information about the |LoggingT|, see
:ref:`p2_core/logging:Builtin Secure Logging Topic`.

Builtin Secure Discovery Topics
-------------------------------

The |SecDiscoveryTopics| are the analogous versions of the Builtin Discovery |TOPICs|. You can configure whether to use the secure version (or the regular/unsecure version) of the builtin Discovery |EPs| for a certain |TOPIC| with the :xmltag:`enable_discovery_protection` |GovRule|. If you set this |GovRule| to :xmlval:`TRUE`, discovery information related to your |TOPIC| will be exchanged through the |SecDiscoveryEPs|. These |EPs| will apply |SubmsgProtection| to the level you configure with the :xmltag:`discovery_protection_kind` |GovRule|. Note that :xmltag:`enable_discovery_protection` also determines whether Topic Queries are secured (see :ref:`p2_core/elements_dds_secure_system:Builtin Secure ServiceRequest Topic`).

Note that the |SecDiscoveryEPs| are created in addition to the unsecure version of the same |EPs|, and have the same QoS configuration. The following table shows the correspondence between the secure and unsecure versions of the discovery builtin |TOPICs|.

.. table:: Correspondence between Unsecure and Secure Versions of Discovery Builtin Topics
  :name: Correspondence between Unsecure and Secure Versions of Discovery Builtin Topics

  +-------------------+--------------------------+------------------------------+
  | Description       | DDS Builtin Topics       | DDS Security Builtin Topics  |
  +===================+==========================+==============================+
  | |DP_disc| (SPDP)  | DCPSParticipant          | DCPSParticipantSecure        |
  +-------------------+--------------------------+------------------------------+
  | |DP_disc| (SPDP2) | DISCParticipantBootstrap | N/A                          |
  |                   +--------------------------+------------------------------+
  |                   | DISCParticipantConfig    | DISCParticipantConfigSecure  |
  +-------------------+--------------------------+------------------------------+
  | |EP_disc|         | DCPSPublication          | DCPSPublicationSecure        |
  |                   +--------------------------+------------------------------+
  |                   | DCPSSubscription         | DCPSSubscriptionSecure       |
  +-------------------+--------------------------+------------------------------+

For further information about discovery |EPs|, see :link_connext_dds_pro_um:`Discovery Implementation in the Core Libraries User's Manual <#users_manual/Discovery_Implementation.htm>`. For more information about the secure version of discovery |EPs| see :ref:`p2_core/cryptography:Builtin Secure Discovery Endpoints`.


Builtin Secure Liveliness Topic
-------------------------------

You can configure whether to use the secure or unsecure version of the Builtin Liveliness |EPs| for a certain |TOPIC| with the :xmltag:`enable_liveliness_protection` |GovRule|. If you set this |GovRule| to :xmlval:`TRUE`, liveliness information related to your |TOPIC| will be exchanged through the |SecLivelinessEPs|. These |EPs| will apply |SubmsgProtection| to the level you configure with the :xmltag:`liveliness_protection_kind` |GovRule|. Please note that the Builtin Liveliness Topics (either the secure and regular version) are only used for |TOPICs| that set the LIVELINESS QosPolicy to :xmlval:`AUTOMATIC` or :xmlval:`MANUAL_BY_PARTICIPANT` (see :ref:`p2_core/cryptography:enable_liveliness_protection (topic_rule)`).

Note that the |SecLivelinessEPs| are created in addition to the unsecure version of the same |EPs|, and have the same QoS configuration. The following table shows the correspondence between the secure and unsecure versions of the liveliness builtin |TOPIC|.

.. list-table:: Correspondence between Unsecure and Secure versions of Liveliness Builtin Topic
  :name: Correspondence between Unsecure and Secure versions of Liveliness Builtin Topic
  :widths: auto
  :width: 100%
  :header-rows: 1
  :class: longtable

  * - Description
    - DDS Builtin Topics
    - DDS Security Builtin Topics
  * - Liveliness (when the LIVELINESS QosPolicy of a particular |TOPIC| is
      :xmlval:`AUTOMATIC` or
      :xmlval:`MANUAL_BY_PARTICIPANT`)
    - DCPSParticipantMessage
    - DCPSParticipantMessageSecure


For more information about the secure version of the liveliness |EPs| see
:ref:`p2_core/cryptography:Builtin Secure Liveliness Endpoints`.


Builtin Secure ServiceRequest Topic
-----------------------------------

The |SecServiceReqTopic| is a vendor-specific |TOPIC| analogous to the Builtin ServiceRequest Topic. Whenever you use the secure version of the Builtin Discovery Endpoints (by setting :xmltag:`enable_discovery_protection`), the |SecServiceReqEPs| will be used to communicate Topic Queries. These |EPs| will apply |SubmsgProtection| to the level you configure with the :xmltag:`discovery_protection_kind` |GovRule|.

Note that the |SecServiceReqEPs| are created in addition to the unsecure version of the same |EPs|. The following table shows the correspondence between the secure and unsecure versions of the ServiceRequest builtin |TOPICs|.

.. list-table:: Correspondence between Unsecure and Secure versions of ServiceRequest Builtin |TOPICs|
  :name: Correspondence between Unsecure and Secure versions of ServiceRequest Builtin Topics
  :widths: auto
  :width: 100%
  :header-rows: 1
  :class: longtable

  * - Description
    - DDS Builtin Topics
    - DDS Security Builtin Topics
  * - Service Request
    - DDSServiceRequest
    - DDSServiceRequestSecure

For further information, see
:link_connext_dds_pro_um:`The Builtin ServiceRequest DataReader in the Core Libraries User's Manual
<#users_manual/TopicQueries_Debugging.htm#48.1_The_Built-in_ServiceRequest_DataReader>`.
