Securing spring cloud config credentials using vault - spring

I’m using spring-cloud-config-server with Git as a backend. I want to secure the git credentials of my private repository (username and password) to be served from the vault server.
I'm thinking to extend the GitCredentialsProviderFactory and create the credentials bean using createFor() with values from the vault. Is this a right approach or there are other recommended ways?

Instead of using the GitCredentialsProviderFactory which I had thought of using. I used MultipleJGitEnvironmentProperties to create the GitPropert bean. And then supplied the credentials via the config values fetched from the vault.
#Bean MultipleJGitEnvironmentProperties createGitProps(){
MultipleJGitEnvironmentProperties
properties = new MultipleJGitEnvironmentProperties();
properties.setUsername(username);
properties.setUri(uri);
properties.setSearchPaths(searchPath);
properties.setPassword(password);
properties.setCloneOnStart(true);
return properties;
}

Related

Enhance DataSourceProperties configuration bean with KMS provided secret

I want to set the password for the datasource programatically and still use auto configuration of Spring GCP and Spring Data.
Background
I want to obtain my password as encrypted blob and decrypt it via Google KMS. I read that spring gcp auto configuration mutates the DataSourceProperties bean to apply gcp secific configurations (https://docs.spring.io/spring-cloud-gcp/docs/1.0.0.RELEASE/reference/html/_spring_jdbc.html#_literal_datasource_literal_creation_flow).
Now I would like to mutate the DataSourceProperties Bean exposed by GcpCloudSqlAutoConfiguration once more.
Exposing the DataSourceProperties as follows does not work because GcpCloudSqlAutoConfiguration then doesn't know which Bean to take: the one configured by spring boot auto configuration or mine. But mine should be applied in the very last step of configuration.
#Bean
public DataSourceProperties dataSourceProperties(DataSourceProperties dataSourceProperties) {
dataSourceProperties.setPassword(getDecryptedSecret());
return dataSourceProperties;
}
private String getDecryptedSecret() {
// get encrypted password and decrypt it
return "myDecryptedPassword"
}
You should be able to provide your own bootstrap property source that contains a value for spring.datasource.password.
See: https://cloud.spring.io/spring-cloud-commons/multi/multi__spring_cloud_context_application_context_services.html#customizing-bootstrap-property-sources
Full answer is on project GitHub: https://github.com/spring-cloud/spring-cloud-gcp/issues/2330
Cloud KMS offers encrypting and decrypting data with a symmetric key[1] and/or an asymmetric key[2].
You can see DataSourceProperties[3] for more of the supported options for Spring Boot.
[1]-https://cloud.google.com/kms/docs/encrypt-decrypt
[2]-https://cloud.google.com/kms/docs/encrypt-decrypt-rsa
[3]-https://github.com/spring-projects/spring-boot/blob/v2.1.8.RELEASE/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceProperties.java

Spring boot application properties load process change programatically to improve security

I have spring boot micro-service with database credentials define in the application properties.
spring.datasource.url=<<url>>
spring.datasource.username=<<username>>
spring.datasource.password=<<password>>
We do not use spring data source to create the connection manually. Only Spring create the database connection with JPA.(org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration)
We only provide the application properties, but spring create the connections automatically to use with the database connection pool.
Our requirement to enhance the security without using db properties in clear text. Two possible methods.
Encrypt the database credentials
Use the AWS secret manager. (then get the credential with the application load)
For the option1, jasypt can be used, since we are just providing the properties only and do not want to create the data source manually, how to do to understand by the spring framework is the problem. If better I can get some working sample or methods.
Regarding the option-2,
first we need to define secretName.
use the secertName and get the database credentials from AWS secret manager.
update the application.properties programatically to understand by spring framework. (I need to know this step)
I need to use either option1 and option2. Mentioned the issues with each option.
What you could do is use environment variables for your properties. You can use them like this:
spring.datasource.url=${SECRET_URL}
You could then retrieve these and start your Spring process using a ProcessBuilder. (Or set the variables any other way)
I have found the solution for my problem.
We need to define org.springframework.context.ApplicationListenerin spring.factories file. It should define the required application context listener like below.
org.springframework.context.ApplicationListener=com.sample.PropsLoader
PropsLoader class is like this.
public class PropsLoader implements ApplicationListener<ApplicationEnvironmentPreparedEvent> {
#Override
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
ConfigurableEnvironment environment = event.getEnvironment();
String appEnv = environment.getProperty("application.env");
//set new properties based on the application environment.
// calling other methods and depends on the enviornment and get the required value set
Properties props = new Properties();
props.put("new_property", "value");
environment.getPropertySources().addFirst(new PropertiesPropertySource("props", props));
}
}
spring.factories file should define under the resources package and META-INF
folder.
This will set the application context with new properties before loading any other beans.

Spring JDBC Authentication vs LoadUserByName Differences

Im new on spring security and I had some research on authentication ,I saw two options there are some guys posted.First one Jdbc authentication or In memory authentication ,and there are also loadUserByName(UserDetailService).
what is difference between them ,and also what is use case of loadUserByName (UserDetailService)
This is the official reference https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#jc-authentication
For In Memory Authentication, you have a set of username-password pair hard-coded in your xml/java config class.
In jdbc authentication, you can have a direct database contact to fetch users and authorities, provided you have configured a datasource
You can define custom authentication by exposing a custom UserDetailsService as a bean. You can do whatever functionality to return an instance of UserDetails in loadUserByUsername(). This method is called implicitly to authenticate a user, when creating an authentication.

get user role in resource server from authorization server

I have an authorization server which on the basis of username and password fetches the user details from the DB along with the roles.
Now while accessing the protected resource in the resource server (passing the access_token), I want to authorize the rest call on the basis of role.How do I do that ?
Because, while I am checking the Principal user in resource server, its getting the default [ROLE_USER]
//Will #preAuthorize() work here ?
#RequestMapping(value="/pinaki", method=RequestMethod.GET)
public String home(Principal principal) {
return "Hello World";
}
Please guide..Thanks in advance
AFAIK spring-security-oauth2 only supports getting the user details (including roles) for a Authorization Server/Ressource Server that share a common data store (either database or in memory)out of the box.
If you do have a common data store you can use the InMemoryClientDetailsService or JdbcClientDetailsService.
However it should not be too hard to extend this by yourself if in your setup there is no common data store. The key interfaces for this task are ClientDetailsService and ResourceServerTokenServices.
A ResourceServerTokenServices implementation returns a OAuth2Authentication including roles. So you could call the tokeninfo endpoint from the authorization server here.
Implementing a ClientDetailsService and using that would be more elegant. Here also you would need to call the tokeninfo endpoint.
In XML configuration you can setup the beans to use in the oauth:resource-server tag in the parameters token-services-ref and auth-details-source-ref.
Details on the Java config can be found on page http://projects.spring.io/spring-security-oauth/docs/oauth2.html
(My info refers to version 2.0.8 of spring-security-oauth2)

Java Configuration equivalent of <jdbc-user-service> in Spring Security

When we use xml based configuration for Spring Security we are able to use <jdbc-user-service> tag with attributes authorities-by-username-query and users-by-username-query to get username, password and role from database for a specific username input.
Reference:
http://docs.spring.io/spring-security/site/docs/3.2.5.RELEASE/reference/htmlsingle/#nsa-jdbc-user-service
The code given in Spring Security documentation for Java Configuration seem to be using hard-coded username & password.
Reference:
http://docs.spring.io/spring-security/site/docs/3.2.5.RELEASE/reference/htmlsingle/#jc-authentication-jdbc
The related sample project (spring-security / samples / jdbc-jc) also appears to use the same hard-coded username & password values.
So with Java Configuration, how can we validate the user input with user credentials stored in a database?
Looks like you're looking for JdbcDaoImpl class with his setters setAuthoritiesByUsernameQuery() and setUsersByUsernameQuery().

Resources