I'm looking for a java argument (or perhaps some different method) to allow me to specify a file to be used by the JVM as the java.security file, rather than using the one found in the JDK (in the JRE lib).
To give you a little more context, I am working with a WebLogic server that was set up by someone else and is running two (or more) different JVMs off the same JDK. We have run into an issue now where the work I'm doing on one JVM requires a different java.security file than the one that is currently being used by the other JVM. I am hoping there will be a way for me to just point my JVM at a new java.security file without having to point it at an entirely new JDK (due to space constraints, we would like to avoid uploading a JDK specific to each JVM).
I realize that the server's set up is not ideal, but completely rearranging the existing set up is not viable and not something I am in a position to do. So, I am hoping someone might have a creative solution that would allow for multiple JVMs running off the same JDK but with different security configurations.
I have been trying to find solutions out there, but it seems my Google-Foo is not as strong as I had hoped. Here's to hoping one of you has the answer!
Many thanks.
EDIT
Sorry maybe my original post was not clear, but I am interested in specifying the java.security file, also often referred to as the Java master security properties file, not the java.policy file which is found in the same directory.
My Solution
I will post my solution here just for reference of others who might fall into a similar situation.
As I can't seem to find an argument to specify at start up, I have decided that I will have to forgo the java.security properties file. It is possible to set properties and providers (typically configured in the file) within code using the Security class (java.security.Security). So, at least in the interim, I plan to write a class that will go through setting up my JVM specific security configurations after startup (essentially overwriting the default configurations provided by the file for the other JVM). While the obvious downside of this solution is that is does not externalize security configurations of this JVM, the solution does provide me a way to set JVM specific properties and providers without affecting the configuration of other JVMs running off the same JDK.
I appreciate the time and consideration given by others. Thanks =)
Looking at the OpenJDK source, you cannot change the loading of the java.security file. However, that file has a property called security.overridePropertiesFile which, if set to true (as it is in my current, vanilla install), allows you to load an additional security properties file specified through the system property named java.security.properties. Note also, that the command line syntax follows a similar pattern to the policy file where = specifies additional configuration and == specifies a complete replacement configuration.
Maybe the accepted answer on this thread would help you out; basically it says that you need to specify your own policy file and the final invocation should look like:
java -Djava.security.manager -Djava.security.policy=/some/path/my.policy
You can just set the system property -Djava.security.properties=***** to specify the security property you want to load, but you must set the property security.overridePropertiesFile=true prior to use this approach.
Related
Due to design constrains the project I am currently working on won't allow us to write certain set of configuration parameters in plain text file such as properties files (mainly due to security constrains).
Is there any way to conceal this configuration parameters in order for them just to be accessible to the code programmers. A plain Java object is so far my only idea.
Also, it's worth noticing that hard-coding values is not a good solutions for us, given there are many 'sub-applications' that requiere their own configuration. In this point consider some kind of resource bundle but that will still have the original problem.
EDIT: So I came across Jasypt as proposed here, nonetheless I think that for my case saving this in some kind of obfuscated file is sufficient since it is all we need in order to make the user stop tampering with configuration files.
Use environment variables:
String value = System.getEnv(myKey);
which are defined at the OS via export foo=bar (*nix) or SET foo=bar (windows), or system properties:
String value = System.getProperty(myKey);
which are defined on the java command line, eg java -DmyKey=myValue ...
Right now my team deals with about 4-5 different servers and about 2-3 different DB servers and we're using environmental variables to decide which server we're on and what server configuration to use.
Is there a better way to do this as my team continues to expand? I've considered compiler flags / args, but it doesn't seem as robust.
From my perspective, in java, you have basically 3 ways to crack this cookie:
Environment variables
-D JVM parameters (which are System Properties)
properties files
You've already discovered Environment Variables and that is pretty much "the unix way" to get the effect you are after; different configuration to common binary that customizes the running application for the environment it is executing on.
System Properties are really the Java "moral equivalent" of Environment Variables. They come in via -D parameters on your application's command line like...
java -Dlogback.configurationFile=/opt/dm/logback.xml -cp app.jar org.rekdev.App
Explicit Properties file processing http://docs.oracle.com/javase/tutorial/essential/environment/properties.html in Java is a third variant which you often see coupled with -D to get something like default behavior which can be overridden at runtime from the command line. That is what is basically going on with the logback.xml configuration above, the JAR file has a logback.xml inside it that will be used unless a System Property called "logback.configurationFile" exists, at which point the App will load it instead.
As you try to figure out how to keep this all in sync and working correctly in a multi-server environment, consider the use of chef http://wiki.opscode.com/display/chef/Home to do the deployments and put each specific environment's customizations under chefs control. Put the chef "recipes" in version control and, voila, full on configuration management.
SHIP IT!
I can see two scenarios
You embed all the different properties within your package (can be a war, ear, jar, or on the file system /yourapp/etc/)
You embed only one property file and this one is created during build (with ant or maven)
Say your app is named foo
Solution 1
It has the advantage that your app can be put as-is on any of the supported servers (all that have a property file in your app package).
Your properties will be named foo.dev.properties, foo.test.properties, foo.prod.properties, foo.damien.properties, foo.bob.properties.
One other advantage is that every developer working has its own dev file that he can safely push on svn/git/whatever and be sure that other developer won't destroy his config.
At runtime the application can check the -D parameter or even retrieve the hostname dinamycally, in order to load the correct property file.
Solution 2
It has the advantage that your package is not polluted by unnecessary properties files.
You must configure a lot of ant tasks/maven target in order to build for specific environment. You will have in your source directory the properties files for the environments also, but only one will be shipped with your app. This one foo.properties will only have placeholders for values, and values will be inferred within it using foo.ENV.properties with the right ant task/maven target.
At my actual job and the previous one also, we did use the solution 1, I think it brings flexibility.
Some parameter (like database user/password) were fetched directly from environment variables on the Unix servers though (so that only the server admins knew the credentials).
You can safely mix the solutions, in order to get where you feel there is the more flexibility for you and your team.
It is possible using -Dproperty=value arguments to set arbitrary system properties (not some fixed set of system properties actually used by the JVM) and a program can get these properties later using System.getProperty("property"). Is it correct to do this?
I haven't found an authoritative answer on this, so that's why I'm asking here. It seems to me that program parameters should be set through command line arguments to the program, not to the JVM. However, perhaps this is an accepted practice that just isn't documented anywhere I've looked so far. I'd like to be sure. Thanks.
I think Java system properties are used to pass values from command line to libraries or plugins inside the execution. It is, that insider component has no direct way to receive the parameter from the main program that's executing it. So it reads it from a "context" that Java system properties are.
If we look at it as layers, command line arguments would be parameters for the inmediate lower layer, and system java properties are context for all the lower layers.
command line: arguments + properties
main program: uses arguments
some library/plugin: uses properties from context
If it's not this way the main program should have to carry all the parameters that user could set to the lower layers and it can be very cumbersome.
I don't like to depend on contextual properties so if I design a program I'd try to pass over all the properties in some non-global way. But it can be very handy some times (and using namespacing it's not probable they collide).
In my opinion this is not "incorrect" and there are programs and libraries that do use their own system properties for configuration.
However, it is probably more practical to put configuration parameters for your software in a configuration file (in whatever format you think is suitable - a .properties file, an XML file, or something else). It is cumbersome, especially if you have many configuration parameters, to have to put all those parameters on the command line with -Dname=value options.
You can use this method to set some of your application settings. I think of settings as a contrast to program arguments. For example. Let's think abount some file converter. It converts file A to B. So files A and B should be command line params. If you converter needs some temporary folder you can make id settable by -Dmy.package.tempfolder=\my\tmp\folder. But there should be a default setting for that and the program should work without this setting.
Think about it as an alternative to .properties file. .properties file will be more convinient of course.
You just have to know what you're doing. If your application is a standalone application, system properties provide an easy to use way to pass named arguments, in any order, to the program, and I don't see anything intrinsically bad in using them.
If your app is a webapp that must be deployed in a app server shared by multiple webapps, then it might not be a good idea, especially if you aren't allowed to change how the server is started, or if you have to deploy multiple versions of the same application.
From http://docs.oracle.com/javase/tutorial/essential/environment/sysprop.html:
For example, the following invocation of getProperty looks up the
System property called subliminal.message. This is not a valid system
property, so instead of returning null, this method returns the
default value provided as a second argument: "Buy StayPuft
Marshmallows!"
System.getProperty("subliminal.message",
"Buy StayPuft Marshmallows!");
This implies that properties other than those used by the JVM are "invalid". However, later in the same document, it gives the example of loading a properties file containing the same property setting.
subliminal.message=Buy StayPuft Marshmallows!
It only advises "In general, be careful not to overwrite system properties."
So it seems that this is a supported use of System Properties. It looks like a case of misleading naming. When I hear "System Properties" I think "properties of the JVM" where the JVM is the system. While the properties are used for this, they can also be used for application settings. I think I'll make a mental note to think of this as "System and Application Properties".
Does anyone disagree with this?
I have a JAR-packaged standalone application that, when executed, unpacks itself into a temporal directory and spawns a child process within that directory. The reason being some third-party code and configuration assumes data files are found relative to current working directory, and java has no chdir() method, so the only way is to switch the working dir for a child process.
All works fine, except for the system properties. An operator may decide to specify some system properties in the command line, both standard ones and ones related to the third-party configuration:
java -Djava.io.tmpdir=/temp -Dsomething=else -jar foo.jar (parameters)
The system properties available to the parent java process are not by default propagated to child. I should do it myself. And here I get into a roadblock: I have no way to tell which properties are set by operator and which are initialized by default by JVM.
Take that java.io.tmpdir one. If operator has provided it, he has a good reason to do so (perhaps the default location is "disk full"). I have to set it to child process, or it will fail. But how do I know if it came from operator? It may be just the default value.
I may try and set all available system properties to the child process. It takes a long list though and, worse, fails in some environments where the command line length is limited.
The only workaround I've found so far (quite a wicked one) is to spawn another child process first, with no arguments at all, and let it pipe back to the parent all the system properties it has. The values that match those that parent has are defaults. The rest should be passed down to the worker child process.
Does anyone have a better alternative?
Where I work, we had a slowly growing list of system properties that users could apply, and while we did not have the child process to worry about, we did have a different issue: there were simply too many.
Rather than making the user supply system properties via the command line (or, in our case, making the line in the script that launches the application yet another property longer), we added support for loading a .properties file by default.
If you can convince users to put permanent properties there, then start the process of launching the child process, and then loading from the file, you could avoid the headache altogether.
Still, you would likely be presented with debug scenarios where temporary, or one-time properties are desired without modifying the file (not that it's really a big deal). You have a few choices here:
Continue to use the approach you are currently.
Get the user to pass the system properties as command line arguments that you then load into system properties for both the parent and child process.
Say tough, use the file. (Not a terrible thing, but I would be annoyed with that solution as a user)
I don't think there is a good answer to this. But fortunately, most of the standard system properties either can't be overridden, or nobody in their right mind would override.
So the following approaches are probably your best bets:
pass on the subset of the standard properties that you think that it makes sense to pass on,
provide a way to specify the JVM options (including -D options) to be used for child JVMs, or
a combination of the above approaches.
Chosen solution:
I still had to go with a child process that does nothing but passes the parent all the system properties it gets to compare. The only minor issue I stumbled upon was line.separator property which caused my line reading code stumble on extra empty line. That was easy to fix.
Why I accepted none of answers:
Approaches suggested in the answers below are reasonable, but none of them is completely satisfying.
I do not have much power over the users to tell them that Java system properties should be passed via a property file or a special command-line argument. This is awkward and goes against operational practices (special cases are always bad).
I cannot also select a subset of system properties to pass to the child process. System class documentation doesn't tell which ones are OK to overwrite (and common sense replaces no documentation). There is also a facility for end-user to define their own properties, and those I cannot predict neither by name no number.
I'm looking for a java argument (or perhaps some different method) to allow me to specify a file to be used by the JVM as the java.security file, rather than using the one found in the JDK (in the JRE lib).
To give you a little more context, I am working with a WebLogic server that was set up by someone else and is running two (or more) different JVMs off the same JDK. We have run into an issue now where the work I'm doing on one JVM requires a different java.security file than the one that is currently being used by the other JVM. I am hoping there will be a way for me to just point my JVM at a new java.security file without having to point it at an entirely new JDK (due to space constraints, we would like to avoid uploading a JDK specific to each JVM).
I realize that the server's set up is not ideal, but completely rearranging the existing set up is not viable and not something I am in a position to do. So, I am hoping someone might have a creative solution that would allow for multiple JVMs running off the same JDK but with different security configurations.
I have been trying to find solutions out there, but it seems my Google-Foo is not as strong as I had hoped. Here's to hoping one of you has the answer!
Many thanks.
EDIT
Sorry maybe my original post was not clear, but I am interested in specifying the java.security file, also often referred to as the Java master security properties file, not the java.policy file which is found in the same directory.
My Solution
I will post my solution here just for reference of others who might fall into a similar situation.
As I can't seem to find an argument to specify at start up, I have decided that I will have to forgo the java.security properties file. It is possible to set properties and providers (typically configured in the file) within code using the Security class (java.security.Security). So, at least in the interim, I plan to write a class that will go through setting up my JVM specific security configurations after startup (essentially overwriting the default configurations provided by the file for the other JVM). While the obvious downside of this solution is that is does not externalize security configurations of this JVM, the solution does provide me a way to set JVM specific properties and providers without affecting the configuration of other JVMs running off the same JDK.
I appreciate the time and consideration given by others. Thanks =)
Looking at the OpenJDK source, you cannot change the loading of the java.security file. However, that file has a property called security.overridePropertiesFile which, if set to true (as it is in my current, vanilla install), allows you to load an additional security properties file specified through the system property named java.security.properties. Note also, that the command line syntax follows a similar pattern to the policy file where = specifies additional configuration and == specifies a complete replacement configuration.
Maybe the accepted answer on this thread would help you out; basically it says that you need to specify your own policy file and the final invocation should look like:
java -Djava.security.manager -Djava.security.policy=/some/path/my.policy
You can just set the system property -Djava.security.properties=***** to specify the security property you want to load, but you must set the property security.overridePropertiesFile=true prior to use this approach.