Deploying Java applications without including production credentials in VC - java

Am using Maven and Jenkins to manage deployment of my web application. Essentially:
When deploy is triggered, CI box checks the code out of version control.
If code passes tests, it triggers the Maven release plugin to build a versioned war, and puts it in our local nexus repo
In same build, pulls the artifact from nexus, and copies the artifact into tomcat, triggering Tocmat to re-explode war.
This works fine, and using this technique I can use maven to replace the appropriate environment specific configurations, so long as they are within the project. However, my SysAdmin considers it a security risk to have production credentials in VC. Instead, we would prefer to store the production credentials on the production machines that will be using them. I can imagine writing a simple bash script to ssh into the service box, and soft link the conf file onto the classpath, but this seems like a pretty inelegant solution.
Is this reasonable? Is there a better/more standard way of acheiving this? Is it actually a security risk to hold production credentials in VC?

You have your conf file on your production server at some location. This location could be a property too.
If there is no specific reason for not loading it as a file from disk rather than loading as a resource from classpath, you could create a separate Maven profile production that would filter the location replacing it with the file path for your production server.

Yes, it's a security risk to have production credentials in version control. It frees your developers to do pretty much whatever they want to production. Regulations like HIPAA in medicine or PCI for e-commerce or SoX for public US companies would frown on that. Your sys-admin is reasonable to as well.
The basic strategy is to externalize this configuration and have the deployment process roll in the environment specific data.
Having that information on the production server itself is an ok, but not great solution. It's a good fit when you have just one target server. Once you have a bunch, there's a maintenance headache. Whenever env. specific data changes, it has to be updated on every server. You also need to be sure to only have env. specific information in there or else changes developers make to early environments may not be communicated to the sys-admin to change at deployment time leading to production deployment errors.
This is where, I think, Hudson lets you down from a continuous delivery perspective. Some of the commercial tools, including my company's uBuild/AnthillPro, formally track different environments and would securely let the sys-admin configure the production credentials and developers configure the dev credentials with the tool. Likewise the application release automation tools like our uDeploy that would pull builds out of Hudson and deploy them, should have this kind of per environment configuration baked.
In these scenarios, most of the property / xml files have generic config, and the deployment engine substitutes env. specific data in as it deploys.
Adding a new tool for just this problem is probably overkill, but the basic strategy of externalizing environment specific info into a central place where it can be looked up a deployment time could work. Since you're a Maven shop, you might consider stashing some of this in your Maven repo in an area locked down for access by only operations. Then pull the latest config for the appropriate environment at deployment time.
You have a range of options here. Consider how things vary by environment; what varies by server; what needs to be secured, what changes with time on the dev side, etc. And please, please, please sit down with your sys-admin and work out a solution together. You each have insight the other doesn't and the end solution will be better for the cooperation.

Related

Problems with the online / offline mode of the Spring Cloud contract tests

We are using Spring Cloud contract testing in a few projects because it has nice features and all our projects use Spring. However these tests are becoming quite unstable and the devs are just disabling them because they break the build even when there isn't any change on the interfaces.
We have the tests configured for Jenkins in online mode so they download the stubs from Artifactory. However quite often (at least twice per month) the tests crash because the stubs are already in the repository. We don't have access to the remote repository for deleting the stubs manually so we change the configuration for running them on offline mode. This works until the version of the provider changes as the tests cannot find the stubs for the new version locally and they crash again, and we change them again to the online mode.
As you may imagine this is not ideal and we are also worried because the local stubs may be for an outdate copy of the current version and we are not going to detect when the provider has breaking changes.
Is there a better way to configure the tests? It would be great if we could configure them so they always download the stubs and override the local ones.
Duplicate of Spring Cloud Contract remote artifact download clashes with local, how to make it temporary?
Let me copy the answer here too:
This problem might (it doesn't always happen) occur in CI systems when
you have a shared .m2. In the next release (1.2.x and 2.0.0), thanks
to closing of this issue
https://github.com/spring-cloud/spring-cloud-contract/issues/545 ,
you'll be able to pass stubrunner.snapshot-check-skip system property
or STUBRUNNER_SNAPSHOT_CHECK_SKIP environment variable or set the
plugin property (for 2.0.0 only) to disable the check.

where to store/keep configuration data for an Java Enterprise application

What is the best way to store parameters and data for an EE7 application. I have to provide the web applications with information like a member fee or similar data (which may/can be altered several times in a year). The owner of the application should also have a central place where these data are stored and an application to change them.
Thanks in advance for any input
Franz
This is one question we are currently struggling with as we re-architect some of our back-end systems here, and I do agree with the comment from #JB Nizet that it should be stored on the database, however I will try to add some additional considerations and options to help you make the decision that is right for you. The right option will depend on a few factors though.
If you are delivering source code and automation to build and deploy your software, the configuration can be stored in a source code repository (i.e. as YAML or XML) and bundled with your deployable during the build process. This is a bit archaic but certainly widely adopted practice and works well, for the most part.
If you are delivering deployable binaries, you have a couple of options.
First one is to have a predetermined place in the file system where your application will look for an "override" configuration file (i.e. home directory of the user used to run your application server). This way you can have your binary deployable file completely separate from your configuration, but you will still need to build some sort of automation and version control for that configuration file so that your customer can roll back versions if/when necessary. This can also be one or many configuration files (i.e. separate files for your app server, vs. the application itself).
The option we are contemplating currently is having a configuration database where all of our applications can query for their own configuration. This can either be a very simple or complex solution depending on your particular needs - for us these are internal applications and we manage the entire lifecycles ourselves, but we have a need to have a central repository since we have tens of services and applications running with a good number of common configuration keys, and updating these keys independently can be error prone.
We are looking at a few different solutions, but I would certainly not store the configuration in our main database as: 1) I don't think SQL is best repository for configuration, 2) I believe we can get better performance from NoSQL databases which can be critical if you need to load some of those configuration keys for every request.
MongoDB and CouchDB both come to mind as good candidates for storing the our configuration keys if you need clearly defined hierarchy for you options, whereas Redis or Memcached are great options if you just need a key-value storage for your configuration (faster than document based too). We will also likely build a small app to help up configure and version the configuration and push changes to existing/active servers, but we haven't spec'd out all the requirements for that.
There are also some OSS solutions that may work for you, although some of them add too much complexity for what we are trying to achieve at this point. If you are using springframework, take a look at the Spring Cloud Config Project, it is very interesting and worth looking into.
This is a very interesting discussion and I am very willing to continue it if you have more questions on how to achieve distributed configurations. Food for thought, here are some of my personal must haves and nice to haves for our new configuration architecture design:
Global configuration per environment (dev,staging,prod)
App specific configuration per environment (dev,staging,prod)
Auto-discovery (auto environment selection depending on requestor)
Access control and versioning
Ability to push updates live to different services
Roger,thanks a lot. Do you have an example for the version predetermined place in the file system"predetermined place in the file system"? Does it make sense to use a singleton which reads the configuration file (using Startup annotation) and provides then the configuration data? But this does not support a dynamic solution.kind regards Franz

How can I set a WebSphere classloader policy to PARENT_LAST for an app created in Eclipse?

Our company is currently using RAD to develop our Java apps, but we're looking to move to Eclipse with the WebSphere Developer Tools. The pilot for our transition is going pretty well, except we're running into a classloader policy issue for new applications that are originally created in Eclipse, not RAD. Our projects that were originally created by RAD are deployed with the correct classloader policy (PARENT_LAST) when published via Eclipse because we originally used the Deployment Descriptor Editor in RAD which set the proper classloader policy in /src/main/application/META-INF/ibmconfig/cells/defaultCell/applications/defaultApp/deployments/defaultApp/deployment.xml. But now with Eclipse & WebSphere Developer Tools, we no longer have the nice Deployment Descriptor Editor UI to create or modify this file for us (apparently it's not included with the WDT plugin).
So, my question then is what is the best way to go about setting this classloader policy? We still need some new apps to have the classloader policy of PARENT_LAST set when we deploy them to our local servers. Our team has though about this a bit and we can see 4 options at the moment.
Open the Admin Console after every publish and change it. This would be a huge pain, and is pretty much not even a real option.
Change the server profile setting to use a PARENT_LAST classloader policy for all apps. This however is not the case for all the apps at our company, and would not work for all groups.
Run a jython script after every publish to set the classloader policy. This is slightly better than option 1, but not by much.
Manually create a deployment.xml file in the same location as the other apps created by RAD with the same structure as the deployment.xml files created by RAD, and modify it as necessary for each app.
Option 4 seems to be the best of the bunch, but it's still a manual process and somewhat error prone. Even if most of our developers can grok this approach for new apps, it would be most ideal if this were a simple one button click type process.
So given the fact that IBM has omitted the Deployment Descriptor Editor from the WDT plugin it would seem as if option 4 is our only hope, but I'll ask once more, is there any other better way to set a WebSphere classloader policy to PARENT_LAST for an app when that app is created in Eclipse? Any help is appreciated, thanks.
Well, Eclipse is free, while Rational Application Developer costs about $5,000 per year (per developer). The nice Deployment Editor (which wasn't that nice. It tends to include all sorts of things that aren't needed. Who needs that Derby DataSource defined there, anyway?) is one of the things you have to give up for saving tons of cash on an annual basis.
I'm digressing.
Option (1) is a complete no-no. You don't want to rely on manual steps for deployments; you should strive to automate deployments to the extent possible.
Option (2) might do. I am not sure which flavour of WebSphere you're using, but if you're using the Network Deployment edition, then you can design a WebSphere topology that consists of multiple servers and clusters. You could, theoretically, come up with such a topology whereby PARENT_LAST applications run on a specific server (or cluster) and PARENT_FIRST applications run on another server (or cluster).
You may be able to combine option (2) with a technical initiative to have all of your applications work with PARENT_LAST. This is the recommended approach if your application is using popular third-party libraries that WebSphere happens to use as well (for its own internal purposes). For example, if you're using Commons Lang, then you're already recommended to switch to PARENT_LAST because WebSphere uses its own internal copy of Commons Lang that might conflict with yours.
Option (3) - it's of course better than option (1) but isn't necessarily worse than option (2) if you can get your WebSphere topology right.
Option (4) is harder to implement but I believe it's the best approach overall:
It's a one-time setup effort for each EAR (and for each WAR that exists within the EAR).
Once it's done, deployment can easily be automated as no extra steps are needed.
If you're working with a local test environment to test your code, and you're rapidly publishing applications from your workspace into your local test environment, then this approach is the only approach (other than option (2)) that will work for you without extra manual work.
If none works... consider paying $5,000 per year (per user) and get option (5) - use IBM's editor. Or, better off... hire someone to design an Eclipse plugin that will do that for you. Shouldn't take more than a week or two to develop.
um nether answer is useful.
Go into WAS console and pick your application; example:
Enterprise Applications > my_application_ear > Class loader AND change the "class loader order and WAR class loader policy"
Open the admin console within eclipse click server >> your server >> scroll down and under server infrastructure >> java process management select class loader >> select new you can change it here

What's a practicable way for automated configuration, versioning and deployment of Maven-based java applications? [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
we're maintaining a medium sized code base consolidated into a single multi(multi)-module maven project. Overall the whole build has up to ten output artifacts for different system components (web applications (.war), utilities (.jar), etc.).
Our deployment process so far is based on simple bash scripts that build the requested artifacts via maven, tag the scm repository with information regarding the artifacts, the target environment and the current build timestamp and then upload the artifacts to the chosen environments application servers and issue commands to restart the running daemons.
Configuration of the built artifacts happens by means of maven profiles and resource filtering. So our builds are specific to the target environment.
This process has served us well but for different reasons I would like to move forward towards a more sophisticated approach. Especially I would like to get rid of the bash scripts.
So what are the best practices regarding configuration, versioning and deployment of Maven-based Java applications?
Should our builds be environment agnostic and the configuration be done via config files on the target systems? If so how would a developer take care that new configuration options are included in the deployed config files on the various application servers?
Should we use Maven-versioning a.k.a. Maven release plugin to tag the various builds?
Is it a good idea to configure a CI server like Jenkins or Teamcity to build and optionally deploy our artifacts for us?
I like to think of there being two problem spaces:
building artifacts (ideally environment agnostic as that means QA can take a hash of the artifact, run their tests on that artifact and when it comes time to deploy, verify the ash and you know it's been QA'd. If your build produces different artifacts depending on whether for QA's env or the staging env, or the production env, then you have to do more work to ensure the artifact going into production has been tested by QA and staged in staging)
shipping artifacts into an environment. Where that environment requires configuration of the artifacts, the shipping process should include that configuration, either by putting the appropriate configuration files in the target environment and letting the artifacts pick that up, or by cracking open the artifacts, configuring them, and sealing them back up (but in a repeatable and deterministic fashion)
Maven is designed for the first problem space. "The Maven way" is all about producing environment agnostic build artifacts and publishing them to a binary artifact store. If you look at the Maven lifecycles, you will see that the phases stop after the artifact is deployed to the Maven repository (a binary artifact store). In short, Maven sees its job as done at that point. Additionally, there are life cycle phases for unit testing and integration-testing both of which should be possible with an environment agnostic artifact, but that is not the full set of testing that you require... Rather to complete your testing you will need to actually deploy the built artifacts into a real environment.
Many people try to hijack Maven to move beyond its goal (myself included). For example you have the cargo-maven-plugin and the ship-maven-plugin which touch on aspects beyond the maven end game (ie after the artifact gets to the maven repository). Of these, I feel personally, that the ship-maven-plugin (which i wrote, hency my previous "myself included") is closest to use "after maven" because by default it is designed to operate, not on the -SNAPSHOT version of the project that you have checked out on disk, but rather on a release version of the same project that it pulls from the remote repository, eg
mvn ship:ship -DshipVersion=2.5.1
IMO, cargo is aimed at use around the integration-test phase in the life cycle, but again, you can hijack it for other purposes.
If you are producing shrink-wrapped software, ie the kind that a user buys, and installs on their system, the installer program itself is designed to configure the application for the end users environment. It is fine to have the Maven build produce the installer because the actual installer is (at least somewhat) environment agnostic. Ok it may be a Microsoft Windows only installer, or a Linux only installer, but it does not care about which users machine it gets installed on.
Now days, though, we tend to concentrate more on Software as a Service, so we are deploying the software onto servers that we control. It becomes more tempting tow to to the "Maven dark side" where build profiles are used to tweak the internal configuration of the build artifacts (after all we only have three environments we deploy to) and we are moving fast so don't want to take the time to make the application pick up the environment specific configuration from external to the built artifact (sound familiar?). The reason I call this the dark side is that you really are fighting the way maven wants to work... You are always wondering if the jar in the local repository was built with a different profile active, so you end up having to do full clean builds all the time. When it comes time to move from QA to staging or from staging to production, you need to do a full build of the software... And all the unit and integration tests end up being run again (or you end up skipping them and in turn skipping the sanity they may be providing on the artifacts they are building) so in effect you are making life harder and more complex... Just for the sake of putting a few profiles into the maven pom.xml... Just think, if you had followed the maven way you'd just take the artifact from the repository and move that along the different environments, unmodified, unmolested, and with MD5, SHA1 (and hopefully GPG) signatures to prove that it is the same artifact.
So, you ask, how do we code the shipping to production...
Well there are a number of ways to tackle this problem. All of them share a similar set of core principles, namely
keep the recipe for shipping to an environment in a source control system
the recipe should ideally have two parts, an environment agnostic part, and the environment specific part.
You can use good old bash scripts, or you can use more "modern" tools such as chef and puppet which are designed for this second problem space.
Recommendations
You should use the right tool for the right job.
If it were me, here's is what I would do:
Cut releases with the Maven Release Plugin
The built artifacts should always be environment agnostic.
The built artifacts should contain "sensible defaults" for all configuration options. In other words, they should either blow up fast if a required configuration option with no sensible default is missing, or they should perform in a sensible way if an optional option is unspecified. An example of a required configuration option might be the database connection details (unless the app is happy to run with an in memory DB)
Pick a side in the chef vs puppet war (doesn't matter which side, and you can change sides if you want. If you have and ANT mindset, chef may suit you better, if you like dependency management magic, puppet may suit you better)
Developers should have a say in defining the chef/puppet scripts for deployment, at least the environment agnostic part of those scripts.
Operations should define the production environment specific details of the chef/puppet deployment
Keep all those scripts in SCM.
Use Jenkins, or any CI, to automate as much of the steps as possible. The promoted builds plugin for Jenkins is your friend.
Your end game is that every commit, providing that it passes all required tests, *could * get deployed into production automatically (or perhaps with the gate of a person saying "go ahead")... note not saying that you actually do this for every commit, only that you could
What I have used in the past which work well is to use Apache Karaf+iPOJO with my version control which was subversion (I would use git today)
What the version control allowed be to do was deploy a versioned copy of Apache Karaf and my configuration files. Any changes made from development or on the production system (when something needed an urgent fix) would still be traced and could be checked in (including information about who made what change when)
What Apache Karaf supports is dynamic deployment of maven libraries from your maven repository. i.e. you have configuration files which specify the versions of jar you want tot release and it will download them as required from your maven repo and run them. The iPOJO adds components for these models which you can configure using properties values (again versioned)
This assumes you have control of the end-to-end development to deployment, but can work very well even with multiple remote sites.

Pass in env specific properties into a webapp

We are looking for deployment options for our continuous integration system for our webapp. We are building a single .war file. We need to deploy it across several different envs (e.g. DEV, QA, STAGE, etc). AFAIK, there are two ways to pass in the env specific properties:
First, use the -D option when starting Tomcat:
-Denv=DEV
This require us to customize the catalina.sh script for every env.
Second, use the environment variables before launching Tomcat:
export env=DEV;
This require us to tweak the deployment script for each env. And this is platform dependent (i.e. on Windows you'll have to do set env=DEV).
Can anyone tell me which of these two options is better? Or is there any other better ones?
We have a web app which is deployed into 14 different environments. To manage this, we create a unique build for each environment.
We are using maven as a build system, so each environment has a unique profile. The profile references a properties file for filtering which contains configuration that varies across environments. This information is tokenized into Spring context files, web.xml, weblogic.xml, etc. (We do not filter source files as this gets ugly fast.)
The second piece of this is our Jenkins CI server. We have a job for each environment which references the corresponding profile. This points to a well-known tag name in our subversion repo. So the flow goes like this:
Development happens and code committed to trunk.
Need to build into some env, so we create a tag called "latest" (removing old copies if they exist). At the same time, we also create a tag with a date-time stamp, but this is optional.
Kick-off the appropriate hudson build. This means we are not building off some developers workstation, and the build is already configured so there is nothing to remember.
Pull the artifact to deploy right out of Jenkins.
I've seen application configuration maintained within the app server itself, but unless you have something like glu to manage things, it quickly becomes a nightmare to maintain. This is especially true if you have different teams for development and ops.

Categories