Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@sdwilsh
Copy link
Contributor

@sdwilsh sdwilsh commented Oct 11, 2025

This change adds two new optional configuration options:

  • ldap_healthcheck_host to pair with ldap_host
  • http_healthcheck_host to pair with http_host

These new options will allow someone to specify a specific address for ldap_host and http_host and still have functional health checks, as health checks were previously hard-coded to check against localhost prior to this change. These new settings default to localhost to preserve the existing behavior.

Fixes #700

@sdwilsh sdwilsh marked this pull request as ready for review October 11, 2025 15:09
@coderabbitai
Copy link

coderabbitai bot commented Oct 11, 2025

πŸ“ Walkthrough

Walkthrough

Introduces health-check host configuration: adds public HealthcheckOptions (defaults to "localhost") and a healthcheck_options: HealthcheckOptions field on Configuration, with a ConfigOverrider to apply overrides. CLI gains a public HealthcheckOpts and a flattened RunOpts.healthcheck_opts mapped to env vars. Health-check functions change signatures to accept host: &str (check_ldap, check_ldaps, check_api), and main.rs passes config.healthcheck_options.{ldap_host,http_host} into those calls. The Docker template adds a commented healthcheck_options section. Timeouts and control flow are unchanged.


πŸ“œ Recent review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between ee48927 and fadfac1.

πŸ“’ Files selected for processing (5)
  • lldap_config.docker_template.toml (1 hunks)
  • server/src/cli.rs (2 hunks)
  • server/src/configuration.rs (4 hunks)
  • server/src/healthcheck.rs (3 hunks)
  • server/src/main.rs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • lldap_config.docker_template.toml
  • server/src/cli.rs
  • server/src/main.rs
  • server/src/configuration.rs
πŸ”‡ Additional comments (2)
server/src/healthcheck.rs (2)

73-74: LGTM: Tuple form handles IPv4/IPv6 correctly.

The tuple-based connection approach properly delegates IPv4/IPv6 resolution to the OS.


129-141: LGTM: Host parameter properly threaded through.

The tracing field update, TLS server name derivation, and tuple-based TCP connection all correctly use the configurable host parameter.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❀️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@sdwilsh sdwilsh marked this pull request as draft October 11, 2025 15:20
@sdwilsh sdwilsh marked this pull request as ready for review October 11, 2025 15:28
@sdwilsh
Copy link
Contributor Author

sdwilsh commented Oct 11, 2025

I can also update lldap_config.docker_template.toml, but wasn't sure if we wanted this additional complexity documented there or not, so I held off on doing so for now.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
server/src/healthcheck.rs (2)

129-150: LDAPS: fix IPv6 connect and robust SNI for IP addresses

  • Connecting via format!("{address}:{port}") breaks for IPv6. Use tuple form.
  • rustls::ServerName::try_from(address) may not accept IPs as strings. Prefer IpAddr when address is an IP.
-#[instrument(skip_all, level = "info", err, fields(address = %address, port = %ldaps_options.port))]
+#[instrument(skip_all, level = "info", err, fields(address = %address, port = %ldaps_options.port))]
 pub async fn check_ldaps(address: &str, ldaps_options: &LdapsOptions) -> Result<()> {
@@
-    let url = format!("{address}:{}", ldaps_options.port);
+    // Use tuple for IPv4/IPv6-safe connect
@@
-            .connect(
-                rustls::ServerName::try_from(address).context("while parsing the server name")?,
-                TcpStream::connect(&url)
+            .connect(
+                {
+                    if let Ok(ip) = address.parse::<std::net::IpAddr>() {
+                        rustls::ServerName::IpAddress(ip)
+                    } else {
+                        rustls::ServerName::try_from(address)
+                            .context("while parsing the server name")?
+                    }
+                },
+                TcpStream::connect((address, ldaps_options.port))
                     .await
                     .context("while connecting TCP")?,
             )

153-159: HTTP health URL fails for IPv6 literals

http://{address}:{port}/health needs brackets for IPv6. Build the URL accordingly.

-pub async fn check_api(address: &str, port: u16) -> Result<()> {
-    reqwest::get(format!("http://{address}:{port}/health"))
+pub async fn check_api(address: &str, port: u16) -> Result<()> {
+    let url = if address.parse::<std::net::IpAddr>().map(|ip| ip.is_ipv6()).unwrap_or(false) {
+        format!("http://[{address}]:{port}/health")
+    } else {
+        format!("http://{address}:{port}/health")
+    };
+    reqwest::get(url)
         .await?
         .error_for_status()?;
     info!("Success");
     Ok(())
 }
πŸ“œ Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 0967888 and 7d59b3f.

πŸ“’ Files selected for processing (4)
  • server/src/cli.rs (2 hunks)
  • server/src/configuration.rs (1 hunks)
  • server/src/healthcheck.rs (3 hunks)
  • server/src/main.rs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • server/src/main.rs

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
server/src/healthcheck.rs (1)

140-150: ServerName should not use bracketed IPv6.

Line 145 constructs ServerName from safe_address which includes brackets for IPv6 (e.g., [2001:db8::42]). TLS SNI expects a hostname or raw IP address, not URL-formatted brackets. This likely causes TLS connection failures for IPv6 addresses.

Apply this diff:

-    let safe_address = get_ipv6_safe_address(address);
-    let url = format!("{}:{}", safe_address, ldaps_options.port);
     check_ldap_endpoint(
         tls_connector
             .connect(
-                rustls::ServerName::try_from(safe_address.as_str())
+                rustls::ServerName::try_from(address)
                     .context("while parsing the server name")?,
-                TcpStream::connect(&url)
+                TcpStream::connect((address, ldaps_options.port))
                     .await
                     .context("while connecting TCP")?,
             )

This also switches TCP connect to tuple form (per the check_ldap discussion).

♻️ Duplicate comments (1)
server/src/healthcheck.rs (1)

73-78: Past review concern still applies: use tuple connect form.

The previous review correctly identified that tuple form TcpStream::connect((address, port)) is the idiomatic approach that handles IPv6 without string manipulation. While get_ipv6_safe_address works for URLs, it's unnecessary for TCP connect.

Apply this diff:

 pub async fn check_ldap(address: &str, port: u16) -> Result<()> {
     check_ldap_endpoint(
-        TcpStream::connect(format!("{}:{}", get_ipv6_safe_address(address), port)).await?,
+        TcpStream::connect((address, port)).await?,
     )
     .await
 }
🧹 Nitpick comments (1)
server/src/healthcheck.rs (1)

170-180: LGTM with minor style note.

Logic correctly handles hostnames, IPv4, IPv6, and prevents double-bracketing. The explicit return is idiomatic but optional in Rust.

Optional: Rust convention prefers implicit return:

 fn get_ipv6_safe_address(address: &str) -> String {
-    return if address
+    if address
         .parse::<std::net::IpAddr>()
         .map(|ip| ip.is_ipv6())
         .unwrap_or(false)
     {
         format!("[{address}]")
     } else {
         address.to_string()
-    };
+    }
 }
πŸ“œ Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 7d59b3f and 22c3659.

πŸ“’ Files selected for processing (1)
  • server/src/healthcheck.rs (3 hunks)
πŸ”‡ Additional comments (2)
server/src/healthcheck.rs (2)

158-168: LGTM!

HTTP URLs correctly require bracketed IPv6 literals, and get_ipv6_safe_address handles this properly.


182-196: LGTM!

Tests cover the essential cases (localhost, IPv4, IPv6) for the helper function.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
server/src/healthcheck.rs (1)

140-149: Simplify TCP connect and support IPv6 in ServerName

  • Use TcpStream::connect((address, ldaps_options.port)) instead of get_ipv6_url_safe_address + URL formatting.
  • Parse address as IpAddr and construct ServerName::IpAddress(ip) for literals, falling back to DNS names via ServerName::try_from.

Example diff:

-    let safe_address = get_ipv6_url_safe_address(address);
-    let url = format!("{}:{}", safe_address, ldaps_options.port);
-    check_ldap_endpoint(
-        tls_connector
-            .connect(
-                rustls::ServerName::try_from(address)
-                    .context("while parsing the server name")?,
-                TcpStream::connect(&url)
+    let server_name = match address.parse::<std::net::IpAddr>() {
+        Ok(ip) => rustls::ServerName::IpAddress(ip),
+        Err(_) => rustls::ServerName::try_from(address)
+            .context("while parsing the server name")?,
+    };
+    check_ldap_endpoint(
+        tls_connector
+            .connect(
+                server_name,
+                TcpStream::connect((address, ldaps_options.port))
     )
     .await
     .context("while connecting TLS")?,
 )
 .await
🧹 Nitpick comments (2)
server/src/healthcheck.rs (2)

73-78: IPv6 issue resolved; tuple form still preferred for TCP connect.

The get_ipv6_url_safe_address helper now correctly wraps IPv6 addresses in brackets, addressing the past review comment's concern. However, the tuple form TcpStream::connect((address, port)) remains cleanerβ€”it handles IPv4/IPv6 without needing the helper and is more idiomatic.

Apply this diff:

 pub async fn check_ldap(address: &str, port: u16) -> Result<()> {
-    check_ldap_endpoint(
-        TcpStream::connect(format!("{}:{}", get_ipv6_url_safe_address(address), port)).await?,
-    )
-    .await
+    check_ldap_endpoint(TcpStream::connect((address, port)).await?).await
 }

170-180: Consider adding a doc comment.

The logic is correct. A brief doc comment would clarify when to use this helper (HTTP URLs, display) versus the tuple form (TCP connections).

Example:

+/// Wraps IPv6 addresses in brackets for URL/display purposes.
+/// For TCP connections, prefer the tuple form `(address, port)` instead.
 fn get_ipv6_url_safe_address(address: &str) -> String {
πŸ“œ Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 22c3659 and e453916.

πŸ“’ Files selected for processing (1)
  • server/src/healthcheck.rs (3 hunks)
πŸ”‡ Additional comments (2)
server/src/healthcheck.rs (2)

158-168: Correct use of helper for HTTP URLs.

The helper function is correctly used hereβ€”HTTP URLs require brackets for IPv6 literals.


182-196: Tests cover key cases.

The tests verify localhost, IPv4, and IPv6 handling correctly.

Copy link
Member

@nitnelave nitnelave left a comment

Choose a reason for hiding this comment

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

The approach looks good, it just needs a bit of polishing.

Don't forget to add the arguments and their docs in the configuration template.

@nitnelave
Copy link
Member

I can also update lldap_config.docker_template.toml, but wasn't sure if we wanted this additional complexity documented there or not, so I held off on doing so for now.

Ah, I just saw your comment. Yes, we want docs there!

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

πŸ“œ Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between e453916 and 2e501ad.

πŸ“’ Files selected for processing (3)
  • lldap_config.docker_template.toml (2 hunks)
  • server/src/configuration.rs (2 hunks)
  • server/src/healthcheck.rs (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • server/src/configuration.rs
🧰 Additional context used
🧠 Learnings (1)
πŸ“š Learning: 2025-09-14T13:45:50.460Z
Learnt from: CR
PR: lldap/lldap#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-09-14T13:45:50.460Z
Learning: Applies to lldap_config.docker_template.toml : Use lldap_config.docker_template.toml as the reference starting point for new configurations

Applied to files:

  • lldap_config.docker_template.toml
πŸ”‡ Additional comments (6)
lldap_config.docker_template.toml (1)

34-37: LGTM!

The HTTP healthcheck documentation is clear and the variable name is correct.

server/src/healthcheck.rs (5)

73-75: LGTM!

Tuple form correctly handles both IPv4 and IPv6 addresses.


152-162: LGTM!

Correctly uses get_ipv6_url_safe_address to wrap IPv6 addresses in brackets for URL construction.


164-174: LGTM!

The helper correctly wraps IPv6 addresses in brackets for URLs while leaving hostnames and IPv4 addresses unchanged.


176-190: LGTM!

Tests cover localhost, IPv4, and IPv6 cases appropriately.


129-149: Verify IP address support in ServerName conversion.
rustls::ServerName::try_from(address) may reject IPv4/IPv6 literals; either parse address as IpAddr and use ServerName::IpAddress, or confirm your custom verifier permits IP endpoints.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

πŸ“œ Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 2696286 and ee48927.

πŸ“’ Files selected for processing (5)
  • lldap_config.docker_template.toml (1 hunks)
  • server/src/cli.rs (4 hunks)
  • server/src/configuration.rs (4 hunks)
  • server/src/healthcheck.rs (3 hunks)
  • server/src/main.rs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • lldap_config.docker_template.toml
  • server/src/configuration.rs
🧰 Additional context used
🧬 Code graph analysis (1)
server/src/main.rs (1)
server/src/healthcheck.rs (3)
  • check_ldap (73-75)
  • check_ldaps (130-149)
  • check_api (152-158)
πŸ”‡ Additional comments (2)
server/src/main.rs (1)

258-269: LGTM!

The healthcheck calls correctly pass the configured host addresses from config.healthcheck_options. Timeout and error handling remain unchanged.

server/src/healthcheck.rs (1)

73-74: LGTM!

The function signatures correctly accept host parameters and use them appropriately:

  • check_ldap and check_ldaps use tuple form (host, port) for TCP connections (handles IPv4/IPv6 correctly)
  • check_ldaps constructs ServerName from the provided host
  • check_api builds the health URL with the provided host

Also applies to: 129-141, 152-153

@sdwilsh sdwilsh requested a review from nitnelave October 14, 2025 03:59
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.

Bug: Listening to an address other than 127.0.0.1/32 or 0.0.0.0/32 breaks docker health checks

2 participants