From 6cdfbe12545d5b8b5a9f1234bb1bcefca00d987b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Hern=C3=A1ndez=20Cordero?= Date: Mon, 20 Jan 2025 18:48:21 +0100 Subject: [PATCH] Added peer template and config key and cert MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Alejandro Hernández Cordero --- zenoh_security_configuration/README.md | 59 ++ .../templates/peer.json5 | 572 ++++++++++++++++++ .../templates/router.json5 | 16 +- .../zenoh_security_configuration.py | 137 ++++- 4 files changed, 762 insertions(+), 22 deletions(-) create mode 100644 zenoh_security_configuration/templates/peer.json5 diff --git a/zenoh_security_configuration/README.md b/zenoh_security_configuration/README.md index 5ab09479..08fcea79 100644 --- a/zenoh_security_configuration/README.md +++ b/zenoh_security_configuration/README.md @@ -1 +1,60 @@ # zenoh security configuration + +### Configure the router + +```bash +ros2 run zenoh_security_configuration zenoh_security_configuration \ + -o zenoh_config \ + -t router \ + --listen_endpoint="tls/localhost:7447" \ + --protocols=tls \ + paths \ + --root_ca_certificate /home/ahcorde/sros2_demo/demo_keystore_zenoh/public/ca.cert.pem \ + --listen_private_key /home/ahcorde/sros2_demo/demo_keystore_zenoh/enclaves/zenohd/key.pem \ + --connect_private_key /home/ahcorde/sros2_demo/demo_keystore_zenoh/enclaves/zenohd/key.pem \ + --connect_certificate /home/ahcorde/sros2_demo/demo_keystore_zenoh/enclaves/zenohd/cert.pem \ + --listen_certificate /home/ahcorde/sros2_demo/demo_keystore_zenoh/enclaves/zenohd/cert.pem +``` + +Using enclaves generated with `ros2 security create_enclave` + +```bash +ros2 run zenoh_security_configuration zenoh_security_configuration \ + -o zenoh_config \ + -t router \ + --listen_endpoint="tls/localhost:0" \ + --protocols=tls \ + enclave \ + --enclave_path /home/ahcorde/sros2_demo/demo_keystore_zenoh \ + --enclave_name /zenoh +``` + +### Configure a Peer + +```bash +ros2 run zenoh_security_configuration zenoh_security_configuration \ + -o zenoh_config \ + -t peer \ + --listen_endpoint="tls/localhost:0" \ + --protocols=tls \ + paths \ + --root_ca_certificate /home/ahcorde/sros2_demo/demo_keystore_zenoh/public/ca.cert.pem \ + --listen_private_key /home/ahcorde/sros2_demo/demo_keystore_zenoh/enclaves/listener/key.pem \ + --connect_private_key /home/ahcorde/sros2_demo/demo_keystore_zenoh/enclaves/listener/key.pem \ + --connect_certificate /home/ahcorde/sros2_demo/demo_keystore_zenoh/enclaves/listener/cert.pem \ + --listen_certificate /home/ahcorde/sros2_demo/demo_keystore_zenoh/enclaves/listener/cert.pem +``` + +Using enclaves generated with `ros2 security create_enclave` + + +```bash +ros2 run zenoh_security_configuration zenoh_security_configuration \ + -o zenoh_config \ + -t peer \ + --listen_endpoint="tls/localhost:0" \ + --protocols=tls \ + enclave \ + --enclave_path /home/ahcorde/sros2_demo/demo_keystore_zenoh \ + --enclave_name /talker_listener/talker +``` diff --git a/zenoh_security_configuration/templates/peer.json5 b/zenoh_security_configuration/templates/peer.json5 new file mode 100644 index 00000000..49a2d8e4 --- /dev/null +++ b/zenoh_security_configuration/templates/peer.json5 @@ -0,0 +1,572 @@ +/// This file attempts to list and document available configuration elements. +/// For a more complete view of the configuration's structure, check out `zenoh/src/config.rs`'s `Config` structure. +/// Note that the values here are correctly typed, but may not be sensible, so copying this file to change only the parts that matter to you is not good practice. +{ + /// The identifier (as unsigned 128bit integer in hexadecimal lowercase - leading zeros are not accepted) + /// that zenoh runtime will use. + /// If not set, a random unsigned 128bit integer will be used. + /// WARNING: this id must be unique in your zenoh network. + // id: "1234567890abcdef", + + /// The node's mode (router, peer or client) + mode: "peer", + + /// Which endpoints to connect to. E.g. tcp/localhost:7447. + /// By configuring the endpoints, it is possible to tell zenoh which router/peer to connect to at startup. + /// + /// For TCP/UDP on Linux, it is possible additionally specify the interface to be connected to: + /// E.g. tcp/192.168.0.1:7447#iface=eth0, for connect only if the IP address is reachable via the interface eth0 + /// + /// It is also possible to specify a priority range and/or a reliability setting to be used on the link. + /// For example `tcp/localhost?prio=6-7;rel=0` assigns priorities "data_low" and "background" to the established link. + /// + /// For TCP and TLS links, it is possible to specify the TCP buffer sizes: + /// E.g. tcp/192.168.0.1:7447#so_sndbuf=65000;so_rcvbuf=65000 + connect: { + /// timeout waiting for all endpoints connected (0: no retry, -1: infinite timeout) + /// Accepts a single value (e.g. timeout_ms: 0) + /// or different values for router, peer and client (e.g. timeout_ms: { router: -1, peer: -1, client: 0 }). + timeout_ms: { router: -1, peer: -1, client: 0 }, + + /// The list of endpoints to connect to. + /// Accepts a single list (e.g. endpoints: ["tcp/10.10.10.10:7447", "tcp/11.11.11.11:7447"]) + /// or different lists for router, peer and client (e.g. endpoints: { router: ["tcp/10.10.10.10:7447"], peer: ["tcp/11.11.11.11:7447"] }). + /// + /// See https://docs.rs/zenoh/latest/zenoh/config/struct.EndPoint.html + /// + /// ROS setting: By default connect to the Zenoh router on localhost on port 7447. + endpoints: [ + "@(connect_endpoint)" + ], + + /// Global connect configuration, + /// Accepts a single value or different values for router, peer and client. + /// The configuration can also be specified for the separate endpoint + /// it will override the global one + /// E.g. tcp/192.168.0.1:7447#retry_period_init_ms=20000;retry_period_max_ms=10000" + + /// exit from application, if timeout exceed + exit_on_failure: { router: false, peer: false, client: true }, + /// connect establishing retry configuration + retry: { + /// initial wait timeout until next connect try + period_init_ms: 1000, + /// maximum wait timeout until next connect try + period_max_ms: 4000, + /// increase factor for the next timeout until nexti connect try + period_increase_factor: 2, + }, + }, + + /// Which endpoints to listen on. E.g. tcp/0.0.0.0:7447. + /// By configuring the endpoints, it is possible to tell zenoh which are the endpoints that other routers, + /// peers, or client can use to establish a zenoh session. + /// + /// For TCP/UDP on Linux, it is possible additionally specify the interface to be listened to: + /// E.g. tcp/0.0.0.0:7447#iface=eth0, for listen connection only on eth0 + /// + /// It is also possible to specify a priority range and/or a reliability setting to be used on the link. + /// For example `tcp/localhost?prio=6-7;rel=0` assigns priorities "data_low" and "background" to the established link. + /// + /// For TCP and TLS links, it is possible to specify the TCP buffer sizes: + /// E.g. tcp/192.168.0.1:7447#so_sndbuf=65000;so_rcvbuf=65000 + listen: { + /// timeout waiting for all listen endpoints (0: no retry, -1: infinite timeout) + /// Accepts a single value (e.g. timeout_ms: 0) + /// or different values for router, peer and client (e.g. timeout_ms: { router: -1, peer: -1, client: 0 }). + timeout_ms: 0, + + /// The list of endpoints to listen on. + /// Accepts a single list (e.g. endpoints: ["tcp/[::]:7447", "udp/[::]:7447"]) + /// or different lists for router, peer and client (e.g. endpoints: { router: ["tcp/[::]:7447"], peer: ["tcp/[::]:0"] }). + /// + /// See https://docs.rs/zenoh/latest/zenoh/config/struct.EndPoint.html + /// + /// ROS setting: By default accept incoming connections only from localhost (i.e. from colocalized Nodes). + /// All communications with other hosts are routed by the Zenoh router. + endpoints: [ + "@(listen_endpoint)" + ], + + /// Global listen configuration, + /// Accepts a single value or different values for router, peer and client. + /// The configuration can also be specified for the separate endpoint + /// it will override the global one + /// E.g. tcp/192.168.0.1:7447#exit_on_failure=false;retry_period_max_ms=1000" + + /// exit from application, if timeout exceed + exit_on_failure: true, + /// listen retry configuration + retry: { + /// initial wait timeout until next try + period_init_ms: 1000, + /// maximum wait timeout until next try + period_max_ms: 4000, + /// increase factor for the next timeout until next try + period_increase_factor: 2, + }, + }, + /// Configure the session open behavior. + open: { + /// Configure the conditions to be met before session open returns. + return_conditions: { + /// Session open waits to connect to scouted peers and routers before returning. + /// When set to false, first publications and queries after session open from peers may be lost. + connect_scouted: true, + /// Session open waits to receive initial declares from connected peers before returning. + /// Setting to false may cause extra traffic at startup from peers. + declares: true, + }, + }, + /// Configure the scouting mechanisms and their behaviours + scouting: { + /// In client mode, the period in milliseconds dedicated to scouting for a router before failing. + timeout: 3000, + /// In peer mode, the maximum period in milliseconds dedicated to scouting remote peers before attempting other operations. + delay: 500, + /// The multicast scouting configuration. + multicast: { + /// Whether multicast scouting is enabled or not + /// + /// ROS setting: disable multicast discovery by default + enabled: false, + /// The socket which should be used for multicast scouting + address: "224.0.0.224:7446", + /// The network interface which should be used for multicast scouting + interface: "auto", // If not set or set to "auto" the interface if picked automatically + /// The time-to-live on multicast scouting packets + ttl: 1, + /// Which type of Zenoh instances to automatically establish sessions with upon discovery on UDP multicast. + /// Accepts a single value (e.g. autoconnect: ["router", "peer"]) + /// or different values for router, peer and client (e.g. autoconnect: { router: [], peer: ["router", "peer"] }). + /// Each value is a list of: "peer", "router" and/or "client". + autoconnect: { router: [], peer: ["router", "peer"] }, + /// Whether or not to listen for scout messages on UDP multicast and reply to them. + listen: true, + }, + /// The gossip scouting configuration. + gossip: { + /// Whether gossip scouting is enabled or not + enabled: true, + /// When true, gossip scouting information are propagated multiple hops to all nodes in the local network. + /// When false, gossip scouting information are only propagated to the next hop. + /// Activating multihop gossip implies more scouting traffic and a lower scalability. + /// It mostly makes sense when using "linkstate" routing mode where all nodes in the subsystem don't have + /// direct connectivity with each other. + multihop: false, + /// Which type of Zenoh instances to automatically establish sessions with upon discovery on gossip. + /// Accepts a single value (e.g. autoconnect: ["router", "peer"]) + /// or different values for router, peer and client (e.g. autoconnect: { router: [], peer: ["router", "peer"] }). + /// Each value is a list of: "peer", "router" and/or "client". + autoconnect: { router: [], peer: ["router", "peer"] }, + }, + }, + + /// Configuration of data messages timestamps management. + timestamping: { + /// Whether data messages should be timestamped if not already. + /// Accepts a single boolean value or different values for router, peer and client. + /// + /// ROS setting: PublicationCache which is required for transient_local durability + /// only works when time-stamping is enabled. + enabled: { router: true, peer: true, client: true }, + /// Whether data messages with timestamps in the future should be dropped or not. + /// If set to false (default), messages with timestamps in the future are retimestamped. + /// Timestamps are ignored if timestamping is disabled. + drop_future_timestamp: false, + }, + + /// The default timeout to apply to queries in milliseconds. + queries_default_timeout: 10000, + + /// The routing strategy to use and it's configuration. + routing: { + /// The routing strategy to use in routers and it's configuration. + router: { + /// When set to true a router will forward data between two peers + /// directly connected to it if it detects that those peers are not + /// connected to each other. + /// The failover brokering only works if gossip discovery is enabled. + peers_failover_brokering: true, + }, + /// The routing strategy to use in peers and it's configuration. + peer: { + /// The routing strategy to use in peers. ("peer_to_peer" or "linkstate"). + mode: "peer_to_peer", + }, + }, + + // /// Overwrite QoS options for Zenoh messages by key expression (ignores Zenoh API QoS config for overwritten values) + // qos: { + // /// Overwrite QoS options for PUT and DELETE messages + // publication: [ + // { + // /// PUT and DELETE messages on key expressions that are included by these key expressions + // /// will have their QoS options overwritten by the given config. + // key_exprs: ["demo/**", "example/key"], + // /// Configurations that will be applied on the publisher. + // /// Options that are supplied here will overwrite the configuration given in Zenoh API + // config: { + // congestion_control: "block", + // priority: "data_high", + // express: true, + // reliability: "best_effort", + // allowed_destination: "remote", + // }, + // }, + // ], + // }, + + // /// The declarations aggregation strategy. + // aggregation: { + // /// A list of key-expressions for which all included subscribers will be aggregated into. + // subscribers: [ + // // key_expression + // ], + // /// A list of key-expressions for which all included publishers will be aggregated into. + // publishers: [ + // // key_expression + // ], + // }, + + // /// The downsampling declaration. + // downsampling: [ + // { + // /// A list of network interfaces messages will be processed on, the rest will be passed as is. + // interfaces: [ "wlan0" ], + // /// Data flow messages will be processed on. ("egress" or "ingress") + // flow: "egress", + // /// A list of downsampling rules: key_expression and the maximum frequency in Hertz + // rules: [ + // { key_expr: "demo/example/zenoh-rs-pub", freq: 0.1 }, + // ], + // }, + // ], + + // /// Configure access control (ACL) rules + // access_control: { + // /// [true/false] acl will be activated only if this is set to true + // "enabled": false, + // /// [deny/allow] default permission is deny (even if this is left empty or not specified) + // "default_permission": "deny", + // /// Rule set for permissions allowing or denying access to key-expressions + // "rules": + // [ + // { + // /// Id has to be unique within the rule set + // "id": "rule1", + // "messages": [ + // "put", "delete", "declare_subscriber", + // "query", "reply", "declare_queryable", + // "liveliness_token", "liveliness_query", "declare_liveliness_subscriber", + // ], + // "flows":["egress","ingress"], + // "permission": "allow", + // "key_exprs": [ + // "test/demo" + // ], + // }, + // { + // "id": "rule2", + // "messages": [ + // "put", "delete", "declare_subscriber", + // "query", "reply", "declare_queryable", + // ], + // "flows":["ingress"], + // "permission": "allow", + // "key_exprs": [ + // "**" + // ], + // }, + // ], + // /// List of combinations of subjects. + // /// + // /// If a subject property (i.e. username, certificate common name or interface) is empty + // /// it is interpreted as a wildcard. Moreover, a subject property cannot be an empty list. + // "subjects": + // [ + // { + // /// Id has to be unique within the subjects list + // "id": "subject1", + // /// Subjects can be interfaces + // "interfaces": [ + // "lo0", + // "en0", + // ], + // /// Subjects can be cert_common_names when using TLS or Quic + // "cert_common_names": [ + // "example.zenoh.io" + // ], + // /// Subjects can be usernames when using user/password authentication + // "usernames": [ + // "zenoh-example" + // ], + // /// This instance translates internally to this filter: + // /// (interface="lo0" && cert_common_name="example.zenoh.io" && username="zenoh-example") || + // /// (interface="en0" && cert_common_name="example.zenoh.io" && username="zenoh-example") + // }, + // { + // "id": "subject2", + // "interfaces": [ + // "lo0", + // "en0", + // ], + // "cert_common_names": [ + // "example2.zenoh.io" + // ], + // /// This instance translates internally to this filter: + // /// (interface="lo0" && cert_common_name="example2.zenoh.io") || + // /// (interface="en0" && cert_common_name="example2.zenoh.io") + // }, + // { + // "id": "subject3", + // /// An empty subject combination is a wildcard + // }, + // ], + // /// The policies list associates rules to subjects + // "policies": + // [ + // /// Each policy associates one or multiple rules to one or multiple subject combinations + // { + // /// Rules and Subjects are identified with their unique IDs declared above + // "rules": ["rule1"], + // "subjects": ["subject1", "subject2"], + // }, + // { + // "rules": ["rule2"], + // "subjects": ["subject3"], + // }, + // ] + //}, + + /// Configure internal transport parameters + transport: { + unicast: { + /// Timeout in milliseconds when opening a link + open_timeout: 10000, + /// Timeout in milliseconds when accepting a link + accept_timeout: 10000, + /// Maximum number of zenoh session in pending state while accepting + accept_pending: 100, + /// Maximum number of sessions that can be simultaneously alive + max_sessions: 1000, + /// Maximum number of incoming links that are admitted per session + max_links: 1, + /// Enables the LowLatency transport + /// This option does not make LowLatency transport mandatory, the actual implementation of transport + /// used will depend on Establish procedure and other party's settings + /// + /// NOTE: Currently, the LowLatency transport doesn't preserve QoS prioritization. + /// NOTE: Due to the note above, 'lowlatency' is incompatible with 'qos' option, so in order to + /// enable 'lowlatency' you need to explicitly disable 'qos'. + /// NOTE: LowLatency transport does not support the fragmentation, so the message size should be + /// smaller than the tx batch_size. + lowlatency: false, + /// Enables QoS on unicast communications. + qos: { + enabled: true, + }, + /// Enables compression on unicast communications. + /// Compression capabilities are negotiated during session establishment. + /// If both Zenoh nodes support compression, then compression is activated. + compression: { + enabled: false, + }, + }, + /// WARNING: multicast communication does not perform any negotiation upon group joining. + /// Because of that, it is important that all transport parameters are the same to make + /// sure all your nodes in the system can communicate. One common parameter to configure + /// is "transport/link/tx/batch_size" since its default value depends on the actual platform + /// when operating on multicast. + /// E.g., the batch size on Linux and Windows is 65535 bytes, on Mac OS X is 9216, and anything else is 8192. + multicast: { + /// JOIN message transmission interval in milliseconds. + join_interval: 2500, + /// Maximum number of multicast sessions. + max_sessions: 1000, + /// Enables QoS on multicast communication. + /// Default to false for Zenoh-to-Zenoh-Pico out-of-the-box compatibility. + qos: { + enabled: false, + }, + /// Enables compression on multicast communication. + /// Default to false for Zenoh-to-Zenoh-Pico out-of-the-box compatibility. + compression: { + enabled: false, + }, + }, + link: { + /// An optional whitelist of protocols to be used for accepting and opening sessions. If not + /// configured, all the supported protocols are automatically whitelisted. The supported + /// protocols are: ["tcp" , "udp", "tls", "quic", "ws", "unixsock-stream", "vsock"] For + /// example, to only enable "tls" and "quic": protocols: ["tls", "quic"], + /// + /// Configure the zenoh TX parameters of a link + protocols: @(protocols), + tx: { + /// The resolution in bits to be used for the message sequence numbers. + /// When establishing a session with another Zenoh instance, the lowest value of the two instances will be used. + /// Accepted values: 8bit, 16bit, 32bit, 64bit. + sequence_number_resolution: "32bit", + /// Link lease duration in milliseconds to announce to other zenoh nodes + lease: 10000, + /// Number of keep-alive messages in a link lease duration. If no data is sent, keep alive + /// messages will be sent at the configured time interval. + /// NOTE: In order to consider eventual packet loss and transmission latency and jitter, + /// set the actual keep_alive interval to one fourth of the lease time: i.e. send + /// 4 keep_alive messages in a lease period. Changing the lease time will have the + /// keep_alive messages sent more or less often. + /// This is in-line with the ITU-T G.8013/Y.1731 specification on continuous connectivity + /// check which considers a link as failed when no messages are received in 3.5 times the + /// target interval. + keep_alive: 4, + /// Batch size in bytes is expressed as a 16bit unsigned integer. + /// Therefore, the maximum batch size is 2^16-1 (i.e. 65535). + /// The default batch size value is the maximum batch size: 65535. + batch_size: 65535, + /// Each zenoh link has a transmission queue that can be configured + queue: { + /// The size of each priority queue indicates the number of batches a given queue can contain. + /// NOTE: the number of batches in each priority must be included between 1 and 16. Different values will result in an error. + /// The amount of memory being allocated for each queue is then SIZE_XXX * BATCH_SIZE. + /// In the case of the transport link MTU being smaller than the ZN_BATCH_SIZE, + /// then amount of memory being allocated for each queue is SIZE_XXX * LINK_MTU. + /// If qos is false, then only the DATA priority will be allocated. + size: { + control: 1, + real_time: 1, + interactive_high: 1, + interactive_low: 1, + data_high: 2, + data: 4, + data_low: 4, + background: 4, + }, + /// Congestion occurs when the queue is empty (no available batch). + congestion_control: { + /// Behavior pushing CongestionControl::Drop messages to the queue. + drop: { + /// The maximum time in microseconds to wait for an available batch before dropping a droppable message if still no batch is available. + wait_before_drop: 1000, + /// The maximum deadline limit for multi-fragment messages. + max_wait_before_drop_fragments: 50000, + }, + /// Behavior pushing CongestionControl::Block messages to the queue. + block: { + /// The maximum time in microseconds to wait for an available batch before closing the transport session when sending a blocking message + /// if still no batch is available. + wait_before_close: 5000000, + }, + }, + /// Perform batching of messages if they are smaller of the batch_size + batching: { + /// Perform adaptive batching of messages if they are smaller of the batch_size. + /// When the network is detected to not be fast enough to transmit every message individually, many small messages may be + /// batched together and sent all at once on the wire reducing the overall network overhead. This is typically of a high-throughput + /// scenario mainly composed of small messages. In other words, batching is activated by the network back-pressure. + enabled: true, + /// The maximum time limit (in ms) a message should be retained for batching when back-pressure happens. + time_limit: 1, + }, + }, + }, + /// Configure the zenoh RX parameters of a link + rx: { + /// Receiving buffer size in bytes for each link + /// The default the rx_buffer_size value is the same as the default batch size: 65535. + /// For very high throughput scenarios, the rx_buffer_size can be increased to accommodate + /// more in-flight data. This is particularly relevant when dealing with large messages. + /// E.g. for 16MiB rx_buffer_size set the value to: 16777216. + buffer_size: 65535, + /// Maximum size of the defragmentation buffer at receiver end. + /// Fragmented messages that are larger than the configured size will be dropped. + /// The default value is 1GiB. This would work in most scenarios. + /// NOTE: reduce the value if you are operating on a memory constrained device. + max_message_size: 1073741824, + }, + /// Configure TLS specific parameters + tls: { + /// Path to the certificate of the certificate authority used to validate either the server + /// or the client's keys and certificates, depending on the node's mode. If not specified + /// on router mode then the default WebPKI certificates are used instead. + root_ca_certificate: "@(root_ca_certificate)", + /// Path to the TLS listening side private key + listen_private_key: "@(listen_private_key)", + /// Path to the TLS listening side public certificate + listen_certificate: "@(listen_certificate)", + /// Enables mTLS (mutual authentication), client authentication + enable_mtls: true, + /// Path to the TLS connecting side private key + connect_private_key: "@(connect_private_key)", + /// Path to the TLS connecting side certificate + connect_certificate: "@(connect_certificate)", + // Whether or not to verify the matching between hostname/dns and certificate when connecting, + // if set to false zenoh will disregard the common names of the certificates when verifying servers. + // This could be dangerous because your CA can have signed a server cert for foo.com, that's later being used to host a server at baz.com. + // If you want your ca to verify that the server at baz.com is actually baz.com, let this be true (default). + verify_name_on_connect: false, + // Whether or not to close links when remote certificates expires. + // If set to true, links that require certificates (tls/quic) will automatically disconnect when the time of expiration of the remote certificate chain is reached + // note that mTLS (client authentication) is required for a listener to disconnect a client on expiration + close_link_on_expiration: false, + /// Optional configuration for TCP system buffers sizes for TLS links + /// + /// Configure TCP read buffer size (bytes) + // so_rcvbuf: 123456, + /// Configure TCP write buffer size (bytes) + // so_sndbuf: 123456, + }, + // // Configure optional TCP link specific parameters + // tcp: { + // /// Optional configuration for TCP system buffers sizes for TCP links + // /// + // /// Configure TCP read buffer size (bytes) + // // so_rcvbuf: 123456, + // /// Configure TCP write buffer size (bytes) + // // so_sndbuf: 123456, + // } + }, + /// Shared memory configuration. + /// NOTE: shared memory can be used only if zenoh is compiled with "shared-memory" feature, otherwise + /// settings in this section have no effect. + shared_memory: { + /// A probing procedure for shared memory is performed upon session opening. To enable zenoh to operate + /// over shared memory (and to not fallback on network mode), shared memory needs to be enabled also on the + /// subscriber side. By doing so, the probing procedure will succeed and shared memory will operate as expected. + /// + /// ROS setting: disabled by default until fully tested + enabled: false, + }, + auth: { + /// The configuration of authentication. + /// A password implies a username is required. + usrpwd: { + user: null, + password: null, + /// The path to a file containing the user password dictionary + dictionary_file: null, + }, + pubkey: { + public_key_pem: null, + private_key_pem: null, + public_key_file: null, + private_key_file: null, + key_size: null, + known_keys_file: null, + }, + }, + }, + + /// Configure the Admin Space + /// Unstable: this configuration part works as advertised, but may change in a future release + adminspace: { + /// Enables the admin space + enabled: true, + /// read and/or write permissions on the admin space + permissions: { + read: true, + write: false, + }, + }, + +} diff --git a/zenoh_security_configuration/templates/router.json5 b/zenoh_security_configuration/templates/router.json5 index a9eaf935..3dc4fd1b 100644 --- a/zenoh_security_configuration/templates/router.json5 +++ b/zenoh_security_configuration/templates/router.json5 @@ -66,7 +66,7 @@ /// /// See https://docs.rs/zenoh/latest/zenoh/config/struct.EndPoint.html endpoints: [ - "tls/localhost:7447" + "@(listen_endpoint)" ], /// Global listen configuration, @@ -435,22 +435,22 @@ /// Path to the certificate of the certificate authority used to validate either the server /// or the client's keys and certificates, depending on the node's mode. If not specified /// on router mode then the default WebPKI certificates are used instead. - root_ca_certificate: null, + root_ca_certificate: "@(root_ca_certificate)", /// Path to the TLS listening side private key - listen_private_key: "/home/ahcorde/sros2_demo/tls/localhost/key.pem", + listen_private_key: "@(listen_private_key)", /// Path to the TLS listening side public certificate - listen_certificate: "/home/ahcorde/sros2_demo/tls/localhost/cert.pem", + listen_certificate: "@(listen_certificate)", /// Enables mTLS (mutual authentication), client authentication - enable_mtls: false, + enable_mtls: true, /// Path to the TLS connecting side private key - connect_private_key: null, + connect_private_key: "@(connect_private_key)", /// Path to the TLS connecting side certificate - connect_certificate: null, + connect_certificate: "@(connect_certificate)", // Whether or not to verify the matching between hostname/dns and certificate when connecting, // if set to false zenoh will disregard the common names of the certificates when verifying servers. // This could be dangerous because your CA can have signed a server cert for foo.com, that's later being used to host a server at baz.com. // If you want your ca to verify that the server at baz.com is actually baz.com, let this be true (default). - verify_name_on_connect: true, + verify_name_on_connect: false, }, }, /// Shared memory configuration. diff --git a/zenoh_security_configuration/zenoh_security_configuration/zenoh_security_configuration.py b/zenoh_security_configuration/zenoh_security_configuration/zenoh_security_configuration.py index 02eaa248..4d0d22aa 100644 --- a/zenoh_security_configuration/zenoh_security_configuration/zenoh_security_configuration.py +++ b/zenoh_security_configuration/zenoh_security_configuration/zenoh_security_configuration.py @@ -25,11 +25,11 @@ class ZenohSecutiryConfigGenerator: def __init__(self): """ - Construct NEXUSConfigGenerator. + Construct ZenohConfigGenerator. """ self.zenoh_cfg_file_extension = "json5" - def generate_router_config(self, data): + def generate_router_config(self, data, zenoh_type): try: output = StringIO() interpreter = em.Interpreter( @@ -43,22 +43,21 @@ def generate_router_config(self, data): template_path = pathlib.Path(os.path.join( get_package_share_directory("zenoh_security_configuration"), "templates", - "router.json5" + zenoh_type + ".json5" )) - with template_path.open('r') as h: template_content = h.read() interpreter.string(template_content, locals=data) return output.getvalue() - except: - print('lol') + except Exception as e: + print(e) finally: if interpreter is not None: interpreter.shutdown() interpreter = None - def generate_zenoh_config(self, output_dir, router_config, encoding: str = 'utf-8'): + def generate_zenoh_config(self, output_dir, router_config, zenoh_type, encoding: str = 'utf-8'): """ Generate Zenoh bridge configs and output to directory 'output_dir'. @@ -69,7 +68,7 @@ def generate_zenoh_config(self, output_dir, router_config, encoding: str = 'utf- """ write_filepath = os.path.join( - output_dir, "router" + "." + output_dir, zenoh_type + "." + self.zenoh_cfg_file_extension, ) output_file = pathlib.Path(write_filepath) @@ -86,10 +85,12 @@ def generate_zenoh_config(self, output_dir, router_config, encoding: str = 'utf- def main(argv=sys.argv): """Entrypoint.""" parser = argparse.ArgumentParser( - description="Generate Zenoh configurations from a NEXUS Network \ - and REDF Configuration", + description="Generate Zenoh security configurations", formatter_class=argparse.ArgumentDefaultsHelpFormatter, ) + subparsers = parser.add_subparsers(help='help for subcommand', dest="subcommand") + parser_path = subparsers.add_parser('paths', help='Use path') + parser_enclave = subparsers.add_parser('enclave', help='Use enclave directory') parser.add_argument( "-o", @@ -99,6 +100,24 @@ def main(argv=sys.argv): help="Output directory for Zenoh bridge configurations", ) + parser.add_argument( + "-l", + "--listen_endpoint", + required=False, + type=str, + default ="tls/localhost:7447", + help="The list of endpoints to listen on (See https://docs.rs/zenoh/latest/zenoh/config/struct.EndPoint.html)", + ) + + parser.add_argument( + "-c", + "--connect_endpoint", + required=False, + type=str, + default ="tls/localhost:7447", + help="The list of endpoints to connect to. (See https://docs.rs/zenoh/latest/zenoh/config/struct.EndPoint.html)", + ) + parser.add_argument( "-p", "--protocols", @@ -109,13 +128,103 @@ def main(argv=sys.argv): help="Protocols chooices", ) - args = parser.parse_args(argv[1:]) + parser.add_argument( + "-t", + "--type", + type=str, + required=True, + choices=["router", "peer"], + default=['router'], + help="Set router or peer", + ) - data = {'protocols': args.protocols} + parser_path.add_argument( + "--root_ca_certificate", + type=str, + required=True, + default='', + help="Path to the certificate of the certificate authority used to validate " \ + "either the server or the client's keys and certificates" + ) + + parser_path.add_argument( + "--listen_private_key", + type=str, + required=True, + default='', + help="Path to the TLS listening side private key" + ) + + parser_path.add_argument( + "--listen_certificate", + type=str, + required=True, + default='', + help="Path to the TLS listening side public certificate" + ) + + parser_path.add_argument( + "--connect_private_key", + type=str, + required=True, + default='', + help="Path to the TLS connecting side private key" + ) + + parser_path.add_argument( + "--connect_certificate", + type=str, + required=True, + default='', + help="Path to the TLS connecting side certificate" + ) + + parser_enclave.add_argument( + "--enclave_path", + type=str, + required=True, + default='', + help="Enclave path" + ) + + parser_enclave.add_argument( + "--enclave_name", + type=str, + required=True, + default='', + help="Enclave name" + ) + + args = parser.parse_args(argv[1:]) + if args.enclave_name is not None: + if args.enclave_name[0] == '/': + args.enclave_name = args.enclave_name[1:] + root_ca_certificate = os.path.join(args.enclave_path, "public", "ca.cert.pem") + listen_private_key = os.path.join(args.enclave_path, "enclaves", args.enclave_name, "key.pem") + listen_certificate = os.path.join(args.enclave_path, "enclaves", args.enclave_name, "cert.pem") + connect_private_key = listen_private_key + connect_certificate = listen_certificate + else: + root_ca_certificate = args.root_ca_certificate + listen_private_key = args.listen_private_key + listen_certificate = args.listen_certificate + connect_private_key = args.connect_private_key + connect_certificate = args.connect_certificate + + data = { + 'protocols': args.protocols, + 'listen_endpoint': args.listen_endpoint, + 'connect_endpoint': args.connect_endpoint, + 'root_ca_certificate': root_ca_certificate, + 'listen_private_key': listen_private_key, + 'listen_certificate': listen_certificate, + 'connect_private_key': connect_private_key, + 'connect_certificate': connect_certificate, + } zenoh_sec_gen = ZenohSecutiryConfigGenerator() - router_config = zenoh_sec_gen.generate_router_config(data) - zenoh_sec_gen.generate_zenoh_config(args.output, router_config) + router_config = zenoh_sec_gen.generate_router_config(data, args.type) + zenoh_sec_gen.generate_zenoh_config(args.output, router_config, args.type) if __name__ == "__main__": main(sys.argv)