21 February 2011

Using Secure Config Files with the WebLogic Maven Plugin


WebLogic Server has long had a mechanism to provide a more secure way of connecting to the Administration Server from client utilities such that the username and password do not need to be specified and therefore can’t be seen from the process list or command shell history.

This secure config authenticaiton mechanism works by first storing the username and password in encrypted form in an external file, and then using this later as the input credential with which to connect to the WebLogic Server domain,  along with the key that was used to encrypt the file. 

** From a security perspective,  controlling access to these files is vital since they permit connection access to the server, but that’s not the focus of this blog.

Securing Access from WLST Online:
http://download.oracle.com/docs/cd/E17904_01/web.1111/e13715/using_wlst.htm#i1092142

Utility weblogic.Deployer, User Credential Arguments:
http://download.oracle.com/docs/cd/E17904_01/web.1111/e13702/wldeployer.htm#DEPGD325

WLST, storeUserConfig Command:
http://download.oracle.com/docs/cd/E17904_01/web.1111/e13813/reference.htm#WLSTC428

WLST, Connection Examples:

http://download.oracle.com/docs/cd/E17904_01/web.1111/e13813/reference.htm#WLSTC157

This security mechanism is particularly interesting with the use of WebLogic Maven Plugin. 
In order to connect to the Administration Server to perform the desired deployment operation, the weblogic-maven-plugin  must supply valid credentials.  For quick and simple cases, this is typically done by specifying the username and password directly in the Maven pom.xml file. 

Here is an example:

<project>    
...      
  <properties>        
  <weblogic.adminurl>t3://localhost:7001</weblogic.adminurl>    
  <weblogic.user>weblogic</weblogic.user>        
  <weblogic.password>welcome1</weblogic.password>    
  </properties>  
...      
  <plugin>        
    <groupid>com.oracle.weblogic</groupid>         
    <artifactid>weblogic-maven-plugin</artifactid>         
    <version>10.3.4</version>          
    <configuration>             
      <adminurl>${weblogic.adminurl}</adminurl>             
      <user>${weblogic.user}</user>             
      <password>${weblogic.password}</password>                                
      <source>                 
${project.build.directory}/${project.build.finalName}.${project.packaging}             
      </source>             
      <name>${project.build.finalName}</name>          
    </configuration>     
  </plugin>    
...
</project>

As can be clearly seen, this results in the username and password entries being stored in clear-text form in the pom.xml file.

To avoid this password exposure, it would be ideal if the secure connection mechanism described above could be used, replacing the clear text username and password entries with the respective external userConfig and userKey files that specify the credentials that are used to perform the connection.

The documentation for the WebLogic Maven Plugin doesn’t explicitly describe this as a connection option for any of the goals it exposes:

http://download.oracle.com/docs/cd/E17904_01/web.1111/e13702/maven_deployer.htm#BABFHAID

But it does contain a reference to the weblogic.Deployer guide for additional usage information:

http://download.oracle.com/docs/cd/E17904_01/web.1111/e13702/wldeployer.htm#g1048318

Which in turn, does support the use of the userconfigfile and userkeyfile parameters to specify the connection credentials:

http://download.oracle.com/docs/cd/E17904_01/web.1111/e13702/wldeployer.htm#i1024421

Looking at the Mojo classes in the weblogic-maven-plugin.jar file, which implement the goals exposed by the plugin,  we can see that there is support for all these additional properties being set on the Mojo by Maven:

public class weblogic.tools.maven.plugins.DeployerMojo extends weblogic.tools.maven.plugins.BaseMojo{
java.util.List flags;
  protected boolean failonerror;
  protected java.lang.String adminurl;
  protected java.lang.String user;
  protected java.lang.String password;
  protected java.lang.String userConfigFile;
  protected java.lang.String userKeyFile;
  protected boolean advanced;
  protected boolean debug;
  protected boolean examples;
  protected boolean help;
  protected boolean noversion;
  protected boolean nowait;
  protected boolean purgetasks;
  protected boolean remote;
  protected java.lang.Integer timeout;
  protected boolean verbose;
  protected boolean version;
  protected boolean external_stage;
  protected boolean stage;
  protected java.lang.String id;
  protected java.lang.String name;
  protected boolean nostage;
  protected java.lang.String source;
  protected java.lang.String targets;
  protected java.lang.Integer retiretimeout;
  protected java.lang.Integer rmiGracePeriod;
  protected java.lang.String action;
  protected boolean upload;
  protected java.lang.String plan;
  protected java.lang.String planversion;
  protected boolean adminmode;
  protected java.lang.String appversion;
  protected boolean graceful;
  protected boolean ignoresessions;
  protected java.lang.String securityModel;
  protected boolean isLibrary;
  protected java.lang.String libSpecVer;
  protected java.lang.String libImplVer;
  protected java.lang.String submoduletargets;
  protected boolean usenonexclusivelock;
  protected boolean allversions;
  protected boolean enableSecurityValidation;
  protected java.lang.String deleteFiles;
  public weblogic.tools.maven.plugins.DeployerMojo();
  public void execute() throws org.apache.maven.plugin.MojoExecutionException;
  protected java.lang.String[] getArgsRedeployer(java.util.List);
}

Therefore to use this more secure connection approach, it should be a simple case of creating and storing the relevant userconfig and userkey files using WLST, and referencing them in the Maven pom.xml file, right?

The answer to this is, yes, but …

It turns out we have a very minor bug that prevents this from working in WLS 10.3.4.  The bug number is 10382796 for reference. It has already been fixed for the next release of WLS.  Should you wish to use this secure connection mechanism, I’d suggest opening a support TAR, referencing the bug number and asking for a backport of the bug fix.

Having access to the bug fix, I can walk through the steps required to configure and use this connection mechanism and show it in operation.

1. Create the userConfigFile and userKeyFile from the weblogic.WLST utility

This is a straight forward step and is well documented in the links shown above.

Connect to the running WebLogic Server domain using WLST and issue the storeUserConfig command, specifying the locations of the userConfig and userKey files that will be generated:

>storeUserConfig(‘/tmp/wls.config’,’/tmp/wls.key’)
Screen shot 2011-02-21 at 10.19.28 AMIn this case, we have created the files as ‘/tmp/wls.config’ and ‘/tmp/wls.key’.

We can validate these files work correctly using the weblogic.Deployer utility to connect to the WebLogic Server domain, using the userconfigfile and –userkeyfile parameters:

$ java weblogic.Deployer -adminurl t3://localhost:7001 -userconfigfile /tmp/wls.config -userkeyfile /tmp/wls.key –listapps
Screen shot 2011-02-21 at 10.59.28 AM

2. Install WebLogic Maven Plugin and Crypto Library into Maven Repository

Summary of steps in this section: in order to use the WebLogic Maven Plugin from Maven, it needs to generated from a WebLogic Server installation, then installed into the local repository.  Furthermore, to use the secure config file connection mechanism, an additional library must also be installed into the repository to support the encryption operations.  This must be manually installed first, then added as dependency of the weblogic-maven-plugin via its pom.xml.  Finally, the weblogic-maven-plugin.jar file is installed.

Install Dependency crytpo.jar into Maven Repository

The <MW_HOME>/modules/crypto.jar is required to support the use of the secure config file connection mechanism by the weblogic-maven-plugin.  It must be installed into the Maven repository first.

$ cd <MW_HOME>
$ cd modules
$ mvn install:install-file -Dfile=cryptoj.jar -DgroupId=com.oracle.cryptoj -DartifactId=cryptoj -Dversion=1.0 -Dpackaging=jar

Generate weblogic-maven-plugin.jar and extract pom.xml

To generate the weblogic-maven-plugin and its pom.xml file, follow steps 1, 2 from the documentation:

http://download.oracle.com/docs/cd/E17904_01/web.1111/e13702/maven_deployer.htm#DEPGD379

$ java -jar wljarbuilder.jar -profile weblogic-maven-plugin
$ jar xvf weblogic-maven-plugin.jar META-INF/maven/com.oracle.weblogic/weblogic-maven-plugin/pom.xml
$ mv META-INF/maven/com.oracle.weblogic/weblogic-maven-plugin/pom.xml .

** It is important that the pom.xml file be available in the directory in which wewill invoke the first “mvn install” command shown below.  The easiest way to do this is as shown above, copy/move it into the same directory as the weblogic-maven-plugin.jar file so all the files we will work with are located together.

Edit pom.xml to specify cryptoj dependency and goalPrefix

There are two changes that need to be made to the pom.xml file.  The first change is to add the cryptoj library as a dependency to the weblogic-maven-plugin.  The second is to add a configuration section to allow the use of the shortname weblogic to invoke the Maven goals.

Here is the final pom.xml with changes at lines [16-22] and [24-35]:

   1:  <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   2:    <modelVersion>4.0.0</modelVersion>
   3:    <groupId>com.oracle.weblogic</groupId>
   4:    <artifactId>weblogic-maven-plugin</artifactId>
   5:    <packaging>maven-plugin</packaging>
   6:    <version>10.3.4</version>
   7:    <name>Maven Mojo Archetype</name>
   8:    <url>http://maven.apache.org</url>
   9:    <dependencies>
  10:      <dependency>
  11:        <groupId>org.apache.maven</groupId>
  12:        <artifactId>maven-plugin-api</artifactId>
  13:        <version>2.0</version>
  14:      </dependency>
  15:   
  16:      <!-- Dependency on cryptoj library -->
  17:      <dependency>
  18:        <groupId>com.oracle.cryptoj</groupId>
  19:        <artifactId>cryptoj</artifactId>
  20:        <version>1.0</version>
  21:      </dependency>
  22:    </dependencies>
  23:   
  24:    <!-- Use weblogic goalPrefix -->
  25:    <build>
  26:      <plugins>
  27:        <plugin>
  28:          <artifactId>maven-plugin-plugin</artifactId>
  29:          <version>2.3</version>
  30:          <configuration>
  31:             <goalPrefix>weblogic</goalPrefix>
  32:          </configuration>
  33:        </plugin>
  34:      </plugins>
  35:    </build>
  36:  </project>

Install weblogic-maven-plugin

Now we want to actually install the weblogic-maven-plugin into the Maven repository.  There are two install commands that are issued here, which both need to be followed.  The first command implictly uses the edited pom.xml file and configures the weblogic-maven-plugin inside the Maven repository.  The second command performs the actual installation of the weblogic-maven-plugin library into the Maven repository.

** Ensure the pom.xml file we have edited is in the directory in which you will execute the commands.

$ mvn install
$ mvn install:install-file -Dfile=weblogic-maven-plugin.jar -DpomFile=pom.xml 

We should see output from these commands as shown in the screencaps below:

Screen shot 2011-02-21 at 11.59.42 AMScreen shot 2011-02-21 at 12.03.47 PM

3. Configure pom.xml to use secure config file for authentication

Now that the secure configuration files have been generated, the cryptoj dependency and the oracle-maven-plugin  installed into the Maven repository, we can configure your Maven pom.xml file to use them to connect to the WebLogic Server domain.

Instead of using the <username> and <password> elements as part of the weblogic-maven-plugin <configuration> stanza to specify the connection credentials, we use the <userConfigFile> and <userKeyFile> elements and point to the location of the files we generated from WLST earlier.

A fully configured Maven pom.xml for a Java EE 5 Web application is shown below. 

Lines [13-18] shows the creation of properties that identify the location of the relevant external files we generated from WLST.

Lines [67-69] shows the use of the <userConfigFile> and <userKeyfile> elements to specify the use of the secure config file authentication model.

Example pom.xml:

   1:  <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   2:    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   3:    <modelVersion>4.0.0</modelVersion>
   4:   
   5:    <groupId>sab.demo.maven</groupId>
   6:    <artifactId>webapp</artifactId>
   7:    <packaging>war</packaging>
   8:    <version>1.0-SNAPSHOT</version>
   9:   
  10:    <name>webapp JEE5 Webapp</name>
  11:    <url>http://maven.apache.org</url>
  12:   
  13:    <!-- weblogic-maven-plugin properties -->
  14:    <properties>        
  15:      <weblogic.adminurl>t3://localhost:7001</weblogic.adminurl>    
  16:      <weblogic.configfile>/tmp/wls.config</weblogic.configfile>
  17:      <weblogic.keyfile>/tmp/wls.key</weblogic.keyfile>
  18:    </properties>  
  19:   
  20:    <dependencies>
  21:   
  22:      <dependency>
  23:        <groupId>javax.servlet</groupId>
  24:        <artifactId>servlet-api</artifactId>
  25:        <version>2.5</version>
  26:        <scope>provided</scope>
  27:      </dependency>
  28:   
  29:      <dependency>
  30:        <groupId>javax.servlet.jsp</groupId>
  31:        <artifactId>jsp-api</artifactId>
  32:        <version>2.1</version>
  33:        <scope>provided</scope>
  34:      </dependency>
  35:   
  36:      <dependency>
  37:        <groupId>junit</groupId>
  38:        <artifactId>junit</artifactId>
  39:        <version>3.8.1</version>
  40:        <scope>test</scope>
  41:      </dependency>
  42:   
  43:    </dependencies>
  44:   
  45:    <build>
  46:      <plugins>
  47:        <plugin>
  48:          <groupId>org.apache.maven.plugins</groupId>
  49:          <artifactId>maven-compiler-plugin</artifactId>
  50:          <version>2.0.2</version>
  51:          <configuration>
  52:            <source>1.5</source>
  53:            <target>1.5</target>
  54:          </configuration>
  55:        </plugin>
  56:        
  57:      <plugin>
  58:          <groupId>com.oracle.weblogic</groupId>         
  59:          <artifactId>weblogic-maven-plugin</artifactId>
  60:          <version>10.3.4</version>
  61:          <configuration>
  62:              <adminurl>${weblogic.adminurl}</adminurl>
  63:              <!--
  64:              <user>${weblogic.user}</user>             
  65:              <password>${weblogic.password}</password>                                
  66:              -->
  67:              <!-- Use external connection files --> 
  68:              <userConfigFile>${weblogic.configfile}</userConfigFile>
  69:              <userKeyFile>${weblogic.keyfile}</userKeyFile>            
  70:              <source>
  71:                  ${project.build.directory}/${project.build.finalName}.${project.packaging}
  72:              </source>
  73:              <name>${project.build.finalName}</name>
  74:          </configuration>
  75:       </plugin>    
  76:              
  77:      </plugins>    
  78:      
  79:      <finalName>webapp</finalName>
  80:    </build>
  81:  </project>

Verify it Works

With all configuration and installation tasks performed, we can now verify that the weblogic-maven-plugin can successfully connect to the WebLogic Server domain.

To do this, I typically use the weblogic:list-apps goal – this doesn’t perform any deployment operation, but does connect to the target server, authenticates, and returns a list of the currently deployed applications.

The output from executing weblogic:list-apps is shown below.  Note the [INFO] output which shows the underlying weblogic.Deployer command that is issued, in which the –userconfigfile and –userkeyfile parameters are used:

$ mvn weblogic:list-apps
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building webapp JEE5 Webapp 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- weblogic-maven-plugin:10.3.4:list-apps (default-cli) @ webapp ---
weblogic.Deployer invoked with options:  -noexit -adminurl t3://localhost:7001 -userconfigfile /tmp/wls.config -userkeyfile /tmp/wls.key -listapps
wls-rest
jersey-bundle [LibSpecVersion=1.1.1,LibImplVersion=1.1.5.1] <ACTIVE VERSION>
jsr311-api [LibSpecVersion=1.1.1,LibImplVersion=1.1.1] <ACTIVE VERSION>
ops-ear
webapp
jackson-jaxrs [LibSpecVersion=1.0,LibImplVersion=1.1.1] <ACTIVE VERSION>
jettison [LibSpecVersion=1.1,LibImplVersion=1.1] <ACTIVE VERSION>
jackson-core-asl [LibSpecVersion=1.0,LibImplVersion=1.1.1] <ACTIVE VERSION>
jackson-mapper-asl [LibSpecVersion=1.0,LibImplVersion=1.1.1] <ACTIVE VERSION>
Number of Applications Found : 9
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 6.150s
[INFO] Finished at: Mon Feb 21 12:31:22 CST 2011
[INFO] Final Memory: 12M/81M
[INFO] ------------------------------------------------------------------------

Summary

In this post, I’ve shown how the the WebLogic Maven Plugin can support the use of secure config files to prevent the need to specify administrator passwords in clear text in the Maven pom.xml. 

I would like to again note that there is a very minor known bug that prevents this being used with the WLS 10.3.4 release, which has already been fixed  in the next release code line. 

If you are wanting to use this feature and need to get a patch, the bug to refer to is #10382796.

5 comments:

Triss said...

I'm very much looking forward to not using the hand-hacked maven deployer goal I hadda write, and your post gives me hope I'll be able to connect it up to the rest of my release tooling, stored credentials and all.

Oracle, on the other hand, is denying they ever wrote a patch for this little miswiring.

Don't suppose they gave you an internal patch number to go with that internal bug number?

Buttso said...

Hey Triss --

The dev team implemented the fix directly on the next release codeline. So there never was an official/unofficial "patch" for this. I was able to pull it directly from the nightly build trees for 10.3.6 and show it working.

If you need this prior to WLS 10.3.6 where the fix is in, you'll need to open a tar, state the problem you are seeing with it not working, note that this is a known bug #10382796 and ask for a patch to be created for it. The bug was marked as feasible to backport so it should be possible to do (the fix was simple) based on the normal support policies.

-steve-

Jay said...

This is a great article and is exactly what I need to do.

A question about the patch...is the patch required for WLST, the weblogic.Deployer, or for the WLS instance to accept deployments via this security config file?...Just want to assess the impact of patching our current instances to use this feature.

Also, does the plugin have to be rebuilt if we supply the crypto via the plugin configuration and don't really mind not using the weblogic prefix?

Thanks again for the article.

Buttso said...

Hi Jay, thanks for the comment.

A specific patch doesn't currently exist. We've fixed the bug in our codeline for the next release. But you should be able to request a fix from support for it.

Since we generate the plugin from a WLS install, the fix would (I assume) be to provide you with a new modules/com.oracle.weblogic.maven.plugin_1.0.0.0.jar jar file, which is what the "wljarbuilder -profile weblogic-maven-plugin" uses as its source to produce the actual maven plugin that is provisioned into the repo.

Since the fix is to the module that contains the plugin classes, and is essentially a client side piece of code, all you'd need to do is apply it to one server, generate the plugin, and store that in your maven plugin repo for all your maven users to declare and use. The fix does nothing to the weblogic server itself, just the client plugin code.

Hope that is clear enough -- please let me know if you have more questions.

-steve-

Jay said...

Hi Buttso

Brilliant article.
I tried the maven weblogic plugin with secured user/password using . But it works fine only on my local windows machine. And it fails on the Linux server when I build using Hudson.
Any idea ?


Error log is here.....
INFO] ++====================================================================++
[INFO] ++ wls-maven-plugin: undeploy ++
[INFO] ++====================================================================++
weblogic.Deployer invoked with options: -noexit -adminurl t3://host:7001 -userconfigfile wls_dev.config -userkeyfile wls_dev.key -undeploy -name abc-1.0.8-SNAPSHOT -targets AdminServer
Please enter username:Please enter a password for the user "installadministrator":Please enter a password for the user "installadministrator":Please enter a password for the user "installadministrator":Please enter a password for the user "installadministrator":Please enter a password for the user "installadministrator":[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 11.292s
[INFO] Finished at: Wed Nov 06 14:46:35 GMT 2013
[INFO] Final Memory: 21M/58M
[INFO] ------------------------------------------------------------------------
[INFO] o.h.m.e.h.MavenExecutionResultHandler - Build failed with exception(s)
[INFO] o.h.m.e.h.MavenExecutionResultHandler - [1] org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal com.oracle.weblogic:wls-maven-plugin:12.1.1.0:undeploy (default-cli) on project abc_presentation: weblogic.deploy.api.tools.deployer.DeployerException: weblogic.deploy.utils.MBeanHomeToolException: Unable to obtain a password for the specified user.
[DEBUG] Closing connection to remote
[ERROR] Failed to execute goal com.oracle.weblogic:wls-maven-plugin:12.1.1.0:undeploy (default-cli) on project abc_presentation: weblogic.deploy.api.tools.deployer.DeployerException: weblogic.deploy.utils.MBeanHomeToolException: Unable to obtain a password for the specified user. InvocationTargetException -> [Help 1]

Thanks
Jay