Spring: Configure security for actuator endpoints with Spring Security - java

Is it possible to configure security for actuator endpoints of a Spring application with Spring Security in a generic way?
According to https://github.com/spring-projects/spring-boot/issues/8646 I need to do this in my custom Spring Security configuration.
But suppose I have both a custom request mapping for /info in my application (on port 8080) and also the actuator info endpoint enabled on port 8081. How can I distinguish these two in Spring Security?

Yes it's possible but not particularly obvious. In your extension of WebSecurityConfigurerAdapter you can inject a collection of the actuator endpoints:
#Inject
private List<AbstractEndpointMvcAdapter<? extends Endpoint<?>>> actuatorEndpoints;
Then in your override of configureHttpSecurity(HttpSecurity http) you can use the getPath() member of each actuator endpoint to pass to the .requestMatchers(forPortAndPath(managementPort, actuatorPath)) builder available on the http argument.

I just found out that Spring Boot 2 explicitly addresses this problem.
See https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#production-ready-endpoints-security

Related

How to register servlet on a different port in spring boot?

In my casual spring boot application I regiser servlet like this.
import io.prometheus.client.exporter.*
.....
#Bean
public ServletRegistrationBean<MetricsServlet> registerMetricsServlet(MetricRegistry metricRegistry) {
return new ServletRegistrationBean<>(new MetricsServlet(), "/metrics");
}
This servlet is registred on the same port as application.
The issue is that my infrastructure(k8s and etc) is expecting that application and metrics endpoint works on a different ports(like actuator does).
How can I register third party servlet on a ddifferent port ?
You can do it with multiple connectors and request filter. (All connectors are handle same way)
https://tech.asimio.net/2016/12/15/Configuring-Tomcat-to-Listen-on-Multiple-ports-using-Spring-Boot.html
pay attention to the lines from
public FilterRegistrationBean javaMelodyRestrictingFilter(FilterRegistrationBean javaMelodyFilter) {...
spring boot 2.0 listening on multiple ports
Original answer here. Configure Spring Boot with two ports

Spring Boot Actuator - Custom Endpoints

I am using Spring Boot Actuator module in my project which exposes REST endpoint URLs to monitor & manage application usages in production environment, without coding & configuration for any of them.
By default, only /health and /info endpoints are exposed.
I am customising the endpoints via application.properties file as per my use case.
application.properties.
#To expose all endpoints
management.endpoints.web.exposure.include=*
#To expose only selected endpoints
management.endpoints.jmx.exposure.include=health,info,env,beans
I want to understand, where exactly does Spring Boot create actual endpoints for /health and /info and how does it expose them over HTTP?
Thanks #Puce and #MarkBramnik for helping me out with the reference docs & code repository.
I wanted to understand how the endpoints were working and how they were exposed over HTTP, so that I could create custom endpoints to leverage in my application.
One of the great features of Spring Framework is that it’s very easy to extend, and I was able to achieve the same.
To create a custom actuator endpoints, Use #Endpoint annotation on a class. Then leverage #ReadOperation / #WriteOperation / #DeleteOperation annotations on the methods to expose them as actuator endpoint bean as needed.
Reference Doc : Implementing Custom Endpoints
Reference Example :
#Endpoint(id="custom_endpoint")
#Component
public class MyCustomEndpoint {
#ReadOperation
#Bean
public String greet() {
return "Hello from custom endpoint";
}
}
The endpoint id i.e custom_endpoint needs to be configured in the list of actuator endpoints to be enabled.
application.properties :
management.endpoints.web.exposure.include=health,info,custom_endpoint
After a restart, endpoint works like a charm!

SpringBoot 2 health end point JSON format has changed

We have recently upgraded out Spring-Boot version to 2.1.2 in one of our applications.
I noticed a change in JSON format when I hit this URL:
http://localhost:xxxx/health.
The changed structure is:
{
Health: {
status: "UP"
}
}
Earlier it was:
{
status: "UP"
}
My question is;
1. Why has it been modified?
2. Is there any config to keep the structure as it was before?
With the release of Spring Boot 2, Actuator has been redesigned, and new exciting endpoints were added.
The /actuator/health endpoint is used to check the health or state of the running application. It’s usually exercised by monitoring software to alert us if the running instance goes down or gets unhealthy for other reasons. E.g. Connectivity issues with our DB, lack of disk space…
http://localhost:8080/actuator/health
{
status: "UP"
}
Monitoring and Management over HTTP
If you are developing a web application, Spring Boot Actuator auto-configures all enabled endpoints to be exposed over HTTP. The default convention is to use the id of the endpoint with a prefix of /actuator as the URL path. For example, health is exposed as /actuator/health. TIP: Actuator is supported natively with Spring MVC, Spring WebFlux, and Jersey.
Actuator Security
For security purposes, all actuators other than /health and /info are disabled by default. The management.endpoints.web.exposure.include property can be used to enable the actuators.
If Spring Security is on the classpath and no other WebSecurityConfigurerAdapter is present, all actuators other than /health and /info are secured by Spring Boot auto-configuration. If you define a custom WebSecurityConfigurerAdapter, Spring Boot auto-configuration will back off and you will be in full control of actuator access rules.
Endpoints
Actuator endpoints let you monitor and interact with your application. Spring Boot includes a number of built-in endpoints and lets you add your own. For example, the health endpoint provides basic application health information.
Each individual endpoint can be enabled or disabled. This controls whether or not the endpoint is created and its bean exists in the application context. To be remotely accessible an endpoint also has to be exposed via JMX or HTTP. Most applications choose HTTP, where the ID of the endpoint along with a prefix of /actuator is mapped to a URL. For example, by default, the health endpoint is mapped to /actuator/health.
Actuator JSON
The JSON payloads returned from many endpoints have been improved with Spring Boot 2.0.
Many endpoints now have JSON that more accurately reflects the underlying data. For example, the /actuator/conditions endpoint (/autoconfig in Spring Boot 1.5) now has a top level contexts key to group results by ApplicationContext.
8. Health (health)
To retrieve the health of the application, make a GET request to /actuator/health, as shown in the following curl-based example:
$ curl 'http://localhost:8080/actuator/health' -i -X GET
Useful Information : Baeldung

Understanding ACTUATOR role in spring boot

After recent spring boot upgrade (1.5+) I am no longer able to access /metrics endpoint in my application. To solve this, I added management.security.enabled=false and management.security.roles=ACTUATOR. This allowed me to access the endpoint and it still required credentials before viewing. This works but I don’t understand why. Am I only disabling the ACTUATOR role to access this endpoint? Is there any security risk here?
I know after you move to spring boot 2.0.0.M5 only status and info endpoints are enabled by default. In Spring Boot 2 also you no longer need to have management.security.enabled https://github.com/spring-projects/spring-boot/issues/11383
I generally use this:
management.endpoints.web.exposure.include=info, health, metrics, env, beans, configprops

How to output all endpoints exposed by Spring

I'd like to have a way how to expose all endpoints that exposed by my Spring application. Is there a simple way to check, for each #profile which are exposed?
Example:
GET /api/resource
GET /api/resource/list
POST /api/resource
PUT /api/resource
In the past, I have used a web application made in Laravel, and they had a simple cli method for checking the exposed methods.
I assume based on how the questions is worded that you are not using Spring Boot, if you were, the actuator mappings endpoint does this for you, but your answer lies in how the mappings endpoint is build in actuator. There is a RequestMappingHandlerMapping object you leverage.
In this scenario you can use two approaches:
Spring Boot Actuator feature. Your endpoints of application will be available at http://host/actuator/mappings
Swagger library can also be used to list all endpoints of a REST API
The best solution is to use Spring boot actuator and hit the endpoint /actuator/mappings to get all the endpoints.
But if you can't use actuator or can't add it as dependency you can retrieve all the endpoints programmatically the mapping handlers, Spring get shipped with three implementations of this interface (HandlerMapping):
RequestMappingHandlerMapping: which is responsible for endpoints that annotated with #RequestMapping and its variants #GetMapping, #PostMapping .. etc
BeanNameUrlHandlerMapping: as the name suggest it will resolve the endpoint(URL) directly to a bean in the application context. for example if you hit the endpoint /resource it will look for a bean with the name /resource.
RouterFunctionMapping: it will scan the application context for RouterFunction beans and dispatch the request to that function.
Anyways, to answer your question you can autowire the bean RequestMappingHandlerMapping and print out all the handler methods. Something similar to this:
#Autowired
RequestMappingHandlerMapping requestMappingHandlerMapping;
#PostConstruct
public void printEnpoints() {
requestMappingHandlerMapping.getHandlerMethods().forEach((k,v) -> System.out.println(k + " : "+ v));
}

Categories