Skip to content

feat: wire up insecure TLS option for S3 client#17

Merged
overtrue merged 6 commits intomainfrom
copilot/add-insecure-option-to-rc-command
Feb 24, 2026
Merged

feat: wire up insecure TLS option for S3 client#17
overtrue merged 6 commits intomainfrom
copilot/add-insecure-option-to-rc-command

Conversation

Copy link
Contributor

Copilot AI commented Feb 24, 2026

  • Explore codebase to understand structure
  • Add aws-smithy-runtime-api and bytes to workspace/crate dependencies
  • Implement ReqwestConnector as a custom HttpConnector + HttpClient for AWS SDK
  • Use ReqwestConnector with danger_accept_invalid_certs(true) when alias.insecure = true
  • Also wire up ca_bundle support for custom CA certificates in S3 client
  • Add tracing warnings for non-convertible headers
  • Update doc comment to mention both insecure and ca_bundle activation conditions
  • Add note about HttpConnectorSettings not being applied
  • Switch CA bundle read from blocking std::fs::read to async tokio::fs::read
  • Fix streaming body: return ConnectorError instead of silently sending empty body
  • Make unit tests async (#[tokio::test]) to match async new() constructor
  • All tests pass (19/19), clippy clean, fmt clean
Original prompt

This section details on the original issue you should resolve

<issue_title>insecure option</issue_title>
<issue_description>The rc command does not have an "insecure" option.

If a self-signed certificate is used, the following error message is displayed.

Error message: ✗ Failed to list buckets: Network error: dispatch failure

I would like the insecure option to be added.

rustfs cli: v0.1.3
rustfs: 1.0.0-alpha.82</issue_description>

Comments on the Issue (you are @copilot in this section)


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

When an alias is configured with `insecure = true` (via `rc alias set
--insecure`), the S3 client now uses a reqwest-based HTTP connector
that calls `danger_accept_invalid_certs(true)`, allowing connections
to servers using self-signed TLS certificates.

Also supports `ca_bundle` for custom CA certificate bundles.

Implements the custom connector by wrapping reqwest::Client in the
aws-smithy-runtime-api HttpConnector and HttpClient traits, and wiring
it into the aws-config builder when insecure mode or ca_bundle is set.

Co-authored-by: overtrue <1472352+overtrue@users.noreply.github.com>
@overtrue overtrue marked this pull request as ready for review February 24, 2026 04:54
Copilot AI review requested due to automatic review settings February 24, 2026 04:54
Copilot AI changed the title [WIP] Add insecure option to rc command feat: wire up insecure TLS option for S3 client Feb 24, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds TLS flexibility to the S3 client layer by introducing a reqwest-based AWS SDK HTTP connector that can (optionally) skip certificate verification and/or trust a custom CA bundle, enabling use against self-signed or privately-issued endpoints.

Changes:

  • Implement ReqwestConnector implementing Smithy HttpConnector + HttpClient to back the AWS SDK with reqwest.
  • Select the custom connector when alias.insecure is enabled or when alias.ca_bundle is provided.
  • Add workspace/crate dependencies for aws-smithy-runtime-api and bytes (and update lockfile).

Reviewed changes

Copilot reviewed 3 out of 4 changed files in this pull request and generated 5 comments.

File Description
crates/s3/src/client.rs Adds reqwest-based Smithy HTTP connector and wires it into S3 client config based on alias TLS options.
crates/s3/Cargo.toml Adds new dependencies required by the custom connector.
Cargo.toml Adds workspace dependency versions for aws-smithy-runtime-api and bytes.
Cargo.lock Lockfile updates for the new dependencies.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 35 to 41
if let Some(bundle_path) = ca_bundle {
let pem = std::fs::read(bundle_path).map_err(|e| {
Error::Network(format!("Failed to read CA bundle '{bundle_path}': {e}"))
})?;
let cert = reqwest::Certificate::from_pem(&pem)
.map_err(|e| Error::Network(format!("Invalid CA bundle '{bundle_path}': {e}")))?;
builder = builder.add_root_certificate(cert);
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ReqwestConnector::new reads the CA bundle using std::fs::read, which is a blocking filesystem call. Since this is invoked from async code (S3Client::new), consider switching to tokio::fs::read or spawn_blocking to avoid blocking the async runtime thread, especially if aliases are created on-demand.

Copilot uses AI. Check for mistakes.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in ae82923. ReqwestConnector::new is now async fn and uses tokio::fs::read(...).await instead of the blocking std::fs::read. The call site in S3Client::new has been updated to .await? accordingly.

Comment on lines 59 to 63
let body_bytes = request
.body()
.bytes()
.map(Bytes::copy_from_slice)
.unwrap_or_default();
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

request.body().bytes().unwrap_or_default() silently turns any non-buffered/streaming request body into an empty body. That can break operations that use streaming bodies (e.g., future uploads/multipart) and can lead to signature mismatches or server-side errors. Prefer handling the streaming case explicitly (buffer the body, or return a ConnectorError indicating unsupported streaming) rather than defaulting to empty.

Copilot uses AI. Check for mistakes.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in ae82923. request.body().bytes().unwrap_or_default() is replaced with a match that returns a clear ConnectorError::user(...) when bytes() is None (streaming body), rather than silently sending an empty body.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was already addressed in ae82923. The unwrap_or_default() is replaced with a match that returns a clear ConnectorError::user(...) when bytes() is None (streaming body).

overtrue and others added 4 commits February 24, 2026 14:10
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: 安正超 <anzhengchao@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: 安正超 <anzhengchao@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: 安正超 <anzhengchao@gmail.com>
- Switch CA bundle file read from std::fs::read (blocking) to
  tokio::fs::read (async), avoiding blocking the async runtime
- Fix streaming body handling: return a clear ConnectorError instead
  of silently sending an empty body when request.body().bytes() is None
- Make ReqwestConnector::new() async and update call site to .await
- Convert unit tests to #[tokio::test] async fns to match async new()
- Remove the unreliable reqwest_connector_invalid_ca_bundle_contents
  test: reqwest with rustls does not validate certificate DER content
  at build time, making this test non-deterministic across versions

Co-authored-by: overtrue <1472352+overtrue@users.noreply.github.com>
@overtrue overtrue merged commit a78a05f into main Feb 24, 2026
14 checks passed
@overtrue overtrue deleted the copilot/add-insecure-option-to-rc-command branch February 24, 2026 07:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

insecure option

3 participants