spring boot actuator endpoints unavailable after (2.5) uprade - spring-boot

I have attempted to take advice offered for similar problems; to no avail. Can someone please explain a resolution for this problem, as if I were six?
I've upgraded my version of spring boot to 2.5. All tests in my suite still pass, except for this #Springboot test:
#Test
void readActuatorInfo_success() throws Exception {
mockMvc.perform(
get("/actuator/info")
.header("Authorization", "Basic dXNlcjpwYXNzd29yZA=="))
.andExpect(status().isOk());
}
It fails because the response is 404. Now, I know that springboot does not, by default, expose the endpoints, that they must be explicitly configured. For example, the following yaml should do it, but no. Any tips?
application:
endpoint:
info:
enabled: true
To be clear, this test passed for Springboot 2.3

From 2.5 onwards the Info endpoint is no longer exposed by default,
The /info actuator endpoint is no longer exposed over the web by default. Additionally, if Spring Security is on the classpath and your application doesn’t have a custom security configuration, the endpoint requires authenticated access by default.
Refer to the documentation on exposing and securing actuator endpoints to change these new defaults.
https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.5-Release-Notes#secure-info-endpoint
management:
endpoint:
web:
exposure: "health,info"

Related

blocked:mixed-content error after spring boot upgrade

I have upgraded some micro services that talk to each other from Spring Boot 1.5.3 to 2.3.5.
Now when my micro service A calls micro service B, the call fails with the following status
on the network tab of chrome's developer tools (blocked:mixed-content)
I am not sure what has changed that I start getting this error.
In browser's console I get the below error:
Mixed Content: The page at 'https://gateway-url/my-endpoint' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://micro-service-b-url/login'. This request has been blocked; the content must be served over HTTPS.
The strange thing is that there is no end-point /login in my entire codebase.
I am unable to understand this behavior after springboot upgrade.
Any guidance on how spring boot upgrade led to this error and possible resolution is appreciated.
Note: I found some answers that suggest using the below code to resolve this
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
but looks like it doesn't work with all browsers and I am not sure if its safe to use this solution in terms of security.
Understood the issue and found the solution.
Looks like the security hooks used in SpringBoot 1 are deprecated in SpringBoot 2.
So in my micro-service B the below config in properties file wasn't working after upgrade
security.basic.enable: false
security.ignored=/**
as a result SpringBoot 2 was enforcing default security config on micro-service B and calls to micro-service B through gateway were being redirected to web-sso login which resulted in the mysterious /login endpoint being called.
The solution was to disable default security. I did the below steps:
1. Removed deprecated hooks from properties file:
security.basic.enable: false
security.ignored=/**
2. Disabled default security using below config
#SpringBootApplication(exclude = { SecurityAutoConfiguration.class,
ManagementWebSecurityAutoConfiguration.class })
public class MyApplication extends WebMvcConfigurerAdapter{
Note: I had to exclude ManagementWebSecurityAutoConfiguration.class because the micro-service was using SpringBoot actuator

How to test a Spring Boot actuator endpoint when the 'server.port' and 'management.server.port' properties are different

I would like to test the /health endpoint of my Spring Boot microservice with the help of the MockMvc bean.
But in my case the server.port and management.server.port properties have different values.
And the GET request issued by my MockMvc always ends on the port defined in server.port.
There is already an answer there : Spring boot's actuator unavailable when set management port
But I cannot find this ManagementContextResolver class in Spring Boot 2.2.2.
So far, I found out that the 'management' ConfigurableWebServerApplicationContext is created in org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration.DifferentManagementContextConfiguration, but I don't see how I can obtain a reference to it..
try this, its from the SpringBoot Docs :
#WebIntegrationTest({"server.port=8080", "management.port=8090"})

Actuator Exposing Endpoints not working

I am using spring boot 2.0.4 and want to expose my actuator endpoints. When adding the following to application.yml only info, health are being exposed.
management:
endpoints:
web:
exposure:
include: "*"
When I run http://localhost:8080/actuator I get
{"_links":{"self":{"href":"http://localhost:8080/actuator","templated":false},"health":{"href":"http://localhost:8080/actuator/health","templated":false},"info":{"href":"http://localhost:8080/actuator/info","templated":false}}}
Spring Boot 2.0 takes a slightly different approach to ensure web endpoints security. The majority of Web endpoints are now disabled by default (Only the /health and /info endpoints are exposed) and the management.security.enabled property has been removed. There is no longer a separate security auto-configuration for the Actuator, individual endpoints may be enabled/disabled and/or exposed via configuration in the application.properties file. For example:
# disable beans endpoint
management.endpoints.beans.enabled=false
# expose all endpoints:
management.endpoints.web.exposure.include=*
See additional info Spring official documentation: https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.0-Migration-Guide#endpoints

Spring Boot 2: Refresh properties on the fly not working

I have followed this official tutorial Getting Started Centralized Configuration using spring boot 2.0.0.RELEASE and spring cloud Finchley.M8
But refreshing properties on the fly (Without restart) is not working.
After Some debugging, I noticed that in method refresh() from ContextRefresher.class, it returns the changed keys correctly, but after reconstructing the bean annotated with #RefreshScope in the next use. It still sees the old value not the updated one.
Note: This was working perfectly with spring boot v 1.5.6 and spring cloud Edgware.RELEASE.
Any help please?
Thanks
It seems spring.cloud.config.uri in spring boot 2.0.1.RELEASE always looking for port 8888 and not accepting other values, so I put the below configuration (you can ignore it, as it is the default value for the client, and the server should run on port 8888)
spring:
cloud:
config:
uri: http://localhost:8888
I also tried to expose all other services in the client for testing as follows
management:
endpoints:
web:
exposure:
include: '*'
or use the following to allow only refresh
management:
endpoints:
web:
exposure:
include: refresh
Then called POST method not GET for refreshing
$ curl -X POST localhost:8080/actuator/refresh -d {} -H "Content-Type: application/json"
Finally, it works.
Instead of Method "POST" , use "OPTIONS" method to call the "actuator/refresh" for spring boot 2.0 or higher.
For lower versions (<2.0), use the endpoint "context/refresh"
Make sure , you have management.endpoints.web.exposure.include=* defined in application.properties.
Use below in application.properties-
management.endpoint.refresh.enabled=true
management.endpoint.restart.enabled=true
management.endpoint.health.enabled=true
management.endpoint.health.show-details=always
management.endpoint.info.enabled=true
management.endpoints.web.exposure.include=info,health,refresh
Using yaml configuration file it was not working for me and when switched to properties file, it worked with above configuration.
Thanks

Spring Cloud Gateway - Return 503 when no Service Instance Available

Trying out Spring Cloud Gateway with Spring Boot microservices registered/discovered via Eureka server. The setup is working fine and clients can call the discovered services via the gateway without problem which is great.
Now, I am trying to test a scenario where a client calls a service (via the gateway) for which currently there are no instances available to service the call (i.e. service is down). When we test this scenario, the default behaviour is that the client gets a 500 Internal Server Error response. What would be the simplest way to change this default behaviour to return a 503 Service Unavilable response instead?
Current Stack:
Java 8
Spring Boot 2.0.0.M6
Spring Cloud 2.0.0.M3
Spring Cloud Starter Eureka 2.0.0.M2 (in Gateway JVM)
Spring Cloud Starter Netflix Ribbon 2.0.0.M3 (in Gateway JVM)
Spring Cloud Starter Netflix Eureka Server 2.0.0.M3 (in Eureka Server JVM)
In the end we have decided to leave the error response as it is. i.e. HTTP 500 - Unable to find instance for test-service-name. We have however added functionality to the Gateway's Routing mechanism to include an enabled: true|false flag to each Route which now allows us to temporarily enable/disable access to those microservices as desired. We are doing this by re-building Routes which are marked with enabled: false to include a GatewayFilter in them which returns:
Mono.error(new WebRequestException(HttpStatus.SERVICE_UNAVAILABLE, "SERVICE_UNAVAILABLE",
"Service is down for maintenance"));
whenever a call to that enabled: false Route is called.
The WebRequestException is our own Throwable class which we then intercept in our own WebExceptionHandler which handles the ServerWebExchange's ServerHttpResponse as needed.
Note 1: The Gateway is using spring-boot-starter-webflux within.
Note 2: Whenever we change the state of a Route's enabled flag we: 1) Re-build the Route, 2) Call CachingRouteLocator Bean's .refresh() method in order for the Route to be re-cached with|without the GatewayFilter in place.
The question is quite similar to:
https://stackoverflow.com/a/69257852/12952273
but is asked in different way.
There is a pattern known as Circuit Breaker and it helps avoid cascade failures (cascade failure can happen if the being called service is not responding)
https://martinfowler.com/bliki/CircuitBreaker.html
This might be a little hacky, but why not add a controller advice? Something like this should get you there.
#ControllerAdvice
public class ServiceNotFoundHandler {
#ExceptionHandler(NotFoundException.class)
#ResponseBody
#ResponseStatus(HttpStatus.SERVICE_UNAVAILABLE)
public String handleUnavailableService(NotFoundException e) {
return "service unavailable";
}
}

Resources