Problem: when developing self-signed certificate is used and SBA Server can be localhost or LAN ip.
Then SBA client cannot connect to SBA server
09:23:39.045 [registrationTask1] WARN d.c.b.a.c.r.ApplicationRegistrator#register:94 - Failed to register application as Application ... : I/O error on POST request for "https://10.10.10.90:9000/api/applications": java.security.cert.CertificateException: No subject alternative names present; nested exception is javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative names present. Further attempts are logged on DEBUG level
When looking for solutions, e.g. below, they point to disabling host verification for whole app.
However it should be possible to disable/overwrite such check for SBA client only, i.e. not effecting other parts of project application.
HttpsURLConnection.setDefaultHostnameVerifier(
SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
Other option may be to import certificate used by SBA server,
but again it should be affecting only SBA client, not the rest of project application.
Trying to use NoopHostnameVerifier as configuration before Spring context loading, had other exception
Code
//FIXME this should be for SBA client only
HttpsURLConnection.setDefaultHostnameVerifier(
//SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER
// * @deprecated (4.4) Use {@link org.apache.http.conn.ssl.NoopHostnameVerifier}
new NoopHostnameVerifier()
);
Exception
10:24:00.931 [registrationTask1] WARN d.c.b.a.c.r.ApplicationRegistrator#register:94 - Failed to register application as Application [name=...] at spring-boot-admin ([https://10.10.10.90:9000/api/applications]): I/O error on POST request for "https://10.10.10.90:9000/api/applications": sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target; nested exception is javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target. Further attempts are logged on DEBUG level
Instantiate the ApplicationRegistrator bean using a custom configured RestTemplate, the client's autoconfig will back off then.
OK, need to try...
Still in progress.
Could not yet succeed with RestTemplate
public static void main(String[] args) {
// we are using httpclient 4.5.6.
CloseableHttpClient httpClient = HttpClients.custom()
.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE).build();
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
requestFactory.setHttpClient(httpClient);
RestTemplate restTemplate = new RestTemplate(requestFactory);
String url ="https://10.10.10.10:9000";
String response = restTemplate.getForObject(url, String.class);
//Exception in thread "main" org.springframework.web.client.ResourceAccessException: I/O error on GET request for "https://10.10.10.10:9000":
// sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException:
// unable to find valid certification path to requested target; nested exception is javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException:
// PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
}
@patrick-vonsteht you just disabled the hostname verification, the trust chain is still validated, but this fails.
OK, I succeeded with custom restTemplate (see code below),
but there is problem with ApplicationRegistrator instantiation:
Field admin in com.company.SBAConfig required a bean of type 'de.codecentric.boot.admin.client.config.AdminProperties' that could not be found.
@Component
public class SBAConfig { // restTemplate with TrustSelfSignedStrategy
@Autowired
AdminProperties admin;
@Autowired
ApplicationFactory applicationFactory;
private static RestTemplate restTemplate = getCustomRestTemplate();
//Field admin in SBAConfig required a bean of type 'de.codecentric.boot.admin.client.config.AdminProperties' that could not be found.
@Bean
public ApplicationRegistrator getCustomApplicationRegistrator(){
return new ApplicationRegistrator(restTemplate, admin, applicationFactory);
}
static RestTemplate getCustomRestTemplate(){
// https://stackoverflow.com/questions/19517538/ignoring-ssl-certificate-in-apache-httpclient-4-3
SSLContextBuilder builder = new SSLContextBuilder();
try {
builder.loadTrustMaterial(null, new TrustSelfSignedStrategy()); // disable trust chain validation
// to solve
// PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
} catch (KeyStoreException e) {
e.printStackTrace();
return null;
}
SSLContext sslContext = null;
try {
sslContext = builder.build();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
} catch (KeyManagementException e) {
e.printStackTrace();
return null;
}
//SSLConnectionSocketFactory sslsf1 = new SSLConnectionSocketFactory(sslContext); //disable chain validation, but still has hostname validation:
SSLConnectionSocketFactory sslsf2 = new SSLConnectionSocketFactory( sslContext, new X509HostnameVerifier() {
@Override
public void verify(String host, SSLSocket ssl)
throws IOException {
}
@Override
public void verify(String host, X509Certificate cert)
throws SSLException {
}
@Override
public void verify(String host, String[] cns,
String[] subjectAlts) throws SSLException {
}
@Override
public boolean verify(String s, SSLSession sslSession) {
return true;
}
});
// we are using httpclient 4.5.6.
CloseableHttpClient httpClient = HttpClients.custom()
//.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE) // disable the hostname verification
.setSSLSocketFactory(sslsf2)
.build();
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
requestFactory.setHttpClient(httpClient);
RestTemplate restTemplate = new RestTemplate(requestFactory);
return restTemplate;
} // getCustomRestTemplate()
// for testing custom RestTemplate
public static void main(String[] args){
restTemplate = getCustomRestTemplate();
String url ="https://10.10.10.10:9000";
String response = restTemplate.getForObject(url, String.class);
// AdminProperties admin = null;
// ApplicationFactory applicationFactory = null;
//
// ApplicationRegistrator applicationRegistrator = new ApplicationRegistrator(restTemplate, admin, applicationFactory);
}
}
@joshiste Continuing from https://github.com/codecentric/spring-boot-admin/commit/60c027e2a337df61d591bf620bf360188c39e2ba
Just use the
DefaultApplicationFactoryprovided by sba client
How to use it? It requires even more classes to be created.
public DefaultApplicationFactory(AdminClientProperties client,
ManagementServerProperties management,
ServerProperties server,
ServletContext servletContext,
String healthEndpointPath) {
See above @Bean creation it fails over 'AdminProperties', now there would be even more.
Should be some correct and easy way....
Yeah you need to add a @EnableConfigurationPropreties for these..
With 2.2.0 it will be easier to customize this as you don't need to instantiate the factory, just a thin wrapper class wrapping the RestTemplate....
I should probably stop here with SBA completely,
as I am spending much more time for it, than getting value from it.
( leaving managements port of apps and SBA server unsecured even during development is not option )
and dev VM don't have fixed names that a certificate should prove.
For those who might follow, there is SpringBootAdminClientAutoConfiguration.java to look at
(choose carefully used version)
( found via https://github.com/codecentric/spring-boot-admin/commit/e5bb797c1c107a66b5b53a764da0c8d2e3267d8d )
and RestTemplate getCustomRestTemplate() suggested and implemented above has no use,
as it actually should be RestTemplateBulder to fit instatiation of ApplicationRegistrator.
Hello @joshiste ,
Thank you for this very cool project.
You said, on March 8: "Instantiate the ApplicationRegistrator bean using a custom configured RestTemplate, the client's autoconfig will back off then."
Would you have any example of this?
Because you give many examples over http (again many thanks, it helps a lot) but as soon as we want to do a two way TLS SBA server <-> client, there is no more documentations.
Also, you said on March 19th:"Yeah you need to add a @EnableConfigurationPropreties for these..
With 2.2.0 it will be easier to customize this as you don't need to instantiate the factory, just a thin wrapper class wrapping the RestTemplate...."
And I downloaded 2.2, fixed all the dependency errors, but cannot see what 2.2 will fix it.
Can you please provide a bit of help?
Thank you
@patpatpat123 With 2.2.x depending on wether you have a traditional or a reactive application you need to instantiate the either the BlockingRegistrationClient or ReactiveRegistrationClient yourself with a custom RestTemplate or `WebClient'.
Hello @joshiste ,
Thank you for your answer.
I join paulvi comment about SBA.
It is a real struggle to enable two way TLS and to rewrite this ApplicationRegistrator.
Even if the custom RestTemplate is written, injecting it to the ApplicationRegistrator is a tedious task.
The examples purely with http are really good though.
Thank you
In prometheus, it's as simple as:
tls_config:
insecure_skip_verify: true
I'd think something this common should also be a setting in SBA.
Most helpful comment
Hello @joshiste ,
Thank you for your answer.
I join paulvi comment about SBA.
It is a real struggle to enable two way TLS and to rewrite this ApplicationRegistrator.
Even if the custom RestTemplate is written, injecting it to the ApplicationRegistrator is a tedious task.
The examples purely with http are really good though.
Thank you