summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClint Byrum <clint@fewbar.com>2013-04-08 17:55:15 -0700
committerClint Byrum <clint@fewbar.com>2013-04-10 15:13:48 -0700
commit97f016304e397dee7fa2ca10c5b37f72d799f078 (patch)
treee4da82f59d6fbd2278e1b23b4027c23586100e09
parente0f26667c4383392be367a73fa91c095daa14269 (diff)
downloadheat-cfntools-97f016304e397dee7fa2ca10c5b37f72d799f078.tar.gz
Cache metadata in /var/cache instead of /tmp1.2.2
/tmp is unsafe if a user were to somehow be able to create the file before it was cached there they can issue commands to cfn-init that would likely elevate their permissions. Fixes bug #1164756 Change-Id: I54e1e1be178274cb0a2b50f54e859e004e1f1c78
-rw-r--r--heat_cfntools/cfntools/cfn_helper.py18
-rw-r--r--heat_cfntools/tests/test_cfn_helper.py26
2 files changed, 40 insertions, 4 deletions
diff --git a/heat_cfntools/cfntools/cfn_helper.py b/heat_cfntools/cfntools/cfn_helper.py
index 27f883b..7bb8cc0 100644
--- a/heat_cfntools/cfntools/cfn_helper.py
+++ b/heat_cfntools/cfntools/cfn_helper.py
@@ -1077,7 +1077,7 @@ class Metadata(object):
self,
meta_str=None,
default_path='/var/lib/heat-cfntools/cfn-init-data',
- last_path='/tmp/last_metadata'):
+ last_path='/var/cache/heat-cfntools/last_metadata'):
"""
Read the metadata from the given filename
"""
@@ -1091,13 +1091,14 @@ class Metadata(object):
# If reading remote metadata fails, we fall-back on local files
# in order to get the most up-to-date version, we try:
- # /tmp/last_metadata, followed by
+ # /var/cache/heat-cfntools/last_metadata, followed by
# /var/lib/heat-cfntools/cfn-init-data
# This should allow us to do the right thing both during the
# first cfn-init run (when we only have cfn-init-data), and
# in the event of a temporary interruption to connectivity
- # affecting cfn-hup, in which case we want to use last_metadata
- # or the logic below could re-run a stale cfn-init-data
+ # affecting cfn-hup, in which case we want to use the locally
+ # cached metadata or the logic below could re-run a stale
+ # cfn-init-data
fd = None
for filepath in [last_path, default_path]:
try:
@@ -1136,6 +1137,15 @@ class Metadata(object):
if old_md5 != current_md5:
self._has_changed = True
+ # if cache dir does not exist try to create it
+ cache_dir = os.path.dirname(last_path)
+ if not os.path.isdir(cache_dir):
+ try:
+ os.makedirs(cache_dir, mode=0700)
+ except IOError as e:
+ LOG.warn('could not create metadata cache dir %s [%s]' %
+ (cache_dir, e))
+ return
# save current metadata to file
tmp_mdpath = last_path
with open(tmp_mdpath, 'w+') as cf:
diff --git a/heat_cfntools/tests/test_cfn_helper.py b/heat_cfntools/tests/test_cfn_helper.py
index 5f27e90..aad782b 100644
--- a/heat_cfntools/tests/test_cfn_helper.py
+++ b/heat_cfntools/tests/test_cfn_helper.py
@@ -570,6 +570,32 @@ class TestMetadataRetrieve(testtools.TestCase):
self.assertDictEqual(md_data, md._metadata)
self.assertEqual(md_str, str(md))
+ def test_metadata_creates_cache(self):
+ temp_home = tempfile.mkdtemp()
+
+ def cleanup_temp_home(thome):
+ os.unlink(os.path.join(thome, 'cache', 'last_metadata'))
+ os.rmdir(os.path.join(thome, 'cache'))
+ os.rmdir(os.path.join(thome))
+
+ self.addCleanup(cleanup_temp_home, temp_home)
+
+ last_path = os.path.join(temp_home, 'cache', 'last_metadata')
+ md_data = {"AWS::CloudFormation::Init": {"config": {"files": {
+ "/tmp/foo": {"content": "bar"}}}}}
+ md_str = json.dumps(md_data)
+ md = cfn_helper.Metadata('teststack', None)
+
+ self.assertFalse(os.path.exists(last_path),
+ "last_metadata file already exists")
+ md.retrieve(meta_str=md_str, last_path=last_path)
+ self.assertTrue(os.path.exists(last_path),
+ "last_metadata file should exist")
+ # Ensure created dirs and file have right perms
+ self.assertTrue(os.stat(last_path).st_mode & 0600 == 0600)
+ self.assertTrue(
+ os.stat(os.path.dirname(last_path)).st_mode & 0700 == 0700)
+
def test_is_valid_metadata(self):
md_data = {"AWS::CloudFormation::Init": {"config": {"files": {
"/tmp/foo": {"content": "bar"}}}}}