Skip to content

Commit fe3c9f0

Browse files
Introduce 'federation enable_tls_peer_verification_for_all_upstreams'
1 parent c33f230 commit fe3c9f0

File tree

5 files changed

+421
-8
lines changed

5 files changed

+421
-8
lines changed

CHANGELOG.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,26 @@
44

55
### Enhancements
66

7+
* `federation enable_tls_peer_verification_for_all_upstreams` is a new command that enables TLS peer verification
8+
for all federation upstreams:
9+
10+
```shell
11+
# Note that the certificate and private key paths below refer
12+
# to the files deployed to the target RabbitMQ node(s), not to the
13+
# local files.
14+
#
15+
# As such, these arguments are command-specific and should not be confused
16+
# with the global `--tls-ca-cert-file`, `--tls-cert-file`, and `--tls-key-file`
17+
# arguments that are used by `rabbitmqadmin` itself to connect to the target node
18+
# over the HTTP API.
19+
rabbitmqadmin federation enable_tls_peer_verification_for_all_upstreams \
20+
--node-local-ca-certificate-bundle-path /path/to/node/local/ca_bundle.pem \
21+
--node-local-client-certificate-file-path /path/to/node/local/client_certificate.pem \
22+
--node-local-client-private-key-file-path /path/to/node/local/client_private_key.pem
23+
```
24+
25+
See [TLS guide](https://www.rabbitmq.com/docs/ssl#peer-verification) and [Federation guide](https://www.rabbitmq.com/docs/federation#tls-connections) to learn more.
26+
727
* `shovel disable_tls_peer_verification_for_all_source_uris` is a new command that disables TLS peer verification
828
for all shovel source URIs.
929

src/cli.rs

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3083,7 +3083,7 @@ pub fn shovel_subcommands(pre_flight_settings: PreFlightSettings) -> [Command; 7
30833083
.map(|cmd| cmd.infer_long_args(pre_flight_settings.infer_long_options))
30843084
}
30853085

3086-
fn federation_subcommands(pre_flight_settings: PreFlightSettings) -> [Command; 7] {
3086+
fn federation_subcommands(pre_flight_settings: PreFlightSettings) -> [Command; 8] {
30873087
let list_all_upstreams = Command::new("list_all_upstreams")
30883088
.long_about("Lists federation upstreams in all virtual hosts")
30893089
.after_help(color_print::cformat!(
@@ -3426,6 +3426,41 @@ fn federation_subcommands(pre_flight_settings: PreFlightSettings) -> [Command; 7
34263426
.after_help(color_print::cformat!(
34273427
r#"<bold>Doc guides</bold>:
34283428
3429+
* {}
3430+
* {}
3431+
* {}"#,
3432+
FEDERATION_GUIDE_URL,
3433+
TLS_GUIDE_URL,
3434+
"https://www.rabbitmq.com/docs/federation#tls-connections"
3435+
));
3436+
3437+
let enable_tls_peer_verification_cmd = Command::new("enable_tls_peer_verification_for_all_upstreams")
3438+
.about("Enables TLS peer verification for all federation upstreams with provided [RabbitMQ node-local] certificate paths.")
3439+
.long_about("Enables TLS peer verification for all federation upstreams by updating their 'verify' parameter and adding [RabbitMQ node-local] certificate and private key file paths.")
3440+
.arg(
3441+
Arg::new("node_local_ca_certificate_bundle_path")
3442+
.long("node-local-ca-certificate-bundle-path")
3443+
.help("Path to the CA certificate bundle file on the target RabbitMQ node(s)")
3444+
.required(true)
3445+
.value_name("PATH")
3446+
)
3447+
.arg(
3448+
Arg::new("node_local_client_certificate_file_path")
3449+
.long("node-local-client-certificate-file-path")
3450+
.help("Path to the client certificate file on the target RabbitMQ node(s)")
3451+
.required(true)
3452+
.value_name("PATH")
3453+
)
3454+
.arg(
3455+
Arg::new("node_local_client_private_key_file_path")
3456+
.long("node-local-client-private-key-file-path")
3457+
.help("Path to the client private key file on the target RabbitMQ node(s)")
3458+
.required(true)
3459+
.value_name("PATH")
3460+
)
3461+
.after_help(color_print::cformat!(
3462+
r#"<bold>Doc guides</bold>:
3463+
34293464
* {}
34303465
* {}
34313466
* {}"#,
@@ -3442,6 +3477,7 @@ fn federation_subcommands(pre_flight_settings: PreFlightSettings) -> [Command; 7
34423477
delete_upstream,
34433478
list_all_links,
34443479
disable_tls_peer_verification_cmd,
3480+
enable_tls_peer_verification_cmd,
34453481
]
34463482
.map(|cmd| cmd.infer_long_args(pre_flight_settings.infer_long_options))
34473483
}

src/commands.rs

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,80 @@ pub fn disable_tls_peer_verification_for_all_federation_upstreams(
733733
Ok(())
734734
}
735735

736+
pub fn enable_tls_peer_verification_for_all_federation_upstreams(
737+
client: APIClient,
738+
args: &ArgMatches,
739+
) -> Result<(), CommandRunError> {
740+
let ca_cert_path = args
741+
.get_one::<String>("node_local_ca_certificate_bundle_path")
742+
.ok_or_else(|| CommandRunError::MissingArgumentValue {
743+
property: "node_local_ca_certificate_bundle_path".to_string(),
744+
})?;
745+
let client_cert_path = args
746+
.get_one::<String>("node_local_client_certificate_file_path")
747+
.ok_or_else(|| CommandRunError::MissingArgumentValue {
748+
property: "node_local_client_certificate_file_path".to_string(),
749+
})?;
750+
let client_key_path = args
751+
.get_one::<String>("node_local_client_private_key_file_path")
752+
.ok_or_else(|| CommandRunError::MissingArgumentValue {
753+
property: "node_local_client_private_key_file_path".to_string(),
754+
})?;
755+
756+
let upstreams = client.list_federation_upstreams()?;
757+
758+
for upstream in upstreams {
759+
let original_uri = &upstream.uri;
760+
let updated_uri = enable_tls_peer_verification(
761+
original_uri,
762+
ca_cert_path,
763+
client_cert_path,
764+
client_key_path,
765+
)?;
766+
767+
if original_uri != &updated_uri {
768+
let upstream_params = FederationUpstreamParams {
769+
name: &upstream.name,
770+
vhost: &upstream.vhost,
771+
uri: &updated_uri,
772+
prefetch_count: upstream
773+
.prefetch_count
774+
.unwrap_or(DEFAULT_FEDERATION_PREFETCH),
775+
reconnect_delay: upstream.reconnect_delay.unwrap_or(5),
776+
ack_mode: upstream.ack_mode,
777+
trust_user_id: upstream.trust_user_id.unwrap_or_default(),
778+
bind_using_nowait: upstream.bind_using_nowait,
779+
channel_use_mode: upstream.channel_use_mode,
780+
queue_federation: if upstream.queue.is_some() {
781+
Some(QueueFederationParams {
782+
queue: upstream.queue.as_deref(),
783+
consumer_tag: upstream.consumer_tag.as_deref(),
784+
})
785+
} else {
786+
None
787+
},
788+
exchange_federation: if upstream.exchange.is_some() {
789+
Some(ExchangeFederationParams {
790+
exchange: upstream.exchange.as_deref(),
791+
max_hops: upstream.max_hops,
792+
queue_type: upstream.queue_type.unwrap_or(QueueType::Classic),
793+
ttl: upstream.expires,
794+
message_ttl: upstream.message_ttl,
795+
resource_cleanup_mode: upstream.resource_cleanup_mode,
796+
})
797+
} else {
798+
None
799+
},
800+
};
801+
802+
let param = RuntimeParameterDefinition::from(upstream_params);
803+
client.upsert_runtime_parameter(&param)?;
804+
}
805+
}
806+
807+
Ok(())
808+
}
809+
736810
pub fn disable_tls_peer_verification_for_all_source_uris(
737811
client: APIClient,
738812
) -> Result<(), CommandRunError> {
@@ -1986,3 +2060,26 @@ fn disable_tls_peer_verification(uri: &str) -> Result<String, CommandRunError> {
19862060
message: format!("Failed to reconstruct (modify) a URI: {}", e),
19872061
})
19882062
}
2063+
2064+
fn enable_tls_peer_verification(
2065+
uri: &str,
2066+
ca_cert_path: &str,
2067+
client_cert_path: &str,
2068+
client_key_path: &str,
2069+
) -> Result<String, CommandRunError> {
2070+
use rabbitmq_http_client::uris::UriBuilder;
2071+
2072+
let ub = UriBuilder::new(uri)
2073+
.map_err(|e| CommandRunError::FailureDuringExecution {
2074+
message: format!("Could not parse a value as a URI '{}': {}", uri, e),
2075+
})?
2076+
.with_tls_peer_verification(TlsPeerVerificationMode::Enabled)
2077+
.with_ca_cert_file(ca_cert_path)
2078+
.with_client_cert_file(client_cert_path)
2079+
.with_client_key_file(client_key_path);
2080+
2081+
ub.build()
2082+
.map_err(|e| CommandRunError::FailureDuringExecution {
2083+
message: format!("Failed to reconstruct (modify) a URI: {}", e),
2084+
})
2085+
}

src/main.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,13 @@ fn dispatch_common_subcommand(
673673
commands::disable_tls_peer_verification_for_all_federation_upstreams(client);
674674
res_handler.no_output_on_success(result);
675675
}
676+
("federation", "enable_tls_peer_verification_for_all_upstreams") => {
677+
let result = commands::enable_tls_peer_verification_for_all_federation_upstreams(
678+
client,
679+
second_level_args,
680+
);
681+
res_handler.no_output_on_success(result);
682+
}
676683
("get", "messages") => {
677684
let result = commands::get_messages(client, &vhost, second_level_args);
678685
res_handler.tabular_result(result)

0 commit comments

Comments
 (0)