Reputation: 10294
Spring boot actuator is already included in the POM, and it shows in the startup logs. However, when I try to access /actuator or even the base url of my project, I get the following -
{
"timestamp": 1577096144986,
"status": 401,
"error": "Unauthorized",
"message": "Full authentication is required to access this resource",
"path": "/actuator"
}
I read that there could be basic HTTP authentication set for the end points. I looked for spring.security.user.name, password in the config properties, but could not find any.
If I hit http://localhost:8083/actuator, or even http://localhost:8083/ or any URL other the mapped API end points, it seems, I get this password prompt on browser -
On application logs, I get this -
2019-12-23 19:30:54,489 75773 [XNIO-3 task-3] INFO c.c.common.web.LoggerInterceptor [LoggerInterceptor.java:42] - Visitor [okp91Dj1NzT2KPPUjaUvhqEg4oOhwPQ49I9LTR2z] [GET] [/error] [1ms] [OK]
2019-12-23 19:30:54,493 75777 [XNIO-3 task-3] ERROR org.apache.velocity [CommonsLogLogChute.java:96] - ResourceManager : unable to find resource 'error.vm' in any resource loader.
On entering credentials, it fails and the password prompt appears again, with the same logs as above repeated.
Updates
Spring boot version - 1.5.2.RELEASE.
There is a web.xml inside /src/main/resources. It has following -
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath*:META-INF/spring/applicationContext*.xml
classpath*:com.packagename
/WEB-INF/spring/oauth-security.xml
/WEB-INF/spring/security-config.xml
classpath*:META-INF/gateway/*.xml
</param-value>
</context-param>
I could locate the oauth-security.xml and security.xml files in this microservice component.
oauth-security.xml has oauth scopes based definitions for API paths -
<sec:http pattern="/service/v2/**"
create-session="never"
entry-point-ref="oauthAuthenticationEntryPoint"
access-decision-manager-ref="accessDecisionManager">
<sec:intercept-url pattern="/some/path/v2/profile/**" access="ROLE_USER,SCOPE_PROFILE" method="GET"/>
I see security-config.xml which imports webmvc-config.xml.
I see some of these in security-config.xml -
<sec:http pattern="/somepath/**">
<sec:intercept-url pattern="/somepath/**" access="ROLE_USER"/>
<sec:http-basic/>
</sec:http>
but I don't see any configurations for /** paths anywhere.
Update 2
I checked that there seem to be auth configurations in a file called customscopes.properties as well, which seems to be a custom file, added to webmvc-config.xml like this -
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="ignoreResourceNotFound" value="true" />
<property name="locations">
<list>
<value>classpath:/spring/application.properties</value>
<value>classpath:/spring/local.properties</value>
<value>classpath:/spring/customscopes.properties</value>
<value> file:${project.config.dir}/application.properties </value>
<value>file:${project.config.dir}/customscopes.properties</value>
</list>
</property>
</bean>
customscopes.properties has urls like these -
service/v2/path/**=SCOPE_SOMETHING;
At the same, time, there is the same url in oauth-security.xml -
<sec:intercept-url pattern="/service/v2/path/**" access="SCOPE_SOMETHING"/>
I am not sure why there are two sets of configs. I tried changing those one by one, while keeping the other with authentication. I observed that only changing the customscopes.properties affected -
service/v2/path/**=IS_AUTHENTICATED_ANONYMOUSLY;
I am new to Spring Security as well. I checked this video tutorial but could not find those mentioned config methods in my project. There is no mention of WebSecurityConfigurerAdapter.
However, adding the path for actuator/** on both these files, with IS_AUTHENTICATED_ANONYMOUSLY did not work - 401 error as shown in the beginning.
Update 3
Oh, another thing - security-config.xml contains
<sec:http pattern="/favicon.ico" security="none"/>
And I see a difference in the logs when I access http://localhost:8083/actuator/ and http://localhost:8083/somethingelse/
http://localhost:8083/actuator/
Step 1 - Hit this url - log -
2019-12-24 12:31:03,051 590999 [XNIO-3 task-16] INFO c.c.common.web.LoggerInterceptor [LoggerInterceptor.java:42] - Visitor [OICBz6CqYzI58UqobnBYNEXsZUNErjBkv6wEUUkX] [GET] [/error] [2ms] [OK]
2019-12-24 12:31:03,054 591002 [XNIO-3 task-16] ERROR org.apache.velocity [CommonsLogLogChute.java:96] - ResourceManager : unable to find resource 'error.vm' in any resource loader.
Step 2 - cancel sign in form - get favicon.ico instead of /error -
2019-12-24 12:31:18,641 606589 [XNIO-3 task-20] ERROR org.apache.velocity [CommonsLogLogChute.java:96] - ResourceManager : unable to find resource 'error.vm' in any resource loader.
2019-12-24 12:31:18,912 606860 [XNIO-3 task-21] INFO c.c.common.web.LoggerInterceptor [LoggerInterceptor.java:42] - Visitor [OICBz6CqYzI58UqobnBYNEXsZUNErjBkv6wEUUkX] [GET] [/favicon.ico] [2ms] [OK]
http://localhost:8083/somethingelse
Step 1 - Hit this url - log -
2019-12-24 12:31:03,051 590999 [XNIO-3 task-16] INFO c.c.common.web.LoggerInterceptor [LoggerInterceptor.java:42] - Visitor [OICBz6CqYzI58UqobnBYNEXsZUNErjBkv6wEUUkX] [GET] [/error] [2ms] [OK]
2019-12-24 12:31:03,054 591002 [XNIO-3 task-16] ERROR org.apache.velocity [CommonsLogLogChute.java:96] - ResourceManager : unable to find resource 'error.vm' in any resource loader.
Step 2 - cancel sign in form - Same log as above, again
Update 4
If I add a class to extend WebSecurityConfigurerAdapter, and just add a permitAll() against my required paths -
@Override
protected void configure(HttpSecurity http) throws Exception {
http.
authorizeRequests().antMatchers("/service/trace/**").permitAll()
.antMatchers("/service/actuator/**").permitAll()
.antMatchers("/actuator/**").permitAll()
.antMatchers("/trace").permitAll()
.antMatchers("/actuator").permitAll();
}
I get different errors this time (404 Not found) -
{
"timestamp": 1577181851520,
"status": 404,
"error": "Not Found",
"message": "Not Found",
"path": "/service/trace"
}
Note - I have a doubt about which are the available actuator end points, so I am trying to ensure for all these combinations. See the application startup logs below if you can confirm on the basis of that.
I get 404 errors against all these URLs -
http://localhost:8083/service/actuator/beans
http://localhost:8083/actuator/beans
http://localhost:8083/beans
And my other authenticated API endpoints start giving this error -
{
"timestamp": 1577181062281,
"status": 403,
"error": "Forbidden",
"message": "Could not verify the provided CSRF token because your session was not found.",
"path": "/service/v2/some/end/point"
}
ALso, I found that we have these filters as well defined in the web.xml. So, it seems there is Spring configuration, as well as Spring boot addition. Correct me if my understanding is wrong.
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
So, the problem comes down to this -
I can't access the actuator end points. I see the following in application startup logs, containing actuator, but I can't seem to load them either. I guess Spring security is coming in between but not able to prevent the same.
2019-12-24 14:14:10,769 14209 [main] INFO o.s.b.a.e.m.EndpointHandlerMapping [AbstractHandlerMethodMapping.java:543] - Mapped "{[/beans || /beans.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2019-12-24 14:14:10,770 14210 [main] INFO o.s.b.a.e.m.EndpointHandlerMapping [AbstractHandlerMethodMapping.java:543] - Mapped "{[/health || /health.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.HealthMvcEndpoint.invoke(javax.servlet.http.HttpServletRequest,java.security.Principal)
2019-12-24 14:14:10,771 14211 [main] INFO o.s.b.a.e.m.EndpointHandlerMapping [AbstractHandlerMethodMapping.java:543] - Mapped "{[/autoconfig || /autoconfig.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2019-12-24 14:14:10,772 14212 [main] INFO o.s.b.a.e.m.EndpointHandlerMapping [AbstractHandlerMethodMapping.java:543] - Mapped "{[/metrics/{name:.*}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.MetricsMvcEndpoint.value(java.lang.String)
2019-12-24 14:14:10,772 14212 [main] INFO o.s.b.a.e.m.EndpointHandlerMapping [AbstractHandlerMethodMapping.java:543] - Mapped "{[/metrics || /metrics.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
Note -
I have added management.endpoints.web.exposure.include=* in application.properties
I can't see anything like this -
2019-12-24 15:57:41.245 INFO 37683 --- [ main] o.s.b.a.e.web.EndpointLinksResolver : Exposing 18 endpoint(s) beneath base path '/actuator'
Upvotes: 2
Views: 3955
Reputation: 72
One way of running the actuator is assigning a different port to the actuator service this could be done by adding following property to application.properties
management.server.port=8084
This way you can run and access actuator on a different port and can create rules on the gateway as to how it can be accessed.
Another way is to disable security from actuator to add following property to the application.properties
management.endpoints.web.exposure.include=*
Another way of bypassing all the security is following
@Configuration(proxyBeanMethods = false)
public class ActuatorSecurity extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.requestMatcher(EndpointRequest.toAnyEndpoint()).authorizeRequests((requests) ->
requests.anyRequest().permitAll());
}
}
Hope it helps.
Upvotes: 0
Reputation: 2850
Dealing with Legacy application is never easy. Indeed, it seems like you are mixing Spring and Spring-boot configuration altogether. I suggest you to proces step by step. Go back to a working, stable state and then move on:
I've been doing some tests with spring-boot-starter-actuator
with spring-boot-starter-parent
.
Here is the content of my pom.xml:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>
Please notice that spring-boot-starter-actuator:2.2.2.RELEASE
works in different ways that spring-boot-starter-actuator:1.5.2.RELEASE
, mostly regarding the security.
Also note that we use the starter
of every dependency. If not, you won't all spring boot autoconfiguration enabled.
spring-boot-starter-actuator
In your application.properties
, add the following lines :
# Make sure every actuator endpoints are located under the same root URL
management.context-path=/actuator
# Disable default actuator security rules to manage everything with your Java configuration
management.security.enabled=false
In your java configuration class, the one that extends WebSecurityConfigurerAdapter
, apply the following changes:
@EnableWebSecurity // Enable spring security configuration
@Configuration // Is a Spring Configuration class
@Order(ManagementServerProperties.ACCESS_OVERRIDE_ORDER) // To override the default actuator security configuration
public class WebSecurity extends WebSecurityConfigurerAdapter {
/**
* We try to make sure you can easily manage spring actuator endpoints
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.mvcMatchers("/actuator/**").authenticated() // To restrict access to authenticated user on actuator endpoints
.anyRequest().permitAll()
.and()
.csrf().disable(); // If you want to POST data, you have to disable CSRF check. Otherwise, you always get an error when POSTing data on an unsecured URL.
}
}
For more information about CSRF, please check: https://fr.wikipedia.org/wiki/Cross-site_request_forgery
019-12-30 12:13:34.767 INFO 13172 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/actuator/beans || /actuator/beans.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2019-12-30 12:13:34.768 INFO 13172 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/actuator/trace || /actuator/trace.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2019-12-30 12:13:34.769 INFO 13172 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/actuator/configprops || /actuator/configprops.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2019-12-30 12:13:34.773 INFO 13172 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/actuator/metrics/{name:.*}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.MetricsMvcEndpoint.value(java.lang.String)
2019-12-30 12:13:34.773 INFO 13172 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/actuator/metrics || /actuator/metrics.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2019-12-30 12:13:34.774 INFO 13172 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/actuator/autoconfig || /actuator/autoconfig.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2019-12-30 12:13:34.775 INFO 13172 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/actuator/health || /actuator/health.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.HealthMvcEndpoint.invoke(javax.servlet.http.HttpServletRequest,java.security.Principal)
2019-12-30 12:13:34.776 INFO 13172 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/actuator/dump || /actuator/dump.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2019-12-30 12:13:34.778 INFO 13172 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/actuator/heapdump || /actuator/heapdump.json],methods=[GET],produces=[application/octet-stream]}" onto public void org.springframework.boot.actuate.endpoint.mvc.HeapdumpMvcEndpoint.invoke(boolean,javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) throws java.io.IOException,javax.servlet.ServletException
2019-12-30 12:13:34.779 INFO 13172 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/actuator/mappings || /actuator/mappings.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2019-12-30 12:13:34.782 INFO 13172 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/actuator/loggers/{name:.*}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.LoggersMvcEndpoint.get(java.lang.String)
2019-12-30 12:13:34.783 INFO 13172 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/actuator/loggers/{name:.*}],methods=[POST],consumes=[application/vnd.spring-boot.actuator.v1+json || application/json],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.LoggersMvcEndpoint.set(java.lang.String,java.util.Map<java.lang.String, java.lang.String>)
2019-12-30 12:13:34.784 INFO 13172 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/actuator/loggers || /actuator/loggers.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2019-12-30 12:13:34.785 INFO 13172 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/actuator/auditevents || /actuator/auditevents.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public org.springframework.http.ResponseEntity<?> org.springframework.boot.actuate.endpoint.mvc.AuditEventsMvcEndpoint.findByPrincipalAndAfterAndType(java.lang.String,java.util.Date,java.lang.String)
2019-12-30 12:13:34.786 INFO 13172 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/actuator/info || /actuator/info.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2019-12-30 12:13:34.788 INFO 13172 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/actuator/env/{name:.*}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EnvironmentMvcEndpoint.value(java.lang.String)
2019-12-30 12:13:34.789 INFO 13172 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/actuator/env || /actuator/env.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
Let me know if you have any difficulties, or you're console is printing different output. Please also share your pom.xml if any of this works.
Upvotes: 0
Reputation: 152
1)I tested the code with spring boot 1.5.2 and discovered that in this version the actuator endpoints are available in the root('/') path and not at /actuator path. Your logs confirm it also:
2019-12-24 14:14:10,769 14209 [main] INFO o.s.b.a.e.m.EndpointHandlerMapping [AbstractHandlerMethodMapping.java:543] - Mapped "{[/beans || /beans.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
As you see in log, endpoint for example for beans is /beans. In your case http://localhost:8083/beans In addition you need also as Prerak Jain wrote following:
management.security.enabled=false
2) To your problem with HTTP 403:
{
"timestamp": 1577181062281,
"status": 403,
"error": "Forbidden",
"message": "Could not verify the provided CSRF token because your session was not found.",
"path": "/service/v2/some/end/point"
}
To fix it you need to add following to your configuration "and().csrf().disable()", so for example:
http.authorizeRequests().antMatchers("/service/trace/**").permitAll().and().csrf().disable()
That disables csrf token stuff.
Upvotes: 0
Reputation: 123
I have faced the similar error and added this configuration in application.properties :
management.endpoints.web.base-path=/
This would allow you to access all the actuator endpoints.
Upvotes: 2
Reputation: 29
The error occurs as security is not enabled on the endpoint. For a locally deployed app, add the following configuration to your application.properties file -
management.security.enabled=false
On a production app, more careful configurations would need to be made.
Upvotes: 1