3. Elements of a Connext DDS Secure System¶
This chapter covers all the elements that you need to secure a Connext DDS application.
3.1. QoS Properties¶
To enable and configure the Security Plugins, we use properties defined in the DomainParticipant’s PROPERTY QosPolicy (see PROPERTY QosPolicy (DDS Extension) in the Core Libraries User’s Manual). You can set these properties in code (see RTI Connext C++ API: PROPERTY) or in XML, similar to how you would set transport properties (see 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 Using Environment Variables in XML in the Core Libraries User’s Manual.
There are two kinds of properties to configure the Security Plugins (you can use a combination of them):
Properties starting with
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
com.rti.serv.secure.
(assuming you usedcom.rti.serv.secure
as the prefix to load the plugin, see Table 9.1) 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., 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.
Authentication, Access Control, Cryptography, and Security Events and Logging describe the properties to configure each of the plugins. Building and Running Security Plugins-Based Applications describes the properties for enabling the Security Plugins. Alternatively, you can make your profile inherit from the Generic.Security builtin
profile (which loads the security plugins dynamically).
All the Security Plugins properties are validated when the DomainParticipant and the plugin are created; for more information, see Property validation in the Core Libraries User’s Manual.
In order to have a successful Security Plugins properties validation, you can not add implementation-specific properties (e.g., properties starting with com.rti.serv.secure.
1) without first specifying the property com.rti.serv.load_plugin
. In the same way, you cannot disable the Security Plugins by just removing the com.rti.serv.load_plugin
, it is also necessary to remove the rest of the properties of the RTI Security Plugins.
Here are some examples:
Correct scenario.
... <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
com.rti.serv.secure.create_function
andcom.rti.serv.secure.library
will be considered invalid, and (by default) the participant creation will fail with an error.... <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 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 Table 9.1). 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.
3.2. Public Key Infrastructure (PKI)¶
The Security Plugins use public-key cryptography to establish a secure and authenticated communication between DomainParticipants. This includes mutually authenticating the participants, which involves validating their identities against the Identity Certificate Authority (CA) and establishing a Shared Key between them. It also includes validating the Governance and Permissions Files against a common Permissions CA.
3.2.1. Identity Certificates¶
To be correctly authenticated in the system, every secure DomainParticipant needs an Identity, consisting of two artifacts:
The Identity Certificate 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 DomainParticipant. The Identity Certificate 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 Identity Certificate to your DomainParticipant, use the
dds.sec.auth.identity_certificate
property (see Table 5.3).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 DomainParticipants, use the
dds.sec.auth.private_key
property (see Table 4.1).
To prevent attackers from forging their own identities, all the Identity Certificates in your system must be signed by a common Identity CA. As part of the authentication process, secure DomainParticipants will use the Identity CA certificate to validate the identity of discovered peers. Alternatively, Identity Certificates can be issued by subordinate CAs that chain up to the Identity CA, creating a chain of trust (see 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 dds.sec.auth.identity_ca
property.
3.2.1.1. Certificate Chaining¶
If your Identity Certificates 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 Identity Certificate, 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 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 Identity Certificate issued by subordinate CAs. (Note that all the DomainParticipants in your system should have access to a copy of the Identity CA certificate).
For details, see Identity Certificate Chaining.
3.2.1.2. Alternative CAs¶
Depending on your use case, different DomainParticipants may trust a different Identity CA. This can happen, for example, when several intermediate CAs exist in your PKI. In this case, your Identity Certificate 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 DomainParticipants. Therefore, there’s no way for every Identity Certificate to chain up to the same Identity CA. In this case, you can use the authentication.alternative_ca_files
property to make your participants load alternative Identity CAs (see Table 4.1). When you do so, your participant will use every alternative Identity CA (as well as the main Identity CA) to validate the Identity Certificate of remotely discovered participants.
3.2.1.3. 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 authentication.crl
property (see Table 4.1). By doing this, your DomainParticipant will check the certificate against the revocation list. For more information, see Identity Certificate Validation.
Important
If you update the revocation list, the changes will not take effect until you delete and recreate your DomainParticipant.
3.2.1.4. Multiple Certificate Revocation Lists¶
The value of the authentication.crl
property may contain the concatenation of multiple CRLs (see Table 4.1). For example, if a DomainParticipant is configured to have a list of alternative CAs, each of those alternative CAs may have its own CRL included as part of the authentication.crl
.
During certificate verification, only the CRL associated with the involved CA will be used. That is, if an Identity Certificate 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 Identity Certificate has been signed by an intermediate CA, then only the intermediate CA’s CRL will be used when verifying the certificate.
The authentication.crl
may also contain CRLs from the intermediate CAs of an Identity Certificate chain. If an element in the dds.sec.auth.identity_certificate
chain has not been revoked by its signer, then certificate verification will proceed as usual.
3.2.2. Governance and Permissions¶
To communicate securely, your participants need to follow the rules that you define through the Governance File, provided to your DomainParticipant through the 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 Permissions File, specified by the dds.sec.access.permissions
property. These properties are defined in Table 5.3.
Key Terms
A Governance File defines how your system is protected, while Permissions Files 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 DomainParticipants, therefore any DomainParticipant trusting that Permissions CA can verify whether another DomainParticipant has the permissions it claims. You specify the Permissions CA to your participants through the dds.sec.access.permissions_ca
property (see Table 5.3).
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 DomainParticipants may trust different Permissions CAs. In this case, you can use the access_control.alternative_permissions_authority_files
property to make your participants load alternative Permissions CAs (see Table 5.3). When you do so, your participant will use every alternative Permissions CA (as well as the main Permissions CA) to validate the Permissions File of remotely discovered participants.
3.3. 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 Governance File. The Governance File defines two levels of configuration properties: domain level, affecting participants in the Domain (see domain-level rules); and topic level, affecting Endpoints from that Topic (see Topic-Level Rules). You can apply these rules to a single Domain, multiple Domains, or ranges of Domains (see Specifying Domain IDs).
The Governance File must be signed by the Permissions CA using a PKCS#7 signature. You need to specify the signed version of your Governance File using the dds.sec.access.governance
property, as described in Table 5.3.
All the participants in your system need to load the same Governance File, or compatible versions (see Governance Compatibility Validation).
3.3.1. Specifying Domain IDs¶
Both the Governance File and the Permissions File require you to specify the applicable domain IDs using the domains
tag. You may use this tag to specify individual domain IDs, domain ranges, open domain ranges, and combinations thereof.
Example: Individual Domain IDs. \(Domains_{protected} = \lbrace 0 \rbrace\cup\lbrace 1\rbrace\)
<domains>
<!-- Domains 0 and 1 -->
<id>0</id>
<id>1</id>
</domains>
Example: Domain Ranges. \(Domains_{protected} = \lbrack 3, 10\rbrack\)
<domains>
<!-- All domains between 3 and 10, inclusive -->
<id_range>
<min>3</min>
<max>10</min>
</id_range>
</domains>
Example: Open Domain Ranges. \(Domains_{protected} =\lbrack 0, 5\rbrack\cup\lbrack 10, \mathtt{MAX\_VALID\_DOMAIN\_ID}\rbrack\) 2
<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. \(Domains_{protected} = \lbrace 3 \rbrace\cup\lbrace 7 \rbrace\cup\lbrack 10, 20 \rbrack\cup\lbrack50, \mathtt{MAX\_VALID\_DOMAIN\_ID}\rbrack\)
<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>
- 2
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 theDDS_RtpsWellKnownPorts_t
structure (see 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 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 Domain ID Support in the Core Libraries Platform Notes.
3.3.2. Domain-Level Rules¶
Domain-level rules affect participants in the Domain, taking effect at the DomainParticipant level. These rules will apply to every DomainParticipant in the Domain (or Domain range) that you specify in the domains
tag (see Specifying Domain IDs). Domain-level rules fall under a domain_rule
tag, as shown in Example Governance File (XML).
allow_unauthenticated_participants
: Determines if a secure DomainParticipant 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 Secure Domain. For details, see allow_unauthenticated_participants (domain_rule).enable_join_access_control
: Determines if the participant-level permissions configured in the Permissions File are enforced for remote participants. For details, see enable_join_access_control (within a domain_rule).discovery_protection_kind
andliveliness_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:ENCRYPT
,ENCRYPT_WITH_ORIGIN_AUTHENTICATION
,SIGN
,SIGN_WITH_ORIGIN_AUTHENTICATION
,NONE
. For details, see Domain-Level Rules.rtps_protection_kind
: Determines what level of protection is applied to RTPS messages. Possible values:ENCRYPT
,ENCRYPT_WITH_ORIGIN_AUTHENTICATION
,SIGN
,SIGN_WITH_ORIGIN_AUTHENTICATION
,NONE
. For details, see Domain-Level Rules.
3.3.3. Topic-Level Rules¶
Topic-level rules affect Endpoints for a particular Topic or set of Topics. They belong in a topic_rule
, which identifies the Topic that the rule applies to with the topic_expression
attribute. All topic_rule
tags that apply to your Domain or Domain range fall under the topic_access_rules
tag, as shown in Example Governance File (XML).
enable_discovery_protection
/enable_liveliness_protection
: Determines if discovery information and liveliness updates related to Endpoints from this Topic will be sent with the level of security defined in the domain-leveldiscovery_protection_kind
andliveliness_protection_kind rules
. For details, see Topic-Level Rules.enable_read_access_control
/enable_write_access_control
: Determines if endpoint-level permissions configured in the Permissions File are enforced for local and remote DataReader/DataWriter. For details, see Topic-Level Rules.metadata_protection_kind
: Determines what level of protection is applied to RTPS submessages from Endpoints of the associated Topic. Possible values:ENCRYPT
,ENCRYPT_WITH_ORIGIN_AUTHENTICATION
,SIGN
,SIGN_WITH_ORIGIN_AUTHENTICATION
,NONE
. For details, see Topic-Level Rules.data_protection_kind
: Determines what level of protection is applied to the serialized payload from Endpoints of the associated topic. Possible values:ENCRYPT
,SIGN
,NONE
. For details, see Topic-Level Rules.
3.3.4. Example Governance File (XML)¶
This is an example of what a Governance File looks like. You can find this example document in 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 Identity Certificates) before signing the Governance File.
<?xml version="1.0" encoding="UTF-8"?>
<dds xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://community.rti.com/schema/6.1.1/dds_security_governance.xsd">
<domain_access_rules>
<domain_rule>
<domains>
<id_range>
<min>0</min>
</id_range>
</domains>
<allow_unauthenticated_participants>
FALSE
</allow_unauthenticated_participants>
<enable_join_access_control>TRUE</enable_join_access_control>
<discovery_protection_kind>ENCRYPT</discovery_protection_kind>
<liveliness_protection_kind>ENCRYPT</liveliness_protection_kind>
<rtps_protection_kind>SIGN</rtps_protection_kind>
<topic_access_rules>
<topic_rule>
<topic_expression>Sq*</topic_expression>
<enable_discovery_protection>FALSE</enable_discovery_protection>
<enable_liveliness_protection>FALSE</enable_liveliness_protection>
<enable_read_access_control>FALSE</enable_read_access_control>
<enable_write_access_control>FALSE</enable_write_access_control>
<metadata_protection_kind>NONE</metadata_protection_kind>
<data_protection_kind>NONE</data_protection_kind>
</topic_rule>
<topic_rule>
<topic_expression>*</topic_expression>
<enable_discovery_protection>TRUE</enable_discovery_protection>
<enable_liveliness_protection>TRUE</enable_liveliness_protection>
<enable_read_access_control>TRUE</enable_read_access_control>
<enable_write_access_control>TRUE</enable_write_access_control>
<metadata_protection_kind>ENCRYPT</metadata_protection_kind>
<data_protection_kind>ENCRYPT</data_protection_kind>
</topic_rule>
</topic_access_rules>
</domain_rule>
</domain_access_rules>
</dds>
The Governance File above defines just one configuration to be applied to any Domain in the system (as specified by the domains
XML tag). Consequently, all the Domains and Topics in the system are protected in the same way, in particular, see Table 3.1:
Domain-level rule ( |
Value |
Security implications |
---|---|---|
|
|
Only authenticated participants are allowed in the system |
|
|
Permissions are checked for any matched and authenticated remote participant |
|
|
The integrity and confidentiality of the Builtin Secure Discovery Topics are protected |
|
|
The integrity and confidentiality of the Builtin Secure Liveliness Topic are protected |
|
|
The integrity of RTPS messages is protected |
Then, this Governance File defines two topic-level rules, as analyzed in Table 3.2 and Table 3.3.
Topic-level rule ( |
Value |
Security implications |
---|---|---|
|
|
Endpoint discovery data for these Topics is not protected |
|
|
Liveliness assertions for these Topics are not protected |
|
|
Neither local or remote permissions are checked for DataReaders of these Topics |
|
|
Neither local or remote permissions are checked for DataWriters of these Topics |
|
|
These Topics are not protected at the Submessage level |
|
|
These Topics are not protected at the Serialized Data level. |
Topic-level rule ( |
Value |
Security implications |
---|---|---|
|
|
Endpoint discovery data for the rest of the Topics is protected (encrypted, as specified by |
|
|
Liveliness assertions for the rest of the Topics are protected (encrypted, as specified by |
|
|
Permissions are checked for locally created and remotely discovered DataReaders |
|
|
Permissions are checked for locally created and remotely discovered DataWriters |
|
|
The integrity and confidentiality of RTPS Submessages are protected for the rest of the Topics |
|
|
The integrity and confidentiality of Serialized Data are protected for the rest of the Topics |
3.3.5. How the Governance File is Interpreted¶
The rules that compose the Governance File specify how your system is protected. All the DomainParticipants in your secure system need to load the same or a compatible Governance File, either by having a copy of it or by accessing a single Governance File from a shared location (see Governance Compatibility Validation for more details).
As defined by the DDS Security specification, the Governance File is parsed from top to bottom. The first domain_rule
matching the participant’s Domain ID will apply to this participant. This means that your Governance File could potentially define other domain_rules
for that Domain ID that will not be used.
Note that a DomainParticipant joining a Secure Domain must have compatible domain-level rules. This means that rtps_protection_kind
, discovery_protection_kind
, and liveliness_protection_kind
must match. Otherwise, secure participants will not be able to communicate in the Secure Domain. For details, see Governance Compatibility Validation.
Then, inside a domain_rule
section, the topic-level rules will also be parsed from top to bottom. The first topic_rule
with a 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 Secure DataWriters and Secure DataReaders need to have compatible topic-level rules. This means that data_protection_kind
, metadata_protection_kind
, enable_discovery_protection
, enable_liveliness_protection
, enable_read_access_control
and enable_write_access_control
must match. Otherwise, Secure Endpoints will not be able to communicate. For details, see Governance Compatibility Validation.
3.3.6. XML Validation in the Governance File¶
The XSD definition of the Governance File is in <NDDSHOME>/resource/schema/dds_security_governance.xsd
.
<?xml version="1.0" encoding="UTF-8"?>
<!--
(c) Copyright, Real-Time Innovations, Inc. 2001-2016.
All rights reserved.
No duplications, whole or partial, manual or electronic, may be made
without prior written permission. Any such copies, or
revisions thereof, must display this notice unaltered.
This code contains trade secrets of Real-Time Innovations, Inc.
-->
<!-- =================================================================== -->
<!-- RTI Domain Governance XML Schema File -->
<!-- =================================================================== -->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="dds" type="DomainAccessRulesNode" />
<xs:complexType name="DomainAccessRulesNode">
<xs:sequence minOccurs="1" maxOccurs="1">
<xs:element name="domain_access_rules" type="DomainAccessRules" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="DomainAccessRules">
<xs:sequence minOccurs="1" maxOccurs="unbounded">
<xs:element name="domain_rule" type="DomainRule" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="DomainRule">
<xs:sequence minOccurs="1" maxOccurs="1">
<xs:element name="domains" type="DomainIdSet" />
<xs:element name="allow_unauthenticated_participants" type="xs:boolean" />
<xs:element name="enable_join_access_control" type="xs:boolean" />
<xs:element name="discovery_protection_kind" type="ProtectionKind" />
<xs:element name="liveliness_protection_kind" type="ProtectionKind" />
<xs:element name="rtps_protection_kind" type="ProtectionKind" />
<xs:element name="topic_access_rules" type="TopicAccessRules" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="DomainIdSet">
<xs:choice minOccurs="1" maxOccurs="unbounded">
<xs:element name="id" type="DomainId" />
<xs:element name="id_range" type="DomainIdRange" />
</xs:choice>
</xs:complexType>
<xs:simpleType name="DomainId">
<xs:restriction base="xs:nonNegativeInteger" />
</xs:simpleType>
<xs:complexType name="DomainIdRange">
<xs:choice>
<xs:sequence>
<xs:element name="min" type="DomainId" />
<xs:element name="max" type="DomainId" minOccurs="0" />
</xs:sequence>
<xs:element name="max" type="DomainId" />
</xs:choice>
</xs:complexType>
<xs:simpleType name="BasicProtectionKind">
<xs:restriction base="xs:string">
<!-- RTI extension: allow whitespaces surrounding values -->
<xs:whiteSpace value="collapse"/>
<xs:enumeration value="ENCRYPT" />
<xs:enumeration value="SIGN" />
<xs:enumeration value="NONE" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="ProtectionKind">
<xs:restriction base="xs:string">
<!-- RTI extension: allow whitespaces surrounding values -->
<xs:whiteSpace value="collapse"/>
<xs:enumeration value="ENCRYPT_WITH_ORIGIN_AUTHENTICATION" />
<xs:enumeration value="SIGN_WITH_ORIGIN_AUTHENTICATION" />
<xs:enumeration value="ENCRYPT" />
<xs:enumeration value="SIGN" />
<xs:enumeration value="NONE" />
</xs:restriction>
</xs:simpleType>
<xs:complexType name="TopicAccessRules">
<xs:sequence minOccurs="1" maxOccurs="unbounded">
<xs:element name="topic_rule" type="TopicRule" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="TopicRule">
<xs:sequence minOccurs="1" maxOccurs="1">
<xs:element name="topic_expression" type="TopicExpression" />
<xs:element name="enable_discovery_protection" type="xs:boolean" />
<xs:element minOccurs="0" name="enable_liveliness_protection" type="xs:boolean" />
<xs:element name="enable_read_access_control" type="xs:boolean" />
<xs:element name="enable_write_access_control" type="xs:boolean" />
<xs:element name="metadata_protection_kind" type="ProtectionKind" />
<xs:element name="data_protection_kind" type="BasicProtectionKind" />
</xs:sequence>
</xs:complexType>
<xs:simpleType name="TopicExpression">
<xs:restriction base="xs:string" />
</xs:simpleType>
</xs:schema>
3.3.7. Governance Compatibility Validation¶
Governance Files loaded by different DomainParticipants need to be compatible. The Security Plugins 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 DomainParticipant 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:
RTPS Protection (configured with the
rtps_protection_kind
domain-level rule)Discovery Protection (configured with the
discovery_protection_kind
domain-level rule)Liveliness Protection (configured with the
liveliness_protection_kind
domain-level rule)
If local and remote Governance Files 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 Governance Rules for the topic of the Secure Endpoints:
Serialized Data Protection (configured with the
data_protection_kind
topic-level rule)Submessage Protection (configured with the
metadata_protection_kind
topic-level rule)Discovery Protection (configured with the
enable_discovery_protection
topic-level rule)Liveliness Protection (configured with the
enable_liveliness_protection
topic-level rule)Access Control Enforcements (configured with the
enable_read_access_control
andenable_write_access_control
topic-level rules).
3.4. Permissions File¶
The Permissions Document specifies what actions a DomainParticipant is allowed to take in a DDS Secure Domain. For example, it determines whether the DomainParticipant can join the Domain, whether it can publish or subscribe to particular Topics, etc.
Permissions Files 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 Permissions Files locks down the specific access that trusted applications have, so if one becomes compromised, the damage to the system is limited.
The Permissions File contains a set of grants, which in turn contain a set of allow_rule
and deny_rule
sections. These rules define what your DomainParticipant is allowed to do in a specific Domain (or range of Domains, as defined in Specifying Domain IDs).
Grants are bound to the DomainParticipant identity. In other words, the subject_name
section of the grant identifies the specific DomainParticipant to which the permissions apply. The contents of the subject_name
tag need to match the subject name in the participant’s Identity Certificate, 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 RTI Security Plugins Getting Started Guide Hands-on 4 for an example openssl command to extract a correctly-formatted subject name.
Each Permissions File must be signed by the Permissions CA using a PKCS#7 signature. You need to specify the signed version of your Permissions File using the dds.sec.access.permissions
property, as described in Table 5.3. Note that the contents of your Permissions Files are sent in the clear during participant authentication (right after Participant Discovery). Therefore, to reduce your network usage each of your Permissions Files should only contain a grant for the participant loading it. For further details, see Contents of Your Permissions Files.
3.4.1. Example Permissions File (XML)¶
This is an example of what a Permissions File looks like. You can find example documents in 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 Identity Certificates) before signing the Permissions Files.
<?xml version="1.0" encoding="UTF-8"?>
<dds xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://community.rti.com/schema/6.1.1/dds_security_permissions.xsd">
<permissions>
<grant name="ParticipantA">
<subject_name>
C = US,
ST = CA,
O = Real Time Innovations,
emailAddress = meECdsa@rti.com,
CN = dtlsexampleECdsa
</subject_name>
<validity>
<!-- Format is CCYY-MM-DDThh:mm:ss[Z|(+|-)hh:mm] in GMT -->
<not_before>2020-06-30T13:00:00</not_before>
<not_after>2030-06-30T13:00:00</not_after>
</validity>
<allow_rule>
<domains>
<id>0</id>
<id>2</id>
</domains>
<publish>
<topics>
<topic>Cir*</topic>
</topics>
<partitions>
<partition>P1*</partition>
</partitions>
</publish>
<subscribe>
<topics>
<topic>*Sq*</topic>
</topics>
<partitions>
<partition>P2</partition>
</partitions>
<data_tags>
<tag>
<name>Title</name>
<value>*Software*</value>
</tag>
</data_tags>
</subscribe>
<subscribe>
<topics>
<topic>Triangle</topic>
</topics>
</subscribe>
</allow_rule>
<default>DENY</default>
</grant>
</permissions>
</dds>
This Permissions File configures a single grant, which are analyzed in Table 3.4.
XML Attribute |
Security Implications |
---|---|
<subject_name>
C = US,
ST = CA,
O = Real Time Innovations,
emailAddress = meECdsa@rti.com,
CN = dtlsexampleECdsa
</subject_name>
|
This grant applies to the participant loading the Identity Certificate, with the subject being:
|
<not_before>2020-06-30T13:00:00</not_before>
|
This grant can only be used after June 30, 2020 at 1:00 pm (GMT). |
<not_after>2030-06-30T13:00:00</not_after>
|
This grant can only be used before June 30, 2030 at 1:00 pm (GMT). |
This grant then defines an 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). Table 3.5 analyzes this grant.
XML Attribute |
Security Implications |
---|---|
<domains>
<id>0</id>
<id>2</id>
</domains>
|
The participant using this grant can only join domain 0 and domain 2. |
<publish>
<topics>
<topic>Cir*</topic>
</topics>
<partitions>
<partition>P1*</partition>
</partitions>
</publish>
|
The participant using this grant is only allowed to publish topics starting with |
<subscribe>
<topics>
<topic>*Sq*</topic>
</topics>
<partitions>
<partition>P2</partition>
</partitions>
<data_tags>
<tag>
<name>Title</name>
<value>*Software*</value>
</tag>
</data_tags>
</subscribe>
|
The participant using this grant is allowed to subscribe to Topics containing Moreover, to subscribe to the aforementioned topics, the participant must use readers that either do not announce any data tag, or they announce the |
</data_tags>
</subscribe>
<subscribe>
<topics>
<topic>Triangle</topic>
|
The participant using this grant is also allowed to publish the Topic The DataReader created by the participant to subscribe to the |
Finally, this grant denies any other action, as explained in Table 3.6.
XML Attribute |
Security Implications |
---|---|
<default>DENY</default>
|
Any action not explicitly allowed in an |
3.4.2. How the Permissions are Interpreted¶
Permissions for DDS Entities in a DomainParticipant are associated with the subject in the DomainParticipant’s Identity Certificate. When a DomainParticipant loads a Permissions File, it looks for a grant with a subject_name
matching its identity. Likewise, when a DomainParticipant receives a remote DomainParticipant’s Permissions File, it looks for a grant with a subject_name
matching the remote’s identity. In other words, the subject_name
identifies the DomainParticipant to which the grant’s permissions apply.
Note
The contents of the subject_name
tag must be the X.509 subject name
for the DomainParticipant, as given in the Subject field of its Identity Certificate.
The Permissions File 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 id
being an exact match or by 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 default
rule is applied.
The Permissions File loaded by your DomainParticipant needs to contain exactly one grant for this DomainParticipant. Otherwise, the participant creation will fail. Also, the grant needs to be valid for the current date. The Access Control Plugin checks the 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 Permissions File and the Identity Certificate (upon creation, your DomainParticipant will independently verify that the Identity Certificate and the grant in your Permissions File are valid for the current date).
You can give a participant permission to join a Domain by including that Domain ID in the domain
tag of an allow_rule
. Alternatively, if you set the default
to ALLOW
, the participant will have access to all Domains that are not included in a 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 deny_rule
has any publish
or subscribe
tags, then the deny_rule
will not prevent a DomainParticipant from being created; it will only prevent certain Topics, DataWriters, and DataReaders from being created.
DomainParticipants will only be allowed to perform publish operations for Topics, Partitions and tags that explicitly appear under an allow_rules
section, unless the default is set to ALLOW
. The same applies to subscribe operations. In the case where the default is ALLOW
, the publish/subscribe operation will only be denied if it appears inside a 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.
...
<deny_rule>
<domains>
<id>0</id>
</domains>
<publish>
<topics>
<topic>*</topic>
</topics>
<partitions>
<partition>A</partition>
</partitions>
</publish>
</deny_rule>
<allow_rule>
<domains>
<id>0</id>
</domains>
<publish>
<topics>
<topic>*</topic>
</topics>
<partitions>
<partition>*</partition>
</partitions>
</publish>
</allow_rule>
<default>DENY</default>
...
For further information on how each rule is interpreted, refer to Permissions Document.
3.4.3. XML Validation in the Permissions File¶
The XSD definition of the Permissions File is in
<NDDSHOME>/resource/schema/dds_security_permissions.xsd
.
<?xml version="1.0" encoding="UTF-8"?>
<!--
(c) Copyright, Real-Time Innovations, Inc. 2014-2017.
All rights reserved.
No duplications, whole or partial, manual or electronic, may be made
without prior written permission. Any such copies, or
revisions thereof, must display this notice unaltered.
This code contains trade secrets of Real-Time Innovations, Inc.
-->
<!-- =================================================================== -->
<!-- RTI Security XML Schema File -->
<!-- =================================================================== -->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<!-- =================================================================== -->
<!-- Main Elements -->
<!-- =================================================================== -->
<xs:element name="dds" type="PermissionsNode" />
<xs:complexType name="PermissionsNode">
<xs:sequence minOccurs="1" maxOccurs="1">
<xs:element name="permissions" type="Permissions" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="Permissions">
<xs:sequence minOccurs="1" maxOccurs="unbounded">
<xs:element name="grant" type="Grant" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="Grant">
<xs:sequence minOccurs="1" maxOccurs="1">
<xs:element name="subject_name" type="xs:string" />
<xs:element name="validity" type="Validity" />
<xs:sequence minOccurs="1" maxOccurs="unbounded">
<xs:choice minOccurs="1" maxOccurs="1">
<xs:element name="allow_rule" minOccurs="0" type="Rule" />
<xs:element name="deny_rule" minOccurs="0" type="Rule" />
</xs:choice>
</xs:sequence>
<xs:element name="default" type="DefaultAction" />
</xs:sequence>
<xs:attribute name="name" type="xs:string" use="required" />
</xs:complexType>
<xs:complexType name="Validity">
<xs:sequence minOccurs="1" maxOccurs="1">
<xs:element name="not_before" type="xs:dateTime" /> <!-- DDSSEC-134 -->
<xs:element name="not_after" type="xs:dateTime" /> <!-- DDSSEC-134 -->
</xs:sequence>
</xs:complexType>
<xs:complexType name="Rule">
<xs:sequence minOccurs="1" maxOccurs="1">
<!-- DDSSEC-75 -->
<xs:element name="domains" type="DomainIdSet" />
<xs:sequence minOccurs="0" maxOccurs="unbounded"> <!-- DDSSEC-134 -->
<xs:element name="publish" type="Criteria" />
</xs:sequence>
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="subscribe" type="Criteria" />
</xs:sequence>
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="relay" type="Criteria" />
</xs:sequence>
</xs:sequence>
</xs:complexType>
<!-- DDSSEC-75 -->
<xs:complexType name="DomainIdSet">
<xs:choice minOccurs="1" maxOccurs="unbounded">
<xs:element name="id" type="DomainId" />
<xs:element name="id_range" type="DomainIdRange" />
</xs:choice>
</xs:complexType>
<!-- DDSSEC-75 -->
<xs:simpleType name="DomainId">
<xs:restriction base="xs:nonNegativeInteger" />
</xs:simpleType>
<!-- DDSSEC-75 -->
<xs:complexType name="DomainIdRange">
<xs:choice> <!-- DDSSEC-134 -->
<xs:sequence>
<xs:element name="min" type="DomainId" />
<xs:element name="max" type="DomainId" minOccurs="0" />
</xs:sequence>
<xs:element name="max" type="DomainId" />
</xs:choice>
</xs:complexType>
<xs:complexType name="Criteria">
<!-- DDSSEC-72 -->
<xs:all minOccurs="1">
<xs:element name="topics" minOccurs="1" type="TopicExpressionList" />
<xs:element name="partitions" minOccurs="0" type="PartitionExpressionList" />
<xs:element name="data_tags" minOccurs="0" type="DataTags" />
</xs:all>
</xs:complexType>
<!-- DDSSEC-72 -->
<xs:complexType name="TopicExpressionList">
<xs:sequence minOccurs="1" maxOccurs="unbounded">
<xs:element name="topic" type="TopicExpression" />
</xs:sequence>
</xs:complexType>
<!-- DDSSEC-72 -->
<xs:complexType name="PartitionExpressionList">
<xs:sequence minOccurs="1" maxOccurs="unbounded">
<xs:element name="partition" type="PartitionExpression" />
</xs:sequence>
</xs:complexType>
<xs:simpleType name="TopicExpression">
<xs:restriction base="xs:string" />
</xs:simpleType>
<xs:simpleType name="PartitionExpression">
<xs:restriction base="xs:string" />
</xs:simpleType>
<xs:complexType name="DataTags">
<xs:sequence minOccurs="1" maxOccurs="unbounded">
<xs:element name="tag" type="TagNameValuePair" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="TagNameValuePair">
<xs:sequence minOccurs="1" maxOccurs="unbounded">
<xs:element name="name" type="xs:string" />
<xs:element name="value" type="xs:string" />
</xs:sequence>
</xs:complexType>
<xs:simpleType name="DefaultAction">
<xs:restriction base="xs:string">
<xs:enumeration value="ALLOW" />
<xs:enumeration value="DENY" />
</xs:restriction>
</xs:simpleType>
</xs:schema>
3.5. Security Builtin Topics¶
To perform some of the security operations (such as mutual authentication) between DomainParticipants, the Security Plugins 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 DataReader and DataWriter entities to read and write the Topics. The Security Plugins 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 Governance File (see details below).
3.5.1. 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 Authentication Builtin Topic (ParticipantStatelessMessage).
Policy |
Kind |
---|---|
|
|
3.5.2. Secure Key Exchange Builtin Topic (ParticipantVolatileMessageSecure)¶
DomainParticipants use the Secure Key Exchange Builtin Topic to exchange the symmetric keys that secure entities need to communicate securely. This Topic allows DomainParticipants 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 Secure Key Exchange Builtin Topic uses Submessage Protection to encrypt the RTPS submessages that include the exchanged keys. For details, see Secure Key Exchange Channel (ParticipantVolatileMessageSecure Topic).
The following tables show the security parameters and QoS settings used by the Secure Key Exchange Builtin Topic.
Topic-Level Rule |
Value |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
Policy |
Kind |
---|---|
|
|
|
|
|
|
3.5.3. Builtin Secure Logging Topic¶
You can distribute the security logging information over DDS. If you decide to do so, your DomainParticipant will publish this information to the Builtin Secure Logging Topic (DDS:Security:LogTopic), as defined in the DDS Security specification.
The following tables show the security parameters used by the Builtin Secure Logging Topic.
Topic-Level Rule |
Value |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
For more information about the Builtin Secure Logging Topic, see Builtin Secure Logging Topic.
- 3
In Connext DDS 5.3.0, the Builtin Secure Logging Topic did not use Submessage Protection (which did not comply with the DDS Security specification). For backward compatibility, you can choose to disable Submessage Protection in this Topic with the
access_control.use_530_logging_protection
property (see Table 7.3).
3.5.4. Builtin Secure Discovery Topics¶
The Builtin Secure Discovery Topics 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 Endpoints for a certain Topic with the enable_discovery_protection
Governance Rule. If you set this Governance Rule to TRUE
, discovery information related to your Topic will be exchanged through the Builtin Secure Discovery Endpoints. These Endpoints will apply Submessage Protection to the level you configure with the discovery_protection_kind
Governance Rule. Note that enable_discovery_protection
also determines whether Topic Queries are secured (see Builtin Secure ServiceRequest Topic).
Note that the Builtin Secure Discovery Endpoints are created in addition to the unsecure version of the same Endpoints, and have the same QoS configuration. The following table shows the correspondence between the secure and unsecure versions of the discovery builtin Topics.
Description |
DDS Builtin Topics |
DDS Security Builtin Topics |
---|---|---|
Participant Discovery |
DCPSParticipant |
DCPSParticipantSecure |
Endpoint Discovery |
DCPSPublication |
DCPSPublicationSecure |
DCPSSubscription |
DCPSSubscriptionSecure |
For further information about discovery Endpoints, see Discovery Implementation in the Core Libraries User’s Manual. For more information about the secure version of discovery Endpoints see Builtin Secure Discovery Endpoints.
3.5.5. Builtin Secure Liveliness Topic¶
You can configure whether to use the secure or unsecure version of the Builtin Liveliness Endpoints for a certain Topic with the enable_liveliness_protection
Governance Rule. If you set this Governance Rule to TRUE
, liveliness information related to your Topic will be exchanged through the Builtin Secure Liveliness Endpoints. These Endpoints will apply Submessage Protection to the level you configure with the liveliness_protection_kind
Governance Rule. Please note that the Builtin Liveliness Topics (either the secure and regular version) are only used for Topics that set the LIVELINESS QosPolicy to AUTOMATIC
or MANUAL_BY_PARTICIPANT
(see enable_liveliness_protection (topic_rule)).
Note that the Builtin Secure Liveliness Endpoints are created in addition to the unsecure version of the same Endpoints, and have the same QoS configuration. The following table shows the correspondence between the secure and unsecure versions of the liveliness builtin Topic.
Description |
DDS Builtin Topics |
DDS Security Builtin Topics |
---|---|---|
Liveliness (when the LIVELINESS QosPolicy of a particular Topic is
|
DCPSParticipantMessage |
DCPSParticipantMessageSecure |
For more information about the secure version of the liveliness Endpoints see Builtin Secure Liveliness Endpoints.
3.5.6. Builtin Secure ServiceRequest Topic¶
The Builtin Secure ServiceRequest Topic is a vendor-specific Topic analogous to the Builtin ServiceRequest Topic. Whenever you use the secure version of the Builtin Discovery Endpoints (by setting enable_discovery_protection
), the Builtin Secure ServiceRequest Endpoints will be used to communicate Topic Queries. These Endpoints will apply Submessage Protection to the level you configure with the discovery_protection_kind
Governance Rule.
Note that the Builtin Secure ServiceRequest Endpoints are created in addition to the unsecure version of the same Endpoints. The following table shows the correspondence between the secure and unsecure versions of the ServiceRequest builtin Topics.
Description |
DDS Builtin Topics |
DDS Security Builtin Topics |
---|---|---|
Service Request |
DDSServiceRequest |
DDSServiceRequestSecure |
For further information, see The Built-in ServiceRequest DataReader in the Core Libraries User’s Manual.