Skip to content

Commit 065b0f2

Browse files
committed
Implements #16: adds SSL/TLS support.
1 parent 53f9945 commit 065b0f2

33 files changed

+795
-87
lines changed

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
.project
2+
/Release
3+
.vscode
4+
results.xml
5+
.buildtool/
6+
javaclasspath.txt

Documentation/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
_build

Documentation/MATLABInterface.md

Lines changed: 89 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,10 @@ of the `rabbitmq.ConnectorProperties` class or using YAML configuration files.
4545
*Default:* Default `rabbitmq.Credentials`
4646
:routingkey: Routing key to subscribe to or poll on - only used for Consumer, when working with Producer the routing key is specified on a per message basis when publishing a message.\
4747
*Default:* ``"test-topic"``
48+
:sslcontext: SSL/TLS Configuration. Leave empty if the AMQP connection does not use SSL.\
49+
*Default:* Empty (0x0) `rabbitmq.SSLContextProperties`
4850

49-
Where, as can be seen, properties `exchange`, `queue` and `credentials` are
51+
Where, as can be seen, properties `exchange`, `queue`, `credentials` and `sslcontext` are
5052
in turn other MATLAB classes:
5153

5254
**rabbitmq.ExchangeProperties**
@@ -88,6 +90,38 @@ in turn other MATLAB classes:
8890
:password: Password\
8991
*Default:* `"guest"`
9092

93+
**rabbitmq.SSLContextProperties**
94+
95+
:server: Server SSL Configuration. Required to be configured if the AMQP connection requires SSL.\
96+
*Default:* Empty (0x0) `rabbitmq.TrustManagerProperties`
97+
98+
:client: Client SSL Configuration. Required to be configured if the RabbitMQ server requires client certificates. Leave unset if the connection is SSL secured but without client certificates.\
99+
*Default:* Empty (0x0) `rabbitmq.KeyManagerProperties`
100+
101+
:protocol: SSL/TLS Protocol (version)\
102+
*Default:* `"TLSv1.2"`
103+
104+
**rabbitmq.TrustManagerProperties**
105+
106+
:truststore: Location of the trust store containing the server certificate (chain) and/or trusted root CA(s).
107+
108+
:passphrase: Passphrase/password of the trust store.
109+
110+
:type: Type of trust store\
111+
*Default:* `"JKS"`
112+
113+
:hostnameVerification: Whether or not hostname verification is enabled. Generally should be left at its default `true`. Only temporarily disable this when debugging SSL/TLS connection issues.\
114+
*Default:* `true`
115+
116+
**rabbitmq.KeyManagerProperties**
117+
118+
:keystore: Location of the keystore containing the client certificate and corresponding private key.
119+
120+
:passphrase: Passphrase/password of the keystore.
121+
122+
:type: Type of keystore.\
123+
*Default:* `"PKCS12"`
124+
91125
Setting properties values can be done through traditional MATLAB class syntax:
92126

93127
```matlab
@@ -142,34 +176,53 @@ configuration file for the MATLAB Production Server interface:
142176
# Messaging connection and routing properties
143177
messageQueue:
144178
queue:
145-
name: RabbitMQ # Name of the Queue on RabbitMQ Server
146-
create: true # Creates/verifies whether queue exists
147-
durable: false # Work with a durable queue or not
148-
exclusive: false # Work with an exclusive queue or not
149-
autoDelete: false # Work with an auto delete queue or not
150-
arguments: # Set additional arguments, can be omitted entirely
151-
x-max-length: 42 # For example, set the maximum queue length
152-
host: localhost # Hostname or IP of the RabbitMQ Server
153-
port: 5672 # Port the RabbitMQ Server runs on
154-
virtualhost: / # RabbitMQ Virtual Host
155-
credentials:
156-
username: guest # RabbitMQ username
157-
password: guest # RabbitMQ password
158-
exchange:
159-
name: amq.topic # Exchange to work with on RabbitMQ
160-
create: true # Creates/verifies whether exchange exists
161-
durable: true # Work with a durable exchange or not
162-
autoDelete: false # Work with an auto delete exchange or not
163-
internal: false # Work with an internal exchange or not
164-
arguments: # Set additional arguments, can be omitted entirely
165-
alternate-exchange: my-ea # For example alternate-exchange
166-
routingkey: test-topic # Routing key to subscribe to
179+
name: RabbitMQ # Name of the Queue on RabbitMQ Server
180+
create: true # Creates/verifies whether queue exists
181+
durable: false # Work with a durable queue or not
182+
exclusive: false # Work with an exclusive queue or not
183+
autoDelete: false # Work with an auto delete queue or not
184+
arguments: # Set additional arguments, can be omitted entirely
185+
x-max-length: 42 # For example, set the maximum queue length
186+
host: localhost # Hostname or IP of the RabbitMQ Server
187+
port: 5672 # Port the RabbitMQ Server runs on
188+
virtualhost: / # RabbitMQ Virtual Host
189+
credentials:
190+
username: guest # RabbitMQ username
191+
password: guest # RabbitMQ password
192+
exchange:
193+
name: amq.topic # Exchange to work with on RabbitMQ
194+
create: true # Creates/verifies whether exchange exists
195+
durable: true # Work with a durable exchange or not
196+
autoDelete: false # Work with an auto delete exchange or not
197+
internal: false # Work with an internal exchange or not
198+
arguments: # Set additional arguments, can be omitted entirely
199+
alternate-exchange: my-ea # For example alternate-exchange
200+
routingkey: test-topic # Routing key to subscribe to
201+
sslcontext: # SSL/TLS Configuration, omit this section entirely when not working with SSL
202+
protocol: TLSv1.2 # Exact SSL/TLS protocol (version)
203+
server: # Server trust store configuration
204+
truststore: /some/location # Location of the trust store containing the server certificate chain
205+
passphrase: rabbitstore # Passphrase/password of the trust store
206+
type: JKS # Type of trust store
207+
hostnameVerification: true # Enable hostname verification
208+
client: # Client Certificate Configuration. Omit this section entirely if your server does not require client certificates
209+
keystore: /some/location # Location of the keystore containing client certificate and private key
210+
passphrase: supersecret # Passphrase/password of the keystore
211+
type: PKCS12 # Type of keystore
167212
```
168213
169214
```{note}
170215
The `arguments` option can be omitted entirely for both `queue` and `exchange` if it is not necessary to set additional arguments. There is no fixed set of arguments which can be added and the entered argument names are not checked by the interface; they are passed on the server as-is. Check the RabbitMQ documentation to learn more about which exact arguments can be configured.
171216
```
172217

218+
```{note}
219+
The `sslcontext` section is omitted entirely if not working with an SSL secured endpoint. If working with an SSL secured endpoint, the `sslcontext` section must be added and the `server` section must be configured. The `client` section is optional; it is needed if your server requires client certificates but is omitted when client certificates are not required/used.
220+
```
221+
222+
#### SSL/TLS Configuration
223+
224+
More details about working with SSL/TLS secured channels can be found in [](./SSLTLS.md).
225+
173226
### RabbitMQ Producer for publishing messages `rabbitmq.Producer`
174227
To work with `rabbitmq.Producer` in MATLAB, first create an instance with
175228
`rabbitmq.ConnectorProperties` or configuration YAML-file as input:
@@ -189,6 +242,18 @@ message as input:
189242
producer.publish('my-routing-key','Hello World');
190243
```
191244

245+
And to send a message with headers use `publishWithHeaders` where headers are
246+
specified as a cell-array with pairs of values where the first value is the header
247+
name and the second value is the header value; repeat to set multiple headers.
248+
For example:
249+
250+
```matlab
251+
producer.publishWithHeaders('my-routing-key',...
252+
{'FirstHeaderName',HeaderValue1,'SecondHeaderName',HeaderValue2},...
253+
'Hello World');
254+
```
255+
256+
192257
### RabbitMQ Consumer for receiving messages `rabbitmq.Consumer`
193258
`rabbitmq.Consumer` offers two approaches for receiving messages from RabbitMQ
194259
in MATLAB. An event-based approach and a polling approach. These two different
@@ -273,4 +338,4 @@ added to the *static* class path but there may be circumstances in which this is
273338
not possible and then it is loaded on the *dynamic* class path; this may make
274339
the event based consumer approach unavailable.
275340

276-
[//]: # (Copyright 2022-2023 The MathWorks, Inc.)
341+
[//]: # (Copyright 2022-2025 The MathWorks, Inc.)

Documentation/MessageBroker.md

Lines changed: 45 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -122,45 +122,60 @@ the options to match your configuration.
122122
The `arguments` for `queue` and `exchange` will likely have to be removed, they are not often used and shown here mainly for illustrative purposes to show *where* these can be added *if* they are needed. There is no fixed set of arguments which can be added and argument names are not verified by `MessageBroker`; they are send to the server as-is. Check the RabbitMQ documentation to learn more about the argument its supports.
123123
```
124124
125+
```{note}
126+
The `sslcontext` section should be omitted entirely if the amqp channel is not SSL/TLS secured at all. If the channel is SSL/TLS secured, the section must be present and the `server` section must be configured. The `client` section is optional; it must be configured if the server requires client certificates but is omitted if it does not. Also see [](./SSLTLS.md) to learn more about the SSL/TLS configuration.
127+
```
128+
125129
```yaml
126130
# MATLAB Production Server connection properties
127131
mps:
128-
protocol: http # Protocol used by the MPS Instance
129-
host: localhost # Hostname or IP of the MPS Instance
130-
port: 9910 # Port the MPS Instance runs on
131-
archive: demo # Name of the CTF containing the function which
132-
# is to be called on MPS when a message received
133-
function: MPSreceive # Function inside the archive which is to be called
134-
timeoutms: 120000 # Timeout on the request to MATLAB Production Server
135-
# MessageBroker will log an error if the request
136-
# to MATLAB Production Server did not complete within
137-
# this time
132+
protocol: http # Protocol used by the MPS Instance
133+
host: localhost # Hostname or IP of the MPS Instance
134+
port: 9910 # Port the MPS Instance runs on
135+
archive: demo # Name of the CTF containing the function which
136+
# is to be called on MPS when a message received
137+
function: MPSreceive # Function inside the archive which is to be called
138+
timeoutms: 120000 # Timeout on the request to MATLAB Production Server
139+
# MessageBroker will log an error if the request
140+
# to MATLAB Production Server did not complete within
141+
# this time
138142
139143
# Messaging connection and routing properties
140144
messageQueue:
141145
queue:
142-
name: RabbitMQ # Name of the Queue on RabbitMQ Server
143-
create: true # Creates/verifies whether queue exists
144-
durable: false # Work with a durable queue or not
145-
exclusive: false # Work with an exclusive queue or not
146-
autoDelete: false # Work with an auto delete queue or not
147-
arguments: # Set additional arguments, can be omitted entirely
148-
x-max-length: 42 # For example, set the maximum queue length
149-
host: localhost # Hostname or IP of the RabbitMQ Server
150-
port: 5672 # Port the RabbitMQ Server runs on
151-
virtualhost: / # RabbitMQ Virtual Host
146+
name: RabbitMQ # Name of the Queue on RabbitMQ Server
147+
create: true # Creates/verifies whether queue exists
148+
durable: false # Work with a durable queue or not
149+
exclusive: false # Work with an exclusive queue or not
150+
autoDelete: false # Work with an auto delete queue or not
151+
arguments: # Set additional arguments, can be omitted entirely
152+
x-max-length: 42 # For example, set the maximum queue length
153+
host: localhost # Hostname or IP of the RabbitMQ Server
154+
port: 5672 # Port the RabbitMQ Server runs on
155+
virtualhost: / # RabbitMQ Virtual Host
152156
credentials:
153-
username: guest # RabbitMQ username
154-
password: guest # RabbitMQ password
157+
username: guest # RabbitMQ username
158+
password: guest # RabbitMQ password
155159
exchange:
156-
name: amq.topic # Exchange to work with on RabbitMQ
157-
create: true # Creates/verifies whether exchange exists
158-
durable: true # Work with a durable exchange or not
159-
autoDelete: false # Work with an auto delete exchange or not
160-
internal: false # Work with an internal exchange or not
161-
arguments: # Set additional arguments, can be omitted entirely
162-
alternate-exchange: my-ea # For example alternate-exchange
163-
routingkey: test-topic # Routing key to subscribe to
160+
name: amq.topic # Exchange to work with on RabbitMQ
161+
create: true # Creates/verifies whether exchange exists
162+
durable: true # Work with a durable exchange or not
163+
autoDelete: false # Work with an auto delete exchange or not
164+
internal: false # Work with an internal exchange or not
165+
arguments: # Set additional arguments, can be omitted entirely
166+
alternate-exchange: my-ea # For example alternate-exchange
167+
routingkey: test-topic # Routing key to subscribe to
168+
sslcontext: # SSL/TLS Configuration, omit this section entirely when not working with SSL
169+
protocol: TLSv1.2 # Exact SSL/TLS protocol (version)
170+
server: # Server trust store configuration
171+
truststore: /some/location # Location of the trust store containing the server certificate chain
172+
passphrase: rabbitstore # Passphrase/password of the trust store
173+
type: JKS # Type of trust store
174+
hostnameVerification: true # Enable hostname verification
175+
client: # Client Certificate Configuration. Omit this section entirely if your server does not require client certificates
176+
keystore: /some/location # Location of the keystore containing client certificate and private key
177+
passphrase: supersecret # Passphrase/password of the keystore
178+
type: PKCS12 # Type of keystore
164179
```
165180
166181
```{note}

Documentation/SSLTLS.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# SSL/TLS Configuration
2+
3+
RabbitMQ supports [securing its (AMQP) channels using TLS](https://www.rabbitmq.com/docs/ssl). If working with such a TLS secured endpoint, the MATLAB RabbitMQ interface or MATLAB Production Server MessageBroker must explicitly be configured for this, in such cases you must:
4+
5+
1. Provide a trust store containing the server certificate chain and/or trusted root CAs, and
6+
2. Optionally provide a keystore containing the client certificate and private key if your server requires client certificates.
7+
8+
Since the MATLAB RabbitMQ interfaces build on top of the RabbitMQ Java libraries, the trust store and key store need to be provided in Java compatible formats. Typically the trust store is in `JKS` format (with no predefined extension) and the keystore can be provided as `PKCS12` file (typically with the `.pfx` or `.p12` extension).
9+
10+
```{hint}
11+
The server administrators who secured the RabbitMQ server with TLS in the first place, can likely help you with obtaining the correct certificates and keys, and in the right formats.
12+
13+
If you are not an expert in this area, it is typically recommended to reach out to the experts within your company rather than try to obtain and/or convert the certificates on your own.
14+
15+
Nevertheless some further hints and tips are provided below.
16+
```
17+
18+
## Trust Store
19+
20+
The Trust Store needs to contain the actual server certificate and/or chain and/or root CA(s) of the server which you want to connect to. The Trust Store is typically provided in `JKS` format. If you have a certificate (chain) in PEM-format instead, you can use Java's `keytool` to import it into a `JKS` Trust Store, for example:
21+
22+
```console
23+
$ keytool -importcert -file certificate.pem -keystore ./mytruststore -storetype JKS
24+
```
25+
26+
This will import the certificate(s) from `certificate.pem` into a new store in the current directory named `mytruststore`. `keytool` will ask for a new passphrase/password with which to secure this trust store.
27+
28+
## Key Store
29+
30+
If your server requires client certificates as well, you need to provide the client certificate and corresponding private key in the form of a `PKCS12` file; typically a file with `.p12` or `.pfx` extension. If you have the client certificate and corresponding key in two separate PEM-format files you will need to convert this to `PKCS12` format first, for example using the `openssl` commandline tool:
31+
32+
```console
33+
$ openssl pkcs12 -export -out client.p12 -inkey client_key.pem -in client_certificate.crt -CAfile CA.crt -chain
34+
```
35+
36+
This this the private key from the `client_key.pem` and certificate from `client_certificate.crt` and together with the CA certificate from `CA.crt` writes it out to `client.p12` in `PKCS12` format.
37+
38+
```{hint}
39+
Depending on the version(s) of tooling used, the (relatively old) Java Runtime as included with MATLAB by default, may not be able to read the client private key from the PKCS12 file. In such cases you may need to configure MATLAB to work with a newer (OpenJDK) Java Runtime, see:
40+
41+
* <https://www.mathworks.com/support/requirements/openjdk.html>
42+
* <https://www.mathworks.com/help/matlab/matlab_external/configure-your-system-to-use-java.html>
43+
```

0 commit comments

Comments
 (0)