How to change Play 2 Framework DB configuration at runtime? - database

We are using Play 2.1.1 and its built-in JPA integration (JPA.em()
etc).
How can we dynamically change the db.pass property? Play.application().configuration() seems
to be immutable as of Play 2.1. (or we're at least not aware of the mutators)
If we are able to change db.pass, how can we reload the DB configuration so that JPA.em() returns an EntityManager using the new password?
What we are trying to avoid is having to recreate the EntityManager using
EntityManagerFactory. We want to continue to let Play manage that in
the JPA helper class.
Background
The system has a default DB configuration for running locally. When deployed to a server, the DB password is dynamically set on the running application using the following script:
#!/bin/bash
stty -echo
read -p "Password: " PASS
stty echo
curl -k https://127.0.0.1:8443/someUrl/pwd --data "password=$PASS"
The application receives this data and then recreates the Hibernate
SessionFactory. Our new Play app will be required to do something
similar.

The key is to use the ConfigFactory to create a new Config entry. This new Config contains an entry for password with the value coming from your http call to your password service.
A new Configuration is created using the new Config, which in turn falls back to the original Config from the original Configuration.
Basically the new password entry supersedes the original.
It sound long winded when you say it, but the code is pretty readable.
public class Global extends GlobalSettings {
// inject http client to make call for password
#Override
public Configuration onLoadConfig(Configuration configuration, File file, ClassLoader classLoader) {
final Config config = ConfigFactory.parseString(String.format("db.default.user=%s", callPasswordService()));
return new Configuration(config.withFallback(configuration.getWrappedConfiguration().underlying()));
}
}

To answer my own question, at first we solved the problem of updating the immutable configuration at runtime by overriding Configuration.onLoadConfig with the following:
If configuration indicates that production.level is PROD
Read the password from stdin
Create a new configuration by converting the old one to a map and building a new one with ConfigFactory.parseMap, with the new parameter as well
Return super.onLoadConfig
However, this still didn't address that the problem of reloading the DB configuration. In the end, my colleague created a Play! plugin which essentially a copy of some JPA classes with the added capability of being reloaded with a Map of configuration properties.
Update
The "hook" is the additional static method which the plugin adds to the JPA class (e.g. reloadWithProperties). This method creates a new data source which is then rebound in JNDI.

Related

Shiro how to secure the data source password

I have been exploring Apache Shiro with Zeppelin and so far has been able to make authentication work with JdbcRealm but one thing that is not going well is giving the data source password as plain text.
Is there a way to avoid that?
My shiro.ini looks like:
[main]
dataSource = org.postgresql.ds.PGPoolingDataSource
dataSource.serverName = localhost
dataSource.databaseName = dp
dataSource.user = dp_test
dataSource.password = Password123
ps = org.apache.shiro.authc.credential.DefaultPasswordService
pm = org.apache.shiro.authc.credential.PasswordMatcher
pm.passwordService = $ps
jdbcRealm = org.apache.shiro.realm.jdbc.JdbcRealm
jdbcRealmCredentialsMatcher = org.apache.shiro.authc.credential.Sha256CredentialsMatcher
jdbcRealm.dataSource = $dataSource
jdbcRealm.credentialsMatcher = $pm
shiro.loginUrl = /api/login
[roles]
admin = *
[urls]
/** = authc
Is there a way to avoid giving data source password as plain text
dataSource.password = Password123?
Would like to give something like:
$shiro1$SHA-256$500000$YdUEhfDpsx9KLGeyshFegQ==$m+4wcq4bJZo1HqDAGECx50LcEkRZI0zCyq99gtRqZDk=
yes, there is a way, but there will still be a password lying around somewhere due to the nature of shiro needing to know the password.
Why Hashing does not work
You posted
something like: $shiro1$SHA-256[…]
This is a hash, and thus it is not reversible. There is no way shiro could log into the datasource using this String.
Container managed datasources
The best approach I can recommend at this point is to have a container managed resource. A container is referring to a (web) application server in this case, like tomcat, OpenLiberty or Wildfly.
For your use case, try looking into the following:
extend org.apache.shiro.realm.jdbc.JdbcRealm or AuthorizingRealm
Add the JPA API to your module and inject a persistence context like so:
#PersistenceContext
EntityManager entityManager;
Override the methods
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals)
… to load from your managed datasource instead.
Drawbacks of this approach:
You just delegated datasource login to your container / application server. The server is still facing the same problems. E.g. with OpenLiberty, you will still need to store a master key of an encrypted (not hashed) password somewhere, and thus liberty will do exactly this.
use another configuration source
Instead of using a shiro.ini file, you could also write your own environment loader. You could request the file from an IP-restricted web service or a cryptographic hardware device.
Always a goal: restrict the environment
You should always restrict the environment.
E.g. create a user which can install, but not run your application and who cannot read the logs (called setup-user or so).
Create another user which can start the application, read but not modify configuration files and write logs, called a run-user.
Restrict access to configurations and logs for all other users on that system.
Getting involved
If you have other needs, feel welcome to discuss other solutions on the shiro mailing lists.

How to test Spring database down?

I have this SpringBoot server app using PostgreSQL database if it's up and sending error response if it's down. So my app is running regardless the database connection.
I would very much like to test it (jUnit / mockmvc).
My question is very simple, yet I did not find the answer online:
how does one simulate a database connection loss in SpringBoot?
If anyone wants, I can supply code (project is up at https://github.com/k-wasilewski/workshop/)
Have you thought of Testcontainers? You can spin up your docker image through a Junit test and make your spring boot use that as your database.
Since you use junit, you can start/stop this container at will.
This will generate a test which creates the condition you are looking for and write code as to what to expect when the database is down.
Here are some links to get started,
Testcontainers and Junit4 with Testcontainers quickstart - https://www.testcontainers.org/quickstart/junit_4_quickstart/
Spring boot documentation - Use Testcontainers for integration testing
https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-testcontainers
Testcontainer github link example for springboot app
https://github.com/testcontainers/testcontainers-java/tree/master/examples/spring-boot
Testcontainer - Generic container javadoc. You can find methods for start/stop
container here. call from your Junit.
https://javadoc.io/static/org.testcontainers/testcontainers/1.12.4/org/testcontainers/containers/GenericContainer.html
You can implement your own Datasource based on DelegatingDataSource and then let it throw exceptions instead of delegating when ever you want to.
I've done this before by creating a Spring Boot test configuration class that created the DataSource and wrapped it in a Java proxy. The proxy simply passed method calls down to the underlying DataSource, until a certain flag was set. Once the flag was set, then any method called on the proxy would throw an exception without calling the underlying DataSource. Essentially, this allowed me to "bring the database down" or "up" simply by flipping the flag.

How can you access Azure Web App AppSettings from a React app at run time

I have a React app created with create-react-app which I have deployed to an Azure Web App. There is no back-end: the site is purely 'static'.
In the production environment, there are a number of keys to API services and other secrets that I need to keep secure, but which the client app needs to be able to read.
In React there's a mechanism for accessing environment-specific information using .env files, such as .env.production, but this is not suitable for keeping secrets, as environment variables mentioned in the code are substituted with the actual value from the .env file during the build process, and are consequently visible to anyone looking at the JavaScript in their browser.
Setting the values of the AppSettings can be done on the Azure Portal (or via suitable scripting in the CI/CD pipeline), but how can I read the AppSettings values at runtime?
A number of StackOverflow questions have been asked about this, but none of the answers address the fundamental question properly, or seem to miss the point. For example, here and here.
First off, this topic is puzzling lot of developers around the globe and it should be addressed properly in Aspnet Core. One viable option would be to set up Server-Side Rendering, but there are some of us who wouldn't benefit from it. Also, there are no proper examples for doing it for ReactJS + Redux in Aspnet Core world.
My solution is to go for a InMemoryFileProvider, see https://github.com/dazinator/Dazinator.AspNet.Extensions.FileProviders for details about the NuGet package.
To start using one, in my Configure() I'll do a:
configuredSpaFileProvider = CreateFileProvider(env);
app.UseSpaStaticFiles(new StaticFileOptions
{
FileProvider = configuredSpaFileProvider
});
My CreateFileProvider() contains an instantiation of InMemoryFileProvider-class, which can be populated with additional fake "files". Pre-existing static file on filesystem will be served with a PhysicalFileProvider.
To allow access to index.html, CSS, JavaScript and all possible static files, do what a DefaultSpaStaticFileProvider would do:
var defaultPath = "build";
if (env.IsDevelopment())
defaultPath = "public";
var absoluteRootPath = System.IO.Path.Combine(
env.ContentRootPath,
$"{ReactJSdirectory}/{defaultPath}");
var physicalFileProvider = new PhysicalFileProvider(absoluteRootPath);
Then create a provider and virtual file like this:
var inMemoryProvider = new InMemoryFileProvider();
inMemoryProvider.Directory.AddFile("/", new StringFileInfo(configJsContent, "app.config.js"));
Finally glue them together, prioritizing on the virtual files:
return new CompositeFileProvider(inMemoryProvider, physicalFileProvider);
Now that a dynamic JavaScript-file exists, it needs to be accessed on client-code. There are options for this, but I'll simply do a:
<script src="/app.config.js" async defer></script>
in my index.html. The trick is to construct a string with suitable JavaScript-parseable content setting up variables and storing them into window-object and accessing them later on a client.
Now my 12 factor application is fully compliant with third factor "Store config in the environment".

Initialize Database connection in Jersey REST webapp

I want to make database queries in my Jersey REST webapp. The ideal situation would be to find a way where the database connection is initialised once at the first app run. Afterwards I only get the instance of DAOFactory object in my REST class and make the queries in the methods. I am using mysql connector. Is there a way to find a way to do it in Jersey? In JSF it was possible - I just used an application-scoped bean when I run the code. Moreover it would be good if I could access the ServletContext object inside this method cause I would like to use it's getResourceAsStream() method to read the database connection parameters from WEB-INF/dao.properties file. But the 'only once per app initialisation' is the crucial part here.

EFCodeFirst 4.2 and Provider Manifest tokens

I have a library that I have created that depends on EF Codefirst for DB interaction. I am also using EntityMigrations Alpha 3. When I use the library in my main application (WPF) everything works fine and as expected. Another part of the system uses Excel and retrieves information using the same library via an additional COM class in between.
In the Excel scenario, as soon as it tries to connect to the database, it throws up an exception to do with "The Provider did not return a ProviderManifestToken".
I'm really not sure why I'm only getting the error when I go through Excel/COM. In both scenarios I can confirm that the same DB connection string is being used. THe method to retrieve the DB Connection string is also the same - they use a shared config file & loader class.
Any suggestions welcome.
Issue resolved.
I had also created a custom DBIntializer and part of the intialization calls upon EntityMigrations to ensure the DB is up to date. The custom migration calls the default constructor on your context. By convention this will either dynamically use it's own connection string for SQLExpress(I don't have installed) or try to look for an entry in your config file (I don't have this either for the dll - config comes from hosting apps).
This is what is causing the failure when being used from Excel(In my scenario). The Migration will be newing up an instance of the context using the default constructor. This means that a config entry for the connection string is required or it uses the default process(SQLExpress). When being used from Excel in a COM env – no config file exists.
Moving the migration out of the Initialization strategy means I no longer have a problem.

Resources