Spring Boot: disable https for actuator endpoint - spring-boot

Is possible to config Spring Booot application to have some url with non-secure (non-https) ex: /actuator/info, /actuator/prometheous While All other enpoint forced to be secure?
Enable SSL like this:
server.ssl.enabled=true
server.ssl.key-store=classpath:keystore.jks
server.ssl.key-store-password=xxxx
I was try to set:
management.server.port=8762
management.server.ssl.enabled=false
and
#Override
protected void configure(HttpSecurity http) throws Exception {
http.requiresChannel().antMatchers("/actuator").requiresInsecure();
http.requiresChannel().anyRequest().requiresSecure();
// accept only IP in range to access metric
http.csrf().disable().authorizeRequests().antMatchers("/actuator/**")
.access("hasIpAddress('" + ipRangeMain + "') or hasIpAddress('" + ipRangeSecond + "')");
}
But it's still not working
When I try to access /actuator/info, it show error:
Bad Request
This combination of host and port requires TLS.
"/actuator/info" endpoint need to accessed by Load Balancer and "/actuator/prometheous" to Monitoring, But now it not work.

In case anybody stumbles over this as well. I solved it using 2 Ports like #user3611168 suggested:
applycation.yml:
server:
port: 10000
ssl:
key-store-type: ...
key-store: ...
key-store-password: ...
key-alias: ...
management:
server:
port: 8080
ssl:
enabled: false
Port 10000 with SSL. Port for Prometheus 8080 without SSL

Related

Spring Cloud Config Server/Client Security Issue

I have following security configs in
Server application.yml
management:
security:
enabled: false
server:
port: 8888
spring:
cloud:
config:
server:
jdbc:
order: 1
sql: SELECT prop_key,value FROM xlabs.properties where application=?
and profile=? and label=?
datasource:
password: XXXXX
url: jdbc:postgresql://localhost:8000/finos?currentSchema=xlabs
username: XXXXX
profiles:
active: jdbc
security:
user:
name: mufg
password: mufg
In Client side.
client application.properties
server:
port: 8082
spring:
application:
name: config-server
cloud:
config:
label: latest
profile: development
uri: http://localhost:8888
username: mufg
password: mufg
With this settings
Config server security works fine I can access properties via http://localhost:8888/config-server/development/latest after entering username and passwords. But when I try to up client it says property not resolved. Any issue here?
Thanks.
After some times I am able to find out the answer. In Config server with only that configs the client side will be blocked. So have to disable csrf and allow any request like as follows.
just add sever side.
#Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http
.csrf()
.disable()
.httpBasic()
.and()
.authorizeRequests()
.antMatchers("/encrypt/**").authenticated()
.antMatchers("/decrypt/**").authenticated();
}
}
But Here default security will be disabled. Here problem is if username or password changed from client side authentication happens.

How to fix "vault connection failed due to proxy issue" in spring-boot vault integration?

I want to connect to vault using a proxy. Here in my case, I only require proxy for vault connection, how can we specify the same?
I tried with below configuration:
spring:
application:
name: qualifier-service
profiles:
active: ${spring_profiles_active}
cloud:
vault:
enabled: true
uri: ${vault_uri}
port: 443
scheme: https
proxy:
https:
host: proxyHost
port: 123
namespace: ${vault_namespace}
authentication: TOKEN
token: ${spring_cloud_config_token}
generic:
enabled: true
backend: kv
kvVersion: 2
profile-separator: '/'
default-context: qualifier-service
application-name: qualifier-service
I am getting the below error:
Vault location [kv/qualifier-service] not resolvable: Cannot login using org.springframework.web.client.ResourceAccessException: I/O error on POST request for "https://vault.url:443/v1/auth/aws/login": Connect to vault.url:443 failed: connect timed out;
How can we pass a proxy specifically for vault. My service is connecting a cloud config server and other external services also but they don't required a proxy.
Any help on this is deeply appreciated.
From the documentation:
You can configure the resttemplate: https://docs.spring.io/spring-cloud-vault/docs/current/reference/html/config-data.html#vault.configdata.customization
import org.apache.http.HttpHost;
import org.apache.http.impl.client.HttpClients;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.vault.config.AbstractVaultConfiguration.ClientFactoryWrapper;
#SpringBootApplication
public class VaultTestApplication {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(VaultTestApplication.class);
application.addBootstrapRegistryInitializer(registry -> registry.register(
ClientFactoryWrapper.class,
ctx -> new ClientFactoryWrapper(
new HttpComponentsClientHttpRequestFactory(
HttpClients.custom()
.setProxy(HttpHost.create("localhost:8080"))
.build()
)
)
)
);
application.run(args);
}
}
Alternatively:
If passing all traffic through the proxy is fine, setting the java properties
-Dhttp.proxyHost=...
-Dhttp.proxyPort=...
-Dhttps.proxyHost=...
-Dhttps.proxyPort=...
will work if you have httpcomponents in your project (Vault will pick it up) e.g.
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>

Springboot Testing via Greenmail

I tried to test my Gmail smtp in my Spring-Application and followed this Tutorial. I have implemented it as specified in the tutorial, but my EmailService throws a MailSendException:
org.springframework.mail.MailSendException: Mail server connection failed; nested exception is com.sun.mail.util.MailConnectException: Couldn't connect to host, port: localhost, 2525; timeout 5000;
nested exception is:
java.net.ConnectException: Connection refused: connect. Failed messages: com.sun.mail.util.MailConnectException: Couldn't connect to host, port: localhost, 2525; timeout 5000;
nested exception is:
java.net.ConnectException: Connection refused: connect
; message exception details (1) are:
Failed message 1:
com.sun.mail.util.MailConnectException: Couldn't connect to host, port: localhost, 2525; timeout 5000;
nested exception is:
java.net.ConnectException: Connection refused: connect
at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:2210)
at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:722)
at javax.mail.Service.connect(Service.java:342)
Has anyone a tip how to solve this? (Never tested something like SMTP/Email and therefore just followed the tutorial above.
EDIT: I can send emails without any problem manually, but I need to test it.
my application.yml:
spring.mail.host: smtp.gmail.com
spring.mail.port: 587
spring.mail.properties.mail.smtp.starttls.enable: true
spring.mail.username: ************#gmail.com
spring.mail.password: ***************
spring.mail.properties.mail.smtp.starttls.required: true
spring.mail.properties.mail.smtp.auth: true
spring.mail.properties.mail.smtp.connectiontimeout: 5000
spring.mail.properties.mail.smtp.timeout: 5000
spring.mail.properties.mail.smtp.writetimeout: 5000
From the log you can see, that Spring is trying to connect to port 2525 but can't make connection. That means that there's no running mail server on this port, during test execution - which should be provided by JUnit Rule implementation (If you're using JUnit5 use Extensions)
Make sure that your test configuration is properly setup. That means, check whether your test code, e.g.
#Rule
public SmtpServerRule smtpServerRule = new SmtpServerRule(2525);
matches
src/test/resources/application.yml
spring:
mail:
default-encoding: UTF-8
host: localhost
jndi-name:
username: username
password: secret
port: 2525
properties:
mail:
debug: false
smtp:
debug: false
auth: true
starttls: true
protocol: smtp
test-connection: false
I would also recommend to update the code from the Tutorial and add test user - as it could be used with secured protocols.
public class SmtpServerRule extends ExternalResource {
// omitted for brevity
#Override
protected void before() throws Throwable {
super.before();
smtpServer = new GreenMail(new ServerSetup(port, null, "smtp"));
smtpServer.addUser("username", "secret");
smtpServer.start();
}
// omitted for brevity
}
Also, refer to the official GreenMail documentation for more specific setup.

Spring Boot: OAuth endpoint redirects to 8443

I have a web-app running with SSL only (no http allowed) on port 8080:
server:
ssl:
key-store-type: PKCS12
key-store: file:${SERVER_KEYSTORE_PATH}
key-store-password: ${SERVER_CERT_PASSWORD}
port: 8080
When I launch the app, I see in the logs:
2020-03-17 17:32:29.836 INFO 90960 --- [main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (https)
One of my endpoints (the root one, actually) is protected by Spring Security, OAuth2:
#Override
protected void configure(HttpSecurity http) throws Exception {
String baseURI = redirectURI.substring(redirectURI.lastIndexOf("/"));
http.csrf().disable()
.authorizeRequests()
.antMatchers("/").authenticated()
.antMatchers("/**").permitAll()
.and()
.oauth2Login()
.defaultSuccessUrl("/")
.redirectionEndpoint().baseUri(baseURI);
}
The problem is that when I go to https://localhost:8080 - it redirects me to https://localhost:8443/oauth2/authorization/oauth So, for some reason the port 8080 is overriden with 8443.
As far as I understood from similar questions, this is happening because Tomcat is trying to redirect the user to the SSL-enabled endpoint (https) from the plain endpoint (http). But my endpoint is already SSL-enabled, so I don't really understand why is it happening. If I go to any other endpoint, it works with https and 8080 port - so only protected endpoint is problematic.
I tried to customize TomcatServletWebServerFactory with ConnectorCustomizers and set there redirect port to 8080, but it didn't help.
Any ideas on how to disable this useless redirect?
As per https://github.com/spring-projects/spring-security/issues/8140#issuecomment-600980028 :
#Override
protected void configure(HttpSecurity http) throws Exception {
PortMapperImpl portMapper = new PortMapperImpl();
portMapper.setPortMappings(Collections.singletonMap("8080","8080"));
PortResolverImpl portResolver = new PortResolverImpl();
portResolver.setPortMapper(portMapper);
LoginUrlAuthenticationEntryPoint entryPoint = new LoginUrlAuthenticationEntryPoint(
"/login");
entryPoint.setPortMapper(portMapper);
entryPoint.setPortResolver(portResolver);
http
.exceptionHandling()
.authenticationEntryPoint(entryPoint)
.and()
//...
;
}

How to Secure Spring Cloud Config Server

I understand that a Spring Cloud Config Server can be protected using an user name and password , which has to be provided by the accessing clients.
How can i prevent the clients from storing these user name and
password as clear text in the bootstrap.yml files in the client
application/services ?
The very basic "basic authentication" (from here https://github.com/spring-cloud-samples/configserver)
You can add HTTP Basic authentication by including an extra dependency on Spring Security (e.g. via spring-boot-starter-security). The user name is "user" and the password is printed on the console on startup (standard Spring Boot approach). If using maven (pom.xml):
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
If you want custom user/password pairs, you need indicate in server configuration file
security:
basic:
enabled: false
and add this minimal Class in your code (BasicSecurityConfiguration.java):
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
#Configuration
//#EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class BasicSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Value("#{'${qa.admin.password:admin}'}") //property with default value
String admin_password;
#Value("#{'${qa.user.password:user}'}") //property with default value
String user_password;
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password(user_password).roles("USER")
.and()
.withUser("admin").password(admin_password).roles("USER", "ACTUATOR");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.disable()
.httpBasic()
.and()
.authorizeRequests()
.antMatchers("/encrypt/**").authenticated()
.antMatchers("/decrypt/**").authenticated()
//.antMatchers("/admin/**").hasAuthority("ROLE_ACTUATOR")
//.antMatchers("/qa/**").permitAll()
;
}
}
#Value("#{'${qa.admin.password:admin}'}") allow passwords to be defined in property configuration file, environment variables or command line.
For example (application.yml):
server:
port: 8888
security:
basic:
enabled: false
qa:
admin:
password: adminadmin
user:
password: useruser
management:
port: 8888
context-path: /admin
logging:
level:
org.springframework.cloud: 'DEBUG'
spring:
cloud:
config:
server:
git:
ignoreLocalSshSettings: true
uri: ssh://git#gitlab.server.corp/repo/configuration.git
This works for me.
Edit: Instead of the Class, you can put basic user configuration directly in application.yaml:
security:
basic:
enabled: true
path: /**
ignored: /health**,/info**,/metrics**,/trace**
user:
name: admin
password: tupassword
For Spring Boot 2 the configuration in application.yml are now under spring.security.* (https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html#security-properties)
spring.security:
basic:
enabled: true
path: /**
ignored: /health**,/info**,/metrics**,/trace**
user:
name: admin
password: tupassword
Basic authentication configuration that works for me.
Server-side:
Needed depedency: org.springframework.boot:spring-boot-starter-security
bootstrap.yml
server:
port: 8888
spring:
cloud:
config:
server:
git:
uri: git#bitbucket.org:someRepo/repoName.git
hostKeyAlgorithm: ssh-rsa
hostKey: "general hostKey for bitbucket.org"
security:
user:
name: yourUser
password: yourPassword
Client-side:
bootstrap.yml
spring:
application:
name: config
profiles:
active: dev
cloud:
config:
uri: http://localhost:8888
username: yourUser
password: yourPassword
management:
security:
enabled: false
Sources: Spring doc security feautres, Spring cloud config client security
encrypted text can be placed in bootstrap.yml.
Check -> http://projects.spring.io/spring-cloud/spring-cloud.html#_encryption_and_decryption

Resources