-
Notifications
You must be signed in to change notification settings - Fork 14
Support trusting Aspire-mapped ASP.NET Core dev certs #52
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
28fae7f
e4493ac
5ce7172
58d5ae6
01cfbdf
eff495c
8c58e1c
88b49e7
2956bc1
8c9534c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,3 @@ | ||
| *.jar binary | ||
| * text eol=lf | ||
| *.patch text eol=lf |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| # Agent Instructions and Reminders | ||
|
|
||
| This file contains important reminders and guidelines for AI agents working on this codebase. | ||
|
|
||
| ## Build Script | ||
|
|
||
| ### Avoid `-DisableCache` Flag | ||
|
|
||
| **Do NOT use `-DisableCache`** when running `build.ps1` from agentic contexts. The `start.spring.io` service may block or rate-limit automated traffic, causing connection failures. | ||
|
|
||
| Instead, to get a fresh build: | ||
|
|
||
| 1. Delete the expanded project folder (e.g., `workspace/springbootadmin/`) | ||
| 2. Run `.\build.ps1 <image-name>` without the flag | ||
|
|
||
| ### Testing Changes | ||
|
|
||
| Before submitting patch changes: | ||
|
|
||
| 1. Run a dry-run of each patch: `git apply --check <patch-file>` | ||
| 2. If dry-run succeeds, run the full build and verify Java compilation | ||
| 3. Test the resulting Docker image with a real client app | ||
|
|
||
| ## Patch Files | ||
|
|
||
| The build script uses `git apply --unidiff-zero --recount --ignore-whitespace` to apply patches, which is more forgiving than the traditional `patch` command. | ||
|
|
||
| ### Patch Format Rules | ||
|
|
||
| 1. **Hunk headers should be accurate**: The format is `@@ -old_start,old_count +new_start,new_count @@` | ||
| - `old_count` is the number of lines in the hunk from the old file (context lines plus lines with `-` prefix) | ||
| - `new_count` is the number of lines in the hunk in the new file (context lines plus lines with `+` prefix) | ||
| - For new file patches (`--- /dev/null`), `old_count` is 0 and `new_count` is the total number of lines in the new-file hunk | ||
| - Note: `--recount` will automatically correct line counts, but keeping them accurate is still good practice | ||
| 2. **Trailing newlines are required**: Patch files must end with a newline character. | ||
| 3. **Preserve exact whitespace**: Context lines must match the target file exactly, including trailing spaces and tabs. The `--ignore-whitespace` flag provides some tolerance but exact matches are preferred. | ||
| 4. **New file patches**: Use `/dev/null` as the old file: | ||
|
|
||
| ```diff | ||
| --- /dev/null | ||
| +++ ./path/to/NewFile.java 2026-01-27 00:00:00.000000000 +0000 | ||
| @@ -0,0 +1,N @@ | ||
| +line 1 | ||
| +line 2 | ||
| ... | ||
| ``` | ||
|
|
||
| ### Example | ||
|
|
||
| If a patch adds 1 line, the hunk header should reflect this: | ||
|
|
||
| ```diff | ||
| -@@ -37,3 +37,10 @@ | ||
| +@@ -37,3 +37,11 @@ | ||
| ``` | ||
|
|
||
| ### Why This Matters | ||
|
|
||
| While `git apply --recount` can fix minor line count issues, keeping patches accurate ensures reliable application and easier debugging. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1 @@ | ||
| 1 | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1 @@ | ||
| 4.3.0 | ||
| 4.3.1 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1 @@ | ||
| 3.5.6 | ||
| 3.5.10 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,13 +1,14 @@ | ||
| --- ./build.gradle 2025-09-30 14:48:20.000000000 -0500 | ||
| +++ ./build.gradle 2025-09-30 14:49:16.584226000 -0500 | ||
| @@ -41,3 +41,10 @@ | ||
| @@ -41,3 +41,11 @@ | ||
| tasks.named('test') { | ||
| useJUnitPlatform() | ||
| } | ||
| + | ||
| +bootBuildImage { | ||
| + createdDate = "now" | ||
| + environment = [ | ||
| + "BP_SPRING_CLOUD_BINDINGS_DISABLED": "true" | ||
| + "BP_SPRING_CLOUD_BINDINGS_DISABLED": "true", | ||
| + "BP_JVM_AOTCACHE_ENABLED": "true" | ||
| + ] | ||
| +} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| 1 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1 @@ | ||
| 3.5.6 | ||
| 3.5.10 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,13 +1,14 @@ | ||
| --- ./build.gradle 2025-09-30 14:48:20.000000000 -0500 | ||
| +++ ./build.gradle 2025-09-30 14:49:16.584226000 -0500 | ||
| @@ -41,3 +41,10 @@ | ||
| @@ -41,3 +41,11 @@ | ||
| tasks.named('test') { | ||
| useJUnitPlatform() | ||
| } | ||
| + | ||
| +bootBuildImage { | ||
| + createdDate = "now" | ||
| + environment = [ | ||
| + "BP_SPRING_CLOUD_BINDINGS_DISABLED": "true" | ||
| + "BP_SPRING_CLOUD_BINDINGS_DISABLED": "true", | ||
| + "BP_JVM_AOTCACHE_ENABLED": "true" | ||
| + ] | ||
| +} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1 @@ | ||
| 3.5.5 | ||
| 3.5.7 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1 @@ | ||
| 3.5.6 | ||
| 3.5.10 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,6 @@ | ||
| --- ./src/main/resources/application.properties 2025-10-01 14:13:49.968047867 -0500 | ||
| +++ ./src/main/resources/application.properties 2025-10-01 14:13:24.727639700 -0500 | ||
| @@ -0,0 +1,2 @@ | ||
| +++ ./src/main/resources/application.properties 2026-01-27 00:00:00.000000000 -0500 | ||
| @@ -0,0 +1,3 @@ | ||
| +server.port=9099 | ||
| +spring.thymeleaf.check-template-location=false | ||
| +logging.level.io.steeltoe.docker=INFO |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,13 +1,14 @@ | ||
| --- ./build.gradle 2025-09-22 14:48:20.000000000 -0500 | ||
| +++ ./build.gradle 2026-01-27 00:00:00.000000000 -0500 | ||
| @@ -38,3 +38,10 @@ | ||
| @@ -38,3 +38,11 @@ | ||
| tasks.named('test') { | ||
| useJUnitPlatform() | ||
| } | ||
| + | ||
| +bootBuildImage { | ||
| + createdDate = "now" | ||
| + environment = [ | ||
| + "BP_SPRING_CLOUD_BINDINGS_DISABLED": "true" | ||
| + "BP_SPRING_CLOUD_BINDINGS_DISABLED": "true", | ||
| + "BP_NATIVE_IMAGE_BUILD_ARGUMENTS": "-H:+UnlockExperimentalVMOptions" | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. According to https://answers.ycrash.io/question/what-is-unlock-experimental-vm-options--xxunlockexperimentalvmoptions?q=702:
Do we really need this?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added We could remove it and just ignore the warning. Here's an explanation of what that does:
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it would be safer not to enable experimental features unless they negatively affect our usage beyond the warning. |
||
| + ] | ||
| +} | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,13 +1,13 @@ | ||
| --- ./src/main/java/io/steeltoe/docker/springbootadmin/SpringBootAdmin.java 2024-09-20 12:49:35.099908129 -0500 | ||
| +++ ./src/main/java/io/steeltoe/docker/springbootadmin/SpringBootAdmin.java 2024-09-20 12:49:59.410273961 -0500 | ||
| @@ -2,8 +2,10 @@ | ||
| +++ ./src/main/java/io/steeltoe/docker/springbootadmin/SpringBootAdmin.java 2026-01-27 00:00:00.000000000 -0500 | ||
| @@ -2,7 +2,11 @@ | ||
|
|
||
| import org.springframework.boot.SpringApplication; | ||
| import org.springframework.boot.autoconfigure.SpringBootApplication; | ||
| +import org.springframework.context.annotation.Import; | ||
| +import de.codecentric.boot.admin.server.config.EnableAdminServer; | ||
|
|
||
| @SpringBootApplication | ||
| +@EnableAdminServer | ||
| +@Import(SteeltoeAdminConfiguration.class) | ||
| public class SpringBootAdmin { | ||
|
|
||
| public static void main(String[] args) { |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,82 @@ | ||
| --- /dev/null | ||
| +++ ./src/main/java/io/steeltoe/docker/springbootadmin/SpringBootAdminSslConfiguration.java 2026-01-27 00:00:00.000000000 +0000 | ||
| @@ -0,0 +1,79 @@ | ||
| +package io.steeltoe.docker.springbootadmin; | ||
| + | ||
| +import org.slf4j.Logger; | ||
| +import org.slf4j.LoggerFactory; | ||
| +import org.springframework.beans.factory.ObjectProvider; | ||
| +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; | ||
| +import org.springframework.context.annotation.Bean; | ||
| +import org.springframework.context.annotation.Configuration; | ||
| +import org.springframework.http.client.reactive.ClientHttpConnector; | ||
| +import org.springframework.http.client.reactive.ReactorClientHttpConnector; | ||
| +import io.netty.handler.ssl.SslContext; | ||
| +import reactor.netty.http.client.HttpClient; | ||
| +import reactor.netty.tcp.SslProvider; | ||
| +import reactor.netty.tcp.TcpSslContextSpec; | ||
| + | ||
| +import javax.net.ssl.X509TrustManager; | ||
| + | ||
| +/** | ||
| + * Spring Boot Admin SSL Configuration | ||
| + * | ||
| + * Configures Spring Boot Admin's WebClient to use the shared SSL trust manager | ||
| + * for trusting development certificates (e.g., ASP.NET Core development certificates). | ||
| + * | ||
| + * Uses ObjectProvider for AOT compatibility - the trust manager is resolved at runtime | ||
| + * when the bean method is called, not at configuration class construction time. | ||
| + */ | ||
| +@Configuration | ||
| +public class SpringBootAdminSslConfiguration { | ||
| + | ||
| + private static final Logger logger = LoggerFactory.getLogger(SpringBootAdminSslConfiguration.class); | ||
| + private final ObjectProvider<X509TrustManager> trustManagerProvider; | ||
| + | ||
| + public SpringBootAdminSslConfiguration(ObjectProvider<X509TrustManager> trustManagerProvider) { | ||
| + this.trustManagerProvider = trustManagerProvider; | ||
| + } | ||
| + | ||
| + /** | ||
| + * Provides a ClientHttpConnector with custom SSL trust for Spring Boot Admin's WebClient. | ||
| + * | ||
| + * Uses ObjectProvider to defer trust manager resolution until runtime, making this | ||
| + * AOT-compatible. The trust manager is resolved when this bean method is called, | ||
| + * not during AOT processing at build time. | ||
| + */ | ||
| + @Bean | ||
| + @ConditionalOnMissingBean(ClientHttpConnector.class) | ||
| + public ClientHttpConnector clientHttpConnector() { | ||
| + logger.info("Configuring Spring Boot Admin WebClient with SSL trust support"); | ||
| + X509TrustManager trustManager = trustManagerProvider.getIfAvailable(); | ||
| + | ||
| + if (trustManager == null) { | ||
| + logger.debug("No custom X509TrustManager available, using default SSL configuration"); | ||
| + return new ReactorClientHttpConnector(HttpClient.create()); | ||
| + } | ||
| + | ||
| + try { | ||
| + logger.info("Using custom X509TrustManager for Spring Boot Admin WebClient"); | ||
| + // Build SslContext first to avoid deprecated sslContext(ProtocolSslContextSpec) method | ||
| + SslContext sslContext = TcpSslContextSpec.forClient() | ||
| + .configure(sslContextBuilder -> { | ||
| + sslContextBuilder.trustManager(trustManager); | ||
| + }) | ||
| + .sslContext(); | ||
| + | ||
| + SslProvider sslProvider = SslProvider.builder() | ||
| + .sslContext(sslContext) | ||
| + .build(); | ||
| + | ||
| + HttpClient httpClient = HttpClient.create() | ||
| + .secure(sslProvider); | ||
| + | ||
| + logger.debug("Configured Spring Boot Admin WebClient with custom SSL trust"); | ||
| + return new ReactorClientHttpConnector(httpClient); | ||
| + } catch (Exception e) { | ||
| + logger.error("Failed to configure SSL trust for Spring Boot Admin WebClient, using default", e); | ||
| + // Fall back to default connector if SSL configuration fails | ||
| + return new ReactorClientHttpConnector(HttpClient.create()); | ||
| + } | ||
| + } | ||
| +} |
Uh oh!
There was an error while loading. Please reload this page.