summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Tantsur <dtantsur@protonmail.com>2021-10-15 18:57:46 +0200
committerDmitry Tantsur <dtantsur@protonmail.com>2021-10-18 10:58:17 +0200
commit2e9d2b5ec45b3b7ef0213ee437aef8092d29aebb (patch)
tree30498087fb875bd4fb2cc6e4c3774f4b369669c3
parenteeb0a6d76b7c66801e68c8f3a47a951a811f052f (diff)
downloadironic-2e9d2b5ec45b3b7ef0213ee437aef8092d29aebb.tar.gz
Do not use any parts of image URL in temporary file names
We currently use the last component, which is: a) a potential information exposure, b) can hit file name length limits [1] Use the master path file name instead, which is always a UUID. [1] https://bugzilla.redhat.com/show_bug.cgi?id=2014630 Change-Id: I2aa1230468132c2b7a8585d691ec180947f89c1e (cherry picked from commit 7d85694fdf85a269cb3023083bf567a0e7e4ec13)
-rw-r--r--ironic/drivers/modules/image_cache.py2
-rw-r--r--ironic/tests/unit/drivers/modules/test_image_cache.py22
-rw-r--r--releasenotes/notes/image-cache-size-28a9072901b98edf.yaml5
3 files changed, 28 insertions, 1 deletions
diff --git a/ironic/drivers/modules/image_cache.py b/ironic/drivers/modules/image_cache.py
index 41ab836fe..7ca96d046 100644
--- a/ironic/drivers/modules/image_cache.py
+++ b/ironic/drivers/modules/image_cache.py
@@ -161,7 +161,7 @@ class ImageCache(object):
# TODO(ghe): timeout and retry for downloads
# TODO(ghe): logging when image cannot be created
tmp_dir = tempfile.mkdtemp(dir=self.master_dir)
- tmp_path = os.path.join(tmp_dir, href.split('/')[-1])
+ tmp_path = os.path.join(tmp_dir, os.path.basename(master_path))
try:
with _concurrency_semaphore:
diff --git a/ironic/tests/unit/drivers/modules/test_image_cache.py b/ironic/tests/unit/drivers/modules/test_image_cache.py
index 51e36cd19..2e077997b 100644
--- a/ironic/tests/unit/drivers/modules/test_image_cache.py
+++ b/ironic/tests/unit/drivers/modules/test_image_cache.py
@@ -227,6 +227,28 @@ class TestImageCacheFetch(base.TestCase):
self.assertEqual("TEST", fp.read())
@mock.patch.object(image_cache, '_fetch', autospec=True)
+ def test__download_image_large_url(self, mock_fetch):
+ # A long enough URL may exceed the file name limits of the file system.
+ # Make sure we don't use any parts of the URL anywhere.
+ url = "http://example.com/image.iso?secret=%s" % ("x" * 1000)
+
+ def _fake_fetch(ctx, href, tmp_path, *args):
+ self.assertEqual(url, href)
+ self.assertNotEqual(self.dest_path, tmp_path)
+ self.assertNotEqual(os.path.dirname(tmp_path), self.master_dir)
+ with open(tmp_path, 'w') as fp:
+ fp.write("TEST")
+
+ mock_fetch.side_effect = _fake_fetch
+ self.cache._download_image(url, self.master_path, self.dest_path)
+ self.assertTrue(os.path.isfile(self.dest_path))
+ self.assertTrue(os.path.isfile(self.master_path))
+ self.assertEqual(os.stat(self.dest_path).st_ino,
+ os.stat(self.master_path).st_ino)
+ with open(self.dest_path) as fp:
+ self.assertEqual("TEST", fp.read())
+
+ @mock.patch.object(image_cache, '_fetch', autospec=True)
@mock.patch.object(image_cache, 'LOG', autospec=True)
@mock.patch.object(os, 'link', autospec=True)
def test__download_image_linkfail(self, mock_link, mock_log, mock_fetch):
diff --git a/releasenotes/notes/image-cache-size-28a9072901b98edf.yaml b/releasenotes/notes/image-cache-size-28a9072901b98edf.yaml
new file mode 100644
index 000000000..e201fe7f6
--- /dev/null
+++ b/releasenotes/notes/image-cache-size-28a9072901b98edf.yaml
@@ -0,0 +1,5 @@
+---
+fixes:
+ - |
+ Fixes ``File name too long`` in the image caching code when a URL contains
+ a long query string.