DDS Security Guide

AstuteDDS provides comprehensive DDS Security support with authentication, access control, encryption, and data tagging capabilities. This guide covers how to enable and use DDS Security plugins.

What is DDS Security?

DDS Security (OMG DDS Security 1.1/1.2) provides a standardized framework for securing DDS systems:

  • Authentication (AuthPlugin): Verifies participant identity using PKI certificates
  • Access Control (AccessControl): Controls who can read/write specific topics
  • Encryption (CryptoPlugin): Encrypts payloads using AES-GCM
  • Logging: Records security events
  • Data Tagging: Assigns classification tags to data streams

Enabling DDS Security

Build with Security Support

cd astutedds-cxx
mkdir build && cd build
cmake .. -DASTUTEDDS_ENABLE_SECURITY=ON -DASTUTEDDS_BUILD_EXAMPLES=ON
cmake --build .

Available Plugins

1. PKI Authentication Plugin

Authenticates participants using X.509 certificates and shared secrets.

#include <astutedds/security/security.hpp>

namespace SEC = astutedds::security;

// Create authentication plugin
auto auth = SEC::create_pki_authentication_plugin();

// Prepare credentials
SEC::CertificateCredentials creds;
creds.identity_certificate = "-----BEGIN CERTIFICATE-----\n...";
creds.identity_ca = "-----BEGIN CERTIFICATE-----\n...";
creds.private_key = "-----BEGIN RSA PRIVATE KEY-----\n...";

// Validate local identity
SEC::SecurityException ex;
auto local_identity = auth->validate_local_identity(creds, 0, SEC::PropertySeq{}, ex);

if (ex.is_ok()) {
    std::cout << "Authentication succeeded" << std::endl;
}

2. XML Access Control Plugin

Controls which participants can read/write specific topics.

// Create access control plugin
auto access = SEC::create_xml_access_control_plugin();

// Validate permissions
auto permissions = access->validate_local_permissions(
    *auth,
    local_identity,
    0,
    SEC::PropertySeq{},
    ex
);

// Check if allowed to create writer on "SensorTopic"
if (access->check_create_datawriter(permissions, 0, "SensorTopic", ex)) {
    std::cout << "Write permission granted" << std::endl;
}

3. AES-GCM Crypto Plugin

Encrypts DDS payloads using AES-GCM encryption.

// Create crypto plugin
auto crypto = SEC::create_aes_gcm_crypto_plugin();

// Register participant
SEC::ParticipantSecurityAttributes part_attrs;
part_attrs.is_rtps_protected = true;

auto participant_crypto = crypto->register_local_participant(
    local_identity,
    permissions,
    SEC::PropertySeq{},
    part_attrs,
    ex
);

// Register writer for encryption
SEC::EndpointSecurityAttributes endpoint_attrs;
endpoint_attrs.is_payload_protected = true;

auto writer_crypto = crypto->register_local_datawriter(
    participant_crypto,
    SEC::PropertySeq{},
    endpoint_attrs,
    ex
);

// Encrypt payload before sending
std::vector<uint8_t> plain = {0x48, 0x65, 0x6c, 0x6c, 0x6f};  // "Hello"
std::vector<uint8_t> encrypted;

if (crypto->encode_serialized_payload(encrypted, plain, writer_crypto, ex)) {
    // Send encrypted payload via DDS
    writer->write(encrypted);
}

4. Data Tagging Plugin

Assigns and matches classification tags on data.

// Create data tagging plugin
auto tagging = SEC::create_data_tagging_plugin();

// Set writer tags
SEC::DataTagSeq writer_tags = {
    {"classification", "SECRET"},
    {"compartment", "ALPHA"}
};

tagging->set_datawriter_tags(writer_handle, writer_tags, ex);

// Check reader tags compatibility
SEC::DataTagSeq reader_tags = {{"classification", "SECRET"}};

if (tagging->match_tags(writer_tags, reader_tags, ex)) {
    std::cout << "Tags compatible, data can flow" << std::endl;
}

5. File Logging Plugin

Records security events to disk.

// Create logging plugin
auto logging = SEC::create_file_logging_plugin("/var/log/astutedds-security.log");

// Configure log level
logging->set_log_level(SEC::SecurityLogLevel::DEBUG, ex);

// Security events are automatically logged
logging->log_authentication_event(
    SEC::SecurityLogLevel::INFORMATIONAL,
    participant_id,
    writer_id,
    "Successful authentication",
    ex
);

// Flush to disk
logging->flush(ex);

Complete Security Example

Here's a complete example using all security plugins together:

#include <astutedds/dcps/domain_participant.hpp>
#include <astutedds/dcps/publisher.hpp>
#include <astutedds/security/security.hpp>
#include <astutedds/security/security_plugins.hpp>

namespace SEC = astutedds::security;
namespace DDS = astutedds::dcps;

int main() {
    // === 1. Create Security Plugins ===
    SEC::SecurityPlugins plugins;
    plugins.authentication = SEC::create_pki_authentication_plugin();
    plugins.access_control = SEC::create_xml_access_control_plugin();
    plugins.crypto = SEC::create_aes_gcm_crypto_plugin();
    plugins.logging = SEC::create_file_logging_plugin("/tmp/security.log");
    plugins.data_tagging = SEC::create_data_tagging_plugin();

    ASSERT(plugins.is_complete());

    // === 2. Setup Credentials ===
    SEC::CertificateCredentials creds;
    creds.identity_certificate = "-----BEGIN CERTIFICATE-----\n...";
    creds.identity_ca = "-----BEGIN CERTIFICATE-----\n...";
    creds.private_key = "-----BEGIN RSA PRIVATE KEY-----\n...";

    // === 3. Authenticate ===
    SEC::SecurityException ex;
    auto identity = plugins.authentication->validate_local_identity(
        creds,
        7,  // participant ID
        SEC::PropertySeq{},
        ex
    );
    ASSERT(ex.is_ok());

    // === 4. Check Permissions ===
    auto permissions = plugins.access_control->validate_local_permissions(
        *plugins.authentication,
        identity,
        7,
        SEC::PropertySeq{},
        ex
    );
    ASSERT(ex.is_ok());

    // === 5. Register with Crypto ===
    auto part_attrs = plugins.access_control->get_participant_sec_attributes(
        permissions,
        ex
    );
    ASSERT(ex.is_ok());

    auto participant_crypto = plugins.crypto->register_local_participant(
        identity,
        permissions,
        SEC::PropertySeq{},
        part_attrs,
        ex
    );
    ASSERT(ex.is_ok());

    // === 6. Create DDS Participant ===
    auto& factory = DDS::DomainParticipantFactory::instance();
    auto participant = factory.create_participant(7);

    // === 7. Create Topic and Endpoints ===
    auto topic = participant->create_topic("SecureTopic", "SecurePayload");
    auto publisher = participant->create_publisher();
    auto writer = publisher->create_datawriter(topic);

    // === 8. Register Endpoints for Encryption ===
    auto endpoint_attrs = plugins.access_control->get_endpoint_sec_attributes(
        permissions,
        "SecureTopic",
        ex
    );
    endpoint_attrs.is_payload_protected = true;

    auto writer_crypto = plugins.crypto->register_local_datawriter(
        participant_crypto,
        SEC::PropertySeq{},
        endpoint_attrs,
        ex
    );
    ASSERT(ex.is_ok());

    // === 9. Encrypt and Send Data ===
    std::vector<uint8_t> plaintext = {0x41, 0x73, 0x74, 0x75, 0x74, 0x65};  // "Astute"
    std::vector<uint8_t> encrypted;

    if (plugins.crypto->encode_serialized_payload(
            encrypted,
            plaintext,
            writer_crypto,
            ex))
    {
        writer->write(encrypted);
        std::cout << "Encrypted payload sent" << std::endl;
    }

    // === 10. Cleanup ===
    plugins.crypto->unregister_datawriter(writer_crypto, ex);
    plugins.crypto->unregister_participant(participant_crypto, ex);
    plugins.access_control->return_permissions_handle(permissions, ex);
    plugins.authentication->return_identity_handle(identity, ex);
    factory.delete_participant(participant);

    return 0;
}

Secure Example Application

AstuteDDS includes a complete secure example:

# Build with security enabled
cd build
cmake .. -DASTUTEDDS_ENABLE_SECURITY=ON
cmake --build . --target secure_hello_world

# Run
./examples/secure/secure_hello_world

This example demonstrates: - PKI authentication - Certificate validation - Payload encryption/decryption - End-to-end secure communication

Testing Security

Run the security test suite:

cd build
ctest -R Security -V

Tests cover: - Authentication handshakes - Permission validation - Crypto encode/decode - RTPS message signing - Data tagging and classification - Logging functionality

Security Best Practices

  1. Use Real Certificates: Replace test certificates with production X.509 certificates
  2. Manage Private Keys: Store private keys securely and never embed in code
  3. Set Appropriate Permissions: Use XML access control to restrict topics by role
  4. Enable Encryption: Always encrypt sensitive payloads with is_payload_protected=true
  5. Monitor Logs: Check /var/log/astutedds-security.log for security events
  6. Rotate Credentials: Periodically renew certificates and keys
  7. Validate Interop: Test with other DDS implementations (Fast DDS, Cyclone, RTI)

Security Policy Configuration

Create a security policy file (security-policy.xml):

<?xml version="1.0" encoding="UTF-8"?>
<dds xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <domain_participant_qos>
        <property>
            <value>
                <name>dds.sec.auth.plugin</name>
                <value>astutedds::security::PkiAuthenticationPlugin</value>
            </value>
            <value>
                <name>dds.sec.access.plugin</name>
                <value>astutedds::security::XmlAccessControlPlugin</value>
            </value>
            <value>
                <name>dds.sec.crypto.plugin</name>
                <value>astutedds::security::AesGcmCryptoPlugin</value>
            </value>
        </property>
    </domain_participant_qos>
</dds>

Troubleshooting

Certificate Validation Failed

  • Ensure certificate files exist and are readable
  • Verify certificate format (PEM encoding)
  • Check certificate expiration dates

Authentication Handshake Timeout

  • Increase wait timeout in security tests
  • Check network connectivity
  • Verify SPDP/SEDP discovery is working

Decrypt Fails

  • Ensure both writer and reader use same crypto plugin
  • Verify writer registered before reader receives data
  • Check that payloads are encrypted before transmission

API Reference

  • <astutedds/security/security.hpp> — Main security API
  • <astutedds/security/security_plugins.hpp> — Plugin interfaces
  • <astutedds/security/security_types.hpp> — Security data types

Further Reading