7. Security Events and Logging

The Security Plugins implement a builtin Logging Plugin to notify you of security events. A security event refers to any significant occurrence within the Connext system that pertains to security mechanisms or concerns. These events can include actions or incidents related to authentication, access control, and cryptography within the Connext environment.

Security events are important for monitoring and ensuring the integrity, confidentiality, and availability of the data being communicated among DomainParticipants in a Connext system. They can be logged and supervised to detect and respond to potential security threats or breaches, such as attempts by unauthorized entities to access or modify data, successful or failed authentication attempts, creation of cryptographic keys, or registration of endpoints with security attributes.

Not all the log messages generated by the Security Plugins correspond to security events (for example, memory allocation failures, DDS-related errors, etc). These messages are not logged using the Logging Plugin, they use the Connext DDS Builtin Logging System instead.

The Logging Plugin supports the following logging methods (non-exclusive):

  • Using Connext’s own builtin logging system to send security messages.

  • Distributing security log messages over DDS using the Builtin Secure Logging Topic.

  • Distributing and storing security log messages in a logging aggregator backend (such as Grafana® Loki) using RTI Observability Framework. Refer to the RTI Connext Observability Framework User’s Manual for more information.

By default, log messages are processed by the Connext DDS Builtin Logging System. You can configure which logging methods to use by setting the logging.mode_mask property. You can also adjust the verbosity level of the log messages with logging.verbosity. See Table 7.2.

If you distribute log messages over DDS using the Builtin Secure Logging Topic, the messages’ log levels are used as the severity values of the BuiltinLoggingTypeV2. If you are using the Connext DDS Builtin Logging System, the messages’ log levels are mapped to the values shown in Table 7.1. See Configuring Connext Logging in the RTI Connext DDS Core Libraries User’s Manual for more information on the Connext DDS Builtin Logging System.

Attention

The verbosity of security-related messages is per application. The last DomainParticipant explicitly setting the logging.verbosity property (set by you, in the QoS settings) will apply that setting to all the DomainParticipants within the application and all security-related messages logged from the Connext libraries. This behavior is true independent of the value of the logging.mode_mask property.

If not explicitly set, the verbosity will be left unchanged. Therefore, if no DomainParticipant has configured the verbosity, it will be left to the default (ERROR).

See the following sections for more information about the different logging methods [1].

7.1. Connext DDS Builtin Logging System

When security logging is configured to be written to Connext’s own builtin logging system (also known as NDDS_Config_Logger), you will see messages that use a JSON format and look something like the following:

[2020-09-11 16:17:06.477203] [CREATE DP] RTI_Security_CertHelper_loadPrivateKey:{"DDS:Security:LogTopicV2":{"f":"10","s":"3","t":{"s":"1599841026","n":"477193999"},"h":"rti-10636","i":"0.0.0.0","a":"RTI Secure DDS Application","p":"2788","k":"33554496","x":[{"DDS":[{"domain_id":"<unknown>"},{"guid":"<unknown>"},{"plugin_class":"RTI:Common"},{"plugin_method":"RTI_Security_CertHelper_loadPrivateKey"}]}],"m":"private_key is not encrypted, yet password is supplied. Aborting participant creation due to inconsistent configuration."}}

[2020-09-11 16:17:06.477233] [CREATE DP] RTI_Security_AuthenticationData_create:{"DDS:Security:LogTopicV2":{"f":"10","s":"0","t":{"s":"1599841026","n":"477228999"},"h":"rti-10636","i":"0.0.0.0","a":"RTI Secure DDS Application","p":"2788","k":"33554496","x":[{"DDS":[{"domain_id":"<unknown>"},{"guid":"<unknown>"},{"plugin_class":"DDS:Auth:PKI-DH"},{"plugin_method":"RTI_Security_AuthenticationData_create"}]}],"m":"failed to read authentication.private_key_file"}}

The mapping from the above format to the fields in the DDS:Security:LogTopicV2 type (see Builtin Secure Logging Topic) is as follows:

  • "f": facility

  • "s": severity

  • "t": timestamp (within this field "s" refers to seconds, and "n" to nanoseconds)

  • "h": hostname

  • "i": hostip

  • "a": appname

  • "p": procid

  • "k": msgid

  • "m": message

  • "x": structured_data

    • The structured data will have at least the DDS key containing an array of key-value pairs. The Security Plugins also populate the guid, domain_id, plugin_class, and plugin_method key-value pairs. You can find more information about these fields in the OMG DDS Security specification. Messages from the Security Plugins can have these possible values for the plugin_class field: DDS:Auth:PKI-DH (Builtin) and DDS:Auth:PSK (Lightweight Builtin) for the Authentication Plugin, DDS:Access:Permissions (Builtin) and DDS:Access:PSK (Lightweight Builtin) for the Access Control Plugin, DDS:Crypto:AES-GCM-GMAC (Builtin) and DDS:Crypto:PSK (Lightweight Builtin) for the Cryptography Plugin, DDS:Logging:DDS_LogTopic for the Logging Plugin (both Builtin Security Plugins and Lightweight Builtin Security Plugins) and RTI:Common for error messages logged by functionality that is not tied to one of the builtin plugins defined in the Security specification. The RTI:Auth, RTI:Access, RTI:Crypto, and RTI:Logging plugin class names are also used for Security Events logged by the core libraries.

The messages may be preceded by additional information, such as timestamps or GUIDs, depending on the Connext DDS Builtin Logging System format configuration and the message NDDS_Config_LogLevel. (See Format of Logged Messages, in the RTI Connext DDS Core Libraries User’s Manual.)

By default, the Connext DDS Builtin Logging System writes to the standard output, but you can configure it to use a log file or an output device such as a custom logging device or the Distributed Logger. (See Configuring Connext Logging in the RTI Connext DDS Core Libraries User’s Manual and RTI Distributed Logger in the Core Libraries User’s Manual.)

Note

When using RTI Observability Framework, the Grafana dashboards will display the plugin class names for every security event. The dashboards also display a category field that represents a more friendly name for these standard plugin class names. For more information, see the Observability User Manual.

7.1.1. Logging Security Events through the Connext DDS Builtin Logging System

To make the security log go through the Connext DDS Builtin Logging System, enable the BUILTIN flag with the logging.mode_mask property within the domain_participant_qos (this is the default configuration, see Configuring QoS with XML, in the RTI Connext DDS Core Libraries User’s Manual):

<domain_participant_qos>
    <property>
        <value>
            <element>
                <name>com.rti.serv.secure.logging.mode_mask</name>
                <value>BUILTIN</value>
            </element>
        </value>
    </property>
</domain_participant_qos>

The granularity of the log messages depends on the verbosity level set for the security log. You can set the verbosity level as follows, DEBUG being the highest verbosity level (see Properties for Configuring Security Events and Logging):

<domain_participant_qos>
    <property>
        <value>
            <element>
                <name>com.rti.serv.secure.logging.verbosity</name>
                <value>DEBUG</value>
            </element>
        </value>
    </property>
</domain_participant_qos>

7.2. Distributed Over DDS

When the messages are distributed over DDS, the information will be logged using the BuiltinLoggingTypeV2, following the OMG DDS Security specification. For example, here is how the messages look in RTI DDS Spy (using the -printSample option) when you use logging distribution over DDS:

1543498637.929123  d +M  DCB9C740    DDS:Security:LogTopicV2        DDSSecurity::BuiltinLoggingTypeV2
facility: 10
severity: DEBUG_LEVEL
timestamp:
   sec: 1543498637
   nanosec: 928903998
hostname: "localhost"
hostip: "0.0.0.0"
appname: "RTI Secure DDS Application"
procid: "9654"
msgid: "33554496"
message: "received submessage from an endpoint that discovered me but that I haven't discovered yet; dropping submessage hoping it will be repaired. It will not be repaired if the endpoint did not properly share its MasterKeyId in its CryptoToken."
structured_data:
   [0]:
      key: "DDS"
      pairs:
         [0]:
            name: "guid"
            value: "DCB9C740.7ECF85EB.42AA8349.000001C1"
         [1]:
            name: "domain_id"
            value: "25"
         [2]:
            name: "plugin_method"
            value: "RTI_Security_Cryptography_preprocess_secure_submsg"
         [3]:
            name: "plugin_class"
            value: "DDS:Crypto:AES-GCM-GMAC"

7.2.1. Configuring the Logging Distribution

To distribute the log messages over DDS, enable the SECURITY_TOPIC flag with the logging.mode_mask [2] property within the domain_participant_qos (see Configuring QoS with XML, in the RTI Connext DDS Core Libraries User’s Manual):

<domain_participant_qos>
    <property>
        <value>
            <element>
                <name>com.rti.serv.secure.logging.mode_mask</name>
                <value>SECURITY_TOPIC</value>
            </element>
        </value>
    </property>
</domain_participant_qos>

The granularity of the log messages depends on the verbosity level set for the security log. You can set the verbosity level as follows, DEBUG being the highest verbosity level (see Properties for Configuring Security Events and Logging):

<domain_participant_qos>
    <property>
        <value>
            <element>
                <name>com.rti.serv.secure.logging.verbosity</name>
                <value>DEBUG</value>
            </element>
        </value>
    </property>
</domain_participant_qos>

For more details on configuring the Logging Distribution over DDS, see Table 7.2.

7.2.2. Builtin Secure Logging Topic

When you distribute the security logging information over DDS, your DomainParticipant will publish this information to the Builtin Secure Logging Topic (DDS:Security:LogTopicV2), as defined in the OMG DDS Security specification. DDS samples in this topic will have the type BuiltinLoggingTypeV2 (DDSSecurity::BuiltinLoggingTypeV2).

This type includes information about the logging level, the DomainParticipant producing the message, a timestamp, etc. You can find the IDL description of the BuiltinLoggingTypeV2 in <NDDSHOME>/resource/idl/builtin_logging_type.idl. (See Paths Mentioned in Documentation.)

7.2.3. Implementation Notes

7.2.3.1. Publication of the Builtin Secure Logging Topic

The DDS:Security:LogTopicV2 (described in Subscribing to the Builtin Logging Topic) is published by the same DomainParticipant that uses the Security Plugins to communicate securely. Therefore, this topic is published in a Secure Domain, and the Governance and Permissions Documents that apply to that DomainParticipant also apply to this log topic. For this reason, the Permissions Document must allow the DDS:Security:LogTopicV2 to be published.

By default, the DDS:Security:LogTopicV2 is protected using Submessage Protection set to SIGN [3] (see Builtin Secure Logging Topic).

Attention

There is no option to use a separate “Builtin Logging” DomainParticipant and to share it among multiple DomainParticipants.

7.2.3.2. Custom QoS Profile for the Builtin Secure Logging Topic

The Security Plugins publish log messages using the QoS Profile specified by the property logging.security_topic.profile. If this property is not set, the Security Plugins will use the BuiltinQosLib::Generic.KeepLastReliable.TransientLocal profile by default, and the Security Plugins will set history.depth to 64 and publish_mode.kind to DDS_ASYNCHRONOUS_PUBLISH_MODE_QOS.

If you specify a custom profile in the property logging.security_topic.profile, only Publisher, Topic, and DataWriter QoS will be used from the specified profile. This is because the DataWriter that distributes the log belongs to the same DomainParticipant as the one instantiating the Security Plugins. As a result, you can use the custom profile for the logger if, for example, you want to change the logger’s reliability, but you cannot use it to change the logger’s identity (Private Key and Identity Certificate).

7.3. Advanced Logging Concepts

7.3.1. Interface Between the Logging Plugin and the Connext DDS Builtin Logging System

Log messages generated by the Logging Plugin in the Security Plugins and those generated by the Connext DDS Builtin Logging System (which is the default method) have a different structure. For example, the Logging Plugin includes information about the process ID (procid) and the host (hostname, hostip) as fields of the DDSSecurity::BuiltinLoggingTypeV2 type. To provide this information when using the Connext DDS Builtin Logging System, security messages use a JSON format, as specified in Connext DDS Builtin Logging System.

The log level values used by these logging systems are also different. Table 7.1 shows the mapping between Logging Plugin log values and the Connext DDS Builtin Logging System log values. For example, messages marked as EMERGENCY, ALERT, CRITICAL, or ERROR in the Security Plugins are translated to ERROR when using the Connext DDS Builtin Logging System.

Table 7.1 Mapping Between Logging Plugin and Connext DDS Builtin Logging System

Logging Plugin (Security Plugins) Log Level Values [4]

Connext DDS Builtin Logging System Log Level Values [5]

DDS_LOGGING_EMERGENCY_LEVEL

NDDS_CONFIG_LOG_LEVEL_FATAL_ERROR

DDS_LOGGING_ALERT_LEVEL
DDS_LOGGING_CRITICAL_LEVEL
DDS_LOGGING_ERROR_LEVEL

NDDS_CONFIG_LOG_LEVEL_ERROR

DDS_LOGGING_WARNING_LEVEL

NDDS_CONFIG_LOG_LEVEL_WARNING

DDS_LOGGING_NOTICE_LEVEL
DDS_LOGGING_INFORMATIONAL_LEVEL

NDDS_CONFIG_LOG_LEVEL_STATUS_LOCAL

DDS_LOGGING_DEBUG_LEVEL

NDDS_CONFIG_LOG_LEVEL_DEBUG

7.3.2. Subscribing to the Builtin Logging Topic

To get the security logging information that is being distributed over DDS, you will need to create an application that subscribes to the Builtin Secure Logging Topic:

  • Topic name: DDS:Security:LogTopicV2

  • Type name: DDSSecurity::BuiltinLoggingTypeV2

Note

Since the log messages are distributed in a secured domain, your subscriber needs an identity (Private Key and Identity Certificate). In addition, it needs to have permission to subscribe to topic DDS:Security:LogTopicV2; this permission needs to be included in its Permissions Document.

You can subscribe to the Builtin Secure Logging Topic with RTI DDS Spy using the -printSample option.

rtiddsspy -printSample -domainId <domainId> -qosProfile <lib::prof>

Alternatively, to create a custom subscriber, you can start from the IDL containing the definition of the DDSSecurity::BuiltinLoggingTypeV2, which can be found here: <NDDSHOME>/resource/idl/builtin_logging_type.idl. (See Paths Mentioned in Documentation.)

With the IDL, you can run rtiddsgen to generate type support code and example code. For example, the following command will generate all the files you need to access the DDS:Security:LogTopicV2 topic from your Connext application:

rtiddsgen -language C -example x64Linux3gcc4.8.2 -unboundedSupport builtin_logging_type.idl

Important

You need to use the command-line option -unboundedSupport because DDSSecurity::BuiltinLoggingTypeV2 contains strings without a specified limit. By default, rtiddsgen will limit unbounded strings to 255 characters, unless you specify the -unboundedSupport option. Without this option, the type support code will not be compatible with the type used by the Security Plugins, and you won’t be able to receive any messages. For more information about the use of unbounded support with builtin types, see Managing Memory for Builtin Types in the RTI Connext DDS Core Libraries User’s Manual.

7.4. Properties for Configuring Security Events and Logging

The following properties in the DomainParticipant property configure Logging:

Table 7.2 Security Plugins Plugins Properties for Configuring Logging

Property Name (prefix with com.rti.serv.secure.) [6]

Property Value Description

logging.log_level (<< deprecated >>)

Optional

The logging verbosity level.

This setting applies to all methods of security logging (the Connext DDS Builtin Logging System and Distributed Over DDS) and all types of messages (security and non-security events). All log messages at and below the logging.log_level setting will be logged.

This property can take any of the following values:

  • 0: emergency

  • 1: alert

  • 2: critical

  • 3 (default): error

  • 4: warning

  • 5: notice

  • 6: informational

  • 7: debug

Notes:

  • This property is (<< deprecated >>) and may stop working in a future release. Use logging.verbosity instead.

  • This property is incompatible with logging.verbosity (i.e., if they are used simultaneously, participant creation will fail).

Integer: [0-7]

Default: 3 (error)

logging.verbosity

Optional

The logging verbosity level.

This setting applies to all methods of security logging (the Connext DDS Builtin Logging System and Distributed Over DDS) and all types of messages (security and non-security events). All log messages at and below the verbosity level will be logged.

This property can take any of the following values (case sensitive):

  • SILENT (least verbose)

  • EMERGENCY

  • ALERT

  • CRITICAL

  • ERROR (default)

  • WARNING

  • NOTICE

  • INFORMATIONAL

  • DEBUG (most verbose)

Notes:

  • This property is incompatible with logging.log_level (i.e. if they are used simultaneously, participant creation will fail).

  • Setting this property will also set the SECURITY category verbosity to the same level. Additionally, because all messages logged by the Security Plugins fall under the SECURITY category, changing the verbosity for the SECURITY category will also set the Security Plugins verbosity to the same value. See Configuring Connext Logging in the RTI Connext DDS Core Libraries User’s Manual for more information about Message Logging Categories [7].

  • The verbosity level for security events always matches the level configured through this property or through the SECURITY category. The only exception in which these two levels may differ is when an RTI Observability Framework remote administration command modifies the collection verbosity for the SECURITY_EVENT facility.

Enum: SILENT, EMERGENCY, ALERT, CRITICAL, ERROR, WARNING, NOTICE, INFORMATIONAL, DEBUG

Default: ERROR

logging.mode_mask

Optional

Controls which logging methods are used to process the log messages produced by the Logging Plugin. You can specify one of these possible values:

  • BUILTIN

  • SECURITY_TOPIC

Or any combination of the above, separating each element by |. For example: BUILTIN | SECURITY_TOPIC

When BUILTIN is enabled, the Logging Plugin will use the Connext DDS Builtin Logging System. When SECURITY_TOPIC is enabled, the Logging Plugin will create a Publisher and DataWriter within the same DomainParticipant that is setting this property. There is no option to use a separate DomainParticipant or to share a DataWriter among multiple DomainParticipants. (See Subscribing to the Builtin Logging Topic.)

Mask: BUILTIN | SECURITY_TOPIC

Default: BUILTIN

Table 7.3 Additional Security Plugins Properties for Configuring Logging Distributed Over DDS [8]

Property Name (prefix with com.rti.serv.secure.) [6]

Property Value Description

logging.security_topic.profile

Optional

QoS Library and QoS Profile used to create logging-related entities (Publisher, Topic and DataWriter). Must be a string of the format "QosLibraryName::QosProfileName". If the profile does not specify the fast_pool.pool_buffer_max_size in the dds.data_writer.history.memory_manager property, its value will be set to 512.

String.

Default: "BuiltinQosLib::Generic.KeepLastReliable.TransientLocal", with history.depth = 64 and publish_mode.kind = DDS_ASYNCHRONOUS_PUBLISH_MODE_QOS

logging.security_topic.queue.size

Optional

Size of the logging thread queue, in bytes.

Integer.

Default: 50688

logging.security_topic.queue.message_count_max

Optional

Maximum number of log messages in the logging queue.

Integer.

Default: 64

logging.security_topic.queue.message_size_max

Optional

Maximum serialized size of a log message in the logging queue.

Integer.

Default: 792

logging.security_topic.thread.message_threshold

Optional

Number of bytes to preallocate for the logging message string in the logging thread, beyond which dynamic allocation will occur.

Integer.

Default: 256

logging.security_topic.thread.plugin_method_threshold

Optional

Number of bytes to preallocate for the plugin method string in the logging thread, beyond which dynamic allocation will occur.

Integer.

Default: 256

logging.security_topic.thread.plugin_class_threshold

Optional

Number of bytes to preallocate for the plugin class string in the logging thread, beyond which dynamic allocation will occur.

Integer.

Default: 256

access_control.use_530_logging_protection

Optional

How to set the value of metadata_protection_kind for the Builtin Secure Logging Topic.

If TRUE: the value will be NONE, which is consistent with Connext 5.3.0 behavior.

If FALSE: the value will be SIGN, which is consistent with the behavior of the OMG DDS Security specification.

Boolean.

Default: FALSE

7.5. Logging Messages

Table 7.4 lists security-related events and the log messages they generate.

Table 7.4 Log Messages

Event

Log Level

Message

Failed to validate local Permissions Document.

ALERT

failed to validate local permissions

Failed to validate remote Permissions Document.

ALERT

failed to validate remote permissions

Topic/DataWriter/DataReader not allowed.

ALERT

topic not allowed: cannot be published or subscribed /
datawriter not allowed / datareader not allowed

Failed to allocate memory

CRITICAL

insufficient memory

Received invalid X509 certificate, from either remote or local participant

ERROR

failed to decode certificate

Couldn’t verify certificate’s signature against neither the certificate of the Identity Certificate Authority nor any alternative CAs

ERROR

failed to verify certificate

Certificate appears in Certificate Revocation List

ERROR [9]

certificate revoked

Upon receiving HandshakeReplyMessageToken or HandshakeFinalMessageToken, couldn’t verify challenge’s signature against peer’s certificate. Peer likely has mismatched private and public keys, so it’s an imposter.

ERROR

failed to verify challenge signature

Couldn’t verify permissions or governance file signature against either the certificate of the Permissions Authority or any alternative permissions authorities

ERROR

Document signature verification failed. Make sure document was signed by the right permissions authority.

Received signed permissions document that is not an XML document

ERROR

received invalid signed permissions document

Received signed governance document that is not an XML document

ERROR

received invalid signed governance document

Couldn’t parse the Permissions Document for some reason, such as duplicate grants for the same subject name or no grant for the intended subject name

ERROR

failed to parse Permissions Document

Couldn’t parse the governance document for some reason

ERROR

failed to parse governance file

Denied participant because there is a deny rule explicitly prohibiting the participant

ERROR

participant not allowed: deny rule found

Denied participant because there is no rule for the participant’s domain ID, and the default is to deny

ERROR

participant not allowed: no rule found for the participant's domainId; default DENY

Denied writer or reader because there is a deny rule explicitly prohibiting the writer or reader

ERROR

endpoint not allowed: deny rule found

Denied writer or reader because there is no rule for the writer or reader, and the default is to deny

ERROR

endpoint not allowed: no rule found; default DENY

Received authenticated content that has been tampered with, i.e. EVP_DecryptFinal_ex failed because the GCM or GMAC tag verification failed

ERROR

DecryptFinal failed. Possible GCM authentication failure.

allow_unauthenticated_participants = FALSE, and discovered remote participant that is unauthenticable, i.e. has not enabled security

WARNING

unauthenticated remote participant [participant ID] denied

allow_unauthenticated_participants = TRUE, and discovered remote participant that is either unauthenticable or fails authentication

WARNING

allowing unauthenticated participant [participant ID]

Writing a log message over the LogTopicV2 fails due to insufficient logging queue size

STATUS_LOCAL [9]

Failed to write log message of size = [message size] because the logging queue is full. Try to increase logging.security_topic.queue.message_count_max, which is currently [message_count_max].

Another participant, which is not using is_rtps_axk_protected = true or is not using security at all, has sent this one an unprotected RTPS message that is not a participant announcement, handshake message, or key exchange message. This participant is using is_rtps_axk_protected = true, so it drops the message.

Or: Network traffic corruption after key exchange.

Or: Misbehaving remote participant after key exchange.

STATUS_REMOTE [9]

MIGInterpreter_parse:received unencoded rtps message. Unacceptable due to is_rtps_axk_protected = true

RTI_Security_Authentication_process_handshake failed (see next row).

STATUS_REMOTE [9]

DDS_DomainParticipantTrustPlugins_forwardProcessHandshake:!security function process_handshake returned VALIDATION_FAILED

Another participant has lost liveliness with this one before authentication was completed and is trying to re-authenticate itself (see Re-Authentication). A new authentication should restore communication once the ongoing authentication times out.

Or: Network traffic corruption during authentication.

Or: Misbehaving remote participant during authentication.

NOTICE

RTI_Security_Authentication_process_handshake:received unexpected handshake message, probably from a participant that lost liveliness with this one before ongoing authentication completed. Once current authentication times out, communication should be restored.

Received submessage encrypted with a key whose MasterKeyId hasn’t yet been exchanged via CryptoToken

DEBUG

received submessage from an endpoint that discovered me but that I haven't discovered yet; dropping submessage hoping it will be repaired. It will not be repaired if the endpoint did not properly share its MasterKeyId in its CryptoToken

Parsed publish/subscribe rule in Permissions Document that does not apply to the writer/reader because no topic expressions match the writer/reader’s topic

DEBUG

This publish/subscribe rule doesn't apply because none of the rule's topic expressions match the endpoint's topic name of [topic name]

Parsed publish/subscribe rule in Permissions Document that does not apply to the writer/reader because even though there’s a matching topic expression, there are no matching partition expressions

DEBUG

This publish/subscribe rule doesn't apply because none of the rule's partition expressions match with any of the endpoint's partitions

Parsed publish/subscribe <allow_rule> in Permissions Document that does not apply to the writer/reader because even though there’s a matching topicexpression, the partition expressions in the QoS are not a subset of the ones in the <allow_rule>

DEBUG

This publish/subscribe rule doesn't apply because endpoint's partitions are not a subset of the rule's partition expressions