6. Hands-On 3: Defining the DomainParticipant Permissions
In this Hands-On, we will specify what the DomainParticipants in your project will be allowed to do within your secure system. We will achieve this by writing a Permissions Document for each of your participants.
Going back to our example, Alice will only have permission to publish the PatientMonitoring data, while Bob will be restricted to subscribe to patient-related Topics. We will associate each Permissions Document with its corresponding participant based on their identities, limiting the system damage if one of your applications becomes compromised. To put the Permissions Documents into effect, we will sign them with the provided Permissions CA. Finally, we will modify your secure participants’ QoS profiles to point to the new Permissions Documents and see how the new permissions are applied.
Note
We will use the OpenSSL CLI to perform the security operations in the generation of the security artifacts. Make sure to include in the path your OpenSSL binary directory [3]. The installation process is described in the RTI Security Plugins Installation Guide.
Note that the Security Plugins do not depend on OpenSSL to generate these artifacts; you can use the security toolkit of your choice. With that said, we recommend using OpenSSL to make sure that the certificates are in the right format.
6.1. Granting Permissions to Your Secure Participants
As the DDS Security expert at Patient Monitoring Innovations (PMI), you are going to specify the permissions of every DomainParticipant in your system. You will define what Topics your publisher, Alice, can read/write by associating rules with the subject in her Identity Certificate.
Create a file called pmiPermissionsAlice.xml
in the xml
directory (along with the rest of XML files) and add the following content:
<?xml version="1.0" encoding="UTF-8"?>
<dds xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://community.rti.com/schema/7.3.0/dds_security_permissions.xsd">
<permissions>
<!-- Grants for a specific DomainParticipant will be grouped under this tag -->
<grant name="ParticipantAlice">
<!-- 1. The rules below will apply to the DomainParticipant
whose Identity certificate contains this subject name -->
<subject_name>Alice's X.509 subject (see below)</subject_name>
<!-- 2. Validity dates for this grant -->
<validity>
<!-- Format is CCYY-MM-DDThh:mm:ss[Z|(+|-)hh:mm] in GMT -->
<not_before>2019-10-31T13:00:00</not_before>
<not_after>2029-10-31T13:00:00</not_after>
</validity>
<!-- 3. Allow this participant to publish the
PatientMonitoring topic -->
<allow_rule>
<domains>
<id>1</id>
</domains>
<publish>
<topics>
<topic>Example PatientMonitoring</topic>
</topics>
</publish>
</allow_rule>
<!-- 4. This participant will not be allowed to publish or
subscribe to any other topic -->
<default>DENY</default>
</grant>
</permissions>
</dds>
This Permissions Document configures a grant for ParticipantAlice, identified by its Identity Certificate (1). We will define the grant’s subject name to make it apply to your publisher in Binding the Permissions Document to Your DomainParticipants. The validity of this grant is restricted in time (2). This grant has a single allow rule (3), so ParticipantAlice will only be allowed to:
Join Domain 1
Publish the Topic “Example PatientMonitoring” — only in Domain 1
ParticipantAlice will be denied attempts to perform any other action (4).
In addition to configuring allow rules, we can specify deny rules with the opposite effect. For details, see the Permissions Document in the RTI Security Plugins User’s Manual.
Note
Permissions Documents are always exchanged during authentication. The larger a Permissions Document is, the more network overhead it will cause. As such, we recommend that you keep separate Permissions Documents per identity (i.e., per DomainParticipant). For further details, see Choosing the Granularity of Your Permissions Documents for DomainParticipants in the RTI Security Plugins User’s Manual.
6.2. Binding the Permissions Document to Your DomainParticipants
When a DomainParticipant loads a Permissions Document, it looks for a grant
with a subject_name
matching its identity. In other words, the
subject_name
identifies the DomainParticipant to which the grant’s
permissions apply. The contents of the subject_name
tag should be
the X.509 subject name for the DomainParticipant, as given in the
Subject field of its Identity Certificate.
If you followed the steps in Hands-On 1: Securing Connext DDS Applications, Alice’s Identity Certificate
should be cert/ecdsa01/identities/ecdsa01Peer01Cert.pem
. The subject
of Alice’s certificate does not match the subject_name
section in
grant ParticipantAlice. We will modify pmiPermissionsAlice.xml
to make
this grant apply to Alice.
Check the information from Alice’s Identity Certificate (
ecdsa01Peer01Cert.pem
) with the following command:$ openssl x509 -in cert/ecdsa01/identities/ecdsa01Peer01Cert.pem -text -noout Certificate: Data: Version: 3 (0x2) Serial Number: 7b:ba:b9:c9:2c:be:ee:b9:71:d0:62:4e:59:6b:de:89:3a:33:5c:ad Signature Algorithm: ecdsa-with-SHA256 Issuer: C=US, ST=CA, L=Santa Clara, O=Real Time Innovations, CN=RTI ECDSA01 (p256) ROOT CA, emailAddress=ecdsa01RootCa@rti.com Validity Not Before: Jan 28 21:26:58 2021 GMT Not After : Jan 27 21:26:58 2026 GMT Subject: C=US, ST=CA, O=Real Time Innovations, emailAddress=ecdsa01Peer01@rti.com, CN=RTI ECDSA01 (p256) PEER01 Subject Public Key Info: ...
$ openssl x509 -in cert/ecdsa01/identities/ecdsa01Peer01Cert.pem -text -noout Certificate: Data: Version: 3 (0x2) Serial Number: 7b:ba:b9:c9:2c:be:ee:b9:71:d0:62:4e:59:6b:de:89:3a:33:5c:ad Signature Algorithm: ecdsa-with-SHA256 Issuer: C=US, ST=CA, L=Santa Clara, O=Real Time Innovations, CN=RTI ECDSA01 (p256) ROOT CA, emailAddress=ecdsa01RootCa@rti.com Validity Not Before: Jan 28 21:26:58 2021 GMT Not After : Jan 27 21:26:58 2026 GMT Subject: C=US, ST=CA, O=Real Time Innovations, emailAddress=ecdsa01Peer01@rti.com, CN=RTI ECDSA01 (p256) PEER01 Subject Public Key Info: ...
> openssl x509 -in cert\ecdsa01\identities\ecdsa01Peer01Cert.pem -text -noout Certificate: Data: Version: 3 (0x2) Serial Number: 7b:ba:b9:c9:2c:be:ee:b9:71:d0:62:4e:59:6b:de:89:3a:33:5c:ad Signature Algorithm: ecdsa-with-SHA256 Issuer: C=US, ST=CA, L=Santa Clara, O=Real Time Innovations, CN=RTI ECDSA01 (p256) ROOT CA, emailAddress=ecdsa01RootCa@rti.com Validity Not Before: Jan 28 21:26:58 2021 GMT Not After : Jan 27 21:26:58 2026 GMT Subject: C=US, ST=CA, O=Real Time Innovations, emailAddress=ecdsa01Peer01@rti.com, CN=RTI ECDSA01 (p256) PEER01 Subject Public Key Info: ...
Replace the
subject_name
in the Permissions Document (pmiPermissionsAlice.xml
) with the Subject field of the Identity Certificate (ecdsa01Peer01Cert.pem
).
You may also want to update the
validity
tag with the information from the Identity Certificate. Note that you are not required to have the same validity dates in the Permissions Document and the Identity Certificate (upon creation, your DomainParticipant will independently verify that the Identity Certificate and the grant in your Permissions Document are valid for the current date). If you decide to update thevalidity
tag, pay attention to the date/time format.
This is the result of updating Alice’s grant in pmiPermissionsAlice.xml
:
... <!-- Grants for a specific DomainParticipant will be grouped under this tag --> <grant name="ParticipantAlice"> <!-- 1. The rules below will apply to the DomainParticipant whose identity certificate contains this subject name --> <subject_name>C=US, ST=CA, O=Real Time Innovations, emailAddress=ecdsa01Peer01@rti.com, CN=RTI ECDSA01 (p256) PEER01</subject_name> <!-- 2. Validity dates for this grant --> <validity> <!-- Format is CCYY-MM-DDThh:mm:ss[Z|(+|-)hh:mm] in GMT --> <not_before>2019-11-15T20:24:34</not_before> <not_after>2024-11-13T20:24:34</not_after> </validity> ...
6.3. Signing the Permissions Documents
We will use the provided Permissions CA’s certificate and key to sign the Permissions Documents that we composed. [1]
Run the command below to create the signed Permissions Document
(with PKCS#7 format) named xml/signed/signed_pmiPermissionsAlice.p7s
:
$ openssl smime -sign -in xml/pmiPermissionsAlice.xml -text -out xml/signed/signed_pmiPermissionsAlice.p7s -signer cert/ecdsa01/ca/ecdsa01RootCaCert.pem -inkey cert/ecdsa01/ca/private/ecdsa01RootCaKey.pem
$ openssl smime -sign -in xml/pmiPermissionsAlice.xml -text -out xml/signed/signed_pmiPermissionsAlice.p7s -signer cert/ecdsa01/ca/ecdsa01RootCaCert.pem -inkey cert/ecdsa01/ca/private/ecdsa01RootCaKey.pem
> openssl smime -sign -in xml\pmiPermissionsAlice.xml -text -out xml\signed\signed_pmiPermissionsAlice.p7s -signer cert\ecdsa01\ca\ecdsa01RootCaCert.pem -inkey cert\ecdsa01\ca\private\ecdsa01RootCaKey.pem
6.4. Updating the QoS Profiles in Your Project
Update USER_QOS_PROFILES.xml
so that your
DomainParticipants will load the new Permissions Document:
<qos_profile name="Alice" base_name="BuiltinQosLib::Generic.Security" is_default_qos="true">
<domain_participant_qos>
<property>
<value>
...
<element>
<name>dds.sec.access.permissions</name>
<value>file:./xml/signed/signed_pmiPermissionsAlice.p7s</value>
</element>
...
Here again, the file:
prefix means that the signed Permissions Document
will be loaded from the specified path in the file system. Note that the
path is relative to the working directory from which you run your
application (unless you specify an absolute path). For more details, see
DDS Security Properties for Configuring Access Control in the RTI Security Plugins User’s Manual.
6.5. Checking that the New Permissions Are Applied
To verify that Alice is correctly loading her new permissions, we will do two tests. First, we will check that communication only works in Domain 1, as specified in the Permissions Document. Then we will make sure that Alice is only allowed to publish data.
6.5.1. Communication Only Works in Domain 1
Run your publisher and subscriber as explained in Running the Applications.
Do not provide any arguments to the applications, so that they will try to communicate in Domain 0.
If the publisher has loaded the new permissions, communication should not occur.
Publisher:
$ ./objs/<architecture>/PatientMonitoring_publisher RTI_Security_AccessControl_create_participant:{"DDS:Security:LogTopicV2":{"f":"10","s":"3","t":{"s":"1602772527","n":"484987999"},"h":"rti-10636","i":"0.0.0.0","a":"RTI Secure DDS Application","p":"15137","k":"33554496","x":[{"DDS":[{"domain_id":"<unknown>"},{"guid":"<unknown>"},{"plugin_class":"DDS:Access:Permissions"},{"plugin_method":"RTI_Security_AccessControl_create_participant"}]}],"m":"participant not allowed: no rule found for the participant's domainId; default DENY"}} DDS_DomainParticipantTrustPlugins_getLocalParticipantSecurityState:!security function check_create_participant returned false DDS_DomainParticipant_createI:!get local participant security state DDS_DomainParticipantFactory_create_participant_disabledI:!create participant Exception in run_publisher_application(): Failed to create DomainParticipant
Subscriber:
$ ./objs/<architecture>/PatientMonitoring_subscriber No data after 1 second No data after 1 second No data after 1 second No data after 1 second
Publisher:
$ ./objs/<architecture>/PatientMonitoring_publisher RTI_Security_AccessControl_create_participant:{"DDS:Security:LogTopicV2":{"f":"10","s":"3","t":{"s":"1602772527","n":"484987999"},"h":"rti-10636","i":"0.0.0.0","a":"RTI Secure DDS Application","p":"15137","k":"33554496","x":[{"DDS":[{"domain_id":"<unknown>"},{"guid":"<unknown>"},{"plugin_class":"DDS:Access:Permissions"},{"plugin_method":"RTI_Security_AccessControl_create_participant"}]}],"m":"participant not allowed: no rule found for the participant's domainId; default DENY"}} DDS_DomainParticipantTrustPlugins_getLocalParticipantSecurityState:!security function check_create_participant returned false DDS_DomainParticipant_createI:!get local participant security state DDS_DomainParticipantFactory_create_participant_disabledI:!create participant Exception in run_publisher_application(): Failed to create DomainParticipant
Subscriber:
$ ./objs/<architecture>/PatientMonitoring_subscriber No data after 1 second No data after 1 second No data after 1 second No data after 1 second
Publisher:
> objs\<architecture>\PatientMonitoring_publisher.exe RTI_Security_AccessControl_create_participant:{"DDS:Security:LogTopicV2":{"f":"10","s":"3","t":{"s":"1602772527","n":"484987999"},"h":"rti-10636","i":"0.0.0.0","a":"RTI Secure DDS Application","p":"15137","k":"33554496","x":[{"DDS":[{"domain_id":"<unknown>"},{"guid":"<unknown>"},{"plugin_class":"DDS:Access:Permissions"},{"plugin_method":"RTI_Security_AccessControl_create_participant"}]}],"m":"participant not allowed: no rule found for the participant's domainId; default DENY"}} DDS_DomainParticipantTrustPlugins_getLocalParticipantSecurityState:!security function check_create_participant returned false DDS_DomainParticipant_createI:!get local participant security state DDS_DomainParticipantFactory_create_participant_disabledI:!create participant Exception in run_publisher_application(): Failed to create DomainParticipant
Subscriber:
> objs\<architecture>\PatientMonitoring_subscriber.exe No data after 1 second No data after 1 second No data after 1 second No data after 1 second
Run your publisher and subscriber using Domain 1 (specified with the -d option in the command line).
Now communication should succeed.
Publisher:
$ ./objs/<architecture>/PatientMonitoring_publisher -d 1 Writing PatientMonitoring, count 0 Writing PatientMonitoring, count 1 Writing PatientMonitoring, count 2 Writing PatientMonitoring, count 3
Subscriber:
$ ./objs/<architecture>/PatientMonitoring_subscriber -d 1 No data after 1 second Received data patient_condition: "" No data after 1 second Received data patient_condition: ""
Publisher:
$ ./objs/<architecture>/PatientMonitoring_publisher -d 1 Writing PatientMonitoring, count 0 Writing PatientMonitoring, count 1 Writing PatientMonitoring, count 2 Writing PatientMonitoring, count 3
Subscriber:
$ ./objs/<architecture>/PatientMonitoring_subscriber -d 1 No data after 1 second Received data patient_condition: "" No data after 1 second Received data patient_condition: ""
Publisher:
> objs\<architecture>\PatientMonitoring_publisher.exe -d 1 Writing PatientMonitoring, count 0 Writing PatientMonitoring, count 1 Writing PatientMonitoring, count 2 Writing PatientMonitoring, count 3
Subscriber:
> objs\<architecture>\PatientMonitoring_subscriber.exe -d 1 No data after 1 second Received data patient_condition: "" No data after 1 second Received data patient_condition: ""
6.5.2. Alice Is Only Allowed to Publish Data
We will now verify that a subscriber application with Alice’s permissions is not able to receive data. This means that even if Alice becomes compromised, she can’t listen for data she is not authorized to access.
Temporarily change your subscriber’s QoS profile to load the same security artifacts as Alice, including her identity and permissions:
<qos_profile name="Bob" base_name="Alice"> </qos_profile>
This means we are now configuring Bob with Alice’s permissions.
Run your publisher and subscriber using Domain 1.
Communication should not occur:
Publisher:
$ ./objs/<architecture>/PatientMonitoring_publisher -d 1 Writing PatientMonitoring, count 0 Writing PatientMonitoring, count 1 Writing PatientMonitoring, count 2 Writing PatientMonitoring, count 3
Subscriber:
$ ./objs/<architecture>/PatientMonitoring_subscriber -d 1 RTI_Security_AccessControl_check_create_datareader:{"DDS:Security:LogTopicV2":{"f":"10","s":"3","t":{"s":"1603104751","n":"420884999"},"h":"rti-10636","i":"0.0.0.0","a":"RTI Secure DDS Application","p":"29279","k":"33554496","x":[{"DDS":[{"domain_id":"1"},{"guid":"B3339B76.D20F2657.11CAF180.000001C1"},{"plugin_class":"DDS:Access:Permissions"},{"plugin_method":"RTI_Security_AccessControl_check_create_datareader"}]}],"m":"endpoint not allowed: no rule found; default DENY"}} DDS_DomainParticipantTrustPlugins_getLocalDataReaderSecurityState:!security function check_create_datareader DDS_DataReader_create_presentation_readerI:ERROR: Failed to get local datareader security state DDS_DataReader_createI:!create reader DDS_Subscriber_create_datareader_disabledI:!create reader DDSDataReader_impl::create_disabledI:!create reader DDSDataReader_impl::createI:!create reader create_datareader error
Publisher:
$ ./objs/<architecture>/PatientMonitoring_publisher -d 1 Writing PatientMonitoring, count 0 Writing PatientMonitoring, count 1 Writing PatientMonitoring, count 2 Writing PatientMonitoring, count 3
Subscriber:
$ ./objs/<architecture>/PatientMonitoring_subscriber -d 1 RTI_Security_AccessControl_check_create_datareader:{"DDS:Security:LogTopicV2":{"f":"10","s":"3","t":{"s":"1603104751","n":"420884999"},"h":"rti-10636","i":"0.0.0.0","a":"RTI Secure DDS Application","p":"29279","k":"33554496","x":[{"DDS":[{"domain_id":"1"},{"guid":"B3339B76.D20F2657.11CAF180.000001C1"},{"plugin_class":"DDS:Access:Permissions"},{"plugin_method":"RTI_Security_AccessControl_check_create_datareader"}]}],"m":"endpoint not allowed: no rule found; default DENY"}} DDS_DomainParticipantTrustPlugins_getLocalDataReaderSecurityState:!security function check_create_datareader DDS_DataReader_create_presentation_readerI:ERROR: Failed to get local datareader security state DDS_DataReader_createI:!create reader DDS_Subscriber_create_datareader_disabledI:!create reader DDSDataReader_impl::create_disabledI:!create reader DDSDataReader_impl::createI:!create reader create_datareader error
Publisher:
> objs\<architecture>\PatientMonitoring_publisher.exe -d 1 Writing PatientMonitoring, count 0 Writing PatientMonitoring, count 1 Writing PatientMonitoring, count 2 Writing PatientMonitoring, count 3
Subscriber:
> objs\<architecture>\PatientMonitoring_subscriber.exe -d 1 RTI_Security_AccessControl_check_create_datareader:{"DDS:Security:LogTopicV2":{"f":"10","s":"3","t":{"s":"1603104751","n":"420884999"},"h":"rti-10636","i":"0.0.0.0","a":"RTI Secure DDS Application","p":"29279","k":"33554496","x":[{"DDS":[{"domain_id":"1"},{"guid":"B3339B76.D20F2657.11CAF180.000001C1"},{"plugin_class":"DDS:Access:Permissions"},{"plugin_method":"RTI_Security_AccessControl_check_create_datareader"}]}],"m":"endpoint not allowed: no rule found; default DENY"}} DDS_DomainParticipantTrustPlugins_getLocalDataReaderSecurityState:!security function check_create_datareader DDS_DataReader_create_presentation_readerI:ERROR: Failed to get local datareader security state DDS_DataReader_createI:!create reader DDS_Subscriber_create_datareader_disabledI:!create reader DDSDataReader_impl::create_disabledI:!create reader DDSDataReader_impl::createI:!create reader create_datareader error
This test requires your Governance Document to set
enable_read_access_control
to TRUE
(see Further Exercises in Hands-On 2);
otherwise, endpoint-level permissions related to DataReaders will not be checked and
Bob will be able to receive the data.
When adding new rules to your Governance Document, keep in mind (as we mentioned
in Adding a Topic Rule for the PatientMonitoring Topic) that the Governance Document
is processed from top to bottom, and that only the first matching rule is
applied.
Also, make sure the Permissions CA signs the modified Governance Document (see
Signing the Governance Document); otherwise the changes will not
be applied.
This exercise illustrates what happens if an application tries to do something it does not have permissions to do, by temporarily giving Bob (the subscriber) the wrong permissions.
Tip
Make sure you revert the changes to your subscriber’s QoS profile before continuing the exercises.
6.6. Further Exercises
At this point, you have defined the permissions that will be applied to your publisher application, restricting it to publish PatientMonitoring data. However, we have not modified your subscriber’s permissions.
6.6.1. Define Different Permissions for Each Application in Your System
To minimize the damage in case one of your secure applications is compromised, a DomainParticipant should only have permissions to perform the actions that are necessary for its legitimate purpose. [2]
Define the permissions for Bob in a file called
pmiPermissionsBob.xml
. This Permissions Document should contain a single grant named ParticipantBob, defining permissions to subscribe to any Topic containing the stringPatient
— only in Domain 1.You may want to use the following
allow_rule
as a reference:<allow_rule> <domains> <id>1</id> </domains> <subscribe> <topics> <topic>*Patient*</topic> </topics> </subscribe> </allow_rule>
ParticipantBob should be denied any other actions.
Bind Bob’s permissions to your subscriber application (see Binding the Permissions Document to Your DomainParticipants).
If you completed the exercises in Hands-On 1: Securing Connext DDS Applications), Bob’s identity certificate should be
cert/ecdsa01/identities/ecdsa01Peer02Cert.pem
. You will have to bind Bob’s permissions to the subject of this certificate.
Make sure the Permissions CA signs the new Permissions Document and modify Bob’s QoS profile to load it.
After applying this configuration, your subscriber application, Bob, will only be allowed to subscribe to any Topic containing the string
Patient
in Domain 1, while your publisher application, Alice, will only be allowed to publish Topic “Example PatientMonitoring” in Domain 1.
This is known as the Principle of Least Privilege. For further information, see Applying DDS Protection in the Security Plugins User’s Manual.
In the evaluation or LM version (with
“eval
” or “lm
” in the bundle name), OpenSSL is installed automatically
when you install the Connext host bundle. After installation, OpenSSL will
be in <installdir>/third_party/openssl-<version>
.
6.7. Troubleshooting
When I run the publisher/subscriber, I get this error:
RTI_Security_PermissionsCfgFileParser_getGrantFromCertificate:XML file doesn't contain a grant for subject name
Make sure your DomainParticipants load the correct Identity Certificate and Permissions Document.
Make sure the subject in your Permissions Document’s grant matches the information in your participant’s identity certificate (see Binding the Permissions Document to Your DomainParticipants). Pay attention to the format.
When I run the publisher/subscriber, I get this error:
RTI_Security_AccessControl_create_participant:participant not allowed: no rule found for the participant's domainId; default DENY
Make sure you run your applications in the right Domain, by specifying the Domain ID with the -d option in the command line. In this example, we are using Domain 1.
The subscriber is able to receive data, even if it does not have permissions to subscribe.
Make sure your Governance Document sets
enable_read_access_control
TRUE
. Otherwise, permissions will not be enforced on locally created or remotely discovered DataReaders.You may be using the Governance Document from Composing a Governance Document with the Security Requirements, with a specific topic rule appearing after the wildcard rule that applies to all topics. If your topic rule is more restrictive than the wildcard rule, it must be located first. The Governance Document is processed from top to bottom, and the first matching rule is applied.
When I run the publisher/subscriber, I get an error I do not understand.
See Logging Messages in the RTI Security Plugins User’s Manual.