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
- Use Real Certificates: Replace test certificates with production X.509 certificates
- Manage Private Keys: Store private keys securely and never embed in code
- Set Appropriate Permissions: Use XML access control to restrict topics by role
- Enable Encryption: Always encrypt sensitive payloads with
is_payload_protected=true - Monitor Logs: Check
/var/log/astutedds-security.logfor security events - Rotate Credentials: Periodically renew certificates and keys
- 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