I successfully secured one of my applications using Keycloak. The procedure was to create a "keycloak.json" file and adding the security constraints in "web.xml" like described here.
Now, since my application loads all configuration from an RDB table, managed by my application, and some of that information is about the realm, I want to centralize that information.
The idea would be to either:
Have the "keycloak.json" and inject Keycloak values obtained at servlet runtime from the RDB table.
Load the configuration at servlet runtime after RDB table configuration load.
I also want to add a configuration parameter to the RDB table to enable\disable Keycloak validation when needed.
Is this even possible? If it is could you please point me to some examples?
Dynamically create the configuration using the KeycloakConfigResolver, see the multi-tentant keycloak example.
Related
I am currently creating a Java Spring application that works with the spring security JWT. Everywhere I look and read about the "secret string", it says should be changed in production. Like this line in my application.properties: security.jwt.secret="this-is-a-512-bit-key-used-for-signing-jwt-tokens-that-should-be-changed-production"
As well as in stackoverflow question that are sort-of related like this one here: How to include jwt secret in application.yaml for Java Spring.
My question is, what should that string become in production? Am I supposed to generate this somewhere in a SecurityConfig class? Or should I generate a 512 bit string and just paste that in the application.properties file?
Thanks in advance.
Secrets should not be added in your regular application.properties file because that would be checked into your version control system. There are various ways to externalize configuration but the easiest is usually to define environment variables.
In your case, you would need an environment variable called SECURITY_JWT_SECRET and Spring Boot will pick this up automatically.
One way to change properties of a spring app is using Spring Cloud Config. Basically your config is in a GitHub repo and as soon as you modify, Spring cloud config server propagates it to other applications referencing it through application.properties.
https://cloud.spring.io/spring-cloud-config/reference/html/
I will share how it has been done in our application which I think one of the standard way of storing credentials.
There may be alternate ways also.
Its not ideal to store token or credentials in properties
We can externalize the token into Vault or config server
when server starts spring application can fetch the properties
Access to vault are controlled
As we have different vault servers across environments, we can store and change the token in runtime and refresh the application.
Regarding generating the jwt token, it should have some expiry time and refreshed periodically.
Currently i am working on a REST based project in Spring Boot.
I have added the api url in 'application.properties' file.
i.e.
application.properties
api-base-url=http://localhost:8080/RestServices/v1
And also this 'api-base-url' value access from java.
In some situations i need to change the 'api-base-url' dynamically.
I have change 'api-base-url' value dynamically & working fine.
But my problem is that
when wildfly restart then the configuration will be reset to default.
i.e
This is my default value
api-base-url=http://localhost:8080/RestServices/v1
dynamically change to
api-base-url=http://10.34.2.3:8080/RestServices/v1
when wildfly restart then the configuration will be reset to default.
i.e.
api-base-url=http://localhost:8080/RestServices/v1
Have any solution for this?
You might want to consider using a cloud config server to host your config. Two examples are Spring Cloud Config and Consul.
These servers will host your application's configuration and your spring boot application will make a call out to the config server on start up to get it's config.
spring-boot-actuator exposes the endpoint /refresh which forces the application to refresh it's configuration. In this case, it will call out to the config server to get the latest version.
This way you can change the config hosted in the config server then hit the /refresh endpoint and the changes will be picked up by your application.
As #moilejter suggests, one possible way is to persist in database table and at start time you simply read from that table instead of application.properties file. Your application.properties files can hold information necessary for database connection.
You would also need a JMX method or a REST API to trigger in your application that the url has changed and which inturn, would simply read from same table. This way you would be safe even if app restarts and you won't lose the override.
You can use BeanFactoryPostProcessor coupled with Environment bean to leverage spring placeholder concept.
#user2214646
Use spring expression language
I'm planning to work on a multi-tenancy application and for now I'm just looking at different implementations on the web to understand the requirements needed to implement such task.
Hibernate + Spring boot are the technologies I'm planning to use.
From my readings, all the different tutorials are using the same approach which is to declare the data sources in a config file so that session factories are launched with the boot of the application, but I really want to have a higher level of the app, where I can add tenants dynamically and input their data sources informations.
This way the application can get the information of the new tenant without the need to touch the config files and re-boot the app.
I thought about having a separate database where I can store my tenants data source credentials or something like that. Can you give me another approach to solve this requirement or a link to an existing implementation that I can refer to.
Thanks
I got similar requirements in the past.
I implemented DataSource proxy class. The class has tenant resolver and a map of simple DataSources. All the places where we need a DataSource use the proxy.
On any method call e.g. getConnection() it resolves tenant, check whether the map contains already created DataSource (if not a new DataSource is created for the tenant and stored in the DB). Then the same method of real DataSource from the map is invoked.
Tenant resolver is ThreadLocal based where tenant value is stored in a filter (got tenant from request header) and used in the DataSource proxy.
What you need to do is using dynamic datasource routing of Spring Framweork via AbstractRoutingDataSource. This answer explains all for you.
In my question.I implements MultiTenantConnectionProvider and CurrentTenantIdentifierResolver.And use DataSourceLookup to choose datasource by tenant.This links is helpful to me.
Here is a full working example of a database-per-tenant multitenat app I built using Spring Boot 2, Spring JPA (Hibernate), Spring Security 5 running on MySQL.
I have explained how it all works and have shared the entire code too.
Take a look here.
I have quite a complex Spring Boot application (including Spring MVC and Security), which among other things requires a database configuration (url, username and password). The requirement is to let end-user configure the DB with the help of the application itself, like the following:
User starts the application, which has no DB configuration yet
Application notices the absence of DB configuration and presents user with configuration screen
User enters url and credentials
Application starts using this DB
The obvious problem is that I cannot create any beans that require a DataSource which requires DB configuration until that configuration is known.
Is there any way to postpone the initialisation of the majority of the application's beans until first configuration step is performed?
-- Update --
Several of application's beans initialise their state from the DB in their #PostConsutrct methods. So I either need to really delay their creation or have a method of refreshing (potentially) all beans in the application context after configuration is provided.
I suggest you could think about having another module/program or a simple script that would ask to provide all details like database etc, store this information to your application.properties file (may be useful re externalized configuration Spring boot external configuration) and then launch your main program with already available information on datasource. This might be a bit easier approach.
As you probably have expected, you need an instance of javax.sql.DataSource at the time when the Spring Application Context is created.
I suggest you subclass Spring's org.springframework.jdbc.datasource.DelegatingDataSource and override afterPropertiesSet with an empty method (the default implementation throws an error if you haven't supplied a datasource). When the user supplies the details you need to select the db, you can inject the final datasource at a later time into DelegatingDataSource.
Source: https://github.com/spring-projects/spring-framework/blob/master/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/DelegatingDataSource.java
I am programming service for getting data from database and providing them via REST service. It uses spring mvc. My database connection cofiguration is in property file from where it is loaded by spring as a data source bean during context initialization.
Now my problem is - I want to change configuration in properties file (for example change database info) but I can't afford to restart the application server so the new configuration does not load.
How can I re-initialize spring context or some particular beans so the newly defined properties are used?
If you want multiple data source in spring and need to deciding appropriate data source dynamically at runtime you can do this with AbstractRoutingDataSource provided with spring. You have to implement your lookup key logic for determining data-source in method determineCurrentLookupKey(). With this you can map different beans to different data-sources at runtime. following are few questions relating to this context.
How to programatically change databases in Spring with one DataSource?
Also
dynamically change Spring data source