Unable to access actuator endpoints when deployed on Google App Engine 11 - spring-boot

I have an inherited spring boot application that was happily living on GAE 8 standard running on jetty. We are in the process of upgrading it to GAE 11 standard.
Based the Differences between Java 8 and Java 11/17 we determined that we would try to Migrating to Java 11/17 with bundled services and followed the instructions to Access bundled services using the App Engine APIs JAR..
The appengine-web.xml and pom.xml were updated as specified above, although we do not have a web.xml, we needed <app-engine-apis>true</app-engine-apis> to prevent some errors on start up because we previously used <sessions-enabled> to secure actuator endpoints. We do not use an app.yaml yet.
There are some release scripts in the code that suggest I should be able to access the actuator endpoints for smoke testing our DEV project to compare against our production endpoints prior to release, for instance /_ah/health, so that is where I am starting to validate my upgrade. So far...
I can access /_ah/health in our current version in production (GAE
8).
I can access /_ah/health in our current version in development
(GAE 8).
I can access /_ah/health locally on http:8080 after
clean package appengine:run (GAE 11, branch), Google App Engine
Maven plugin (deploy)
I cannot access /_ah/health and get 404 Error: Not Found when deployed to out dev (GAE 11, branch)
I've turned up the logs. I can see that is falls through several security filters but I still get a 404:
WebAsyncManagerIntegrationFilter
SecurityContextPersistenceFilter
HeaderWriterFilter
CorsFilter
LogoutFilter
BasicAuthenticationFilter
RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
AnonymousAuthenticationFilter
SessionManagementFilter
ExceptionTranslationFilter
So I am thinking this is related to the Security Configuration.
The intention is to allow the /health and /health/** for all but secure all other actuator endpoints with basic authentication (configured user/pass) in application.yml
Any help would be appreciated. Here is what I think are some valid config files. notes and logs...
All of the necessary work to upgrade the underlying spring boot application from java 8 to 11 (as suggested by many articles/checklists on the web) was completed many months ago and now we are compiling to java 11 and upgrading our GAE deployment.
appengine-web.xml updated for java 11
<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
<service>my-api</service>
<runtime>java11</runtime>
<instance-class>F4</instance-class>
<app-engine-apis>true</app-engine-apis>
<!-- To allow securing actuator endpoints with a login -->
<sessions-enabled>true</sessions-enabled>
<automatic-scaling>
<min-idle-instances>1</min-idle-instances>
</automatic-scaling>
<system-properties>
<property name="java.util.logging.config.file" value="WEB-INF/classes/logging.properties"/>
</system-properties>
</appengine-web-app>
application.yml
# ...
management:
endpoints:
web:
# GAE Standard Runtime looks for health checks under /_ah - not sure if valid any more
base-path: /_ah
exposure:
include: env,health
health:
probes:
# This enables base-path/health/liveness and base-path/health/readiness
enabled: true
# This health check will fail on GAE Standard Runtime
diskspace:
enabled: false
spring:
security:
user:
name: foo
password: bar
roles: ADMIN
# ...
SecurityConfig.java
#Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(final HttpSecurity http) throws Exception {
http
.cors().and().csrf().disable()
.authorizeRequests()
.requestMatchers(EndpointRequest.to("health")).permitAll()
.requestMatchers(EndpointRequest.toAnyEndpoint()).hasRole("ADMIN")
.antMatchers("/**").anonymous()
.and().httpBasic();
}
}
Application.java
#EnableWebSecurity
#SpringBootApplication
public class Application {
public static void main(final String[] args) {
SpringApplication.run(Application.class, args);
}
// ...
}
ServletInitializer.java
Public class ServletInitializer extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(final SpringApplicationBuilder application) {
return application.sources(Application.class);
}
}

As confirmed in the comments section, using an older working version of Cloud SDK (in this case v371.0.0) resulted in being able to successfully access the endpoints again.
Additionally, the issue has already been reported in the issue tracker: App Engine Standard Java 8: 404 Not Found

Related

Spring Boot 2.4.3 - Actuator /startup endpoint not found

I have a spring boot app that I upgraded from v2.2.x to now be v2.4.3.
I saw in their documentation that there is a new actuator endpoint of /startup, however it does not exist when I start my app.
There is no special requirement according to their documentation here
I am using spring-boot-admin-starter-client v2.4.3 which provides spring-boot-actuator v2.4.3, and i even have management.endpoint.startup.enabled=true in my application.properties file.
Has anyone else used this version of spring boot and gotten this actuator enpoint to work?
You need to tweak startup configuration:
#SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(DemoApplication.class);
app.setApplicationStartup(new BufferingApplicationStartup(1000));
app.run(args);
}
}
In application.properties:
management.endpoints.web.exposure.include=startup
If you want to visualize startup events check out this tool I made some months ago https://spring-boot-startup-analyzer.netlify.app/ (look at the configuration instructions as you need to enable CORS on this endpoint)
May be you are using BootstrapApplicationListener which build the application context again but ignores the previous applicationStartup, so it sets the default, this is a bug in spring-cloud-context:3.0.0

securing jolokia actuator endpoint not working when accessing through hawt.io

I've got hawtio 2.1.0 installed connecting to the jolokia endpoint exposed by a spring boot 2.0.5 app.
My app yaml contains
management:
endpoints:
enabled-by-default: true
web:
exposure:
include: "jolokia"
jmx:
exposure:
exclude: "*"
endpoint:
jolokia:
enabled: true
config:
debug: true
In addition I have a filter
#Configuration
public class ActuatorSecurity extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.requestMatchers(EndpointRequest.to(ShutdownEndpoint.class))
.hasRole("ADMIN")
.requestMatchers(EndpointRequest.to(HealthEndpoint.class, InfoEndpoint.class))
.permitAll()
.requestMatchers(EndpointRequest.toAnyEndpoint())
.fullyAuthenticated()
.and().httpBasic();
}
When I access the jolokia actuator endpoint in my browser it correctly asks me for my credentials.
So using this method the endpoints are secured.
When I connect to the jolokia endpoint through the hawt.io web app I don't need to provide any credentials. It makes no differnence if hawt.io is running on a remote or on the local maschine the spring boot app is running on. Hawt.io is able to get all the MBean infos via jolokia.
How can that be?
Hawt.io somehow circumvents the securing of the jolokia actuator endpoint.
Any ideas why this is or how I can secure the jolokia actuator endpoint so that even hawt.io prompts for the credentials?
Thanks a lot in advance!
Cheers
Oliver

Spring Boot 2.0.0.M4 breaks http basic auth in application.yml

Spring Boot 1.5.6.RELEASE respected the basic-auth username and password as specified in my application.yml below.
I have upgraded to 2.0.0.M4 and now the application always starts with the default 'user' and randomly generated password. Basically the settings below are always completely ignored.
I saw some changes in the release note/doc specific to simplifying actuator security enabled/disabled. I didn't see anything specific to this.
Any ideas?
From my application.yml
security:
basic:
enabled: true
realm: some-service
user:
name: example_user
password: example_password
Update:
I've confirmed this functionality was just plainly taken out starting with Spring Boot 2.0.0.M4
In the appendices:
All the security.basic.* family of stuff is missing here from the M4 reference:
https://docs.spring.io/spring-boot/docs/2.0.0.M4/reference/html/common-application-properties.html
But appears here in the M3 reference:
https://docs.spring.io/spring-boot/docs/2.0.0.M3/reference/html/common-application-properties.html
I was able to temporarily downgrade to M3 to restore the previous functionality but would still appreciate some guidance on what replaced it. I just need a single hardcoded basic-auth user for this scenario. I'm aware I could use object configurations to do a much more complicated setup.
Edit 2018-01-31:
The ability to auto-configure a single user has been restored (via the spring.security.user configuration keys) starting with Spring Boot 2.0.0-RC1 (source).
Original answer:
The Spring Boot security.* properties have been deprecated starting with Spring Boot 2.0.0-M4. You can read about this in the Release Notes:
Security auto-configuration has been completely revisited: developers should read the companion blog post and refer to the Spring Boot 2.0 Security wiki page for more details about the change.
In order to restore the basic auth functionality you can register a custom WebSecurityConfigurerAdapter, like this:
#Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Bean
public InMemoryUserDetailsManager inMemoryUserDetailsManager() {
return new InMemoryUserDetailsManager(
User.withDefaultPasswordEncoder().username("user").password("password")
.authorities("ROLE_USER").build(),
User.withDefaultPasswordEncoder().username("admin").password("admin")
.authorities("ROLE_ACTUATOR", "ROLE_USER").build());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.requestMatchers(EndpointRequest.to("health", "info")).permitAll()
.requestMatchers(EndpointRequest.toAnyEndpoint()).hasRole("ACTUATOR")
.requestMatchers(StaticResourceRequest.toCommonLocations()).permitAll()
.antMatchers("/**").hasRole("USER")
.and()
.cors()
.and()
.httpBasic();
}
}
(This will also configure basic auth for the Actuator endpoints)
If you additionally need to read the username and password from a .properties file, you can simply inject the values using the #Value annotation.

UserInfoRestTemplateFactory setup fails with ResourceServerConfigurerAdapter and two spring-cloud-services-starters

I've slightly updated an Spring Cloud Services example to illustrate a problem that I'm having:
https://github.com/spring-cloud-services-samples/greeting/compare/master...timtebeek:master
After the above changes I'm using:
spring-cloud-services-starter-config-client:1.5.0.RELEASE
spring-cloud-services-starter-service-registry:1.5.0.RELEASE
spring-cloud-starter-oauth2:2.0.14.RELEASE
I've also added a minimal ResourceServerConfigurerAdapter
#Configuration
#EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
#Override
public void configure(final HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated();
}
#Override
public void configure(final ResourceServerSecurityConfigurer resources) {
resources.resourceId("greeter");
}
}
And the bare minimum configuration setting:
security:
oauth2:
resource:
jwt:
key-uri: https://example.com/oauth/token_key
With these changes my application fails to deploy in PCF-DEV; I've not tried PCF proper, but expect the results to be similar. Here's the error message I get:
Method userInfoRestTemplateFactory in org.springframework.boot.autoconfigure.security.oauth2.resource.ResourceServerTokenServicesConfiguration required a single bean, but 2 were found:
- eurekaOAuth2ResourceDetails: defined by method 'eurekaOAuth2ResourceDetails' in class path resource [io/pivotal/spring/cloud/service/eureka/EurekaOAuth2AutoConfiguration.class]
- configClientOAuth2ResourceDetails: defined by method 'configClientOAuth2ResourceDetails' in io.pivotal.spring.cloud.service.config.ConfigClientOAuth2BootstrapConfiguration
Action:
Consider marking one of the beans as #Primary, updating the consumer to accept multiple beans, or using #Qualifier to identify the bean that should be consumed
So it's trying to use what should be completely separate OAuth2ProtectedResourceDetails from spring-cloud-services-starters to setup my application security; Where I would want it to use the external JWT key only.
Can anyone help me with how I can have my PCF deployed application using both config and discovery services also use an external JWT token for authentication setup?
I ran into the same thing. I saw this thread a few months ago. I also upgraded to spring boot 1.5.4 and cloud Dalston.SR4 and that got me over the hump. Thanks.
I was shown that http://start.spring.io was using spring boot 1.5.9. It runs on PivotalWS, so I knew there was a solution.
Try this change:
security:
oauth2:
client:
client-id: someclient
client-secret: someclientpass
resource:
jwt:
key-uri: https://example.com/oauth/token_key
The client-id and client-secret are dummy values in my case. I assume since you are also using JWT token, that your resource doesn't need to validate the token with your JWT token provider, only the signature (key-uri).
So by adding the client-id and client-secret, I'm guessing (totally guessing) that it creates the required OAuth2ProtectedResourceDetails with a better (closer) scope.
The fact that it was looking for "userInfoRestTemplateFactory" when we don't need to lookup user info is what pointed me in this direction.
My services are successfully deploying on PivotalWS (run.pivotal.io) with this change, using spring boot 1.5.9 and Dalston.SR4 with io.pivotal.spring.cloud:spring-cloud-services-dependencies:1.5.0.RELEASE
change spring-boot-starter-parent to be 1.5.2.RELEASE ,spring-cloud-dependencies to be Dalston.RC1 , spring-cloud-services-dependencies 1.5.0.RELEASE

DIsabling JBoss EAP 6.4 basic authentication

I have Spring Boot application which use Spring Security OAuth2 as the protection. The application worked well when tested using default server. However, when I try to deploy it on JBoss EAP 6.4 , the application expects the CSRF token. How do I disable JBoss' basic authentication so that my application does not require CSRF token?
EDIT:
As I have described at the comment for sadasidha's answer, this problem didn't show up on Wildfly 8 (JBoss AS)
Disable csrf protection. It's enabled by default
#Configuration #EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
// Disable
http.csrf().disable();
// ...... }
I have found the solution. Actually it is the result of mapping problem. I'm following the solution from
Spring Java Config vs Jboss 7

Resources