.. include:: ../vars.rst .. _chapter-elements-dds-secure-system: *************************************** Elements of a Connext DDS Secure System *************************************** This chapter covers all the elements that you need to secure a Connext DDS application. QoS Properties ============== To enable and configure the |SP|, we use properties defined in the |DP|'s PROPERTY QosPolicy (see :link_um:`PROPERTY QosPolicy (DDS Extension) in the Core Libraries User’s Manual `). You can set these properties in code (see :link_api_cpp98:`RTI Connext C++ API: PROPERTY `) or in XML, similar to how you would set transport properties (see :link_um:`Transport Properties in the Core Libraries User’s Manual `). .. note:: You can include environment variables within XML tags and attributes by using the following notation: ``$(MY_VARIABLE)``. See :link_um:`Using Environment Variables in XML in the Core Libraries User's Manual `. There are two kinds of properties to configure the |SP| (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 DDS Security specification but where no configuration method is specified. .. note:: For brevity, in this document we omit the prefix (e.g., :property:`com.rti.serv.secure.`) when referring to implementation-specific properties; we will still use the full name for properties defined by the DDS Security standard. :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:`p2_core/building_apps:Building and Running Security Plugins-Based Applications` describes the properties for enabling the |SP|. Alternatively, you can make your profile inherit from the ``Generic.Security builtin`` profile (which loads the security plugins dynamically). All the |SP| properties are validated when the |DP| and the plugin are created; for more information, see :link_um:`Property validation in the Core Libraries User’s Manual `. In order to have a successful |SP| properties validation, you can not 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 |SP| 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|. Here are some examples: * Correct scenario. .. code-block:: xml ... com.rti.serv.load_plugin com.rti.serv.secure com.rti.serv.secure.library nddssecurity com.rti.serv.secure.create_function RTI_Security_PluginSuite_create ... * 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 ... com.rti.serv.secure.library nddssecurity com.rti.serv.secure.create_function RTI_Security_PluginSuite_create ... For further details and configuration options that control the behavior of property validation, see :link_um:`Property Validation in the RTI Connext DDS Core Libraries User's Manual `. .. 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. .. [#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| 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 |PermissionsFiles| 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, a 256-bit Elliptic Curve Key, or any other private key supported by OpenSSL. 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. 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_ca_files` 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. Certificate Revocation ^^^^^^^^^^^^^^^^^^^^^^ The Identity CA (and any CA under it) can maintain a certificate revocation list (CRL) with information about digital certificates that have been revoked before their scheduled expiration date and should no longer be trusted. You can provide the CRL to your participants by setting the :property:`authentication.crl` property (see :numref:`DDS Security Properties for Configuring Authentication`). By doing this, your |DP| will check the certificate against the revocation list. For more information, see :ref:`p2_core/authentication:Identity Certificate Validation`. .. important:: If you update the revocation list, the changes will not take effect until you delete and recreate your |DP|. 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 |GovernanceFile|, 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 |PermissionsFile|, 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 |GovernanceFile| defines *how* your system is protected, while |PermissionsFiles| 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 Files 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_authority_files` 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 |PermissionsFile| of remotely discovered participants. Governance File =============== The Governance Document specifies which DDS |DOMAINs| will be protected and the details of the protection. The Governance Document is specified in an XML file called the |GovernanceFile|. The |GovernanceFile| defines two levels of configuration properties: domain level, affecting participants in the |DOMAIN| (see 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 Domain IDs). The |GovernanceFile| must be signed by the Permissions CA using a PKCS#7 signature. You need to specify the signed version of your |GovernanceFile| 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 |GovernanceFile|, or compatible versions (see :ref:`p2_core/elements_dds_secure_system:Governance Compatibility Validation`). Specifying Domain IDs --------------------- Both the |GovernanceFile| and the |PermissionsFile| 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. **Example**: Individual Domain IDs. :math:`Domains_{protected} = \lbrace 0 \rbrace\cup\lbrace 1\rbrace` .. code-block:: xml 0 1 **Example**: Domain Ranges. :math:`Domains_{protected} = \lbrack 3, 10\rbrack` .. code-block:: xml 3 10 **Example**: Open Domain Ranges. :math:`Domains_{protected} =\lbrack 0, 5\rbrack\cup\lbrack 10, \mathtt{MAX\_VALID\_DOMAIN\_ID}\rbrack` [#f2]_ .. code-block:: xml 10 5 **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 3 7 10 20 50 .. [#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_um:`Ports Used for Discovery in the WIRE_PROTOCOL QoSPolicy section of the Connext DDS Core Libraries User's Manual `) and the transport’s port mapping for discovery traffic (see :link_um:`Ports Used for Discovery in the Discovery section of the Connext DDS Core Libraries User's Manual `). For more information on the domain ID limit on Windows systems, see :link_platform_notes:`Domain ID Support in the Core Libraries Platform Notes <#platform_notes/Windows_Platforms.htm#WindowsPlatforms_DomainIDSupport>`. Domain-Level Rules ------------------ Domain-level rules affect participants in the |DOMAIN|, taking effect at the |DP| level. These rules will apply to every |DP| in the |DOMAIN| (or |DOMAIN| range) that you specify in the :xmltag:`domains` tag (see :ref:`p2_core/elements_dds_secure_system:Specifying Domain IDs`). Domain-level rules fall under a :xmltag:`domain_rule` tag, as shown in :ref:`p2_core/elements_dds_secure_system:Example Governance File (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 |PermissionsFile| are enforced for remote participants. For details, see :ref:`p2_core/access_control:enable_join_access_control (within a domain_rule)`. #. :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:`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`. 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 File (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 |PermissionsFile| 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 File (XML) ----------------------------- This is an example of what a |GovernanceFile| 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 |GovernanceFile|. .. literalinclude:: ../snippets/example_governance_file.xml :language: xml The |GovernanceFile| 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 File`: .. list-table:: Domain-Level Rules in the Example |GovernanceFile| :name: Domain-Level Rules in the Example Governance File :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 |GovernanceFile| 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 File is Interpreted -------------------------------------- The rules that compose the |GovernanceFile| specify how your system is protected. All the |DPs| in your secure system need to load the same or a compatible |GovernanceFile|, either by having a copy of it or by accessing a single |GovernanceFile| from a shared location (see :ref:`p2_core/elements_dds_secure_system:Governance Compatibility Validation` for more details). As defined by the DDS Security specification, the |GovernanceFile| 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 |GovernanceFile| 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. 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 DDS Security specification. 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`. XML Validation in the Governance File ------------------------------------- The XSD definition of the |GovernanceFile| is in ``/resource/schema/dds_security_governance.xsd``. .. literalinclude:: /../../resource/schema/dds_security_governance.xsd :language: xml Governance Compatibility Validation ----------------------------------- |GovernanceFiles| loaded by different |DPs| need to be compatible. The |SP| 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 |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 |GovernanceFiles| are not compatible, the discovery of the remote participant will fail. In order to communicate, two matching |EPs| 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). Permissions File ================ 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. |PermissionsFiles| 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 |PermissionsFiles| locks down the specific access that trusted applications have, so if one becomes compromised, the damage to the system is limited. The |PermissionsFile| 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 Domain IDs`). 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_sec_gsg:`RTI Security Plugins Getting Started Guide Hands-on 4 ` for an example openssl command to extract a correctly-formatted subject name. Each |PermissionsFile| must be signed by the Permissions CA using a PKCS#7 signature. You need to specify the signed version of your |PermissionsFile| 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 |PermissionsFiles| are sent in the clear during participant authentication (right after Participant Discovery). Therefore, to reduce your network usage each of your |PermissionsFiles| should only contain a grant for the participant loading it. For further details, see :ref:`p3_advanced/design_considerations:Contents of Your Permissions Files`. Example Permissions File (XML) ------------------------------ This is an example of what a |PermissionsFile| 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 |PermissionsFiles|. .. literalinclude:: ../snippets/example_permissions_file.xml :language: xml This |PermissionsFile| configures a single grant, which are analyzed in :numref:`Permissions Defined by Grant in Sample Permissions File`. .. list-table:: Permissions Defined by Grant in Sample |PermissionsFile| :name: Permissions Defined by Grant in Sample Permissions File :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: :end-at: - This grant applies to the participant loading the |IdentityCert|, with the subject being: * Country: ``US`` * State: ``CA`` * Organization: ``Real Time Innovations`` * email address: ``meECdsa@rti.com`` * Common Name: ``dtlsexampleECdsa`` * - .. literalinclude:: ../snippets/example_permissions_file.xml :language: xml :class: break-lines :start-at: :end-at: - 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: :end-at: - 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 File` analyzes this grant. .. list-table:: Actions Allowed by Grant in Sample |PermissionsFile| :name: Actions Allowed by Grant in Sample Permissions File :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: :end-at: - The participant using this grant can only join domain 0 and domain 2. * - .. literalinclude:: ../snippets/example_permissions_file.xml :language: xml :class: break-lines :start-at: :end-at: - 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: :end-at: - 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 :lines: 44-48 - The participant using this grant is also allowed to publish 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. Finally, this grant denies any other action, as explained in :numref:`Default Permissions Defined by Grant in Sample Permissions File`. .. list-table:: Default Permissions Defined by Grant in Sample |PermissionsFile| :name: Default Permissions Defined by Grant in Sample Permissions File :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: :end-at: - 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 |PermissionsFile|, it looks for a grant with a :xmltag:`subject_name` matching its identity. Likewise, when a |DP| receives a remote |DP|'s |PermissionsFile|, 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 |PermissionsFile| is parsed from top to bottom. In other words, the first rule that matches the operation being attempted will apply, as defined by the DDS Security specification. 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 or subscribe 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 |PermissionsFile| 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 |PermissionsFile| and the |IdentityCert| (upon creation, your |DP| will independently verify that the |IdentityCert| and the grant in your |PermissionsFile| 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` or :xmltag:`subscribe` 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 operations. In the case where the default is :xmlval:`ALLOW`, the publish/subscribe 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`. XML Validation in the Permissions File -------------------------------------- The XSD definition of the |PermissionsFile| is in :file:`/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 |SP| 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 DDS Security specification introduces new builtin |TOPICs| and corresponding builtin |DR| and |DW| entities to read and write the |TOPICs|. The |SP| implements these |TOPICs| using the parameters defined by the DDS Security specification. 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 DDS Security specification, while others can be tuned through the |GovernanceFile| (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| (|LoggingTName|), as defined in the DDS Security specification. The following tables show the security parameters used by the |LoggingT|. .. list-table:: Endpoint Security Attributes for Builtin Secure Logging |DW| and |DR| (not configurable) :name: Endpoint Security Attributes for Builtin Secure Logging 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:`TRUE` * - :xmltag:`enable_write_access_control` - :xmlval:`FALSE` * - :xmltag:`metadata_protection_kind` - :xmlval:`SIGN` [#]_ * - :xmltag:`data_protection_kind` - :xmlval:`ENCRYPT` For more information about the |LoggingT|, see :ref:`p2_core/logging:Builtin Secure Logging Topic`. .. [#] In |CONNEXT| 5.3.0, the |LoggingT| did not use |SubmsgProtection| (which did not comply with the DDS Security specification). 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 Security Plugins Properties for Configuring Logging Distributed over DDS`). 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| | DCPSParticipant | DCPSParticipantSecure | +-------------+--------------------+-----------------------------+ | |EP_disc| | DCPSPublication | DCPSPublicationSecure | | +--------------------+-----------------------------+ | | DCPSSubscription | DCPSSubscriptionSecure | +-------------+--------------------+-----------------------------+ For further information about discovery |EPs|, see :link_um:`Discovery Implementation in the Core Libraries User's Manual `. 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_um:`The Built-in ServiceRequest DataReader in the Core Libraries User's Manual `.