Is it possible in spring boot to dynamically update RBAC but only for certain methods? I have my application.yml like this which I store in cloud config server
rbac:
- endpoint: /api/v1/user
permissions: read-user, write-user
- endpoint: /api/v1/admin
permissions: read-admin, write-admin
In my SecurityConfig class, I have marked it as RefreshScope and I parse these configs and add the rbac in spring security. This works fine and if I updated the yml file in my repo, config server successfully pushes it to the running instances and it gets dynamically updated.
But now I want to define a more granular level of RBAC by adding it on methods such that certain methods can only be accessed by some users. Is it possible in Spring Boot to do this and also that we can update the method level RBAC dynamically via some config file without requiring to restart the application?
Related
I have to change my custom defined spring properties (defined via #ConfigurationProperties beans) during runtime of my Spring Boot application.
Is there any elegant way of doing this using Spring Cloud Config?
I don't want to use an external application.properties in a git repository (as the spring boot application gets shipped to customers and I dont' want to create a git repository for everyone of them).
I just want to access and change the local application.properties (the one in the classpath, located in src/main/resources) file in my Spring container or (if thats not possible) in the Spring Cloud Config Server, which I could embed into my Spring Boot app. Is that possible somehow?
BTW: The goal is to create a visual editor for the customers, so that they can change the application.properties during runtime in their spring boot app.
Spring Boot supports profile based application configuration. Just add application-<profile>.properties file. Then just when running the application select a profile depending on the environment making use of spring.profiles.active.
-Dspring.profiles.active=dev
This will run the application with application-dev.properties file (overriding the default application.properties, i.e you can just leave the common stuff in the default file and change the rest depending on the env)
On a side note, having a repo for configuration is not a must. You could just place them in the class path and give a search-location.
spring:
application:
name: config-server
profiles:
active: native
cloud:
config:
server:
native:
search-locations: classpath:configs/
It actually is possible and in the end quite easy to achieve. It just took me a whole day to get all the information together. Maybe this helps someone:
You basically just need Spring Actuator, but for a certain endpoint, you also need the spring cloud dependency. (to make Post requests to the /env endpoint of Spring Actuator)
To alter your config at runtime, just add the following to your application.properties:
management.endpoints.web.exposure.include: env,refresh
management.endpoint.env.post.enabled: true //this property is only available when spring cloud is added as dependency to your project
If you (like me) don't need the feature of an externalized config, then you also have to add the following (otherwise, your Spring app will not start and throw an error that some config is missing)
spring.cloud.config.enabled: false
Now, if you send a POST request to /actuator/env endpoint with an object in the HTTP body in the form of {"name":"...", "value":"..."} (name is the name of a config property), then your config gets changed. To check that, you can do a GET request to /actuator/env/[name_of_config_property] and see that your config property has changed. No need to restart your app.
Don't forget to secure the /actuator endpoint in your SecurityConfig if you use a custom one.
It seems to me that you neither need the #RefreshScope annotation at your config classes nor the /actuator/refresh endpoint to "apply" the config changes.
Maybe what your looking for could be achieved with Spring cloud config and spring cloud bus. It's explained here: https://cloud.spring.io/spring-cloud-config/reference/html/#_push_notifications_and_spring_cloud_bus
In summary, any change on configuration sent an event to the spring cloud bus and you can then reload app context or configuration with new properties.
I have a Spring Boot application for UI test automation using Cucumber and Selenium.
The application is expected to test multiple environments.
To begin with I have created json files with required properties like URLs, credentials etc. and load it(pass the file path as a property and use it) while triggering the test (mvn test -DconfigFile=config/env1_config.json).
I see that using profiles while running test is an option-Dspring.profiles.active=client1 but as i will configure multiple pipelines in Jenkins for testing multiple environments to use same project with different configuration files, it will clone the entire project and run tests in workspace corresponding to the pipeline. To avoid keeping multiple copies of the project, i am planning to use Rest API to trigger Selenium tests and have configuration files in Git.
Is it possible to create multiple application properties files with custom properties, place them in Git and use required property file in a Spring Boot application(inside a Rest API impl) based on a property or RequestParam using Spring Cloud Config or something?
you can use spring boot profiles and pass it as maven argument
just pass -Dspring.profiles.active=test1 as command line argument
you can read more here
You can do it by setting spring.profiles.active environment variable. Like if you are using property file for every environment by convention application-dev.properties, application-qa.properties. You can define you spring.profiles.active as dev and qa.
You can refer to the below link for more in site on same.
https://stackabuse.com/spring-boot-configuring-properties/
You can use Spring cloud server and client.
Make A project With Dependency Spring cloud server and make config file(appilcation.properties) there. For use that config file in other microservice
just add spring cloud cilent dependency in other projects and add this line in application.properties
spring.cloud.config.uri:[your spring cloud server project url]
refrence:-
spring cloud server:-
https://www.youtube.com/watch?v=gb1i4WyWNK4&list=PLqq-6Pq4lTTaoaVoQVfRJPqvNTCjcTvJB&index=11
spring cloud client:- https://www.youtube.com/watch?v=E2HkL766VHs&list=PLqq-6Pq4lTTaoaVoQVfRJPqvNTCjcTvJB&index=12
Sharing the approach I ended up with as it might help someone someday.
As i wanted to create a Rest API and use properties from different config files in API implementation, based on the api request,
I created a Spring Cloud Config Server application that connects to application properties repo in git and I consumed Rest APIs exposed by Spring Cloud Config Server (host:port/app/profile) in the service layer of my Rest API implementation.
I am new to spring and creating a spring cloud config service. I have successfully created the configuration service where all the configurations are there. In my client service(this will fetch all the necessary configurations from the configuration service) I need to fetch the configurations depending on the SPRING_PROFILES_ACTIVE value which is defined in the manifest file. There are multiple manifest files in the client service and each has its own SPRING_PROFILES_ACTIVE value.
Currently I am using #ConfigurationProperties(prefix="profile_name") i.e manually defining the "profile_name". But, I want to make it dynamically i.e depending on the value of SPRING_PROFILES_ACTIVE the value should be fetched from configuration service.
Can anyone please suggest me how to load the value dynamically.
Thanks in advance.
Pass SPRING_PROFILES_ACTIVE as environment variable to Spring Boot app instead of declaring it in yaml and hard coding it in configuration file. The app picks the corresponding yaml based on the profile.
How to pass spring profile as parameter to spring boot app
depending on the value of SPRING_PROFILES_ACTIVE the value should be fetched from configuration service.
If I understand correctly, you are trying to get configuration from a Config Server based on the active profiles in the client app. Spring Cloud Config Client does this automatically, as described in the documentation. For example, if the client app has spring.profiles.active=profile1,profile2, then at boostrapping the config client will make requests to the Config Server with URLs like
https://my-config-server.example.com/sample-app/profile1/master
https://my-config-server.example.com/sample-app/profile2/master
and load the response from each request into a property source in the client app.
We have a spring boot application running in PCF and it reads the PCF environment variables(CF_INSTANCE_INDEX, CF_INSTANCE_ADDR,..) from an application. Based on those variables, we are trying to implement the logic for a scheduler. While running this scheduler, these variables' values could have changed. Is there a way to refresh/reload bean that have env values during runtime?
we used #RefreshScope annotation on config properties bean.
#Configuration
#RefreshScope
public class PcfEnvProperties{
#Value("${CF_INSTANCE_INDEX}")
private int intanceIndex;
#Value("${CF_INSTANCE_ADDR}")
private String intanceAddr;
...
}
and refresh using
context.getBean(RefreshScope.class).refresh("PcfEnvProperties");
PcfEnvProperties pcfEnv = context.getBean(PcfEnvProperties.class);
But It is not loading the recently changed env variable into running application. Any ideas on how to accomplish this?
You can use Spring Cloud Config Server in combination with Spring Actuator to expose an endpoint in your service that will refresh the application's properties on the fly. You could set up your scheduler to hit this endpoint on a timer or as needed.
Here is one tutorial I found that seems pretty straightforward: https://jeroenbellen.com/manage-and-reload-spring-application-properties-on-the-fly/
You may have to play with the setup depending on how your platform is configured, but I believe it should do what you're wanting. We have deployed many java web services on our PCF platform using this actuator/config server approach, and we can just make a call to the refresh endpoint and it successfully pulls in (and overwrites when necessary) the new properties and values from the config server. Also you can pull out a list of the property names and values that changed from the response.
I'm not familiar with the specific property values you mentioned, but as long as they are normally a part of Spring's ApplicationContext (where properties usually are found) then you should be able to pull in changed values using this approach with Spring's cloud config server and actuator libraries.
Hope this helps
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