Bug 917085 - Relative paths to rhq:file element fail if parent deploy destination has not yet been created
Summary: Relative paths to rhq:file element fail if parent deploy destination has not ...
Keywords:
Status: CLOSED CURRENTRELEASE
Alias: None
Product: JBoss Operations Network
Classification: JBoss
Component: Provisioning
Version: JON 3.1.2
Hardware: All
OS: All
unspecified
medium
Target Milestone: ER01
: JON 3.2.0
Assignee: John Mazzitelli
QA Contact: Mike Foley
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2013-03-01 16:24 UTC by bkramer
Modified: 2018-11-30 19:29 UTC (History)
2 users (show)

Fixed In Version:
Clone Of: 917088
: 917088 (view as bug list)
Environment:
Last Closed: 2014-01-02 20:43:00 UTC
Type: Bug
Embargoed:


Attachments (Terms of Use)
Contains agent.log and test bundle (5.65 KB, application/zip)
2013-03-01 16:24 UTC, bkramer
no flags Details
patch for fix (6.28 KB, patch)
2013-04-26 05:24 UTC, John Mazzitelli
no flags Details | Diff


Links
System ID Private Priority Status Summary Last Updated
Red Hat Bugzilla 917765 0 medium CLOSED If bundle destination path contains a symbolic link, relative paths specified in bundle recipe may resolve to incorrect ... 2021-02-22 00:41:40 UTC
Red Hat Bugzilla 957174 1 None None None 2021-01-20 06:05:38 UTC
Red Hat Knowledge Base (Solution) 318143 0 None None None Never

Internal Links: 917765 957174

Description bkramer 2013-03-01 16:24:19 UTC
Created attachment 704238 [details]
Contains agent.log and test bundle

Description of problem:
If deploy.xml is using relative links for destinationFile for instance:


<project name="my-test-deployment" default="main" xmlns:rhq="antlib:org.rhq.bundle">
    <rhq:bundle name="myTest" version="1.1.1" description="first my-test deployment">
        <rhq:deployment-unit name="Datasource">
            <rhq:file name="app.properties" destinationFile="../../conf/app.properties" replace="false"/>
        </rhq:deployment-unit>
    </rhq:bundle>
    <target name="main"/>
</project>

bundle deployment will fail with the following exception:

2013-03-01 14:40:03,411 ERROR [ResourceContainer.invoker.nonDaemon-1] (org.rhq.plugins.ant.AntBundlePluginComponent)- Failed to deploy bundle [class org.rhq.core.pluginapi.bundle.BundleDeployRequest: deployment=[BundleResourceDeployment: bdd=[BundleDeployment[id=10291, name=Deployment [1] of Version [1.1.1] to [myDest]]], resource=[Resource[id=13802, uuid=ecb58f7d-a967-45f2-ac72-f39695efe600, type={JBossAS5}JBossAS Server, key=/home/biljana/JBoss/jboss-eap-5.1.2/jboss-eap-5.1/jboss-as/server/default, name=EAP bkramer.redhat.com:1099 default, version=EAP 5.1.2]]], full-deploy-directory=[/home/biljana/JBoss/jboss-eap-5.1.2/jboss-eap-5.1/jboss-as/server/default/deploy/myTest], clean=[false], revert=[false]]
java.lang.Exception: Failed to execute the bundle Ant script
	at org.rhq.plugins.ant.AntBundlePluginComponent.deployBundle(AntBundlePluginComponent.java:159)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.rhq.core.pc.inventory.ResourceContainer$ComponentInvocationThread.call(ResourceContainer.java:634)
	at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
	at java.util.concurrent.FutureTask.run(FutureTask.java:138)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
	at java.lang.Thread.run(Thread.java:619)
Caused by: java.lang.RuntimeException: Failed to execute bundle deploy file [/home/biljana/JON_312/rhq-agent/data/tmp/bundle-versions/10211/ant-bundle-recipe106831198048929530.xml]. Cause: /home/biljana/JON_312/rhq-agent/data/tmp/bundle-versions/10211/ant-bundle-recipe106831198048929530.xml:2: Failed to deploy bundle [fxmpDatasource] version [1.1.1]: java.lang.Exception: Failed to create new parent directory for raw file [/home/biljana/JBoss/jboss-eap-5.1.2/jboss-eap-5.1/jboss-as/server/default/deploy/myTest/../../conf/app.properties]

Attached agent.log excerpt that covers this and test bundle (info.zip).


Version-Release number of selected component (if applicable):
JON 3.1.2

How reproducible:
Always

Steps to Reproduce:
1. Attempt to deploy attached bundle 

  
Actual results:
The bundle is not deployed and java.lang.Exception: Failed to create new parent directory for raw file [...] is thrown.

Expected results:
The bundle should be properly deployed without any exception.


Additional info:

** If I add a new <rhq:file> element into deploy.xml that does not use destinationFile nor destinationDir, the deployment is properly done.

** Also, I tried to use the following as a workaround:

<project name="my-test-deployment" default="main" xmlns:rhq="antlib:org.rhq.bundle">
    <rhq:bundle name="myTest" version="1.1.1" description="first my-test deployment">
        <rhq:deployment-unit name="Datasource">
            <rhq:file name="app.properties" destinationFile="${rhq.deploy.dir}/../../conf/app.properties" replace="false"/>
        </rhq:deployment-unit>
    </rhq:bundle>
    <target name="main"/>
</project>

but this throws the same exception.

Comment 1 Larry O'Leary 2013-03-04 16:53:54 UTC
The failure is due to the parent directory not existing. In this case, the parent is /home/biljana/JBoss/jboss-eap-5.1.2/jboss-eap-5.1/jboss-as/server/default/deploy/myTest. Because nothing is actually being created directly in the parent, the parent does not get created and therefore, the result is that when you attempt to use the parent directory in a relative path reference, it will fail because it doesn't exist. This same error occurs if you attempt to execute the same command from a command-line. For example:

    touch /opt/jboss/jboss-eap-5.2.0/jboss-as/server/all/deploy/myTest/../../conf/app.properties
    touch: cannot touch `/opt/jboss/jboss-eap-5.2.0/jboss-as/server/all/deploy/myTest/../../conf/app.properties': No such file or directory


One way to resolve this would be to make rhq:file create the destination path.

Comment 2 Larry O'Leary 2013-03-04 17:39:21 UTC
Changing the title of this bug to be more accurate to the issue identified. 

Relative links when defining destinationFile in the deploy.xml are broken >>> Relative paths to rhq:file element fail if parent deploy destination has not yet been created

This is because the issue only relates to relative paths that name a parent directory that does not exist. When rhq:file processes the destinationFile or destinationDir attribute it checks to see if the directory exists. However, this fails if the destination directory has not been created by extracting a file to the destination.

Comment 3 John Mazzitelli 2013-04-24 16:22:55 UTC
for the record, the code is this:

  File newLocationParentDir = newLocationFile.getParentFile();
  newLocationParentDir.mkdirs();
  if (!newLocationParentDir.isDirectory()) {
      throw new Exception("Failed to create new parent directory for raw file [" + newLocationFile + "]");
  }

in org.rhq.core.util.updater.Deployer.extractZipAndRawFiles

Comment 4 John Mazzitelli 2013-04-24 16:38:19 UTC
This problem can be averted by getting the canonical path from the location:

   newLocationParentDir.getCanonicalFile().mkdirs();

There are several calls to mkdirs() in this class - will have to examine all of them to see where this problem also occurs.

Comment 5 John Mazzitelli 2013-04-25 18:55:52 UTC
it turns out this has opened a pandora's box.

I should have written the bundle stuff to disallow using ".." in the rhq:file destination attributes.

For one, this is allowing you to deploy/overwrite files outside of the bundle destination directory. This technically isn't a major problem because we allow you to do this anyway if your destination attribute uses absolute paths (and thus you can write files anywhere the agent has file permissions).

But the real problem I am hitting is that if you use ".." in RELATIVE paths, you are moving outside of the destination directory. The major problem I see is that if we need to BACKUP these files, we can't put them under .rhqdeployments/backup directory. This is where we backup files found in the dest dir, but if you use ".." in the relative paths, this potentially takes you out of the backup directory.

For example:

The normal, common use case for rhq:file is this:

<rhq:file name="app.properties" destinationFile="app.properties" />

where the relative path is "app.properties". If, during a bundle upgrade, that file needed to be backed up when deploying bundle deployment #1, we'd put the backup copy in:

<bundle-dest-dir>/.rhqdeployments/1/backup/app.properties

Now, using the example found in this BZ description:

<rhq:file name="app.properties" destinationFile="../../conf/app.properties" />

That is a relative path, too. If, during a bundle upgrade, that file needs to be backed up, notice how this is a problem - where do we put the backup file?

<bundle-dest-dir>/.rhqdeployments/1/backup/../../app.properties

whose canonical path is:

<bundle-dest-dir>/.rhqdeployments/app.properties

THAT isn't what we want. Take it to the extreme:

<rhq:file name="app.properties" destinationFile="../../../../..conf/app.properties" />

would have a canonical path of of the parent of the bundle-dest-dir itself!

So clearly, this isn't going to work. We can't backup files with relative paths that have ".." in them.

I may need to alter this such that if a relative path has ".." in it, we store it in the ext-backup location (which is used for destination file paths that were absolute in the recipe, like:

<rhq:file name="app.properties" destinationFile="/opt/app.properties" />

we'd store this in:

<bundle-dest-dir>/.rhqdeployments/1/ext-backup/opt/app.properties

I'm not sure what would happen if I back up files specified with relative paths in the ext-backup location, but if that doesn't work, the only other option is to just not backup the files, and warn the user that if they want to rollback the bundle to the previous version, they will lose some data because we can't backup files with "..".

Well, I lied - there is another alternative. You could write your bundle recipe with the dest dir as the top most directory that you plan on storing relative paths. So, if your file path in a recipe is "../app.properties", your destination directory should be the parent directory of what you specified, and your recipe could then include "app.properties".

Comment 6 John Mazzitelli 2013-04-26 04:02:16 UTC
Two problems to overcome if the file has ".." in its path:

1) if the file is actually above the destination directory, it isn't really considered a "relative" file or one that is under destination directory. We MUST treat it as if it was specified via an absolute path (which means we treat it like an external raw file, not one that belongs under dest dir).

e.g. this happens if destination dir == "/opt/jbossas/server/default/deploy" and rhq:file destinationFile == "../../conf/app.properties"

2) if the file still remains under the dest dir, we still must extract out the ".." but if we do, the Deployer class breaks (the backup stuff doesn't work and it gets confused and thinks it needs to delete the file). We need to enhance Deployer so it normalizes the path so ".." are removed, but yet remains a relative path so we can treat it as any relative path

e.g. this happens if destination dir == "/opt/something" and rhq:file destinationFile == "subdir/../conf/app.properties"

[note: why someone would do this, I don't know. but because I'm paranoid, I'll assume someone out there will find a need to specify the file path like that, so I will attempt to support this]

Comment 7 John Mazzitelli 2013-04-26 05:24:36 UTC
Created attachment 740225 [details]
patch for fix

attached a patch that should fix this. I have a new unit test class (not in the  patch) that shows this working. Once I verify this more with additional testing, I'll commit this patch along with tests.

Comment 8 John Mazzitelli 2013-04-26 18:41:53 UTC
git commit to master: 8ae20bd510aa660e94f70cad95fc680fd0dedd47

Comment 9 Larry O'Leary 2013-09-06 14:31:04 UTC
As this is MODIFIED or ON_QA, setting milestone to ER1.


Note You need to log in before you can comment on or make changes to this bug.